'''[http://www.speech.kth.se/snack/%|%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]: [SnackAmp]: [a musicbox]: [A Radio Recorder]: [A toy piano]: A simple Snack demo [TclMusic]: [Basic Snack stream player]: [SndBite]: [tkchat]: Ff snack is present then tkchat has a streaming audio plugin [Using Tcl/Tk in Multimedia Applications]: ** Attributes ** name: Snack website: http://www.speech.kth.se/snack/ latest release: {2 2 10} release time: {2004 12 01} development repository: https://chiselapp.com/user/pooryorick/repository/snack ** distributions ** [ActiveTcl]: Only the 32-bit version provides Snack. [Cygwin]: A set of binaries by [PYK] includes Snack. tcltk.co.kr: [In-Hak Min]: [http://tcltk.co.kr/?q=node/1319%|%Win32] binary snack 2.2.10. ** 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 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. ** News ** [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 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:kare@speech.kth.se (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:joakim_g@speech.kth.se 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:majordomo@etca.fr ("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... [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 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 ---- ---- How does Snack compare to Audacity [http://audacity.sourceforge.net]? 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 [http://82.168.209.239/Tripod/Diary/Samples/kick.wav]. 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] 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 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] 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: 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? ---- ---- 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: ======none tar -xf snack2.2.10.tar.gz ./configure --enable-alsa make sudo make install ====== which gave another error: ======none 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 : ======c #include ====== right after the #include line. Now Snack compiled and linked ok but when using it from tcl, it gave yet another error: ======none 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: ======none 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: ======c --- 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. [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 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, ======c 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 libpulsedsp.so before running a program that uses snack, e.g.,in csh: setenv LD_PRELOAD libpulsedsp.so or in sh: LD_PRELOAD=libpulsedsp.so; 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 ` and Snack will be able to access `/dev/dsp`. <> Package | Music | Sound | Visualization