FIX: Clone AI Var kế thừa midiChannel của track gốc → 2 track DÙNG CHUNG channel
This commit is contained in:
@@ -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) {}
|
||||
|
||||
Reference in New Issue
Block a user