#include #include "asserts.h" #include "StateVariableFilter.h" #include "TestSignal.h" /** * Simple test - can we get output that looks kind of low pass */ template static void test1() { StateVariableFilterParams params; StateVariableFilterState state; params.setMode(StateVariableFilterParams::Mode::LowPass); params.setFreq(T(.05)); // TODO: make an even fraction params.setQ(T(.7)); T lastValue = -1; for (int i = 0; i < 5; ++i) { T output = StateVariableFilter::run(1, state, params); assert(output > lastValue); lastValue = output; } } /** * Measure freq response at some points */ template static void testLowpass() { const T fc = T(.001); const T q = T(1.0 / std::sqrt(2)); // butterworth StateVariableFilterParams params; StateVariableFilterState state; params.setMode(StateVariableFilterParams::Mode::LowPass); params.setFreq(fc); // TODO: make an even fraction params.setQ(q); double g = TestSignal::measureGain(fc / 4, [&state, ¶ms](T input) { return StateVariableFilter::run(input, state, params); }); g = AudioMath::db(g); assert(AudioMath::closeTo(g, 0, .05)); g = TestSignal::measureGain(fc, [&state, ¶ms](T input) { return StateVariableFilter::run(input, state, params); }); g = AudioMath::db(g); assert(AudioMath::closeTo(g, -3, .05)); double g2 = TestSignal::measureGain(fc * 4, [&state, ¶ms](T input) { return StateVariableFilter::run(input, state, params); }); g2 = AudioMath::db(g2); double g3 = TestSignal::measureGain(fc * 8, [&state, ¶ms](T input) { return StateVariableFilter::run(input, state, params); }); g3 = AudioMath::db(g3); assert(AudioMath::closeTo(g2 - g3, 12, 2)); } /** * Verify that passband gain tracks Q */ static void testBandpass() { const float fc = .01f; const float q = (1.0f / float(std::sqrt(2))); // butterworth StateVariableFilterParams params; StateVariableFilterState state; params.setMode(StateVariableFilterParams::Mode::BandPass); params.setFreq(fc); // TODO: make an even fraction params.setQ(q); double g0 = TestSignal::measureGain(fc, [&state, ¶ms](float input) { return StateVariableFilter::run(input, state, params); }); g0 = AudioMath::db(g0); for (int i = 2; i < 100; i *= 2) { const float q = float(i); params.setQ(q); double g = TestSignal::measureGain(fc, [&state, ¶ms](float input) { return StateVariableFilter::run(input, state, params); }); g = AudioMath::db(g); // printf("q = %f, gain db = %f qdb=%f\n", q, g, AudioMath::db(q)); assertClose(g, AudioMath::db(q), .5); } } template static void testSetBandwidth() { StateVariableFilterParams params; params.setNormalizedBandwidth(T(.1)); assertEQ(params.getNormalizedBandwidth(), T(.1)); params.setNormalizedBandwidth(T(.5)); assertEQ(params.getNormalizedBandwidth(), T(.5)); params.setQ(10); assertEQ(params.getNormalizedBandwidth(), T(.1)) } template static void test() { test1(); testLowpass(); testSetBandwidth(); } void testStateVariable() { test(); test(); testBandpass(); }