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 FloatToDouble(double* dest, const float* src, unsigned length) { #ifdef __APPLE__ vDSP_vspdp(src, 1, dest, 1, length); #else // Otherwise do it manually unsigned i; const unsigned end = 4 * (length / 4); for (i = 0; i < end; i+=4) { dest[i] = (double)(src[i]); dest[i + 1] = (double)(src[i + 1]); dest[i + 2] = (double)(src[i + 2]); dest[i + 3] = (double)(src[i + 3]); } for (i = end; i < length; ++i) { dest[i] = (double)(src[i]); } #endif return NOERR; }
void AVFAudioEqualizer::RunFilter(const Float32 *inSourceP, Float32 *inDestP, UInt32 inFramesToProcess, UInt32 channel) { if (mEnabled && !mEQBands.empty()) { if (inFramesToProcess + 2 > mEQBufferSize) { mEQBufferSize = inFramesToProcess + 2; mEQBufferA.free(); mEQBufferA.alloc(mEQBufferSize); mEQBufferB.free(); mEQBufferB.alloc(mEQBufferSize); } // start processing with A buffer first bool srcA = true; // The first two elements are copied each time we call a band to process // float* cast is needed for Xcode 4.5 vDSP_vspdp((float*)inSourceP, 1, mEQBufferA.get() + 2, 1, inFramesToProcess); // Run each band in sequence for (AVFEQBandIterator iter = mEQBands.begin(); iter != mEQBands.end(); iter++) { if (iter->second) { if (srcA) { iter->second->ApplyFilter(mEQBufferA, mEQBufferB, inFramesToProcess, channel); } else { iter->second->ApplyFilter(mEQBufferB, mEQBufferA, inFramesToProcess, channel); } srcA = !srcA; } } // Copy back to dest stream vDSP_vdpsp((srcA ? mEQBufferA : mEQBufferB)+2, 1, inDestP, 1, inFramesToProcess); } }