Module dsp

Module dsp 

Source
Expand description

DSP foundation for the mic chain: a float audio bus, a stage contract, and a metered chain runner.

The original mic chain passed Vec<i16> from stage to stage — every hop re-quantized (adding noise floor) and every boundary was a hidden clip point. This module is the engineer’s version: samples are converted to f32 once on entry, every stage processes in float with headroom, and one saturating conversion happens at the exit — where clipping is counted, not silent.

// `ignore`: the resampler/STFT stages need the `dsp` feature and the
// denoiser the `denoise` feature; `live` is a `Live` builder.
let chain = DspChain::new(16_000)
    .stage(HighPass::speech_default(16_000))   // DC / rumble removal
    .stage(IntStage::new(Denoiser::new(16_000))) // legacy i16 stage, one boundary
    .stage(Agc::default_speech())
    .stage(Limiter::default_ceiling());
let metrics = chain.metrics();                  // live per-stage meters
live.mic_processor(chain);                      // drop into the existing seam

§Design rules

  • Allocation-free steady state: scratch buffers are owned by the chain and stages; the hot path only does arithmetic. (A stage may resize its output — resamplers legitimately change length — but must not allocate per call once warmed.)
  • Uniform measurement: the chain, not the stages, meters peak/RMS in and out of every stage plus exit clipping, so every stage is observed identically and stages stay pure.
  • Latency is declared: every stage reports its group delay via DspStage::latency_samples; DspChain::total_latency_samples sums the chain’s causal budget so turn-commit timestamps can cite it.

§Canonical stage order

HPF → AEC → denoise → AGC → gate → limiter — each stage assumes what the previous one guarantees: echo cancellation needs the linear signal (before the nonlinear denoiser breaks the echo-path model), gain control wants denoised speech so it does not amplify noise, and the limiter is last so nothing after it can clip.

Re-exports§

pub use aec::Aec;
pub use aec::AecConfig;
pub use aec::AecFarEnd;
pub use resample::SincResampler;
pub use stages::Agc;
pub use stages::HighPass;
pub use stages::Limiter;
pub use stft::Identity;
pub use stft::SpectralFloor;
pub use stft::SpectralStage;
pub use stft::Stft;

Modules§

aec
Acoustic echo cancellation: subtract the bot’s own voice from the mic before anything else touches it.
resample
Windowed-sinc resampling as a chain stage (feature dsp).
stages
Time-domain stage library: high-pass, AGC, and limiter.
stft
STFT engine with WOLA (weighted overlap-add) processing.

Structs§

AudioBus
One block of audio moving through the chain: f32 samples in [-1.0, 1.0] nominal range (headroom above is legal between stages) plus the sample rate a stage may change (resamplers).
ChainMetrics
Shared metrics handle — clone freely; reading never blocks the chain.
ChainSnapshot
Point-in-time view of the whole chain.
DspChain
The metered float chain. Build with stage, hand to the existing mic_processor(..) seam — it implements InputAudioProcessor.
IntStage
Wrap a legacy integer-domain InputAudioProcessor (e.g. the RNNoise Denoiser or NoiseGate) as a DspStage. This is the one deliberate int boundary in a float chain — the cost of reusing a proven stage unchanged.
StageSnapshot
Point-in-time view of one stage’s meters.

Traits§

DspStage
A single processing stage on the float bus.