Add missing linear resampler to the option setting list
[openal-soft.git] / alc / filters / biquad.h
blob3ce70cb36ce9bc6a51f61fd56ee7c3b18aac2b32
1 #ifndef FILTERS_BIQUAD_H
2 #define FILTERS_BIQUAD_H
4 #include <algorithm>
5 #include <cmath>
6 #include <cstddef>
7 #include <utility>
9 #include "alspan.h"
10 #include "math_defs.h"
13 /* Filters implementation is based on the "Cookbook formulae for audio
14 * EQ biquad filter coefficients" by Robert Bristow-Johnson
15 * http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt
17 /* Implementation note: For the shelf and peaking filters, the specified gain
18 * is for the centerpoint of the transition band. This better fits EFX filter
19 * behavior, which expects the shelf's reference frequency to reach the given
20 * gain. To set the gain for the shelf or peak itself, use the square root of
21 * the desired linear gain (or halve the dB gain).
24 enum class BiquadType {
25 /** EFX-style low-pass filter, specifying a gain and reference frequency. */
26 HighShelf,
27 /** EFX-style high-pass filter, specifying a gain and reference frequency. */
28 LowShelf,
29 /** Peaking filter, specifying a gain and reference frequency. */
30 Peaking,
32 /** Low-pass cut-off filter, specifying a cut-off frequency. */
33 LowPass,
34 /** High-pass cut-off filter, specifying a cut-off frequency. */
35 HighPass,
36 /** Band-pass filter, specifying a center frequency. */
37 BandPass,
40 template<typename Real>
41 class BiquadFilterR {
42 /* Last two delayed components for direct form II. */
43 Real mZ1{0.0f}, mZ2{0.0f};
44 /* Transfer function coefficients "b" (numerator) */
45 Real mB0{1.0f}, mB1{0.0f}, mB2{0.0f};
46 /* Transfer function coefficients "a" (denominator; a0 is pre-applied). */
47 Real mA1{0.0f}, mA2{0.0f};
49 void setParams(BiquadType type, Real f0norm, Real gain, Real rcpQ);
51 /**
52 * Calculates the rcpQ (i.e. 1/Q) coefficient for shelving filters, using
53 * the reference gain and shelf slope parameter.
54 * \param gain 0 < gain
55 * \param slope 0 < slope <= 1
57 static Real rcpQFromSlope(Real gain, Real slope)
58 { return std::sqrt((gain + 1.0f/gain)*(1.0f/slope - 1.0f) + 2.0f); }
60 /**
61 * Calculates the rcpQ (i.e. 1/Q) coefficient for filters, using the
62 * normalized reference frequency and bandwidth.
63 * \param f0norm 0 < f0norm < 0.5.
64 * \param bandwidth 0 < bandwidth
66 static Real rcpQFromBandwidth(Real f0norm, Real bandwidth)
68 const Real w0{al::MathDefs<Real>::Tau() * f0norm};
69 return 2.0f*std::sinh(std::log(Real{2.0f})/2.0f*bandwidth*w0/std::sin(w0));
72 public:
73 void clear() noexcept { mZ1 = mZ2 = 0.0f; }
75 /**
76 * Sets the filter state for the specified filter type and its parameters.
78 * \param type The type of filter to apply.
79 * \param f0norm The normalized reference frequency (ref / sample_rate).
80 * This is the center point for the Shelf, Peaking, and BandPass filter
81 * types, or the cutoff frequency for the LowPass and HighPass filter
82 * types.
83 * \param gain The gain for the reference frequency response. Only used by
84 * the Shelf and Peaking filter types.
85 * \param slope Slope steepness of the transition band.
87 void setParamsFromSlope(BiquadType type, Real f0norm, Real gain, Real slope)
89 gain = std::max<Real>(gain, 0.001f); /* Limit -60dB */
90 setParams(type, f0norm, gain, rcpQFromSlope(gain, slope));
93 /**
94 * Sets the filter state for the specified filter type and its parameters.
96 * \param type The type of filter to apply.
97 * \param f0norm The normalized reference frequency (ref / sample_rate).
98 * This is the center point for the Shelf, Peaking, and BandPass filter
99 * types, or the cutoff frequency for the LowPass and HighPass filter
100 * types.
101 * \param gain The gain for the reference frequency response. Only used by
102 * the Shelf and Peaking filter types.
103 * \param bandwidth Normalized bandwidth of the transition band.
105 void setParamsFromBandwidth(BiquadType type, Real f0norm, Real gain, Real bandwidth)
106 { setParams(type, f0norm, gain, rcpQFromBandwidth(f0norm, bandwidth)); }
108 void copyParamsFrom(const BiquadFilterR &other)
110 mB0 = other.mB0;
111 mB1 = other.mB1;
112 mB2 = other.mB2;
113 mA1 = other.mA1;
114 mA2 = other.mA2;
117 void process(const al::span<const Real> src, Real *dst);
118 /** Processes this filter and the other at the same time. */
119 void dualProcess(BiquadFilterR &other, const al::span<const Real> src, Real *dst);
121 /* Rather hacky. It's just here to support "manual" processing. */
122 std::pair<Real,Real> getComponents() const noexcept { return {mZ1, mZ2}; }
123 void setComponents(Real z1, Real z2) noexcept { mZ1 = z1; mZ2 = z2; }
124 Real processOne(const Real in, Real &z1, Real &z2) const noexcept
126 const Real out{in*mB0 + z1};
127 z1 = in*mB1 - out*mA1 + z2;
128 z2 = in*mB2 - out*mA2;
129 return out;
133 template<typename Real>
134 struct DualBiquadR {
135 BiquadFilterR<Real> &f0, &f1;
137 void process(const al::span<const Real> src, Real *dst)
138 { f0.dualProcess(f1, src, dst); }
141 using BiquadFilter = BiquadFilterR<float>;
142 using DualBiquad = DualBiquadR<float>;
144 #endif /* FILTERS_BIQUAD_H */