[CM] yuk yuk yuk

Rick Taube taube@uiuc.edu
Wed, 24 Mar 2004 12:55:45 -0600

well its spring break. here is an implementation of "max" (three 
functions) so you can pretend you're composing too.  the first patch 
works anywhere the second example is an interactive composition (etude 
for openmcl/midishare)

;; "max" patching

(defun box (fn &rest args)
   (vector fn args '()))

(defun box-> (box &rest boxes)
   (setf (elt box 2) boxes) ; make boxes the "outlets" of box

(defun bang! (box &rest args)
   ;; allow override of box's current args
   (when args (setf (elt box 1) args))
   ;; call fn on args and collect results
   (let ((res (multiple-value-list
               (apply (elt box 0)
                      (elt box 1)))))
     ;; "send" args to any forward boxes and
     ;; bang! them in left-to-right order
     (dolist (o (elt box 2))
       (setf (elt o 1) res)
       (bang! o))

;; example patch that prints random message

(defparameter box1 (box #'(lambda () (random 100))))
(defparameter box2 (box #'(lambda (x) (list :hiho! :interaction x))))
(defparameter box3 (box #'print))
(box-> box1 box2)
(box-> box2 box3)
(bang! box1)

;; look Ma, im an interactive composer!

(defparameter midiin
   ;; "send" along the received event.
   (box (lambda (e) e)))

(defparameter midiout
   ;; "send" out to midishare
   (box (lambda (e) (output e))))

(defparameter midiran
   ;; random note with same dynamic
   (box (lambda (e)
          (ms:new typeNote
             :duration (between 100 1000)
             :keynum (between 20 100)
             :velocity (ms:vel e)))))

(defparameter miditrans
   ;; transpose event on octave
   (box (lambda (e)
          (let ((n (ms:MidiCopyEv e)))
            (ms:pitch n (+ 12 (ms:pitch e)))

(box-> midiin midiout miditrans midiran)
(box-> miditrans midiout)
(box-> midiran midiout)

(receive #'(lambda (e) (bang! midiin e)))