(define *srate* 44100)

(definstrument (resonator-series start duration pulse-frequency-env center-frequency-env q-env amplitude-env)
  ; chaining bandpass filters in series to try to get a more peaky resonance
  (let* ((start-sample (* start *srate*))
         (end-sample (+ start-sample (* duration *srate*)))
         (pulse-f-env (make-env :envelope pulse-frequency-env
                                :duration duration
                                :scaler (hz->radians 1)))
         (filter-f-env (make-env :envelope center-frequency-env
                                 :duration duration))
         (filter-q-env (make-env :envelope q-env
                                 :duration duration))
         (amp-env (make-env :envelope amplitude-env
                            :duration duration))
         (pulse (make-pulse-train :frequency 0))
         (resonator1 (make-formant :frequency 220 :radius 0.1))
         (resonator2 (make-formant :frequency 220 :radius 0.1))
         (resonator3 (make-formant :frequency 220 :radius 0.1))
         (frequency-placeholder 0.0)
         (q-placeholder 0.0))
    (do ((sample-number start-sample (+ sample-number 1)))
         ((> sample-number end-sample))
          (set! frequency-placeholder (env filter-f-env)) ; only call the envelope function once per sample
          (set! q-placeholder (env filter-q-env))
          (set! (mus-frequency resonator1) frequency-placeholder) ; change the resonator center frequency
          (set! (mus-frequency resonator2) frequency-placeholder)
          (set! (mus-frequency resonator3) frequency-placeholder)
          (outa sample-number (* (env amp-env)
                           (formant resonator1 
                                    (formant resonator2
                                             (formant resonator3 
                                                      (pulse-train pulse (env pulse-f-env))))))))))

(with-sound (:srate 44100 :statistics #t :output "resonator-series1.aiff")
  (resonator-series 0 10 
                    '(0 110 1 440) 
                    '(0 880 1 300)
                    '(0 0.9 1 0.99) 
                    '(0 0 0.5 50 1 0)))

; woodpecker sound :=)
(with-sound (:srate 44100 :statistics #t :output "resonator-series1.aiff") 
  (resonator-series 0 10 
		    '(0 10 1 4) 
		    '(0 880 1 300) 
		    '(0 0.9 1 0.99) 
		    '(0 0 0.5 500 1 0)))