Build with this node

Start with a prompt in Studio, or copy it into your own coding agent.

Ask Studio

@maruaudio/dsp/delays/saturated-feedback is a tape-style delay core. Each sample reads the whole-frame line, passes the read through a one-pole damping filter (pole exp(−2π·fc/rate), f32), saturates it with the rational approximation tanh(x) ≈ x(27 + x²)/(27 + 9x²) (input clamped to ±3) divided by the drive for unity slope at silence, scales by feedback and writes clamp(x + that, −1, 1) back as f32. The output is x·(1 − mix) + read·mix. Since |saturate(x)| ≤ |x| and feedback is at most 0.95, the loop is bounded.

const state = initSaturatedFeedbackDelayNode(48000, SATURATED_DELAY_MAX_MILLISECONDS)
setSaturatedDelayTime(state, 420)
setSaturatedDelayAge(state, 0.6) // sets the damping pole
const y = saturatedFeedbackDelayNodeTick(state, x)

Parameters

SetterRange the setter enforcesDefaultUnit
setSaturatedDelayTime1 to 2000 ms, then capped at the line allocated by initThe init timems
setSaturatedDelayFeedback0 to 0.950.55linear
setSaturatedDelayMix0 to 10.35linear
setSaturatedDelayAge0 to 1; damping cutoff 7000 − 4600·age Hz0.6normalized
setSaturatedDelayDrive0.25 to 4, rounded to f321.6linear

Lifecycle

initSaturatedFeedbackDelayNode(sampleRate, ms) allocates the line once; pass the maximum time and the highest rate to leave room → setters → tick → resetSaturatedFeedbackDelayNode, which zeroes line, index and damping state and keeps the controls. prepareSaturatedFeedbackDelayNodeSampleRate re-derives the length and the damping pole (fixed in Hz) without allocating and keeps history. clearSaturatedFeedbackDelayNodeStep zeroes at most 256 samples per call, returning the line length when done; then call finalize…Clear.

When to use it

Echoes that darken and soften as they repeat, from slapback to long tape-style feedback.

Limits

  • Mono, whole-frame delay; a time change jumps the read position.
  • A new state reads age 0.6 but has a damping pole of 0 (no damping) until setSaturatedDelayAge or prepare runs.
  • The rational curve saturates to exactly ±1 at |x| ≥ 3; the browser reference's oversampled tanh is not reproduced.

Algorithm properties and proofs

Lean 4 checks specific properties of this algorithm’s mathematical model. Each model result applies within its stated domain and assumptions.

2 Lean 4 results: 1 proof in exact arithmetic; 1 counterexample.

Proved in exact arithmetic.The real rationalTanh, generated from Maru compiler IR, stays within plus or minus 1 for every input.exact rational arithmetic
Limits and assumptions
  • False on Float: NaN passes straight through, and an ordinary finite input just below 3 gives 1.0000000000000002.
Theorem
IrToLean.Proof.rationalTanh_bounded
Recorded axioms
propext, Classical.choice, Quot.sound
Manifest reviewed
Counterexample.On Float the real rationalTanh is not bounded by 1: NaN gives NaN, and an input just below 3 gives one unit in the last place over 1.concrete binary64 inputs, checked in the kernel on Lean's logical model of Float
Limits and assumptions
  • Concrete inputs only; it does not bound how far over 1 the output can go.
  • This record also covers IrToLean.Proof.rationalTanh_nan_is_nan, IrToLean.Proof.rationalTanh_over_one_on_float; axioms describe IrToLean.Proof.rationalTanh_not_bounded_on_float only.
Theorem
IrToLean.Proof.rationalTanh_not_bounded_on_float
Recorded axioms
propext, Classical.choice, Quot.sound
Manifest reviewed
Explore proofs alongside performance

Parameters

ParameterTypeSetter
Feedback feedbackfloatsetSaturatedDelayFeedback
Delay milliseconds delayMilliseconds

Select a bounded active length inside a preallocated maximum line. Shared graph instances allocate the maximum once on the control plane, then this setter remains allocation-free when a rack automates delay time.

floatsetSaturatedDelayTime
Mix mixfloatsetSaturatedDelayMix
Age agefloatsetSaturatedDelayAge
Drive drive

Set feedback saturation depth. The default (1.6) is the historical fixed value; callers that do not set this control preserve the existing stream.

floatsetSaturatedDelayDrive

Ports

  • In ininput · audio · mono
  • Out outoutput · audio · mono

One sample per saturatedFeedbackDelayNodeTick call.

Dependencies

None: this node imports no other node.

Dependents

Used by