Music 680 (Spring 2006): Special Topics in Music Theory - Programming for Sound Synthesis
Assignment 4: due Wednesday, March 8, 2006

The goal for this assignment is to create a CLM instrument which implements FM synthesis using more than two oscillators. (Remember that part of the reason for the Yamaha DX7's success was that it offered six "operators", or oscillators, which made it much more timbrally flexible than its two- and four-oscillator predecessors).

You are welcome to implement as many oscillators as you like -- your instrument might have several carrier oscillators, several modulator oscillators, or both. You could create an instrument which additively combines the outputs of several independent arrier/modulator pairs (a "parallel FM" structure), an instrument in which a carrier/modulator pair is used to modulate another carrier (a "serial FM" structure), or perhaps one in which several modulators are added together and then act in combination on a single carrier. The Roads Computer Music Tutorial sections on frequency modulation can give you a number of ideas for useful FM structures.

To help get you started, take a look at the following instrument, in which a single modulator operates on two separate carrier oscillators, which are then added together to form the output:

(definstrument two-carrier (start-time duration carrier-frequency-1 carrier-frequency-2 modulator-frequency index-envelope amplitude-envelope)
    (let* ((start-sample (* start-time *srate*))
           (end-sample (+ start-sample (* duration *srate*)))
           (carrier-1 (make-oscil :frequency carrier-frequency-1))
           (carrier-2 (make-oscil :frequency carrier-frequency-2))
           (modulator (make-oscil :frequency modulator-frequency))
           (index-env (make-env :duration duration :envelope index-envelope :scaler (hz->radians modulator-frequency)))
           (amp-env (make-env :duration duration :envelope amplitude-envelope))
           (modulator-output 0.0))
      (run
       (loop for sample-number from start-sample to end-sample do
            (setf modulator-output (* (env index-env) (oscil modulator))) ; capture modulator output so we can use it twice
            (outa sample-number (* 0.5                                    ; scale by 0.5 to compensate for addition of two oscillators
                                   (env amp-env)
                                   (+ (oscil carrier-1 modulator-output)  ; note the additive structure here....
                                      (oscil carrier-2 modulator-output))))))))

; (with-sound (:srate 44100 :statistics t) (two-carrier 0 10 440 660 110 '(0 0 1 5) '(0 0 0.1 0.9 0.9 0.9 1 0)))

Please remember to include a sample (with-sound) call along with your instrument code. Good luck and let me know if I can assist!