[CM] cm cvs, portmidi + supercollider?

Rick Taube taube@uiuc.edu
Fri, 16 Dec 2005 21:22:33 -0600

> Which begets the question: while using rts I'm binding the scheduler to
> a given stream, for example, one for supercollider output. Is it
> possible to, for example, trigger something in supercollider with
> messages coming in from portmidi? How would one do that?

yes, sure. The easiest way is to set a portmidi receiver hook that 
sc processes:

1. Open both streams to variables:

(use-system :portmidi)
(define *sc* (sc-open))
(define *pm* (portmidi-open :latency 0 :input 1 ))

2. define a process that outputs sc notes:

(defobject simple (scsynth)
   ((freq :initform 440)
    (dur :initform 1)
    (amp :initform .2)
    (pan :initform 0))
   (:parameters freq dur amp pan time))

(define (test-simple reps key amp)
    (process for i below reps
             for k = (between key (+ key 12))
             output (new simple :time (now) :dur .2
                         :freq (hertz k)
                         :amp (interp i 0 amp reps (/ amp 3)))
             wait .25))

3. Start rts and give it the *sc* stream as output:

(rts nil *sc*)

4. Define and set a hook function that sprouts a sc process:

(define (myhook mm ms)
   ;;(midi-print-message mm ms)
   (sprout (test-simple (pick 4 8 12)
                        (note-on-key mm)
                       (/ (note-on-velocity mm) 127.0))))

(set-receiver! #'myhook *pm*)

;; clear hook and stop rts when done
(remove-receiver! *pm*)


One other thing, the 'output' clause in a process actually takes an 
optional 'to' arg:

output (new ..) TO *pm*
output (new ..) TO *foo*

so a process does not have to output to the stream you pass to rts. in 
fact you dont really have to pass a stream to rts at all, in which case 
your process would handle all the routing explicitly.