Critique a beginner's code!
Larry Troxler
lt@westnet.com
Fri, 15 Nov 1996 22:41:26 -0500 (EST)
Thanks Rick,Tobias, and the other list members for helping this beginner so
far. Unfortunately for you, I am paying you back by offering the following
code for you to critique :-). At this stage, I have a number of questions,
mostly minor details, and I thought it would make the most sense simply to
post some code, with my questions embedded in the comments. So, if anyone
has the time to look through this, I would welcome any suggestions, either
specifically regarding the questions I raise, or more generally, pointing to
ways I should be doing things differently. Thanks in advance, everyone!
Also let me know if the line-formatting gets mangled in transit - if so I
will repost.
Larry Troxler
lt@westnet.com
-----------
;;; A first stab at MIDI creation in CM. Please read through questions in
comments below
;;; and critique! Thanks!
(setf opus-len 60) ; quit after a minute
;;; The following is so we can use names instead of numbers for MIDI program
changes.
(setf patches
'((Org400 8)
(Vulcan-Harp 21)))
;;; This maintains the current MIDI program (patch) for each channel, should
probably
;;; be local to the "pnote" class below - Suggestions, anyone?
(setf cur-chan-pat (make-array 16 :initial-element nil))
;;; "pnote" is a MIDI note which includes a patch parameter. If the "patch"
parameter is
;;; different from
;;; the patch currently being played on a given channel, then write-event
will send the
;;; new program change before the note. What I don't know how to do is to
schedule the
;;; the program change a couple ticks in advance of the note, for synths
that require it.
(defobject pnote (midi-note)
((patch :initarg :patch :initform nil :accessor pnote-patch)))
;;; modeled after the detuned MIDI note class - the guts haven't been tested
thuroughly but
;;; hopefully you understand the concept here.
(defmethod write-event ((me pnote ) file)
(let ((patchnum (second (assoc (pnote-patch me) patches)))) ; symbol -> number
(unless
(eql patchnum (aref cur-chan-pat (slot-value me 'channel))) ; unless
same patch on this channel,
(setf (aref cur-chan-pat (slot-value me 'channel)) patchnum) ; register
new patch.
(let ((obj (object midi-message ; send the
program change.
message (make-program-change
(slot-value me 'channel)
patchnum))))
(setf (slot-value obj 'time) (slot-value me 'time))
(write-event obj file))))
(call-next-method)) ; Always send the original midi-note (obviously)
;;; Now for the specific task at hand.
;;; Following are the two algorithms that will be run for this experiment.
;;; The "Org400" part
(defun do-Org400 (chan)
(algorithm
Org400 pnote (
patch 'Org400
start 0
channel chan
end (- opus-len 1)
amplitude (amplitude 'mf) ; syntax is a bit awkward - why
can't symbolic values
duration (rhythm '32)) ; be directly used in algo inits?
(setf
note
(item
(intervals
7 2 0 ; would be nicer to us symbolic intervals here - how do i do
that?
linked-to 'root)))
(setf
rhythm ; variations on a 7/8 rhythm
(item
(rhythms
e.
(rhythms
((rhythms e. e e) min 4 max 4) ; there's got to be a better way than
the mix/max
((rhythms e e. e) min 4 max 4) ; bit. What I really want is to
choose a new subseq
((rhythms e e e.) min 4 max 4) ; at a rythmic rate of E*7*2*2 = once
every 'root
in random for 1) ; cycle (see 'root stream below). How
should I do that?
e
e)))))
;; The "Vulcan-Harp" part
(defun do-Vulcan-Harp (chan)
(algorithm
Vulcan-Harp pnote (
patch 'Vulcan-Harp
start 0
channel chan
end (- opus-len 1)
duration (rhythm '32))
(setf amplitude (item (amplitudes mp pp pp pp p pp pp))) ; emphasize the
7/8 meter
(setf rhythm (rhythm 'e))
(setf
note
(transpose
(item
(intervals 0 5 10 linked-to 'root)) ; again, symbolic intervals would be
nicer - how?
-12))))
;;; Now, ladies and gentlemen, whithout further adieu(sp?), here's the music!
;;;
;;; One problem with this merge is that the 'root item selection seems to
;;; happen *after* the item selections of the two threads, making the change
of root hapen
;;; after the beat instead of on it. What determines the order of evaluation
and how should
;;; I fix this problem?
(in-tempo 120 'q)
(merge
merge-1 ()
(mute ; "root-selector" sets the root note for the two defun'd algos below.
root-selector (start 0 end opus-len rhythm (rhythm 'e*7*2)) ; 2 7/8
measures per root
(item (notes c4 b3 named 'root))) ; thus, 4 7/8 measures per cycle
; The two parts for this creation:
(do-Org400 1) ; The argument is a MIDI channel #. Eventually it
would be nice
(do-Vulcan-Harp 2)) ; to have a channel allocate/free setup. Any prior art
in this area?
;; the end