46#ifndef SBL_DSP_MODULES_LADDER_HPP_
47#define SBL_DSP_MODULES_LADDER_HPP_
105 cd_resonance_.
reset(su);
121 target_drive_ = drive;
124 op_drive_.
reset(drive);
143 const float* cutoff_mod =
nullptr,
float mod_depth = 0.0f) {
145 float freq_target = target_freq_hz_;
146 float q_target = target_q_;
147 float drive_target = target_drive_;
149 float s0 = stage_[0], s1 = stage_[1];
150 float s2 = stage_[2], s3 = stage_[3];
152 float dp = decim_prev_;
154 for (uint16_t i = 0; i < frames; ++i) {
156 float center = cd_cutoff_.
process(freq_target);
157 float q = cd_resonance_.
process(q_target);
158 float drive = op_drive_.
process(drive_target);
161 float freq = (cutoff_mod !=
nullptr)
167 float g = compute_g(freq, sr_os);
169 float gain_comp = 1.0f + k * 0.5f;
170 float total_drive = drive * gain_comp;
171 if (total_drive > MAX_INPUT_DRIVE) total_drive = MAX_INPUT_DRIVE;
173 float x = buf[i] * total_drive;
176 float os_out[OS_FACTOR];
177 for (
int os = 0; os < OS_FACTOR; ++os) {
178 float feedback = d * k;
191 float half0 = (os_out[0] + os_out[1]) * 0.5f;
192 float half1 = (os_out[2] + os_out[3]) * 0.5f;
193 buf[i] = 0.25f * dp + 0.5f * half0 + 0.25f * half1;
197 stage_[0] = s0; stage_[1] = s1;
198 stage_[2] = s2; stage_[3] = s3;
203 sync_cached_coefficients();
208 stage_[0] = stage_[1] = stage_[2] = stage_[3] = 0.0f;
218 void set_cutoff(
float freq_hz) {
219 target_freq_hz_ = freq_hz;
220 cd_cutoff_.
reset(freq_hz);
221 apply_cutoff(freq_hz);
226 void set_resonance(
float q) {
228 cd_resonance_.
reset(q);
234 void set_drive(
float drive) {
235 target_drive_ = drive;
236 op_drive_.
reset(drive);
241 void apply_cutoff(
float freq_hz) {
242 cutoff_hz_ = freq_hz;
246 void apply_resonance(
float q) {
248 gain_comp_ = 1.0f + k_ * 0.5f;
252 static float compute_g(
float freq_hz,
float sr) {
253 float fc = freq_hz / sr;
254 if (fc > 0.497f) fc = 0.497f;
255 if (fc < 0.0f) fc = 0.0f;
258 constexpr float inv_ln2 = 1.4426950f;
266 void ensure_smoothers() {
267 if (!smoothers_configured_) {
271 cd_cutoff_.
reset(target_freq_hz_);
272 cd_resonance_.
reset(target_q_);
273 op_drive_.
reset(target_drive_);
274 smoothers_configured_ =
true;
279 void sync_cached_coefficients() {
280 float q = cd_resonance_.
value();
282 gain_comp_ = 1.0f + k_ * 0.5f;
283 cutoff_hz_ = cd_cutoff_.
value();
284 drive_ = op_drive_.
value();
288 static constexpr int OS_FACTOR = 4;
289 static constexpr float OS_RECIP = 1.0f /
static_cast<float>(OS_FACTOR);
290 static constexpr float MAX_INPUT_DRIVE = 6.0f;
292 float stage_[4] = {};
296 float gain_comp_ = 1.0f;
298 float cutoff_hz_ = 1000.0f;
299 float decim_prev_ = 0.0f;
302 primitives::CriticalDamp cd_cutoff_;
303 primitives::CriticalDamp cd_resonance_;
304 primitives::ParameterSmoother op_drive_;
305 float target_freq_hz_ = 1000.0f;
306 float target_q_ = 0.0f;
307 float target_drive_ = 1.0f;
308 bool cutoff_init_ =
false;
309 bool reso_init_ =
false;
310 bool drive_init_ =
false;
311 bool smoothers_configured_ =
false;
Clamping (Cross-cutting — Math)
void process(float *buf, uint16_t frames, const float *cutoff_mod=nullptr, float mod_depth=0.0f)
Process a block of audio samples in-place (4-pole lowpass)
void set_drive_su(float su)
Set drive from normalized [0,1] signal unit.
void set_cutoff_su(float su)
Set cutoff frequency from normalized [0,1] signal unit.
static constexpr float kMaxDrive
void reset()
Reset filter state (audio state only, not parameter smoothers)
void set_resonance_su(float su)
Set resonance from normalized [0,1] signal unit.
static constexpr float kMinFreqHz
static constexpr float kMaxFreqHz
static constexpr float kMinDrive
static constexpr float kCutoffOctaves
friend struct LadderTestAccess
float value() const
Current output value.
void set_time_ms(float ms, float rate_hz)
Set settling time in milliseconds.
void reset()
Reset to zero.
float process(float target)
Process one sample toward target.
void reset()
Reset to zero.
void set_time_ms(float ms, float rate_hz)
Compute coefficient from settling time in milliseconds.
float process(float target)
Process one sample toward target.
float value() const
Current smoothed value.
The numbers every layer reaches for.
Critically damped 2nd-order parameter smoother.
Exponential modulation converter (Signal layer)
Fast analytical approximations (Audio Stack — Atoms)
Fixed-point constants and audio sample types.
constexpr float clamp01(float x)
x held to [0, 1]; NaN → 0.
float fast_exp2f(float x)
float exp_mod(float base, float mod, float depth, float lo=20.0f, float hi=20000.0f)
float su_to_hz(float su, float min_hz, float octaves)
float fast_tanhf(float x)
One-pole parameter smoother.