Music 220b: Winter 2001
Fernando Lopez-Lezcano, instructor
Christopher Burns, teaching assistant
Tamara Smyth, teaching assistant
Week 3: structuring a large score
Some useful ideas for longer and more complicated scores:
(with-mix)
The (with-mix) function lets you encapsulate a finished section of your piece and save it as a temporary soundfile. Each time you render your score by sending a (with-sound) call to the interpreter, CLM will look at the section inside the (with-mix) and examines it for changes. If there are no differences from the last time it was computed, CLM simply slots the temporary soundfile into place. This can save enormous amounts of computation for complex scores....
The syntax is much like (with-sound):
(with-mix () "section-name" start-time (...arbitrary lisp code))
For example, this code writes two temporary soundfiles, "/zap/a1.snd" and "/zap/a2.snd":
(with-sound (:statistics t :channels 4 :srate 44100 :output "/zap/mockup1.snd") (with-mix () "a1" 0 (let* ((default-envelope '(0 1 0.6 1 1 0))) (ringer "/usr/ccrma/snd/cburns/double1.snd" "/usr/ccrma/snd/cburns/4convolve1.snd" :first-srate 0.18 :first-start 30 :second-srate 0.97 :second-start 1 :scaler 3.3 :degree 0))) (with-mix () "b1" 70.7 (let* ((default-decay 0.0001) (default-scaler 0.6) (default-amp-srate 0.001) (default-envelope '(0 0 0.75 1 1 0))) (follower "/usr/ccrma/snd/cburns/double4.snd" "/usr/ccrma/snd/cburns/4convolve1.snd" :degree 0 :start 10 :duration 55 :spectr-srate 0.99))))
(open-input)
The (open-input) function provides a similar capability, except that we can load arbitrary lisp code from another file entirely. In the example below, files like "left-1-1.clm" were lisp files containing a single (with-sound) call; this code combines the files in order and provides mixing instructions. (It's not exactly Pro Tools, but it works). As with (with-mix), whenever one of the underlying "channel-n-n" files was changed, its associated soundfile will be recomputed.
(with-sound (:statistics t :srate 44100 :channels 2 :output "/zap/questionsfissures.snd") ; left channel section 1 (mix (open-input "/zap/left-1-1") :start-time 0.0 :ampAA 1.0) (mix (open-input "/zap/left-1-2") :start-time 12.0 :ampAA 0.65) (mix (open-input "/zap/left-1-3") :start-time 28.0 :ampAA 1.0) (mix (open-input "/zap/left-1-4") :start-time 90.0 :ampAA 0.85) ; right channel section 1 (mix (open-input "/zap/right-1-1") :start-time 0.0 :ampAB 1.0) (mix (open-input "/zap/right-1-2") :start-time 48.0 :ampAB 0.85) (mix (open-input "/zap/right-1-3") :start-time 71.0 :envAB '(0 0.9 1 1) :ampAB 0.9) (mix (open-input "/zap/right-1-4") :start-time 114.0 :ampAB 1.0) (mix (open-input "/zap/right-1-5") :start-time 176.0 :ampAB 1.0)
(mix)
The above example suggests that the (mix) function is also extremely useful -- as you can see, any soundfile can be added into a mix by using (mix) inside of (with-sound). Start-time, duration, amplitude, and amplitude envelope parameters are all demonstrated above, and mono files are panned left and right using the AA and AB commands. (AA maps input channel 1 to output channel 1; AB maps input channel 1 to output channel 2. BA maps 2 to 1, and BB maps 2 to 2). See the CLM manual for more complicated uses of mix. (Note: the example above was composed with CLM-1; things may have changed in CLM-2).
(sound-let)
The (sound-let) is essentially a local or temporary binding for soundfiles. Why is that useful? Well, imagine making a soundfile for use as grani fodder:
(with-sound (:srate 44100 :statistics t) (sound-let ((temp-1 () (loop for i from 0 by 0.1 below 5 do (fm-violin i (+ i 0.1) (- 440 (* i 50)) 0.02)))) (grani 0 15 1.0 temp-1 :grain-start-spread '(0 0 1 1) :grain-density '(0 5 1 100))))
As always, there are many other possibilities -- check the CLM manual for more details.