void AVFEqualizerBand::ApplyFilter(double *inSource, double *inDest, int frameCount, int channel) { if (mBypass && mEQ->GetSampleRate() > 0.0) { // Have a sample rate now, can recalculate RecalculateParams(); } if (mBypass || channel < 0) { return; } // We may have more channels now than when we were initialized if (channel > mChannels) { mChannels = mEQ->GetChannelCount(); SetChannelCount(mChannels); } if (mChannels > 0 && mHistory != NULL) { // copy source and dest history inSource[1] = mHistory[channel].x1; inSource[0] = mHistory[channel].x2; inDest[1] = mHistory[channel].y1; inDest[0] = mHistory[channel].y2; vDSP_deq22D(inSource, 1, mCoefficients, inDest, 1, frameCount); // update history mHistory[channel].x1 = inSource[frameCount+1]; mHistory[channel].x2 = inSource[frameCount]; mHistory[channel].y1 = inDest[frameCount+1]; mHistory[channel].y2 = inDest[frameCount]; } }
t_int *myObj_perform(t_int *w) { t_myObj *x = (t_myObj*)(w[1]); float *in= (float *)(w[2]); float *out= (float *)(w[3]); int vs = w[4]; int k; double *outfilt = x->outfilt; double *infilt = x->infilt; double *xms = x->xms; double *yms = x->yms; int poles2 = x->poles >> 1; //each biquad can calc 2 poles (and 2 zeros) if(!x->inputconnected || x->b_ob.z_disabled) return w+5; // copy input and use outfilt for that (this is so the recursion works) /* for(i=0; i<vs; i++) { outfilt[i+2] = in[i]; }*/ vDSP_vspdp(in, 1, outfilt+2, 1, vs); for(k=0; k<poles2; k++) { // restore last two input samps infilt[0] = xms[k*2]; infilt[1] = xms[k*2+1]; // copy from outfilt to infilt (recursion) memcpy(infilt+2, outfilt+2, vs*sizeof(double)); // restore last two output samps outfilt[0] = yms[k*2]; outfilt[1] = yms[k*2+1]; // do the biquad! vDSP_deq22D(infilt, 1, x->coeffs+(k*5), outfilt, 1, vs); // save last two input & output samples for next vector xms[k*2] = infilt[vs]; xms[k*2+1] = infilt[vs+1]; yms[k*2] = outfilt[vs]; yms[k*2+1] = outfilt[vs+1]; } // TODO: check for denormals??? /* for(i=0; i<vs; i++) { out[i] = outfilt[i+2]; }*/ vDSP_vdpsp(outfilt+2, 1, out, 1, vs); return w+5; }
Error_t BiquadFilterProcessD(BiquadFilterD *filter, double *outBuffer, const double *inBuffer, unsigned n_samples) { #ifdef __APPLE__ // Use accelerate if we have it double coeffs[5] = { filter->b[0], filter->b[1], filter->b[2], filter->a[0], filter->a[1] }; double temp_in[n_samples + 2]; double temp_out[n_samples + 2]; // Put filter overlaps into beginning of input and output vectors cblas_dcopy(2, filter->x, 1, temp_in, 1); cblas_dcopy(2, filter->y, 1, temp_out, 1); cblas_dcopy(n_samples, inBuffer, 1, (temp_in + 2), 1); // Process vDSP_deq22D(temp_in, 1, coeffs, temp_out, 1, n_samples); // Write overlaps to filter x and y arrays cblas_dcopy(2, (temp_in + n_samples), 1, filter->x, 1); cblas_dcopy(2, (temp_out + n_samples), 1, filter->y, 1); // Write output cblas_dcopy(n_samples, (temp_out + 2), 1, outBuffer, 1); #else double buffer[n_samples]; for (unsigned buffer_idx = 0; buffer_idx < n_samples; ++buffer_idx) { // DF-II Implementation buffer[buffer_idx] = filter->b[0] * inBuffer[buffer_idx] + filter->w[0]; filter->w[0] = filter->b[1] * inBuffer[buffer_idx] - filter->a[0] * \ buffer[buffer_idx] + filter->w[1]; filter->w[1] = filter->b[2] * inBuffer[buffer_idx] - filter->a[1] * \ buffer[buffer_idx]; } // Write output CopyBufferD(outBuffer, buffer, n_samples); #endif return NOERR; }
void Biquad::processSliceFast(double* sourceP, double* destP, double* coefficientsP, size_t framesToProcess) { // Use double-precision for filter stability vDSP_deq22D(sourceP, 1, coefficientsP, destP, 1, framesToProcess); // Save history. Note that sourceP and destP reference m_inputBuffer and m_outputBuffer respectively. // These buffers are allocated (in the constructor) with space for two extra samples so it's OK to access // array values two beyond framesToProcess. sourceP[0] = sourceP[framesToProcess - 2 + 2]; sourceP[1] = sourceP[framesToProcess - 1 + 2]; destP[0] = destP[framesToProcess - 2 + 2]; destP[1] = destP[framesToProcess - 1 + 2]; }
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[0]; t_double *out= outs[0]; int vs = sampleframes; int k; double *outfilt = x->outfilt; double *infilt = x->infilt; double *xms = x->xms; double *yms = x->yms; int poles2 = x->poles >> 1; //each biquad can calc 2 poles (and 2 zeros) if(!x->inputconnected || x->b_ob.z_disabled) return; // copy input and use outfilt for that (this is so the recursion works) memcpy(outfilt+2, in, vs*sizeof(double)); // dest, source, len for(k=0; k<poles2; k++) { // restore last two input samps infilt[0] = xms[k*2]; infilt[1] = xms[k*2+1]; // copy from outfilt to infilt (recursion) memcpy(infilt+2, outfilt+2, vs*sizeof(double)); // restore last two output samps outfilt[0] = yms[k*2]; outfilt[1] = yms[k*2+1]; // do the biquad! vDSP_deq22D(infilt, 1, x->coeffs+(k*5), outfilt, 1, vs); // save last two input & output samples for next vector xms[k*2] = infilt[vs]; xms[k*2+1] = infilt[vs+1]; yms[k*2] = outfilt[vs]; yms[k*2+1] = outfilt[vs+1]; } // TODO: check for denormals??? memcpy(out, outfilt+2, sizeof(double)*vs); // old version /* for(i=0; i<vs; i++) { input = *in++; output = 0; for(k=0; k<poles2; k++) { k2 = k<<1; k3 = k*3; //output = input * a[k3] + xx[k2]*a[k3+1] + xx[k2+1]*a[k3+2] //+ yy[k2]*b[k3+1] + yy[k2+1]*b[k3+2]; // biquad ffw = input * a[k3] + xx[k2]*a[k3+1] + xx[k2+1]*a[k3+2]; // zeros fb = yy[k2]*b[k3+1] + yy[k2+1]*b[k3+2]; // poles FIX_DENORM_DOUBLE(fb); output = ffw + fb; xx[k2+1] = xx[k2]; xx[k2] = input; yy[k2+1] = yy[k2]; yy[k2] = output; input = output; } *out++ = output; }*/ }