Round 1 findings and fixes, all previously uncommitted: - FXProcessor per-slot DSP history repair (HEAD does not compile without it) - SynthVoice::getModulationValue, editor control-lock guard - ExactCompare.h naming the deliberate exact float comparisons - KnobLookAndFeel replacing the never-installed SerumLookAndFeel - 55 first-party compiler warnings to 0 - AGENT.md renamed to AGENTS.md across Source/ - graft repository context graph and its hooks - JANITOR_TASKS.md and UI_UX_AUDIT.md records
59 lines
1.7 KiB
C++
59 lines
1.7 KiB
C++
#include "Phaser.h"
|
|
|
|
namespace serum
|
|
{
|
|
|
|
void PhaserUnit::prepare (double sampleRate, int)
|
|
{
|
|
sr = sampleRate;
|
|
reset();
|
|
}
|
|
|
|
void PhaserUnit::reset()
|
|
{
|
|
lfoPhase = 0.0;
|
|
for (int i = 0; i < 6; ++i)
|
|
{
|
|
xL[i] = xR[i] = yL[i] = yR[i] = 0.0f;
|
|
}
|
|
}
|
|
|
|
void PhaserUnit::process (float* l, float* r, int numSamples, const float p[4])
|
|
{
|
|
const double rate = 0.05 + p[0] * 2.0;
|
|
const float depth = 0.3f + p[1] * 0.6f;
|
|
const float feedback = p[2] * 0.7f;
|
|
const int stages = juce::jlimit (2, 6, 2 + (int) (p[3] * 4.0f + 0.5f));
|
|
|
|
for (int i = 0; i < numSamples; ++i)
|
|
{
|
|
lfoPhase += juce::MathConstants<double>::twoPi * rate / sr;
|
|
if (lfoPhase > juce::MathConstants<double>::twoPi) lfoPhase -= juce::MathConstants<double>::twoPi;
|
|
|
|
const float sweep = (float) (0.5 + 0.5 * std::sin (lfoPhase));
|
|
// The allpass cascade is stable only while the coefficient stays inside
|
|
// (-1, 1). depth can push 0.3 + depth * sweep above 1, which makes every
|
|
// stage self-excite, so the filter state runs away to inf/NaN and keeps
|
|
// producing it. Clamp at the point where the coefficient is computed.
|
|
const float a = juce::jlimit (0.0f, 0.99f, 0.3f + depth * sweep);
|
|
|
|
float outL = l[i] + yL[5] * feedback;
|
|
float outR = r[i] + yR[5] * feedback;
|
|
|
|
for (int s = 0; s < stages; ++s)
|
|
{
|
|
// y = a*x + x_prev - a*y_prev
|
|
const float inL = outL, inR = outR;
|
|
outL = a * inL + xL[s] - a * yL[s];
|
|
outR = a * inR + xR[s] - a * yR[s];
|
|
xL[s] = inL; xR[s] = inR;
|
|
yL[s] = outL; yR[s] = outR;
|
|
}
|
|
|
|
l[i] = outL;
|
|
r[i] = outR;
|
|
}
|
|
}
|
|
|
|
} // namespace serum
|