Experimenting with scripted Linux Jack / Midi

TV Nov 18 '017

For the sake of measurments with Linux Jack based audio I made some basic facilities for writing a Jack based midi message with a Tcl script, and read from Jakc audio paths and get results from that measurment back into the tcl script using external processes communicating via stdio.

Here's a a signal graph of the first successful test setup:

tclsjackmidi1.png

This is the little script "test.tcl":

#
#
#   testing jack/alsa midi sending
#

proc slsend a {
   puts "177 1 $a"
}

scale .sl
.sl conf -from 0 -to 127 -tickinterval 16 -command {slsend }
pack .sl -expand y -fill y
button .bnote
.bnote conf -text play -command {
     after 100 {puts "144 69 64" ; flush stdout }
     after 3000 "puts \"128 69 0\"" 
     set c [open "|./jack_max jm default 3 jack_rack_filt:out_ 2>/dev/null" ]
     fileevent $c read {set ret [gets $c] ; close $c}
}
pack .bnote
entry .emax
.emax conf -textvar ret -width 12
pack .emax

These are the C source files for theo Midi Out command line process and the Jack based audio measurement tool: http://www.theover.org/Wiki/jack_max.c , http://www.theover.org/Wiki/midimes.c .

The experiment that requires scripting in this case is an audio filter (the jack-rack in the picture) running over a sample (the "qsynth" sampler application in the graph, connected with Midi (red) and audio out (green) to the filter ), of which the maximum output amplitude is measured after the filter with the "jm" code from above. Changing the filter will find different overall spectral maxima that can be searched and intelligently (also automated and unsupervised) used for gathering audio processing data. This simple test lets you adjust the frequency of the filter, and press "play" to play the sample (the decimal codes are MIDI codes to start a note and change the Modulation wheel setting) and search for the maximum filter output amplitude, which is put in the bottom entry automatically after the measurement time is over (in this case 3 seconds with a piano "A" tone).

TV Nov 22 '017 I used the same principles, but a few changes to the C programs (the ones above are updated), with connected Midi equipment over USB and traditional Midi, in a similar fashion to the above. In this case, I programmed a string of a hundred measurements to compare the maximum output of a single piano note being played on a Kurzweil PC3 synthesizer (with internal effects off) digitally connected to a Lexicon MX400 digital reverberation unit, when changing the Lexicon room ambience effect's "diffusion" parameter from 0 to 99. The script I used:

#
#
#   testing jack/alsa midi sending
#

proc waitfor {s} {
 for {set i 0} {$i < [expr 10.0*$s]}  {incr i} {
   update
   after 100;
 }
   update
}

 source ~theo/Tcl/unixconsole.tcl
waitfor .1

set a 64
set ret -1

# our midi output interface program (creates "jm1" out port) reads decimal from stdin
set m [open "|./jack_mess 2>/dev/null" a+]
waitfor .5 
# (on Linux) connect with jack-midi to alsa-midi bridge
exec jack_connect jm1:out j2a_bridge:playback

#send a Midi CC message
proc mcc {c v} {
  global m
  puts $m "180 $c $v" ; flush $m
}

# take a CC valur of "diffusion" in this case, start a note, and measure
proc measure { di } {
  global ret m
  waitfor .1 
  puts $m "180 43 $di" ; flush $m

     # Note on (Middle C, average strength)
     after 100 {puts $m "144 60 64" ; flush $m }
     # start Jack audio measurement node
     set c [open "|./jack_max jm default 1.5 system:capture_ 2>/dev/null" a+ ]
     fileevent $c read " if {\[eof $c\] != 0} {close $c} {
        if {\[ gets $c rett \] > 0} { set ret \$rett }} "
     waitfor 1.8
     #send "Note off"
     puts $m "128 60 0"  ; flush $m
     waitfor .1A
   # return maximum amplitude of all samples measured
   return $ret
}


#MX400 global Bypass on
mcc 120 127
measure 0
     puts $ret
waitfor 0.1
#MX400 global Bypass off
mcc 120 0

# Go over all values from 0 .. 99
# translate to proper CC value
# collect measurements
for {set j 0} {$j < 100} {set j [expr $j+1]} { 
   set di [expr int((128.0*($j+0.5))/100.0)] 
   puts -nonewline " $j"
   puts " [measure $di]"
   waitfor 0.1 
}

The result in a graph:

roomdiffusion.png Horizontal: diffusion, Vertical max amplitude of response, output with room effect was 263