FastLED 3.9.15
Loading...
Searching...
No Matches
biquad_filter_impl.h
Go to the documentation of this file.
1#pragma once
2
3#include "fl/math/math.h"
4
5namespace fl {
6namespace detail {
7
8template <typename T>
10 public:
11 BiquadFilterImpl(T b0, T b1, T b2, T a1, T a2)
12 : mB0(b0), mB1(b1), mB2(b2), mA1(a1), mA2(a2),
13 mX1(T(0)), mX2(T(0)), mY1(T(0)), mY2(T(0)), mLastValue(T(0)) {}
14
15 // Butterworth low-pass: -12 dB/octave roll-off above cutoff_hz.
16 static BiquadFilterImpl butterworth(float cutoff_hz, float sample_rate) {
17 float omega = 2.0f * static_cast<float>(FL_PI) * cutoff_hz / sample_rate;
18 float sn = fl::sinf(omega);
19 float cs = fl::cosf(omega);
20 float alpha = sn * 0.7071067811865476f;
21 float a0 = 1.0f + alpha;
22 float b0f = (1.0f - cs) * 0.5f / a0;
23 float b1f = (1.0f - cs) / a0;
24 float b2f = b0f;
25 float a1f = (-2.0f * cs) / a0;
26 float a2f = (1.0f - alpha) / a0;
27 return BiquadFilterImpl(T(b0f), T(b1f), T(b2f), T(a1f), T(a2f));
28 }
29
30 // Butterworth high-pass: -12 dB/octave roll-off below cutoff_hz.
31 static BiquadFilterImpl highpass(float cutoff_hz, float sample_rate) {
32 float omega = 2.0f * static_cast<float>(FL_PI) * cutoff_hz / sample_rate;
33 float sn = fl::sinf(omega);
34 float cs = fl::cosf(omega);
35 float alpha = sn * 0.7071067811865476f;
36 float a0 = 1.0f + alpha;
37 float b0f = (1.0f + cs) * 0.5f / a0;
38 float b1f = -(1.0f + cs) / a0;
39 float b2f = b0f;
40 float a1f = (-2.0f * cs) / a0;
41 float a2f = (1.0f - alpha) / a0;
42 return BiquadFilterImpl(T(b0f), T(b1f), T(b2f), T(a1f), T(a2f));
43 }
44
45 // Band-pass filter centered at center_hz with given Q factor.
46 // Q controls bandwidth: higher Q = narrower band. Q=0.707 is broadband.
47 static BiquadFilterImpl bandpass(float center_hz, float sample_rate,
48 float q = 1.0f) {
49 float omega = 2.0f * static_cast<float>(FL_PI) * center_hz / sample_rate;
50 float sn = fl::sinf(omega);
51 float cs = fl::cosf(omega);
52 float alpha = sn / (2.0f * q);
53 float a0 = 1.0f + alpha;
54 float b0f = alpha / a0;
55 float b1f = 0.0f;
56 float b2f = -alpha / a0;
57 float a1f = (-2.0f * cs) / a0;
58 float a2f = (1.0f - alpha) / a0;
59 return BiquadFilterImpl(T(b0f), T(b1f), T(b2f), T(a1f), T(a2f));
60 }
61
62 // Notch (band-reject) filter at center_hz with given Q factor.
63 // Removes a narrow frequency band. Q=30 is good for 50/60 Hz hum.
64 static BiquadFilterImpl notch(float center_hz, float sample_rate,
65 float q = 1.0f) {
66 float omega = 2.0f * static_cast<float>(FL_PI) * center_hz / sample_rate;
67 float sn = fl::sinf(omega);
68 float cs = fl::cosf(omega);
69 float alpha = sn / (2.0f * q);
70 float a0 = 1.0f + alpha;
71 float b0f = 1.0f / a0;
72 float b1f = (-2.0f * cs) / a0;
73 float b2f = b0f;
74 float a1f = b1f;
75 float a2f = (1.0f - alpha) / a0;
76 return BiquadFilterImpl(T(b0f), T(b1f), T(b2f), T(a1f), T(a2f));
77 }
78
79 T update(T input) {
80 T output = mB0 * input + mB1 * mX1 + mB2 * mX2
81 - mA1 * mY1 - mA2 * mY2;
82 mX2 = mX1;
83 mX1 = input;
84 mY2 = mY1;
85 mY1 = output;
86 mLastValue = output;
87 return output;
88 }
89
90 T value() const { return mLastValue; }
91
92 void reset() {
93 mX1 = mX2 = mY1 = mY2 = mLastValue = T(0);
94 }
95
96 private:
97 T mB0, mB1, mB2, mA1, mA2;
98 T mX1, mX2;
99 T mY1, mY2;
101};
102
103} // namespace detail
104} // namespace fl
static BiquadFilterImpl highpass(float cutoff_hz, float sample_rate)
static BiquadFilterImpl butterworth(float cutoff_hz, float sample_rate)
static BiquadFilterImpl bandpass(float center_hz, float sample_rate, float q=1.0f)
BiquadFilterImpl(T b0, T b1, T b2, T a1, T a2)
static BiquadFilterImpl notch(float center_hz, float sample_rate, float q=1.0f)
#define FL_PI
Definition math.h:26
Compile-time linker keep-alive hook for a single fl::Bus.
Definition bus_traits.h:48
float sinf(float value) FL_NOEXCEPT
Definition math.h:352
float cosf(float value) FL_NOEXCEPT
Definition math.h:358
Base definition for an LED controller.
Definition crgb.hpp:179