Build with this node

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

Ask Studio

@maruaudio/dsp/physical/modal is the shared arithmetic of a modal resonator: the coupled-form (rotation) two-pole recurrence that rings one mode as an exponentially decaying sinusoid, with its pole and coefficient mapping, displacement and velocity taps, the per-mode amplitude roll-off, and the exciter low-pass and Hann window a struck model uses. It is the single copy of this math; @maru/physical-modal-resonator, @maru/physical-modal-resonator-bank and the gamelan, gong and modal-struck voices all call it.

const r = modalPoleRadius(decay, fs) // exp(-decay / fs)
const w = modalPoleAngle(frequency, fs) // 2π f / fs
const c = modalCoefficientC(r, w), s = modalCoefficientS(r, w)
const re2 = modalNextRe(re, im, c, s), im2 = modalNextIm(re, im, c, s)

Lifecycle

None: pure stage functions. The caller owns the re and im state, adds excitation into re (the cosine axis) and reads im, the sine-phase displacement, so an impulse starts the mode from zero amplitude. Coefficient functions call exp, cos and sin; run them when a mode changes.

When to use it

Bells, bars, gongs, kalimba tines and other struck bodies whose sound is a sum of decaying modes, where low-frequency pitch and the beat rate between detuned mode pairs must be held precisely in f32.

Limits

  • Every state update and coefficient is rounded to f32 (Math.fround).
  • The pole radius is clamped below 1 (to 0.99999994, the largest f32 below 1), so a mode cannot grow; a negative decay counts as 0. A non-positive sample rate falls back to 48 kHz.
  • modalModeAboveNyquistGuard reports modes at or above 0.45 × fs, which callers silence rather than let fold; the pole mapping itself is unchanged.
  • Roll-off is amp · min(1, 1000 / f) above 1 kHz. The velocity tap is a one-sample difference times the rate.

Algorithm properties and proofs

No Lean 4 proof is mapped to this node.

Explore proofs alongside performance

Dependencies

None: this node imports no other node.

Dependents

Used by