#pragma once #include #include enum class FilterType { LowPass12 = 0, LowPass24, BandPass, HighPass, Notch, NumTypes }; class Filter { public: void prepare(double sr) { sampleRate = sr; reset(); } void reset() { for (int i = 0; i < 4; ++i) { stage[i] = 0.0f; } } void setCoefficients(float cutoff, float res, FilterType type) { cutoff = std::clamp(cutoff, 20.0f, static_cast(sampleRate * 0.49)); resonance = std::clamp(res, 0.0f, 1.0f); filterType = type; float g = std::tan(static_cast(pi) * cutoff / static_cast(sampleRate)); float k = 2.0f - 2.0f * resonance; float a1 = 1.0f / (1.0f + g * (g + k)); float a2 = g * a1; gCoeff = g; kCoeff = k; m0 = 0.0f; m1 = 0.0f; m2 = 0.0f; m3 = 0.0f; switch (filterType) { case FilterType::LowPass12: m0 = 0.0f; m1 = 0.0f; m2 = a2; m3 = 0.0f; break; case FilterType::LowPass24: m0 = 0.0f; m1 = 0.0f; m2 = 0.0f; m3 = a2 * a2; break; case FilterType::BandPass: m0 = 0.0f; m1 = a2; m2 = 0.0f; m3 = 0.0f; break; case FilterType::HighPass: m0 = 1.0f; m1 = -a1; m2 = -a2; m3 = 0.0f; break; case FilterType::Notch: m0 = 1.0f; m1 = -a1 * k; m2 = -a2; m3 = 0.0f; break; case FilterType::NumTypes: break; } } float process(float input) { float denom = 1.0f + kCoeff * gCoeff + gCoeff * gCoeff; float hp = (input - (kCoeff + gCoeff) * stage[0] - stage[1]) / denom; float bp = gCoeff * hp + stage[0]; float lp = gCoeff * bp + stage[1]; stage[0] = gCoeff * hp + bp; stage[1] = gCoeff * bp + lp; float hp2 = (lp - (kCoeff + gCoeff) * stage[2] - stage[3]) / denom; float bp2 = gCoeff * hp2 + stage[2]; float lp2 = gCoeff * bp2 + stage[3]; stage[2] = gCoeff * hp2 + bp2; stage[3] = gCoeff * bp2 + lp2; float output = 0.0f; switch (filterType) { case FilterType::LowPass12: output = lp; break; case FilterType::LowPass24: output = lp2; break; case FilterType::BandPass: output = bp; break; case FilterType::HighPass: output = hp; break; case FilterType::Notch: output = input - bp; break; case FilterType::NumTypes: output = input; break; } return output; } private: static constexpr float pi = 3.14159265358979323846f; double sampleRate = 44100.0; float stage[4] = {0.0f, 0.0f, 0.0f, 0.0f}; float gCoeff = 0.0f, kCoeff = 0.0f; float m0 = 0.0f, m1 = 0.0f, m2 = 0.0f, m3 = 0.0f; float resonance = 0.0f; FilterType filterType = FilterType::LowPass12; };