arduino-audio-tools
Loading...
Searching...
No Matches
Filter.h
Go to the documentation of this file.
1#pragma once
2#include <math.h>
3
4#include "AudioToolsConfig.h"
5#ifdef USE_TYPETRAITS
6#include <type_traits>
7#endif
8
9
16namespace audio_tools {
17
26template <typename T>
27class Filter {
28 public:
29 // construct without coefs
30 Filter() = default;
31 virtual ~Filter() = default;
32 Filter(Filter const&) = delete;
33 Filter& operator=(Filter const&) = delete;
35 virtual T process(T in) = 0;
39 virtual void reset() {}
40};
41
49template <typename T>
50class NoFilter : public Filter<T> {
51 public:
52 // construct without coefs
53 NoFilter() = default;
54 T process(T in) override { return in; }
55};
56
67template <typename T>
68class FIR : public Filter<T> {
69 public:
70 template <size_t B>
71 FIR(const T (&b)[B], const T factor = 1.0) : lenB(B), factor(factor) {
72 setValues(b);
73 }
74
75 template <size_t B>
76 void setValues(const T (&b)[B]) {
77 x.resize(lenB);
78 coeff_b.resize(2 * lenB - 1);
79 for (uint16_t i = 0; i < 2 * lenB - 1; i++) {
80 coeff_b[i] = b[(2 * lenB - 1 - i) % lenB];
81 }
82 }
83
84 void reset() override {
85 i_b = 0;
86 for (uint16_t i = 0; i < lenB; i++) x[i] = 0;
87 }
88
89 T process(T value) override {
90 x[i_b] = value;
91 T b_terms = 0;
92 T* b_shift = &coeff_b[lenB - i_b - 1];
93 for (uint16_t i = 0; i < lenB; i++) {
94 b_terms += b_shift[i] * x[i];
95 }
96 i_b++;
97 if (i_b == lenB) i_b = 0;
98
99#ifdef USE_TYPETRAITS
100 if (!(std::is_same<T, float>::value || std::is_same<T, double>::value)) {
101 b_terms = b_terms / factor;
102 }
103#else
104 if (factor != 1.0) {
105 b_terms = b_terms / factor;
106 }
107#endif
108 return b_terms;
109 }
110
111 private:
112 const uint16_t lenB;
113 uint16_t i_b = 0;
114 Vector<T> x;
115 Vector<T> coeff_b;
116 T factor;
117};
118
129template <typename T>
130class IIR : public Filter<T> {
131 public:
132 template <size_t B, size_t A>
133 IIR(const T (&b)[B], const T (&_a)[A], T factor = 1.0)
134 : factor(factor), lenB(B), lenA(A - 1) {
135 x.resize(lenB);
136 y.resize(lenA);
137 coeff_b.resize(2 * lenB - 1);
138 coeff_a.resize(2 * lenA - 1);
139 T a0 = _a[0];
140 const T* a = &_a[1];
141 for (uint16_t i = 0; i < 2 * lenB - 1; i++) {
142 coeff_b[i] = b[(2 * lenB - 1 - i) % lenB] / a0;
143 }
144 for (uint16_t i = 0; i < 2 * lenA - 1; i++) {
145 coeff_a[i] = a[(2 * lenA - 2 - i) % lenA] / a0;
146 }
147 }
148
149 void reset() override {
150 i_b = 0;
151 i_a = 0;
152 for (uint16_t i = 0; i < lenB; i++) x[i] = 0;
153 for (uint16_t i = 0; i < lenA; i++) y[i] = 0;
154 }
155
156 T process(T value) override {
157 x[i_b] = value;
158 T b_terms = 0;
159 T* b_shift = &coeff_b[lenB - i_b - 1];
160
161 T a_terms = 0;
162 T* a_shift = &coeff_a[lenA - i_a - 1];
163
164 for (uint16_t i = 0; i < lenB; i++) {
165 b_terms += x[i] * b_shift[i];
166 }
167 for (uint16_t i = 0; i < lenA; i++) {
168 a_terms += y[i] * a_shift[i];
169 }
170
171 T filtered = b_terms - a_terms;
172 y[i_a] = filtered;
173 i_b++;
174 if (i_b == lenB) i_b = 0;
175 i_a++;
176 if (i_a == lenA) i_a = 0;
177
178#ifdef USE_TYPETRAITS
179 if (!(std::is_same<T, float>::value || std::is_same<T, double>::value)) {
180 filtered = filtered / factor;
181 }
182#else
183 if (factor != 1.0) {
184 filtered = filtered / factor;
185 }
186#endif
187 return filtered;
188 }
189
190 private:
191 T factor;
192 const uint16_t lenB, lenA;
193 uint16_t i_b = 0, i_a = 0;
194 Vector<T> x;
195 Vector<T> y;
196 Vector<T> coeff_b;
197 Vector<T> coeff_a;
198};
199
209template <typename T>
210class BiQuadDF1 : public Filter<T> {
211 public:
212 BiQuadDF1(const T (&b)[3], const T (&a)[3])
213 : b_0(b[0] / a[0]),
214 b_1(b[1] / a[0]),
215 b_2(b[2] / a[0]),
216 a_1(a[1] / a[0]),
217 a_2(a[2] / a[0]) {}
218 BiQuadDF1(const T (&b)[3], const T (&a)[2])
219 : b_0(b[0]), b_1(b[1]), b_2(b[2]), a_1(a[0]), a_2(a[1]) {}
220 BiQuadDF1(const T (&b)[3], const T (&a)[2], T gain)
221 : b_0(gain * b[0]),
222 b_1(gain * b[1]),
223 b_2(gain * b[2]),
224 a_1(a[0]),
225 a_2(a[1]) {}
226 BiQuadDF1(const T (&b)[3], const T (&a)[3], T gain)
227 : b_0(gain * b[0] / a[0]),
228 b_1(gain * b[1] / a[0]),
229 b_2(gain * b[2] / a[0]),
230 a_1(a[1] / a[0]),
231 a_2(a[2] / a[0]) {}
232
233 void reset() override { x_0 = x_1 = y_1 = y_2 = 0; }
234
235 T process(T value) override {
236 T x_2 = x_1;
237 x_1 = x_0;
238 x_0 = value;
239 T b_terms = x_0 * b_0 + x_1 * b_1 + x_2 * b_2;
240 T a_terms = y_1 * a_1 + y_2 * a_2;
241 y_2 = y_1;
242 y_1 = b_terms - a_terms;
243 return y_1;
244 }
245
246 private:
247 T b_0;
248 T b_1;
249 T b_2;
250 T a_1;
251 T a_2;
252
253 T x_0 = 0;
254 T x_1 = 0;
255 T y_1 = 0;
256 T y_2 = 0;
257};
258
270template <typename T>
271class BiQuadDF2 : public Filter<T> {
272 public:
273 BiQuadDF2(const T (&b)[3], const T (&a)[3])
274 : b_0(b[0] / a[0]),
275 b_1(b[1] / a[0]),
276 b_2(b[2] / a[0]),
277 a_1(a[1] / a[0]),
278 a_2(a[2] / a[0]) {}
279 BiQuadDF2(const T (&b)[3], const T (&a)[2])
280 : b_0(b[0]), b_1(b[1]), b_2(b[2]), a_1(a[0]), a_2(a[1]) {}
281 BiQuadDF2(const T (&b)[3], const T (&a)[2], T gain)
282 : b_0(gain * b[0]),
283 b_1(gain * b[1]),
284 b_2(gain * b[2]),
285 a_1(a[0]),
286 a_2(a[1]) {}
287 BiQuadDF2(const T (&b)[3], const T (&a)[3], T gain)
288 : b_0(gain * b[0] / a[0]),
289 b_1(gain * b[1] / a[0]),
290 b_2(gain * b[2] / a[0]),
291 a_1(a[1] / a[0]),
292 a_2(a[2] / a[0]) {}
293
294 void reset() override { w_0 = w_1 = 0; }
295
296 T process(T value) override {
297 T w_2 = w_1;
298 w_1 = w_0;
299 w_0 = value - a_1 * w_1 - a_2 * w_2;
300 T y = b_0 * w_0 + b_1 * w_1 + b_2 * w_2;
301 return y;
302 }
303
304 protected:
305 T b_0 = 0;
306 T b_1 = 0;
307 T b_2 = 0;
308 T a_1 = 0;
309 T a_2 = 0;
310
311 // allow constructor w/o parameter in subclasses
312 BiQuadDF2() = default;
313
314 T w_0 = 0;
315 T w_1 = 0;
316};
317
331template <typename T>
332class LowPassFilter : public BiQuadDF2<T> {
333 public:
334 LowPassFilter() = default;
335 LowPassFilter(float frequency, float sampleRate, float q = 0.7071f)
336 : BiQuadDF2<T>() {
337 begin(frequency, sampleRate, q);
338 }
339 void begin(float frequency, float sampleRate, float q = 0.7071f) {
340 T w0 = frequency * (2.0f * PI / sampleRate);
341 T sinW0 = sin(w0);
342 T alpha = sinW0 / ((float)q * 2.0);
343 T cosW0 = cos(w0);
344 T scale = 1.0 / (1.0 + alpha);
345 BiQuadDF2<T>::b_0 = ((1.0 - cosW0) / 2.0) * scale;
346 BiQuadDF2<T>::b_1 = (1.0 - cosW0) * scale;
348 BiQuadDF2<T>::a_1 = (-2.0 * cosW0) * scale;
349 BiQuadDF2<T>::a_2 = (1.0 - alpha) * scale;
350 }
351};
352
366template <typename T>
367class HighPassFilter : public BiQuadDF2<T> {
368 public:
369 HighPassFilter() = default;
370 HighPassFilter(float frequency, float sampleRate, float q = 0.7071f)
371 : BiQuadDF2<T>() {
372 begin(frequency, sampleRate, q);
373 }
374 void begin(float frequency, float sampleRate, float q = 0.7071f) {
375 T w0 = frequency * (2.0f * PI / sampleRate);
376 T sinW0 = sin(w0);
377 T alpha = sinW0 / ((float)q * 2.0);
378 T cosW0 = cos(w0);
379 T scale = 1.0 / (1.0 + alpha);
380 BiQuadDF2<T>::b_0 = ((1.0 + cosW0) / 2.0) * scale;
381 BiQuadDF2<T>::b_1 = -(1.0 + cosW0) * scale;
383 BiQuadDF2<T>::a_1 = (-2.0 * cosW0) * scale;
384 BiQuadDF2<T>::a_2 = (1.0 - alpha) * scale;
385 }
386};
387
402template <typename T>
403class BandPassFilter : public BiQuadDF2<T> {
404 public:
405 BandPassFilter() = default;
406 BandPassFilter(float frequency, float sampleRate, float q = 1.0)
407 : BiQuadDF2<T>() {
408 begin(frequency, sampleRate, q);
409 }
410 void begin(float frequency, float sampleRate, float q = 1.0) {
411 T w0 = frequency * (2.0f * PI / sampleRate);
412 T sinW0 = sin(w0);
413 T alpha = sinW0 / ((T)q * 2.0);
414 T cosW0 = cos(w0);
415 T scale = 1.0 / (1.0 + alpha);
416 BiQuadDF2<T>::b_0 = alpha * scale;
418 BiQuadDF2<T>::b_2 = (-alpha) * scale;
419 BiQuadDF2<T>::a_1 = (-2.0 * cosW0) * scale;
420 BiQuadDF2<T>::a_2 = (1.0 - alpha) * scale;
421 }
422};
423
439template <typename T>
440class NotchFilter : public BiQuadDF2<T> {
441 public:
442 NotchFilter() = default;
443 NotchFilter(float frequency, float sampleRate, float q = 1.0)
444 : BiQuadDF2<T>() {
445 begin(frequency, sampleRate, q);
446 }
447
448 void begin(float frequency, float sampleRate, float q = 1.0) {
449 T w0 = frequency * (2.0f * PI / sampleRate);
450 T sinW0 = sin(w0);
451 T alpha = sinW0 / ((float)q * 2.0);
452 T cosW0 = cos(w0);
453 T scale = 1.0 / (1.0 + alpha);
454 BiQuadDF2<T>::b_0 = scale;
455 BiQuadDF2<T>::b_1 = (-2.0 * cosW0) * scale;
457 BiQuadDF2<T>::a_1 = (-2.0 * cosW0) * scale;
458 BiQuadDF2<T>::a_2 = (1.0 - alpha) * scale;
459 }
460};
461
477template <typename T>
478class LowShelfFilter : public BiQuadDF2<T> {
479 public:
480 LowShelfFilter() = default;
481 LowShelfFilter(float frequency, float sampleRate, float gain,
482 float slope = 1.0f)
483 : BiQuadDF2<T>() {
484 begin(frequency, sampleRate, gain, slope);
485 }
486
487 void begin(float frequency, float sampleRate, float gain,
488 float slope = 1.0f) {
489 T a = pow(10.0, gain / 40.0f);
490 T w0 = frequency * (2.0f * PI / sampleRate);
491 T sinW0 = sin(w0);
492 // float alpha = (sinW0 * sqrt((a+1/a)*(1/slope-1)+2) ) / 2.0;
493 T cosW0 = cos(w0);
494 // generate three helper-values (intermediate results):
495 T sinsq = sinW0 *
496 sqrt((pow(a, 2.0) + 1.0) * (1.0 / (float)slope - 1.0) + 2.0 * a);
497 T aMinus = (a - 1.0) * cosW0;
498 T aPlus = (a + 1.0) * cosW0;
499 T scale = 1.0 / ((a + 1.0) + aMinus + sinsq);
500 BiQuadDF2<T>::b_0 = a * ((a + 1.0) - aMinus + sinsq) * scale;
501 BiQuadDF2<T>::b_1 = 2.0 * a * ((a - 1.0) - aPlus) * scale;
502 BiQuadDF2<T>::b_2 = a * ((a + 1.0) - aMinus - sinsq) * scale;
503 BiQuadDF2<T>::a_1 = -2.0 * ((a - 1.0) + aPlus) * scale;
504 BiQuadDF2<T>::a_2 = ((a + 1.0) + aMinus - sinsq) * scale;
505 }
506};
507
524template <typename T>
525class HighShelfFilter : public BiQuadDF2<T> {
526 public:
527 HighShelfFilter() = default;
528 HighShelfFilter(float frequency, float sampleRate, float gain,
529 float slope = 1.0f)
530 : BiQuadDF2<T>() {
531 begin(frequency, sampleRate, gain, slope);
532 }
533 void begin(float frequency, float sampleRate, float gain,
534 float slope = 1.0f) {
535 T a = pow(10.0, gain / 40.0f);
536 T w0 = frequency * (2.0f * PI / sampleRate);
537 T sinW0 = sin(w0);
538 // float alpha = (sinW0 * sqrt((a+1/a)*(1/slope-1)+2) ) / 2.0;
539 T cosW0 = cos(w0);
540 // generate three helper-values (intermediate results):
541 T sinsq = sinW0 *
542 sqrt((pow(a, 2.0) + 1.0) * (1.0 / (float)slope - 1.0) + 2.0 * a);
543 T aMinus = (a - 1.0) * cosW0;
544 T aPlus = (a + 1.0) * cosW0;
545 T scale = 1.0 / ((a + 1.0) - aMinus + sinsq);
546 BiQuadDF2<T>::b_0 = a * ((a + 1.0) + aMinus + sinsq) * scale;
547 BiQuadDF2<T>::b_1 = -2.0 * a * ((a - 1.0) + aPlus) * scale;
548 BiQuadDF2<T>::b_2 = a * ((a + 1.0) + aMinus - sinsq) * scale;
549 BiQuadDF2<T>::a_1 = 2.0 * ((a - 1.0) - aPlus) * scale;
550 BiQuadDF2<T>::a_2 = ((a + 1.0) - aMinus - sinsq) * scale;
551 }
552};
553
567template <typename T, size_t N>
568class SOSFilter : public Filter<T> {
569 public:
570 SOSFilter(const T (&b)[N][3], const T (&a)[N][3], const T (&gain)[N]) {
571 for (size_t i = 0; i < N; i++)
572 filters[i] = new BiQuadDF2<T>(b[i], a[i], gain[i]);
573 }
574 SOSFilter(const T (&sos)[N][6], const T (&gain)[N]) {
575 for (size_t i = 0; i < N; i++) {
576 T b[3];
577 T a[3];
578 copy(b, &sos[i][0]);
579 copy(a, &sos[i][3]);
580 filters[i] = new BiQuadDF2<T>(b, a, gain[i]);
581 }
582 }
583 SOSFilter(const T (&b)[N][3], const T (&a)[N][2], const T (&gain)[N]) {
584 for (size_t i = 0; i < N; i++)
585 filters[i] = new BiQuadDF2<T>(b[i], a[i], gain[i]);
586 }
587 SOSFilter(const T (&b)[N][3], const T (&a)[N][2]) {
588 for (size_t i = 0; i < N; i++) filters[i] = new BiQuadDF2<T>(b[i], a[i]);
589 }
590 SOSFilter(const T (&b)[N][3], const T (&a)[N][3]) {
591 for (size_t i = 0; i < N; i++) filters[i] = new BiQuadDF2<T>(b[i], a[i]);
592 }
593 SOSFilter(SOSFilter const&) = delete;
594 SOSFilter& operator=(SOSFilter const&) = delete;
596 for (size_t i = 0; i < N; i++) delete filters[i];
597 }
598 void reset() override {
599 for (Filter<T>*& filter : filters) filter->reset();
600 }
601 T process(T value) override {
602 for (Filter<T>*& filter : filters) value = filter->process(value);
603 return value;
604 }
605
606 private:
607 Filter<T>* filters[N];
608 template <size_t M>
609 void copy(T (&dest)[M], const T* src) {
610 for (size_t i = 0; i < M; i++) dest[i] = src[i];
611 }
612};
613
622template <typename T, size_t N>
623class FilterChain : public Filter<T> {
624 public:
625 FilterChain(Filter<T>* (&&filters)[N]) {
626 for (size_t i = 0; i < N; i++) {
627 this->filters[i] = filters[i];
628 }
629 }
630
631 void reset() override {
632 for (Filter<T>*& filter : filters) {
633 if (filter != nullptr) filter->reset();
634 }
635 }
636
637 T process(T value) override {
638 for (Filter<T>*& filter : filters) {
639 if (filter != nullptr) {
640 value = filter->process(value);
641 }
642 }
643 return value;
644 }
645
646 private:
647 Filter<T>* filters[N] = {0};
648};
649
650} // namespace audio_tools
#define PI
Definition AudioEffectsSuite.h:27
Second-order band-pass filter (BiQuad DF2). Passes frequencies near the center frequency and attenuat...
Definition Filter.h:403
BandPassFilter(float frequency, float sampleRate, float q=1.0)
Definition Filter.h:406
void begin(float frequency, float sampleRate, float q=1.0)
Definition Filter.h:410
Second-order IIR filter in Direct Form I. Maintains separate input and output histories (x and y dela...
Definition Filter.h:210
T process(T value) override
Processes the input value and returns the filtered output value.
Definition Filter.h:235
BiQuadDF1(const T(&b)[3], const T(&a)[2])
Definition Filter.h:218
BiQuadDF1(const T(&b)[3], const T(&a)[3], T gain)
Definition Filter.h:226
BiQuadDF1(const T(&b)[3], const T(&a)[3])
Definition Filter.h:212
void reset() override
Definition Filter.h:233
BiQuadDF1(const T(&b)[3], const T(&a)[2], T gain)
Definition Filter.h:220
Second-order IIR filter in Direct Form II. Uses a single delay line, requiring less memory than DF1....
Definition Filter.h:271
T process(T value) override
Processes the input value and returns the filtered output value.
Definition Filter.h:296
T a_2
Definition Filter.h:309
T w_0
Definition Filter.h:314
BiQuadDF2(const T(&b)[3], const T(&a)[3])
Definition Filter.h:273
T w_1
Definition Filter.h:315
T b_1
Definition Filter.h:306
T b_2
Definition Filter.h:307
BiQuadDF2(const T(&b)[3], const T(&a)[3], T gain)
Definition Filter.h:287
T a_1
Definition Filter.h:308
BiQuadDF2(const T(&b)[3], const T(&a)[2])
Definition Filter.h:279
T b_0
Definition Filter.h:305
void reset() override
Definition Filter.h:294
BiQuadDF2(const T(&b)[3], const T(&a)[2], T gain)
Definition Filter.h:281
Finite Impulse Response (FIR) filter. Performs convolution of the input signal with a set of feedforw...
Definition Filter.h:68
T process(T value) override
Processes the input value and returns the filtered output value.
Definition Filter.h:89
void setValues(const T(&b)[B])
Definition Filter.h:76
FIR(const T(&b)[B], const T factor=1.0)
Definition Filter.h:71
void reset() override
Definition Filter.h:84
A cascade of N arbitrary filters applied in series. Each sample is passed through all filters in orde...
Definition Filter.h:623
T process(T value) override
Processes the input value and returns the filtered output value.
Definition Filter.h:637
void reset() override
Definition Filter.h:631
FilterChain(Filter< T > *(&&filters)[N])
Definition Filter.h:625
Abstract filter interface definition. Subclasses implement process() to transform audio samples one a...
Definition Filter.h:27
virtual void reset()
Definition Filter.h:39
Filter(Filter const &)=delete
virtual T process(T in)=0
Processes the input value and returns the filtered output value.
Filter & operator=(Filter const &)=delete
virtual ~Filter()=default
Second-order high-pass filter (BiQuad DF2). Attenuates frequencies below the cutoff frequency....
Definition Filter.h:367
HighPassFilter(float frequency, float sampleRate, float q=0.7071f)
Definition Filter.h:370
void begin(float frequency, float sampleRate, float q=0.7071f)
Definition Filter.h:374
Second-order high-shelf filter (BiQuad DF2). Boosts or cuts frequencies above the shelf frequency by ...
Definition Filter.h:525
HighShelfFilter(float frequency, float sampleRate, float gain, float slope=1.0f)
Definition Filter.h:528
void begin(float frequency, float sampleRate, float gain, float slope=1.0f)
Definition Filter.h:533
Infinite Impulse Response (IIR) filter. Uses both feedforward (b[]) and feedback (a[]) coefficients....
Definition Filter.h:130
T process(T value) override
Processes the input value and returns the filtered output value.
Definition Filter.h:156
IIR(const T(&b)[B], const T(&_a)[A], T factor=1.0)
Definition Filter.h:133
void reset() override
Definition Filter.h:149
Second-order low-pass filter (BiQuad DF2). Attenuates frequencies above the cutoff frequency....
Definition Filter.h:332
void begin(float frequency, float sampleRate, float q=0.7071f)
Definition Filter.h:339
LowPassFilter(float frequency, float sampleRate, float q=0.7071f)
Definition Filter.h:335
Second-order low-shelf filter (BiQuad DF2). Boosts or cuts frequencies below the shelf frequency by t...
Definition Filter.h:478
void begin(float frequency, float sampleRate, float gain, float slope=1.0f)
Definition Filter.h:487
LowShelfFilter(float frequency, float sampleRate, float gain, float slope=1.0f)
Definition Filter.h:481
Passes the input through unchanged. Useful as a placeholder when a Filter is required but no processi...
Definition Filter.h:50
T process(T in) override
Processes the input value and returns the filtered output value.
Definition Filter.h:54
Second-order notch (band-reject) filter (BiQuad DF2). Rejects frequencies near the center frequency a...
Definition Filter.h:440
NotchFilter(float frequency, float sampleRate, float q=1.0)
Definition Filter.h:443
void begin(float frequency, float sampleRate, float q=1.0)
Definition Filter.h:448
Second Order Sections (SOS) filter — a cascade of N BiQuad DF2 stages. Higher-order filters should be...
Definition Filter.h:568
SOSFilter(const T(&b)[N][3], const T(&a)[N][2], const T(&gain)[N])
Definition Filter.h:583
T process(T value) override
Processes the input value and returns the filtered output value.
Definition Filter.h:601
SOSFilter & operator=(SOSFilter const &)=delete
SOSFilter(const T(&b)[N][3], const T(&a)[N][3], const T(&gain)[N])
Definition Filter.h:570
SOSFilter(const T(&b)[N][3], const T(&a)[N][3])
Definition Filter.h:590
SOSFilter(SOSFilter const &)=delete
~SOSFilter()
Definition Filter.h:595
SOSFilter(const T(&sos)[N][6], const T(&gain)[N])
Definition Filter.h:574
SOSFilter(const T(&b)[N][3], const T(&a)[N][2])
Definition Filter.h:587
void reset() override
Definition Filter.h:598
Vector implementation which provides the most important methods as defined by std::vector....
Definition Vector.h:21
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition LMSEchoCancellationStream.h:6