Package to play sound files from Tcl, using a simple API common to all architectures. It is part of the
eTcl distributions, and available on all platforms supported by
eTcl (Win32, Windows Mobile/WinCE, Linux, MacOSX).
Only a very simple API is provided, with no support for asynchronous I/O. However, since all
eTcl builds are thread-enabled, one can emulate a non-blocking API using threads.
package require evodio
# Procedure to play wave (RIFF) in background
namespace eval ::evodio {}
proc ::evodio::playwav {f {usercb ""}} {
set ns [namespace current]
package require Thread
set slaveid [::thread::create]
thread::send $slaveid {
namespace eval ::evodio {}
proc ::evodio::playsub {f {callback ""}} {
package require evodio
package require Thread
evodio play -file $f
if {[string compare "" $callback]} {
set rc [catch {uplevel \#0 $callback} res]
}
::thread::unwind
return
}
}
set cb [list ::thread::send -async [::thread::id] [list ${ns}::playdone $slaveid $usercb]]
thread::send -async $slaveid [list ${ns}::playsub $f $cb]
return
}
proc ::evodio::playdone {slaveid cb} {
set rc [catch {uplevel \#0 $cb} res]
return
}
Several audio files can then be played simultaneously:
set thisdir [file dirname [file normalize [info script]]]
set w1 [file join $thisdir sample1.wav]
set w2 [file join $thisdir sample2.wav]
set ::wcount 0
set ::nwait 0
puts "+++ BEGIN"
::evodio::playwav $sample1 [list incr ::wcount]
incr nwait
if {[string compare "" $sample2]} {
# Play two sounds concurrently
::evodio::playwav $sample2 [list incr ::wcount]
incr nwait
}
# Wait
while {$wcount<$nwait} {
puts "+++ WAITING $wcount/$nwait"
vwait ::wcount
puts "+++ DONE $wcount/$nwait"
}
puts "+++ DONE"