#pragma once #include enum class LFODest { FilterCutoff = 0, OSC1Freq, OSC2Freq, BothOsc }; enum class LFOShape { Sine = 0, Triangle, Saw, Square }; class LFO { public: void prepare(double sr) { sampleRate = sr; } void setParameters(float rate, float depth, LFOShape s, LFODest d) { lfoRate = rate; lfoDepth = depth; shape = s; dest = d; } float getNextSample() { float twoPi = 6.2831853f; phase += lfoRate / static_cast(sampleRate); if (phase >= 1.0f) phase -= 1.0f; float out = 0.0f; float p = phase; switch (shape) { case LFOShape::Sine: out = std::sin(p * twoPi); break; case LFOShape::Triangle: out = 2.0f * std::abs(2.0f * (p - 0.5f)) - 1.0f; break; case LFOShape::Saw: out = 2.0f * p - 1.0f; break; case LFOShape::Square: out = p < 0.5f ? 1.0f : -1.0f; break; } return out * lfoDepth; } LFODest getDest() const { return dest; } void reset() { phase = 0.0f; } private: double sampleRate = 44100.0; float phase = 0.0f; float lfoRate = 2.0f; float lfoDepth = 0.0f; LFOShape shape = LFOShape::Sine; LFODest dest = LFODest::FilterCutoff; };