;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; leslie.cms ;; ;; Time varying delay-lines ;; ======================== ;; Doppler shift for Leslie ;; ;; Based on: ;; Abel, Berners, Serafin, Smith J.O ;; "Doppler Simulation and the Leslie", ;; Proc. of DAFx-02, September, 2002 ;; ;; Thanks to Patty Huang ;; ;; ;; Syntax: CLM-4, S7 ;; ;; ;; juanig@ccrma ;; ;; ;; NOTES: ;; Get Leslie effect on a pulse-train waveshape. Try acceleration with the vel-envelope. ;; It can also be used to apply a Leslie effect to a soundfile. Just switch to the ;; 'make-readin', readin ug. ;; ;; First version: Sat 20 Mar 2004 11:22:47 AM PST ;; Last update: Wed 13 Nov 2019 04:13:30 PM PST ;; ;; HISTORY: ;; 06/20/2014 fixed delays and delay lines length ;; 09/10/2014 added reflection delay lines ;; 09/12/2014 added lowport baffle section ;; 09/18/2014 S7 .cms version ;; 11/13/2019 Fixed delay line lengths and added a two-pole for the baffle part. ;; Removed butterworth in exchange for a two-pole frequency shifting. ;; ;; ;; (define sspeed 345.12) ;; Velocity of sound (define twopi (* 2 pi)) (define oneturn (* pi 2)) ;; ;;; ;; (definstrument (rotates start dur freq (speedsl 3.33) ;; Speed source listener mts/sec (velenv '(0 1 100 1)) ;; Velocity envelope (gain 0.35) ;; scales output ;; (onset 0.0) ;; onset duration (secs) in case of reading a soundfile (rev-amount 0.025)) ;; very short reverb (let* ((beg (seconds->samples start)) (sig (make-pulse-train :frequency freq)) ;; (rdA (make-readin :file infile ;; just in case you want to read ;; :start (seconds->samples onset))) ;; a soundfile instead ;;; (maxddelayl (if (= *clm-srate* 44100) (values 160) (values 192))) (startddelay (if (= *clm-srate* 44100) (values 48) (values 52))) (m2samp (/ *clm-srate* sspeed)) (vel-env (make-env velenv :duration (* dur 0.5))) ;;; ;;; Doppler delay lines ;;; (dpdelays (make-vector 4)) (dshift (make-vector 4 startddelay)) ;; ;;; ;;; Reflection path delay arrays ;;; (refldelays (make-vector 4)) (reflectlen (make-vector 4)) (reflections (make-vector 4 0.0)) (hornout (make-vector 4 0.0)) ;; ;; Lowpass (baffle) 'frequency shift' array (fshift (make-vector 4)) (baffleout (make-vector 4)) ;; ;; (lpf (make-vector 4)) ;; ;; (growf0 0.0) (growf1 0.0) (growfa 0.0) (growfb 0.0) ;; (hornangvel 1.0) (baffleangvel 1.0) (hornangle 0.0) (hornradius 0.18) (baffleangle 0.0) (baffleradius 0.19050) ;; (xdev 0.0) (ydev 0.0) (cabinetlen 0.71) (cabinetwid 0.52) ;; (end (+ beg (seconds->samples dur))) ) ;; ;; Make delays ;; (do ((i 0 (1+ i))) ((= i 4 )) (set! (dpdelays i) (make-delay :size startddelay :max-size maxddelayl :type mus-interp-linear )) (set! (refldelays i) (make-delay :size startddelay :max-size (ceiling (* cabinetlen 2 m2samp)) )) ) ;; ;; Make filters ;; (do ((i 0 (1+ i))) ((= i 4 )) (set! (lpf i) (make-two-pole :a0 0.304 :b1 0.62986 :b2 0.825)) ) ;; ;; ;;; ;;; main loop ;;; (do ((i beg (1+ i))) ((= i end )) ;; (let ((sample (pulse-train sig)) ;; (sample (readin rdA)) ;; switch in case of reading a soundfile (deltavel (env vel-env)) (sigouta 0.0) (sigoutb 0.0) ;; horn (sigoutc 0.0) (sigoutd 0.0) ;; reflections (woofera 0.0) (wooferb 0.0)) ;; low baffle output ;; ;;; set acceleration of horn ;; (set! hornangvel (* speedsl deltavel)) (set! hornangle (+ hornangle (* twopi (/ hornangvel *clm-srate*)))) ;; ;;; set motion parameter for baffle lower port ;; (set! baffleangvel (* 0.895 speedsl )) ;; 0.98 (set! baffleangle (+ baffleangle (* twopi (/ baffleangvel *clm-srate*)))) ;; (if (> hornangle twopi) (set! hornangle (- hornangle twopi))) (if (> baffleangle twopi) (set! baffleangle (- baffleangle twopi))) ;; ;;; calculate grow functions for delay line size (horn Doppler shifts) ;; (set! growf0 (/ (*(* (- twopi) hornradius) (* hornangvel (cos hornangle))) sspeed)) (set! growf1 (/ (*(* (- twopi) hornradius) (* hornangvel (sin hornangle))) sspeed)) ;; (set! (dshift 0) (- (dshift 0) growf0)) (set! (dshift 1) (- (dshift 1) growf1)) (set! (dshift 2) (- (dshift 2) (- growf0))) (set! (dshift 3) (- (dshift 3) (- growf1))) ;; (do ((j 0 (1+ j))) ((= j 4)) (set! (hornout j ) (delay (dpdelays j) sample (dshift j))) ) ;; ;;; Reflections ;; (set! xdev (* hornradius (cos hornangle))) (set! ydev (* hornradius (sin hornangle))) (set! (reflectlen 0) (* (+ (/ cabinetwid 2) ydev) m2samp)) (set! (reflectlen 1) (* (- cabinetlen xdev) m2samp)) (set! (reflectlen 2) (* 1.5 (- cabinetwid ydev) m2samp)) (set! (reflectlen 3) (* (+ cabinetlen xdev) m2samp)) ;; ;; Need to add these reflections to *reverb* ;; (do ((j 0 (1+ j))) ((= j 4)) (set! (reflections j) (delay (refldelays j) (hornout j) (reflectlen j)))) ;; (set! sigouta (+ (hornout 0) (hornout 2))) (set! sigoutb (+ (hornout 1) (hornout 3))) (set! sigoutc (+ (reflections 0) (reflections 2))) (set! sigoutd (+ (reflections 1) (reflections 3))) ;; ;; ;; Grow functions baffle low port section (set! growfa (* (- twopi) baffleradius baffleangvel (cos baffleangle))) (set! growfb (* (- twopi) baffleradius baffleangvel (sin baffleangle))) ;; (set! (fshift 0) (+ 200 (* growfa 250))) (set! (fshift 1) (+ 200 (* growfb 250))) (set! (fshift 2) (+ 225 (* (- growfa) 250))) (set! (fshift 3) (+ 225 (* (- growfb) 250))) ;; ;;; Filter for baffle low port section ;; (do ((k 0 (1+ k))) ((= k 4)) (set! (mus-frequency (lpf k)) (fshift k)) (set! (mus-scaler (lpf k)) 0.938987) ) ;; ;; (do ((k 0 (1+ k))) ((= k 4)) (set! (baffleout k) (two-pole (lpf k) sample)) ) ;; ;; (set! woofera (* 0.175 (+ (baffleout 0) (baffleout 2)))) (set! wooferb (* 0.175 (+ (baffleout 1) (baffleout 3)))) ;; ;; (outa i (* gain (+ sigouta sigoutc woofera))) (outb i (* gain (+ sigoutb sigoutd wooferb))) ;; ;;; in case of reverb ;; (if *reverb* (progn (outa i (* (* 0.5 gain) (+ sigouta woofera) rev-amount) *reverb*) (outb i (* (* 0.5 gain) (+ sigoutb wooferb) rev-amount) *reverb*) )) )) )) ;;; (with-sound (:channels 2) (rotates 0 1 800)) ;;; (with-sound (:channels 2) (rotates 0 3 200)) ;;; (with-sound (:channels 2) (rotates 0 8 300 :speedsl 1.0)) ;;; (with-sound (:channels 2) (rotates 0 3 500 :speedsl 1.0)) ;;; (with-sound (:channels 2) (rotates 0 3 800 :velenv '(0 0.05 100 1))) ;;; (with-sound (:channels 2) (rotates 0 3 500 :velenv '(0 1 100 0.25))) ;;; (with-sound (:channels 2) (rotates 0 5 1000 :velenv '(0 0.25 50 1 100 0.3))) ;;; (load "nrev.ins") ;;; (with-sound (:channels 2 :reverb nrev :reverb-channels 2) (rotates 0 5 500 :velenv '(0 1 100 0.25)))