fix: only send All Notes Off (CC123) when sustain pedal is not active

- Track sustain state per channel via _sustainStates[]
- sustainActive(channel) returns boolean
- MIDI NoteOn: only send CC123 if !sustainActive(ch)
- Preserves sustained notes when playing new notes
This commit is contained in:
2026-07-27 11:30:35 +07:00
parent 48e4047a84
commit 8aeac14e4b
2 changed files with 17 additions and 5 deletions
+3
View File
@@ -6758,9 +6758,12 @@ const App = () => {
activeMidiPitchesRef.current.add(pitch); activeMidiPitchesRef.current.add(pitch);
setActiveMidiPitches(new Set(activeMidiPitchesRef.current)); setActiveMidiPitches(new Set(activeMidiPitchesRef.current));
// Stop previous notes on this channel before playing new note // Stop previous notes on this channel before playing new note
// Only send All Notes Off when sustain pedal is not active
{ if (window.SonicSF) { { if (window.SonicSF) {
const ch = msg.data[0] & 0x0F; const ch = msg.data[0] & 0x0F;
if (!window.SonicSF.sustainActive || !window.SonicSF.sustainActive(ch)) {
try { window.SonicSF.controllerChange(ch, 123, 0); } catch (e) {} try { window.SonicSF.controllerChange(ch, 123, 0); } catch (e) {}
}
const arSub = subTabsRef && subTabsRef.current && activeTabRef && subTabsRef.current.find(s => s.id === activeTabRef.current && s.type === 'PIANO_ROLL' && s.isArmed); const arSub = subTabsRef && subTabsRef.current && activeTabRef && subTabsRef.current.find(s => s.id === activeTabRef.current && s.type === 'PIANO_ROLL' && s.isArmed);
if (arSub) { if (arSub) {
window.SonicSF.playNote(pitch, velocity, 60000, undefined, arSub.instrumentProgram, null, ch, arSub.synth_engine); window.SonicSF.playNote(pitch, velocity, 60000, undefined, arSub.instrumentProgram, null, ch, arSub.synth_engine);
@@ -36,6 +36,7 @@
let _initPromise = null; let _initPromise = null;
let _currentSfId = null; let _currentSfId = null;
const _scheduledNotes = []; const _scheduledNotes = [];
const _sustainStates = new Array(16).fill(false);
const SonicSF = { const SonicSF = {
loadedFonts: {}, loadedFonts: {},
@@ -122,6 +123,9 @@
_channels[channel].bank = value; _channels[channel].bank = value;
_channels[channel].isPercussion = (value === 128); _channels[channel].isPercussion = (value === 128);
} }
if (controller === 64) {
_sustainStates[channel] = value >= 64;
}
}, },
programChange: function (channel, program) { programChange: function (channel, program) {
@@ -154,6 +158,11 @@
return { ..._channels[channel] }; return { ..._channels[channel] };
}, },
sustainActive: function (channel) {
if (channel < 0 || channel > 15) return false;
return _sustainStates[channel];
},
pitchBend: function (channel, value) { pitchBend: function (channel, value) {
if (channel < 0 || channel > 15) return; if (channel < 0 || channel > 15) return;
if (_initialized && _synthInstance) { if (_initialized && _synthInstance) {