fix: multi-track ARM + activeNotes map cho stopNote

1. precompiled: find(t=>isArmed) → filter(t=>isArmed) loop all tracks
2. soundfontPlayer: _activeNotes[ch:pitch] = mappedCh lưu khi noteOn
3. stopNote lookup mappedCh từ _activeNotes thay vì dùng MIDI ch 0
→ Fix: đổi SF track → channel mới → noteOff vẫn tìm đúng voice
This commit is contained in:
2026-07-27 15:48:34 +07:00
parent 638d56ce63
commit cb23d36bc8
2 changed files with 10 additions and 5 deletions
+9 -4
View File
@@ -14,6 +14,7 @@
let _nextMelodicChannel = 0;
let _sustainStates = new Array(16).fill(false);
let _engineChMap = {};
let _activeNotes = {};
let _leftBufPtr = null;
let _rightBufPtr = null;
let _renderTimer = null;
@@ -319,11 +320,13 @@
stopNote: function (channel, pitch) {
if (channel < 0 || channel > 15) return;
if (_initialized && _fluidModule) {
var mappedCh = _activeNotes[channel + ':' + pitch];
if (mappedCh === undefined) mappedCh = channel;
delete _activeNotes[channel + ':' + pitch];
try {
var r1 = _fluidModule._fluid_synth_noteoff(_synthPtr, channel, pitch);
var r2 = _fluidModule._fluid_synth_noteon(_synthPtr, channel, pitch, 0);
if (r1 !== 0 && r2 !== 0) {
console.warn("[SonicSF] noteoff/non failed ch:", channel, "pitch:", pitch, "r:", r1, r2);
var r1 = _fluidModule._fluid_synth_noteoff(_synthPtr, mappedCh, pitch);
if (r1 !== 0) {
r1 = _fluidModule._fluid_synth_noteon(_synthPtr, mappedCh, pitch, 0);
}
} catch (e) { console.warn("[SonicSF] stopNote error:", e); }
}
@@ -391,10 +394,12 @@
try {
console.log("[SonicSF] noteOn ch:", ch, "pitch:", midiPitch, "vel:", midiVel);
_fluidModule._fluid_synth_noteon(_synthPtr, ch, midiPitch, midiVel);
_activeNotes[ch + ':' + midiPitch] = ch;
if (durationMs > 0 && durationMs < 60000) {
scheduledNote.off = setTimeout(function () {
try {
_fluidModule._fluid_synth_noteoff(_synthPtr, ch, midiPitch);
delete _activeNotes[ch + ':' + midiPitch];
} catch (e) {}
}, durSec * 1000);
}