One Pole Low Pass
Overview
Basic one pole low-pass filter serves as an important building block due to its utility in a vast number of applications including noise reduction, signal smoothing, and extracting relevant information from a signal. The 6dB/octave slope of the single pole filter is suitable for many non-critical use-cases and its simplicity makes it computationally efficient.
q/fx/lowpass.hpp also holds fixed_pt_leaky_integrator, which does the work in integers, for targets where floating point is slow or absent. See Fixed Point Leaky Integrator.
Declaration
struct one_pole_lowpass
{
one_pole_lowpass(float a);
one_pole_lowpass(frequency f, float sps);
float operator()(float s);
float operator()() const;
one_pole_lowpass& operator=(float y);
void cutoff(frequency f, float sps);
float y = 0.0f, a;
};
Expressions
Notation
lp,a,b-
Objects of type
one_pole_lowpass. f-
Object of type
frequencyrepresenting the cutoff frequency. sps-
Floating point value representing samples per second.
s-
Input sample.
c-
Floating point coefficient, 0 to 1.
Constructors and Assignment
| Expression | Semantics |
|---|---|
|
Construct a |
|
Construct a |
|
Copy construct a |
|
Assign |
|
Set the latest result to |
| C++ brace initialization may also be used. |
Function Call
| Expression | Semantics | Return Type |
|---|---|---|
|
Return the latest result. |
|
|
Process the input sample, |
|
Mutators
| Expression | Semantics | Return Type |
|---|---|---|
|
Set the cutoff frequency given
|
|
Accessors
| Expression | Semantics | Return Type |
|---|---|---|
|
The latest result. |
|
|
The coefficient. |
|
Example
Taming zipper noise on a gain control. A control that arrives in steps, say once per audio block, is heard as a buzz at the block rate. A low-pass at a few tens of hertz turns each step into a short glide:
q::one_pole_lowpass smooth{30_Hz, sps};
// ... per sample:
float out = s * smooth(gain);
Fixed Point Leaky Integrator
fixed_pt_leaky_integrator<k, T> computes y += s - y / k in the integer type T, int by default. Its pole is 1 - 1 / k, so k sets the cutoff, roughly sps / (2π k) for large k. At 48 kHz, k = 16 gives the pole of a 493 Hz cutoff. Make k a power of two and the division compiles to a shift.
The filter’s gain is k: a steady input s settles at k * s (within rounding). Divide the result by k, published as gain, to read it at the input’s scale. For the same reason, a state assigned to y must be multiplied by k first.
Declaration
template <int k, typename T = int>
struct fixed_pt_leaky_integrator
{
using self_type = fixed_pt_leaky_integrator;
typedef T result_type;
static constexpr int gain = k;
T operator()(T s);
T operator()() const;
self_type& operator=(float y);
T y = 0;
};
Expressions
Notation
F-
A
fixed_pt_leaky_integrator<k, T>type. fi-
Object of type
F. s-
Input sample of type
T. v-
A state, already scaled by
k.