[Stk] Processing messages consideration

Carlos Pita carlosjosepita@yahoo.com.ar
Tue, 10 May 2005 05:21:01 -0300


Hi!

I've been using stk intensively for the last month or so,
I have "rewriten" some pd patches of mine into stk/c++ and
having had considerable (often bad) experience with csound
and pd I really feel at home with stk. IMHO
non trivial control tasks are much harder to express
via graphical languages and at the other hand csound
ibm 360 assembler-like language is too rough
for these times. Perhaps a thin scripting layer on top
of stk (basically a binding) would be convenient to code
instruments, schedule and process messages, control
performance from UI, etc. Of course the binding should
exclusively call the c++ tick(vector) like methods as
computing one simple sample during each scripting-side
iteration would kill performance. As my experience with
stk becomes a little more established and I've some free
time, I will work in a (probably python) binding (cause
I love Numeric/scipy packages, which could nicely
complement stk).

At the risk of being impertinent I will suggest a
modest design change that won't break current
code. Currently the Instrmnt class can deal 
with NoteOn/Off and ControlChange messages. Of
course you can subclass it to cope with different
ones but the common Instrmnt interface only allows
these. Also ControlChange "multiplexes"
control but you are forced to put it into
ControlChange messages instead of arbitrary
SKINI messages. This is not important when you use
Instrmnts subclasses directly but when you do
it through the Voicer or another layer on top of
Instrmnt you get no way to send arbitrary messages
to the controlled Instrmnts (cause Voicer is
aware of the polymorphic Instrmnt interface
but not of its specific subinterfaces). For
example, from the Voicer you can't send
AfterTouch or another custom message, so you
end up wrapping them into ControlChanges
messages. Also the Voicer implements PitchBend
which IMHO is more an Instrmnt responsability
(how to deal with an specific message in a
common -although overridable- way). I think
a good alternative would be having a processMessage()
method in both the Voicer and Instrmnt classes.
The default implementation of Instrmnt::processMessage()
would delegate to Instrmnt::controlChange() when
it receives a ControlChange message or directly
process some common messages as PitchBend -instead
of doing it at the Voicer layer-. This way you can
override processMessage() to deal with specific
messages or simply override controlChange() if
you only need to cope with ControlChange ones.
>From the Voicer user perspective you would
replace the ubiquos delegation

  case __SK_NoteOn_:
      data->voicer.noteOn( value1, value2 );
  case __SK_NoteOff_:
    data->voicer.noteOff( value1, value2 );
  case __SK_ControlChange_:
    data->voicer.controlChange( (int) value1, value2 );
  case __SK_AfterTouch_:
    data->voicer.controlChange( 128, value1 );
  case __SK_PitchChange_:
    data->voicer.setFrequency( value1 );
  case __SK_PitchBend_:
    data->voicer.pitchBend( value1 );

by a concise data->voicer.processMessage(message).

Well, that's all. Hope it could be useful.
Regards,
Carlos.