@@ -32,25 +32,48 @@ void HighPassFilterEffect::process(float & left, float & right, uint32_t sampleR
3232 return ;
3333 }
3434
35+ // Zero-Delay Feedback State Variable Filter (2nd order)
3536 const float freq = 20 .0f * std::pow (std::min (20000 .0f , sampleRate * 0 .49f ) / 20 .0f , m_cutoff);
36- const float f = std::min (1 .0f , 2 .0f * std::sin (std::numbers::pi_v<float > * freq / static_cast <float >(sampleRate)));
37- const float q = 0 .5f ;
38-
39- m_hpL = left - m_lpL - q * m_bpL;
40- m_bpL += f * m_hpL;
41- m_lpL += f * m_bpL;
42- left = m_hpL;
43-
44- m_hpR = right - m_lpR - q * m_bpR;
45- m_bpR += f * m_hpR;
46- m_lpR += f * m_bpR;
47- right = m_hpR;
37+ const double g = std::tan (std::numbers::pi * static_cast <double >(freq) / static_cast <double >(sampleRate));
38+ const double k = 1.0 ; // Q = 1.0 / k
39+ const double damping = 1.0 / (1.0 + g * (g + k));
40+
41+ // Left channel
42+ {
43+ const double hp = (static_cast <double >(left) - (g + k) * m_s1L - m_s2L) * damping;
44+ const double v1 = g * hp;
45+ const double v = v1 + m_s1L;
46+ m_s1L = v1 + v;
47+ const double v2 = g * v;
48+ const double lp = v2 + m_s2L;
49+ m_s2L = v2 + lp;
50+ left = static_cast <float >(hp);
51+ }
52+
53+ // Right channel
54+ {
55+ const double hp = (static_cast <double >(right) - (g + k) * m_s1R - m_s2R) * damping;
56+ const double v1 = g * hp;
57+ const double v = v1 + m_s1R;
58+ m_s1R = v1 + v;
59+ const double v2 = g * v;
60+ const double lp = v2 + m_s2R;
61+ m_s2R = v2 + lp;
62+ right = static_cast <float >(hp);
63+ }
64+
65+ // NaN protection
66+ if (std::isnan (left) || std::isnan (right)) {
67+ reset ();
68+ left = 0 .0f ;
69+ right = 0 .0f ;
70+ }
4871}
4972
5073void HighPassFilterEffect::reset ()
5174{
52- m_lpL = m_hpL = m_bpL = 0 . 0f ;
53- m_lpR = m_hpR = m_bpR = 0 . 0f ;
75+ m_s1L = m_s2L = 0.0 ;
76+ m_s1R = m_s2R = 0.0 ;
5477}
5578
5679} // namespace noteahead
0 commit comments