Prepared comb filters¶
CombFilter::new(CombKind, delay_samples, coefficient) prepares a one-channel
f64 comb with a fixed delay D of 1..=1048576 whole samples. Feedforward computes
y[n] = x[n] + g*x[n-D], a finite input echo; Feedback computes
y[n] = x[n] + g*y[n-D], a recursive echo train. Both include current input at
unity gain. Positive and negative coefficients change the comb's reinforcement
and cancellation frequencies. Feedforward accepts any finite g (including +/-1
for complete notches); feedback requires finite |g| < 1 for fixed-coefficient
stability. Delay is measured in samples, so consumers convert their own time/rate.
use ravet_signal::{CombFilter, CombKind};
let mut comb = CombFilter::new(CombKind::Feedback, 2, 0.5).unwrap();
let mut impulse = [1.0, 0.0, 0.0, 0.0, 0.0];
comb.process_in_place(&mut impulse);
assert_eq!(impulse, [1.0, 0.0, 0.5, 0.0, 0.25]);
Preparation validates before allocating exactly D f64 history values (at most
8 MiB, excluding overhead). set_coefficient validates before mutation and
retains history without smoothing. A zero coefficient returns input exactly
while advancing history. process_sample, process_in_place and reset use
existing storage; empty blocks do nothing and arbitrary partitions match.
Reset retains the prepared kind, delay and latest coefficient. Type/delay changes
require a new instance; instantiate separately for channels.
This standalone profile supplies no damping, fractional delay or normalization. Feedback near unity has substantial gain and a long tail; consumers own headroom, smoothing, nonfinite/denormal policy and deadlines. The reverb below has its own private lowpass-feedback comb network. Tests cover exact signed impulse timing, independent full-history recurrence with live edits, analytic complex frequency response, partition/reset/zero history, atomic invalid edits and bounded maximum storage with 10000 heap-instrumented prepared workloads. See decision 0150.