The Snack Sound Toolkit , by Kåre Sjölander, provides for the creation of multi-platform audio applications with just a few lines of code.

See Also

Reanimation of Snack
a musicbox
A Radio Recorder
A toy piano
A simple Snack demo
Basic Snack stream player
Ff snack is present then tkchat has a streaming audio plugin
Using Tcl/Tk in Multimedia Applications


latest release
{2 2 10}
release time
{2004 12 01}
development repository


Only the 32-bit version provides Snack.
A set of binaries by PYK includes Snack.
In-Hak Min: Win32 binary snack 2.2.10.


The Snack sound extension adds commands to play and record audio. Snack supports in-memory sound objects, file based audio, and streaming audio, with background audio processing. It handles file formats such as AIFF, AU, MP3, NIST/Sphere, and WAV. Snack is extensible; new commands and sound file formats can be added using the Snack C-library. Snack also does sound visualization, e.g. waveforms and spectrograms. The visualization canvas item types update in real time and can output postscript. Works with Tcl 8.0.3 and later, as well as is stubs enabled. Works with the Tcl plug-in. Platforms: HP-UX, Irix, Linux, Solaris, Windows 95/98/NT/2000/XP. Latest version is 2.2.10.

To load Snack without loading Tk:

package require sound
proc playwav myWavFile { 
    snack::sound s -file $myWavFile
    s play -block 1
playwav c:/path/to/wavfile.wav


NJG 2006-06-28: But if you want to enjoy what you hear you should drop the "-block 1" (whatever it means).


PYK 2015-10-01: Created a Fossil repository and populated it with available releases of Snack. Was not able to locate a previous repository.

To sort

  What: WaveSurfer
  Description: A tool for recording, playing, editing, viewing, printing,
          and labelling audio data.  Runs on Macintosh, Unix, Windows, Solaris
          and Linux.  Has its own sound visualization megawidget.
          Reads and writes CLS, WAVE, AU, AIFF, and other file formats.
          Requires Tcl/Tk 8.x and Snack 1.7.0 or newer.
          Latest version is 1.8.5.
  Updated: 11/2005
  Contact: mailto:[email protected] (Kare Sjolander)

  What: Netscape client Tcl Tclet (joakim_g)

  Description: Set of exercises on speech technology.  Requires Snack.
          The html page is a paper describing the setup.
  Updated: 05/1999
  Contact: mailto:[email protected]

  What: transcriber
  Description: Tool for assisting the creation of speech corpora.
          Allows one to manually segment, label and transcribe
          speech signals for laster use in auto speech processing.
          Developed in Tcl/Tk, and C, and requires Snack and tcLex.
          Tested on Linux, Solaris, SGI, and Windows NT.
          Latest version is 1.4.6.
  Updated: 10/2003
  Contact: mailto:[email protected] ("subscribe transcriber-announce")

Beware Why does the following script cause Wish to crash on windows XP?

package require sound

snack::sound s1
snack::sound s2

s1 configure -file ex1.wav
s2 configure -file ex2.wav
set t 0
set t2 0
pack [button .b1 -command "s1 play" -text Play1]
pack [button .b2 -command "s2 play" -text Play2]
pack [entry .e1 -textvariable t]
pack [entry .e2 -textvariable t2]

proc w {} {
        global t t2
        set t [s1 current_position]
        set t2 [s2 current_position]
        after 200 w


ex1 and ex2 are the sound files included with the snack download...

FrBa (20151005) tested the script on WinXP with tcl 8.6.4 32bit and snack 2.2.10 and confirmed wish does crash. It appears the query of current_position of the non-playing sound causes the error. Playing s1 and checking current_position of s1 succeeds, but checking position of s2 crashes the script. The script does not crash if the button command is "s1 play -blocking 1"

Additional commands not in the official manual (why?)

PS 2004-03-30: I've found these because I wondered how the 'tomAmp.tcl' showed the current position in a file. The current_position is probably the most important omission.

  • soundName current_position ?-type samples|seconds?: returns the current playing/paused position, defaults to sample number.
*Note*: In my version of snack (2.2.9) the flag is -units, ie current_position ?-units samples|seconds?
  • soundName datasamples ?-begin sample? ?-end sample? ?-byteorder littleEndian|bigEndian?: returns the sample data from the sound as (tcl string?)
  • soundName1 swap soundName2: swaps the audio buffers of the two named sounds. On completion, soundName1 contains the audio data previously associated with soundName2 and conversely. Works only on in-memory sounds. Additional arguments such as -begin and -end are accepted but ignored.
  • soundName an: Declared, but does nothing.
  • soundName stretch ?-pitch x? ?-pitchlist x? ?-rate x? ?-ratelist x? ?-tract x? ?-segments x?: stretches the sound by a factor x without changing the pitch.
  • soundName op: Declared, but does nothing.

Notes: although the options to the stretch subcommand were all available in version 2.2.6, the current version 2.2.9 only has the option '-segments'.

I did some experiments with the swap subcommand and read the source, on the basis of which I have corrected the description of this command above. WJP 2008-01-18

How does Snack compare to Audacity [L1 ]?

Well, for one thing, Audacity is a C/C++ application, which Snack is a C Tcl extension. This makes Snack capable of being used within other Tcl applications relatively easily, while one would have to work harder at using Audacity...

TV: I just tried a little addition to the Colliding Balls where I loaded a drum sample and play it at every bounce:

package require snack
snack::sound -load soundfilename.wav

Is needed at init somewhere, and then:

# collide a given coin with all other coins that overlap with it
proc collide {coin radius} {
    # find coin's center
    foreach {x1 y1 x2 y2} [$::canvas coords $coin] break
    set x [expr {($x1+$x2)/2.0}]
    set y [expr {($y1+$y2)/2.0}]
    # find other coins that overlap with the given coin
    set overlap [list]
    $::canvas raise $coin ;# not sure if really needed
    set next $coin
    while {[set next [$::canvas find closest $x $y $radius $next]] != $coin} {
        lappend overlap $next
    # when there is a collision play the sound
    if {[llength $overlap] >0} {sound1 play}
    # collide the given coin with other coins
    foreach other $overlap { collideCoins $coin $other }

The soundfile, a kick drum, I used you could get from here [L2 ].

I was running quite some things and didn't pay much attention to simultaneously sounding sounds, and even loaded tcltalk simultaneously to feel right at homein computer game lab and let the thing speak to me where a certain ball is, and it crashed after maybe 15 minutes...

Have a ball.

Jason Tang: You may have noticed that snack doesn't play well when some other application has control of the sound card. On Windows based systems, the package require snack will immediately return with an error if something is using the sound card. In Linux (and I presume other Unix based systems) package require snack blocks untils the other process relinquishes control. Here's a little hack to prevent this blocking:

proc soundInit {} {
    set soundAvail 1
    global tcl_platform
    if {$tcl_platform(platform) == "unix"} {
        # on unix, libsnack blocks if sound device is in use; so
        # detect by trying to open /dev/dsp
        if {[catch {open /dev/dsp "WRONLY NONBLOCK"} f]} {
            set soundAvail 0
        } else {
            close $f
    if {[catch {package require sound}]} {
        set soundAvail 0
    if {[catch {package require snackogg}]} {
        set soundAvail 0

Note that this detection works under x86, kernel 2.4.18, Tcl/Tk 8.4.2, OSS drivers. I do not know the behavior when run under ALSA, esd, and/or non x86 systems.

DKF: The problem is that Linux, like many other UNIX systems, only allows exclusive opens on the sound device. If you're going to support multiple channels assigned to different apps, you need to put a mixer on the front end. That's what the likes of esd etc. do. (I've no idea how to configure Snack to make use of these sorts of resources though.)

LV: On solaris, at least, you need to make certain that when you build this extension, you use the -R link flag or the LD_LIBRARY_PATH environment variable, so that tcl, upon loading Solaris, finds the various dynamic libraries used. In particular, the Solaris ActiveTcl distribution's snack extension has a dependency on libsnackogg, so applications have to make certain they have things set to find that library before the package require for snack occurs.

Zarutian 2005-07-22: How does one mix two or more audio streams together using snack?

AMG 2005-07-25: I don't think it can be done. :^( I am working on a project that needs Tcl-based audio recording, playback, loading, and saving plus filtering and combination of said audio, all in real time. Snack doesn't seem to support all this, but at least it has decent code for reading and writing audio.

Beware 2005-07-28: I've done this in windows - just have two players and alter the volumes accordingly. I'm working on a DJ MP3 mixer (using Snack, it might be possible to get auto beat matching)

AMG 2005-11-02: Ah, I got it working the same way (should have posted sooner), but still the result isn't what I want. I would like to be able to capture the mixed result in software and write it back to disk, rather than merely have it go out the speakers and into my fleshy brain.

SRIV 2005-11-02: Check out mp3mixer which is a very simple c app to mix 2 raw audio streams. I'm sure someone could use critcl to turn this into a tcl extension.

AMG 2005-11-03: mp3mixer requires that both input streams have the same sampling rate, channel count, and resolution (44.1KHz/stereo/16 bit), and that's a major weakness.

Also, in December 2005, Aric Bills writes, "Snack can produce a WAV file via a sound object's write subcommand:

$sound write C:/my/sound/file.wav -fileformat WAV

The -fileformat part is optional if you include the .wav extension.

Snack can also do AU, SND, AIFF, SMP, CSL, and RAW (RAW is just a bunch of samples with no header).

If you use the snackogg or snacksphere package, you can also do Ogg/Vorbis and NIST/Sphere formats.

As always, more details on the man pages:


[To mix two sounds:]

1. create three sound objects. Use whatever options are appropriate.

set one [snack::sound -load $file1]
set two [snack::sound -load $file2]
set three [snack::sound]

1a. (If your sound data is coming from some other source than a file--if you're recording or generating it in snack--take care of that here).

2. copy the relevant data from object 1 into object 3:

$three copy $one -start $startsample1 -end $endsample1

3. mix the relevant data from object 2 into object 3:

$three mix $two -start $startsample2 -end $endsample2"

To play a .wav or .mp3 file:

package require snack
snack::sound snd 
snd read $filename 
snd play

LV: Eric Taylor and Jeff Hobbs mention on clt that within the snack distribution is the script "demos/snack/cool.tcl" which is a "decent features mp3 (and other audio formats) player".

NJG 2006-07-05: The original link on Transcriber is dead, use instead

UKo 2007-01-25: The original authors of snack and wavesurfer aren't reachable at this time. Does anyone know what's happening? The snack waveform and spectrogram doesn't work with 8.5a4 on win, osx and linux and I have no clue, where to start searching ...

I don't know what the reason was, but a simple recompilation of the extension from the original sources was enough to let it work with 8.5 at least on linux and osx.

dzach: I have some applications with snack that fail with tclkit-8.5a6 on WinXP, although they work for me on Linux.

WJP 2008-05-23: Snack graphics work for me on Linux with 8.5.1.

WJP 2008-03-01: Snack implements only a simplified form of the .wav specification. It is unable to handle .wav files containing "chunks" other than the audio data chunk, such as playlists and cuelists. In theory files with such extra chunks should only arise in applications in the music industry, but some digital recorders, such as the Sonifex Courier, produce files that Snack cannot read. If you encounter files that Snack cannot read and the extra chunks are empty, you can work around the problem by reading them into an editor that understands complex .wav files (e.g. Audacity) and then writing them out again. Another approach is to strip the extra chunks. My program SimplifyWave will strip the extra chunks whether or not they are empty. ( )

dzach 2008-3-3: How about a Tcl version of it?

Example sound generator for Snack: Soundgenerator

dzach 2010-7-25: I love Snack but I had problems using it in Linux. Here are some instructions on how to make it work in Kubuntu 10.04:

Trying to use the package I had from previous installations gave me the error Could not gain access to /dev/sound/dsp for writing. Some searches later I found out that Snack was using OSS for the sound system, while (K)ubuntu 10.04 uses Alsa. So I had to download Snack2.2.10 from its home page (file ), recompile it using:

tar -xf snack2.2.10.tar.gz
./configure --enable-alsa
sudo make install

which gave another error:

error: expected declaration specifiers or ‘...’ before ‘(’ token

To correct that (after more searching) I had to include the following line in the source code of file jkFormatMP3.c in the snack2.2.10/generic directory :

#include <math.h>

right after the #include <string.h> line. Now Snack compiled and linked ok but when using it from tcl, it gave yet another error:

couldn't load file "/lib/snack2.2/": /lib/snack2.2/ undefined symbol: _snd_pcm_mmap_hw_ptr

Google pointed to a patch for the file jkAudIO_alsa.c (for Gentoo, but nonetheless it worked for Kubuntu too) , in a file alsa.asc. I applied the patch with:

patch jkAudIO_alsa.c alsa.asc

recompiled Snack as above and finally I now have Snack2.2.10 working again. I republish the patch here in case the link above dies in the future:

--- unix/jkAudIO_alsa.c   2005-12-14 12:29:38.000000000 +0100
+++ unix/jkAudIO_alsa.c   2008-09-01 22:51:20.000000000 +0200
@@ -49,6 +49,8 @@
 static int minNumChan = 1;
+static snd_pcm_uframes_t hw_bufsize = 0;
 SnackAudioOpen(ADesc *A, Tcl_Interp *interp, char *device, int mode, int freq,
           int nchannels, int encoding)
@@ -135,6 +137,9 @@
     Tcl_AppendResult(interp, "Failed setting HW params.", NULL);
     return TCL_ERROR;
+  snd_pcm_hw_params_get_buffer_size (hw_params, &hw_bufsize);
   if (A->mode == RECORD) {
@@ -202,6 +207,8 @@
   int i;
   static char buf[64];
+  return;
   if (A->debug > 1) Snack_WriteLog("  Enter SnackAudioPost\n");
   for (i = 0; i < 1000; i++) {
@@ -267,12 +274,14 @@
 SnackAudioPlayed(ADesc *A)
-  long avail = _snd_pcm_mmap_hw_ptr(A->handle);
+  // FIX Here, _snd_pcm_mmap_hw_ptr is deprecated in new alsalib
+  long played = A->nWritten - (hw_bufsize - SnackAudioWriteable(A));
+  // long avail = _snd_pcm_mmap_hw_ptr(A->handle);
-  if (avail < 0)
-    avail = 0;
+  if (played < 0)
+   return 0;
-  return (avail+A->nPlayed);
+  return (played);

ZB 2010-07-26: does the "non-blocking" (asynchronous) playing mode work well in your installation? I've got a problem, that after an asynchronous playback, I'm unable to repeat playback of the same sound data (with just "s play", for instance) without reloading a sound file - it won't then play anything even in synchronous mode without reloading that formerly played file (seems to be blocking playing device? Not sure). Synchronous mode - from the other side - is taking entire CPU for playback... Update: when I used the sound package from Activestate's Teapot library, the above described problem with asynchronous playback doesn't occur. But since it has been compiled AFAIK against TCL 8.4, the problem must be caused by some changes introduced in 8.6b1, when compiling from sources? dzach Asynchronous mode doesn't seem to have a problem in my setup, running tcl8.6b1.2 from the HEAD. ZB 20110107 I tried today two more times to compile Snack according to the instructions from this page - using the patches above - this time on my Slackware64 installation. I made compilation against TCL8.5.9 and then 8.6b1, and the mentioned problem still's here. Perhaps someone from Activestate could be kind enough to explain, how Snack should be compiled from the sources, to fix the problem? Maybe there are(?) some fixes in tcl8.6b1.2 - but there are no such sources to download like 8.6b1.2, but only the 2-years old 8.6.b1.

LWS 2011-01-04 - Has anyone had any luck getting snack to *simultaneously* play a sound (or even two different ones) at the same time on two different devices (sound cards)? From what I can tell so far, if a sound is playing, the device it is playing on seems to trump the specification of a new device on a subsequent call. For instance,

set s1 [snack::sound -load "somesample.wav"]
set s2 [snack::sound -load "anotherone.wav"]
$s1 play -device "Output Device 1" -blocking 0
$s2 play -device "Output Device 2" -blocking 0

will play both sounds on Output Device 1. Allowing both calls to play to block does play on two different devices, but sequential playing is not what I am after! I tried doing this in two interpreters, too, but to the same end. Thoughts?

WJP 2011-02-18: On current Ubuntu Linux systems (10.10 Maverick Meerkat), there is no /dev/dsp as a result of which snack fails. The solution is to use the OSS emulation, which you can do by setting the environment variable LD_PRELOAD to before running a program that uses snack, e.g.,in csh:

   setenv LD_PRELOAD

or in sh:; export LD_PRELOAD

EF 2014-08-29: On more modern Ubuntu systems, I've discovered that padsp is a better answer to provide OSS emulation on top of PulseAudio. Just run padsp tclsh8.6 script.tcl <args> and Snack will be able to access /dev/dsp.

tarzan - 2017-05-22 10:45:12

Force Build Under MSYS Console


force CYGPATH to use "cygpath -u"

cd to snack/win
do autoconf

undefined `WAVE_FORMAT_IEEE_FLOAT` and friends ?
@file generic/jkSoundFile.c
/* #ifndef WIN */
#  define WAVE_FORMAT_ALAW  6
/* #endif */`
to test demo
exec tclsh8.7 "$0" "$@"
package require Tk

@some demo files i got segmentation fault occurs ;(

ralfixx - 2021-09-23 10:25:51

In addition to the above patch for unix/jkAudIO_alsa.c, we also needed the following patch to protect from closing the same device twice:

--- snack2.2.10/unix/jkAudIO_alsa.c.orig        2005-12-14 12:29:38.000000000 +0100
+++ snack2.2.10/unix/jkAudIO_alsa.c        2021-09-23 12:22:53.523858925 +0200
@@ -155,9 +160,11 @@
   if (A->debug > 1) Snack_WriteLog("  Enter SnackAudioClose\n");
-  snd_pcm_drop(A->handle);
-  snd_pcm_close(A->handle);
+  if (A->handle) {
+    snd_pcm_drop(A->handle);
+    snd_pcm_close(A->handle);
+    A->handle = NULL;
+  }
   if (A->debug > 1) Snack_WriteLog("  Exit SnackAudioClose\n");