fix: gracefully fallback to oscillator when SpessaSynth bank load fails

- SpessaSynth init tries to load default bank, gracefully handles failure
- When bank load fails, _currentSfId stays null → _playNoteOsc fallback
- Client preview: oscillator emulation (approximate GM sound)
- Server-side render via FluidSynth: authentic SoundFont audio
This commit is contained in:
2026-07-26 19:32:32 +07:00
parent 6a2522d039
commit 6d9060a52b
+33 -2
View File
@@ -60,16 +60,46 @@
await audioContext.audioWorklet.addModule(procUrl); await audioContext.audioWorklet.addModule(procUrl);
_synthInstance = new window.SpessaSynthClass(audioContext); _synthInstance = new window.SpessaSynthClass(audioContext);
await _synthInstance.isReady; await _synthInstance.isReady;
// Load default SF2 to verify parsing works
try {
const resp = await fetch("/api/v1/plugins/soundfonts/download/sgm_v2.01?t=" + Date.now());
if (resp.ok) {
const buf = await resp.arrayBuffer();
await _synthInstance.soundBankManager.addSoundBank(buf.slice(0), "sgm_v2.01");
await _synthInstance.isReady;
// Check if presets were loaded by querying soundBankList
const bankCount = _synthInstance.soundBankManager?.soundBankList?.length ?? 0;
console.log("[SonicSF] SpessaSynth initialized. Banks loaded:", bankCount);
if (bankCount > 0) {
_initialized = true;
_initInProgress = false;
return;
}
}
} catch (bankErr) {
console.warn("[SonicSF] Default bank load failed:", bankErr);
}
// Fallback: init without bank — oscillator will handle preview
_initialized = true; _initialized = true;
_initInProgress = false; _initInProgress = false;
console.log("[SonicSF] SpessaSynth initialized via AudioWorklet."); console.log("[SonicSF] SpessaSynth initialized (no sound bank). Oscillator fallback active.");
} catch (e) { } catch (e) {
_initInProgress = false; _initInProgress = false;
console.warn("[SonicSF] AudioWorklet failed, trying WorkerSynthesizer:", e); console.warn("[SonicSF] AudioWorklet failed:", e);
// Try WorkerSynthesizer as fallback
try { try {
const mod = await import("https://cdn.jsdelivr.net/npm/spessasynth_lib@4.3.1/dist/index.js"); const mod = await import("https://cdn.jsdelivr.net/npm/spessasynth_lib@4.3.1/dist/index.js");
_synthInstance = new mod.WorkerSynthesizer(audioContext); _synthInstance = new mod.WorkerSynthesizer(audioContext);
await _synthInstance.isReady; await _synthInstance.isReady;
try {
const resp = await fetch("/api/v1/plugins/soundfonts/download/sgm_v2.01?t=" + Date.now());
if (resp.ok) {
const buf = await resp.arrayBuffer();
await _synthInstance.soundBankManager.addSoundBank(buf.slice(0), "sgm_v2.01");
await _synthInstance.isReady;
console.log("[SonicSF] Worker synth with bank OK.");
}
} catch (e2) {}
_initialized = true; _initialized = true;
console.log("[SonicSF] SpessaSynth initialized via Worker."); console.log("[SonicSF] SpessaSynth initialized via Worker.");
} catch (e2) { } catch (e2) {
@@ -77,6 +107,7 @@
} }
} }
}, },
},
// ── Load SF3 from IndexedDB cache or server ── // ── Load SF3 from IndexedDB cache or server ──
loadSoundFont: async function (sfId) { loadSoundFont: async function (sfId) {