@maruaudio/dsp/voices/note-stack tracks which MIDI notes are held, the velocity each was pressed with and the order they were pressed, so a mono or legato voice can fall back to the most recent note still held when the sounding one is released. The source header says it was extracted verbatim from Newsynth1's Processor. The caller owns voice allocation, retriggering and glide; this DSP node only answers what is held and which note is selected.
Parameters
There are no setters. Inputs arrive through the calls:
| Call | Coded behavior |
|---|---|
noteStackPush(state, note, velocity) | note must be 0 to 127; a note already held is ignored; velocity is clamped to 0..1 and stored as f32 |
noteStackRelease(state, note) | A note not held is ignored; the press order closes the gap |
noteStackLast(state) | Most recent held note, or −1 |
noteStackSelected(state, priority) | 0 last (also any other value), 1 lowest pitch, 2 highest pitch; −1 when none held |
noteStackPressId(state, note, velocity, noteId) | Identity-aware press: same identity, else lowest free slot, else the oldest pressed slot; returns the slot |
noteStackFindId(state, note, noteId) | Held slot for an identity, or −1; noteId < 0 matches by pitch |
Lifecycle
initNoteStack() allocates five 128-entry typed arrays (held, velocity, order, pitch, noteId) → push, release and the queries from the owning Processor's note events → resetNoteStack clears held flags, velocities and order and restores pitch[i] = i, noteId[i] = −1. Nothing is allocated after init.
When to use it
A monophonic or legato instrument that should return to the previous held key when the newest one is lifted, or select the lowest or highest held key. For the retrigger decisions that sit on top of it use @maru/voices-mono-performance.
Limits
- Fixed capacity of 128 entries (
NOTE_STACK_CAPACITY), one per MIDI note. - Notes outside 0 to 127 are not checked by
noteStackPush. - Lowest and highest priority scan all 128 entries per call.
- No audio output and no sample tick.