Nyquist voice synthesis instrument by Eduardo Reck Miranda.
;--------------------------------------------------------------------------- ; Nyquist voice synthesis instrument by Eduardo Reck Miranda ; ; Implements a geometrical articulator for tongue position (h p) and ; lips rouding (r) ; ;--------------------------------------------------------------------------- ; Geometrical articulator: the following FORMx functions estimates the formant ; values from the positions of the three articulators p h and r, where: ; p = horizontal position of the tongue: 0.0 = front and 1.0 = back ; h = vertical position of the tongue: 0.0 = low and 1.0 = high ; r = rounding of the lips: 0.0 = spread -> 1.0 rounded ;--------------------------------------------------------------------------- ; FORM1: converts p-h-r articulators to first formant frequency ;--------------------------------------------------------------------------- (defmacro form1 (p h r) `(+ (* (+ (* (+ (- 392) (* 392 ,r)) (expt ,h 2)) (* (- 596 (* 668 ,r)) ,h) (+ (- 146) (* 166 ,r))) (expt ,p 2)) (* (+ (* (- 348 (* 348 ,r)) (expt ,h 2)) (* (+ (- 494) (* 606 ,r)) ,h) (- 141 (* 175 ,r))) ,p) (+ (* (- 340 (* 72 ,r)) (expt ,h 2)) (* (+ (- 796) (* 108 ,r)) ,h) (- 708 (* 38 ,r))) )) ;--------------------------------------------------------------------------- ; FORM2: converts p-h-r articulators to second formant frequency ;--------------------------------------------------------------------------- (defmacro form2 (p h r) `(+ (* (+ (* (+ (- 1200) (* 1208 ,r)) (expt ,h 2)) (* (- 1320 (* 1328 ,r)) ,h) (- 118 (* 158 ,r))) (expt ,p 2)) (* (+ (* (- 1864 (* 1488 ,r)) (expt ,h 2)) (* (+ (- 2644) (* 1510 ,r)) ,h) (+ (- 561) (* 221 ,r))) ,p) (+ (* (+ (- 670) (* 490 ,r)) (expt ,h 2)) (* (- 1355 (* 697 ,r)) ,h) (- 1517 (* 117 ,r))) )) ;--------------------------------------------------------------------------- ; FORM3: converts p-h-r articulators to third formant frequency ;--------------------------------------------------------------------------- (defmacro form3 (p h r) `(+ (* (+ (* (- 604 (* 604 ,r)) (expt ,h 2)) (* (- 1038 (* 1178 ,r)) ,h) (+ 246 (* 566 ,r))) (expt ,p 2)) (* (+ (* (+ (- 1150) (* 1262 ,r)) (expt ,h 2)) (* (+ (- 1443) (* 1313 ,r)) ,h) (- (- 317) (* 483 ,r))) ,p) (+ (* (- 1130 (* 836 ,r)) (expt ,h 2)) (* (+ (- 315) (* 44 ,r)) ,h) (- 2427 (* 127 ,r))) )) ;--------------------------------------------------------------------------- ; FORM4: converts p-h-r articulators to fourth formant frequency ;--------------------------------------------------------------------------- (defmacro form4 (p h r) `(+ (* (+ (* (+ (- 1120) (* 16 ,r)) (expt ,h 2)) (* (- 1696 (* 180 ,r)) ,h) (+ 500 (* 522 ,r))) (expt ,p 2)) (* (+ (* (+ (- 140) (* 240 ,r)) (expt ,h 2)) (* (+ (- 578) (* 214 ,r)) ,h) (- (- 692) (* 419 ,r))) ,p) (+ (* (- 1480 (* 602 ,r)) (expt ,h 2)) (* (+ (- 1220) (* 289 ,r)) ,h) (- 3678 (* 178 ,r))) )) ;--------------------------------------------------------------------------- ; ADSR-SMOOTH: a standard ADSR envelope ;--------------------------------------------------------------------------- (defun adsr-smooth (signal dur) (mult signal (env 0.1 0.2 0.5 1.0 0.8 0.4 dur))) ;--------------------------------------------------------------------------- ; VIBRATO: generates vibrato ; vib-rate = vibrato rate in Hz ; dur = duration in seconds ;--------------------------------------------------------------------------- (defun vibrato (vib-rate dur) (osc (hz-to-step vib-rate) dur)) ;--------------------------------------------------------------------------- ; PULSE-TABLE: build table for generating a pulse signal ; harm = number of harmonics ;--------------------------------------------------------------------------- (defun pulse-table (harm) (abs-env ;prevent any timewarping in the following (let ((table (build-harmonic 1 2048))) (cond ((> harm 1) ;sum remaining harmonics (setf harm (- harm 1)) (dotimes (i harm) (setf table (sum table (build-harmonic (1+ i) 2048)))))) table))) ;--------------------------------------------------------------------------- ; PULSE-WITH-VIBRATO: generate pulse with vibrato ; step = pitch in steps ; duration = duration in seconds ; vib-rate = vibrato rate in Hz ;--------------------------------------------------------------------------- (defun pulse-with-vibrato (step duration vib-rate) (let (harm freq) (setf freq (step-to-hz step)) (setf harm (truncate (/ 22050 (* 2 freq)))) (setf table (scale (/ 1.0 harm) (pulse-table harm))) (fmosc step (vibrato vib-rate duration) (list table (hz-to-step 1) t)))) ;--------------------------------------------------------------------------- ; VOICING-SOURCE: generate voicing source: pulse with vibrato + LPFs ; step = pitch in steps ; duration = duration in seconds ; vib-rate = vibrato rate in Hz ;--------------------------------------------------------------------------- (defun voicing-source (step duration vib-rate) (lp (lp (pulse-with-vibrato step duration vib-rate) (* 1.414 (* 2 (step-to-hz step)))) (* 1.414 (* 4 (step-to-hz step))))) ;--------------------------------------------------------------------------- ; NOISE-SOURCE: generate noise source: noise + offset oscillator + LPF ; step = pitch in steps ; duration = duration in seconds ; vib-rate = vibrato rate in Hz ;--------------------------------------------------------------------------- (defun noise-source (step duration vib-rate) (lp (sum (noise duration) (fmosc step (vibrato vib-rate duration))) 8000)) ;--------------------------------------------------------------------------- ; SOURCE: generate source signal: voicing + noise sources ; freq = fundamental frequency in Hz ; duration = duration in seconds ; vib-rate = vibrato rate in Hz ; voicing-scale = percentage of voicing in the resulting signal (0.0 -> 1.0) ; noise-scale = percentage of noise in the resulting signal (0.0 -> 1.0) ;--------------------------------------------------------------------------- (defun source (freq duration vib-rate voicing-scale noise-scale) (sum (scale voicing-scale (voicing-source (hz-to-step freq) duration vib-rate)) (scale noise-scale (noise-source (hz-to-step freq) duration vib-rate)))) ;--------------------------------------------------------------------------- ; MAKE-SPECTRUM: formant filters ; freq = fundamental frequency in Hz ; dur = duration in seconds ; vib-rate = vibrato rate in Hz ; v-scale = amplitude scaling for the voicing source ; n-scale = amplitude scaling for the noise source ; p = horizontal position of the tongue (0.0 = front -> 1.0 = back) ; h = vertical position of the tongue (0.0 = low -> 1.0 = high) ; r = rouding of the lips (0.0 = spread -> 1.0 = rounded) ;--------------------------------------------------------------------------- (defun make-spectrum (freq dur vib-rate v-scale n-scale p h r) (let ((src (source freq dur vib-rate v-scale n-scale))) (setf spectrum (sim (reson src (form1 p h r) 50 1) (reson (scale-db (- 10) src) (form2 p h r) 70 1) (reson (scale-db (- 14) src) (form3 p h r) 110 1) (reson (scale-db (- 20) src) (form4 p h r) 250 1))))) ;--------------------------------------------------------------------------- ; SYNTHESISE: the synthesise function ; Simplified version of the instrument used by the agents discussed in Chapter 6. ; f0 = pitch frequency ; w1 = amplitude of voicing source (min = 0.0 max = 1.0) ; w2 = amplitude of noise source (min = 0.0 max = 1.0) ; a = horizontal position of the tongue (0.0 = front -> 1.0 = back) ; b = vertical position of the tongue (0.0 = low -> 1.0 = high) ; c = rouding of the lips (0.0 = spread -> 1.0 = rounded) ; fm = vibrato rate (in Hz) ; h = duration in seconds ;--------------------------------------------------------------------------- (defun synthesise (f0 w1 w2 a b c fm h) (adsr-smooth (make-spectrum f0 h fm w1 w2 a b c) h)) ;=== The code for the instrument ends here === ;--------------------------------------------------------------------------- ; Test the SYNTHESISE function with different positions of the articulators ; ; Running steps: ; 1 - run Nyquist ; 2 - load "articulator.lsp" ; 3 - type (play (vowel-1)) to synthesise the first test, and so on ;--------------------------------------------------------------------------- (defun vowel-1 () (synthesise 220 1.0 0.005 0.0 0.0 0.0 5.6 1.0)) (defun vowel-2 () (synthesise 220 1.0 0.005 0.0 0.0 1.0 5.6 1.0)) (defun vowel-3 () (synthesise 220 1.0 0.005 0.5 0.0 0.0 5.6 1.0)) (defun vowel-4 () (synthesise 220 1.0 0.005 0.5 0.0 1.0 5.6 1.0)) (defun vowel-5 () (synthesise 220 1.0 0.005 1.0 0.0 0.0 5.6 1.0)) (defun vowel-6 () (synthesise 220 1.0 0.005 1.0 0.0 1.0 5.6 1.0)) (defun vowel-7 () (synthesise 220 1.0 0.005 0.0 0.5 0.0 5.6 1.0)) (defun vowel-8 () (synthesise 220 1.0 0.005 0.0 0.5 1.0 5.6 1.0)) (defun vowel-9 () (synthesise 220 1.0 0.005 0.5 0.5 0.0 5.6 1.0)) (defun vowel-10 () (synthesise 220 1.0 0.005 0.5 0.5 1.0 5.6 1.0)) (defun vowel-11 () (synthesise 220 1.0 0.005 1.0 0.5 0.0 5.6 1.0)) (defun vowel-12 () (synthesise 220 1.0 0.005 1.0 0.5 1.0 5.6 1.0)) (defun vowel-13 () (synthesise 220 1.0 0.005 0.0 1.0 0.0 5.6 1.0)) (defun vowel-14 () (synthesise 220 1.0 0.005 0.0 1.0 1.0 5.6 1.0)) (defun vowel-15 () (synthesise 220 1.0 0.005 0.5 1.0 0.0 5.6 1.0)) (defun vowel-16 () (synthesise 220 1.0 0.005 0.5 1.0 1.0 5.6 1.0)) (defun vowel-17 () (synthesise 220 1.0 0.005 1.0 1.0 0.0 5.6 1.0)) (defun vowel-18 () (synthesise 220 1.0 0.005 1.0 1.0 1.0 5.6 1.0)) ;; play everything (defun vowel-n (n) (funcall (intern (format nil "VOWEL-~A" n)))) (defun play-all-vowels () (autonorm-off) (dotimes (i 18) (play (scale 20 (vowel-n (1+ i))))) (autonorm-on)) ; (play-all-vowels) will play everything in sequence