[Sc-devel] FSinOsc amplitude fix

kernel kernel at audiospillage.com
Wed Jun 11 13:23:52 PDT 2008


Hi all, I found a fix for the problem where the amplitude of FSinOsc  
varies with frequency.  I've implemented this in SC and pasted the  
UGen code below in case anyone wants to try it out or comment.  There  
is a slight increase in CPU usage.  The frequency is updated only once  
per block so it works best with smaller block sizes (same for original  
FSinOsc).  Using it for FM can be interesting.

kernel

struct FSinOsc : public Unit
{
	double m_b1, m_y1, m_y2, m_freq, m_phase;
};

void FSinOsc_Ctor(FSinOsc *unit)
{
	SETCALC(FSinOsc_next);
	unit->m_freq = ZIN0(0);
	float iphase = ZIN0(1);
	float w = unit->m_freq * unit->mRate->mRadiansPerSample;
	unit->m_b1 = 2. * cos(w);
	unit->m_y1 = sin(iphase);
	unit->m_y2 = sin(iphase - w);
	unit->m_phase = iphase;
	ZOUT0(0) = unit->m_y1;
}

void FSinOsc_next(FSinOsc *unit, int inNumSamples)
{
	float *out = ZOUT(0);
	double freq = ZIN0(0);
	
	double phase = unit->m_phase;
	double b1, y0, y1, y2;
	
	if (freq != unit->m_freq) {
		unit->m_freq = freq;
		double w = freq * unit->mRate->mRadiansPerSample;
		b1 = 2.0 * cos(w);
		y1 = sin(phase);
		y2 = sin(phase - w);
	} else {
		b1 = unit->m_b1;
		y1 = unit->m_y1;
		y2 = unit->m_y2;
	}
	
	// becuase loop is unrolled update phase separately
	// by accumulating total phase per block
	double frqScale = twopi * unit->mRate->mSampleDur;
	double freq2 = (freq * frqScale) * inNumSamples;
	phase += freq2;
	fmod(phase, twopi);
	
	//Print("y %g %g  b1 %g\n", y1, y2, b1);
	//Print("%d %d\n", unit->mRate->mFilterLoops, unit->mRate- 
 >mFilterRemain);
	LOOP(unit->mRate->mFilterLoops,
		ZXP(out) = y0 = b1 * y1 - y2;
		ZXP(out) = y2 = b1 * y0 - y1;
		ZXP(out) = y1 = b1 * y2 - y0;
	);
	LOOP(unit->mRate->mFilterRemain,
		ZXP(out) = y0 = b1 * y1 - y2;
		y2 = y1;
		y1 = y0;
	);
	//Print("y %g %g  b1 %g\n", y1, y2, b1);
	unit->m_y1 = y1;
	unit->m_y2 = y2;
	unit->m_b1 = b1;
	unit->m_phase = phase;
}




More information about the Sc-devel mailing list