; flanger.ins
; bring back the seventies!
; last updated lcb 02.20.2001

(definstrument flanger (source-filename &key 
					 (source-srate 1.0)
					 (start 0.0)
					 (duration nil)
					 (min-delay-samples 599)
					 (max-delay-samples 699) 
					 (frequency 0.75)
					 (feedback 0.9)    ; should still be < 1.0
					 (gain 0.5)        ; scales output
					 (decay-time 0.1)) ; lengthens output file
  (let* ((source-file (open-input* source-filename))
	 (source-file-duration (/ (sound-duration source-filename) 
				  (abs source-srate)))
	 (minimum-duration (if (null duration)
			       (+ decay-time source-file-duration)
			     (+ decay-time
				(min duration source-file-duration))))
	 (source-src (make-src :input source-file
			       :srate source-srate))
	 (oscil-width (/ (- max-delay-samples min-delay-samples) 2))
	 (oscil-center (/ (+ max-delay-samples min-delay-samples) 2))
	 (oscillator (make-oscil :frequency frequency))
	 ; oscillator is used to drive the delay length
	 ; to put it another way, the delay length varies sinusoidally
	 (echo (make-delay :size oscil-center :max-size max-delay-samples)))
	 ; using the :max-size variable automatically forces (make-delay) to create an
	 ; interpolating / fractional delay line
    (multiple-value-bind (beg end) (times->samples start minimum-duration)
      (run
       (loop for i from beg to end do
	 (outa i (* gain (delay echo 
				(+ (src source-src)
					(* feedback (tap echo)))
				(* oscil-width (oscil oscillator))))))))
      (close-input source-file)))

#|
example with-sound call:

(with-sound (:statistics t :srate 44100 :scaled-to 0.9)  (flanger "/usr/ccrma/snd/cburns/trumpet4.snd"))
|#