$nyquist plug-in $version 3 $type process $preview linear $name (_ "Delay") $manpage "Delay" $action (_ "Applying Delay Effect...") $author (_ "Steve Daulton") $release 2.3.0 $copyright (_ "Released under terms of the GNU General Public License version 2") ;; by Steve Daulton, July 2012. ;; based on 'Delay' by David R. Sky ;; Released under terms of the GNU General Public License version 2: ;; http://www.gnu.org/licenses/old-licenses/gpl-2.0.html ;; ;; For information about writing and modifying Nyquist plug-ins: ;; https://wiki.audacityteam.org/wiki/Nyquist_Plug-ins_Reference $control delay-type (_ "Delay type") choice ( (_ "Regular") ("BouncingBall" (_ "Bouncing Ball")) ("ReverseBouncingBall" (_ "Reverse Bouncing Ball")) ) 0 $control dgain (_ "Delay level per echo (dB)") real "" -6 -30 1 $control delay (_ "Delay time (seconds)") real "" 0.3 0 5 $control pitch-type (_ "Pitch change effect") choice ( ("PitchTempo" (_ "Pitch/Tempo")) ("LQPitchShift" (_ "Low-quality Pitch Shift")) ) 0 $control shift (_ "Pitch change per echo (semitones)") real "" 0 -2 2 $control number (_ "Number of echoes") int "" 5 1 30 $control constrain (_ "Allow duration to change") choice ( (_ "Yes") (_ "No") ) 0 ;; The default pitch shift effect is a simple resampling, ;; so both pitch and tempo of the delayed audio will change ;; [as in Audacity's Change Speed effect]. ;; LQ Pitch Shift (Low Quality) changes the pitch without ;; changing the tempo, but the sound quality is not very good ;; and tends to cause a short echo effect which can be quite ;; noticeable on percussive sounds though may be acceptable ;; on other sounds. (setf err "") ; initialise error message (defun err-chk (arg min max) (if (or (< arg min) (> arg max)) T nil)) (when (err-chk number 1 50)(setq err (format nil (_ "Number of echoes '~a' outside valid range 1 to 50.~%~a") number err))) (when (err-chk shift -12 12)(setq err (format nil (_ "Pitch change '~a' outside valid range -12 to +12 semitones.~%~a") shift err))) (when (err-chk delay 0 10)(setq err (format nil (_ "Delay time '~a' outside valid range 0 to 10 seconds.~%~a") delay err))) (when (err-chk dgain -30 6)(setq err (format nil (_ "Delay level '~a' outside valid range -30 to +6 dB.~%~a") dgain err))) ;;; anti-alias low pass filter (defun lp-wall (sig freq) (do ((count 0 (1+ count)) (freq (* 0.94 freq))) ((= count 10) sig) (setf sig (lowpass8 sig freq)))) ;;; Change speed (defun change-speed (sig shift) (if (= shift 0) ; no pitch shift sig (let ((ratio (expt 0.5 (/ shift 12.0)))) ; shift value as frequency ratio (force-srate *sound-srate* (stretch-abs ratio (sound sig)))))) ;;; pitch shift audio (defun p-shift (sig shift) (if (= shift 0) ; no pitch shift sig (let ((sig (force-srate 44100 sig)) ; pitshift quality best at 44100 ; anti-alias filter frequency (minrate (* 0.5 (min *sound-srate* 44100))) (ratio (expt 0.5 (/ shift -12.0)))) ; shift value as frequency ratio (force-srate *sound-srate* ; convert back to correct rate (progv '(*sound-srate*) (list 44100) ; pitshift requires rates to match (cond ((> shift 5) ; reduce aliasing (pitshift (lp-wall sig (/ minrate ratio)) ratio 1)) ((< shift -2) (pitshift (hp sig 20) ratio 1)) ; reduce sub-sonic frequencies (T (pitshift sig ratio 1)))))))) ;;; apply effects to echo (defun modify (sig num gain shift p-type) (let ((gain (db-to-linear (* num gain))) (shift (* num shift))) (if (= p-type 0) (mult gain (change-speed sig shift)) (mult gain (p-shift sig shift))))) ;;; compute echoes (defun delays (sound gain delay shift num type mod) (let ((echo (s-rest 0))) (do ((count 1 (1+ count)) (dly 0)) ((> count num)(sim echo sound)) (setq dly (case type (0 (+ dly delay)) (1 (+ dly (* delay (- (1+ num) count)))) (2 (+ dly (* delay count))))) (setf echo (sim (at 0 (cue echo)) (at-abs dly (cue (modify sound count gain shift mod)))))))) (defun constrain-abs (sig dur) (extract-abs 0 dur (cue sig))) ;;; return errors or process (if (> (length err) 0) (format nil (_ "Error.~%~a") err) ; return error (let* ((delay (if (= delay-type 0) delay (/ delay number))) (output (multichan-expand #'delays s dgain delay shift number delay-type pitch-type))) (if (= constrain 1) (multichan-expand #'constrain-abs output (get-duration 1)) output)))