Version 88 of Snack

Updated 2011-01-05 06:50:05 by LWS

Purpose: to describe the Snack sound extension and provide examples, tips, etc.

This package is part of the ActiveTcl Batteries Included distribution.

Since the official package has seen no progress since some years now, we try to start a process of Reanimation of Snack


  What: Snack
  Where: http://www.speech.kth.se/snack/
  Description: 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
          fileformats 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.
  Updated: 12/2005
  Contact: mailto:[email protected] (Kare Sjolander)


  What: WaveSurfer
  Where: http://www.speech.kth.se/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)
  Where: http://www.speech.kth.se/labs/analysis/
          http://www.speech.kth.se/%7Ejoakim_g/plan/icslp98_web.html
          http://www.speech.kth.se/snack/
  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
  Where: http://www.etca.fr/CTA/gip/Projets/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
}

w

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


Additional commands not in the official manual (why?)

PS 30Mar2004: 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 verion 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


Applications based on Snack, or in related areas

See also Using Tcl/Tk in Multimedia Applications ,


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
                return
            } else {
                close $f
            }
        }
        if {[catch {package require sound}]} {
            set soundAvail 0
            return
        }
        if {[catch {package require snackogg}]} {
            set soundAvail 0
            return
        }
    }

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 22. july 2005: How does one mix two or more audio streams together using snack?

AMG 25 Jul 2005: 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 28 July 2005: 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 02 Nov 2005: 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 02 Nov 2005: Check out mp3mixer http://szyzyg.arm.ac.uk/~spm/mp3mixer.html 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 03 Nov 2005: 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:

http://www.speech.kth.se/snack/man/snack2.2/tcl-man.html#swrite http://www.speech.kth.se/snack/man/snack2.2/tcl-man.html#defpack

...

[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 http://trans.sourceforge.net/en/install.php 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. (http://billposer.org/Software/waveutils.html )

dzach 2008-3-3 How about a tcl version of it?



In-Hak Min Win32 binary snack 2.2.10 : http://tcltk.co.kr/?q=node/1319


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 http://www.speech.kth.se/snack/ (file http://www.speech.kth.se/snack/dist/snack2.2.10.tar.gz ), recompile it using:

tar -xf snack2.2.10.tar.gz
./configure --enable-alsa
make
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/libsnack.so": /lib/snack2.2/libsnack.so: 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) http://bugs.gentoo.org/attachment.cgi?id=166378 , 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;
+
 int
 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);
+
   snd_pcm_hw_params_free(hw_params);
   snd_pcm_prepare(A->handle);
   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 @@
 long
 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 20100726 - 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.


LWS 20110104 - 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?