Sound Byte Libs 0.5.1-121-g3358a44
C++ firmware library for audio applications on 32-bit ARM Cortex-M processors
Loading...
Searching...
No Matches
allpass_filter.hpp
Go to the documentation of this file.
1// sbl/dsp/primitives/allpass_filter.hpp — Schroeder allpass filter
2//
3// y[n] = -g*x[n] + x[n-d] + g*y[n-d]
4//
5// Disperses energy in time without changing frequency magnitude response.
6// Core building block for reverb diffusion networks.
7//
8// Float-domain processing — STM32H7 (Cortex-M7) has hardware FPU with
9// single-cycle float ops.
10//
11// Usage:
12// float buf[256] = {};
13// sbl::dsp::AllpassFilter ap;
14// ap.init(buf, 256);
15// ap.set_feedback(0.5f);
16// float out = ap.process(in);
17
18#ifndef SBL_DSP_PRIMITIVES_ALLPASS_FILTER_HPP_
19#define SBL_DSP_PRIMITIVES_ALLPASS_FILTER_HPP_
20
21#include <cstdint>
22
24
26public:
27 /// @note All public methods are ISR-safe — bounded computation, no I/O.
28
29 /**
30 * @brief Construct with caller-provided buffer
31 * @param buffer Float buffer (must outlive the AllpassFilter)
32 * @param delay Delay length in samples (buffer size)
33 */
34 AllpassFilter(float* buffer, uint32_t delay)
35 : buffer_(buffer), delay_(delay), write_pos_(0) {}
36
37 /// Default constructor for array initialization (must call init() before use)
38 AllpassFilter() = default;
39
40 /**
41 * @brief Initialize after default construction
42 * @param buffer Float buffer (must outlive the AllpassFilter)
43 * @param delay Delay length in samples
44 */
45 void init(float* buffer, uint32_t delay) {
46 buffer_ = buffer;
47 delay_ = delay;
48 write_pos_ = 0;
49 }
50
51 /**
52 * @brief Process a single sample
53 *
54 * Schroeder allpass: y = -g*x + x[n-d] + g*y[n-d]
55 * where the buffer stores the output history.
56 *
57 * @param x Input sample in [-1.0, 1.0]
58 * @return Allpass-filtered output in [-1.0, 1.0]
59 */
60 float process(float x) {
61 float delayed = buffer_[write_pos_];
62
63 float output = -feedback_ * x + delayed;
64 float to_buffer = x + feedback_ * output;
65
66 buffer_[write_pos_] = to_buffer;
67
68 ++write_pos_;
69 if (write_pos_ >= delay_) {
70 write_pos_ = 0;
71 }
72
73 return output;
74 }
75
76 /**
77 * @brief Set feedback coefficient
78 * @param g Feedback gain, typically 0.5–0.7 for reverb diffusion
79 */
80 void set_feedback(float g) { feedback_ = g; }
81
82 /** @brief Current feedback coefficient */
83 float feedback() const { return feedback_; }
84
85 /** @brief Zero the buffer and reset write position */
86 void reset() {
87 if (buffer_) {
88 for (uint32_t i = 0; i < delay_; ++i) buffer_[i] = 0.0f;
89 }
90 write_pos_ = 0;
91 }
92
93 /** @brief Delay length in samples */
94 uint32_t delay() const { return delay_; }
95
96 /** @brief Current write position (for external tap reads) */
97 uint32_t write_pos() const { return write_pos_; }
98
99private:
100 float* buffer_ = nullptr;
101 uint32_t delay_ = 0;
102 uint32_t write_pos_ = 0;
103 float feedback_ = 0.5f;
104};
105
106} // namespace sbl::dsp::primitives
107
108#endif // SBL_DSP_PRIMITIVES_ALLPASS_FILTER_HPP_
AllpassFilter()=default
Default constructor for array initialization (must call init() before use)
uint32_t write_pos() const
Current write position (for external tap reads)
void set_feedback(float g)
Set feedback coefficient.
void init(float *buffer, uint32_t delay)
Initialize after default construction.
uint32_t delay() const
Delay length in samples.
float process(float x)
Process a single sample.
void reset()
Zero the buffer and reset write position.
float feedback() const
Current feedback coefficient.
AllpassFilter(float *buffer, uint32_t delay)
Construct with caller-provided buffer.
Stateful, single-concern building blocks.