AME
ame_Biquad.hpp
Go to the documentation of this file.
1
13#pragma once
14
15#include "ame_AudioBuffer.hpp"
16#include "ame_Math.hpp"
17
18#include <array>
19#include <atomic>
20#include <cassert>
21#include <cmath>
22#include <concepts>
23#include <cstdint>
24
25namespace ame::dsp
26{
28template <std::floating_point FloatType, size_t MaximumChannels>
29class Biquad
30{
31public:
32 explicit Biquad (const FloatType sampleRate)
33 : sampleRate (sampleRate)
34 {
35 }
36 ~Biquad() = default;
37
39 void setSampleRate (const FloatType newSampleRate) noexcept
40 {
41 sampleRate = newSampleRate;
42 }
43
45 FloatType getSampleRate() const noexcept
46 {
47 return sampleRate;
48 }
49
52 {
53 FloatType a0 = 0.0;
54 FloatType a1 = 0.0;
55 FloatType a2 = 0.0;
56 FloatType b0 = 0.0;
57 FloatType b1 = 0.0;
58 FloatType b2 = 0.0;
59 };
60
67 void setCoefficients (const Coefficients& c) noexcept
68 {
69 coef = c;
70 }
71
72 Coefficients getCoefficients() const noexcept
73 {
74 return coef;
75 }
76
78 void makeLowPass (const FloatType cutOffFrequency, const FloatType Q) noexcept
79 {
80 const FloatType w0 = twoPi<FloatType> * cutOffFrequency / sampleRate;
81 const FloatType alpha = sinf (w0) / (FloatType (2.0) * Q);
82
83 coef.a0 = FloatType (1.0) + alpha;
84 coef.b0 = (FloatType (1.0) - cosf (w0)) / FloatType (2.0);
85 coef.b1 = FloatType (1.0) - cosf (w0);
86 coef.b2 = coef.b0;
87 coef.a1 = FloatType (-2.0) * cosf (w0);
88 coef.a2 = FloatType (1.0) - alpha;
89 normalizeCoefficientsByA0();
90 }
91
93 void makeHighPass (const FloatType cutOffFrequency, const FloatType Q) noexcept
94 {
95 const FloatType w0 = twoPi<FloatType> * cutOffFrequency / sampleRate;
96 const FloatType alpha = sinf (w0) / (FloatType (2.0) * Q);
97
98 coef.a0 = FloatType (1.0) + alpha;
99 coef.b0 = (FloatType (1.0) + cosf (w0)) / FloatType (2.0);
100 coef.b1 = -(FloatType (1.0) + cosf (w0));
101 coef.b2 = coef.b0;
102 coef.a1 = FloatType (-2.0) * cosf (w0);
103 coef.a2 = FloatType (1.0) - alpha;
104 normalizeCoefficientsByA0();
105 }
106
108 void makeBandPass (const FloatType cutOffFrequency, const FloatType Q) noexcept
109 {
110 const FloatType w0 = twoPi<FloatType> * cutOffFrequency / sampleRate;
111 const FloatType alpha = sinf (w0) / (FloatType (2.0) * Q);
112
113 coef.a0 = FloatType (1.0) + alpha;
114 coef.b0 = alpha;
115 coef.b1 = FloatType (0.0);
116 coef.b2 = -alpha;
117 coef.a1 = FloatType (-2.0) * cosf (w0);
118 coef.a2 = FloatType (1.0) - alpha;
119 normalizeCoefficientsByA0();
120 }
121
123 void makeNotch (const FloatType sampleRate, const FloatType cutOffFrequency, const FloatType Q) noexcept
124 {
125 const FloatType w0 = twoPi<FloatType> * cutOffFrequency / sampleRate;
126 const FloatType alpha = sinf (w0) / (FloatType (2.0) * Q);
127
128 coef.a0 = FloatType (1.0) + alpha;
129 coef.b0 = FloatType (1.0);
130 coef.b1 = FloatType (-2.0) * cosf (w0);
131 coef.b2 = FloatType (1.0);
132 coef.a1 = FloatType (-2.0) * cosf (w0);
133 coef.a2 = FloatType (1.0) - alpha;
134 normalizeCoefficientsByA0();
135 }
136
138 void makeAllPass (const FloatType cutOffFrequency, const FloatType Q) noexcept
139 {
140 const FloatType w0 = twoPi<FloatType> * cutOffFrequency / sampleRate;
141 const FloatType alpha = sinf (w0) / (FloatType (2.0) * Q);
142
143 coef.a0 = FloatType (1.0) + alpha;
144 coef.b0 = FloatType (1.0) - alpha;
145 coef.b1 = FloatType (-2.0) * cosf (w0);
146 coef.b2 = FloatType (1.0) + alpha;
147 coef.a1 = FloatType (-2.0) * cosf (w0);
148 coef.a2 = FloatType (1.0) - alpha;
149 normalizeCoefficientsByA0();
150 }
151
153 void makePeakFilter (const FloatType cutOffFrequency, const FloatType Q, const FloatType gainDb) noexcept
154 {
155 const FloatType A = std::pow (FloatType (10.0), gainDb / FloatType (40.0));
156 const FloatType w0 = twoPi<FloatType> * cutOffFrequency / sampleRate;
157 const FloatType alpha = sinf (w0) / FloatType (2.0) * Q;
158
159 coef.a0 = FloatType (1.0) + alpha / A;
160 coef.b0 = FloatType (1.0) - alpha * A;
161 coef.b1 = FloatType (-2.0) * cosf (w0);
162 coef.b2 = FloatType (1.0) + alpha * A;
163 coef.a1 = FloatType (-2.0) * cosf (w0);
164 coef.a2 = FloatType (1.0) - alpha / A;
165 normalizeCoefficientsByA0();
166 }
167
169 void makeLowShelf (const FloatType cutOffFrequency, const FloatType Q, const FloatType gainDb) noexcept
170 {
171 const FloatType A = std::pow (FloatType (10.0), gainDb / FloatType (40.0));
172 const FloatType w0 = twoPi<FloatType> * cutOffFrequency / sampleRate;
173 const FloatType alpha = sinf (w0) / (FloatType (2.0) * Q);
174
175 coef.a0 = FloatType (1.0) + alpha / A;
176 coef.b0 = A * ((A + FloatType (1.0)) - (A - FloatType (1.0)) * cosf (w0) + FloatType (2.0) * std::sqrt (A) * alpha);
177 coef.b1 = FloatType (2.0) * A * ((A - FloatType (1.0)) - (A + FloatType (1.0)) * cosf (w0));
178 coef.b2 = A * ((A + FloatType (1.0)) - (A - FloatType (1.0)) * cosf (w0) - FloatType (2.0) * std::sqrt (A) * alpha);
179 coef.a1 = FloatType (-2.0) * ((A - FloatType (1.0)) + (A + FloatType (1.0)) * cosf (w0));
180 coef.a2 = (A + FloatType (1.0)) + (A - FloatType (1.0)) * cosf (w0) - FloatType (2.0) * std::sqrt (A) * alpha;
181 normalizeCoefficientsByA0();
182 }
183
185 void makeHighShelf (const FloatType cutOffFrequency, const FloatType Q, const FloatType gainDb) noexcept
186 {
187 const FloatType A = std::pow (FloatType (10.0), gainDb / FloatType (40.0));
188 const FloatType w0 = twoPi<FloatType> * cutOffFrequency / sampleRate;
189 const FloatType alpha = sinf (w0) / (FloatType (2.0) * Q);
190
191 coef.a0 = FloatType (1.0) + alpha / A;
192 coef.b0 = A * ((A + FloatType (1.0)) + (A - FloatType (1.0)) * cosf (w0) + FloatType (2.0) * std::sqrt (A) * alpha);
193 coef.b1 = FloatType (-2.0) * A * ((A - FloatType (1.0)) + (A + FloatType (1.0)) * cosf (w0));
194 coef.b2 = A * ((A + FloatType (1.0)) + (A - FloatType (1.0)) * cosf (w0) - FloatType (2.0) * std::sqrt (A) * alpha);
195 coef.a1 = FloatType (2.0) * ((A - FloatType (1.0)) - (A + FloatType (1.0)) * cosf (w0));
196 coef.a2 = (A + FloatType (1.0)) - (A - FloatType (1.0)) * cosf (w0) - FloatType (2.0) * std::sqrt (A) * alpha;
197 normalizeCoefficientsByA0();
198 }
199
201 template <typename SampleType, size_t N>
203 {
204 assert (block.getNumChannels() <= MaximumChannels);
205 const uint_fast32_t numChannels = block.getNumChannels();
206 const uint_fast32_t bufferSize = block.getNumSamplesPerChannel();
207
208 uint_fast32_t i = 0;
209 for (uint_fast32_t samp = 0; samp < bufferSize; ++samp)
210 {
211 for (uint_fast32_t ch = 0; ch < numChannels; ++ch)
212 {
213 const FloatType input = block.view[i];
214 const FloatType output = coef.b0 * input + coef.b1 * x1[ch] + coef.b2 * x2[ch] - coef.a1 * y1[ch] - coef.a2 * y2[ch];
215 x2[ch] = x1[ch];
216 x1[ch] = input;
217 y2[ch] = y1[ch];
218 y1[ch] = output;
219 block.view[i] = output;
220 ++i;
221 }
222 }
223 }
224
225private:
226 void normalizeCoefficientsByA0()
227 {
228 coef.b0 /= coef.a0;
229 coef.b1 /= coef.a0;
230 coef.b2 /= coef.a0;
231 coef.a1 /= coef.a0;
232 coef.a2 /= coef.a0;
233 }
234
235 Coefficients coef {};
236 FloatType sampleRate {};
237 std::array<FloatType, MaximumChannels> x1 {};
238 std::array<FloatType, MaximumChannels> x2 {};
239 std::array<FloatType, MaximumChannels> y1 {};
240 std::array<FloatType, MaximumChannels> y2 {};
241};
242} // namespace ame::dsp
Audio buffer.
Math functions.
A lightweight data structure that stores a pointer to an audio buffer.
Definition: ame_AudioBuffer.hpp:32
uint_fast32_t getNumChannels() const noexcept
Returns the number of channels.
Definition: ame_AudioBuffer.hpp:49
uint_fast32_t getNumSamplesPerChannel() const noexcept
Returns the number of samples per channel.
Definition: ame_AudioBuffer.hpp:55
BiQuad filter.
Definition: ame_Biquad.hpp:30
void setSampleRate(const FloatType newSampleRate) noexcept
Set new sampleRate.
Definition: ame_Biquad.hpp:39
void makeHighShelf(const FloatType cutOffFrequency, const FloatType Q, const FloatType gainDb) noexcept
High-shelf coefficients calculation from RBJ cookbook.
Definition: ame_Biquad.hpp:185
void setCoefficients(const Coefficients &c) noexcept
Set BiQuad coefficients.
Definition: ame_Biquad.hpp:67
void makeNotch(const FloatType sampleRate, const FloatType cutOffFrequency, const FloatType Q) noexcept
Notch coefficients calculation from RBJ cookbook.
Definition: ame_Biquad.hpp:123
FloatType getSampleRate() const noexcept
Return sampleRate.
Definition: ame_Biquad.hpp:45
void makeBandPass(const FloatType cutOffFrequency, const FloatType Q) noexcept
BandPass coefficients calculation from RBJ cookbook.
Definition: ame_Biquad.hpp:108
void makeLowShelf(const FloatType cutOffFrequency, const FloatType Q, const FloatType gainDb) noexcept
Low-shelf coefficients calculation from RBJ cookbook.
Definition: ame_Biquad.hpp:169
void makePeakFilter(const FloatType cutOffFrequency, const FloatType Q, const FloatType gainDb) noexcept
Peak coefficients calculation from RBJ cookbook.
Definition: ame_Biquad.hpp:153
void makeHighPass(const FloatType cutOffFrequency, const FloatType Q) noexcept
High-pass coefficients calculation from RBJ cookbook.
Definition: ame_Biquad.hpp:93
void makeLowPass(const FloatType cutOffFrequency, const FloatType Q) noexcept
Low-pass coefficients calculation from RBJ cookbook.
Definition: ame_Biquad.hpp:78
void makeAllPass(const FloatType cutOffFrequency, const FloatType Q) noexcept
AllPass coefficients calculation from RBJ cookbook.
Definition: ame_Biquad.hpp:138
void process(AudioBlockView< SampleType, N > &block)
Process audio effect.
Definition: ame_Biquad.hpp:202
BiQuad filter coefficients.
Definition: ame_Biquad.hpp:52