;; type is LPF4, LPF2, BPF4, BPF2, HPF4, HPF2
;; rate is the minimum number of samples to allow between frq/res updates
(bind-func static moog_ladder
(lambda (type)
(let ((m_dK 0.0)
(m_dAlpha_0 1.0)
(m_dAlpha 0.0)
(m_dGamma 0.0)
(dSigma 0.0) (dU 0.0)
(m_dA 0.0) (m_dB 0.0) (m_dC 0.0) (m_dD 0.0) (m_dE 1.0)
(dlpf1 0.0) (dlpf2 0.0) (dlpf3 0.0) (dlpf4 0.0)
(lpf1 (va_onepole LPF1))
(lpf2 (va_onepole LPF1))
(lpf3 (va_onepole LPF1))
(lpf4 (va_onepole LPF1))
(lpf1output:SAMPLE* (lpf1.feedbackOutput))
(lpf2output:SAMPLE* (lpf2.feedbackOutput))
(lpf3output:SAMPLE* (lpf3.feedbackOutput))
(lpf4output:SAMPLE* (lpf4.feedbackOutput))
(lpf1alpha:SAMPLE* (lpf1.m_dAlpha))
(lpf2alpha:SAMPLE* (lpf2.m_dAlpha))
(lpf3alpha:SAMPLE* (lpf3.m_dAlpha))
(lpf4alpha:SAMPLE* (lpf4.m_dAlpha))
(lpf1beta:SAMPLE* (lpf1.m_dBeta))
(lpf2beta:SAMPLE* (lpf2.m_dBeta))
(lpf3beta:SAMPLE* (lpf3.m_dBeta))
(lpf4beta:SAMPLE* (lpf4.m_dBeta))
(feedback:SAMPLE 0.01)
(saturation:SAMPLE 1.0)
(T (/ 1.0 SRs))
(g:SAMPLE 0.0)
(G:SAMPLE 0.0)
(t2 (/ 2.0 T))
(halfT (/ T 2.0))
(oldfrq 0.0)
(oldQ 0.0))
(cond ((= type LPF4) (set! m_dA 0.0) (set! m_dB 0.0) (set! m_dC 0.0) (set! m_dD 0.0) (set! m_dE 1.0))
((= type LPF2) (set! m_dA 0.0) (set! m_dB 0.0) (set! m_dC 1.0) (set! m_dD 0.0) (set! m_dE 0.0))
((= type BPF4) (set! m_dA 0.0) (set! m_dB 0.0) (set! m_dC 4.0) (set! m_dD -8.0) (set! m_dE 4.0))
((= type BPF2) (set! m_dA 0.0) (set! m_dB 2.0) (set! m_dC -2.0) (set! m_dD 0.0) (set! m_dE 0.0))
((= type HPF4) (set! m_dA 1.0) (set! m_dB -4.0) (set! m_dC 6.0) (set! m_dD -4.0) (set! m_dE 1.0))
((= type HPF2) (set! m_dA 1.0) (set! m_dB -4.0) (set! m_dC 6.0) (set! m_dD -4.0) (set! m_dE 1.0))
(else ;; default to LPF4
(set! m_dA 0.0) (set! m_dB 0.0) (set! m_dC 0.0) (set! m_dD 0.0) (set! m_dE 1.0)))
(lambda (in:SAMPLE frq:SAMPLE Q:SAMPLE)
;; update Q
(if (or (<> oldQ Q) (<> oldfrq frq))
(begin (if (< frq 0.0) (set! frq (fabs frq)))
(if (< Q 0.0) (set! Q (fabs Q)))
(set! oldQ Q)
(set! oldfrq frq)
(set! m_dK (* 4.0 Q))
(set! oldfrq frq)
(set! m_dAlpha (* t2 (tan (* STWOPI frq halfT))))
(set! g (* halfT m_dAlpha))
(set! G (/ g (+ 1.0 g)))
(pset! lpf1alpha 0 G)
(pset! lpf2alpha 0 G)
(pset! lpf3alpha 0 G)
(pset! lpf4alpha 0 G)
(pset! lpf1beta 0 (* G G (/ G (+ 1.0 g))))
(pset! lpf2beta 0 (* G (/ G (+ 1.0 g))))
(pset! lpf3beta 0 (/ G (+ 1.0 g)))
(pset! lpf4beta 0 (/ 1.0 (+ 1.0 g)))
(set! m_dGamma (* G G G G))
(set! m_dAlpha_0 (/ 1.0 (+ 1.0 (* m_dK m_dGamma))))))
(set! dSigma (+ (pref lpf1output 0) (pref lpf2output 0) (pref lpf3output 0) (pref lpf4output 0)))
(set! in (* in (+ 1.0 m_dK)))
(set! dU (* (- in (* m_dK dSigma)) m_dAlpha_0))
(set! dU (tanh (* saturation dU)))
;; cascade filters
(set! dlpf1 (lpf1 dU feedback))
(set! dlpf2 (lpf2 dlpf1 feedback))
(set! dlpf3 (lpf3 dlpf2 feedback))
(set! dlpf4 (lpf4 dlpf3 feedback))
;; filter type
(+ (* m_dA dU) (* m_dB dlpf1) (* m_dC dlpf2) (* m_dD dlpf3) (* m_dE dlpf4))))))