Draft 2 (failed)
This commit is contained in:
19
.gitignore
vendored
19
.gitignore
vendored
@@ -1,10 +1,11 @@
|
||||
.vscode
|
||||
test.sh
|
||||
index.html
|
||||
model.tzst
|
||||
clapack-wasm
|
||||
kaldi
|
||||
libarchive
|
||||
vosk-api
|
||||
zstd
|
||||
test.cc
|
||||
vosk-api
|
||||
kaldi
|
||||
test
|
||||
test.sh
|
||||
libarchive
|
||||
.vscode
|
||||
clapack-wasm
|
||||
node_modules
|
||||
package.json
|
||||
package-lock.json
|
||||
File diff suppressed because one or more lines are too long
@@ -12,34 +12,6 @@
|
||||
|
||||
var Module = {};
|
||||
|
||||
// Node.js support
|
||||
var ENVIRONMENT_IS_NODE = typeof process == 'object' && typeof process.versions == 'object' && typeof process.versions.node == 'string';
|
||||
if (ENVIRONMENT_IS_NODE) {
|
||||
// Create as web-worker-like an environment as we can.
|
||||
|
||||
var nodeWorkerThreads = require('worker_threads');
|
||||
|
||||
var parentPort = nodeWorkerThreads.parentPort;
|
||||
|
||||
parentPort.on('message', (data) => onmessage({ data: data }));
|
||||
|
||||
var fs = require('fs');
|
||||
var vm = require('vm');
|
||||
|
||||
Object.assign(global, {
|
||||
self: global,
|
||||
require,
|
||||
Module,
|
||||
location: {
|
||||
href: __filename
|
||||
},
|
||||
Worker: nodeWorkerThreads.Worker,
|
||||
importScripts: (f) => vm.runInThisContext(fs.readFileSync(f, 'utf8'), {filename: f}),
|
||||
postMessage: (msg) => parentPort.postMessage(msg),
|
||||
performance: global.performance || { now: Date.now },
|
||||
});
|
||||
}
|
||||
|
||||
// Thread-local guard variable for one-time init of the JS state
|
||||
var initializedJS = false;
|
||||
|
||||
@@ -49,11 +21,6 @@ function assert(condition, text) {
|
||||
|
||||
function threadPrintErr() {
|
||||
var text = Array.prototype.slice.call(arguments).join(' ');
|
||||
// See https://github.com/emscripten-core/emscripten/issues/14804
|
||||
if (ENVIRONMENT_IS_NODE) {
|
||||
fs.writeSync(2, text + '\n');
|
||||
return;
|
||||
}
|
||||
console.error(text);
|
||||
}
|
||||
function threadAlert() {
|
||||
@@ -97,6 +64,7 @@ function handleMessage(e) {
|
||||
|
||||
// And add a callback for when the runtime is initialized.
|
||||
self.startWorker = (instance) => {
|
||||
Module = instance;
|
||||
// Notify the main thread that this thread has loaded.
|
||||
postMessage({ 'cmd': 'loaded' });
|
||||
// Process any messages that were queued before the thread was ready.
|
||||
@@ -133,6 +101,7 @@ function handleMessage(e) {
|
||||
importScripts(objectUrl);
|
||||
URL.revokeObjectURL(objectUrl);
|
||||
}
|
||||
loadBR(Module);
|
||||
} else if (e.data.cmd === 'run') {
|
||||
// Pass the thread address to wasm to store it for fast access.
|
||||
Module['__emscripten_thread_init'](e.data.pthread_ptr, /*is_main=*/0, /*is_runtime=*/0, /*can_block=*/1);
|
||||
|
||||
13
README.md
13
README.md
@@ -25,7 +25,7 @@ spkModel.init(url, storepath, id)
|
||||
- ***delete***: Delete self and free resources
|
||||
#### Events
|
||||
- ***ready***: The model is ready to be put into a recognizer via the constructor, or setSpkModel() for SpkModel.
|
||||
- ***error***: An error occured, check the event's **details** property.
|
||||
- ***error***: An error occured, check the event's "details" property.
|
||||
### Recognizer
|
||||
```
|
||||
recognizer = new Recognizer()
|
||||
@@ -43,11 +43,11 @@ recognizer.init(model)
|
||||
- ***setMaxAlternatives***: Set the max number of alternatives for result event (default: false)
|
||||
- ***setGrm***: Add grammar to the recognizer (default: none)
|
||||
- ***setSpkModel***: Set the speaker model of the recognizer (default: none)
|
||||
- ***delete***: Delete self and free resources
|
||||
- ***delete***: Call stop, delete self and free all resource
|
||||
#### Events
|
||||
- ***partialResult***: There is a partial recognition result, check the event's **details** property
|
||||
- ***result***: There is a full recognition result, check the event's **details** property
|
||||
- ***error***: An error occured, check the event's **details** property.
|
||||
- ***partialResult***: There is a partial recognition result, check the event's "details" property
|
||||
- ***result***: There is a full recognition result, check the event's "details" property
|
||||
- ***error***: An error occured, check the event's "details" property.
|
||||
## Other key points
|
||||
### IMPORTANT
|
||||
- You MUST call delete() on objects at the end of its usage. Or put:
|
||||
@@ -56,7 +56,8 @@ recognizer.init(model)
|
||||
__genericObj__.objects.forEach(obj => obj.delete())
|
||||
```
|
||||
at the end of your program to automatically do that. We have to do this because Emscripten doesn't call destructors. See [here](https://emscripten.org/docs/getting_started/FAQ.html#what-does-exiting-the-runtime-mean-why-don-t-atexit-s-run).
|
||||
- To be safe, always handle the API through events by adding all event listener before calling init().
|
||||
- To be safe, always handle the API through events by adding all event listener before calling init() on objects.
|
||||
- Always call init on the regular Model object before calling init on the recognizer. SpkModel can be init and set later.
|
||||
### Guarantees
|
||||
- If an error occurs (error event is fired), no changes was made, and no other dependent events will fire. For example, if an error occur while loading the model, the "ready" event won't fire in order to prevent executing code on a nonexistent model.
|
||||
### Limitations compared to vosk-browser:
|
||||
|
||||
13
index.html
Normal file
13
index.html
Normal file
@@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script src="BrowserRecognizer.js" defer></script>
|
||||
<script type="module" src="src/genericObj.js" defer></script>
|
||||
<script src="src/model.js" defer></script>
|
||||
<script src="src/spkModel.js" defer></script>
|
||||
<script src="src/recognizer.js" defer></script>
|
||||
</head>
|
||||
<script>
|
||||
|
||||
</script>
|
||||
</html>
|
||||
@@ -8,6 +8,8 @@
|
||||
# Total build time is around 45 minutes, mostly from building Kaldi
|
||||
|
||||
sudo apt install shtool libtool autogen autotools-dev pkg-config make &&
|
||||
wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash &&
|
||||
nvm install 20.11.0 &&
|
||||
|
||||
SRC=$(realpath src) &&
|
||||
KALDI=$(realpath kaldi) &&
|
||||
@@ -52,7 +54,7 @@ echo "PACKAGE_VERSION = 1.8.0" >> $OPENFST/Makefile &&
|
||||
|
||||
cd $KALDI/src &&
|
||||
git apply $SRC/kaldi.patch &&
|
||||
CXXFLAGS="-O3 -msse3 -mssse3 -msse4.1 -msse4.2 -mavx -msimd128 -UHAVE_EXECINFO_H -pthread -flto" LDFLAGS="-O3 -sERROR_ON_UNDEFINED_SYMBOLS=0 -lembind -pthread -flto" emconfigure ./configure --use-cuda=no --with-cudadecoder=no --static --static-math=yes --static-fst=yes --double-precision=yes --debug-level=0 --clapack-root=$CLAPACK_WASM --host=WASM &&
|
||||
CXXFLAGS="-O3 -msimd128 -UHAVE_EXECINFO_H -pthread -flto" LDFLAGS="-O3 -sERROR_ON_UNDEFINED_SYMBOLS=0 -lembind -pthread -flto" emconfigure ./configure --use-cuda=no --with-cudadecoder=no --static --static-math=yes --static-fst=yes --debug-level=0 --clapack-root=$CLAPACK_WASM --host=WASM &&
|
||||
emmake make online2 lm rnnlm &&
|
||||
|
||||
cd $VOSK/src &&
|
||||
@@ -61,4 +63,4 @@ em++ -pthread -O3 -flto -I. -I$KALDI/src -I$OPENFST/include $VOSK_FILES -c &&
|
||||
emar -rcs vosk.a ${VOSK_FILES//.cc/.o} &&
|
||||
|
||||
cd $SRC
|
||||
em++ -O3 genericObj.cc genericModel.cc model.cc spkModel.cc recognizer.cc bindings.cc -sWASMFS -sWASM_BIGINT -sSUPPORT_BIG_ENDIAN -sSINGLE_FILE -sINITIAL_MEMORY=300mb -sASYNCIFY -sPTHREAD_POOL_SIZE=2 -pthread --no-entry -flto --post-js genericObj.js --post-js model.js --post-js spkModel.js --post-js recognizer.js -I. -I$LIBARCHIVE/include -I$VOSK/src -L$LIBARCHIVE/lib -larchive -L$ZSTD/lib -lzstd -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 -lopfs.js -lembind -lopenal -o BrowserRecognizer.js
|
||||
em++ -O3 genericObj.cc genericModel.cc model.cc spkModel.cc recognizer.cc bindings.cc -sWASMFS -sWASM_BIGINT -sSUPPORT_BIG_ENDIAN -sSINGLE_FILE -sMODULARIZE -sASYNCIFY -sEXPORT_NAME=loadBR -sENVIRONMENT=web,worker -sINITIAL_MEMORY=300mb -sPTHREAD_POOL_SIZE=2 -pthread -flto -I. -I$LIBARCHIVE/include -I$VOSK/src -L$LIBARCHIVE/lib -larchive -L$ZSTD/lib -lzstd -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 -lopfs.js -lembind -lopenal -o ../BrowserRecognizer.js
|
||||
|
||||
@@ -2,6 +2,13 @@
|
||||
#include "model.h"
|
||||
#include "recognizer.h"
|
||||
using namespace emscripten;
|
||||
int main() {
|
||||
//vosk_set_log_level(-1);
|
||||
std::thread t{[](){
|
||||
wasmfs_create_directory("/opfs",0777,wasmfs_create_opfs_backend());
|
||||
}};
|
||||
t.detach();
|
||||
}
|
||||
EMSCRIPTEN_BINDINGS() {
|
||||
function("setLogLevel", &vosk_set_log_level, allow_raw_pointers());
|
||||
class_<model>("__model__")
|
||||
@@ -14,7 +21,6 @@ EMSCRIPTEN_BINDINGS() {
|
||||
.constructor<model*, int, int>(allow_raw_pointers())
|
||||
.function("start", &recognizer::start, allow_raw_pointers())
|
||||
.function("stop", &recognizer::stop, allow_raw_pointers())
|
||||
.function("deinit", &recognizer::deinit, allow_raw_pointers())
|
||||
.function("setWords", &recognizer::setWords, allow_raw_pointers())
|
||||
.function("setPartialWords", &recognizer::setPartialWords, allow_raw_pointers())
|
||||
.function("setGrm", &recognizer::setGrm, allow_raw_pointers())
|
||||
|
||||
16
src/clapack-wasm.patch
Normal file
16
src/clapack-wasm.patch
Normal file
@@ -0,0 +1,16 @@
|
||||
diff --git a/libf2c/main.c b/libf2c/main.c
|
||||
index d95fdc9..ac82f68 100644
|
||||
--- a/libf2c/main.c
|
||||
+++ b/libf2c/main.c
|
||||
@@ -105,9 +105,9 @@ char **xargv;
|
||||
|
||||
int
|
||||
#ifdef KR_headers
|
||||
-main(argc, argv) int argc; char **argv;
|
||||
+m(argc, argv) int argc; char **argv;
|
||||
#else
|
||||
-main(int argc, char **argv)
|
||||
+m(int argc, char **argv)
|
||||
#endif
|
||||
{
|
||||
xargc = argc;
|
||||
@@ -1,21 +1,9 @@
|
||||
#include "genericModel.h"
|
||||
|
||||
bool genericModel::first = true;
|
||||
genericModel::genericModel(const std::string &url, const std::string& storepath, const std::string &id, int index) : url(url), id(id), genericObj(index) {
|
||||
fs::current_path("/opfs");
|
||||
fs::create_directories(storepath);
|
||||
fs::current_path(storepath);
|
||||
if(first) {
|
||||
vosk_set_log_level(0);
|
||||
int res{};
|
||||
std::thread t{[&res](){
|
||||
res = wasmfs_create_directory("opfs",0777,wasmfs_create_opfs_backend());
|
||||
}};
|
||||
t.join();
|
||||
if(res == 1){
|
||||
fireEv("error", "Unable to create OPFS directory");
|
||||
return;
|
||||
}
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
bool genericModel::checkId(const std::string& id) {
|
||||
std::ifstream file {"id", std::ifstream::binary};
|
||||
@@ -28,42 +16,46 @@ bool genericModel::checkId(const std::string& id) {
|
||||
file.read(&oldid[0], size);
|
||||
return id.compare(oldid) == 0 ? true : false;
|
||||
}
|
||||
bool genericModel::loadModel() {
|
||||
bool genericModel::loadModel(const std::string& storepath) {
|
||||
if(!checkModel() || !checkId(id)) {
|
||||
if(emscripten_wget(url.c_str(),"opfs/model.tzst") == 1) {
|
||||
char filename[] {"/opfs/XXXXXX.tzst"};
|
||||
close(mkostemps(filename, 5, O_PATH));
|
||||
if(emscripten_wget(url.c_str(),filename) == 1) {
|
||||
fireEv("error", "Unable to fetch model");
|
||||
return false;
|
||||
}
|
||||
if(!extractModel()) {
|
||||
if(!extractModel(filename)) {
|
||||
fireEv("error", "Unable to extract model");
|
||||
return false;
|
||||
}
|
||||
fs::remove("opfs/model.tzst");
|
||||
fs::remove(filename);
|
||||
if(!checkModel()) {
|
||||
fireEv("error", "Model URL contains invalid model files");
|
||||
fs::remove_all(".");
|
||||
fs::current_path("/opfs");
|
||||
fs::remove_all(storepath);
|
||||
return false;
|
||||
}
|
||||
std::ofstream idFile("id");
|
||||
if(!idFile.is_open()) {
|
||||
fireEv("error", "Unable to write new id");
|
||||
fs::remove_all(".");
|
||||
fs::remove_all(storepath);
|
||||
return false;
|
||||
}
|
||||
idFile << id;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool genericModel::extractModel() {
|
||||
bool genericModel::extractModel(char* name) {
|
||||
std::string path{};
|
||||
archive* src {archive_read_new()};
|
||||
archive_entry* entry {};
|
||||
archive_read_support_filter_all(src);
|
||||
archive_read_support_format_all(src);
|
||||
archive_read_open_filename(src, "opfs/model.tzst",10240);
|
||||
archive_read_open_filename(src, name,10240);
|
||||
if(archive_errno(src) != 0) return false;
|
||||
while (archive_read_next_header(src, &entry) == ARCHIVE_OK) {
|
||||
path = archive_entry_pathname(entry);
|
||||
// Strip first component
|
||||
archive_entry_set_pathname(entry, path.substr(path.find("/")).c_str());
|
||||
if(archive_errno(src) != 0) return false;
|
||||
archive_read_extract(src, entry, ARCHIVE_EXTRACT_UNLINK);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <fstream>
|
||||
#include <thread>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <vosk_api.h>
|
||||
#include <archive.h>
|
||||
#include <archive_entry.h>
|
||||
@@ -15,12 +16,11 @@
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
struct genericModel : genericObj {
|
||||
static bool first;
|
||||
const std::string url{};
|
||||
const std::string id{};
|
||||
static bool extractModel();
|
||||
static bool extractModel(char *name);
|
||||
static bool checkId(const std::string& id);
|
||||
virtual bool checkModel() = 0;
|
||||
bool loadModel();
|
||||
genericModel(const std::string& url, const std::string& storepath, const std::string& id, int index);
|
||||
bool loadModel(const std::string& storepath);
|
||||
genericModel(const std::string &url, const std::string &storepath, const std::string &id, int index);
|
||||
};
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
#include "genericObj.h"
|
||||
|
||||
void genericObj::fireEv(const char *type, const char *content) {
|
||||
if(content == nullptr) {
|
||||
EM_ASM({
|
||||
if($0 === 0) {
|
||||
__genericObj__.objects[$0].dispatchEvent(new Event(UTF8ToString($1)));
|
||||
},this->index, type);
|
||||
return;
|
||||
}
|
||||
EM_ASM({
|
||||
__genericObj__.objects[$0].dispatchEvent(new CustomEvent(UTF8ToString($0), {"details" : UTF8ToString($1)}));
|
||||
__genericObj__.objects[$0].dispatchEvent(new CustomEvent(UTF8ToString($1), {"details" : UTF8ToString($2)}));
|
||||
},this->index, type, content);
|
||||
}
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
class __genericObj__ {static objects = []}
|
||||
|
||||
|
||||
@@ -25,18 +25,7 @@ index 4573e24f1..4af4e73ea 100644
|
||||
|
||||
MultiThreadable::~MultiThreadable() {
|
||||
// default implementation does nothing
|
||||
diff --git a/src/base/kaldi-types.h b/src/base/kaldi-types.h
|
||||
index 7ebf4f853..2f5979e42 100644
|
||||
--- a/src/base/kaldi-types.h
|
||||
+++ b/src/base/kaldi-types.h
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#ifndef KALDI_BASE_KALDI_TYPES_H_
|
||||
#define KALDI_BASE_KALDI_TYPES_H_ 1
|
||||
+#define KALDI_DOUBLEPRECISION 1
|
||||
|
||||
namespace kaldi {
|
||||
// TYPEDEFS ..................................................................
|
||||
diff --git a/src/ivector/ivector-extractor.cc b/src/ivector/ivector-extractor.cc
|
||||
index c3a122281..71d37256d 100644
|
||||
--- a/src/ivector/ivector-extractor.cc
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "model.h"
|
||||
|
||||
model::model(const std::string &url, const std::string& storepath, const std::string& id, int index) : genericModel(url, id, storepath, index) {
|
||||
if(!loadModel()) return;
|
||||
if(!loadModel(storepath)) return;
|
||||
mdl = vosk_model_new(".");
|
||||
if(mdl == nullptr) {
|
||||
fireEv("error", "Unable to initialize model");
|
||||
@@ -9,7 +9,9 @@ model::model(const std::string &url, const std::string& storepath, const std::st
|
||||
}
|
||||
fireEv("ready");
|
||||
};
|
||||
|
||||
model::~model() {
|
||||
vosk_model_free(mdl);
|
||||
}
|
||||
bool model::checkModel() {
|
||||
return fs::exists("am/final.mdl") &&
|
||||
fs::exists("conf/mfcc.conf") &&
|
||||
|
||||
@@ -5,6 +5,7 @@ struct model : genericModel {
|
||||
bool checkModel();
|
||||
VoskModel* mdl{};
|
||||
model(const std::string &url, const std::string& storepath, const std::string& id, int index);
|
||||
~model();
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -3,12 +3,10 @@ class Model extends EventTarget{
|
||||
super()
|
||||
}
|
||||
init(url, storepath, id) {
|
||||
this.obj = new Module.__model__(url, storepath, id, __genericObj__.objects.length);
|
||||
this.obj = new BrowserRecognizer.__model__(url, storepath, id, __genericObj__.objects.length);
|
||||
__genericObj__.objects.push(this)
|
||||
}
|
||||
delete() {
|
||||
this.obj.then(() => {
|
||||
this.obj.delete()
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -7,11 +7,6 @@ void recognizer::stop() {
|
||||
controller.clear(std::memory_order_relaxed);
|
||||
controller.notify_all();
|
||||
}
|
||||
void recognizer::deinit() {
|
||||
done.test_and_set(std::memory_order_relaxed);
|
||||
done.notify_all();
|
||||
stop();
|
||||
}
|
||||
recognizer::recognizer(model* mdl, int sampleRate, int index) : genericObj(index) {
|
||||
mic = alcCaptureOpenDevice("Emscripten OpenAL capture",sampleRate, AL_FORMAT_MONO16, 22480);
|
||||
if(alcGetError(mic) != 0) {
|
||||
@@ -25,32 +20,15 @@ recognizer::recognizer(model* mdl, int sampleRate, int index) : genericObj(index
|
||||
}
|
||||
main();
|
||||
}
|
||||
void recognizer::main() {
|
||||
char buffer[22480];
|
||||
int sample{};
|
||||
fireEv("ready");
|
||||
while(!done.test()) {
|
||||
controller.wait(done.test(std::memory_order_relaxed), std::memory_order_relaxed);
|
||||
alcCaptureStart(mic);
|
||||
while(controller.test()) {
|
||||
alcGetIntegerv(mic, ALC_CAPTURE_SAMPLES, sizeof(int), &sample);
|
||||
alcCaptureSamples(mic, buffer, sample);
|
||||
switch(vosk_recognizer_accept_waveform(rec, buffer, 22480)) {
|
||||
case 0:
|
||||
fireEv("result", vosk_recognizer_result(rec));
|
||||
break;
|
||||
case 1:
|
||||
fireEv("partialResult", vosk_recognizer_partial_result(rec));
|
||||
break;
|
||||
default:
|
||||
fireEv("error", "Recognition result error");
|
||||
}
|
||||
}
|
||||
alcCaptureStop(mic);
|
||||
}
|
||||
recognizer::~recognizer() {
|
||||
done.test_and_set(std::memory_order_relaxed);
|
||||
done.notify_all();
|
||||
stop();
|
||||
vosk_recognizer_free(rec);
|
||||
alcCaptureCloseDevice(mic);
|
||||
}
|
||||
void recognizer::acceptWaveForm() {
|
||||
}
|
||||
void recognizer::setGrm(const std::string& grm) {
|
||||
vosk_recognizer_set_grm(rec, grm.c_str());
|
||||
}
|
||||
|
||||
@@ -19,13 +19,11 @@ namespace fs = std::filesystem;
|
||||
struct recognizer : genericObj {
|
||||
VoskRecognizer* rec{};
|
||||
ALCdevice* mic{};
|
||||
std::atomic_flag done {false};
|
||||
std::atomic_flag controller{false};
|
||||
void main();
|
||||
void acceptWaveForm();
|
||||
recognizer(model* model, int sampleRate, int index);
|
||||
~recognizer();
|
||||
void start();
|
||||
void stop();
|
||||
void deinit();
|
||||
void setSpkModel(spkModel* model);
|
||||
void setGrm(const std::string& grm);
|
||||
void setWords(bool words);
|
||||
|
||||
@@ -4,7 +4,7 @@ class Recognizer extends EventTarget {
|
||||
}
|
||||
init(model) {
|
||||
ctx = new (AudioContext || webkitAudioContext)()
|
||||
new Module.__recognizer__(model.obj,ctx.sampleRate,__genericObj__.objects.length)
|
||||
new BrowserRecognizer.__recognizer__(model.obj,ctx.sampleRate,__genericObj__.objects.length)
|
||||
ctx.close()
|
||||
__genericObj__.objects.push(this)
|
||||
}
|
||||
@@ -15,7 +15,6 @@ class Recognizer extends EventTarget {
|
||||
this.obj.stop()
|
||||
}
|
||||
delete() {
|
||||
this.obj.deinit()
|
||||
this.obj.delete()
|
||||
}
|
||||
setWords(words) {
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
#include "spkModel.h"
|
||||
spkModel::spkModel(const std::string &url, const std::string& storepath, const std::string& id, int index) : genericModel(url, storepath, id, index) {
|
||||
if(!loadModel()) return;
|
||||
if(!loadModel(storepath)) return;
|
||||
mdl = vosk_spk_model_new(".");
|
||||
if(mdl == nullptr) {
|
||||
fireEv("error", "Unable to initialize speaker model");
|
||||
}
|
||||
fireEv("ready");
|
||||
};
|
||||
spkModel::~spkModel() {
|
||||
vosk_spk_model_free(mdl);
|
||||
}
|
||||
bool spkModel::checkModel() {
|
||||
return fs::exists("mfcc.conf") &&
|
||||
fs::exists("final.ext.raw") &&
|
||||
|
||||
@@ -3,8 +3,9 @@
|
||||
|
||||
struct spkModel : genericModel {
|
||||
bool checkModel();
|
||||
spkModel(const std::string &url, const std::string& storepath, const std::string& id, const int index);
|
||||
VoskSpkModel* mdl{};
|
||||
spkModel(const std::string &url, const std::string& storepath, const std::string& id, const int index);
|
||||
~spkModel();
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ class SpkModel extends EventTarget{
|
||||
super()
|
||||
}
|
||||
init(url, storepath, id) {
|
||||
this.obj = new Module.__spkModel__(url, storepath, id, __genericObj__.objects.length)
|
||||
this.obj = new BrowserRecognizer.__spkModel__(url, storepath, id, __genericObj__.objects.length)
|
||||
__genericObj__.objects.push(this)
|
||||
}
|
||||
delete() {
|
||||
|
||||
Reference in New Issue
Block a user