| mergeInto(LibraryManager.library, { |
| $WebGLTenVad: { |
| module: null, |
| modulePromise: null, |
| handles: null, |
| nextInstanceId: 1, |
| ready: false, |
| loading: false, |
| failed: false, |
| lastError: "", |
|
|
| ensureHandles: function() { |
| if (!WebGLTenVad.handles) { |
| WebGLTenVad.handles = {}; |
| } |
| }, |
|
|
| getStreamingAssetsBaseUrl: function() { |
| var basePath = "StreamingAssets"; |
|
|
| if (typeof Module !== "undefined") { |
| if (Module.streamingAssetsUrl) { |
| basePath = Module.streamingAssetsUrl; |
| } else if (Module.absoluteStreamingAssetsUrl) { |
| basePath = Module.absoluteStreamingAssetsUrl; |
| } |
| } |
|
|
| if (basePath.length > 0 && basePath.charAt(basePath.length - 1) === "/") { |
| basePath = basePath.substring(0, basePath.length - 1); |
| } |
|
|
| return basePath; |
| }, |
|
|
| buildStreamingAssetUrl: function(fileName) { |
| var combinedPath = WebGLTenVad.getStreamingAssetsBaseUrl() + "/" + fileName; |
|
|
| if (typeof URL !== "undefined" && typeof document !== "undefined" && document.baseURI) { |
| try { |
| return new URL(combinedPath, document.baseURI).toString(); |
| } catch (err) { |
| |
| } |
| } |
|
|
| return combinedPath; |
| }, |
|
|
| ensureModuleLoading: function() { |
| var vad = WebGLTenVad; |
| if (vad.ready && vad.module) { |
| return Promise.resolve(vad.module); |
| } |
|
|
| if (vad.modulePromise) { |
| return vad.modulePromise; |
| } |
|
|
| var moduleUrl = WebGLTenVad.buildStreamingAssetUrl("ten_vad.js"); |
| var wasmUrl = WebGLTenVad.buildStreamingAssetUrl("ten_vad.wasm"); |
|
|
| vad.loading = true; |
| vad.failed = false; |
| vad.lastError = ""; |
|
|
| vad.modulePromise = import(moduleUrl) |
| .then(function(namespace) { |
| var createFactory = null; |
| if (namespace) { |
| if (typeof namespace.default === "function") { |
| createFactory = namespace.default; |
| } else if (typeof namespace.createVADModule === "function") { |
| createFactory = namespace.createVADModule; |
| } |
| } |
|
|
| if (!createFactory) { |
| throw new Error("ten_vad.js does not export a VAD module factory."); |
| } |
|
|
| return createFactory({ |
| locateFile: function(path) { |
| if (path === "ten_vad.wasm") { |
| return wasmUrl; |
| } |
|
|
| var slashIndex = wasmUrl.lastIndexOf("/"); |
| if (slashIndex >= 0) { |
| return wasmUrl.substring(0, slashIndex + 1) + path; |
| } |
|
|
| return path; |
| } |
| }); |
| }) |
| .then(function(moduleInstance) { |
| if (!moduleInstance || typeof moduleInstance._ten_vad_create !== "function") { |
| throw new Error("Loaded module is missing ten_vad exports."); |
| } |
|
|
| vad.module = moduleInstance; |
| vad.ready = true; |
| vad.loading = false; |
| vad.failed = false; |
| console.log("[WebGLTenVad] ten_vad module loaded."); |
| return moduleInstance; |
| }) |
| ["catch"](function(err) { |
| vad.module = null; |
| vad.ready = false; |
| vad.loading = false; |
| vad.failed = true; |
| vad.lastError = err && err.message ? err.message : String(err); |
| console.warn("[WebGLTenVad] Failed to load ten_vad module:", err); |
| return null; |
| }); |
|
|
| return vad.modulePromise; |
| }, |
|
|
| createInstance: function(hopSize, threshold) { |
| var vad = WebGLTenVad; |
| if (!vad.ready || !vad.module) { |
| if (vad.failed) { |
| return -1; |
| } |
|
|
| WebGLTenVad.ensureModuleLoading(); |
| return -2; |
| } |
|
|
| var moduleInstance = vad.module; |
| var handlePtr = moduleInstance._malloc(4); |
| if (!handlePtr) { |
| vad.lastError = "Failed to allocate handle pointer."; |
| return -1; |
| } |
|
|
| try { |
| var result = moduleInstance._ten_vad_create(handlePtr, hopSize, threshold); |
| if (result !== 0) { |
| vad.lastError = "ten_vad_create failed: " + result; |
| return -1; |
| } |
|
|
| var nativeHandle = moduleInstance.HEAP32[handlePtr >> 2]; |
| if (!nativeHandle) { |
| vad.lastError = "ten_vad_create returned an invalid handle."; |
| return -1; |
| } |
|
|
| WebGLTenVad.ensureHandles(); |
| var instanceId = vad.nextInstanceId++; |
| vad.handles[instanceId] = { |
| nativeHandle: nativeHandle, |
| inputPtr: 0, |
| inputCapacity: 0, |
| probPtr: 0, |
| flagPtr: 0 |
| }; |
| return instanceId; |
| } catch (err) { |
| vad.lastError = err && err.message ? err.message : String(err); |
| console.warn("[WebGLTenVad] createInstance failed:", err); |
| return -1; |
| } finally { |
| moduleInstance._free(handlePtr); |
| } |
| }, |
|
|
| process: function(instanceId, audioPtr, audioLength, outProbabilityPtr, outFlagPtr) { |
| var vad = WebGLTenVad; |
| if (!vad.ready || !vad.module) { |
| if (vad.failed) { |
| return -1; |
| } |
|
|
| WebGLTenVad.ensureModuleLoading(); |
| return -2; |
| } |
|
|
| WebGLTenVad.ensureHandles(); |
| var instance = vad.handles[instanceId]; |
| if (!instance || !instance.nativeHandle) { |
| vad.lastError = "Invalid instance id: " + instanceId; |
| return -1; |
| } |
|
|
| if (!audioPtr || audioLength <= 0 || !outProbabilityPtr || !outFlagPtr) { |
| vad.lastError = "Invalid process arguments."; |
| return -1; |
| } |
|
|
| var moduleInstance = vad.module; |
|
|
| try { |
| if (!instance.inputPtr || instance.inputCapacity < audioLength) { |
| if (instance.inputPtr) { |
| moduleInstance._free(instance.inputPtr); |
| } |
|
|
| instance.inputPtr = moduleInstance._malloc(audioLength * 2); |
| instance.inputCapacity = instance.inputPtr ? audioLength : 0; |
| if (!instance.inputPtr) { |
| vad.lastError = "Failed to allocate process input buffer."; |
| return -1; |
| } |
| } |
|
|
| if (!instance.probPtr) { |
| instance.probPtr = moduleInstance._malloc(4); |
| if (!instance.probPtr) { |
| vad.lastError = "Failed to allocate process probability buffer."; |
| return -1; |
| } |
| } |
|
|
| if (!instance.flagPtr) { |
| instance.flagPtr = moduleInstance._malloc(4); |
| if (!instance.flagPtr) { |
| vad.lastError = "Failed to allocate process flag buffer."; |
| return -1; |
| } |
| } |
|
|
| var sourceData = HEAP16.subarray(audioPtr >> 1, (audioPtr >> 1) + audioLength); |
| moduleInstance.HEAP16.set(sourceData, instance.inputPtr >> 1); |
|
|
| var result = moduleInstance._ten_vad_process(instance.nativeHandle, instance.inputPtr, audioLength, instance.probPtr, instance.flagPtr); |
| if (result !== 0) { |
| vad.lastError = "ten_vad_process failed: " + result; |
| return result; |
| } |
|
|
| HEAPF32[outProbabilityPtr >> 2] = moduleInstance.HEAPF32[instance.probPtr >> 2]; |
| HEAP32[outFlagPtr >> 2] = moduleInstance.HEAP32[instance.flagPtr >> 2]; |
| return 0; |
| } catch (err) { |
| vad.lastError = err && err.message ? err.message : String(err); |
| console.warn("[WebGLTenVad] process failed:", err); |
| return -1; |
| } |
| }, |
|
|
| destroyInstance: function(instanceId) { |
| var vad = WebGLTenVad; |
| WebGLTenVad.ensureHandles(); |
|
|
| var instance = vad.handles[instanceId]; |
| if (!instance || !instance.nativeHandle) { |
| return 0; |
| } |
|
|
| delete vad.handles[instanceId]; |
|
|
| if (!vad.ready || !vad.module) { |
| return 0; |
| } |
|
|
| var moduleInstance = vad.module; |
| var handlePtr = moduleInstance._malloc(4); |
| if (!handlePtr) { |
| return -1; |
| } |
|
|
| try { |
| if (instance.inputPtr) { |
| moduleInstance._free(instance.inputPtr); |
| instance.inputPtr = 0; |
| } |
| if (instance.probPtr) { |
| moduleInstance._free(instance.probPtr); |
| instance.probPtr = 0; |
| } |
| if (instance.flagPtr) { |
| moduleInstance._free(instance.flagPtr); |
| instance.flagPtr = 0; |
| } |
|
|
| moduleInstance.HEAP32[handlePtr >> 2] = instance.nativeHandle; |
| return moduleInstance._ten_vad_destroy(handlePtr); |
| } catch (err) { |
| console.warn("[WebGLTenVad] destroyInstance failed:", err); |
| return -1; |
| } finally { |
| moduleInstance._free(handlePtr); |
| } |
| }, |
|
|
| getState: function() { |
| var vad = WebGLTenVad; |
| if (vad.ready && vad.module) { |
| return 1; |
| } |
| if (vad.failed) { |
| return -1; |
| } |
| if (vad.loading || vad.modulePromise) { |
| return 0; |
| } |
|
|
| return 0; |
| } |
| }, |
|
|
| WebGLTenVad_Create__deps: ["$WebGLTenVad"], |
| WebGLTenVad_Create: function(hopSize, threshold) { |
| return WebGLTenVad.createInstance(hopSize, threshold); |
| }, |
|
|
| WebGLTenVad_Process__deps: ["$WebGLTenVad"], |
| WebGLTenVad_Process: function(instanceId, audioPtr, audioLength, outProbabilityPtr, outFlagPtr) { |
| return WebGLTenVad.process(instanceId, audioPtr, audioLength, outProbabilityPtr, outFlagPtr); |
| }, |
|
|
| WebGLTenVad_Destroy__deps: ["$WebGLTenVad"], |
| WebGLTenVad_Destroy: function(instanceId) { |
| return WebGLTenVad.destroyInstance(instanceId); |
| }, |
|
|
| WebGLTenVad_GetState__deps: ["$WebGLTenVad"], |
| WebGLTenVad_GetState: function() { |
| return WebGLTenVad.getState(); |
| } |
| }); |
|
|