Fox Board Tcl: a audio mixer application

by Theo Verelst

This page is about two essential tcl scripts for a big project of mine, which is a computer and otherwise controlled audio mixer.

Image TV Wiki dsc00194b.jpg The prototype hardware in buildup

Both the control side in the mixer machine and the control program on a PC are pure Tcl, which is fun and well maintainable.

The prototype with its tcl-scripts currently controls (in very high quality) one stereo volume via a slider on the screen of a Linux (I used Fedora Core 6/64) or Windows XP (professional):

Image TV Wiki scrvol1.jpg

The first tryout script is this one:

 proc slidsend { {n} {v} } {
  set w [format "%.2x" [expr $v+191]]
  send "00$w$w$w"

 }

 proc slidsendupdate { } {

 #   send update

 } 



 set sock {}
 proc send { {line {\n}} } {
   global sock
   if {$sock == -1} {
     # log "(failed attempt to send:\n$line)\n"
      return
   }
   puts $sock $line
   flush $sock
   # log $line\n
 } 

 proc log a {puts -nonewline $a}



 set sock [socket 192.168.1.38 4448]

 #sliders {{vol 255}}



 wm geometry . 88x478
 scale .sl
 .sl conf -from 64 -to -191 -tickinterval 32 -command {slidsend 0 }
 pack .sl -expand y -fill y

The slider above is shown on the screen, moving it immedeately changes the volume of the single text channel of the mixer.

The ticks are in 0.5 dB steps ( a small volume change), which is not to lose resolution, when the slider values would be in Decibels, (-96 .. 31.5) the accuracy would become a decibel per slider step.

The send command computes the hardware setting and assumes exactly 4 bytes must be send over the socket per volume change. The local IP address is of the mixer machine.

The following picture shows the machinery setup:

Image TV Wiki volume1.jpg

The computer runs a script which on the screen shows sliders, controls etc, which is currently only one long Tk slider. It connects over ethernet to a Fox board (see [L1 ] and Fox Board Tcl), which runs another Tcl (not Tk) script which can access storage and has a direct serial connection (115kbps) with a FPGA (programmable logic) where messages can be put into serial driver commands for the high grade volume control chip(s).

Using Tcl in the fox board makes it possible to store and save configurations easily, do computations which can be changed on the fly, have web page access to the mixer where a tcl cgi can directly access the mixer and display (in buildup) settings, and with the front pannel controls the machine can be used stand-alone, and is then extremely easy to customize and to build almost any user interface in which could be required.

On a PC (or several PCs in a network) the whole mixer, which will have dozens of sliders) can be shown on a large screen, all under Tcl control, and all freely programmable, also by users.

For the current prototype, this is the script in the machine's Fox Board, which is automatically started at boot time

 set sock [socket -server connect 4448]
 set s1 {}

 proc connect {s host port} {
    global s1
    set s1 $s
    fconfigure $s1 -blocking 0 -buffering line
    fileevent $s1 readable [list handleSocket $s1]
 }

 proc handleSocket {s} {
    gets $s line
    if {[eof $s]} {
        close $s
        set s -1
        return
    }
    if {$line eq ""} return
    w $line
 }


 set fh [open /dev/ttyS2 RDWR]

 fconfigure $fh -blocking 0 -mode 115200,n,8,1 -translation binary \
    -buffering  full

 fileevent $fh readable {
    set w [read $fh] ;
    foreach c [split $w {}] {
       binary scan $c H* a; set v $a
       if {$s1 != {}} {puts $s1 "$v"}
       # flush stdout
    }
 }
 proc w h {
    global fh
    puts -nonewline $fh [binary format H* "$h"] ; flush $fh
 }
 w 00 ; w C0 ; w C0 ; w C0
 # after 500 exit
 vwait forever

I'm not sure this machine will be all open source, thus far they're simple but very well working (and fast) programs and free to use.

May 8 '07 TV I've added a 'auto-slider' facility, see this picture:

Image TV Wiki mixer2.jpg

The left slider is linked directly with the mixer, whenever it is changed, every change immedeately is sent to the hardware mixer, which then quickly repsonds by setting the (in this case one) volume control to the latest setting, this is done in less then a few milliseconds, having measured the whole chain, including the receiving fox board tcl script, taking out the 'after' can make this quite under a mS. Like above that is.

The second slider from the left is a slow response one, once it is released at a new volume setting, the left slider will slowly move to match it's setting, at a rate determined by the right slider. You can play with this script by taking the socket command out, and see how this works. Zero setting of the right slider makes the left slider respond very fast to the middle one, maximimum slowness on the right slider is 100, which lets the left slider search for the middle sliders' setting very slowly.

While the sliders are moving the middle and right slider can be dynamically changed. As things are programmed now, the mixer will never make a jump when the middle slider is used, all 255 possible intermedeate value setting are always passed.

This is the script:

 proc slidsend { {n} {v} } {
  set w [format "%.2x" [expr $v+191]]
  send "00$w$w$w"
 }

 proc slidsendupdate { } {
 #   send update
 } 

 proc send { {line {

}} } {

   global sock
   if {$sock == -1} {
     # log "(failed attempt to send:\n$line)\n"
      return
   }
   puts $sock $line
   flush $sock
   # log $line\n
 } 

 proc log a {puts -nonewline $a}

 proc volset { {v 1} } {
  set w [format "%.2x" [expr $v+191]]
  send "00$w$w$w"
 }
 proc e {a} {}

 proc updatevol {v w} {
   set d [expr $v-$w] ; 
   if {$d < 0} {set d -1} {
      if {$d == 0} {return done} {set d 1}
   } ;
   return $d
 }

 proc doupdatevol {} {
   set w [.s.sl get] ;
   set v [.s.sl1 get] ;
   set u [updatevol $v $w] ;
   if {"done" == "$u"} {return} ;
   set w [expr $w + $u] ;
   volset $w ; .s.sl set $w ;
   after [.s.sl2 get] {doupdatevol} 
 }

 set sock {}
 set sock [socket 192.168.1.38 4448]

 toplevel .s
 scale .s.sl -from 64 -to -191 -tickinterval 32 -command {slidsend 0 }
 pack .s.sl -expand y -fill y -side left
 wm geometry .s 253x478
 scale .s.sl1 -from 64 -to -191 -tickinterval 32 -command { e }
 pack .s.sl1 -expand y -fill y -side left
 scale .s.sl2 -from 100 -to 0 -tickinterval 20 -command { e }
 pack .s.sl2 -expand y -fill y -side left
 bind .s.sl1 <ButtonRelease-1> {doupdatevol}

TV (29-5-08) I changed the fax board processor such that it better startup on a random network with dhcp and also that it easily can run wget to browse the internet when connected to it, but now it is sometimes a bit slow with the tcl script to pass data from a PC over the intranet to the board. I'll have to find out how to fix this, the mixer is already limited by the 10kilobyte/sec link with the (extremely fast so probably for future use as interpolator) FPGA, but is normally totally apt responsive and with one slider completely immideate, and this is how it should be of course.

The change has made it possible to connect up the board with web server and a working tcl-cgi script to a router/modem connected to the internet and to use a mobile phone with internet browser to directly change the volume on the machine without using a PC, and using the simple tcl-cgi directly, so I could walk outside, click the phone and change the volume directly, which is cool.