;;; -*- Lisp -*-
;;;
;;; waveguide clarinet as outlined by Julius Smith in "Musical Applications of Digital Waveguides"

(definstrument clarinet (beg dur freq amp att)
  (let* ((start (floor (* beg sampling-rate)))
	 (finish (+ start (floor (* dur sampling-rate))))
	 (len (/ sampling-rate freq))
	 (mouth-function (make-env :envelope (list 0 0 att 1 (- dur att) 1 dur 0) 
				   :scaler 1.0 :start-time beg :duration dur))
	 (bore-right (make-delay len))
	 (bore-left (make-delay (* 2 len)))
	 (noise (make-randh :frequency 1000 :amplitude .001))
	 (reed 0.0)
	 (reed-back 0.0)
	 (filtered 0.0)
	 (la 0.0) (lb 0.0) (lc 0.0)
	 (lowpass (make-one-pole .7 .3))) ;actually a highpass filter, I think
    (Run
     (loop for i from start to finish do
       (setf reed-back (+ (* (env mouth-function) (1+ (randh noise))) (* .9 reed)))
       (setf filtered (one-pole lowpass (* reed-back reed-back (+ .3 (* reed-back -.8)))))
       (setf reed (* .45 (+ (delay bore-right filtered) (delay bore-left filtered))))
       (setf lc lb)			;a "modified least-squares" low pass filter
       (setf lb la)
       (setf la (* amp filtered))
       (outa i (+ (* .5 lb) (* .25 (* (+ la lc)))))))
    (end-run)))

;;; (with-sound () (clarinet 0 2 440 1 .1))

