[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