Enforce one nameing convention

This commit is contained in:
msqr1
2024-08-19 18:53:52 -07:00
parent 01105868c6
commit 2122902190
24 changed files with 211 additions and 211 deletions

34
src/Bindings.cc Normal file
View File

@@ -0,0 +1,34 @@
#include "CommonModel.h"
#include "Recognizer.h"
#include <emscripten/bind.h>
using namespace emscripten;
EMSCRIPTEN_BINDINGS() {
function("setLogLevel", &vosk_set_log_level, allow_raw_pointers());
enum_<VoskEndpointerMode>("EpMode")
.value("ANSWER_DEFAULT", VOSK_EP_ANSWER_DEFAULT)
.value("ANSWER_SHORT", VOSK_EP_ANSWER_SHORT)
.value("ANSWER_LONG", VOSK_EP_ANSWER_LONG)
.value("ANSWER_VERY_LONG", VOSK_EP_ANSWER_VERY_LONG);
class_<CommonModel>("CommonModel")
.constructor<int, bool, std::string, std::string, int, int>(allow_raw_pointers())
.function("findWord", &CommonModel::findWord, allow_raw_pointers());
class_<Recognizer>("Recognizer")
.constructor<int, float, CommonModel*>(allow_raw_pointers())
.constructor<int, float, CommonModel*, CommonModel*>(allow_raw_pointers())
.constructor<int, float, CommonModel*, std::string, int>(allow_raw_pointers())
.function("pushData", &Recognizer::pushData, allow_raw_pointers())
.function("reset", &Recognizer::reset, allow_raw_pointers())
.function("setEndpointerMode", &Recognizer::setEndpointerMode, allow_raw_pointers())
.function("setEndpointerDelays", &Recognizer::setEndpointerDelays, allow_raw_pointers())
.function("setWords", &Recognizer::setWords, allow_raw_pointers())
.function("setPartialWords", &Recognizer::setPartialWords, allow_raw_pointers())
.function("setGrm", &Recognizer::setGrm, allow_raw_pointers())
.function("setNLSML", &Recognizer::setNLSML, allow_raw_pointers())
.function("setSpkModel", &Recognizer::setSpkModel, allow_raw_pointers())
.function("setMaxAlternatives", &Recognizer::setMaxAlternatives, allow_raw_pointers());
};

39
src/CommonModel.cc Normal file
View File

@@ -0,0 +1,39 @@
#include "CommonModel.h"
CommonModel::CommonModel(int index, bool normalMdl, std::string storepath, std::string id, int tarStart, int tarSize) : normalMdl{normalMdl}, index{index}, storepath{std::move(storepath)}, id{std::move(id)} {
t = std::thread{extractAndLoad, reinterpret_cast<unsigned char*>(tarStart), tarSize};
}
void CommonModel::extractAndLoad(unsigned char* tar, int tarSize) {
int res{untar(tar, tarSize, storepath)};
free(tar);
switch(res) {
case IncorrectFormat:
fireEv(index, "Untar: Incorrect tar format, must be USTAR");
return;
case IncorrectFiletype:
fireEv(index, "Untar: Not a directory or regular file");
return;
case FailedOpen:
fireEv(index, "Untar: Unable to open file for write");
return;
case FailedWrite:
fireEv(index, "Untar: Unable to write file");
return;
case FailedClose:
fireEv(index, "Untar: Unable to close file after write");
return;
};
if(normalMdl) mdl = vosk_model_new(storepath.c_str());
else mdl = vosk_spk_model_new(storepath.c_str());
if(normalMdl ? std::get<VoskModel*>(mdl) != nullptr : std::get<VoskSpkModel*>(mdl) != nullptr) fireEv(index, "0");
else fireEv(index, "Unable to load model for recognition");
fs::remove_all(storepath);
}
int CommonModel::findWord(std::string word) {
return vosk_model_find_word(std::get<VoskModel*>(mdl), word.c_str());
}
CommonModel::~CommonModel() {
if(normalMdl) vosk_model_free(std::get<VoskModel*>(mdl));
else vosk_spk_model_free(std::get<VoskSpkModel*>(mdl));
if(t.joinable()) t.join();
}

21
src/CommonModel.h Normal file
View File

