fix: clean sfload with _allocCStr helper + printErr debug + verbose FluidSynth

- Thay MEMFS path từ /soundfonts/ → root / (tránh lỗi thư mục)
- Helper _allocCStr + _tryLoadSFL: unique filename, manual C string alloc, cleanup
- Thêm printErr callback để capture FluidSynth C stderr log
- Bật synth.verbose=1, synth.ladspa.active=0
- Loại bỏ _fluid_synth_get_sfont_count (không export)
- Log buffer magic bytes (RIFF/sfbk) để verify file valid
This commit is contained in:
2026-07-27 14:56:07 +07:00
parent 6fe0cd8d61
commit a887db587f
+36 -26
View File
@@ -81,7 +81,10 @@
}
return path;
},
TOTAL_MEMORY: TOTAL_MEMORY
TOTAL_MEMORY: TOTAL_MEMORY,
printErr: function (msg) {
if (msg.indexOf('stderr') === -1) console.warn('[FluidSynth:err]', msg);
}
});
if (!_fluidModule || !_fluidModule._new_fluid_settings) {
@@ -89,9 +92,13 @@
}
_settingsPtr = _fluidModule._new_fluid_settings();
_fluidModule._fluid_settings_setnum(_settingsPtr, "synth.sample-rate", _audioCtx.sampleRate);
_fluidModule._fluid_settings_setnum(_settingsPtr, "synth.sample-rate", _audioCtx.sampleRate || 44100);
_fluidModule._fluid_settings_setnum(_settingsPtr, "synth.gain", 0.5);
_fluidModule._fluid_settings_setnum(_settingsPtr, "synth.polyphony", 256);
_fluidModule._fluid_settings_setint(_settingsPtr, "synth.verbose", 1);
_fluidModule._fluid_settings_setint(_settingsPtr, "synth.ladspa.active", 0);
_fluidModule._fluid_settings_setstr(_settingsPtr, "player.timing-source", "audio");
console.log("[SonicSF] FluidSynth settings configured");
_synthPtr = _fluidModule._new_fluid_synth(_settingsPtr);
if (!_synthPtr) throw new Error("Failed to create FluidSynth synthesizer");
@@ -117,6 +124,26 @@
return _initPromise;
},
_allocCStr: function (str) {
var ptr = _fluidModule._malloc(str.length + 1);
for (var i = 0; i < str.length; i++) {
_fluidModule.HEAPU8[ptr + i] = str.charCodeAt(i);
}
_fluidModule.HEAPU8[ptr + str.length] = 0;
return ptr;
},
_tryLoadSFL: function (buf, ext) {
var fname = '/' + ext + '_' + Date.now();
try { _fluidModule.FS.unlink(fname); } catch (e) {}
_fluidModule.FS.writeFile(fname, new Uint8Array(buf));
var cPath = this._allocCStr(fname);
var handle = _fluidModule._fluid_synth_sfload(_synthPtr, cPath, 1);
_fluidModule._free(cPath);
try { _fluidModule.FS.unlink(fname); } catch (e) {}
return handle;
},
loadSoundFont: async function (sfId) {
if (!_initialized || !_fluidModule) return false;
if (_currentSfId === sfId) return true;
@@ -137,31 +164,14 @@
buf = await resp.arrayBuffer();
if (cache) await cache.saveBuffer(sfId, buf);
}
var ext = '.sf3';
var virtualPath = '/soundfonts/' + sfId + ext;
console.log("[SonicSF] Writing to MEMFS:", virtualPath, (buf.byteLength / 1024 / 1024).toFixed(2) + 'MB');
try { _fluidModule.FS.unlink(virtualPath); } catch (e) {}
_fluidModule.FS.writeFile(virtualPath, new Uint8Array(buf));
var fsSize = 0;
try { fsSize = _fluidModule.FS.stat(virtualPath).size; } catch (e) {}
console.log("[SonicSF] MEMFS stat:", fsSize, "bytes");
var sfHandle = _fluidModule._fluid_synth_sfload(_synthPtr, virtualPath, 1);
var sfHandle = this._tryLoadSFL(buf, '.sf3');
if (sfHandle === -1) {
var errPtr = _fluidModule._fluid_synth_error(_synthPtr);
var errMsg = errPtr ? _fluidModule.UTF8ToString(errPtr) : "unknown";
console.warn("[SonicSF] sfload failed for", sfId, "as", ext, "error:", errMsg);
try { _fluidModule.FS.unlink(virtualPath); } catch (e) {}
ext = '.sf2';
virtualPath = '/soundfonts/' + sfId + ext;
_fluidModule.FS.writeFile(virtualPath, new Uint8Array(buf));
sfHandle = _fluidModule._fluid_synth_sfload(_synthPtr, virtualPath, 1);
if (sfHandle === -1) {
var errPtr2 = _fluidModule._fluid_synth_error(_synthPtr);
var errMsg2 = errPtr2 ? _fluidModule.UTF8ToString(errPtr2) : "unknown";
console.error("[SonicSF] FluidSynth failed to parse", sfId, "even as .sf2:", errMsg2);
return false;
}
console.log("[SonicSF] Loaded", sfId, "as .sf2 fallback, handle:", sfHandle);
console.warn("[SonicSF] sfload .sf3 failed, trying .sf2 for", sfId);
sfHandle = this._tryLoadSFL(buf, '.sf2');
}
if (sfHandle === -1) {
console.error("[SonicSF] FluidSynth failed to parse SoundFont:", sfId);
return false;
}
_sfHandleMap.set(sfId, sfHandle);
_currentSfId = sfId;