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
21namespace audio_tools {
22
31template <typename T>
32class Filter {
33 public:
34 // construct without coefs
35 Filter() = default;
36 virtual ~Filter() = default;
37 Filter(Filter const&) = delete;
38 Filter& operator=(Filter const&) = delete;
40 virtual T process(T in) = 0;
44 virtual void reset() {}
45};
46
54template <typename T>
55class NoFilter : public Filter<T> {
56 public:
57 // construct without coefs
58 NoFilter() = default;
59 T process(T in) override { return in; }
60};
61
72template <typename T>
73class FIR : public Filter<T> {
74 public:
75 template <size_t B>
76 FIR(const T (&b)[B], const T factor = 1.0) : lenB(B), factor(factor) {
77 setValues(b);
78 }
79
80 template <size_t B>
81 void setValues(const T (&b)[B]) {
82 x.resize(lenB);
83 coeff_b.resize(2 * lenB - 1);
84 for (uint16_t i = 0; i < 2 * lenB - 1; i++) {
85 coeff_b[i] = b[(2 * lenB - 1 - i) % lenB];
86 }
87 }
88
89 void reset() override {
90 i_b = 0;
91 for (uint16_t i = 0; i < lenB; i++) x[i] = 0;
92 }
93
94 T process(T value) override {
95 x[i_b] = value;
96 T b_terms = 0;
97 T* b_shift = &coeff_b[lenB - i_b - 1];
98 for (uint16_t i = 0; i < lenB; i++) {
99 b_terms += b_shift[i] * x[i];
100 }
101 i_b++;
102 if (i_b == lenB) i_b = 0;
103
104#ifdef USE_TYPETRAITS
105 if (!(std::is_same<T, float>::value || std::is_same<T, double>::value)) {
106 b_terms = b_terms / factor;
107 }
108#else
109 if (factor != 1.0) {
110 b_terms = b_terms / factor;
111 }
112#endif
113 return b_terms;
114 }
115
116 private:
117 const uint16_t lenB;
118 uint16_t i_b = 0;
119 Vector<T> x;
120 Vector<T> coeff_b;
121 T factor;
122};
123
134template <typename T>
135class IIR : public Filter<T> {
136 public:
137 template <size_t B, size_t A>
138 IIR(const T (&b)[B], const T (&_a)[A], T factor = 1.0)
139 : factor(factor), lenB(B), lenA(A - 1) {
140 x.resize(lenB);
141 y.resize(lenA);
142 coeff_b.resize(2 * lenB - 1);
143 coeff_a.resize(2 * lenA - 1);
144 T a0 = _a[0];
145 const T* a = &_a[1];
146 for (uint16_t i = 0; i < 2 * lenB - 1; i++) {
147 coeff_b[i] = b[(2 * lenB - 1 - i) % lenB] / a0;
148 }
149 for (uint16_t i = 0; i < 2 * lenA - 1; i++) {
150 coeff_a[i] = a[(2 * lenA - 2 - i) % lenA] / a0;
151 }
152 }
153
154 void reset() override {
155 i_b = 0;
156 i_a = 0;
157 for (uint16_t i = 0; i < lenB; i++) x[i] = 0;
158 for (uint16_t i = 0; i < lenA; i++) y[i] = 0;
159 }
160
161 T process(T value) override {
162 x[i_b] = value;
163 T b_terms = 0;
164 T* b_shift = &coeff_b[lenB - i_b - 1];
165
166 T a_terms = 0;
167 T* a_shift = &coeff_a[lenA - i_a - 1];
168
169 for (uint16_t i = 0; i < lenB; i++) {
170 b_terms += x[i] * b_shift[i];
171 }
172 for (uint16_t i = 0; i < lenA; i++) {
173 a_terms += y[i] * a_shift[i];
174 }
175
176 T filtered = b_terms - a_terms;
177 y[i_a] = filtered;
178 i_b++;
179 if (i_b == lenB) i_b = 0;
180 i_a++;
181 if (i_a == lenA) i_a = 0;
182
183#ifdef USE_TYPETRAITS
184 if (!(std::is_same<T, float>::value || std::is_same<T, double>::value)) {
185 filtered = filtered / factor;
186 }
187#else
188 if (factor != 1.0) {
189 filtered = filtered / factor;
190 }
191#endif
192 return filtered;
193 }
194
195 private:
196 T factor;
197 const uint16_t lenB, lenA;
198 uint16_t i_b = 0, i_a = 0;
199 Vector<T> x;
200 Vector<T> y;
201 Vector<T> coeff_b;
202 Vector<T> coeff_a;
203};
204
214template <typename T>
215class BiQuadDF1 : public Filter<T> {
216 public:
217 BiQuadDF1(const T (&b)[3], const T (&a)[3])
218 : b_0(b[0] / a[0]),
219 b_1(b[1] / a[0]),
220 b_2(b[2] / a[0]),
221 a_1(a[1] / a[0]),
222 a_2(a[2] / a[0]) {}
223 BiQuadDF1(const T (&b)[3], const T (&a)[2])
224 : b_0(b[0]), b_1(b[1]), b_2(b[2]), a_1(a[0]), a_2(a[1]) {}
225 BiQuadDF1(const T (&b)[3], const T (&a)[2], T gain)
226 : b_0(gain * b[0]),
227 b_1(gain * b[1]),
228 b_2(gain * b[2]),
229 a_1(a[0]),
230 a_2(a[1]) {}
231 BiQuadDF1(const T (&b)[3], const T (&a)[3], T gain)
232 : b_0(gain * b[0] / a[0]),
233 b_1(gain * b[1] / a[0]),
234 b_2(gain * b[2] / a[0]),
235 a_1(a[1] / a[0]),
236 a_2(a[2] / a[0]) {}
237
238 void reset() override { x_0 = x_1 = y_1 = y_2 = 0; }
239
240 T process(T value) override {
241 T x_2 = x_1;
242 x_1 = x_0;
243 x_0 = value;
244 T b_terms = x_0 * b_0 + x_1 * b_1 + x_2 * b_2;
245 T a_terms = y_1 * a_1 + y_2 * a_2;
246 y_2 = y_1;
247 y_1 = b_terms - a_terms;
248 return y_1;
249 }
250
251 private:
252 T b_0;
253 T b_1;
254 T b_2;
255 T a_1;
256 T a_2;
257
258 T x_0 = 0;
259 T x_1 = 0;
260 T y_1 = 0;
261 T y_2 = 0;
262};
263
275template <typename T>
276class BiQuadDF2 : public Filter<T> {
277 public:
278 BiQuadDF2(const T (&b)[3], const T (&a)[3])
279 : b_0(b[0] / a[0]),
280 b_1(b[1] / a[0]),
281 b_2(b[2] / a[0]),
282 a_1(a[1] / a[0]),
283 a_2(a[2] / a[0]) {}
284 BiQuadDF2(const T (&b)[3], const T (&a)[2])
285 : b_0(b[0]), b_1(b[1]), b_2(b[2]), a_1(a[0]), a_2(a[1]) {}
286 BiQuadDF2(const T (&b)[3], const T (&a)[2], T gain)
287 : b_0(gain * b[0]),
288 b_1(gain * b[1]),
289 b_2(gain * b[2]),
290 a_1(a[0]),
291 a_2(a[1]) {}
292 BiQuadDF2(const T (&b)[3], const T (&a)[3], T gain)
293 : b_0(gain * b[0] / a[0]),
294 b_1(gain * b[1] / a[0]),
295 b_2(gain * b[2] / a[0]),
296 a_1(a[1] / a[0]),
297 a_2(a[2] / a[0]) {}
298
299 void reset() override { w_0 = w_1 = 0; }
300
301 T process(T value) override {
302 T w_2 = w_1;
303 w_1 = w_0;
304 w_0 = value - a_1 * w_1 - a_2 * w_2;
305 T y = b_0 * w_0 + b_1 * w_1 + b_2 * w_2;
306 return y;
307 }
308
309 protected:
310 T b_0 = 0;
311 T b_1 = 0;
312 T b_2 = 0;
313 T a_1 = 0;
314 T a_2 = 0;
315
316 // allow constructor w/o parameter in subclasses
317 BiQuadDF2() = default;
318
319 T w_0 = 0;
320 T w_1 = 0;
321};
322
336template <typename T>
337class LowPassFilter : public BiQuadDF2<T> {
338 public:
339 LowPassFilter() = default;
340 LowPassFilter(float frequency, float sampleRate, float q = 0.7071f)
341 : BiQuadDF2<T>() {
342 begin(frequency, sampleRate, q);
343 }
344 void begin(float frequency, float sampleRate, float q = 0.7071f) {
345 T w0 = frequency * (2.0f * PI / sampleRate);
346 T sinW0 = sin(w0);
347 T alpha = sinW0 / ((float)q * 2.0);
348 T cosW0 = cos(w0);
349 T scale = 1.0 / (1.0 + alpha);
350 BiQuadDF2<T>::b_0 = ((1.0 - cosW0) / 2.0) * scale;
351 BiQuadDF2<T>::b_1 = (1.0 - cosW0) * scale;
353 BiQuadDF2<T>::a_1 = (-2.0 * cosW0) * scale;
354 BiQuadDF2<T>::a_2 = (1.0 - alpha) * scale;
355 }
356};
357
371template <typename T>
372class HighPassFilter : public BiQuadDF2<T> {
373 public:
374 HighPassFilter() = default;
375 HighPassFilter(float frequency, float sampleRate, float q = 0.7071f)
376 : BiQuadDF2<T>() {
377 begin(frequency, sampleRate, q);
378 }
379 void begin(float frequency, float sampleRate, float q = 0.7071f) {
380 T w0 = frequency * (2.0f * PI / sampleRate);
381 T sinW0 = sin(w0);
382 T alpha = sinW0 / ((float)q * 2.0);
383 T cosW0 = cos(w0);
384 T scale = 1.0 / (1.0 + alpha);
385 BiQuadDF2<T>::b_0 = ((1.0 + cosW0) / 2.0) * scale;
386 BiQuadDF2<T>::b_1 = -(1.0 + cosW0) * scale;
388 BiQuadDF2<T>::a_1 = (-2.0 * cosW0) * scale;
389 BiQuadDF2<T>::a_2 = (1.0 - alpha) * scale;
390 }
391};
392
407template <typename T>
408class BandPassFilter : public BiQuadDF2<T> {
409 public:
410 BandPassFilter() = default;
411 BandPassFilter(float frequency, float sampleRate, float q = 1.0)
412 : BiQuadDF2<T>() {
413 begin(frequency, sampleRate, q);
414 }
415 void begin(float frequency, float sampleRate, float q = 1.0) {
416 T w0 = frequency * (2.0f * PI / sampleRate);
417 T sinW0 = sin(w0);
418 T alpha = sinW0 / ((T)q * 2.0);
419 T cosW0 = cos(w0);
420 T scale = 1.0 / (1.0 + alpha);
421 BiQuadDF2<T>::b_0 = alpha * scale;
423 BiQuadDF2<T>::b_2 = (-alpha) * scale;
424 BiQuadDF2<T>::a_1 = (-2.0 * cosW0) * scale;
425 BiQuadDF2<T>::a_2 = (1.0 - alpha) * scale;
426 }
427};
428
444template <typename T>
445class NotchFilter : public BiQuadDF2<T> {
446 public:
447 NotchFilter() = default;
448 NotchFilter(float frequency, float sampleRate, float q = 1.0)
449 : BiQuadDF2<T>() {
450 begin(frequency, sampleRate, q);
451 }
452
453 void begin(float frequency, float sampleRate, float q = 1.0) {
454 T w0 = frequency * (2.0f * PI / sampleRate);
455 T sinW0 = sin(w0);
456 T alpha = sinW0 / ((float)q * 2.0);
457 T cosW0 = cos(w0);
458 T scale = 1.0 / (1.0 + alpha);
459 BiQuadDF2<T>::b_0 = scale;
460 BiQuadDF2<T>::b_1 = (-2.0 * cosW0) * scale;
462 BiQuadDF2<T>::a_1 = (-2.0 * cosW0) * scale;
463 BiQuadDF2<T>::a_2 = (1.0 - alpha) * scale;
464 }
465};
466
482template <typename T>
483class LowShelfFilter : public BiQuadDF2<T> {
484 public:
485 LowShelfFilter() = default;
486 LowShelfFilter(float frequency, float sampleRate, float gain,
487 float slope = 1.0f)
488 : BiQuadDF2<T>() {
489 begin(frequency, sampleRate, gain, slope);
490 }
491
492 void begin(float frequency, float sampleRate, float gain,
493 float slope = 1.0f) {
494 T a = pow(10.0, gain / 40.0f);
495 T w0 = frequency * (2.0f * PI / sampleRate);
496 T sinW0 = sin(w0);
497 // float alpha = (sinW0 * sqrt((a+1/a)*(1/slope-1)+2) ) / 2.0;
498 T cosW0 = cos(w0);
499 // generate three helper-values (intermediate results):
500 T sinsq = sinW0 *
501 sqrt((pow(a, 2.0) + 1.0) * (1.0 / (float)slope - 1.0) + 2.0 * a);
502 T aMinus = (a - 1.0) * cosW0;
503 T aPlus = (a + 1.0) * cosW0;
504 T scale = 1.0 / ((a + 1.0) + aMinus + sinsq);
505 BiQuadDF2<T>::b_0 = a * ((a + 1.0) - aMinus + sinsq) * scale;
506 BiQuadDF2<T>::b_1 = 2.0 * a * ((a - 1.0) - aPlus) * scale;
507 BiQuadDF2<T>::b_2 = a * ((a + 1.0) - aMinus - sinsq) * scale;
508 BiQuadDF2<T>::a_1 = -2.0 * ((a - 1.0) + aPlus) * scale;
509 BiQuadDF2<T>::a_2 = ((a + 1.0) + aMinus - sinsq) * scale;
510 }
511};
512
529template <typename T>
530class HighShelfFilter : public BiQuadDF2<T> {
531 public:
532 HighShelfFilter() = default;
533 HighShelfFilter(float frequency, float sampleRate, float gain,
534 float slope = 1.0f)
535 : BiQuadDF2<T>() {
536 begin(frequency, sampleRate, gain, slope);
537 }
538 void begin(float frequency, float sampleRate, float gain,
539 float slope = 1.0f) {
540 T a = pow(10.0, gain / 40.0f);
541 T w0 = frequency * (2.0f * PI / sampleRate);
542 T sinW0 = sin(w0);
543 // float alpha = (sinW0 * sqrt((a+1/a)*(1/slope-1)+2) ) / 2.0;
544 T cosW0 = cos(w0);
545 // generate three helper-values (intermediate results):
546 T sinsq = sinW0 *
547 sqrt((pow(a, 2.0) + 1.0) * (1.0 / (float)slope - 1.0) + 2.0 * a);
548 T aMinus = (a - 1.0) * cosW0;
549 T aPlus = (a + 1.0) * cosW0;
550 T scale = 1.0 / ((a + 1.0) - aMinus + sinsq);
551 BiQuadDF2<T>::b_0 = a * ((a + 1.0) + aMinus + sinsq) * scale;
552 BiQuadDF2<T>::b_1 = -2.0 * a * ((a - 1.0) + aPlus) * scale;
553 BiQuadDF2<T>::b_2 = a * ((a + 1.0) + aMinus - sinsq) * scale;
554 BiQuadDF2<T>::a_1 = 2.0 * ((a - 1.0) - aPlus) * scale;
555 BiQuadDF2<T>::a_2 = ((a + 1.0) - aMinus - sinsq) * scale;
556 }
557};
558
572template <typename T, size_t N>
573class SOSFilter : public Filter<T> {
574 public:
575 SOSFilter(const T (&b)[N][3], const T (&a)[N][3], const T (&gain)[N]) {
576 for (size_t i = 0; i < N; i++)
577 filters[i] = new BiQuadDF2<T>(b[i], a[i], gain[i]);
578 }
579 SOSFilter(const T (&sos)[N][6], const T (&gain)[N]) {
580 for (size_t i = 0; i < N; i++) {
581 T b[3];
582 T a[3];
583 copy(b, &sos[i][0]);
584 copy(a, &sos[i][3]);
585 filters[i] = new BiQuadDF2<T>(b, a, gain[i]);
586 }
587 }
588 SOSFilter(const T (&b)[N][3], const T (&a)[N][2], const T (&gain)[N]) {
589 for (size_t i = 0; i < N; i++)
590 filters[i] = new BiQuadDF2<T>(b[i], a[i], gain[i]);
591 }
592 SOSFilter(const T (&b)[N][3], const T (&a)[N][2]) {
593 for (size_t i = 0; i < N; i++) filters[i] = new BiQuadDF2<T>(b[i], a[i]);
594 }
595 SOSFilter(const T (&b)[N][3], const T (&a)[N][3]) {
596 for (size_t i = 0; i < N; i++) filters[i] = new BiQuadDF2<T>(b[i], a[i]);
597 }
598 SOSFilter(SOSFilter const&) = delete;
599 SOSFilter& operator=(SOSFilter const&) = delete;
601 for (size_t i = 0; i < N; i++) delete filters[i];
602 }
603 void reset() override {
604 for (Filter<T>*& filter : filters) filter->reset();
605 }
606 T process(T value) override {
607 for (Filter<T>*& filter : filters) value = filter->process(value);
608 return value;
609 }
610
611 private:
612 Filter<T>* filters[N];
613 template <size_t M>
614 void copy(T (&dest)[M], const T* src) {
615 for (size_t i = 0; i < M; i++) dest[i] = src[i];
616 }
617};
618
627template <typename T, size_t N>
628class FilterChain : public Filter<T> {
629 public:
630 FilterChain(Filter<T>* (&&filters)[N]) {
631 for (size_t i = 0; i < N; i++) {
632 this->filters[i] = filters[i];
633 }
634 }
635
636 void reset() override {
637 for (Filter<T>*& filter : filters) {
638 if (filter != nullptr) filter->reset();
639 }
640 }
641
642 T process(T value) override {
643 for (Filter<T>*& filter : filters) {
644 if (filter != nullptr) {
645 value = filter->process(value);
646 }
647 }
648 return value;
649 }
650
651 private:
652 Filter<T>* filters[N] = {0};
653};
654
655} // 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:408
BandPassFilter(float frequency, float sampleRate, float q=1.0)
Definition Filter.h:411
void begin(float frequency, float sampleRate, float q=1.0)
Definition Filter.h:415
Second-order IIR filter in Direct Form I. Maintains separate input and output histories (x and y dela...
Definition Filter.h:215
T process(T value) override
Processes the input value and returns the filtered output value.
Definition Filter.h:240
BiQuadDF1(const T(&b)[3], const T(&a)[2])
Definition Filter.h:223
BiQuadDF1(const T(&b)[3], const T(&a)[3], T gain)
Definition Filter.h:231
BiQuadDF1(const T(&b)[3], const T(&a)[3])
Definition Filter.h:217
void reset() override
Definition Filter.h:238
BiQuadDF1(const T(&b)[3], const T(&a)[2], T gain)
Definition Filter.h:225
Second-order IIR filter in Direct Form II. Uses a single delay line, requiring less memory than DF1....
Definition Filter.h:276
T process(T value) override
Processes the input value and returns the filtered output value.
Definition Filter.h:301
T a_2
Definition Filter.h:314
T w_0
Definition Filter.h:319
BiQuadDF2(const T(&b)[3], const T(&a)[3])
Definition Filter.h:278
T w_1
Definition Filter.h:320
T b_1
Definition Filter.h:311
T b_2
Definition Filter.h:312
BiQuadDF2(const T(&b)[3], const T(&a)[3], T gain)
Definition Filter.h:292
T a_1
Definition Filter.h:313
BiQuadDF2(const T(&b)[3], const T(&a)[2])
Definition Filter.h:284
T b_0
Definition Filter.h:310
void reset() override
Definition Filter.h:299
BiQuadDF2(const T(&b)[3], const T(&a)[2], T gain)
Definition Filter.h:286
Finite Impulse Response (FIR) filter. Performs convolution of the input signal with a set of feedforw...
Definition Filter.h:73
T process(T value) override
Processes the input value and returns the filtered output value.
Definition Filter.h:94
void setValues(const T(&b)[B])
Definition Filter.h:81
FIR(const T(&b)[B], const T factor=1.0)
Definition Filter.h:76
void reset() override
Definition Filter.h:89
A cascade of N arbitrary filters applied in series. Each sample is passed through all filters in orde...
Definition Filter.h:628
T process(T value) override
Processes the input value and returns the filtered output value.
Definition Filter.h:642
void reset() override
Definition Filter.h:636
FilterChain(Filter< T > *(&&filters)[N])
Definition Filter.h:630
Abstract filter interface definition. Subclasses implement process() to transform audio samples one a...
Definition Filter.h:32
virtual void reset()
Definition Filter.h:44
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:372
HighPassFilter(float frequency, float sampleRate, float q=0.7071f)
Definition Filter.h:375
void begin(float frequency, float sampleRate, float q=0.7071f)
Definition Filter.h:379
Second-order high-shelf filter (BiQuad DF2). Boosts or cuts frequencies above the shelf frequency by ...
Definition Filter.h:530
HighShelfFilter(float frequency, float sampleRate, float gain, float slope=1.0f)
Definition Filter.h:533
void begin(float frequency, float sampleRate, float gain, float slope=1.0f)
Definition Filter.h:538
Infinite Impulse Response (IIR) filter. Uses both feedforward (b[]) and feedback (a[]) coefficients....
Definition Filter.h:135
T process(T value) override
Processes the input value and returns the filtered output value.
Definition Filter.h:161
IIR(const T(&b)[B], const T(&_a)[A], T factor=1.0)
Definition Filter.h:138
void reset() override
Definition Filter.h:154
Second-order low-pass filter (BiQuad DF2). Attenuates frequencies above the cutoff frequency....
Definition Filter.h:337
void begin(float frequency, float sampleRate, float q=0.7071f)
Definition Filter.h:344
LowPassFilter(float frequency, float sampleRate, float q=0.7071f)
Definition Filter.h:340
Second-order low-shelf filter (BiQuad DF2). Boosts or cuts frequencies below the shelf frequency by t...
Definition Filter.h:483
void begin(float frequency, float sampleRate, float gain, float slope=1.0f)
Definition Filter.h:492
LowShelfFilter(float frequency, float sampleRate, float gain, float slope=1.0f)
Definition Filter.h:486
Passes the input through unchanged. Useful as a placeholder when a Filter is required but no processi...
Definition Filter.h:55
T process(T in) override
Processes the input value and returns the filtered output value.
Definition Filter.h:59
Second-order notch (band-reject) filter (BiQuad DF2). Rejects frequencies near the center frequency a...
Definition Filter.h:445
NotchFilter(float frequency, float sampleRate, float q=1.0)
Definition Filter.h:448
void begin(float frequency, float sampleRate, float q=1.0)
Definition Filter.h:453
Second Order Sections (SOS) filter — a cascade of N BiQuad DF2 stages. Higher-order filters should be...
Definition Filter.h:573
SOSFilter(const T(&b)[N][3], const T(&a)[N][2], const T(&gain)[N])
Definition Filter.h:588
T process(T value) override
Processes the input value and returns the filtered output value.
Definition Filter.h:606
SOSFilter & operator=(SOSFilter const &)=delete
SOSFilter(const T(&b)[N][3], const T(&a)[N][3], const T(&gain)[N])
Definition Filter.h:575
SOSFilter(const T(&b)[N][3], const T(&a)[N][3])
Definition Filter.h:595
SOSFilter(SOSFilter const &)=delete
~SOSFilter()
Definition Filter.h:600
SOSFilter(const T(&sos)[N][6], const T(&gain)[N])
Definition Filter.h:579
SOSFilter(const T(&b)[N][3], const T(&a)[N][2])
Definition Filter.h:592
void reset() override
Definition Filter.h:603
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 AudioCodecsBase.h:10
size_t writeData(Print *p_out, T *data, int samples, int maxSamples=512)
Definition AudioTypes.h:508