fix(voice): CC 120 hard-stops voices (incl. Trigger); Mono sizes voices_ to 1; comments corrected
CC 120 -> allSoundsOff/hardStop (immediate silence, stops Trigger one-shots); CC 123 -> allNotesOff/releaseAll (release, unchanged). Mono VoiceEngine sizes voices_ to 1 structurally. Legato same-note re-press edge documented. Three new tests.
This commit is contained in:
@@ -766,16 +766,28 @@ tresult PLUGIN_API ReaSamplerProcessor::process(ProcessData& data) {
|
||||
if (inst) inst->engine.noteOff(e.noteOff.pitch);
|
||||
if (drain) drain->engine.noteOff(e.noteOff.pitch);
|
||||
} else if (e.type == Event::kLegacyMIDICCOutEvent) {
|
||||
// PANIC (Phase S voice-review Major #2): CC 123 (All Notes Off) / CC 120 (All
|
||||
// Sound Off) reset the engine — clear the mono held stack and release every
|
||||
// voice, live AND drain, engine AND preview card — so a phantom held-stack
|
||||
// entry left by a lost note-off can never be resurrected by the mono fallback
|
||||
// and sustain forever. REAPER delivers raw input MIDI CC to a VST3 instrument
|
||||
// as kLegacyMIDICCOut events on the INPUT event list (a REAPER-ism — the type
|
||||
// is nominally an output event; DAW-verify, see handoff). allNotesOff /
|
||||
// releaseAll are RT-safe (no allocation, bounded scans).
|
||||
// PANIC (Phase S voice-review Major #2): REAPER delivers raw input MIDI CC to a
|
||||
// VST3 instrument as kLegacyMIDICCOut events on the INPUT event list (a REAPER-ism
|
||||
// — the type is nominally an output event; DAW-verify, see handoff).
|
||||
// CC 123 (All Notes Off): release semantics — Gate voices enter their AHDSR
|
||||
// release tail; Trigger one-shots play through their bounded play length.
|
||||
// CC 120 (All Sounds Off): hard-stop semantics — immediate silence regardless
|
||||
// of play mode, including Trigger one-shots that ignore CC 123. This is the
|
||||
// true "panic" for a ringing one-shot (e.g. a full-length capture).
|
||||
// Both clear the mono held stack. Both apply to live AND drain, engine AND preview.
|
||||
// allNotesOff / allSoundsOff / releaseAll / hardStop are RT-safe (no allocation,
|
||||
// bounded scans).
|
||||
const auto cc = static_cast<int>(e.midiCCOut.controlNumber);
|
||||
if (cc == kCtrlAllNotesOff || cc == kCtrlAllSoundsOff) {
|
||||
if (cc == kCtrlAllSoundsOff) {
|
||||
if (inst) {
|
||||
inst->engine.allSoundsOff();
|
||||
inst->preview.hardStop();
|
||||
}
|
||||
if (drain) {
|
||||
drain->engine.allSoundsOff();
|
||||
drain->preview.hardStop();
|
||||
}
|
||||
} else if (cc == kCtrlAllNotesOff) {
|
||||
if (inst) {
|
||||
inst->engine.allNotesOff();
|
||||
inst->preview.releaseAll();
|
||||
|
||||
Reference in New Issue
Block a user