Sound Byte Libs 29c5ff3
C++ firmware library for audio applications on 32-bit ARM Cortex-M processors
Loading...
Searching...
No Matches
one_pole.hpp
Go to the documentation of this file.
1// sbl/dsp/one_pole.hpp — Single-pole IIR filter
2//
3// Classic one-pole lowpass: y[n] = a * x[n] + (1-a) * y[n-1]
4//
5// Float-native. Coefficient range [0.0, 1.0]: 0 = hold, 1 = passthrough.
6// Cold-path set_frequency() computes coefficient from cutoff frequency.
7//
8// Usage:
9// sbl::dsp::OnePole lp;
10// lp.set_coefficient(0.125f); // Direct coefficient
11// lp.set_frequency(1000.0f, 48000); // 1 kHz at 48 kHz
12// float y = lp.process(x); // Single sample
13// lp.process(buf, frames); // In-place block
14
15#pragma once
16
17#include <cstdint>
18
19namespace sbl::dsp {
20
21class OnePole {
22public:
23 /// @note All public methods are ISR-safe — bounded computation, no I/O.
24
25 /**
26 * @brief Set filter coefficient directly
27 *
28 * a = 0.0 → no filtering (hold previous output), 1.0 → full passthrough.
29 * For audio-rate smoothing: ~0.03-0.12. For parameter smoothing: ~0.002-0.008.
30 */
31 void set_coefficient(float a) { coeff_ = a; }
32
33 /**
34 * @brief Compute coefficient from cutoff frequency (cold path)
35 *
36 * Uses approximation of 1 - exp(-2pi * fc / sr).
37 *
38 * @param freq_hz Cutoff frequency in Hz
39 * @param sr Sample rate
40 */
41 void set_frequency(float freq_hz, uint32_t sr = 48000) {
42 float w = 6.2831853f * freq_hz / static_cast<float>(sr);
43 if (w >= 1.0f) {
44 coeff_ = 1.0f;
45 } else {
46 // Padé-like: exp(-x) ≈ 1/(1 + x + x²/2 + x³/6)
47 float x2 = w * w;
48 float denom = 1.0f + w + x2 * 0.5f + x2 * w * 0.166667f;
49 coeff_ = 1.0f - 1.0f / denom;
50 }
51 }
52
53 /**
54 * @brief Process a single sample
55 * @param x Input sample
56 * @return Filtered output
57 */
58 float process(float x) {
59 // y = a*x + (1-a)*y = y + a*(x - y)
60 state_ += coeff_ * (x - state_);
61 return state_;
62 }
63
64 /**
65 * @brief Process a block of samples in-place
66 * @param buf Audio buffer (modified in-place)
67 * @param frames Number of samples
68 */
69 void process(float* buf, uint16_t frames) {
70 for (uint16_t i = 0; i < frames; ++i) {
71 buf[i] = process(buf[i]);
72 }
73 }
74
75 /** @brief Current filter state (last output) */
76 float value() const { return state_; }
77
78 /** @brief Current coefficient */
79 float coefficient() const { return coeff_; }
80
81 /** @brief Reset filter state to zero */
82 void reset() { state_ = 0.0f; }
83
84 /** @brief Reset filter state to a specific value */
85 void reset(float initial) { state_ = initial; }
86
87private:
88 float coeff_ = 0.0f;
89 float state_ = 0.0f;
90};
91
92} // namespace sbl::dsp
void reset(float initial)
Reset filter state to a specific value.
Definition one_pole.hpp:85
float value() const
Current filter state (last output)
Definition one_pole.hpp:76
void reset()
Reset filter state to zero.
Definition one_pole.hpp:82
void process(float *buf, uint16_t frames)
Process a block of samples in-place.
Definition one_pole.hpp:69
float process(float x)
Process a single sample.
Definition one_pole.hpp:58
float coefficient() const
Current coefficient.
Definition one_pole.hpp:79
void set_coefficient(float a)
Set filter coefficient directly.
Definition one_pole.hpp:31
void set_frequency(float freq_hz, uint32_t sr=48000)
Compute coefficient from cutoff frequency (cold path)
Definition one_pole.hpp:41
DSP atoms for audio signal processing.
Definition allpass.hpp:22