@maruaudio/dsp/voices/pluck is an extended Karplus-Strong plucked string (Jaffe & Smith). Each note renders a bounded excitation (a raised-cosine pick pulse blended with seeded xorshift32 one-pole-filtered noise, peak-normalized and combed by the pluck position) into a fractional-delay loop with a mixed one-pole loss filter, a negative-coefficient first-order allpass for stiffness, and a loop gain solved from a pitch-tilted 60 dB time. A three-mode body bank is mixed over the string, a 20 ms raised-cosine tail fade ends on exact zero, and a linked-stereo safety trim follows. The stereo pair is two independently seeded strings detuned by the width control, identical at width 0.
Parameters
pluckNoteOn(state, note, frequency, velocity, hardness, noise, position, damping, brightness, stiffness, sustain, body, width) snapshots everything at the strike:
| Argument | Clamp as coded |
|---|---|
frequency | Must be finite and positive, else the call returns −1 |
velocity | 0 to 1; one of 4 velocity layers picks the excitation |
hardness | Tilted by 0.35 × (layer velocity − 0.7), then 0 to 1 |
noise, damping, brightness, stiffness, body, width | 0 to 1 |
position | Folded about 0.5, then 0.02 to 0.5; non-finite gives 0.02 |
sustain | 0.05 to 12 s |
width detunes the right string by up to 5 cents. pluckNoteOff(state, note, sustain) damps over 0.1 + sustain × 0.09 s, clamped to 0.12..0.9 s.
Lifecycle
createPluckVoiceState() allocates twelve voices' delay lines, excitations and coefficients → preparePluckVoiceState(state, rate) solves the body coefficients (scaled to keep the reference-rate level) and clears every voice → pluckNoteOn returns the slot (a ringing voice on the same note is damped over 0.06 s first; lowest free slot, else the oldest) → pluckNoteOff / pluckAllNotesOff (0.05 s) → pluckTick once per frame leaves the summed pair in outLeft[0] / outRight[0]; the caller applies master gain → resetPluckVoiceState silences every voice and clears the per-note strike counters that choose between two excitation variants.
When to use it
Plucked-string parts where each note's settings are fixed at the pluck and stereo width comes from two detuned strings.
Limits
- Stereo, sample tick, twelve voices; a note's render length is capped at 5 s.
- Parameters are captured per note at note-on (loop solve and excitation render, allocation-free).