Subtractive synth: voices, envelope and filter¶
The example instrument owns eight fixed voice slots. Each slot contains ravet_signal::Oscillator, ravet_signal::Adsr and ravet_signal::StateVariableFilter. ravet_instrument::MpeReceiver decides voice and expression ownership; the processor decides how those values affect sound.
Prepare the patch outside the callback¶
SynthPatch::new validates all nine physical controls and an 8–192 kHz sample rate. It converts ADSR milliseconds into seconds and creates 256 filter coefficient entries. Each entry represents increasing envelope/timbre excursion above the base cutoff, capped below 45% of sample rate.
The waveform index must be an integer from zero to three. Sine, polyBLEP saw and polyBLEP square are available alongside a triangle that can alias. There is no waveform crossfade.
Respond to a note¶
MIDI and normalized note events feed the shared MPE voice receiver. Its changed-slot mask avoids reinitializing untouched voices. A newly started or stolen voice resets oscillator and filter history, latches the current ADSR configuration and triggers attack. A released voice triggers envelope release exactly once.
Pitch is the note key plus member and master bend. Convert semitones to frequency relative to A4 = 440 Hz and cap it below 49% of sample rate. Retuning does not require creating a new oscillator.
Render a voice¶
Advance the envelope; combine member/master timbre and pressure with explicit clamps. Envelope excursion plus up to 24 semitones of timbre chooses an entry from the prepared filter table. Render oscillator → low-pass filter → envelope-controlled amplitude.
Velocity scales amplitude. Pressure can add up to 50%. Sum active slots and multiply by the requested level divided by eight. This fixed scaling is not a limiter or an overload guarantee at high resonance.
Finish the release¶
When the envelope enters Idle, call the receiver's finish for that slot. Note-off alone does not free the voice: release audio still owns it. ADSR edits latch at the next note-on; level, waveform and filter changes also affect held notes.
Read synth.rs and the subtractive tests for the code and checks. This example has no MIDI 2.0 synthesis or plug-in export.