Example #1
0
void MLProcBiquad::calcCoeffs(const int frames) 
{
	static MLSymbol modeSym("mode");
	int mode = (int)getParam(modeSym);
	const MLSignal& frequency = getInput(2);
	const MLSignal& q = getInput(3);
	int coeffFrames;
	
	float twoPiOverSr = kMLTwoPi*getContextInvSampleRate();		

	bool paramSignalsAreConstant = frequency.isConstant() && q.isConstant();
	
	if (paramSignalsAreConstant)
	{
		coeffFrames = 1;
	}
	else
	{
		coeffFrames = frames;
	}
	
	// set proper constant state for coefficient signals
	mA0.setConstant(paramSignalsAreConstant);
	mA1.setConstant(paramSignalsAreConstant);
	mA2.setConstant(paramSignalsAreConstant);
	mB1.setConstant(paramSignalsAreConstant);
	mB2.setConstant(paramSignalsAreConstant);
	
	float a0, a1, a2, b0, b1, b2;
	float qm1, omega, alpha, sinOmega, cosOmega;
	float highLimit = getContextSampleRate() * 0.33f;
				
	// generate coefficient signals
	// TODO SSE
	for(int n=0; n<coeffFrames; ++n)
	{
		qm1 = 1.f/(q[n] + 0.05f);
		omega = clamp(frequency[n], kLowFrequencyLimit, highLimit) * twoPiOverSr;
		sinOmega = fsin1(omega);
		cosOmega = fcos1(omega);
		alpha = sinOmega * 0.5f * qm1;
		b0 = 1.f/(1.f + alpha);
				
		switch (mode) 
		{
		default:
		case kLowpass:
			a0 = ((1.f - cosOmega) * 0.5f) * b0;
			a1 = (1.f - cosOmega);
			a2 = a0;
			b1 = (-2.f * cosOmega);
			b2 = (1.f - alpha);		
			break;
				
		case kHighpass:		
			a0 = ((1.f + cosOmega) * 0.5f);
			a1 = -(1.f + cosOmega);
			a2 = a0;
			b1 = (-2.f * cosOmega);
			b2 = (1.f - alpha);
			break;
				
		case kBandpass:
			a0 = alpha;
			a1 = 0.f;
			a2 = -alpha;
			b1 = -2.f * cosOmega;
			b2 = (1.f - alpha);
			break;
			
		case kNotch:
			a0 = 1;
			a1 = -2.f * cosOmega;
			a2 = 1;
			b1 = -2.f * cosOmega;
			b2 = (1.f - alpha);
			break;
		}
						
		mA0[n] = a0*b0;
		mA1[n] = a1*b0;
		mA2[n] = a2*b0;
		mB1[n] = b1*b0;
		mB2[n] = b2*b0;
	}
}
Example #2
0
void MLProcRate::process(const int samples)
{	
	const MLSignal& x = getInput(1);
	const MLSignal& ratioSig = getInput(2);
	MLSignal& y = getOutput(1);
	const float isr = getContextInvSampleRate();
	const float kFeedback = isr*10.f; 
	
	// allow ratio change once per buffer
	float rIn = ratioSig[samples - 1];
	if (rIn != mFloatRatio)
	{	
		mCorrectedRatio = correctRatio(rIn);
		mFloatRatio = rIn;
	}
		
	// if input phasor is off, reset and return.
	if(x[0] < 0.f) 
	{
		mOmega = 0.f;
		y.fill(-0.0001f);
		return;
	}
	
	if(mCorrectedRatio)
	{
		// run the PLL, correcting the output phasor to the input phasor and ratio.
		float r = mCorrectedRatio.getFloat();
		float rInv = 1.0f/r;
		float numerator = mCorrectedRatio.top;			
		float numeratorInv = 1.0f/numerator;
		float error;
		for (int n=0; n<samples; ++n)
		{
			float px = x[n];
			float dxdt = px - mx1;
			mx1 = px;
			float dydt = ml::max(dxdt*r, 0.f);
			float dxy = px - mOmega*rInv;
			
			// get modOffset, such that phase difference is 0 at each integer value of modOffset
			float modOffset = dxy*numerator;
			
			// get error term, valid at any phase difference.
			error = roundf(modOffset) - modOffset;
			
			// convert back to absolute phase difference
			error *= numeratorInv;
			
			// feedback = negative error * time constant
			dydt -= kFeedback*error;
			
			// don't ever run clock backwards.
			dydt = ml::max(dydt, 0.f);
			
			// wrap phasor
			mOmega += dydt;
			if(mOmega >= 1.0f)
			{
				mOmega -= 1.0f;
			}		
						
			y[n] = mOmega;
		}
	}
	else
	{
		// don't correct the phase, just run phasor at float ratio of input rate.
		for (int n=0; n<samples; ++n)
		{
			float px = x[n];
			float dxdt = px - mx1;
			mx1 = px;
			float dydt = ml::max(dxdt*mFloatRatio, 0.f);
			
			// wrap phasor
			mOmega += dydt;
			if(mOmega >= 1.0f)
			{
				mOmega -= 1.0f;
			}		
			
			y[n] = mOmega;
		}
	}
}