;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; ;;; Banded Waveguide Instrument based on ;;; ====== ========= ;;; ;;; Essl, G. and Cook, P. "Banded ;;; Waveguides: Towards Physical Modelling of Bar ;;; Percussion Instruments", Proceedings of the ;;; 1999 International Computer Music Conference. ;;; ;;; Also, Essl, Serafin, Cook, and Smith J.O., ;;; "Theory of Banded Waveguides", CMJ, 28:1, ;;; pp37-50, Spring 2004. ;;; ;;; NOTES: ;;; As with all physical models, initial conditions matter. ;;; Frequency range is not too broad. 220Hz. is a good ;;; starting point. ;;; ;;; ;;; Tuned bar, Glass Harmonica and Uniform Bar for now. ;;; ;;; 08/22/2013 update bandpass filters with CLM's filter generator (juanig) ;;; 08/24/2013 replaced delay line macros with DelayL using clm's delay ug ;;; 08/29/2014 fixed waveguide with feed and reflections ;;; 08/30/2014 Try different delay line lengths. Fixing bandpass radius param. ;;; 09/04/2014 This SND's S7 version ;;; (define* (make-bowtable (offset 0.0) (slope 1.0)) (float-vector offset slope)) (define (bowtable b samp) (max 0.0 (- 1.0 (abs (* (b 1) (+ samp (b 0))))))) (define (make-bandpassbq freq radius) (let ((arra (make-float-vector 3)) (arrb (make-float-vector 3))) (set! (arra 1) (* -1.998 radius (cos (hz->radians freq)))) (set! (arra 2) (* radius radius)) ;;; ;;; gain gets normalized ;;; (set! (arrb 0) (- 0.5 (* 0.5 (arra 2)))) (set! (arrb 2) (- (arrb 0) )) (make-filter 3 arra arrb) )) ;;; To handle bandpass filter (define (bandpassbq f sample0) (filter f sample0)) ;;; Delay line structures and functions using SND's delay generator (as per prc95.scm) (defgenerator dlya (outp 0) (input #f)) (define (make-delayl len lag) (make-dlya :input (make-delay len :max-size (ceiling (+ len lag 1))) :outp (- lag len))) (define (delayl d samp) (delay-tick (d 'input) samp) (tap (d 'input) (d 'outp))) ;;;;;;;;;;;;;;;;;;;; (definstrument (bandedwg beg dur freq amplitude ;; vibration modes ;; 1=tuned Bar; 2=Glass Harmonica; ;; 3= Uniform bar (mode 3) (maxa 0.9998) ;; max bow velocity (bv 1.0) ;; bow velocity scaler ;; velocity envelope (vel-env '(0 1.0 .95 1.1 1 1.0)) (amp-env '(0 1 1 1)) ;;'(0 0.0 .95 1.0 .99 0.00)) (rev-amount .08) ) (let ((nrmodes 4)) (cond ((= mode 1) (set! nrmodes 4)) ((= mode 2) (set! nrmodes 6)) (else (set! nrmodes 4)) ) (let* ((start (seconds->samples beg)) (baselen (/ *clm-srate* freq)) ;; original Stk delayl length (baselag (- (/ *clm-srate* freq) 0.5)) (dtapoffs 0.0) ;; tap offset is 0.0 in StK's version (bandpass (make-vector nrmodes)) (delayslft (make-vector nrmodes)) (delaysrfl (make-vector nrmodes)) (modes (make-float-vector nrmodes)) (gains (make-float-vector nrmodes)) (basegains (make-float-vector nrmodes)) (excitations (make-float-vector nrmodes)) (delastout (make-float-vector nrmodes)) ;; (fradius 0.0) ;; radius for bandpass filter (dlength 0.0) ;; delay-line length (dlag 0.0) ;; delay lag (for tap) ;; (bowtab (make-bowtable :slope 3.0 :offset 0.001)) (ampenv (make-env amp-env :scaler amplitude :duration dur)) ;; (vel-env (make-env vel-env :scaler bv :duration dur)) ;; (maxvelocity maxa) (end (+ start (seconds->samples dur))) ) ;; ;; (cond ((= mode 1) ;; Tuned Bar (begin (set! (modes 0) 1.000) (set! (modes 1) 4.0198391420) (set! (modes 2) 10.7184986595) (set! (modes 3) 18.0697050938) (do ((i 0 (+ i 1))) ((= i nrmodes)) (set! (basegains i) (expt 0.998 (+ i 1))) (set! (excitations i) 1.0) ) )) ((= mode 2) ;; Glass Harmonica (begin (set! (modes 0) 1.000) (set! (modes 1) 2.32) (set! (modes 2) 4.25) (set! (modes 3) 6.63) (set! (modes 4) 9.38) (set! (modes 5) 12.22) (do ((i 0 (+ i 1))) ((= i nrmodes)) (set! (basegains i ) (expt 0.988 (+ i 1))) (set! (excitations i) 1.0)) )) (else ;; Uniform Bar (begin (set! (modes 0) 1.000) (set! (modes 1) 2.756) (set! (modes 2) 5.404) (set! (modes 3) 8.933) (do ((i 0 (+ i 1))) ((= i nrmodes)) (set! (basegains i ) (expt 0.9 (+ i 1))) (set! (excitations i) 1.0)) )) ) ;; ;; set-frequency method in STK's BandedWG ;; ;; (set! fradius (- 1.0 (* pi (/ 32 *clm-srate*)))) (set! fradius (- 0.3998 (* pi (/ 32 *clm-srate*)))) (do ((i 0 (+ i 1))) ((= i nrmodes)) (set! dlength (floor (/ baselen (modes i)))) (set! dlag (floor (/ baselag (modes i)))) ;; (- lag len) --> tap offset (set! (delayslft i) (make-delayl dlength dlag)) (set! (delaysrfl i) (make-delayl dlength dlag)) (set! (gains i) (basegains i)) (set! (bandpass i) (make-bandpassbq (* freq (modes i)) fradius)) ) ;; ;;;;;;;;;;;; ;; (do ((i start (+ i 1))) ((= i end)) ;; (let ((input 0.0) (velinput 0.0) (bowvelocity 0.0) (bplastout 0.0) (dlastsampl 0.0) (outsampl 0.0) ) (do ((k 0 (+ k 1))) ((= k nrmodes)) (set! velinput (+ velinput (* (basegains k) (delastout k))) ) ) ;; ;; (set! bowvelocity (* 0.3 (env vel-env) maxvelocity)) (set! bowvelocity (* 0.3 maxvelocity)) (set! input (- bowvelocity velinput)) (set! input (* input (bowtable bowtab input))) (set! input (/ input nrmodes )) ;; ;; Here the waveguide ;; (do ((j 0 (+ j 1))) ((= j nrmodes)) (set! bplastout (+ bplastout (bandpassbq (bandpass j) (delayl (delayslft j) (+ input (* (gains j) dlastsampl)) )))) (set! dlastsampl (+ dlastsampl (delayl (delaysrfl j) bplastout))) (set! (delastout j) dlastsampl) ) ;; ;; (set! outsampl (* 4.0 (env ampenv) bplastout)) (outa i outsampl) ;; (if *reverb* (begin (outa i (* outsampl rev-amount) *reverb*))) ))) )) ;;; (with-sound () (bandedwg 0 1 220 0.4)) ;;; (with-sound () (bandedwg 0 1 220 0.4 :mode 1)) ;;; (with-sound () (bandedwg 0 1 220 0.4 :mode 2)) ;;; (with-sound () (bandedwg 0 1.0 220 0.7 :mode 1 :maxa 0.497))