@@ -0,0 +1,21 @@
#pragma once
#include "Util.h"
#include <vosk_api.h>
extern void free(void*);
struct CommonModel {
bool normalMdl;
bool thrdUsed{};
int index;
std::thread t;
std::string storepath;
std::string id;
std::variant<VoskModel*, VoskSpkModel*> mdl;
void extractAndLoad(unsigned char* tarStart, int tarSize);
int findWord(std::string word);
CommonModel(int index, bool normalMdl, std::string storepath, std::string id, int tarStart, int tarSize);
~CommonModel();
};

View File

@@ -1,57 +1,60 @@
#include "recognizer.h"
recognizer::recognizer(int index, float sampleRate, genericModel* model) : index{index}, rec{vosk_recognizer_new(std::get<VoskModel*>(model->mdl),sampleRate)} {
recognizer::recognizer(int index, float sampleRate, CommonModel* model) : index{index}, rec{vosk_recognizer_new(std::get<VoskModel*>(model->mdl),sampleRate)}, t{std::move(model->t)} {
finishConstruction(model);
}
recognizer::recognizer(int index, float sampleRate, genericModel* model, genericModel* spkModel) : index{index}, rec{vosk_recognizer_new_spk(std::get<VoskModel*>(model->mdl), sampleRate, std::get<VoskSpkModel*>(spkModel->mdl))} {
recognizer::recognizer(int index, float sampleRate, CommonModel* model, CommonModel* spkModel) : index{index}, rec{vosk_recognizer_new_spk(std::get<VoskModel*>(model->mdl), sampleRate, std::get<VoskSpkModel*>(spkModel->mdl))}, t{std::move(model->t)} {
finishConstruction(model, spkModel);
}
recognizer::recognizer(int index, float sampleRate, genericModel* model, const std::string& grm, int) : index{index}, rec{vosk_recognizer_new_grm(std::get<VoskModel*>(model->mdl), sampleRate, grm.c_str())} {
recognizer::recognizer(int index, float sampleRate, CommonModel* model, const std::string& grm, int) : index{index}, rec{vosk_recognizer_new_grm(std::get<VoskModel*>(model->mdl), sampleRate, grm.c_str())}, t{std::move(model->t)} {
finishConstruction(model);
}
recognizer::~recognizer() {
done = true;
vosk_recognizer_free(rec);
if(t.joinable()) t.join();
}
void recognizer::finishConstruction(genericModel* model, genericModel* spkModel) {
void recognizer::finishConstruction(CommonModel* model, CommonModel* spkModel) {
if(rec == nullptr) {
fireEv(index, "Unable to initialize recognizer");
return;
}
auto main {[this](){
fireEv(index, "0");
audioData* next;
while(!done) {
blocker.wait(done, std::memory_order_relaxed);
blocker = false;
next = &dataQ.front();
while(!dataQ.empty()) {
switch(vosk_recognizer_accept_waveform_f(rec, dataQ.front().data, dataQ.front().len)) {
switch(vosk_recognizer_accept_waveform_f(rec, next->data, next->len)) {
case 0:
fireEv(index, vosk_recognizer_result(rec), "result");
break;
case 1:
fireEv(index, vosk_recognizer_partial_result(rec), "partialResult");
}
free(dataQ.front().data);
free(next->data);
dataQ.pop();
}
}
}};
if(!model->resourceUsed) {
model->resourceUsed = true;
if(!model->thrdUsed) {
model->thrdUsed = true;
model->func = main;
model->blocker = true;
model->blocker.notify_one();
return;
}
if(spkModel != nullptr && !spkModel->resourceUsed) {
spkModel->resourceUsed = true;
if(spkModel != nullptr && !spkModel->thrdUsed) {
spkModel->thrdUsed = true;
spkModel->func = main;
spkModel->blocker = true;
model->blocker.notify_one();
return;
}
std::thread t{main};
t.detach();
blocker.is_always_lock_free
std::thread{main}.detach();
}
void recognizer::pushData(int start, int len) {
dataQ.emplace(start, len);
@@ -70,11 +73,11 @@ void recognizer::setEndpointerDelays(float tStartMax, float tEnd, float tMax) {
void recognizer::setGrm(const std::string& grm) {
vosk_recognizer_set_grm(rec, grm.c_str());
}
void recognizer::setSpkModel(genericModel* spkModel) {
void recognizer::setSpkModel(CommonModel* spkModel) {
vosk_recognizer_set_spk_model(rec, std::get<VoskSpkModel*>(spkModel->mdl));
}
void recognizer::setWords(bool words) {
vosk_recognizer_set_words(rec,words);
vosk_recognizer_set_words(rec, words);
}
void recognizer::setPartialWords(bool partialWords) {
vosk_recognizer_set_partial_words(rec, partialWords);

View File

@@ -1,5 +1,5 @@
#pragma once
#include "genericModel.h"
#include "CommonModel.h"
#include <queue>
@@ -10,22 +10,23 @@ struct audioData {
int len;
audioData(int start, int len) : data{reinterpret_cast<float*>(start)}, len{len} {}
};
struct recognizer {
struct Recognizer {
std::atomic_bool done{};
std::atomic_bool blocker{};
int index;
std::thread t;
VoskRecognizer* rec;
std::queue<audioData> dataQ{};
recognizer(int index, float sampleRate, genericModel* model);
recognizer(int index, float sampleRate, genericModel* model, genericModel* spkModel);
recognizer(int index, float sampleRate, genericModel* model, const std::string& grm, int);
~recognizer();
void finishConstruction(genericModel* model, genericModel* spkModel = nullptr);
std::queue<audioData> dataQ;
Recognizer(int index, float sampleRate, CommonModel* model);
Recognizer(int index, float sampleRate, CommonModel* model, CommonModel* spkModel);
Recognizer(int index, float sampleRate, CommonModel* model, const std::string& grm, int);
~Recognizer();
void finishConstruction(CommonModel* model, CommonModel* spkModel = nullptr);
void pushData(int start, int len);
void reset();
void setEndpointerMode(VoskEndpointerMode mode);
void setEndpointerDelays(float tStartMax, float tEnd, float tMax);
void setSpkModel(genericModel* model);
void setSpkModel(CommonModel* model);
void setGrm(const std::string& grm);
void setWords(bool words);
void setPartialWords(bool partialWords);

View File

@@ -1,12 +1,11 @@
#include "util.h"
#include "Util.h"
void fireEv(int index, const char* content, const char* type) {
MAIN_THREAD_EM_ASM({
objs[$0].dispatchEvent(new CustomEvent($2 === 0 ? "0" : UTF8ToString($2), { "detail" : UTF8ToString($1) }));
}, index, content, type);
}
int untar(unsigned char* tar, int tarSize, const std::string& storepath) {
if(memcmp(tar + 257, "ustar", 5)) return 1;
if(memcmp(tar + 257, "ustar", 5)) return IncorrectFormat;
unsigned char* ptr = tar;
size_t size{0};
std::string path{};
@@ -15,7 +14,7 @@ int untar(unsigned char* tar, int tarSize, const std::string& storepath) {
while(ptr <= end) {
if(ptr[156] != '5' && ptr[156] != 0 &&
ptr[156] != '0') {
return 2;
return IncorrectFiletype;
}
path.clear();
path += reinterpret_cast<char*>(ptr + 345);
@@ -36,12 +35,12 @@ int untar(unsigned char* tar, int tarSize, const std::string& storepath) {
if(size == 0) fs::create_directory(path);
else {
int fd {open(path.c_str(), O_CREAT | O_WRONLY | O_TRUNC, 0777)};
if(fd == -1) return 3;
if(fd == -1) return FailedOpen;
int res = write(fd, ptr, size);
if(res == -1) return 4;
if(close(fd) == -1) return 5;
if(res == -1) return FailedWrite;
if(close(fd) == -1) return FailedClose;
ptr += size + 512 - size % 512;
}
}
return 0;
return Successful;
}

View File

@@ -10,6 +10,13 @@
#include <emscripten/console.h>
namespace fs = std::filesystem;
enum UntarStatus {
Successful,
IncorrectFormat,
IncorrectFiletype,
FailedOpen,
FailedWrite,
FailedClose
};
void fireEv(int index, const char* content, const char* type = nullptr);
int untar(unsigned char* tar, int tarSize, const std::string& storepath);

View File

@@ -44,25 +44,23 @@ async function getFileHandle(path, create = false) {
return prevDir.getFileHandle(components[components.length - 1], { create : create })
}
class genericModel extends EventTarget {
class CommonModel extends EventTarget {
constructor() {
super()
objs.push(this)
}
static async create(url, storepath, id, normalMdl) {
let mdl = new genericModel()
let mdl = new CommonModel()
let result = new Promise((resolve, reject) => {
mdl.addEventListener("0", ev => {
if(ev.detail == "0") {
if(normalMdl) mdl.findWord = (word) => mdl.obj.findWord(word)
return resolve(mdl)
}
mdl.delete()
reject(ev.detail)
}, { once : true })
})
let tar
mdl.obj = new Module.genericModel(objs.length - 1, normalMdl, "/" + storepath, id)
try {
let dataFile = await (await getFileHandle(storepath + "/model.tgz")).getFile()
let idFile = await (await getFileHandle(storepath + "/id")).getFile()
@@ -89,7 +87,7 @@ class genericModel extends EventTarget {
}
let tarStart = Module._malloc(tar.byteLength)
Module.HEAPU8.set(new Uint8Array(tar), tarStart)
mdl.obj.extractAndLoad(tarStart, tar.byteLength)
mdl.obj = new Module.CommonModel(objs.length - 1, normalMdl, "/" + storepath, id, tarStart, tar.byteLength)
return result
}
delete() {
@@ -98,14 +96,14 @@ class genericModel extends EventTarget {
}
Module.createModel = async (url, storepath, id) => {
return genericModel.create(url, storepath, id, true)
return CommonModel.create(url, storepath, id, true)
}
Module.createSpkModel = async (url, storepath, id) => {
return genericModel.create(url, storepath, id, false)
return CommonModel.create(url, storepath, id, false)
}
class recognizer extends EventTarget {
class Recognizer extends EventTarget {
constructor() {
super()
objs.push(this)
@@ -116,7 +114,7 @@ class recognizer extends EventTarget {
})
}
static async create(model, sampleRate, mode, grammar, spkModel) {
let rec = new recognizer()
let rec = new Recognizer()
let result = new Promise((resolve, reject) => {
rec.addEventListener("0", ev => {
if(ev.detail == "0") return resolve(rec)
@@ -126,13 +124,13 @@ class recognizer extends EventTarget {
})
switch(mode) {
case 1:
rec.obj = new Module.recognizer(objs.length - 1, sampleRate, model)
rec.obj = new Module.Recognizer(objs.length - 1, sampleRate, model)
break
case 2:
rec.obj = new Module.recognizer(objs.length -1, sampleRate, model, spkModel)
rec.obj = new Module.Recognizer(objs.length -1, sampleRate, model, spkModel)
break
default:
rec.obj = new Module.recognizer(objs.length - 1, sampleRate, model, grammar, 0)
rec.obj = new Module.Recognizer(objs.length - 1, sampleRate, model, grammar, 0)
}
return result
}
@@ -147,15 +145,15 @@ class recognizer extends EventTarget {
}
Module.createRecognizer = (model, sampleRate) => {
return recognizer.create(model.obj, sampleRate, 1)
return Recognizer.create(model.obj, sampleRate, 1)
}
Module.createRecognizerWithSpkModel = (model, sampleRate, spkModel) => {
return recognizer.create(model.obj, sampleRate, 2, null, spkModel.obj)
return Recognizer.create(model.obj, sampleRate, 2, null, spkModel.obj)
}
Module.createRecognizerWithGrm = (model, sampleRate, grammar) => {
return recognizer.create(model.obj, sampleRate, 3, grammar, null)
return Recognizer.create(model.obj, sampleRate, 3, grammar, null)
}
// See Emscripten issue #21937

View File

@@ -1,35 +0,0 @@
#include "genericModel.h"
#include "recognizer.h"
#include <emscripten/bind.h>
using namespace emscripten;
EMSCRIPTEN_BINDINGS() {
function("setLogLevel", &vosk_set_log_level, allow_raw_pointers());
enum_<VoskEndpointerMode>("EpMode")
.value("ANSWER_DEFAULT", VOSK_EP_ANSWER_DEFAULT)
.value("ANSWER_SHORT", VOSK_EP_ANSWER_SHORT)
.value("ANSWER_LONG", VOSK_EP_ANSWER_LONG)
.value("ANSWER_VERY_LONG", VOSK_EP_ANSWER_VERY_LONG);
class_<genericModel>("genericModel")
.constructor<int, bool, std::string, std::string>(allow_raw_pointers())
.function("extractAndLoad", &genericModel::extractAndLoad, allow_raw_pointers())
.function("findWord", &genericModel::findWord, allow_raw_pointers());
class_<recognizer>("recognizer")
.constructor<int, float, genericModel*>(allow_raw_pointers())
.constructor<int, float, genericModel*, genericModel*>(allow_raw_pointers())
.constructor<int, float, genericModel*, std::string, int>(allow_raw_pointers())
.function("pushData", &recognizer::pushData, allow_raw_pointers())
.function("reset", &recognizer::reset, allow_raw_pointers())
.function("setEndpointerMode", &recognizer::setEndpointerMode, allow_raw_pointers())
.function("setEndpointerDelays", &recognizer::setEndpointerDelays, allow_raw_pointers())
.function("setWords", &recognizer::setWords, allow_raw_pointers())
.function("setPartialWords", &recognizer::setPartialWords, allow_raw_pointers())
.function("setGrm", &recognizer::setGrm, allow_raw_pointers())
.function("setNLSML", &recognizer::setNLSML, allow_raw_pointers())
.function("setSpkModel", &recognizer::setSpkModel, allow_raw_pointers())
.function("setMaxAlternatives", &recognizer::setMaxAlternatives, allow_raw_pointers());
};

View File

@@ -1,44 +0,0 @@
#include "genericModel.h"
genericModel::genericModel(int index, bool normalMdl, std::string storepath, std::string id) : normalMdl{normalMdl}, index{index}, storepath{std::move(storepath)}, id{std::move(id)} {}
void genericModel::extractAndLoad(int tarStart, int tarSize) {
func = [this, tar = reinterpret_cast<unsigned char*>(tarStart), tarSize]() {
int res{untar(tar, tarSize, storepath)};
free(tar);
switch(res) {
case 1:
fireEv(index, "Untar: Incorrect tar format, must be USTAR");
return;
case 2:
fireEv(index, "Untar: Not a directory or regular file");
return;
case 3:
fireEv(index, "Untar: Unable to open file for write");
return;
case 4:
fireEv(index, "Untar: Unable to write file");
return;
case 5:
fireEv(index, "Untar: Unable to close file after write");
return;
};
if(normalMdl) mdl = vosk_model_new(storepath.c_str());
else mdl = vosk_spk_model_new(storepath.c_str());
if(normalMdl ? std::get<VoskModel*>(mdl) != nullptr : std::get<VoskSpkModel*>(mdl) != nullptr) fireEv(index, "0");
else fireEv(index, "Unable to load model for recognition");
fs::remove_all(storepath);
};
std::thread t{[this](){
func();
blocker.wait(false, std::memory_order_relaxed);
func();
}};
t.detach();
}
int genericModel::findWord(std::string word) {
return vosk_model_find_word(std::get<VoskModel*>(mdl), word.c_str());
}
genericModel::~genericModel() {
if(normalMdl) vosk_model_free(std::get<VoskModel*>(mdl));
else vosk_spk_model_free(std::get<VoskSpkModel*>(mdl));
}

View File

@@ -1,21 +0,0 @@
#pragma once
#include "util.h"
#include <vosk_api.h>
extern void free(void*);
struct genericModel {
bool normalMdl;
bool resourceUsed{};
std::atomic_bool blocker{};
int index;
std::string storepath;
std::string id;
std::variant<VoskModel*, VoskSpkModel*> mdl;
std::function<void()> func;
void extractAndLoad(int tarStart, int tarSize);
int findWord(std::string word);
genericModel(int index, bool normalMdl, std::string storepath, std::string id);
~genericModel();
};

View File

@@ -41,7 +41,7 @@ if [ ! -d $OPENFST ]; then
rm -rf /tmp/openfst &&
git clone --depth=1 https://github.com/alphacep/openfst /tmp/openfst &&
cd /tmp/openfst &&
git apply $SRC/openfst.patch
git apply $SRC/Openfst.patch
autoreconf -is &&
CXXFLAGS="-r -O3 -flto -msimd128 -mreference-types -mnontrapping-fptoint -mextended-const -msign-ext -mmutable-globals" LDFLAGS="-O3 -flto" emconfigure ./configure --prefix=$OPENFST --enable-static --disable-shared --enable-lookahead-fsts --enable-ngram-fsts --disable-bin &&
emmake make -j$JOBS install &&
@@ -51,14 +51,14 @@ fi
if [ ! -d $CLAPACK_WASM ]; then
git clone --depth=1 https://gitlab.inria.fr/multispeech/kaldi.web/clapack-wasm.git $CLAPACK_WASM &&
cd $CLAPACK_WASM &&
git apply $SRC/clapack-wasm.patch &&
git apply $SRC/Clapack-wasm.patch &&
bash install_repo.sh emcc
fi
if [ ! -d $KALDI ]; then
git clone -b vosk --depth=1 https://github.com/alphacep/kaldi $KALDI &&
cd $KALDI/src &&
git apply $SRC/kaldi.patch &&
git apply $SRC/Kaldi.patch &&
CXXFLAGS="-O3 -UHAVE_EXECINFO_H -flto -msimd128 -mreference-types -mnontrapping-fptoint -mextended-const -msign-ext -mmutable-globals -Wno-unused-variable -Wno-unused-but-set-variable -g0" LDFLAGS="-O3 -lembind -flto -g0" emconfigure ./configure --use-cuda=no --with-cudadecoder=no --static --static-math=yes --static-fst=yes --debug-level=0 --fst-root=$OPENFST --clapack-root=$CLAPACK_WASM --host=WASM &&
emmake make -j$JOBS online2 rnnlm
fi
@@ -66,14 +66,14 @@ fi
if [ ! -d $VOSK ]; then
git clone -b v0.3.50 --depth=1 https://github.com/alphacep/vosk-api $VOSK &&
cd $VOSK/src &&
git apply $SRC/vosk.patch &&
VOSK_FILES="recognizer.cc language_model.cc model.cc spk_model.cc vosk_api.cc" &&
git apply $SRC/Vosk.patch &&
VOSK_FILES="Recognizer.cc language_model.cc model.cc spk_model.cc vosk_api.cc" &&
em++ -O3 -flto -msimd128 -mreference-types -mnontrapping-fptoint -mextended-const -msign-ext -mmutable-globals -Wno-deprecated -I. -I$KALDI/src -I$OPENFST/include $VOSK_FILES -c &&
emar -rcs vosk.a ${VOSK_FILES//.cc/.o}
fi
cd $SRC &&
em++ util.cc genericModel.cc recognizer.cc bindings.cc -O3 -sWASMFS -sWASM_BIGINT -sSINGLE_FILE -sMODULARIZE -sEMBIND_STD_STRING_IS_UTF8 -sPTHREAD_POOL_DELAY_LOAD -sALLOW_MEMORY_GROWTH -sTEXTDECODER=2 -sPTHREAD_POOL_SIZE_STRICT=2 -sINITIAL_MEMORY=$INITIAL_MEMORY -sPTHREAD_POOL_SIZE=$MAX_THREADS -sPOLYFILL=0 -sEXIT_RUNTIME=0 -sINVOKE_RUN=0 -sSUPPORT_LONGJMP=0 -sEXPORTED_FUNCTIONS=_malloc -sEXPORT_NAME=loadVosklet -sMALLOC=emmalloc -sEXPORTED_RUNTIME_METHODS=UTF8ToString,stringToUTF8OnStack -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 -pthread -flto -msimd128 -mreference-types -mnontrapping-fptoint -mextended-const -msign-ext -mmutable-globals --pre-js wrapper.js -o ../Vosklet.js &&
em++ util.cc CommonModel.cc Recognizer.cc Bindings.cc -O3 -sWASMFS -sWASM_BIGINT -sSINGLE_FILE -sMODULARIZE -sEMBIND_STD_STRING_IS_UTF8 -sPTHREAD_POOL_DELAY_LOAD -sALLOW_MEMORY_GROWTH -sTEXTDECODER=2 -sPTHREAD_POOL_SIZE_STRICT=2 -sINITIAL_MEMORY=$INITIAL_MEMORY -sPTHREAD_POOL_SIZE=$MAX_THREADS -sPOLYFILL=0 -sEXIT_RUNTIME=0 -sINVOKE_RUN=0 -sSUPPORT_LONGJMP=0 -sEXPORTED_FUNCTIONS=_malloc -sEXPORT_NAME=loadVosklet -sMALLOC=emmalloc -sEXPORTED_RUNTIME_METHODS=UTF8ToString,stringToUTF8OnStack -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 -pthread -flto -msimd128 -mreference-types -mnontrapping-fptoint -mextended-const -msign-ext -mmutable-globals --pre-js Wrapper.js -o ../Vosklet.js &&
cd .. &&
rm -f Vosklet.worker.js