@@ -114,3 +114,68 @@ TEST_F(TestBiquadCascade, reset_clears_state)
114114 filters::passive::Biquad<float >::LowPass (fc, fs, Q).b0 ,
115115 1e-5f );
116116}
117+
118+ TEST_F (TestBiquadCascade, bandpass_attenuates_dc)
119+ {
120+ filters::passive::Biquad<float > bq{ filters::passive::Biquad<float >::BandPass (fc, fs, Q) };
121+
122+ for (int i = 0 ; i < 500 ; ++i)
123+ bq.Filter (1 .0f );
124+
125+ EXPECT_NEAR (bq.Filter (1 .0f ), 0 .0f , 1e-4f );
126+ }
127+
128+ TEST_F (TestBiquadCascade, notch_rejects_center_freq)
129+ {
130+ filters::passive::Biquad<float > bq{ filters::passive::Biquad<float >::Notch (fc, fs, Q) };
131+ const float w{ 2 .0f * std::numbers::pi_v<float > * fc / fs };
132+ constexpr int settleSamples{ 500 };
133+ constexpr int measureSamples{ 100 };
134+
135+ for (int i = 0 ; i < settleSamples; ++i)
136+ bq.Filter (std::sin (static_cast <float >(i) * w));
137+
138+ float maxAmp{ 0 .0f };
139+ for (int i = settleSamples; i < settleSamples + measureSamples; ++i)
140+ {
141+ const float y{ bq.Filter (std::sin (static_cast <float >(i) * w)) };
142+ const float absY{ y < 0 .0f ? -y : y };
143+ if (absY > maxAmp)
144+ maxAmp = absY;
145+ }
146+
147+ EXPECT_LT (maxAmp, 0 .01f );
148+ }
149+
150+ TEST_F (TestBiquadCascade, notch_passes_dc)
151+ {
152+ filters::passive::Biquad<float > bq{ filters::passive::Biquad<float >::Notch (fc, fs, Q) };
153+
154+ for (int i = 0 ; i < 500 ; ++i)
155+ bq.Filter (1 .0f );
156+
157+ EXPECT_NEAR (bq.Filter (1 .0f ), 1 .0f , 1e-3f );
158+ }
159+
160+ TEST_F (TestBiquadCascade, peaking_boosts_center_freq)
161+ {
162+ constexpr float gainDb{ 6 .0f };
163+ filters::passive::Biquad<float > bq{ filters::passive::Biquad<float >::Peaking (fc, fs, Q, gainDb) };
164+ const float w{ 2 .0f * std::numbers::pi_v<float > * fc / fs };
165+ constexpr int settleSamples{ 500 };
166+ constexpr int measureSamples{ 100 };
167+
168+ for (int i = 0 ; i < settleSamples; ++i)
169+ bq.Filter (std::sin (static_cast <float >(i) * w));
170+
171+ float maxAmp{ 0 .0f };
172+ for (int i = settleSamples; i < settleSamples + measureSamples; ++i)
173+ {
174+ const float y{ bq.Filter (std::sin (static_cast <float >(i) * w)) };
175+ const float absY{ y < 0 .0f ? -y : y };
176+ if (absY > maxAmp)
177+ maxAmp = absY;
178+ }
179+
180+ EXPECT_NEAR (maxAmp, std::pow (10 .0f , gainDb / 20 .0f ), 0 .05f );
181+ }
0 commit comments