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:
@@ -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) {
|
||||||
|
|||||||
Reference in New Issue
Block a user