On a mac the Accelerate framework delivers a lot of very useful DSP functions. Most of them are pretty straight forward to use, some are a little complicated. One of those is vDSP_deq22 / vDSP_deq22D which implements a vectorized 2 pole 2 zero filter (biquad).
Because of the recursive structure of a biquad filter, the input and output vectors must both be two elements longer than the actual number of samples that you want to filter. The first two elements of the input and output vectors must be filled with the last two values from the last calculation. The new input values then start from index 3. After applying the biquad, the output values start from index 3 of the output vector – it’s a common mistake to use the output values starting from index 0!
Below is a little code example, which is the perform routine of a max external that implements a simple biquad filter. Coefficient calculation is not included.
void myObj_perform64(t_myObj *x, t_object *dsp64, double **ins, long numins,
double **outs, long numouts, long sampleframes, long flags, void *userparam)
t_double *in= ins;
t_double *out= outs;
int vs = sampleframes;
double *infilt = x->infilt; // filter input array, containing sampleframes+2 elements
double *outfilt = x->outfilt; // filter output array, containing sampleframes+2 elements
// copy last two input values from last vector
infilt = infilt[vs];
infilt = infilt[vs+1];
// copy audio in vector to filter input starting at 3rd index
memcpy(infilt+2, in, vs*sizeof(double));
// copy last two output values from last vector
outfilt = outfilt[vs];
outfilt = outfilt[vs+1];
// do the actual filtering
vDSP_deq22D(infilt, 1, x->coeffs, outfilt, 1, vs);
// copy filter output starting from 3rd index to audio out vector
memcpy(out, outfilt+2, sizeof(double)*vs);