/*
Transposed Direct Form II Biquad
Based on C++ code by Nigel Redmon:
http://www.earlevel.com/main/2012/11/26/biquad-c-source-code/
OUTPUT
aout - filtered signal
INPUT
asig - input signal
ifilter_type - filter type:
0 - Low Pass
1 - High Pass
2 - Band Pass
3 - Notch
4 - Peaking
5 - Low Shelf
6 - High Shelf
acutoff - cutoff frequency
aQ - Q value
again - gain (used by peaking, low shelf, and high shelf)
*/
opcode tdf2, a, aiaaa
asig, ifilter_type, acutoff, aQ, again xin
/* Memory */
kz1 init 0
kz2 init 0
klast_Fc init 0
klast_Q init 0
klast_gain init 0
ka0 init 0
ka1 init 0
ka2 init 0
kb1 init 0
kb2 init 0
aout init 0
kndx = 0
while (kndx < ksmps) do
kcut = acutoff[kndx]
kQ = aQ[kndx]
kgain = again[kndx]
if(kcut != klast_Fc || kQ != klast_Q || kgain != klast_gain) then
kK = tan($M_PI * (kcut / sr))
kV = pow(10, abs(kgain) / 20.0)
kK2 = kK * kK
if (ifilter_type == 0) then ;; LPF
knorm = 1 / (1 + kK / kQ + kK2)
ka0 = kK2 * knorm
ka1 = 2 * ka0
ka2 = ka0
kb1 = 2 * (kK2 - 1) * knorm
kb2 = (1 - kK / kQ + kK2) * knorm
elseif (ifilter_type == 1) then ;; HPF
knorm = 1 / (1 + kK / kQ + kK2)
ka0 = 1 * knorm
ka1 = -2 * ka0
ka2 = ka0
kb1 = 2 * (kK2 - 1) * knorm
kb2 = (1 - kK / kQ + kK2) * knorm
elseif (ifilter_type == 2) then ;; BPF
knorm = 1 / (1 + kK / kQ + kK2)
ka0 = kK / kQ * knorm
ka1 = 0
ka2 = -ka0
kb1 = 2 * (kK2 - 1) * knorm
kb2 = (1 - kK / kQ + kK2) * knorm
elseif (ifilter_type == 3) then ;; Notch
knorm = 1 / (1 + kK / kQ + kK2)
ka0 = (1 + kK2) * knorm
ka1 = 2 * (kK2 - 1) * knorm
ka2 = ka0
kb1 = ka1
kb2 = (1 - kK / kQ + kK2) * knorm
elseif (ifilter_type == 4) then ;; Peaking
if (kgain >= 0) then ;; boost
knorm = 1 / (1 + kK/kQ + kK2);
ka0 = (1 + kV/kQ * kK + kK2) * knorm;
ka1 = 2 * (kK2 - 1) * knorm;
ka2 = (1 - kV/kQ * kK + kK2) * knorm;
kb1 = ka1;
kb2 = (1 - 1/kQ * kK + kK2) * knorm;
else ;; cut
knorm = 1 / (1 + kV/kQ * kK + kK2)
ka0 = (1 + kK/kQ + kK2) * knorm
ka1 = 2 * (kK2 - 1) * knorm
ka2 = (1 - kK/kQ + kK2) * knorm
kb1 = ka1
kb2 = (1 - kV/kQ * kK + kK2) * knorm
endif
elseif (ifilter_type == 5) then ;; Low Shelf
if (kgain >= 0) then ;; boost
knorm = 1 / (1 + sqrt(2) * kK + kK2)
ka0 = (1 + sqrt(2*kV) * kK + kV * kK2) * knorm
ka1 = 2 * (kV * kK2 - 1) * knorm
ka2 = (1 - sqrt(2*kV) * kK + kV * kK2) * knorm
kb1 = 2 * (kK2 - 1) * knorm
kb2 = (1 - sqrt(2) * kK + kK2) * knorm
else ;; cut
knorm = 1 / (1 + sqrt(2*kV) * kK + kV * kK2)
ka0 = (1 + sqrt(2) * kK + kK2) * knorm
ka1 = 2 * (kK2 - 1) * knorm
ka2 = (1 - sqrt(2) * kK + kK2) * knorm
kb1 = 2 * (kV * kK2 - 1) * knorm
kb2 = (1 - sqrt(2*kV) * kK + kV * kK2) * knorm
endif
elseif (ifilter_type == 6) then ;; High Shelf
if (kgain >= 0) then ;; boost
knorm = 1 / (1 + sqrt(2) * kK + kK2)
ka0 = (kV + sqrt(2*kV) * kK + kK2) * knorm
ka1 = 2 * (kK2 - kV) * knorm
ka2 = (kV - sqrt(2*kV) * kK + kK2) * knorm
kb1 = 2 * (kK2 - 1) * knorm
kb2 = (1 - sqrt(2) * kK + kK2) * knorm
else ;; cut
knorm = 1 / (kV + sqrt(2*kV) * kK + kK2)
ka0 = (1 + sqrt(2) * kK + kK2) * knorm
ka1 = 2 * (kK2 - 1) * knorm
ka2 = (1 - sqrt(2) * kK + kK2) * knorm
kb1 = 2 * (kK2 - kV) * knorm
kb2 = (kV - sqrt(2*kV) * kK + kK2) * knorm
endif
endif
endif
kin = asig[kndx]
/* TDF2 Biquad Calculation */
kout = kin * ka0 + kz1
kz1 = kin * ka1 + kz2 - kb1 * kout
kz2 = kin * ka2 - kb2 * kout
/* Output, state saving for next pass */
aout[kndx] = kout
klast_Fc = kcut
klast_Q = kQ
kndx += 1
od
xout aout
endop