@maruaudio/dsp/filters/lfo-lowpass is a wet-only stereo low-pass whose cutoff moves with one sine LFO. A single @maru/modulation-lfo clock at unit depth drives two independent @maru/filters-biquad low-pass histories, so both lanes move together without summing the channels. The cutoff follows the Auto Filter exponential law, fc = base·2^(lfo·sweep·0.5), a centred sweep of ±sweep/2 octaves, bounded to 10 Hz to 0.45 × the rate.
const state = initStereoLfoLowpassNode(48000)
setStereoLfoLowpassSweepOctaves(state, 3)
stereoLfoLowpassNodeTick(state, left, right) // state.outLeft, state.outRightParameters
Each setter replaces a non-finite value with the default, then clamps.
| Setter | Range the setter enforces | Default | Unit |
|---|---|---|---|
setStereoLfoLowpassBaseCutoffHz | 80 to 8000, and at most 0.45 × the rate | 1000 | Hz |
setStereoLfoLowpassQ | 0.5 to 6 | 0.7071 | Q |
setStereoLfoLowpassRateHz | 0.05 to 10 | 1 | Hz |
setStereoLfoLowpassSweepOctaves | 0 to 6 | 2 | octaves, peak to peak |
Lifecycle
initStereoLfoLowpassNode(sampleRate) (rate bounded to 8 to 384 kHz, NaN gives 48 kHz) → setters → stereoLfoLowpassNodeTick(state, left, right) → resetStereoLfoLowpassNode. Cutoff and sweep edits apply the centred cutoff at once; the rate setter keeps the LFO phase. The tick advances the LFO once even at zero sweep and refreshes coefficients only when the derived cutoff changes. Reset clears the LFO phase, both histories and the outputs and keeps the controls. There is no prepare step.
When to use it
Slow, cyclic filter motion on a stereo pad, loop or drum bus, moving both sides together.
Limits
- Stereo in, stereo out, wet only: no dry path, delay line or latency.
- The cutoff law is shared with the Graph Auto Filter, but the Graph's control routing clamp and PCM output are not claimed.
- Coefficients refresh per sample while the sweep moves, with no further smoothing. The tests check finite output, not a unity bound, at high Q.