Digital Music Programming II: Biquad filter




A biquad filter is a linear filter, defined by the following flowgraph or difference equation:

The name biquad is an abbreviation of the word bi-quadratic because the transfer-function (which can be derived from the difference equation or flowgraph) contains two quadratic functions:

Here is an example set of values for the filter coefficients:

       a0 =  1
       a1 =  0
       a2 = -1
       b1 =  0.1
       b2 =  0.9
       

These values will generate the following z-plane magnitude plot:

Examing the unit circle in the above z-plane figure, you can determine the spectrum of the filter:


Source Code Example Usage
mybiquad.c


#include "ext.h"
#include "z_dsp.h"

typedef struct {
   t_pxobject msp_data;
   float      lastinput, lastinput2;
   float      lastoutput, lastoutput2;
   float      a0, a1, a2, b1, b2;
} MyObject;

void* object_data;

void   main            (void);
void*  create_object   (void);
void   MessageDSP      (MyObject* mo, t_signal** signal, short* count);
void   MessageClear    (MyObject* mo);
void   InputA0         (MyObject* mo, float value);
void   InputA1         (MyObject* mo, float value);
void   InputA2         (MyObject* mo, float value);
void   InputB1         (MyObject* mo, float value);
void   InputB2         (MyObject* mo, float value);
t_int* Perform         (t_int *parameters);

void main(void) {
   setup((t_messlist**)&object_data, (method)create_object, (method)dsp_free,
         (short)sizeof(MyObject), NULL, A_NOTHING);
   addftx((method)InputB2, 1); addftx((method)InputB1, 2);
   addftx((method)InputA2, 3); addftx((method)InputA1, 4);
   addftx((method)InputA0, 5);
   addmess((method)MessageDSP,   "dsp",   A_CANT, A_NOTHING);
   addmess((method)MessageClear, "clear", A_NOTHING);
   dsp_initclass();
}

void* create_object(void) {
   MyObject *mo = (MyObject*)newobject(object_data);
   dsp_setup((t_pxobject*)mo, 1);
   outlet_new((t_pxobject*)mo, "signal");
   floatin(mo, 1); floatin(mo, 2); floatin(mo, 3); floatin(mo, 4); floatin(mo, 5);
   mo->a0 = 0.0; mo->a1 = 0.0; mo->a2 = 0.0; mo->b1 = 0.0; mo->b2 = 0.0;
   MessageClear(mo);
   return mo;
}

void InputA0 (MyObject* mo, float value) { mo->a0 = value; }
void InputA1 (MyObject* mo, float value) { mo->a1 = value; }
void InputA2 (MyObject* mo, float value) { mo->a2 = value; }
void InputB1 (MyObject* mo, float value) { mo->b1 = value; }
void InputB2 (MyObject* mo, float value) { mo->b2 = value; }

void MessageDSP(MyObject* mo, t_signal** signal, short* count) {
   #pragma unused(count)
   dsp_add(Perform, 5, 5, mo, signal[0]->s_vec, signal[1]->s_vec, signal[0]->s_n);
}

void MessageClear(MyObject *mo) {
   mo->lastinput = mo->lastinput2 = mo->lastoutput = mo->lastoutput2 = 0.0;
}

t_int* Perform(t_int *parameters) {
   long      pcount = (long)     (parameters[1]);
   MyObject *mo     = (MyObject*)(parameters[2]);
   t_float  *input  = (t_float*) (parameters[3]);
   t_float  *output = (t_float*) (parameters[4]);
   long      count  = (long)     (parameters[5]);
   long      i;

   for (i=0; i<count; i++) {
      output[i] = mo->a0 * input[i] + mo->a1 * mo->lastinput +
                  mo->a2 * mo->lastinput2 - mo->b1 * mo->lastoutput -
                  mo->b2 * mo->lastoutput2;
      mo->lastinput2  = mo->lastinput;
      mo->lastoutput2 = mo->lastoutput;
      mo->lastinput   = input[i];
      mo->lastoutput  = output[i];
   }

   return parameters+pcount+1;
}


Further Reading:


Exercises

  1. Compile the mybiquad~ filter and try it out. Try different values for the filter coefficients. Use whitenoise as an input to the filter program.

  2. Compare the output from the mybiquad~ filter to the MSP filter object biquad~ with the following patch:



  3. How can the biquad filter be used to immitate the dcblock filter?