Fix regression in recognizer delete()

This commit is contained in:
msqr1
2024-09-28 12:23:33 -07:00
parent 479f611d00
commit 3290a321f2
6 changed files with 29 additions and 30 deletions

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -4,17 +4,18 @@
*/ */
let objs = []; let objs = [];
let events = ["status", "partialResult", "result"]; let events = ['status', 'partialResult', 'result'];
let storageWorkerURL = URL.createObjectURL(new Blob(['(', (() => { let storageWorkerURL = URL.createObjectURL(new Blob(['(', (async () => {
let txtDecoder = new TextDecoder(); let txtDecoder = new TextDecoder();
let txtEncoder = new TextEncoder(); let txtEncoder = new TextEncoder();
let OPFSRoot = await navigator.storage.getDirectory();
onmessage = async msg => { onmessage = async msg => {
msg = msg.data; msg = msg.data;
let components = msg.storepath.split("/"); let components = msg.storepath.split('/');
let prevDir = await navigator.storage.getDirectory(); let prevDir = OPFSRoot;
for(let component of components) prevDir = await prevDir.getDirectoryHandle(component, { create: true }); for(let component of components) prevDir = await prevDir.getDirectoryHandle(component, { create: true });
let idHandle = await prevDir.getFileHandle("id", { create: true }); let idHandle = await prevDir.getFileHandle('id', { create: true });
let mdlHandle = await prevDir.getFileHandle("model.tgz", { create: true }); let mdlHandle = await prevDir.getFileHandle('model.tgz', { create: true });
let idFile = await idHandle.createSyncAccessHandle(); let idFile = await idHandle.createSyncAccessHandle();
let mdlFile = await mdlHandle.createSyncAccessHandle(); let mdlFile = await mdlHandle.createSyncAccessHandle();
let oldIdBuf = new ArrayBuffer(idFile.getSize()); let oldIdBuf = new ArrayBuffer(idFile.getSize());
@@ -23,16 +24,16 @@ let storageWorkerURL = URL.createObjectURL(new Blob(['(', (() => {
if(txtDecoder.decode(oldIdBuf) == msg.id) { if(txtDecoder.decode(oldIdBuf) == msg.id) {
tgz = new ArrayBuffer(mdlFile.getSize()); tgz = new ArrayBuffer(mdlFile.getSize());
mdlFile.read(tgz); mdlFile.read(tgz);
tar = await new Response(new Response(tgz).body.pipeThrough(new DecompressionStream("gzip"))).arrayBuffer(); tar = await new Response(new Response(tgz).body.pipeThrough(new DecompressionStream('gzip'))).arrayBuffer();
} }
else { else {
let res = await fetch(msg.url); let res = await fetch(msg.url);
if(!res.ok) { if(!res.ok) {
postMessage("Unable to download model"); postMessage('Unable to download model');
return; return;
} }
let teed = res.body.tee(); let teed = res.body.tee();
tgz = await new Response(teed[0].pipeThrough(new CompressionStream("gzip"))).arrayBuffer(); tgz = await new Response(teed[0].pipeThrough(new CompressionStream('gzip'))).arrayBuffer();
mdlFile.write(tgz, { at: 0 }); mdlFile.write(tgz, { at: 0 });
mdlFile.truncate(tgz.byteLength); mdlFile.truncate(tgz.byteLength);
let newId = txtEncoder.encode(msg.id); let newId = txtEncoder.encode(msg.id);
@@ -44,10 +45,10 @@ let storageWorkerURL = URL.createObjectURL(new Blob(['(', (() => {
mdlFile.close(); mdlFile.close();
self.postMessage(tar, [tar]); self.postMessage(tar, [tar]);
} }
}).toString(), ')()'], { type: "text/javascript" })) }).toString(), ')()'], { type: 'text/javascript' }))
let storageWorker = new Worker(storageWorkerURL); let storageWorker = new Worker(storageWorkerURL);
let processorURL = URL.createObjectURL(new Blob(['(', (() => { let processorURL = URL.createObjectURL(new Blob(['(', (() => {
registerProcessor("VoskletTransferer", class extends AudioWorkletProcessor { registerProcessor('VoskletTransferer', class extends AudioWorkletProcessor {
constructor(opts) { constructor(opts) {
super(); super();
this.count = 0; this.count = 0;
@@ -65,7 +66,7 @@ let processorURL = URL.createObjectURL(new Blob(['(', (() => {
return true; return true;
} }
}) })
}).toString(), ')()'], { type: "text/javascript" })); }).toString(), ')()'], { type: 'text/javascript' }));
Module['cleanUp'] = async () => { Module['cleanUp'] = async () => {
for(let obj of objs) await obj.delete(); for(let obj of objs) await obj.delete();
@@ -76,8 +77,8 @@ Module['cleanUp'] = async () => {
Module['createTransferer'] = async (ctx, bufferSize) => { Module['createTransferer'] = async (ctx, bufferSize) => {
await ctx.audioWorklet.addModule(processorURL); await ctx.audioWorklet.addModule(processorURL);
return new AudioWorkletNode(ctx, "VoskletTransferer", { return new AudioWorkletNode(ctx, 'VoskletTransferer', {
channelCountMode: "explicit", channelCountMode: 'explicit',
numberOfInputs: 1, numberOfInputs: 1,
numberOfOutputs: 0, numberOfOutputs: 0,
channelCount: 1, channelCount: 1,
@@ -96,19 +97,19 @@ class CommonModel extends EventTarget {
static async mk(url, storepath, id, normalMdl) { static async mk(url, storepath, id, normalMdl) {
let mdl = new CommonModel(); let mdl = new CommonModel();
let result = new Promise((resolve, reject) => { let result = new Promise((resolve, reject) => {
mdl.addEventListener("status", ev => { mdl.addEventListener('status', ev => {
if(!ev.detail) { if(!ev.detail) {
if(normalMdl) mdl['findWord'] = word => mdl.obj['findWord'](word) if(normalMdl) mdl['findWord'] = word => mdl.obj['findWord'](word)
resolve(mdl) resolve(mdl)
} }
else reject(ev.detail) else reject(ev.detail)
}, { once : true }) }, { once: true })
}); });
storageWorker.addEventListener("message", tar => { storageWorker.addEventListener('message', tar => {
tar = tar.data; tar = tar.data;
let tarStart = _malloc(tar.byteLength); let tarStart = _malloc(tar.byteLength);
HEAPU8.set(new Uint8Array(tar), tarStart); HEAPU8.set(new Uint8Array(tar), tarStart);
mdl.obj = new Module['CommonModel'](objs.length - 1, normalMdl, "/" + storepath, id, tarStart, tar.byteLength); mdl.obj = new Module['CommonModel'](objs.length - 1, normalMdl, '/' + storepath, id, tarStart, tar.byteLength);
}, { once: true }); }, { once: true });
storageWorker.postMessage({ storageWorker.postMessage({
url: url, url: url,
@@ -128,7 +129,7 @@ Module['createSpkModel'] = async (url, storepath, id) =>
class Recognizer extends EventTarget { class Recognizer extends EventTarget {
constructor() { constructor() {
super(); super();
// Closure workaround, this is removed if I put it as a regular class function. For some reason delete() doesn't // Closure workaround to prevent acceptWaveform from getting removed
this['acceptWaveform'] = audioData => { this['acceptWaveform'] = audioData => {
let start = _malloc(audioData.length * 4); let start = _malloc(audioData.length * 4);
HEAPF32.set(audioData, start / 4); HEAPF32.set(audioData, start / 4);
@@ -146,17 +147,17 @@ class Recognizer extends EventTarget {
}) })
} }
async delete(processCurrent = false) { async delete(processCurrent = false) {
let result = new Promise((resolve, _) => this.addEventListener("status", _ => { let result = new Promise((resolve, _) => this.addEventListener('status', _ => {
this.obj.delete(); this.obj.delete();
resolve(); resolve();
}, { once: true })); }, { once: true }));
this.obj.safeDelete(processCurrent); this.obj['safeDelete'](processCurrent);
return result; return result;
} }
static async mk(model, sampleRate, mode, grammar, spkModel) { static async mk(model, sampleRate, mode, grammar, spkModel) {
let rec = new Recognizer(); let rec = new Recognizer();
let result = new Promise((resolve, reject) => { let result = new Promise((resolve, reject) => {
rec.addEventListener("status", ev => { rec.addEventListener('status', ev => {
if(!ev.detail) resolve(rec); if(!ev.detail) resolve(rec);
else reject(ev.detail); else reject(ev.detail);
}, { once: true }); }, { once: true });
@@ -183,5 +184,3 @@ Module['createRecognizerWithSpkModel'] = (model, sampleRate, spkModel) =>
Module['createRecognizerWithGrm'] = (model, sampleRate, grammar) => Module['createRecognizerWithGrm'] = (model, sampleRate, grammar) =>
Recognizer.mk(model.obj, sampleRate, 3, grammar, null); Recognizer.mk(model.obj, sampleRate, 3, grammar, null);

6
test
View File

@@ -36,12 +36,12 @@ OPENFST=$(realpath openfst)
CLAPACK_WASM=$(realpath clapack-wasm) CLAPACK_WASM=$(realpath clapack-wasm)
cd src && cd src &&
MODE=1 && # 0: Debug, 1: Optimized release MODE=0 && # 0: Debug, 1: Optimized release
echo "Mode = $MODE" && echo "Mode = $MODE" &&
if [ "$MODE" = 0 ]; then if [ "$MODE" = 0 ]; then
em++ Util.cc CommonModel.cc Recognizer.cc Bindings.cc -O0 -std=c++23 -g3 -Wall -Wextra -Wpedantic -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0 -fno-rtti -DMAX_WORKERS="$MAX_THREADS" -sWASMFS -sWASM_BIGINT -sMODULARIZE -sWASM_EXNREF -sTEXTDECODER=2 -sWASM_WORKERS=2 -sEVAL_CTORS=2 -sSTACK_OVERFLOW_CHECK=2 -sASSERTIONS=2 -sINITIAL_MEMORY="$INITIAL_MEMORY" -sALLOW_MEMORY_GROWTH -sRUNTIME_DEBUG -sPOLYFILL=0 -sEXIT_RUNTIME=0 -sINVOKE_RUN=0 -sDISABLE_EXCEPTION_CATCHING=0 -sINCOMING_MODULE_JS_API=wasmMemory,instantiateWasm,wasm -sEXPORT_NAME=loadVosklet -sMALLOC=emmalloc -sENVIRONMENT=web,worker -I. -I"$VOSK"/src -L"$KALDI"/src -l:online2/kaldi-online2.a -l:decoder/kaldi-decoder.a -l:ivector/kaldi-ivector.a -l:gmm/kaldi-gmm.a -l:tree/kaldi-tree.a -l:feat/kaldi-feat.a -l:cudamatrix/kaldi-cudamatrix.a -l:lat/kaldi-lat.a -l:lm/kaldi-lm.a -l:rnnlm/kaldi-rnnlm.a -l:hmm/kaldi-hmm.a -l:nnet3/kaldi-nnet3.a -l:transform/kaldi-transform.a -l:matrix/kaldi-matrix.a -l:fstext/kaldi-fstext.a -l:util/kaldi-util.a -l:base/kaldi-base.a -L"$OPENFST"/lib -l:libfst.a -l:libfstngram.a -L"$CLAPACK_WASM" -l:CBLAS/lib/cblas.a -l:CLAPACK-3.2.1/lapack.a -l:CLAPACK-3.2.1/libcblaswr.a -l:f2c_BLAS-3.8.0/blas.a -l:libf2c/libf2c.a -L"$VOSK"/src -l:vosk.a -lembind -msimd128 -matomics -mbulk-memory -mreference-types -mnontrapping-fptoint -mextended-const -msign-ext -mmutable-globals --pre-js Wrapper.js -o ../test.js em++ Util.cc CommonModel.cc Recognizer.cc Bindings.cc -O0 -std=c++23 -g3 -Wall -Wextra -Wpedantic -fno-rtti -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0 -DMAX_WORKERS="$MAX_THREADS" -sWASMFS -sWASM_BIGINT -sMODULARIZE -sWASM_EXNREF -sTEXTDECODER=2 -sWASM_WORKERS=2 -sEVAL_CTORS=2 -sSTACK_OVERFLOW_CHECK=2 -sASSERTIONS=2 -sINITIAL_MEMORY="$INITIAL_MEMORY" -sALLOW_MEMORY_GROWTH -sRUNTIME_DEBUG -sPOLYFILL=0 -sEXIT_RUNTIME=0 -sINVOKE_RUN=0 -sDISABLE_EXCEPTION_CATCHING=0 -sINCOMING_MODULE_JS_API=wasmMemory,instantiateWasm,wasm -sEXPORT_NAME=loadVosklet -sMALLOC=emmalloc -sENVIRONMENT=web,worker -I. -I"$VOSK"/src -L"$KALDI"/src -l:online2/kaldi-online2.a -l:decoder/kaldi-decoder.a -l:ivector/kaldi-ivector.a -l:gmm/kaldi-gmm.a -l:tree/kaldi-tree.a -l:feat/kaldi-feat.a -l:cudamatrix/kaldi-cudamatrix.a -l:lat/kaldi-lat.a -l:lm/kaldi-lm.a -l:rnnlm/kaldi-rnnlm.a -l:hmm/kaldi-hmm.a -l:nnet3/kaldi-nnet3.a -l:transform/kaldi-transform.a -l:matrix/kaldi-matrix.a -l:fstext/kaldi-fstext.a -l:util/kaldi-util.a -l:base/kaldi-base.a -L"$OPENFST"/lib -l:libfst.a -l:libfstngram.a -L"$CLAPACK_WASM" -l:CBLAS/lib/cblas.a -l:CLAPACK-3.2.1/lapack.a -l:CLAPACK-3.2.1/libcblaswr.a -l:f2c_BLAS-3.8.0/blas.a -l:libf2c/libf2c.a -L"$VOSK"/src -l:vosk.a -lembind -msimd128 -matomics -mbulk-memory -mreference-types -mnontrapping-fptoint -mextended-const -msign-ext -mmutable-globals --pre-js Wrapper.js -o ../test.js
elif [ "$MODE" = 1 ]; then elif [ "$MODE" = 1 ]; then
em++ Util.cc CommonModel.cc Recognizer.cc Bindings.cc -std=c++23 -O3 -Wall -Wextra -Wpedantic -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0 -fno-rtti -DMAX_WORKERS="$MAX_THREADS" -sWASMFS -sWASM_BIGINT -sMODULARIZE -sWASM_EXNREF -sTEXTDECODER=2 -sWASM_WORKERS=2 -sEVAL_CTORS=2 -sINITIAL_MEMORY="$INITIAL_MEMORY" -sALLOW_MEMORY_GROWTH -sPOLYFILL=0 -sEXIT_RUNTIME=0 -sINVOKE_RUN=0 -sSUPPORT_LONGJMP=0 -sINCOMING_MODULE_JS_API=wasmMemory,instantiateWasm,wasm -sEXPORT_NAME=loadVosklet -sMALLOC=emmalloc -sENVIRONMENT=web,worker -I. -I"$VOSK"/src -L"$KALDI"/src -l:online2/kaldi-online2.a -l:decoder/kaldi-decoder.a -l:ivector/kaldi-ivector.a -l:gmm/kaldi-gmm.a -l:tree/kaldi-tree.a -l:feat/kaldi-feat.a -l:cudamatrix/kaldi-cudamatrix.a -l:lat/kaldi-lat.a -l:lm/kaldi-lm.a -l:rnnlm/kaldi-rnnlm.a -l:hmm/kaldi-hmm.a -l:nnet3/kaldi-nnet3.a -l:transform/kaldi-transform.a -l:matrix/kaldi-matrix.a -l:fstext/kaldi-fstext.a -l:util/kaldi-util.a -l:base/kaldi-base.a -L"$OPENFST"/lib -l:libfst.a -l:libfstngram.a -L"$CLAPACK_WASM" -l:CBLAS/lib/cblas.a -l:CLAPACK-3.2.1/lapack.a -l:CLAPACK-3.2.1/libcblaswr.a -l:f2c_BLAS-3.8.0/blas.a -l:libf2c/libf2c.a -L"$VOSK"/src -l:vosk.a -lembind -flto -msimd128 -matomics -mbulk-memory -mreference-types -mnontrapping-fptoint -mextended-const -msign-ext -mmutable-globals --pre-js Wrapper.js --closure 1 -o ../test.js && em++ Util.cc CommonModel.cc Recognizer.cc Bindings.cc -std=c++23 -O3 -Wall -Wextra -Wpedantic -fno-rtti -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0 -DMAX_WORKERS="$MAX_THREADS" -sWASMFS -sWASM_BIGINT -sMODULARIZE -sWASM_EXNREF -sTEXTDECODER=2 -sWASM_WORKERS=2 -sEVAL_CTORS=2 -sINITIAL_MEMORY="$INITIAL_MEMORY" -sALLOW_MEMORY_GROWTH -sPOLYFILL=0 -sEXIT_RUNTIME=0 -sINVOKE_RUN=0 -sSUPPORT_LONGJMP=0 -sINCOMING_MODULE_JS_API=wasmMemory,instantiateWasm,wasm -sEXPORT_NAME=loadVosklet -sMALLOC=emmalloc -sENVIRONMENT=web,worker -I. -I"$VOSK"/src -L"$KALDI"/src -l:online2/kaldi-online2.a -l:decoder/kaldi-decoder.a -l:ivector/kaldi-ivector.a -l:gmm/kaldi-gmm.a -l:tree/kaldi-tree.a -l:feat/kaldi-feat.a -l:cudamatrix/kaldi-cudamatrix.a -l:lat/kaldi-lat.a -l:lm/kaldi-lm.a -l:rnnlm/kaldi-rnnlm.a -l:hmm/kaldi-hmm.a -l:nnet3/kaldi-nnet3.a -l:transform/kaldi-transform.a -l:matrix/kaldi-matrix.a -l:fstext/kaldi-fstext.a -l:util/kaldi-util.a -l:base/kaldi-base.a -L"$OPENFST"/lib -l:libfst.a -l:libfstngram.a -L"$CLAPACK_WASM" -l:CBLAS/lib/cblas.a -l:CLAPACK-3.2.1/lapack.a -l:CLAPACK-3.2.1/libcblaswr.a -l:f2c_BLAS-3.8.0/blas.a -l:libf2c/libf2c.a -L"$VOSK"/src -l:vosk.a -lembind -flto -msimd128 -matomics -mbulk-memory -mreference-types -mnontrapping-fptoint -mextended-const -msign-ext -mmutable-globals --pre-js Wrapper.js --closure 1 -o ../test.js &&
tr -d '\n' < ../test.js | tr -s ' ' > /tmp/hehe && mv /tmp/hehe ../test.js tr -d '\n' < ../test.js | tr -s ' ' > /tmp/hehe && mv /tmp/hehe ../test.js
fi fi
cd .. && cd .. &&