FIX: Clone AI Var kế thừa midiChannel của track gốc → 2 track DÙNG CHUNG channel

This commit is contained in:
2026-08-05 15:49:44 +07:00
parent 4233c1eeda
commit b3ced7a7b3
5 changed files with 150 additions and 31 deletions
+26 -13
View File
@@ -24,6 +24,7 @@
let _gainNode = null;
let _pendingOutputDestination = null;
let _outputDestination = null; // cache đích route — dedupe swap dư giữa stream
let _validPercCache = {}; // { sfId: [bank, prog] | null } — preset percussion hợp lệ
let _scheduledNotes = [];
let _loadPromises = {};
let _sfloadSeq = 0;
@@ -562,22 +563,34 @@
console.log('[SonicSF] selectProgram for channel:', ch, 'sfHandle:', sfHandle, 'bank:', finalBank, 'prog:', finalProg);
if (sfHandle !== undefined) {
try {
var _selRet = _fluidModule._fluid_synth_program_select(_synthPtr, ch, sfHandle, finalBank, finalProg);
// Percussion (bank 128) preset không tồn tại trong
// font → fallback preset trống hợp lệ (GM kit 48 →
// preset đầu font) — nếu không, noteon trên preset
// rỗng = CÂM (track percussion "1 âm đầu rồi câm").
if (_selRet !== 0 && finalBank === 128) {
var _cands = [[128, 48], [0, 0], [128, 1], [0, 48]];
for (var _ci = 0; _ci < _cands.length; _ci++) {
try {
if (_fluidModule._fluid_synth_program_select(_synthPtr, ch, sfHandle, _cands[_ci][0], _cands[_ci][1]) === 0) {
finalBank = _cands[_ci][0]; finalProg = _cands[_ci][1];
break;
// Percussion (bank 128): tìm preset HỢP LỆ trong
// font — quét bank 128 + bank 0 (0-127) MỘT LẦN,
// cache theo sfId. Trước đây chỉ thử 4 preset cố
// định → font không có → cache channel = (128,0)
// INVALID → note sau skip re-select (progAlreadySet)
// → noteon preset rỗng = CÂM ("1 âm đầu rồi câm").
if (finalBank === 128) {
var _vKey = finalSfId || ('h' + sfHandle);
if (_validPercCache[_vKey] === undefined) {
var _found = null;
for (var _b = 0; _b < 2 && !_found; _b++) {
var _bk = _b === 0 ? 128 : 0;
for (var _p = 0; _p < 128 && !_found; _p++) {
try {
if (_fluidModule._fluid_synth_program_select(_synthPtr, 9, sfHandle, _bk, _p) === 0) {
_found = [_bk, _p];
}
} catch (e) {}
}
} catch (e) {}
}
_validPercCache[_vKey] = _found;
}
if (_validPercCache[_vKey]) {
finalBank = _validPercCache[_vKey][0];
finalProg = _validPercCache[_vKey][1];
}
}
var _selRet = _fluidModule._fluid_synth_program_select(_synthPtr, ch, sfHandle, finalBank, finalProg);
} catch (e) {}
} else {
try { _fluidModule._fluid_synth_bank_select(_synthPtr, ch, finalBank); } catch (e) {}