fix: MIDI NoteOff stops note immediately (60000ms duration + stopNote)
- NoteOn: durationMs=60000 (1 phút, giữ cho đến khi NoteOff) - NoteOff: stopNote(ch, pitch) gọi synthInstance.noteOff() ngay - MIDI channel (msg.data[0] & 0x0F) truyền đúng vào playNote - CC (sustain/modulation) + pitch bend forward qua SpessaSynth
This commit is contained in:
+15
-10
@@ -6761,26 +6761,31 @@ const App = () => {
|
||||
const ch = msg.data[0] & 0x0F;
|
||||
const arSub = subTabsRef && subTabsRef.current && activeTabRef && subTabsRef.current.find(s => s.id === activeTabRef.current && s.type === 'PIANO_ROLL' && s.isArmed);
|
||||
if (arSub) {
|
||||
window.SonicSF.playNote(pitch, velocity, 500, undefined, arSub.instrumentProgram, null, undefined, arSub.synth_engine);
|
||||
window.SonicSF.playNote(pitch, velocity, 60000, undefined, arSub.instrumentProgram, null, ch, arSub.synth_engine);
|
||||
} else {
|
||||
const armedTrack = activeTracksRef.current ? activeTracksRef.current.find(t => t.isArmed) : null;
|
||||
if (armedTrack) {
|
||||
const prog = armedTrack.instrumentProgram;
|
||||
const se = armedTrack.synth_engine;
|
||||
const dest = activeTrackNodesRef.current[armedTrack.id]?.gainNode || null;
|
||||
window.SonicSF.playNote(pitch, velocity, 500, undefined, prog, dest, undefined, se);
|
||||
window.SonicSF.playNote(pitch, velocity, 60000, undefined, prog, dest, ch, se);
|
||||
}
|
||||
}
|
||||
} }
|
||||
} else if (cmd === 0x8 || (cmd === 0x9 && velocity === 0)) {
|
||||
activeMidiPitchesRef.current.delete(pitch);
|
||||
setActiveMidiPitches(new Set(activeMidiPitchesRef.current));
|
||||
const current = lastMidiNoteRef.current;
|
||||
if (current && current.pitch === pitch) {
|
||||
const lenSec = (performance.now() - current.startTime) / 1000;
|
||||
lastMidiNoteRef.current = { ...current, length: lenSec };
|
||||
setLastMidiNote(prev => prev && prev.pitch === pitch ? { ...prev, length: lenSec, time: Date.now() } : prev);
|
||||
}
|
||||
activeMidiPitchesRef.current.delete(pitch);
|
||||
setActiveMidiPitches(new Set(activeMidiPitchesRef.current));
|
||||
const current = lastMidiNoteRef.current;
|
||||
if (current && current.pitch === pitch) {
|
||||
const lenSec = (performance.now() - current.startTime) / 1000;
|
||||
lastMidiNoteRef.current = { ...current, length: lenSec };
|
||||
setLastMidiNote(prev => prev && prev.pitch === pitch ? { ...prev, length: lenSec, time: Date.now() } : prev);
|
||||
}
|
||||
// Stop the note immediately via SpessaSynth
|
||||
if (window.SonicSF && window.SonicSF.stopNote) {
|
||||
const ch = msg.data[0] & 0x0F;
|
||||
window.SonicSF.stopNote(ch, pitch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -161,6 +161,13 @@
|
||||
}
|
||||
},
|
||||
|
||||
stopNote: function (channel, pitch) {
|
||||
if (channel < 0 || channel > 15) return;
|
||||
if (_initialized && _synthInstance) {
|
||||
try { _synthInstance.noteOff(channel, pitch); } catch (e) {}
|
||||
}
|
||||
},
|
||||
|
||||
playNote: function (note, velocity, durationMs, startTime, program, destinationNode, channel, synthEngine) {
|
||||
if (_initialized && _synthInstance) {
|
||||
this._playNoteSpessa(note, velocity, durationMs, startTime, program, channel, synthEngine);
|
||||
|
||||
Reference in New Issue
Block a user