10 #include "opthelpers.h"
13 template<typename Real
>
14 void BiquadFilterR
<Real
>::setParams(BiquadType type
, Real f0norm
, Real gain
, Real rcpQ
)
16 // Limit gain to -100dB
17 assert(gain
> 0.00001f
);
19 const Real w0
{al::MathDefs
<Real
>::Tau() * f0norm
};
20 const Real sin_w0
{std::sin(w0
)};
21 const Real cos_w0
{std::cos(w0
)};
22 const Real alpha
{sin_w0
/2.0f
* rcpQ
};
24 Real sqrtgain_alpha_2
;
25 Real a
[3]{ 1.0f
, 0.0f
, 0.0f
};
26 Real b
[3]{ 1.0f
, 0.0f
, 0.0f
};
28 /* Calculate filter coefficients depending on filter type */
31 case BiquadType::HighShelf
:
32 sqrtgain_alpha_2
= 2.0f
* std::sqrt(gain
) * alpha
;
33 b
[0] = gain
*((gain
+1.0f
) + (gain
-1.0f
)*cos_w0
+ sqrtgain_alpha_2
);
34 b
[1] = -2.0f
*gain
*((gain
-1.0f
) + (gain
+1.0f
)*cos_w0
);
35 b
[2] = gain
*((gain
+1.0f
) + (gain
-1.0f
)*cos_w0
- sqrtgain_alpha_2
);
36 a
[0] = (gain
+1.0f
) - (gain
-1.0f
)*cos_w0
+ sqrtgain_alpha_2
;
37 a
[1] = 2.0f
* ((gain
-1.0f
) - (gain
+1.0f
)*cos_w0
);
38 a
[2] = (gain
+1.0f
) - (gain
-1.0f
)*cos_w0
- sqrtgain_alpha_2
;
40 case BiquadType::LowShelf
:
41 sqrtgain_alpha_2
= 2.0f
* std::sqrt(gain
) * alpha
;
42 b
[0] = gain
*((gain
+1.0f
) - (gain
-1.0f
)*cos_w0
+ sqrtgain_alpha_2
);
43 b
[1] = 2.0f
*gain
*((gain
-1.0f
) - (gain
+1.0f
)*cos_w0
);
44 b
[2] = gain
*((gain
+1.0f
) - (gain
-1.0f
)*cos_w0
- sqrtgain_alpha_2
);
45 a
[0] = (gain
+1.0f
) + (gain
-1.0f
)*cos_w0
+ sqrtgain_alpha_2
;
46 a
[1] = -2.0f
* ((gain
-1.0f
) + (gain
+1.0f
)*cos_w0
);
47 a
[2] = (gain
+1.0f
) + (gain
-1.0f
)*cos_w0
- sqrtgain_alpha_2
;
49 case BiquadType::Peaking
:
50 b
[0] = 1.0f
+ alpha
* gain
;
51 b
[1] = -2.0f
* cos_w0
;
52 b
[2] = 1.0f
- alpha
* gain
;
53 a
[0] = 1.0f
+ alpha
/ gain
;
54 a
[1] = -2.0f
* cos_w0
;
55 a
[2] = 1.0f
- alpha
/ gain
;
58 case BiquadType::LowPass
:
59 b
[0] = (1.0f
- cos_w0
) / 2.0f
;
61 b
[2] = (1.0f
- cos_w0
) / 2.0f
;
63 a
[1] = -2.0f
* cos_w0
;
66 case BiquadType::HighPass
:
67 b
[0] = (1.0f
+ cos_w0
) / 2.0f
;
68 b
[1] = -(1.0f
+ cos_w0
);
69 b
[2] = (1.0f
+ cos_w0
) / 2.0f
;
71 a
[1] = -2.0f
* cos_w0
;
74 case BiquadType::BandPass
:
79 a
[1] = -2.0f
* cos_w0
;
91 template<typename Real
>
92 void BiquadFilterR
<Real
>::process(const al::span
<const Real
> src
, Real
*dst
)
102 /* Processing loop is Transposed Direct Form II. This requires less storage
103 * compared to Direct Form I (only two delay components, instead of a four-
104 * sample history; the last two inputs and outputs), and works better for
105 * floating-point which favors summing similarly-sized values while being
106 * less bothered by overflow.
108 * See: http://www.earlevel.com/main/2003/02/28/biquads/
110 auto proc_sample
= [b0
,b1
,b2
,a1
,a2
,&z1
,&z2
](Real input
) noexcept
-> Real
112 const Real output
{input
*b0
+ z1
};
113 z1
= input
*b1
- output
*a1
+ z2
;
114 z2
= input
*b2
- output
*a2
;
117 std::transform(src
.cbegin(), src
.cend(), dst
, proc_sample
);
123 template<typename Real
>
124 void BiquadFilterR
<Real
>::dualProcess(BiquadFilterR
&other
, const al::span
<const Real
> src
,
132 const Real b10
{other
.mB0
};
133 const Real b11
{other
.mB1
};
134 const Real b12
{other
.mB2
};
135 const Real a11
{other
.mA1
};
136 const Real a12
{other
.mA2
};
142 auto proc_sample
= [b00
,b01
,b02
,a01
,a02
,b10
,b11
,b12
,a11
,a12
,&z01
,&z02
,&z11
,&z12
](Real input
) noexcept
-> Real
144 const Real tmpout
{input
*b00
+ z01
};
145 z01
= input
*b01
- tmpout
*a01
+ z02
;
146 z02
= input
*b02
- tmpout
*a02
;
149 const Real output
{input
*b10
+ z11
};
150 z11
= input
*b11
- output
*a11
+ z12
;
151 z12
= input
*b12
- output
*a12
;
154 std::transform(src
.cbegin(), src
.cend(), dst
, proc_sample
);
162 template class BiquadFilterR
<float>;
163 template class BiquadFilterR
<double>;