fix: stopNote/stoplAll uses CC120 (All Sound Off) instead of CC123 (All Notes Off) to kill sustained instrument voices immediately
Root cause: SpessaSynth's CC123 (All Notes Off) calls stopAllNotes(false) which enters the SoundFont release envelope. Tremolo Strings (GM#44) and similar sustained instruments have 2-5s release tails, causing notes to continue playing after MIDI key release. Fix: Replace CC 123 with CC 120 (All Sound Off) in stopNote() and stopAll(). CC 120 calls stopAllNotes(true) which sets voice.isActive=false instantly, bypassing the release envelope entirely. Removed redundant noteOff(ch,pitch,0) and resetAllControllers(CC121) which unnecessarily reset volume/pan/expression on the channel.
This commit is contained in:
@@ -175,12 +175,12 @@
|
|||||||
if (_initialized && _synthInstance) {
|
if (_initialized && _synthInstance) {
|
||||||
// Ensure sustain is OFF before noteOff (SpessaSynth uses >=8192 threshold)
|
// Ensure sustain is OFF before noteOff (SpessaSynth uses >=8192 threshold)
|
||||||
try { _synthInstance.controllerChange(channel, 64, 0); } catch (e) {}
|
try { _synthInstance.controllerChange(channel, 64, 0); } catch (e) {}
|
||||||
// Standard noteOff with multiple velocity variants
|
// Standard MIDI noteOff for the specific pitch — enters SoundFont release envelope
|
||||||
try { _synthInstance.noteOff(channel, pitch); } catch (e) {}
|
try { _synthInstance.noteOff(channel, pitch); } catch (e) {}
|
||||||
try { _synthInstance.noteOff(channel, pitch, 0); } catch (e) {}
|
// Force immediate voice kill: CC 120 (All Sound Off) sets isActive=false instantly,
|
||||||
// Backup: All Notes Off + reset controllers
|
// bypassing the release envelope. CC 123 (All Notes Off) merely enters the release
|
||||||
try { _synthInstance.controllerChange(channel, 123, 0); } catch (e) {}
|
// phase which respects long release tails (2-5s for sustained instruments).
|
||||||
try { _synthInstance.controllerChange(channel, 121, 0); } catch (e) {}
|
try { _synthInstance.controllerChange(channel, 120, 0); } catch (e) {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -321,7 +321,7 @@
|
|||||||
|
|
||||||
stopAll: function () {
|
stopAll: function () {
|
||||||
if (_initialized && _synthInstance) {
|
if (_initialized && _synthInstance) {
|
||||||
try { for (let ch = 0; ch < 16; ch++) _synthInstance.allNotesOff(ch); } catch (e) {}
|
try { for (let ch = 0; ch < 16; ch++) _synthInstance.controllerChange(ch, 120, 0); } catch (e) {}
|
||||||
}
|
}
|
||||||
// Cancel all scheduled future notes
|
// Cancel all scheduled future notes
|
||||||
while (_scheduledNotes.length > 0) {
|
while (_scheduledNotes.length > 0) {
|
||||||
|
|||||||
Reference in New Issue
Block a user