// SonicForge TrackInstrument Service // Bọc FluidSynth channel per-track: playNote/noteOff theo TrackInstrumentCtx // (ch/program/synthEngine/sfId/bank/prog/dest) — dùng cho preview mọi nguồn // (keybed, piano roll, draw, hardware MIDI, click) qua UnifiedMidiRouter. // Tạo mới mỗi note-on (overwrite registry) — voice cũ giữ engine cũ trong // tracker nên note-off luôn stop đúng channel. window.TrackInstrument = window.TrackInstrument || {}; (function () { function TrackInstrument(trackId, ctx) { this.trackId = trackId; this.ch = ctx ? (ctx.ch != null ? ctx.ch : 0) : 0; this.program = ctx ? ctx.program : undefined; this.synthEngine = ctx ? ctx.synthEngine : undefined; this.sfId = ctx ? ctx.sfId : undefined; this.bank = ctx ? (ctx.bank || 0) : 0; this.prog = ctx ? (ctx.prog || 0) : 0; this.dest = ctx ? (ctx.dest || null) : null; } // Đảm bảo channel đã select đúng instrument trước khi play (fire-and-forget: // playNote tự load + retry nếu SF chưa load xong — dedup trong loadSoundFont). TrackInstrument.prototype._ensure = function () { try { if (!window.SonicSF || !window.SonicSF.selectInstrument) return; if (this.sfId) { window.SonicSF.selectInstrument(this.ch, this.bank, this.prog, this.sfId); } else if (this.program !== undefined) { window.SonicSF.selectInstrument(this.ch, 0, this.program, null); } } catch (e) { console.warn('[TrackInstrument] selectInstrument error:', e); } }; TrackInstrument.prototype.playNote = function (pitch, velocity, durationMs, startTime) { try { if (!window.SonicSF || !window.SonicSF.playNote) return; this._ensure(); var dur = (durationMs != null ? durationMs : 500) || 500; window.SonicSF.playNote(pitch, velocity != null ? velocity : 0.8, dur, startTime, this.program, this.dest, this.ch, this.synthEngine); } catch (e) { console.warn('[TrackInstrument] playNote error:', e); } }; TrackInstrument.prototype.noteOff = function (pitch) { try { if (window.SonicSF && window.SonicSF.stopNote) window.SonicSF.stopNote(this.ch, pitch); } catch (e) {} }; window.TrackInstrument = TrackInstrument; })();