packages feed

csound-expression-typed-0.1.0.0: data/opcodes/tdf2.udo


/* 
   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