;nyquist plug-in
;version 3
;type process
;name "Multi-Tap Test..."
;action "Multi-Tap Test..."
;info "This is a test plugin, not for production use."
;control delay "Room Size" real "ms" 30 15 100
;control decay "Intensity" real "%" 50 25 75
;control cutoff "Brightness" real "Hz" 2000 500 5000
;control rolloff "Damping" real "%" 25 10 50
;control taps "Density" int " " 5 1 10
;control diff "Diffusion" int " " 5 1 10
(setf delay (* 0.001 (min 100 (max 15 delay))))
(setf decay (* 0.01 (min 75 (max 25 decay))))
(setf cutoff (min 5000 (max 500 cutoff)))
(setf rolloff (* 0.01 (- 100 (min 50 (max 10 rolloff)))))
(setf taps (min 10 (max 1 (round taps))))
(setf diff (min 10 (max 1 (round diff))))
(format t "delay ~a~%" delay)
(format t "decay ~a~%" decay)
(format t "cutoff ~a~%" cutoff)
(format t "rolloff ~a~%" rolloff)
(format t "taps ~a~%" taps)
(format t "diff ~a~%" diff)
(defun tapped-delay (snd delay)
(do ((del delay (+ del delay)) ; delay time
(dec decay (* dec decay)) ; volume level
(cut cutoff (* cut rolloff)) ; lowpass frequency
(i 0 (1+ i))) ; tap counter
((= i taps) snd)
(setf snd (sum snd (mult dec (at-abs del (cue (lp snd cut))))))))
;; Running filters in parallel always produces phase-related
;; side-effects because filters have no constant phase behaviour.
;; The only way to avoid unwanted "coloring" of the output signal
;; is to distribute the phase effects possibly equally over the
;; entire audio spectrum, so they can statistically compensate
;; each other.
;;
;; Prime numbers are used for computing the delay times because
;; prime numbers do not have common divisors. This means that
;; multiplying the same base number by different prime numbers
;; cannot produce common multiples. This way no unwanted peaks
;; can occur in the spectrum of the output signal.
;;
;; The prime numbers must be in a range of 1:2 (octave)
(setf prime-offset ; prime numbers
(case diff ( 1 0) ; 2 .. 3
( 2 4) ; 11 .. 19
( 3 8) ; 23 .. 43
( 4 11) ; 37 .. 67
( 5 14) ; 47 .. 89
( 6 15) ; 53 .. 103
( 7 16) ; 59 .. 113
( 8 22) ; 83 .. 163
( 9 23) ; 89 .. 179
(10 24))) ; 97 .. 193
(defun prime-number (n channel)
(aref #(2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79
83 89 97 101 103 107 109 113 127 131 137 139 149 151 157 163
167 173 179 181 191 193)
(+ prime-offset n n channel)))
;; A delay "base" number is computed by dividing the delay time by the
;; smallest prime number, the result is then rounded to the next integer
;; sample time. Multiplying this base number with integer prime numbers
;; will always produce delay times that match integer sample times.
;; round (/ delay first-prime) to the next integer sample value
(setf delay (/ (round (* (/ delay (prime-number 0 0)) *sound-srate*))
*sound-srate*))
(format t "rounded delay ~a~%" (* delay (prime-number 0 0)))
(format t "delay base is ~a samples" (* delay *sound-srate*))
;; With stereo signals the left channel uses the 1st, 3rd, 5th, ...
;; and the right channel uses the 2nd, 4th, 6th ... etc prime numbers.
(defun tapped-left (snd)
(let ((tap (s-rest)))
(dotimes (n diff)
;; (format t "left prime ~a~%" (prime-number n 0))
(setf tap (sum tap (tapped-delay snd (* delay (prime-number n 0))))))
(mult (/ 1.0 (1+ diff)) ; 1 / (snd + number-of-taps)
(sum snd (extract-abs 0.0 (get-duration 1.0) tap)))))
(defun tapped-right (snd)
(let ((tap (s-rest)))
(dotimes (n diff)
;; (format t "right prime ~a~%" (prime-number n 1))
(setf tap (sum tap (tapped-delay snd (* delay (prime-number n 1))))))
(mult (/ 1.0 (1+ diff)) ; 1 / (snd + number-of-taps)
(sum snd (extract-abs 0.0 (get-duration 1.0) tap)))))
(defun early-reflections (snd)
(if (arrayp snd)
(vector (tapped-left (aref snd 0))
(tapped-right (aref snd 1)))
(mult 0.5 (sum (tapped-left snd)
(tapped-right snd)))))
(early-reflections s)