TTErr TTBalance::processAudio(TTAudioSignalArrayPtr inputs, TTAudioSignalArrayPtr outputs) { TTAudioSignal& in = inputs->getSignal(0); TTAudioSignal& out = outputs->getSignal(0); TTUInt16 vs; TTSampleValue *inSampleA, *inSampleB, *outSample; TTFloat64 tempxA, absTempxA, tempxB, absTempxB, tempyA, tempyB; TTUInt16 channel; TTUInt16 numChannels; // Twice as many input channels are expected as output channels numChannels = TTAudioSignal::getNumChannels(in) / 2; if (TTAudioSignal::getNumChannels(out) < numChannels) numChannels = TTAudioSignal::getNumChannels(out); // This outside loop works through each channel one at a time for (channel=0; channel<numChannels; channel++) { // We first expect all channels of inputSignalA, then all channels of inputSignalB inSampleA = in.mSampleVectors[channel]; inSampleB = in.mSampleVectors[channel+numChannels]; outSample = out.mSampleVectors[channel]; vs = in.getVectorSizeAsInt(); // This inner loop works through each sample within the channel one at a time while (vs--) { tempxA = *inSampleA++; absTempxA = fabs(tempxA); tempxB = *inSampleB++; absTempxB = fabs(tempxB); // Lopass filter left and right signals tempyA = a0*absTempxA + a1*xm1A[channel] + a2*xm2A[channel] - b1*ym1A[channel] - b2*ym2A[channel]; TTZeroDenormal(tempyA); tempyB = a0*absTempxB + a1*xm1B[channel] + a2*xm2B[channel] - b1*ym1B[channel] - b2*ym2B[channel]; TTZeroDenormal(tempyB); // Scale left input to produce output, avoid dividing by zero if (tempyA) *outSample++ = tempxA * (tempyB/tempyA); else *outSample++ = 0.; // Update filter values xm2A[channel] = xm1A[channel]; xm1A[channel] = absTempxA; ym2A[channel] = ym1A[channel]; ym1A[channel] = tempyA; xm2B[channel] = xm1B[channel]; xm1B[channel] = absTempxB; ym2B[channel] = ym1B[channel]; ym1B[channel] = tempyB; } } return kTTErrNone; }
inline TTErr TTDCBlock::calculateValue(const TTFloat64& x, TTFloat64& y, TTPtrSizedInt channel) { y = x - mLastInput[channel] + (mLastOutput[channel] * 0.9997); TTZeroDenormal(y); mLastOutput[channel] = y; mLastInput[channel] = x; return kTTErrNone; }
inline TTErr TTLowpassTwoPole::calculateValue(const TTFloat64& x, TTFloat64& y, TTPtrSizedInt channel) { y = (mFeedback1[channel] * mCoefficientA) - (mFeedback2[channel] * mCoefficientB) + (x * mCoefficientC); TTZeroDenormal(y); mFeedback2[channel] = mFeedback1[channel]; mFeedback1[channel] = y; return kTTErrNone; }
inline TTErr TTHighpassButterworth1::calculateValue(const TTFloat64& x, TTFloat64& y, TTPtrSizedInt channel) { //y = TTAntiDenormal(mA0*x + mA1*mX1[channel] - mB1*mY1[channel]); //since mA1 = -mA0, we can simplyfiy to y = mA0*(x - mX1[channel]) - mB1*mY1[channel]; TTZeroDenormal(y); mX1[channel] = x; mY1[channel] = y; return kTTErrNone; }
inline TTErr TTHighpassButterworth2::calculateValue(const TTFloat64& x, TTFloat64& y, TTPtrSizedInt channel) { //y = TTAntiDenormal(mA0*x + mA1*mX1[channel] + mA2*mX2[channel] - mB1*mY1[channel] - mB2*mY2[channel]); // since mA0 = mA2, one can optimize to: y = mA0*(x + mX2[channel])+ mA1*mX1[channel] - mB1*mY1[channel] - mB2*mY2[channel]; TTZeroDenormal(y); mX2[channel] = mX1[channel]; mX1[channel] = x; mY2[channel] = mY1[channel]; mY1[channel] = y; return kTTErrNone; }
inline TTErr TTHighpassLinkwitzRiley2::calculateValue(const TTFloat64& x, TTFloat64& y, TTPtrSizedInt channel) { //y = TTAntiDenormal(mA0*x + mA1*mX1[channel] + mA2*mX2[channel] - mB1*mY1[channel] - mB2*mY2[channel]); //since mA2 = mA0, we write y = mA0* (x + mX2[channel]) + mA1*mX1[channel] - mB1*mY1[channel] - mB2*mY2[channel]; TTZeroDenormal(y); mX2[channel] = mX1[channel]; mX1[channel] = x; mY2[channel] = mY1[channel]; mY1[channel] = y; return kTTErrNone; }
void TTSvf::tick(TTSampleValue value, TTUInt16 channel) { // UNROLLED (oversampling) FOR LOOP FOR SPEED mNotch_output[channel] = value - mDamp * mBandpass_output[channel]; TTZeroDenormal(mNotch_output[channel]); mLowpass_output[channel] += TTAntiDenormal(mFrequency * mBandpass_output[channel]); mHighpass_output[channel] = mNotch_output[channel] - mLowpass_output[channel]; TTZeroDenormal(mHighpass_output[channel]); mBandpass_output[channel] = mFrequency * mHighpass_output[channel] + mBandpass_output[channel]; TTZeroDenormal(mBandpass_output[channel]); mNotch_output[channel] = value - mDamp * mBandpass_output[channel]; TTZeroDenormal(mNotch_output[channel]); mLowpass_output[channel] += TTAntiDenormal(mFrequency * mBandpass_output[channel]); mHighpass_output[channel] = mNotch_output[channel] - mLowpass_output[channel]; TTZeroDenormal(mHighpass_output[channel]); mBandpass_output[channel] = mFrequency * mHighpass_output[channel] + mBandpass_output[channel]; TTZeroDenormal(mBandpass_output[channel]); }
inline TTErr TTLowpassButterworth3::calculateValue(const TTFloat64& x, TTFloat64& y, TTPtrSizedInt channel) { //y = TTAntiDenormal(mA0*x + mA1*mX1[channel] + mA2*mX2[channel] + mA3*mX3[channel] - mB1*mY1[channel] - mB2*mY2[channel] -mB3*mY3[channel]); // since mA2 = mA1 and mA3 = mA0, we can write y = mA0*(x +mX3[channel]) + mA1*(mX1[channel] + mX2[channel]) - mB1*mY1[channel] - mB2*mY2[channel] -mB3*mY3[channel]; TTZeroDenormal(y); mX3[channel] = mX2[channel]; mX2[channel] = mX1[channel]; mX1[channel] = x; mY3[channel] = mY2[channel]; mY2[channel] = mY1[channel]; mY1[channel] = y; return kTTErrNone; }
inline TTErr TTHighpassLinkwitzRiley4::calculateValue(const TTFloat64& x, TTFloat64& y, TTPtrSizedInt channel) { //y = TTAntiDenormal(mA0*x + mA1*mX1[channel] + mA2*mX2[channel] + mA3*mX3[channel] + mA4*mX4[channel] - mB1*mY1[channel] - mB2*mY2[channel] -mB3*mY3[channel] - mB4*mY4[channel]); // since mA3 = mA1 and mA0 = mA4, we can simplyfy to y = mA0*(x + mX4[channel]) + mA1*( mX1[channel] + mX3[channel] ) + mA2*mX2[channel] - mB1*mY1[channel] - mB2*mY2[channel] -mB3*mY3[channel] - mB4*mY4[channel]; TTZeroDenormal(y); mX4[channel] = mX3[channel]; mX3[channel] = mX2[channel]; mX2[channel] = mX1[channel]; mX1[channel] = x; mY4[channel] = mY3[channel]; mY3[channel] = mY2[channel]; mY2[channel] = mY1[channel]; mY1[channel] = y; return kTTErrNone; }