feat: VSTi live playback 100% client-side (không Carla) — autosample SF2 backend (pedalboard) → FluidSynth WASM qua masterBus → mastering → main out; SonicVstiAutosample ensure+dedup+cooldown; runtime gating __enableCarlaLivePlayback; âm bắt qua ensureMidiCapture → clientSideExport
This commit is contained in:
@@ -464,7 +464,7 @@
|
||||
bank = bank !== undefined ? bank : (synthEngine.soundfont_bank || 0);
|
||||
program = program !== undefined ? program : (synthEngine.soundfont_program || 0);
|
||||
}
|
||||
var sfId = synthEngine && synthEngine.soundfont_id;
|
||||
var sfId = synthEngine && (synthEngine.soundfont_id || synthEngine.autosampled_sf_id);
|
||||
var engKey = (sfId || '') + ':' + bank + ':' + program;
|
||||
if (!_engineChMap[engKey]) {
|
||||
var channel = this.allocateChannel(bank);
|
||||
@@ -587,7 +587,36 @@
|
||||
if (isNaN(finalBank) || !isFinite(finalBank)) finalBank = 0;
|
||||
var finalProg = parseInt(usedProg);
|
||||
if (isNaN(finalProg) || !isFinite(finalProg)) finalProg = 0;
|
||||
var finalSfId = synthEngine ? synthEngine.soundfont_id : undefined;
|
||||
var finalSfId = synthEngine ? (synthEngine.soundfont_id || synthEngine.autosampled_sf_id) : undefined;
|
||||
// VSTi live playback (không Carla): chưa có SF2 autosampled → chờ
|
||||
// SonicVstiAutosample.ensure (1 request backend / plugin+preset) rồi
|
||||
// play qua FluidSynth WASM như soundfont thường — âm đi qua masterBus
|
||||
// → mastering → main out. ensure dedup in-flight + cooldown lỗi 60s.
|
||||
if (!finalSfId && window.SonicVstiAutosample && synthEngine && !synthEngine.soundfont_id
|
||||
&& String(synthEngine.type || '').indexOf('vst') !== -1 && !!synthEngine.plugin_id) {
|
||||
var _pendKey = ch + ':' + midiPitch;
|
||||
var _gen = _noteGeneration;
|
||||
_pendingNoteOns[_pendKey] = (_pendingNoteOns[_pendKey] || 0) + 1;
|
||||
window.SonicVstiAutosample.ensure(synthEngine).then(function (sfId) {
|
||||
if (_gen !== _noteGeneration) return;
|
||||
var _pend = _pendingNoteOns[_pendKey];
|
||||
if (_pend) {
|
||||
_pendingNoteOns[_pendKey] = _pend - 1;
|
||||
if (_pendingNoteOns[_pendKey] <= 0) delete _pendingNoteOns[_pendKey];
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
if (!sfId) {
|
||||
// Không autosample được (404/501) → fallback oscillator để note
|
||||
// KHÔNG câm; cooldown trong ensure chặn re-request.
|
||||
try { self._playNoteFallback(note, velocity, durationMs, startTime, program, null, channel, synthEngine); } catch (e) {}
|
||||
return;
|
||||
}
|
||||
synthEngine.autosampled_sf_id = sfId;
|
||||
doNote();
|
||||
});
|
||||
return;
|
||||
}
|
||||
var cachedCh = _channels[ch];
|
||||
// The note's own synth engine (track instrument) is
|
||||
// authoritative. Channel state is only a cache: it must never
|
||||
|
||||
Reference in New Issue
Block a user