1$nyquist plug-in 2$version 3 3$type process 4$preview enabled 5$name (_ "Vocoder") 6$manpage "Vocoder" 7$action (_ "Processing Vocoder...") 8$author (_ "Edgar-RFT") 9$release 2.3.0 10$copyright (_ "Released under terms of the GNU General Public License version 2") 11 12;; vocoder.ny by Edgar-RFT 13;; a bit of code added by David R. Sky 14;; GUI update by Steve Daulton July 2012. 15;; Performance improvement, error message for mono, code cleanup 16;; by Paul Licameli and Steve Daulton October 2014 17 18;; Released under terms of the GNU General Public License version 2: 19;; http://www.gnu.org/licenses/old-licenses/gpl-2.0.html 20;; 21;; For information about writing and modifying Nyquist plug-ins: 22;; https://wiki.audacityteam.org/wiki/Nyquist_Plug-ins_Reference 23 24$control dst (_ "Distance: (1 to 120, default = 20)") real "" 20 1 120 25$control mst (_ "Output choice") choice ( 26 ("BothChannels" (_ "Both Channels")) 27 ("RightOnly" (_ "Right Only")) 28) 0 29$control bands (_ "Number of vocoder bands") int "" 40 10 240 30$control track-vl (_ "Amplitude of original audio (percent)") real "" 100 0 100 31$control noise-vl (_ "Amplitude of white noise (percent)") real "" 0 0 100 32$control radar-vl (_ "Amplitude of Radar Needles (percent)") real "" 0 0 100 33$control radar-f (_ "Frequency of Radar Needles (Hz)") real "" 30 1 100 34 35; maybe the code once again has to be changed into _one_ local let-binding 36; if you have lots of nyquist "[gc:" messages try this: 37; (expand 100) ; gives Xlisp more memory but I have noticed no speed difference 38 39;; number of octaves between 20hz and 20khz 40(setf octaves (/ (log 1000.0) (log 2.0))) 41 42;; convert octaves to number of steps (semitones) 43(setf steps (* octaves 12.0)) 44 45;; interval - number of steps per vocoder band 46(setf interval (/ steps bands)) 47 48;;; Some useful calculations but not used in this plugin 49 50;; half tone distance in linear 51; (print (exp (/ (log 2.0) 12))) 52 53;; octave distance in linear 54; (print (exp (/ (log 1000.0) 40))) 55 56;;; The Radar Wavetable 57 58;; make *radar-table* a global variable. 59(setf contol-dummy *control-srate*) ; save old *control-srate* 60(set-control-srate *sound-srate*) 61(setf *radar-table* (pwl (/ 1.0 *control-srate*) 1.0 ; 1.0 after 1 sample 62 (/ 2.0 *control-srate*) 0.0 ; 0.0 after 2 samples 63 (/ 1.0 radar-f))) ; stay 0.0 until end of the period 64(set-control-srate contol-dummy) ; restore *control-srate* 65;; make *radar-table* become a nyquist wavetable of frequency radar-f 66(setf *radar-table* (list *radar-table* (hz-to-step radar-f) T)) 67 68;; increase the volume of the audacity track in the middle of the slider 69;; the sqrt trick is something like an artificial db scaling 70(setf track-vol (sqrt (/ track-vl 100.0))) 71;; decrease the volume of the white noise in the middle of the slider 72;; the expt trick is an inverse db scaling 73(setf noise-vol (expt (/ noise-vl 100.0) 2.0)) 74;; also increase the volume of the needles in the middle of the slider 75(setf radar-vol (sqrt (/ radar-vl 100.0))) 76 77;;; here you can switch the tracks on and off for bug tracking 78 79; (setf radar-vol 0) 80; (setf noise-vol 0) 81; (setf track-vol 0) 82 83;;; The Mixer 84 85;; calculate duration of audacity selection 86(setf duration (/ len *sound-srate*)) 87 88(defun mix () 89 ;; if track volume slider is less than 100 percent decrease track volume 90 (if (< track-vl 100) 91 (setf s 92 (vector (aref s 0) (scale track-vol (aref s 1))))) 93 94 ;; if radar volume slider is more than 0 percent add some radar needles 95 (if (> radar-vl 0) 96 (setf s 97 (vector (aref s 0) 98 (sim (aref s 1) 99 (scale radar-vol (osc (hz-to-step radar-f) 100 duration *radar-table*)))))) 101 102 ;; if noise volume slider is more than 0 percent add some white noise 103 (if (> noise-vl 0) 104 (setf s 105 (vector (aref s 0) 106 (sim (aref s 1) (scale noise-vol (noise duration))))))) 107 108;;; The Vocoder 109 110(defun vocoder () 111 (do* ((i 0 (1+ i)) 112 mod-envelope ; local variable for filtered envelope of left channel. 113 band ; local variable for band-passed audio. 114 (result 0) ; result must be initialized because you cannot sum to NIL. 115 (q (/ (sqrt 2.0) (/ octaves bands))) ; quick approximation of q 116 ; for given bandwidth. 117 (p (+ (hz-to-step 20) (/ interval 2.0)) ; midi step of 20 Hz + offset. 118 (+ p interval)) 119 (f (step-to-hz p) (step-to-hz p))) 120 ((= i bands) result) ; DO for each band then return 'result'. 121 (setf band (bandpass2 s f q)) ; intermediate results (2 channels) 122 (setf mod-envelope (lowpass8 (s-abs (aref band 0)) (/ f dst))) 123 (setf result 124 (sum result 125 (bandpass2 126 (mult mod-envelope (aref band 1)) 127 f q))))) 128 129;;; The Program 130 131(cond 132 ((arrayp s) 133 (mix) ; changes s 134 (let ((original (or (= mst 0) (aref s 0)))) 135 (setf s (vocoder)) 136 ;; Now normalize s to 0 db peak 137 (setf s (scale (/ (peak s ny:all)) s)) 138 (case mst 139 (0 s) ; let Audacity coerce back to stereo 140 (1 (vector original s))))) 141 (t ; this effect isn't meant for mono 142 (format nil (_ "Error.~%Stereo track required.")))) 143