Publish sherpa_onnx.har for HarmonyOS (#1572)
This commit is contained in:
@@ -1,227 +0,0 @@
|
||||
// scripts/node-addon-api/src/audio-tagging.cc
|
||||
//
|
||||
// Copyright (c) 2024 Xiaomi Corporation
|
||||
#include <sstream>
|
||||
|
||||
#include "macros.h" // NOLINT
|
||||
#include "napi.h" // NOLINT
|
||||
#include "sherpa-onnx/c-api/c-api.h"
|
||||
|
||||
static SherpaOnnxOfflineZipformerAudioTaggingModelConfig
|
||||
GetAudioTaggingZipformerModelConfig(Napi::Object obj) {
|
||||
SherpaOnnxOfflineZipformerAudioTaggingModelConfig c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
|
||||
if (!obj.Has("zipformer") || !obj.Get("zipformer").IsObject()) {
|
||||
return c;
|
||||
}
|
||||
|
||||
Napi::Object o = obj.Get("zipformer").As<Napi::Object>();
|
||||
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(model, model);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static SherpaOnnxAudioTaggingModelConfig GetAudioTaggingModelConfig(
|
||||
Napi::Object obj) {
|
||||
SherpaOnnxAudioTaggingModelConfig c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
|
||||
if (!obj.Has("model") || !obj.Get("model").IsObject()) {
|
||||
return c;
|
||||
}
|
||||
|
||||
Napi::Object o = obj.Get("model").As<Napi::Object>();
|
||||
c.zipformer = GetAudioTaggingZipformerModelConfig(o);
|
||||
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(ced, ced);
|
||||
|
||||
SHERPA_ONNX_ASSIGN_ATTR_INT32(num_threads, numThreads);
|
||||
|
||||
if (o.Has("debug") &&
|
||||
(o.Get("debug").IsNumber() || o.Get("debug").IsBoolean())) {
|
||||
if (o.Get("debug").IsBoolean()) {
|
||||
c.debug = o.Get("debug").As<Napi::Boolean>().Value();
|
||||
} else {
|
||||
c.debug = o.Get("debug").As<Napi::Number>().Int32Value();
|
||||
}
|
||||
}
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(provider, provider);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static Napi::External<SherpaOnnxAudioTagging> CreateAudioTaggingWrapper(
|
||||
const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() != 1) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 1 argument. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsObject()) {
|
||||
Napi::TypeError::New(env, "You should pass an object as the only argument.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
Napi::Object o = info[0].As<Napi::Object>();
|
||||
|
||||
SherpaOnnxAudioTaggingConfig c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
c.model = GetAudioTaggingModelConfig(o);
|
||||
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(labels, labels);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_INT32(top_k, topK);
|
||||
|
||||
const SherpaOnnxAudioTagging *at = SherpaOnnxCreateAudioTagging(&c);
|
||||
|
||||
if (c.model.zipformer.model) {
|
||||
delete[] c.model.zipformer.model;
|
||||
}
|
||||
|
||||
if (c.model.ced) {
|
||||
delete[] c.model.ced;
|
||||
}
|
||||
|
||||
if (c.model.provider) {
|
||||
delete[] c.model.provider;
|
||||
}
|
||||
|
||||
if (c.labels) {
|
||||
delete[] c.labels;
|
||||
}
|
||||
|
||||
if (!at) {
|
||||
Napi::TypeError::New(env, "Please check your config!")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
return Napi::External<SherpaOnnxAudioTagging>::New(
|
||||
env, const_cast<SherpaOnnxAudioTagging *>(at),
|
||||
[](Napi::Env env, SherpaOnnxAudioTagging *at) {
|
||||
SherpaOnnxDestroyAudioTagging(at);
|
||||
});
|
||||
}
|
||||
|
||||
static Napi::External<SherpaOnnxOfflineStream>
|
||||
AudioTaggingCreateOfflineStreamWrapper(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() != 1) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 1 argument. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(
|
||||
env, "You should pass an audio tagging pointer as the only argument")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
SherpaOnnxAudioTagging *at =
|
||||
info[0].As<Napi::External<SherpaOnnxAudioTagging>>().Data();
|
||||
|
||||
const SherpaOnnxOfflineStream *stream =
|
||||
SherpaOnnxAudioTaggingCreateOfflineStream(at);
|
||||
|
||||
return Napi::External<SherpaOnnxOfflineStream>::New(
|
||||
env, const_cast<SherpaOnnxOfflineStream *>(stream),
|
||||
[](Napi::Env env, SherpaOnnxOfflineStream *stream) {
|
||||
SherpaOnnxDestroyOfflineStream(stream);
|
||||
});
|
||||
}
|
||||
|
||||
static Napi::Object AudioTaggingComputeWrapper(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() != 3) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 3 arguments. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(
|
||||
env, "You should pass an audio tagging pointer as the first argument")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[1].IsExternal()) {
|
||||
Napi::TypeError::New(
|
||||
env, "You should pass an offline stream pointer as the second argument")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[2].IsNumber()) {
|
||||
Napi::TypeError::New(env,
|
||||
"You should pass an integer as the third argument")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
SherpaOnnxAudioTagging *at =
|
||||
info[0].As<Napi::External<SherpaOnnxAudioTagging>>().Data();
|
||||
|
||||
SherpaOnnxOfflineStream *stream =
|
||||
info[1].As<Napi::External<SherpaOnnxOfflineStream>>().Data();
|
||||
|
||||
int32_t top_k = info[2].As<Napi::Number>().Int32Value();
|
||||
|
||||
const SherpaOnnxAudioEvent *const *events =
|
||||
SherpaOnnxAudioTaggingCompute(at, stream, top_k);
|
||||
|
||||
auto p = events;
|
||||
int32_t k = 0;
|
||||
while (p && *p) {
|
||||
++k;
|
||||
++p;
|
||||
}
|
||||
|
||||
Napi::Array ans = Napi::Array::New(env, k);
|
||||
for (uint32_t i = 0; i != k; ++i) {
|
||||
Napi::Object obj = Napi::Object::New(env);
|
||||
obj.Set(Napi::String::New(env, "name"),
|
||||
Napi::String::New(env, events[i]->name));
|
||||
obj.Set(Napi::String::New(env, "index"),
|
||||
Napi::Number::New(env, events[i]->index));
|
||||
obj.Set(Napi::String::New(env, "prob"),
|
||||
Napi::Number::New(env, events[i]->prob));
|
||||
ans[i] = obj;
|
||||
}
|
||||
|
||||
SherpaOnnxAudioTaggingFreeResults(events);
|
||||
|
||||
return ans;
|
||||
}
|
||||
|
||||
void InitAudioTagging(Napi::Env env, Napi::Object exports) {
|
||||
exports.Set(Napi::String::New(env, "createAudioTagging"),
|
||||
Napi::Function::New(env, CreateAudioTaggingWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "audioTaggingCreateOfflineStream"),
|
||||
Napi::Function::New(env, AudioTaggingCreateOfflineStreamWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "audioTaggingCompute"),
|
||||
Napi::Function::New(env, AudioTaggingComputeWrapper));
|
||||
}
|
||||
1
scripts/node-addon-api/src/audio-tagging.cc
Symbolic link
1
scripts/node-addon-api/src/audio-tagging.cc
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../harmony-os/SherpaOnnxHar/sherpa_onnx/src/main/cpp/audio-tagging.cc
|
||||
@@ -1,266 +0,0 @@
|
||||
// scripts/node-addon-api/src/keyword-spotting.cc
|
||||
//
|
||||
// Copyright (c) 2024 Xiaomi Corporation
|
||||
#include <sstream>
|
||||
|
||||
#include "macros.h" // NOLINT
|
||||
#include "napi.h" // NOLINT
|
||||
#include "sherpa-onnx/c-api/c-api.h"
|
||||
|
||||
// defined ./streaming-asr.cc
|
||||
SherpaOnnxFeatureConfig GetFeatureConfig(Napi::Object obj);
|
||||
|
||||
// defined ./streaming-asr.cc
|
||||
SherpaOnnxOnlineModelConfig GetOnlineModelConfig(Napi::Object obj);
|
||||
|
||||
static Napi::External<SherpaOnnxKeywordSpotter> CreateKeywordSpotterWrapper(
|
||||
const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() != 1) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 1 argument. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsObject()) {
|
||||
Napi::TypeError::New(env, "Expect an object as the argument")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
Napi::Object o = info[0].As<Napi::Object>();
|
||||
SherpaOnnxKeywordSpotterConfig c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
c.feat_config = GetFeatureConfig(o);
|
||||
c.model_config = GetOnlineModelConfig(o);
|
||||
|
||||
SHERPA_ONNX_ASSIGN_ATTR_INT32(max_active_paths, maxActivePaths);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_INT32(num_trailing_blanks, numTrailingBlanks);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_FLOAT(keywords_score, keywordsScore);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_FLOAT(keywords_threshold, keywordsThreshold);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(keywords_file, keywordsFile);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(keywords_buf, keywordsBuf);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_INT32(keywords_buf_size, keywordsBufSize);
|
||||
|
||||
SherpaOnnxKeywordSpotter *kws = SherpaOnnxCreateKeywordSpotter(&c);
|
||||
|
||||
if (c.model_config.transducer.encoder) {
|
||||
delete[] c.model_config.transducer.encoder;
|
||||
}
|
||||
|
||||
if (c.model_config.transducer.decoder) {
|
||||
delete[] c.model_config.transducer.decoder;
|
||||
}
|
||||
|
||||
if (c.model_config.transducer.joiner) {
|
||||
delete[] c.model_config.transducer.joiner;
|
||||
}
|
||||
|
||||
if (c.model_config.paraformer.encoder) {
|
||||
delete[] c.model_config.paraformer.encoder;
|
||||
}
|
||||
|
||||
if (c.model_config.paraformer.decoder) {
|
||||
delete[] c.model_config.paraformer.decoder;
|
||||
}
|
||||
|
||||
if (c.model_config.zipformer2_ctc.model) {
|
||||
delete[] c.model_config.zipformer2_ctc.model;
|
||||
}
|
||||
|
||||
if (c.model_config.tokens) {
|
||||
delete[] c.model_config.tokens;
|
||||
}
|
||||
|
||||
if (c.model_config.provider) {
|
||||
delete[] c.model_config.provider;
|
||||
}
|
||||
|
||||
if (c.model_config.model_type) {
|
||||
delete[] c.model_config.model_type;
|
||||
}
|
||||
|
||||
if (c.keywords_file) {
|
||||
delete[] c.keywords_file;
|
||||
}
|
||||
|
||||
if (c.keywords_buf) {
|
||||
delete[] c.keywords_buf;
|
||||
}
|
||||
|
||||
if (!kws) {
|
||||
Napi::TypeError::New(env, "Please check your config!")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
return Napi::External<SherpaOnnxKeywordSpotter>::New(
|
||||
env, kws, [](Napi::Env env, SherpaOnnxKeywordSpotter *kws) {
|
||||
SherpaOnnxDestroyKeywordSpotter(kws);
|
||||
});
|
||||
}
|
||||
|
||||
static Napi::External<SherpaOnnxOnlineStream> CreateKeywordStreamWrapper(
|
||||
const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() != 1) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 1 argument. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(
|
||||
env, "You should pass a keyword spotter pointer as the only argument")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
SherpaOnnxKeywordSpotter *kws =
|
||||
info[0].As<Napi::External<SherpaOnnxKeywordSpotter>>().Data();
|
||||
|
||||
SherpaOnnxOnlineStream *stream = SherpaOnnxCreateKeywordStream(kws);
|
||||
|
||||
return Napi::External<SherpaOnnxOnlineStream>::New(
|
||||
env, stream, [](Napi::Env env, SherpaOnnxOnlineStream *stream) {
|
||||
SherpaOnnxDestroyOnlineStream(stream);
|
||||
});
|
||||
}
|
||||
|
||||
static Napi::Boolean IsKeywordStreamReadyWrapper(
|
||||
const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() != 2) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 2 arguments. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(env, "Argument 0 should be a keyword spotter pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[1].IsExternal()) {
|
||||
Napi::TypeError::New(env, "Argument 1 should be an online stream pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
SherpaOnnxKeywordSpotter *kws =
|
||||
info[0].As<Napi::External<SherpaOnnxKeywordSpotter>>().Data();
|
||||
|
||||
SherpaOnnxOnlineStream *stream =
|
||||
info[1].As<Napi::External<SherpaOnnxOnlineStream>>().Data();
|
||||
|
||||
int32_t is_ready = SherpaOnnxIsKeywordStreamReady(kws, stream);
|
||||
|
||||
return Napi::Boolean::New(env, is_ready);
|
||||
}
|
||||
|
||||
static void DecodeKeywordStreamWrapper(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() != 2) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 2 arguments. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(env, "Argument 0 should be a keyword spotter pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!info[1].IsExternal()) {
|
||||
Napi::TypeError::New(env, "Argument 1 should be an online stream pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
SherpaOnnxKeywordSpotter *kws =
|
||||
info[0].As<Napi::External<SherpaOnnxKeywordSpotter>>().Data();
|
||||
|
||||
SherpaOnnxOnlineStream *stream =
|
||||
info[1].As<Napi::External<SherpaOnnxOnlineStream>>().Data();
|
||||
|
||||
SherpaOnnxDecodeKeywordStream(kws, stream);
|
||||
}
|
||||
|
||||
static Napi::String GetKeywordResultAsJsonWrapper(
|
||||
const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() != 2) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 2 arguments. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(env, "Argument 0 should be a keyword spotter pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[1].IsExternal()) {
|
||||
Napi::TypeError::New(env, "Argument 1 should be an online stream pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
SherpaOnnxKeywordSpotter *kws =
|
||||
info[0].As<Napi::External<SherpaOnnxKeywordSpotter>>().Data();
|
||||
|
||||
SherpaOnnxOnlineStream *stream =
|
||||
info[1].As<Napi::External<SherpaOnnxOnlineStream>>().Data();
|
||||
|
||||
const char *json = SherpaOnnxGetKeywordResultAsJson(kws, stream);
|
||||
|
||||
Napi::String s = Napi::String::New(env, json);
|
||||
|
||||
SherpaOnnxFreeKeywordResultJson(json);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void InitKeywordSpotting(Napi::Env env, Napi::Object exports) {
|
||||
exports.Set(Napi::String::New(env, "createKeywordSpotter"),
|
||||
Napi::Function::New(env, CreateKeywordSpotterWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "createKeywordStream"),
|
||||
Napi::Function::New(env, CreateKeywordStreamWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "isKeywordStreamReady"),
|
||||
Napi::Function::New(env, IsKeywordStreamReadyWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "decodeKeywordStream"),
|
||||
Napi::Function::New(env, DecodeKeywordStreamWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "getKeywordResultAsJson"),
|
||||
Napi::Function::New(env, GetKeywordResultAsJsonWrapper));
|
||||
}
|
||||
1
scripts/node-addon-api/src/keyword-spotting.cc
Symbolic link
1
scripts/node-addon-api/src/keyword-spotting.cc
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../harmony-os/SherpaOnnxHar/sherpa_onnx/src/main/cpp/keyword-spotting.cc
|
||||
@@ -1,51 +0,0 @@
|
||||
// scripts/node-addon-api/src/macros.h
|
||||
//
|
||||
// Copyright (c) 2024 Xiaomi Corporation
|
||||
#ifndef SCRIPTS_NODE_ADDON_API_SRC_MACROS_H_
|
||||
#define SCRIPTS_NODE_ADDON_API_SRC_MACROS_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
#define SHERPA_ONNX_ASSIGN_ATTR_STR(c_name, js_name) \
|
||||
do { \
|
||||
if (o.Has(#js_name) && o.Get(#js_name).IsString()) { \
|
||||
Napi::String _str = o.Get(#js_name).As<Napi::String>(); \
|
||||
std::string s = _str.Utf8Value(); \
|
||||
char *p = new char[s.size() + 1]; \
|
||||
std::copy(s.begin(), s.end(), p); \
|
||||
p[s.size()] = 0; \
|
||||
\
|
||||
c.c_name = p; \
|
||||
} else if (o.Has(#js_name) && o.Get(#js_name).IsTypedArray()) { \
|
||||
Napi::Uint8Array _array = o.Get(#js_name).As<Napi::Uint8Array>(); \
|
||||
char *p = new char[_array.ElementLength() + 1]; \
|
||||
std::copy(_array.Data(), _array.Data() + _array.ElementLength(), p); \
|
||||
p[_array.ElementLength()] = '\0'; \
|
||||
\
|
||||
c.c_name = p; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define SHERPA_ONNX_ASSIGN_ATTR_INT32(c_name, js_name) \
|
||||
do { \
|
||||
if (o.Has(#js_name) && o.Get(#js_name).IsNumber()) { \
|
||||
c.c_name = o.Get(#js_name).As<Napi::Number>().Int32Value(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define SHERPA_ONNX_ASSIGN_ATTR_FLOAT(c_name, js_name) \
|
||||
do { \
|
||||
if (o.Has(#js_name) && o.Get(#js_name).IsNumber()) { \
|
||||
c.c_name = o.Get(#js_name).As<Napi::Number>().FloatValue(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define SHERPA_ONNX_DELETE_C_STR(p) \
|
||||
do { \
|
||||
if (p) { \
|
||||
delete[] p; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif // SCRIPTS_NODE_ADDON_API_SRC_MACROS_H_
|
||||
1
scripts/node-addon-api/src/macros.h
Symbolic link
1
scripts/node-addon-api/src/macros.h
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../harmony-os/SherpaOnnxHar/sherpa_onnx/src/main/cpp/macros.h
|
||||
@@ -1,461 +0,0 @@
|
||||
// scripts/node-addon-api/src/non-streaming-asr.cc
|
||||
//
|
||||
// Copyright (c) 2024 Xiaomi Corporation
|
||||
#include <sstream>
|
||||
|
||||
#include "macros.h" // NOLINT
|
||||
#include "napi.h" // NOLINT
|
||||
#include "sherpa-onnx/c-api/c-api.h"
|
||||
|
||||
// defined in ./streaming-asr.cc
|
||||
SherpaOnnxFeatureConfig GetFeatureConfig(Napi::Object obj);
|
||||
|
||||
static SherpaOnnxOfflineTransducerModelConfig GetOfflineTransducerModelConfig(
|
||||
Napi::Object obj) {
|
||||
SherpaOnnxOfflineTransducerModelConfig c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
|
||||
if (!obj.Has("transducer") || !obj.Get("transducer").IsObject()) {
|
||||
return c;
|
||||
}
|
||||
|
||||
Napi::Object o = obj.Get("transducer").As<Napi::Object>();
|
||||
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(encoder, encoder);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(decoder, decoder);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(joiner, joiner);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static SherpaOnnxOfflineParaformerModelConfig GetOfflineParaformerModelConfig(
|
||||
Napi::Object obj) {
|
||||
SherpaOnnxOfflineParaformerModelConfig c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
|
||||
if (!obj.Has("paraformer") || !obj.Get("paraformer").IsObject()) {
|
||||
return c;
|
||||
}
|
||||
|
||||
Napi::Object o = obj.Get("paraformer").As<Napi::Object>();
|
||||
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(model, model);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static SherpaOnnxOfflineNemoEncDecCtcModelConfig GetOfflineNeMoCtcModelConfig(
|
||||
Napi::Object obj) {
|
||||
SherpaOnnxOfflineNemoEncDecCtcModelConfig c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
|
||||
if (!obj.Has("nemoCtc") || !obj.Get("nemoCtc").IsObject()) {
|
||||
return c;
|
||||
}
|
||||
|
||||
Napi::Object o = obj.Get("nemoCtc").As<Napi::Object>();
|
||||
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(model, model);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static SherpaOnnxOfflineWhisperModelConfig GetOfflineWhisperModelConfig(
|
||||
Napi::Object obj) {
|
||||
SherpaOnnxOfflineWhisperModelConfig c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
|
||||
if (!obj.Has("whisper") || !obj.Get("whisper").IsObject()) {
|
||||
return c;
|
||||
}
|
||||
|
||||
Napi::Object o = obj.Get("whisper").As<Napi::Object>();
|
||||
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(encoder, encoder);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(decoder, decoder);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(language, language);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(task, task);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_INT32(tail_paddings, tailPaddings);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static SherpaOnnxOfflineMoonshineModelConfig GetOfflineMoonshineModelConfig(
|
||||
Napi::Object obj) {
|
||||
SherpaOnnxOfflineMoonshineModelConfig c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
|
||||
if (!obj.Has("moonshine") || !obj.Get("moonshine").IsObject()) {
|
||||
return c;
|
||||
}
|
||||
|
||||
Napi::Object o = obj.Get("moonshine").As<Napi::Object>();
|
||||
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(preprocessor, preprocessor);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(encoder, encoder);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(uncached_decoder, uncachedDecoder);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(cached_decoder, cachedDecoder);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static SherpaOnnxOfflineTdnnModelConfig GetOfflineTdnnModelConfig(
|
||||
Napi::Object obj) {
|
||||
SherpaOnnxOfflineTdnnModelConfig c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
|
||||
if (!obj.Has("tdnn") || !obj.Get("tdnn").IsObject()) {
|
||||
return c;
|
||||
}
|
||||
|
||||
Napi::Object o = obj.Get("tdnn").As<Napi::Object>();
|
||||
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(model, model);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static SherpaOnnxOfflineSenseVoiceModelConfig GetOfflineSenseVoiceModelConfig(
|
||||
Napi::Object obj) {
|
||||
SherpaOnnxOfflineSenseVoiceModelConfig c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
|
||||
if (!obj.Has("senseVoice") || !obj.Get("senseVoice").IsObject()) {
|
||||
return c;
|
||||
}
|
||||
|
||||
Napi::Object o = obj.Get("senseVoice").As<Napi::Object>();
|
||||
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(model, model);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(language, language);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_INT32(use_itn, useInverseTextNormalization);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static SherpaOnnxOfflineModelConfig GetOfflineModelConfig(Napi::Object obj) {
|
||||
SherpaOnnxOfflineModelConfig c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
|
||||
if (!obj.Has("modelConfig") || !obj.Get("modelConfig").IsObject()) {
|
||||
return c;
|
||||
}
|
||||
|
||||
Napi::Object o = obj.Get("modelConfig").As<Napi::Object>();
|
||||
|
||||
c.transducer = GetOfflineTransducerModelConfig(o);
|
||||
c.paraformer = GetOfflineParaformerModelConfig(o);
|
||||
c.nemo_ctc = GetOfflineNeMoCtcModelConfig(o);
|
||||
c.whisper = GetOfflineWhisperModelConfig(o);
|
||||
c.tdnn = GetOfflineTdnnModelConfig(o);
|
||||
c.sense_voice = GetOfflineSenseVoiceModelConfig(o);
|
||||
c.moonshine = GetOfflineMoonshineModelConfig(o);
|
||||
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(tokens, tokens);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_INT32(num_threads, numThreads);
|
||||
|
||||
if (o.Has("debug") &&
|
||||
(o.Get("debug").IsNumber() || o.Get("debug").IsBoolean())) {
|
||||
if (o.Get("debug").IsBoolean()) {
|
||||
c.debug = o.Get("debug").As<Napi::Boolean>().Value();
|
||||
} else {
|
||||
c.debug = o.Get("debug").As<Napi::Number>().Int32Value();
|
||||
}
|
||||
}
|
||||
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(provider, provider);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(model_type, modelType);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(modeling_unit, modelingUnit);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(bpe_vocab, bpeVocab);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(telespeech_ctc, teleSpeechCtc);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static SherpaOnnxOfflineLMConfig GetOfflineLMConfig(Napi::Object obj) {
|
||||
SherpaOnnxOfflineLMConfig c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
|
||||
if (!obj.Has("lmConfig") || !obj.Get("lmConfig").IsObject()) {
|
||||
return c;
|
||||
}
|
||||
|
||||
Napi::Object o = obj.Get("lmConfig").As<Napi::Object>();
|
||||
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(model, model);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_FLOAT(scale, scale);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static Napi::External<SherpaOnnxOfflineRecognizer>
|
||||
CreateOfflineRecognizerWrapper(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() != 1) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 1 argument. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsObject()) {
|
||||
Napi::TypeError::New(env, "Expect an object as the argument")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
Napi::Object o = info[0].As<Napi::Object>();
|
||||
|
||||
SherpaOnnxOfflineRecognizerConfig c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
c.feat_config = GetFeatureConfig(o);
|
||||
c.model_config = GetOfflineModelConfig(o);
|
||||
c.lm_config = GetOfflineLMConfig(o);
|
||||
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(decoding_method, decodingMethod);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_INT32(max_active_paths, maxActivePaths);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(hotwords_file, hotwordsFile);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_FLOAT(hotwords_score, hotwordsScore);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(rule_fsts, ruleFsts);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(rule_fars, ruleFars);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_FLOAT(blank_penalty, blankPenalty);
|
||||
|
||||
const SherpaOnnxOfflineRecognizer *recognizer =
|
||||
SherpaOnnxCreateOfflineRecognizer(&c);
|
||||
|
||||
SHERPA_ONNX_DELETE_C_STR(c.model_config.transducer.encoder);
|
||||
SHERPA_ONNX_DELETE_C_STR(c.model_config.transducer.decoder);
|
||||
SHERPA_ONNX_DELETE_C_STR(c.model_config.transducer.joiner);
|
||||
|
||||
SHERPA_ONNX_DELETE_C_STR(c.model_config.paraformer.model);
|
||||
|
||||
SHERPA_ONNX_DELETE_C_STR(c.model_config.nemo_ctc.model);
|
||||
|
||||
SHERPA_ONNX_DELETE_C_STR(c.model_config.whisper.encoder);
|
||||
SHERPA_ONNX_DELETE_C_STR(c.model_config.whisper.decoder);
|
||||
SHERPA_ONNX_DELETE_C_STR(c.model_config.whisper.language);
|
||||
SHERPA_ONNX_DELETE_C_STR(c.model_config.whisper.task);
|
||||
|
||||
SHERPA_ONNX_DELETE_C_STR(c.model_config.tdnn.model);
|
||||
|
||||
SHERPA_ONNX_DELETE_C_STR(c.model_config.sense_voice.model);
|
||||
SHERPA_ONNX_DELETE_C_STR(c.model_config.sense_voice.language);
|
||||
|
||||
SHERPA_ONNX_DELETE_C_STR(c.model_config.moonshine.preprocessor);
|
||||
SHERPA_ONNX_DELETE_C_STR(c.model_config.moonshine.encoder);
|
||||
SHERPA_ONNX_DELETE_C_STR(c.model_config.moonshine.uncached_decoder);
|
||||
SHERPA_ONNX_DELETE_C_STR(c.model_config.moonshine.cached_decoder);
|
||||
|
||||
SHERPA_ONNX_DELETE_C_STR(c.model_config.tokens);
|
||||
SHERPA_ONNX_DELETE_C_STR(c.model_config.provider);
|
||||
SHERPA_ONNX_DELETE_C_STR(c.model_config.model_type);
|
||||
SHERPA_ONNX_DELETE_C_STR(c.model_config.modeling_unit);
|
||||
SHERPA_ONNX_DELETE_C_STR(c.model_config.bpe_vocab);
|
||||
SHERPA_ONNX_DELETE_C_STR(c.model_config.telespeech_ctc);
|
||||
|
||||
SHERPA_ONNX_DELETE_C_STR(c.lm_config.model);
|
||||
|
||||
SHERPA_ONNX_DELETE_C_STR(c.decoding_method);
|
||||
SHERPA_ONNX_DELETE_C_STR(c.hotwords_file);
|
||||
SHERPA_ONNX_DELETE_C_STR(c.rule_fsts);
|
||||
SHERPA_ONNX_DELETE_C_STR(c.rule_fars);
|
||||
|
||||
if (!recognizer) {
|
||||
Napi::TypeError::New(env, "Please check your config!")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
return Napi::External<SherpaOnnxOfflineRecognizer>::New(
|
||||
env, const_cast<SherpaOnnxOfflineRecognizer *>(recognizer),
|
||||
[](Napi::Env env, SherpaOnnxOfflineRecognizer *recognizer) {
|
||||
SherpaOnnxDestroyOfflineRecognizer(recognizer);
|
||||
});
|
||||
}
|
||||
|
||||
static Napi::External<SherpaOnnxOfflineStream> CreateOfflineStreamWrapper(
|
||||
const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() != 1) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 1 argument. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(
|
||||
env,
|
||||
"You should pass an offline recognizer pointer as the only argument")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
SherpaOnnxOfflineRecognizer *recognizer =
|
||||
info[0].As<Napi::External<SherpaOnnxOfflineRecognizer>>().Data();
|
||||
|
||||
const SherpaOnnxOfflineStream *stream =
|
||||
SherpaOnnxCreateOfflineStream(recognizer);
|
||||
|
||||
return Napi::External<SherpaOnnxOfflineStream>::New(
|
||||
env, const_cast<SherpaOnnxOfflineStream *>(stream),
|
||||
[](Napi::Env env, SherpaOnnxOfflineStream *stream) {
|
||||
SherpaOnnxDestroyOfflineStream(stream);
|
||||
});
|
||||
}
|
||||
|
||||
static void AcceptWaveformOfflineWrapper(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
|
||||
if (info.Length() != 2) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 2 arguments. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(env, "Argument 0 should be an online stream pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
SherpaOnnxOfflineStream *stream =
|
||||
info[0].As<Napi::External<SherpaOnnxOfflineStream>>().Data();
|
||||
|
||||
if (!info[1].IsObject()) {
|
||||
Napi::TypeError::New(env, "Argument 1 should be an object")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Napi::Object obj = info[1].As<Napi::Object>();
|
||||
|
||||
if (!obj.Has("samples")) {
|
||||
Napi::TypeError::New(env, "The argument object should have a field samples")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!obj.Get("samples").IsTypedArray()) {
|
||||
Napi::TypeError::New(env, "The object['samples'] should be a typed array")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!obj.Has("sampleRate")) {
|
||||
Napi::TypeError::New(env,
|
||||
"The argument object should have a field sampleRate")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!obj.Get("sampleRate").IsNumber()) {
|
||||
Napi::TypeError::New(env, "The object['samples'] should be a number")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Napi::Float32Array samples = obj.Get("samples").As<Napi::Float32Array>();
|
||||
int32_t sample_rate = obj.Get("sampleRate").As<Napi::Number>().Int32Value();
|
||||
|
||||
SherpaOnnxAcceptWaveformOffline(stream, sample_rate, samples.Data(),
|
||||
samples.ElementLength());
|
||||
}
|
||||
|
||||
static void DecodeOfflineStreamWrapper(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() != 2) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 2 arguments. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(env,
|
||||
"Argument 0 should be an offline recognizer pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!info[1].IsExternal()) {
|
||||
Napi::TypeError::New(env, "Argument 1 should be an offline stream pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
SherpaOnnxOfflineRecognizer *recognizer =
|
||||
info[0].As<Napi::External<SherpaOnnxOfflineRecognizer>>().Data();
|
||||
|
||||
SherpaOnnxOfflineStream *stream =
|
||||
info[1].As<Napi::External<SherpaOnnxOfflineStream>>().Data();
|
||||
|
||||
SherpaOnnxDecodeOfflineStream(recognizer, stream);
|
||||
}
|
||||
|
||||
static Napi::String GetOfflineStreamResultAsJsonWrapper(
|
||||
const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() != 1) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 1 argument. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(env, "Argument 0 should be an online stream pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
SherpaOnnxOfflineStream *stream =
|
||||
info[0].As<Napi::External<SherpaOnnxOfflineStream>>().Data();
|
||||
|
||||
const char *json = SherpaOnnxGetOfflineStreamResultAsJson(stream);
|
||||
Napi::String s = Napi::String::New(env, json);
|
||||
|
||||
SherpaOnnxDestroyOfflineStreamResultJson(json);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void InitNonStreamingAsr(Napi::Env env, Napi::Object exports) {
|
||||
exports.Set(Napi::String::New(env, "createOfflineRecognizer"),
|
||||
Napi::Function::New(env, CreateOfflineRecognizerWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "createOfflineStream"),
|
||||
Napi::Function::New(env, CreateOfflineStreamWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "acceptWaveformOffline"),
|
||||
Napi::Function::New(env, AcceptWaveformOfflineWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "decodeOfflineStream"),
|
||||
Napi::Function::New(env, DecodeOfflineStreamWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "getOfflineStreamResultAsJson"),
|
||||
Napi::Function::New(env, GetOfflineStreamResultAsJsonWrapper));
|
||||
}
|
||||
1
scripts/node-addon-api/src/non-streaming-asr.cc
Symbolic link
1
scripts/node-addon-api/src/non-streaming-asr.cc
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../harmony-os/SherpaOnnxHar/sherpa_onnx/src/main/cpp/non-streaming-asr.cc
|
||||
@@ -1,310 +0,0 @@
|
||||
// scripts/node-addon-api/src/non-streaming-speaker-diarization.cc
|
||||
//
|
||||
// Copyright (c) 2024 Xiaomi Corporation
|
||||
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
|
||||
#include "macros.h" // NOLINT
|
||||
#include "napi.h" // NOLINT
|
||||
#include "sherpa-onnx/c-api/c-api.h"
|
||||
|
||||
static SherpaOnnxOfflineSpeakerSegmentationPyannoteModelConfig
|
||||
GetOfflineSpeakerSegmentationPyannoteModelConfig(Napi::Object obj) {
|
||||
SherpaOnnxOfflineSpeakerSegmentationPyannoteModelConfig c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
|
||||
if (!obj.Has("pyannote") || !obj.Get("pyannote").IsObject()) {
|
||||
return c;
|
||||
}
|
||||
|
||||
Napi::Object o = obj.Get("pyannote").As<Napi::Object>();
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(model, model);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static SherpaOnnxOfflineSpeakerSegmentationModelConfig
|
||||
GetOfflineSpeakerSegmentationModelConfig(Napi::Object obj) {
|
||||
SherpaOnnxOfflineSpeakerSegmentationModelConfig c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
|
||||
if (!obj.Has("segmentation") || !obj.Get("segmentation").IsObject()) {
|
||||
return c;
|
||||
}
|
||||
|
||||
Napi::Object o = obj.Get("segmentation").As<Napi::Object>();
|
||||
|
||||
c.pyannote = GetOfflineSpeakerSegmentationPyannoteModelConfig(o);
|
||||
|
||||
SHERPA_ONNX_ASSIGN_ATTR_INT32(num_threads, numThreads);
|
||||
|
||||
if (o.Has("debug") &&
|
||||
(o.Get("debug").IsNumber() || o.Get("debug").IsBoolean())) {
|
||||
if (o.Get("debug").IsBoolean()) {
|
||||
c.debug = o.Get("debug").As<Napi::Boolean>().Value();
|
||||
} else {
|
||||
c.debug = o.Get("debug").As<Napi::Number>().Int32Value();
|
||||
}
|
||||
}
|
||||
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(provider, provider);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static SherpaOnnxSpeakerEmbeddingExtractorConfig
|
||||
GetSpeakerEmbeddingExtractorConfig(Napi::Object obj) {
|
||||
SherpaOnnxSpeakerEmbeddingExtractorConfig c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
|
||||
if (!obj.Has("embedding") || !obj.Get("embedding").IsObject()) {
|
||||
return c;
|
||||
}
|
||||
|
||||
Napi::Object o = obj.Get("embedding").As<Napi::Object>();
|
||||
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(model, model);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_INT32(num_threads, numThreads);
|
||||
|
||||
if (o.Has("debug") &&
|
||||
(o.Get("debug").IsNumber() || o.Get("debug").IsBoolean())) {
|
||||
if (o.Get("debug").IsBoolean()) {
|
||||
c.debug = o.Get("debug").As<Napi::Boolean>().Value();
|
||||
} else {
|
||||
c.debug = o.Get("debug").As<Napi::Number>().Int32Value();
|
||||
}
|
||||
}
|
||||
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(provider, provider);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static SherpaOnnxFastClusteringConfig GetFastClusteringConfig(
|
||||
Napi::Object obj) {
|
||||
SherpaOnnxFastClusteringConfig c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
|
||||
if (!obj.Has("clustering") || !obj.Get("clustering").IsObject()) {
|
||||
return c;
|
||||
}
|
||||
|
||||
Napi::Object o = obj.Get("clustering").As<Napi::Object>();
|
||||
|
||||
SHERPA_ONNX_ASSIGN_ATTR_INT32(num_clusters, numClusters);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_FLOAT(threshold, threshold);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static Napi::External<SherpaOnnxOfflineSpeakerDiarization>
|
||||
CreateOfflineSpeakerDiarizationWrapper(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() != 1) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 1 argument. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsObject()) {
|
||||
Napi::TypeError::New(env, "Expect an object as the argument")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
Napi::Object o = info[0].As<Napi::Object>();
|
||||
|
||||
SherpaOnnxOfflineSpeakerDiarizationConfig c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
|
||||
c.segmentation = GetOfflineSpeakerSegmentationModelConfig(o);
|
||||
c.embedding = GetSpeakerEmbeddingExtractorConfig(o);
|
||||
c.clustering = GetFastClusteringConfig(o);
|
||||
|
||||
SHERPA_ONNX_ASSIGN_ATTR_FLOAT(min_duration_on, minDurationOn);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_FLOAT(min_duration_off, minDurationOff);
|
||||
|
||||
const SherpaOnnxOfflineSpeakerDiarization *sd =
|
||||
SherpaOnnxCreateOfflineSpeakerDiarization(&c);
|
||||
|
||||
if (c.segmentation.pyannote.model) {
|
||||
delete[] c.segmentation.pyannote.model;
|
||||
}
|
||||
|
||||
if (c.segmentation.provider) {
|
||||
delete[] c.segmentation.provider;
|
||||
}
|
||||
|
||||
if (c.embedding.model) {
|
||||
delete[] c.embedding.model;
|
||||
}
|
||||
|
||||
if (c.embedding.provider) {
|
||||
delete[] c.embedding.provider;
|
||||
}
|
||||
|
||||
if (!sd) {
|
||||
Napi::TypeError::New(env, "Please check your config!")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
return Napi::External<SherpaOnnxOfflineSpeakerDiarization>::New(
|
||||
env, const_cast<SherpaOnnxOfflineSpeakerDiarization *>(sd),
|
||||
[](Napi::Env env, SherpaOnnxOfflineSpeakerDiarization *sd) {
|
||||
SherpaOnnxDestroyOfflineSpeakerDiarization(sd);
|
||||
});
|
||||
}
|
||||
|
||||
static Napi::Number OfflineSpeakerDiarizationGetSampleRateWrapper(
|
||||
const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
|
||||
if (info.Length() != 1) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 1 argument. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(
|
||||
env, "Argument 0 should be an offline speaker diarization pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
const SherpaOnnxOfflineSpeakerDiarization *sd =
|
||||
info[0].As<Napi::External<SherpaOnnxOfflineSpeakerDiarization>>().Data();
|
||||
|
||||
int32_t sample_rate = SherpaOnnxOfflineSpeakerDiarizationGetSampleRate(sd);
|
||||
|
||||
return Napi::Number::New(env, sample_rate);
|
||||
}
|
||||
|
||||
static Napi::Array OfflineSpeakerDiarizationProcessWrapper(
|
||||
const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
|
||||
if (info.Length() != 2) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 2 arguments. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(
|
||||
env, "Argument 0 should be an offline speaker diarization pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
const SherpaOnnxOfflineSpeakerDiarization *sd =
|
||||
info[0].As<Napi::External<SherpaOnnxOfflineSpeakerDiarization>>().Data();
|
||||
|
||||
if (!info[1].IsTypedArray()) {
|
||||
Napi::TypeError::New(env, "Argument 1 should be a typed array")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
Napi::Float32Array samples = info[1].As<Napi::Float32Array>();
|
||||
|
||||
const SherpaOnnxOfflineSpeakerDiarizationResult *r =
|
||||
SherpaOnnxOfflineSpeakerDiarizationProcess(sd, samples.Data(),
|
||||
samples.ElementLength());
|
||||
|
||||
int32_t num_segments =
|
||||
SherpaOnnxOfflineSpeakerDiarizationResultGetNumSegments(r);
|
||||
|
||||
const SherpaOnnxOfflineSpeakerDiarizationSegment *segments =
|
||||
SherpaOnnxOfflineSpeakerDiarizationResultSortByStartTime(r);
|
||||
|
||||
Napi::Array ans = Napi::Array::New(env, num_segments);
|
||||
|
||||
for (int32_t i = 0; i != num_segments; ++i) {
|
||||
Napi::Object obj = Napi::Object::New(env);
|
||||
|
||||
obj.Set(Napi::String::New(env, "start"), segments[i].start);
|
||||
obj.Set(Napi::String::New(env, "end"), segments[i].end);
|
||||
obj.Set(Napi::String::New(env, "speaker"), segments[i].speaker);
|
||||
|
||||
ans.Set(i, obj);
|
||||
}
|
||||
|
||||
SherpaOnnxOfflineSpeakerDiarizationDestroySegment(segments);
|
||||
SherpaOnnxOfflineSpeakerDiarizationDestroyResult(r);
|
||||
|
||||
return ans;
|
||||
}
|
||||
|
||||
static void OfflineSpeakerDiarizationSetConfigWrapper(
|
||||
const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
|
||||
if (info.Length() != 2) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 2 arguments. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(
|
||||
env, "Argument 0 should be an offline speaker diarization pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const SherpaOnnxOfflineSpeakerDiarization *sd =
|
||||
info[0].As<Napi::External<SherpaOnnxOfflineSpeakerDiarization>>().Data();
|
||||
|
||||
if (!info[1].IsObject()) {
|
||||
Napi::TypeError::New(env, "Expect an object as the argument")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Napi::Object o = info[0].As<Napi::Object>();
|
||||
|
||||
SherpaOnnxOfflineSpeakerDiarizationConfig c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
|
||||
c.clustering = GetFastClusteringConfig(o);
|
||||
SherpaOnnxOfflineSpeakerDiarizationSetConfig(sd, &c);
|
||||
}
|
||||
|
||||
void InitNonStreamingSpeakerDiarization(Napi::Env env, Napi::Object exports) {
|
||||
exports.Set(Napi::String::New(env, "createOfflineSpeakerDiarization"),
|
||||
Napi::Function::New(env, CreateOfflineSpeakerDiarizationWrapper));
|
||||
|
||||
exports.Set(
|
||||
Napi::String::New(env, "getOfflineSpeakerDiarizationSampleRate"),
|
||||
Napi::Function::New(env, OfflineSpeakerDiarizationGetSampleRateWrapper));
|
||||
|
||||
exports.Set(
|
||||
Napi::String::New(env, "offlineSpeakerDiarizationProcess"),
|
||||
Napi::Function::New(env, OfflineSpeakerDiarizationProcessWrapper));
|
||||
|
||||
exports.Set(
|
||||
Napi::String::New(env, "offlineSpeakerDiarizationSetConfig"),
|
||||
Napi::Function::New(env, OfflineSpeakerDiarizationSetConfigWrapper));
|
||||
}
|
||||
1
scripts/node-addon-api/src/non-streaming-speaker-diarization.cc
Symbolic link
1
scripts/node-addon-api/src/non-streaming-speaker-diarization.cc
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../harmony-os/SherpaOnnxHar/sherpa_onnx/src/main/cpp/non-streaming-speaker-diarization.cc
|
||||
@@ -1,329 +0,0 @@
|
||||
// scripts/node-addon-api/src/non-streaming-tts.cc
|
||||
//
|
||||
// Copyright (c) 2024 Xiaomi Corporation
|
||||
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
|
||||
#include "macros.h" // NOLINT
|
||||
#include "napi.h" // NOLINT
|
||||
#include "sherpa-onnx/c-api/c-api.h"
|
||||
|
||||
static SherpaOnnxOfflineTtsVitsModelConfig GetOfflineTtsVitsModelConfig(
|
||||
Napi::Object obj) {
|
||||
SherpaOnnxOfflineTtsVitsModelConfig c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
|
||||
if (!obj.Has("vits") || !obj.Get("vits").IsObject()) {
|
||||
return c;
|
||||
}
|
||||
|
||||
Napi::Object o = obj.Get("vits").As<Napi::Object>();
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(model, model);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(lexicon, lexicon);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(tokens, tokens);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(data_dir, dataDir);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_FLOAT(noise_scale, noiseScale);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_FLOAT(noise_scale_w, noiseScaleW);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_FLOAT(length_scale, lengthScale);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(dict_dir, dictDir);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static SherpaOnnxOfflineTtsModelConfig GetOfflineTtsModelConfig(
|
||||
Napi::Object obj) {
|
||||
SherpaOnnxOfflineTtsModelConfig c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
|
||||
if (!obj.Has("model") || !obj.Get("model").IsObject()) {
|
||||
return c;
|
||||
}
|
||||
|
||||
Napi::Object o = obj.Get("model").As<Napi::Object>();
|
||||
|
||||
c.vits = GetOfflineTtsVitsModelConfig(o);
|
||||
|
||||
SHERPA_ONNX_ASSIGN_ATTR_INT32(num_threads, numThreads);
|
||||
|
||||
if (o.Has("debug") &&
|
||||
(o.Get("debug").IsNumber() || o.Get("debug").IsBoolean())) {
|
||||
if (o.Get("debug").IsBoolean()) {
|
||||
c.debug = o.Get("debug").As<Napi::Boolean>().Value();
|
||||
} else {
|
||||
c.debug = o.Get("debug").As<Napi::Number>().Int32Value();
|
||||
}
|
||||
}
|
||||
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(provider, provider);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static Napi::External<SherpaOnnxOfflineTts> CreateOfflineTtsWrapper(
|
||||
const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() != 1) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 1 argument. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsObject()) {
|
||||
Napi::TypeError::New(env, "Expect an object as the argument")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
Napi::Object o = info[0].As<Napi::Object>();
|
||||
|
||||
SherpaOnnxOfflineTtsConfig c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
|
||||
c.model = GetOfflineTtsModelConfig(o);
|
||||
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(rule_fsts, ruleFsts);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_INT32(max_num_sentences, maxNumSentences);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(rule_fars, ruleFars);
|
||||
|
||||
SherpaOnnxOfflineTts *tts = SherpaOnnxCreateOfflineTts(&c);
|
||||
|
||||
if (c.model.vits.model) {
|
||||
delete[] c.model.vits.model;
|
||||
}
|
||||
|
||||
if (c.model.vits.lexicon) {
|
||||
delete[] c.model.vits.lexicon;
|
||||
}
|
||||
|
||||
if (c.model.vits.tokens) {
|
||||
delete[] c.model.vits.tokens;
|
||||
}
|
||||
|
||||
if (c.model.vits.data_dir) {
|
||||
delete[] c.model.vits.data_dir;
|
||||
}
|
||||
|
||||
if (c.model.vits.dict_dir) {
|
||||
delete[] c.model.vits.dict_dir;
|
||||
}
|
||||
|
||||
if (c.model.provider) {
|
||||
delete[] c.model.provider;
|
||||
}
|
||||
|
||||
if (c.rule_fsts) {
|
||||
delete[] c.rule_fsts;
|
||||
}
|
||||
|
||||
if (c.rule_fars) {
|
||||
delete[] c.rule_fars;
|
||||
}
|
||||
|
||||
if (!tts) {
|
||||
Napi::TypeError::New(env, "Please check your config!")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
return Napi::External<SherpaOnnxOfflineTts>::New(
|
||||
env, tts, [](Napi::Env env, SherpaOnnxOfflineTts *tts) {
|
||||
SherpaOnnxDestroyOfflineTts(tts);
|
||||
});
|
||||
}
|
||||
|
||||
static Napi::Number OfflineTtsSampleRateWrapper(
|
||||
const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
|
||||
if (info.Length() != 1) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 1 argument. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(env, "Argument 0 should be an offline tts pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
SherpaOnnxOfflineTts *tts =
|
||||
info[0].As<Napi::External<SherpaOnnxOfflineTts>>().Data();
|
||||
|
||||
int32_t sample_rate = SherpaOnnxOfflineTtsSampleRate(tts);
|
||||
|
||||
return Napi::Number::New(env, sample_rate);
|
||||
}
|
||||
|
||||
static Napi::Number OfflineTtsNumSpeakersWrapper(
|
||||
const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
|
||||
if (info.Length() != 1) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 1 argument. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(env, "Argument 0 should be an offline tts pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
SherpaOnnxOfflineTts *tts =
|
||||
info[0].As<Napi::External<SherpaOnnxOfflineTts>>().Data();
|
||||
|
||||
int32_t num_speakers = SherpaOnnxOfflineTtsNumSpeakers(tts);
|
||||
|
||||
return Napi::Number::New(env, num_speakers);
|
||||
}
|
||||
|
||||
static Napi::Object OfflineTtsGenerateWrapper(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
|
||||
if (info.Length() != 2) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 1 argument. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(env, "Argument 0 should be an offline tts pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
SherpaOnnxOfflineTts *tts =
|
||||
info[0].As<Napi::External<SherpaOnnxOfflineTts>>().Data();
|
||||
|
||||
if (!info[1].IsObject()) {
|
||||
Napi::TypeError::New(env, "Argument 1 should be an object")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
Napi::Object obj = info[1].As<Napi::Object>();
|
||||
|
||||
if (!obj.Has("text")) {
|
||||
Napi::TypeError::New(env, "The argument object should have a field text")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!obj.Get("text").IsString()) {
|
||||
Napi::TypeError::New(env, "The object['text'] should be a string")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!obj.Has("sid")) {
|
||||
Napi::TypeError::New(env, "The argument object should have a field sid")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!obj.Get("sid").IsNumber()) {
|
||||
Napi::TypeError::New(env, "The object['sid'] should be a number")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!obj.Has("speed")) {
|
||||
Napi::TypeError::New(env, "The argument object should have a field speed")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!obj.Get("speed").IsNumber()) {
|
||||
Napi::TypeError::New(env, "The object['speed'] should be a number")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
bool enable_external_buffer = true;
|
||||
if (obj.Has("enableExternalBuffer") &&
|
||||
obj.Get("enableExternalBuffer").IsBoolean()) {
|
||||
enable_external_buffer =
|
||||
obj.Get("enableExternalBuffer").As<Napi::Boolean>().Value();
|
||||
}
|
||||
|
||||
Napi::String _text = obj.Get("text").As<Napi::String>();
|
||||
std::string text = _text.Utf8Value();
|
||||
int32_t sid = obj.Get("sid").As<Napi::Number>().Int32Value();
|
||||
float speed = obj.Get("speed").As<Napi::Number>().FloatValue();
|
||||
|
||||
const SherpaOnnxGeneratedAudio *audio =
|
||||
SherpaOnnxOfflineTtsGenerate(tts, text.c_str(), sid, speed);
|
||||
|
||||
if (enable_external_buffer) {
|
||||
Napi::ArrayBuffer arrayBuffer = Napi::ArrayBuffer::New(
|
||||
env, const_cast<float *>(audio->samples), sizeof(float) * audio->n,
|
||||
[](Napi::Env /*env*/, void * /*data*/,
|
||||
const SherpaOnnxGeneratedAudio *hint) {
|
||||
SherpaOnnxDestroyOfflineTtsGeneratedAudio(hint);
|
||||
},
|
||||
audio);
|
||||
Napi::Float32Array float32Array =
|
||||
Napi::Float32Array::New(env, audio->n, arrayBuffer, 0);
|
||||
|
||||
Napi::Object ans = Napi::Object::New(env);
|
||||
ans.Set(Napi::String::New(env, "samples"), float32Array);
|
||||
ans.Set(Napi::String::New(env, "sampleRate"), audio->sample_rate);
|
||||
return ans;
|
||||
} else {
|
||||
// don't use external buffer
|
||||
Napi::ArrayBuffer arrayBuffer =
|
||||
Napi::ArrayBuffer::New(env, sizeof(float) * audio->n);
|
||||
|
||||
Napi::Float32Array float32Array =
|
||||
Napi::Float32Array::New(env, audio->n, arrayBuffer, 0);
|
||||
|
||||
std::copy(audio->samples, audio->samples + audio->n, float32Array.Data());
|
||||
|
||||
Napi::Object ans = Napi::Object::New(env);
|
||||
ans.Set(Napi::String::New(env, "samples"), float32Array);
|
||||
ans.Set(Napi::String::New(env, "sampleRate"), audio->sample_rate);
|
||||
SherpaOnnxDestroyOfflineTtsGeneratedAudio(audio);
|
||||
return ans;
|
||||
}
|
||||
}
|
||||
|
||||
void InitNonStreamingTts(Napi::Env env, Napi::Object exports) {
|
||||
exports.Set(Napi::String::New(env, "createOfflineTts"),
|
||||
Napi::Function::New(env, CreateOfflineTtsWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "getOfflineTtsSampleRate"),
|
||||
Napi::Function::New(env, OfflineTtsSampleRateWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "getOfflineTtsNumSpeakers"),
|
||||
Napi::Function::New(env, OfflineTtsNumSpeakersWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "offlineTtsGenerate"),
|
||||
Napi::Function::New(env, OfflineTtsGenerateWrapper));
|
||||
}
|
||||
1
scripts/node-addon-api/src/non-streaming-tts.cc
Symbolic link
1
scripts/node-addon-api/src/non-streaming-tts.cc
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../harmony-os/SherpaOnnxHar/sherpa_onnx/src/main/cpp/non-streaming-tts.cc
|
||||
@@ -1,135 +0,0 @@
|
||||
// scripts/node-addon-api/src/punctuation.cc
|
||||
//
|
||||
// Copyright (c) 2024 Xiaomi Corporation
|
||||
#include <sstream>
|
||||
|
||||
#include "macros.h" // NOLINT
|
||||
#include "napi.h" // NOLINT
|
||||
#include "sherpa-onnx/c-api/c-api.h"
|
||||
|
||||
static SherpaOnnxOfflinePunctuationModelConfig GetOfflinePunctuationModelConfig(
|
||||
Napi::Object obj) {
|
||||
SherpaOnnxOfflinePunctuationModelConfig c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
|
||||
if (!obj.Has("model") || !obj.Get("model").IsObject()) {
|
||||
return c;
|
||||
}
|
||||
|
||||
Napi::Object o = obj.Get("model").As<Napi::Object>();
|
||||
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(ct_transformer, ctTransformer);
|
||||
|
||||
SHERPA_ONNX_ASSIGN_ATTR_INT32(num_threads, numThreads);
|
||||
|
||||
if (o.Has("debug") &&
|
||||
(o.Get("debug").IsNumber() || o.Get("debug").IsBoolean())) {
|
||||
if (o.Get("debug").IsBoolean()) {
|
||||
c.debug = o.Get("debug").As<Napi::Boolean>().Value();
|
||||
} else {
|
||||
c.debug = o.Get("debug").As<Napi::Number>().Int32Value();
|
||||
}
|
||||
}
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(provider, provider);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static Napi::External<SherpaOnnxOfflinePunctuation>
|
||||
CreateOfflinePunctuationWrapper(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() != 1) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 1 argument. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsObject()) {
|
||||
Napi::TypeError::New(env, "You should pass an object as the only argument.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
Napi::Object o = info[0].As<Napi::Object>();
|
||||
|
||||
SherpaOnnxOfflinePunctuationConfig c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
c.model = GetOfflinePunctuationModelConfig(o);
|
||||
|
||||
const SherpaOnnxOfflinePunctuation *punct =
|
||||
SherpaOnnxCreateOfflinePunctuation(&c);
|
||||
|
||||
if (c.model.ct_transformer) {
|
||||
delete[] c.model.ct_transformer;
|
||||
}
|
||||
|
||||
if (c.model.provider) {
|
||||
delete[] c.model.provider;
|
||||
}
|
||||
|
||||
if (!punct) {
|
||||
Napi::TypeError::New(env, "Please check your config!")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
return Napi::External<SherpaOnnxOfflinePunctuation>::New(
|
||||
env, const_cast<SherpaOnnxOfflinePunctuation *>(punct),
|
||||
[](Napi::Env env, SherpaOnnxOfflinePunctuation *punct) {
|
||||
SherpaOnnxDestroyOfflinePunctuation(punct);
|
||||
});
|
||||
}
|
||||
|
||||
static Napi::String OfflinePunctuationAddPunctWraper(
|
||||
const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() != 2) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 2 arguments. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(
|
||||
env,
|
||||
"You should pass an offline punctuation pointer as the first argument")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[1].IsString()) {
|
||||
Napi::TypeError::New(env, "You should pass a string as the second argument")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
SherpaOnnxOfflinePunctuation *punct =
|
||||
info[0].As<Napi::External<SherpaOnnxOfflinePunctuation>>().Data();
|
||||
Napi::String js_text = info[1].As<Napi::String>();
|
||||
std::string text = js_text.Utf8Value();
|
||||
|
||||
const char *punct_text =
|
||||
SherpaOfflinePunctuationAddPunct(punct, text.c_str());
|
||||
|
||||
Napi::String ans = Napi::String::New(env, punct_text);
|
||||
SherpaOfflinePunctuationFreeText(punct_text);
|
||||
return ans;
|
||||
}
|
||||
|
||||
void InitPunctuation(Napi::Env env, Napi::Object exports) {
|
||||
exports.Set(Napi::String::New(env, "createOfflinePunctuation"),
|
||||
Napi::Function::New(env, CreateOfflinePunctuationWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "offlinePunctuationAddPunct"),
|
||||
Napi::Function::New(env, OfflinePunctuationAddPunctWraper));
|
||||
}
|
||||
1
scripts/node-addon-api/src/punctuation.cc
Symbolic link
1
scripts/node-addon-api/src/punctuation.cc
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../harmony-os/SherpaOnnxHar/sherpa_onnx/src/main/cpp/punctuation.cc
|
||||
@@ -1,47 +0,0 @@
|
||||
// scripts/node-addon-api/src/sherpa-onnx-node-addon-api.cc
|
||||
//
|
||||
// Copyright (c) 2024 Xiaomi Corporation
|
||||
#include "napi.h" // NOLINT
|
||||
|
||||
void InitStreamingAsr(Napi::Env env, Napi::Object exports);
|
||||
|
||||
void InitNonStreamingAsr(Napi::Env env, Napi::Object exports);
|
||||
|
||||
void InitNonStreamingTts(Napi::Env env, Napi::Object exports);
|
||||
|
||||
void InitVad(Napi::Env env, Napi::Object exports);
|
||||
|
||||
void InitWaveReader(Napi::Env env, Napi::Object exports);
|
||||
|
||||
void InitWaveWriter(Napi::Env env, Napi::Object exports);
|
||||
|
||||
void InitSpokenLanguageID(Napi::Env env, Napi::Object exports);
|
||||
|
||||
void InitSpeakerID(Napi::Env env, Napi::Object exports);
|
||||
|
||||
void InitAudioTagging(Napi::Env env, Napi::Object exports);
|
||||
|
||||
void InitPunctuation(Napi::Env env, Napi::Object exports);
|
||||
|
||||
void InitKeywordSpotting(Napi::Env env, Napi::Object exports);
|
||||
|
||||
void InitNonStreamingSpeakerDiarization(Napi::Env env, Napi::Object exports);
|
||||
|
||||
Napi::Object Init(Napi::Env env, Napi::Object exports) {
|
||||
InitStreamingAsr(env, exports);
|
||||
InitNonStreamingAsr(env, exports);
|
||||
InitNonStreamingTts(env, exports);
|
||||
InitVad(env, exports);
|
||||
InitWaveReader(env, exports);
|
||||
InitWaveWriter(env, exports);
|
||||
InitSpokenLanguageID(env, exports);
|
||||
InitSpeakerID(env, exports);
|
||||
InitAudioTagging(env, exports);
|
||||
InitPunctuation(env, exports);
|
||||
InitKeywordSpotting(env, exports);
|
||||
InitNonStreamingSpeakerDiarization(env, exports);
|
||||
|
||||
return exports;
|
||||
}
|
||||
|
||||
NODE_API_MODULE(addon, Init)
|
||||
1
scripts/node-addon-api/src/sherpa-onnx-node-addon-api.cc
Symbolic link
1
scripts/node-addon-api/src/sherpa-onnx-node-addon-api.cc
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../harmony-os/SherpaOnnxHar/sherpa_onnx/src/main/cpp/sherpa-onnx-node-addon-api.cc
|
||||
@@ -1,808 +0,0 @@
|
||||
// scripts/node-addon-api/src/speaker-identification.cc
|
||||
//
|
||||
// Copyright (c) 2024 Xiaomi Corporation
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
|
||||
#include "macros.h" // NOLINT
|
||||
#include "napi.h" // NOLINT
|
||||
#include "sherpa-onnx/c-api/c-api.h"
|
||||
|
||||
static Napi::External<SherpaOnnxSpeakerEmbeddingExtractor>
|
||||
CreateSpeakerEmbeddingExtractorWrapper(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() != 1) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 1 argument. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsObject()) {
|
||||
Napi::TypeError::New(env, "You should pass an object as the only argument.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
Napi::Object o = info[0].As<Napi::Object>();
|
||||
|
||||
SherpaOnnxSpeakerEmbeddingExtractorConfig c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(model, model);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_INT32(num_threads, numThreads);
|
||||
|
||||
if (o.Has("debug") &&
|
||||
(o.Get("debug").IsNumber() || o.Get("debug").IsBoolean())) {
|
||||
if (o.Get("debug").IsBoolean()) {
|
||||
c.debug = o.Get("debug").As<Napi::Boolean>().Value();
|
||||
} else {
|
||||
c.debug = o.Get("debug").As<Napi::Number>().Int32Value();
|
||||
}
|
||||
}
|
||||
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(provider, provider);
|
||||
|
||||
const SherpaOnnxSpeakerEmbeddingExtractor *extractor =
|
||||
SherpaOnnxCreateSpeakerEmbeddingExtractor(&c);
|
||||
|
||||
if (c.model) {
|
||||
delete[] c.model;
|
||||
}
|
||||
|
||||
if (c.provider) {
|
||||
delete[] c.provider;
|
||||
}
|
||||
|
||||
if (!extractor) {
|
||||
Napi::TypeError::New(env, "Please check your config!")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
return Napi::External<SherpaOnnxSpeakerEmbeddingExtractor>::New(
|
||||
env, const_cast<SherpaOnnxSpeakerEmbeddingExtractor *>(extractor),
|
||||
[](Napi::Env env, SherpaOnnxSpeakerEmbeddingExtractor *extractor) {
|
||||
SherpaOnnxDestroySpeakerEmbeddingExtractor(extractor);
|
||||
});
|
||||
}
|
||||
|
||||
static Napi::Number SpeakerEmbeddingExtractorDimWrapper(
|
||||
const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
|
||||
if (info.Length() != 1) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 1 argument. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(
|
||||
env, "Argument 0 should be a speaker embedding extractor pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
SherpaOnnxSpeakerEmbeddingExtractor *extractor =
|
||||
info[0].As<Napi::External<SherpaOnnxSpeakerEmbeddingExtractor>>().Data();
|
||||
|
||||
int32_t dim = SherpaOnnxSpeakerEmbeddingExtractorDim(extractor);
|
||||
|
||||
return Napi::Number::New(env, dim);
|
||||
}
|
||||
|
||||
static Napi::External<SherpaOnnxOnlineStream>
|
||||
SpeakerEmbeddingExtractorCreateStreamWrapper(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() != 1) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 1 argument. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(env,
|
||||
"You should pass a speaker embedding extractor "
|
||||
"pointer as the only argument")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
SherpaOnnxSpeakerEmbeddingExtractor *extractor =
|
||||
info[0].As<Napi::External<SherpaOnnxSpeakerEmbeddingExtractor>>().Data();
|
||||
|
||||
const SherpaOnnxOnlineStream *stream =
|
||||
SherpaOnnxSpeakerEmbeddingExtractorCreateStream(extractor);
|
||||
|
||||
return Napi::External<SherpaOnnxOnlineStream>::New(
|
||||
env, const_cast<SherpaOnnxOnlineStream *>(stream),
|
||||
[](Napi::Env env, SherpaOnnxOnlineStream *stream) {
|
||||
SherpaOnnxDestroyOnlineStream(stream);
|
||||
});
|
||||
}
|
||||
|
||||
static Napi::Boolean SpeakerEmbeddingExtractorIsReadyWrapper(
|
||||
const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() != 2) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 2 arguments. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(
|
||||
env, "Argument 0 should be a speaker embedding extractor pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[1].IsExternal()) {
|
||||
Napi::TypeError::New(env, "Argument 1 should be an online stream pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
SherpaOnnxSpeakerEmbeddingExtractor *extractor =
|
||||
info[0].As<Napi::External<SherpaOnnxSpeakerEmbeddingExtractor>>().Data();
|
||||
|
||||
SherpaOnnxOnlineStream *stream =
|
||||
info[1].As<Napi::External<SherpaOnnxOnlineStream>>().Data();
|
||||
|
||||
int32_t is_ready =
|
||||
SherpaOnnxSpeakerEmbeddingExtractorIsReady(extractor, stream);
|
||||
|
||||
return Napi::Boolean::New(env, is_ready);
|
||||
}
|
||||
|
||||
static Napi::Float32Array SpeakerEmbeddingExtractorComputeEmbeddingWrapper(
|
||||
const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() != 2 && info.Length() != 3) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 2 or 3 arguments. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(
|
||||
env, "Argument 0 should be a speaker embedding extractor pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[1].IsExternal()) {
|
||||
Napi::TypeError::New(env, "Argument 1 should be an online stream pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
bool enable_external_buffer = true;
|
||||
if (info.Length() == 3) {
|
||||
if (info[2].IsBoolean()) {
|
||||
enable_external_buffer = info[2].As<Napi::Boolean>().Value();
|
||||
} else {
|
||||
Napi::TypeError::New(env, "Argument 2 should be a boolean.")
|
||||
.ThrowAsJavaScriptException();
|
||||
}
|
||||
}
|
||||
|
||||
SherpaOnnxSpeakerEmbeddingExtractor *extractor =
|
||||
info[0].As<Napi::External<SherpaOnnxSpeakerEmbeddingExtractor>>().Data();
|
||||
|
||||
SherpaOnnxOnlineStream *stream =
|
||||
info[1].As<Napi::External<SherpaOnnxOnlineStream>>().Data();
|
||||
|
||||
const float *v =
|
||||
SherpaOnnxSpeakerEmbeddingExtractorComputeEmbedding(extractor, stream);
|
||||
|
||||
int32_t dim = SherpaOnnxSpeakerEmbeddingExtractorDim(extractor);
|
||||
|
||||
if (enable_external_buffer) {
|
||||
Napi::ArrayBuffer arrayBuffer = Napi::ArrayBuffer::New(
|
||||
env, const_cast<float *>(v), sizeof(float) * dim,
|
||||
[](Napi::Env /*env*/, void *data) {
|
||||
SherpaOnnxSpeakerEmbeddingExtractorDestroyEmbedding(
|
||||
reinterpret_cast<float *>(data));
|
||||
});
|
||||
|
||||
return Napi::Float32Array::New(env, dim, arrayBuffer, 0);
|
||||
} else {
|
||||
// don't use external buffer
|
||||
Napi::ArrayBuffer arrayBuffer =
|
||||
Napi::ArrayBuffer::New(env, sizeof(float) * dim);
|
||||
|
||||
Napi::Float32Array float32Array =
|
||||
Napi::Float32Array::New(env, dim, arrayBuffer, 0);
|
||||
|
||||
std::copy(v, v + dim, float32Array.Data());
|
||||
|
||||
SherpaOnnxSpeakerEmbeddingExtractorDestroyEmbedding(v);
|
||||
|
||||
return float32Array;
|
||||
}
|
||||
}
|
||||
|
||||
static Napi::External<SherpaOnnxSpeakerEmbeddingManager>
|
||||
CreateSpeakerEmbeddingManagerWrapper(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() != 1) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 1 argument. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsNumber()) {
|
||||
Napi::TypeError::New(env,
|
||||
"You should pass an integer as the only argument.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
int32_t dim = info[0].As<Napi::Number>().Int32Value();
|
||||
|
||||
const SherpaOnnxSpeakerEmbeddingManager *manager =
|
||||
SherpaOnnxCreateSpeakerEmbeddingManager(dim);
|
||||
|
||||
if (!manager) {
|
||||
Napi::TypeError::New(env, "Please check your input dim!")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
return Napi::External<SherpaOnnxSpeakerEmbeddingManager>::New(
|
||||
env, const_cast<SherpaOnnxSpeakerEmbeddingManager *>(manager),
|
||||
[](Napi::Env env, SherpaOnnxSpeakerEmbeddingManager *manager) {
|
||||
SherpaOnnxDestroySpeakerEmbeddingManager(manager);
|
||||
});
|
||||
}
|
||||
|
||||
static Napi::Boolean SpeakerEmbeddingManagerAddWrapper(
|
||||
const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() != 2) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 2 arguments. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(env,
|
||||
"You should pass a speaker embedding manager pointer "
|
||||
"as the first argument.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[1].IsObject()) {
|
||||
Napi::TypeError::New(env, "Argument 1 should be an object")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
SherpaOnnxSpeakerEmbeddingManager *manager =
|
||||
info[0].As<Napi::External<SherpaOnnxSpeakerEmbeddingManager>>().Data();
|
||||
|
||||
Napi::Object obj = info[1].As<Napi::Object>();
|
||||
|
||||
if (!obj.Has("v")) {
|
||||
Napi::TypeError::New(env, "The argument object should have a field v")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!obj.Get("v").IsTypedArray()) {
|
||||
Napi::TypeError::New(env, "The object['v'] should be a typed array")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!obj.Has("name")) {
|
||||
Napi::TypeError::New(env, "The argument object should have a field name")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!obj.Get("name").IsString()) {
|
||||
Napi::TypeError::New(env, "The object['name'] should be a string")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
Napi::Float32Array v = obj.Get("v").As<Napi::Float32Array>();
|
||||
Napi::String js_name = obj.Get("name").As<Napi::String>();
|
||||
std::string name = js_name.Utf8Value();
|
||||
|
||||
int32_t ok =
|
||||
SherpaOnnxSpeakerEmbeddingManagerAdd(manager, name.c_str(), v.Data());
|
||||
return Napi::Boolean::New(env, ok);
|
||||
}
|
||||
|
||||
static Napi::Boolean SpeakerEmbeddingManagerAddListFlattenedWrapper(
|
||||
const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() != 2) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 2 arguments. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(env,
|
||||
"You should pass a speaker embedding manager pointer "
|
||||
"as the first argument.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[1].IsObject()) {
|
||||
Napi::TypeError::New(env, "Argument 1 should be an object")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
SherpaOnnxSpeakerEmbeddingManager *manager =
|
||||
info[0].As<Napi::External<SherpaOnnxSpeakerEmbeddingManager>>().Data();
|
||||
|
||||
Napi::Object obj = info[1].As<Napi::Object>();
|
||||
|
||||
if (!obj.Has("vv")) {
|
||||
Napi::TypeError::New(env, "The argument object should have a field vv")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!obj.Get("vv").IsTypedArray()) {
|
||||
Napi::TypeError::New(env, "The object['vv'] should be a typed array")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!obj.Has("name")) {
|
||||
Napi::TypeError::New(env, "The argument object should have a field name")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!obj.Get("name").IsString()) {
|
||||
Napi::TypeError::New(env, "The object['name'] should be a string")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!obj.Has("n")) {
|
||||
Napi::TypeError::New(env, "The argument object should have a field n")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!obj.Get("n").IsNumber()) {
|
||||
Napi::TypeError::New(env, "The object['n'] should be an integer")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
Napi::Float32Array v = obj.Get("vv").As<Napi::Float32Array>();
|
||||
Napi::String js_name = obj.Get("name").As<Napi::String>();
|
||||
int32_t n = obj.Get("n").As<Napi::Number>().Int32Value();
|
||||
|
||||
std::string name = js_name.Utf8Value();
|
||||
|
||||
int32_t ok = SherpaOnnxSpeakerEmbeddingManagerAddListFlattened(
|
||||
manager, name.c_str(), v.Data(), n);
|
||||
|
||||
return Napi::Boolean::New(env, ok);
|
||||
}
|
||||
|
||||
static Napi::Boolean SpeakerEmbeddingManagerRemoveWrapper(
|
||||
const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() != 2) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 2 arguments. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(env,
|
||||
"You should pass a speaker embedding manager pointer "
|
||||
"as the first argument.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[1].IsString()) {
|
||||
Napi::TypeError::New(env, "Argument 1 should be string")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
SherpaOnnxSpeakerEmbeddingManager *manager =
|
||||
info[0].As<Napi::External<SherpaOnnxSpeakerEmbeddingManager>>().Data();
|
||||
|
||||
Napi::String js_name = info[1].As<Napi::String>();
|
||||
std::string name = js_name.Utf8Value();
|
||||
|
||||
int32_t ok = SherpaOnnxSpeakerEmbeddingManagerRemove(manager, name.c_str());
|
||||
|
||||
return Napi::Boolean::New(env, ok);
|
||||
}
|
||||
|
||||
static Napi::String SpeakerEmbeddingManagerSearchWrapper(
|
||||
const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() != 2) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 2 arguments. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(env,
|
||||
"You should pass a speaker embedding manager pointer "
|
||||
"as the first argument.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[1].IsObject()) {
|
||||
Napi::TypeError::New(env, "Argument 1 should be an object")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
SherpaOnnxSpeakerEmbeddingManager *manager =
|
||||
info[0].As<Napi::External<SherpaOnnxSpeakerEmbeddingManager>>().Data();
|
||||
|
||||
Napi::Object obj = info[1].As<Napi::Object>();
|
||||
|
||||
if (!obj.Has("v")) {
|
||||
Napi::TypeError::New(env, "The argument object should have a field v")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!obj.Get("v").IsTypedArray()) {
|
||||
Napi::TypeError::New(env, "The object['v'] should be a typed array")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!obj.Has("threshold")) {
|
||||
Napi::TypeError::New(env,
|
||||
"The argument object should have a field threshold")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!obj.Get("threshold").IsNumber()) {
|
||||
Napi::TypeError::New(env, "The object['threshold'] should be a float")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
Napi::Float32Array v = obj.Get("v").As<Napi::Float32Array>();
|
||||
float threshold = obj.Get("threshold").As<Napi::Number>().FloatValue();
|
||||
|
||||
const char *name =
|
||||
SherpaOnnxSpeakerEmbeddingManagerSearch(manager, v.Data(), threshold);
|
||||
const char *p = name;
|
||||
if (!p) {
|
||||
p = "";
|
||||
}
|
||||
|
||||
Napi::String js_name = Napi::String::New(env, p);
|
||||
SherpaOnnxSpeakerEmbeddingManagerFreeSearch(name);
|
||||
|
||||
return js_name;
|
||||
}
|
||||
|
||||
static Napi::Boolean SpeakerEmbeddingManagerVerifyWrapper(
|
||||
const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() != 2) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 2 arguments. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(env,
|
||||
"You should pass a speaker embedding manager pointer "
|
||||
"as the first argument.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[1].IsObject()) {
|
||||
Napi::TypeError::New(env, "Argument 1 should be an object")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
SherpaOnnxSpeakerEmbeddingManager *manager =
|
||||
info[0].As<Napi::External<SherpaOnnxSpeakerEmbeddingManager>>().Data();
|
||||
|
||||
Napi::Object obj = info[1].As<Napi::Object>();
|
||||
|
||||
if (!obj.Has("v")) {
|
||||
Napi::TypeError::New(env, "The argument object should have a field v")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!obj.Get("v").IsTypedArray()) {
|
||||
Napi::TypeError::New(env, "The object['v'] should be a typed array")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!obj.Has("threshold")) {
|
||||
Napi::TypeError::New(env,
|
||||
"The argument object should have a field threshold")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!obj.Get("threshold").IsNumber()) {
|
||||
Napi::TypeError::New(env, "The object['threshold'] should be a float")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!obj.Has("name")) {
|
||||
Napi::TypeError::New(env, "The argument object should have a field name")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!obj.Get("name").IsString()) {
|
||||
Napi::TypeError::New(env, "The object['name'] should be a string")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
Napi::Float32Array v = obj.Get("v").As<Napi::Float32Array>();
|
||||
float threshold = obj.Get("threshold").As<Napi::Number>().FloatValue();
|
||||
|
||||
Napi::String js_name = obj.Get("name").As<Napi::String>();
|
||||
std::string name = js_name.Utf8Value();
|
||||
|
||||
int32_t found = SherpaOnnxSpeakerEmbeddingManagerVerify(manager, name.c_str(),
|
||||
v.Data(), threshold);
|
||||
|
||||
return Napi::Boolean::New(env, found);
|
||||
}
|
||||
|
||||
static Napi::Boolean SpeakerEmbeddingManagerContainsWrapper(
|
||||
const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() != 2) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 2 arguments. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(env,
|
||||
"You should pass a speaker embedding manager pointer "
|
||||
"as the first argument.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[1].IsString()) {
|
||||
Napi::TypeError::New(env, "Argument 1 should be a string")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
SherpaOnnxSpeakerEmbeddingManager *manager =
|
||||
info[0].As<Napi::External<SherpaOnnxSpeakerEmbeddingManager>>().Data();
|
||||
|
||||
Napi::String js_name = info[1].As<Napi::String>();
|
||||
std::string name = js_name.Utf8Value();
|
||||
|
||||
int32_t exists =
|
||||
SherpaOnnxSpeakerEmbeddingManagerContains(manager, name.c_str());
|
||||
|
||||
return Napi::Boolean::New(env, exists);
|
||||
}
|
||||
|
||||
static Napi::Number SpeakerEmbeddingManagerNumSpeakersWrapper(
|
||||
const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() != 1) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 1 argument. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(env,
|
||||
"You should pass a speaker embedding manager pointer "
|
||||
"as the first argument.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
SherpaOnnxSpeakerEmbeddingManager *manager =
|
||||
info[0].As<Napi::External<SherpaOnnxSpeakerEmbeddingManager>>().Data();
|
||||
|
||||
int32_t num_speakers = SherpaOnnxSpeakerEmbeddingManagerNumSpeakers(manager);
|
||||
|
||||
return Napi::Number::New(env, num_speakers);
|
||||
}
|
||||
|
||||
static Napi::Array SpeakerEmbeddingManagerGetAllSpeakersWrapper(
|
||||
const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() != 1) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 1 argument. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(env,
|
||||
"You should pass a speaker embedding manager pointer "
|
||||
"as the first argument.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
SherpaOnnxSpeakerEmbeddingManager *manager =
|
||||
info[0].As<Napi::External<SherpaOnnxSpeakerEmbeddingManager>>().Data();
|
||||
|
||||
int32_t num_speakers = SherpaOnnxSpeakerEmbeddingManagerNumSpeakers(manager);
|
||||
if (num_speakers == 0) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const char *const *all_speaker_names =
|
||||
SherpaOnnxSpeakerEmbeddingManagerGetAllSpeakers(manager);
|
||||
|
||||
Napi::Array ans = Napi::Array::New(env, num_speakers);
|
||||
for (uint32_t i = 0; i != num_speakers; ++i) {
|
||||
ans[i] = Napi::String::New(env, all_speaker_names[i]);
|
||||
}
|
||||
SherpaOnnxSpeakerEmbeddingManagerFreeAllSpeakers(all_speaker_names);
|
||||
return ans;
|
||||
}
|
||||
|
||||
void InitSpeakerID(Napi::Env env, Napi::Object exports) {
|
||||
exports.Set(Napi::String::New(env, "createSpeakerEmbeddingExtractor"),
|
||||
Napi::Function::New(env, CreateSpeakerEmbeddingExtractorWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "speakerEmbeddingExtractorDim"),
|
||||
Napi::Function::New(env, SpeakerEmbeddingExtractorDimWrapper));
|
||||
|
||||
exports.Set(
|
||||
Napi::String::New(env, "speakerEmbeddingExtractorCreateStream"),
|
||||
Napi::Function::New(env, SpeakerEmbeddingExtractorCreateStreamWrapper));
|
||||
|
||||
exports.Set(
|
||||
Napi::String::New(env, "speakerEmbeddingExtractorIsReady"),
|
||||
Napi::Function::New(env, SpeakerEmbeddingExtractorIsReadyWrapper));
|
||||
|
||||
exports.Set(
|
||||
Napi::String::New(env, "speakerEmbeddingExtractorComputeEmbedding"),
|
||||
Napi::Function::New(env,
|
||||
SpeakerEmbeddingExtractorComputeEmbeddingWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "createSpeakerEmbeddingManager"),
|
||||
Napi::Function::New(env, CreateSpeakerEmbeddingManagerWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "speakerEmbeddingManagerAdd"),
|
||||
Napi::Function::New(env, SpeakerEmbeddingManagerAddWrapper));
|
||||
|
||||
exports.Set(
|
||||
Napi::String::New(env, "speakerEmbeddingManagerAddListFlattened"),
|
||||
Napi::Function::New(env, SpeakerEmbeddingManagerAddListFlattenedWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "speakerEmbeddingManagerRemove"),
|
||||
Napi::Function::New(env, SpeakerEmbeddingManagerRemoveWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "speakerEmbeddingManagerSearch"),
|
||||
Napi::Function::New(env, SpeakerEmbeddingManagerSearchWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "speakerEmbeddingManagerVerify"),
|
||||
Napi::Function::New(env, SpeakerEmbeddingManagerVerifyWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "speakerEmbeddingManagerContains"),
|
||||
Napi::Function::New(env, SpeakerEmbeddingManagerContainsWrapper));
|
||||
|
||||
exports.Set(
|
||||
Napi::String::New(env, "speakerEmbeddingManagerNumSpeakers"),
|
||||
Napi::Function::New(env, SpeakerEmbeddingManagerNumSpeakersWrapper));
|
||||
|
||||
exports.Set(
|
||||
Napi::String::New(env, "speakerEmbeddingManagerGetAllSpeakers"),
|
||||
Napi::Function::New(env, SpeakerEmbeddingManagerGetAllSpeakersWrapper));
|
||||
}
|
||||
1
scripts/node-addon-api/src/speaker-identification.cc
Symbolic link
1
scripts/node-addon-api/src/speaker-identification.cc
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../harmony-os/SherpaOnnxHar/sherpa_onnx/src/main/cpp/speaker-identification.cc
|
||||
@@ -1,188 +0,0 @@
|
||||
// scripts/node-addon-api/src/spoken-language-identification.cc
|
||||
//
|
||||
// Copyright (c) 2024 Xiaomi Corporation
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "macros.h" // NOLINT
|
||||
#include "napi.h" // NOLINT
|
||||
#include "sherpa-onnx/c-api/c-api.h"
|
||||
|
||||
static SherpaOnnxSpokenLanguageIdentificationWhisperConfig
|
||||
GetSpokenLanguageIdentificationWhisperConfig(Napi::Object obj) {
|
||||
SherpaOnnxSpokenLanguageIdentificationWhisperConfig c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
|
||||
if (!obj.Has("whisper") || !obj.Get("whisper").IsObject()) {
|
||||
return c;
|
||||
}
|
||||
|
||||
Napi::Object o = obj.Get("whisper").As<Napi::Object>();
|
||||
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(encoder, encoder);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(decoder, decoder);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_INT32(tail_paddings, tailPaddings);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static Napi::External<SherpaOnnxSpokenLanguageIdentification>
|
||||
CreateSpokenLanguageIdentificationWrapper(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() != 1) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 1 argument. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsObject()) {
|
||||
Napi::TypeError::New(env, "You should pass an object as the only argument.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
Napi::Object o = info[0].As<Napi::Object>();
|
||||
|
||||
SherpaOnnxSpokenLanguageIdentificationConfig c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
c.whisper = GetSpokenLanguageIdentificationWhisperConfig(o);
|
||||
|
||||
SHERPA_ONNX_ASSIGN_ATTR_INT32(num_threads, numThreads);
|
||||
|
||||
if (o.Has("debug") &&
|
||||
(o.Get("debug").IsNumber() || o.Get("debug").IsBoolean())) {
|
||||
if (o.Get("debug").IsBoolean()) {
|
||||
c.debug = o.Get("debug").As<Napi::Boolean>().Value();
|
||||
} else {
|
||||
c.debug = o.Get("debug").As<Napi::Number>().Int32Value();
|
||||
}
|
||||
}
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(provider, provider);
|
||||
|
||||
const SherpaOnnxSpokenLanguageIdentification *slid =
|
||||
SherpaOnnxCreateSpokenLanguageIdentification(&c);
|
||||
|
||||
if (c.whisper.encoder) {
|
||||
delete[] c.whisper.encoder;
|
||||
}
|
||||
|
||||
if (c.whisper.decoder) {
|
||||
delete[] c.whisper.decoder;
|
||||
}
|
||||
|
||||
if (c.provider) {
|
||||
delete[] c.provider;
|
||||
}
|
||||
|
||||
if (!slid) {
|
||||
Napi::TypeError::New(env, "Please check your config!")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
return Napi::External<SherpaOnnxSpokenLanguageIdentification>::New(
|
||||
env, const_cast<SherpaOnnxSpokenLanguageIdentification *>(slid),
|
||||
[](Napi::Env env, SherpaOnnxSpokenLanguageIdentification *slid) {
|
||||
SherpaOnnxDestroySpokenLanguageIdentification(slid);
|
||||
});
|
||||
}
|
||||
|
||||
static Napi::External<SherpaOnnxOfflineStream>
|
||||
SpokenLanguageIdentificationCreateOfflineStreamWrapper(
|
||||
const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() != 1) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 1 argument. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(
|
||||
env,
|
||||
"You should pass an offline language ID pointer as the only argument")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
SherpaOnnxSpokenLanguageIdentification *slid =
|
||||
info[0]
|
||||
.As<Napi::External<SherpaOnnxSpokenLanguageIdentification>>()
|
||||
.Data();
|
||||
|
||||
SherpaOnnxOfflineStream *stream =
|
||||
SherpaOnnxSpokenLanguageIdentificationCreateOfflineStream(slid);
|
||||
|
||||
return Napi::External<SherpaOnnxOfflineStream>::New(
|
||||
env, stream, [](Napi::Env env, SherpaOnnxOfflineStream *stream) {
|
||||
SherpaOnnxDestroyOfflineStream(stream);
|
||||
});
|
||||
}
|
||||
|
||||
static Napi::String SpokenLanguageIdentificationComputeWrapper(
|
||||
const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() != 2) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 2 arguments. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(
|
||||
env, "Argument 0 should be an offline spoken language ID pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[1].IsExternal()) {
|
||||
Napi::TypeError::New(env, "Argument 1 should be an offline stream pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
SherpaOnnxSpokenLanguageIdentification *slid =
|
||||
info[0]
|
||||
.As<Napi::External<SherpaOnnxSpokenLanguageIdentification>>()
|
||||
.Data();
|
||||
|
||||
SherpaOnnxOfflineStream *stream =
|
||||
info[1].As<Napi::External<SherpaOnnxOfflineStream>>().Data();
|
||||
|
||||
const SherpaOnnxSpokenLanguageIdentificationResult *r =
|
||||
SherpaOnnxSpokenLanguageIdentificationCompute(slid, stream);
|
||||
|
||||
std::string lang = r->lang;
|
||||
SherpaOnnxDestroySpokenLanguageIdentificationResult(r);
|
||||
|
||||
return Napi::String::New(env, lang);
|
||||
}
|
||||
|
||||
void InitSpokenLanguageID(Napi::Env env, Napi::Object exports) {
|
||||
exports.Set(
|
||||
Napi::String::New(env, "createSpokenLanguageIdentification"),
|
||||
Napi::Function::New(env, CreateSpokenLanguageIdentificationWrapper));
|
||||
|
||||
exports.Set(
|
||||
Napi::String::New(env, "createSpokenLanguageIdentificationOfflineStream"),
|
||||
Napi::Function::New(
|
||||
env, SpokenLanguageIdentificationCreateOfflineStreamWrapper));
|
||||
|
||||
exports.Set(
|
||||
Napi::String::New(env, "spokenLanguageIdentificationCompute"),
|
||||
Napi::Function::New(env, SpokenLanguageIdentificationComputeWrapper));
|
||||
}
|
||||
1
scripts/node-addon-api/src/spoken-language-identification.cc
Symbolic link
1
scripts/node-addon-api/src/spoken-language-identification.cc
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../harmony-os/SherpaOnnxHar/sherpa_onnx/src/main/cpp/spoken-language-identification.cc
|
||||
@@ -1,708 +0,0 @@
|
||||
// scripts/node-addon-api/src/streaming-asr.cc
|
||||
//
|
||||
// Copyright (c) 2024 Xiaomi Corporation
|
||||
#include <sstream>
|
||||
|
||||
#include "macros.h" // NOLINT
|
||||
#include "napi.h" // NOLINT
|
||||
#include "sherpa-onnx/c-api/c-api.h"
|
||||
/*
|
||||
{
|
||||
'featConfig': {
|
||||
'sampleRate': 16000,
|
||||
'featureDim': 80,
|
||||
}
|
||||
};
|
||||
*/
|
||||
SherpaOnnxFeatureConfig GetFeatureConfig(Napi::Object obj) {
|
||||
SherpaOnnxFeatureConfig c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
|
||||
if (!obj.Has("featConfig") || !obj.Get("featConfig").IsObject()) {
|
||||
return c;
|
||||
}
|
||||
|
||||
Napi::Object o = obj.Get("featConfig").As<Napi::Object>();
|
||||
|
||||
SHERPA_ONNX_ASSIGN_ATTR_INT32(sample_rate, sampleRate);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_INT32(feature_dim, featureDim);
|
||||
|
||||
return c;
|
||||
}
|
||||
/*
|
||||
{
|
||||
'transducer': {
|
||||
'encoder': './encoder.onnx',
|
||||
'decoder': './decoder.onnx',
|
||||
'joiner': './joiner.onnx',
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
static SherpaOnnxOnlineTransducerModelConfig GetOnlineTransducerModelConfig(
|
||||
Napi::Object obj) {
|
||||
SherpaOnnxOnlineTransducerModelConfig c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
|
||||
if (!obj.Has("transducer") || !obj.Get("transducer").IsObject()) {
|
||||
return c;
|
||||
}
|
||||
|
||||
Napi::Object o = obj.Get("transducer").As<Napi::Object>();
|
||||
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(encoder, encoder);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(decoder, decoder);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(joiner, joiner);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static SherpaOnnxOnlineZipformer2CtcModelConfig
|
||||
GetOnlineZipformer2CtcModelConfig(Napi::Object obj) {
|
||||
SherpaOnnxOnlineZipformer2CtcModelConfig c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
|
||||
if (!obj.Has("zipformer2Ctc") || !obj.Get("zipformer2Ctc").IsObject()) {
|
||||
return c;
|
||||
}
|
||||
|
||||
Napi::Object o = obj.Get("zipformer2Ctc").As<Napi::Object>();
|
||||
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(model, model);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static SherpaOnnxOnlineParaformerModelConfig GetOnlineParaformerModelConfig(
|
||||
Napi::Object obj) {
|
||||
SherpaOnnxOnlineParaformerModelConfig c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
|
||||
if (!obj.Has("paraformer") || !obj.Get("paraformer").IsObject()) {
|
||||
return c;
|
||||
}
|
||||
|
||||
Napi::Object o = obj.Get("paraformer").As<Napi::Object>();
|
||||
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(encoder, encoder);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(decoder, decoder);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
SherpaOnnxOnlineModelConfig GetOnlineModelConfig(Napi::Object obj) {
|
||||
SherpaOnnxOnlineModelConfig c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
|
||||
if (!obj.Has("modelConfig") || !obj.Get("modelConfig").IsObject()) {
|
||||
return c;
|
||||
}
|
||||
|
||||
Napi::Object o = obj.Get("modelConfig").As<Napi::Object>();
|
||||
|
||||
c.transducer = GetOnlineTransducerModelConfig(o);
|
||||
c.paraformer = GetOnlineParaformerModelConfig(o);
|
||||
c.zipformer2_ctc = GetOnlineZipformer2CtcModelConfig(o);
|
||||
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(tokens, tokens);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_INT32(num_threads, numThreads);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(provider, provider);
|
||||
|
||||
if (o.Has("debug") &&
|
||||
(o.Get("debug").IsNumber() || o.Get("debug").IsBoolean())) {
|
||||
if (o.Get("debug").IsBoolean()) {
|
||||
c.debug = o.Get("debug").As<Napi::Boolean>().Value();
|
||||
} else {
|
||||
c.debug = o.Get("debug").As<Napi::Number>().Int32Value();
|
||||
}
|
||||
}
|
||||
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(model_type, modelType);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(modeling_unit, modelingUnit);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(bpe_vocab, bpeVocab);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(tokens_buf, tokensBuf);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_INT32(tokens_buf_size, tokensBufSize);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static SherpaOnnxOnlineCtcFstDecoderConfig GetCtcFstDecoderConfig(
|
||||
Napi::Object obj) {
|
||||
SherpaOnnxOnlineCtcFstDecoderConfig c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
|
||||
if (!obj.Has("ctcFstDecoderConfig") ||
|
||||
!obj.Get("ctcFstDecoderConfig").IsObject()) {
|
||||
return c;
|
||||
}
|
||||
|
||||
Napi::Object o = obj.Get("ctcFstDecoderConfig").As<Napi::Object>();
|
||||
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(graph, graph);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_INT32(max_active, maxActive);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static Napi::External<SherpaOnnxOnlineRecognizer> CreateOnlineRecognizerWrapper(
|
||||
const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() != 1) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 1 argument. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsObject()) {
|
||||
Napi::TypeError::New(env, "Expect an object as the argument")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
Napi::Object o = info[0].As<Napi::Object>();
|
||||
SherpaOnnxOnlineRecognizerConfig c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
c.feat_config = GetFeatureConfig(o);
|
||||
c.model_config = GetOnlineModelConfig(o);
|
||||
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(decoding_method, decodingMethod);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_INT32(max_active_paths, maxActivePaths);
|
||||
|
||||
// enableEndpoint can be either a boolean or an integer
|
||||
if (o.Has("enableEndpoint") && (o.Get("enableEndpoint").IsNumber() ||
|
||||
o.Get("enableEndpoint").IsBoolean())) {
|
||||
if (o.Get("enableEndpoint").IsNumber()) {
|
||||
c.enable_endpoint =
|
||||
o.Get("enableEndpoint").As<Napi::Number>().Int32Value();
|
||||
} else {
|
||||
c.enable_endpoint = o.Get("enableEndpoint").As<Napi::Boolean>().Value();
|
||||
}
|
||||
}
|
||||
|
||||
SHERPA_ONNX_ASSIGN_ATTR_FLOAT(rule1_min_trailing_silence,
|
||||
rule1MinTrailingSilence);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_FLOAT(rule2_min_trailing_silence,
|
||||
rule2MinTrailingSilence);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_FLOAT(rule3_min_utterance_length,
|
||||
rule3MinUtteranceLength);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(hotwords_file, hotwordsFile);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_FLOAT(hotwords_score, hotwordsScore);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(rule_fsts, ruleFsts);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(rule_fars, ruleFars);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_FLOAT(blank_penalty, blankPenalty);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(hotwords_buf, hotwordsBuf);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_INT32(hotwords_buf_size, hotwordsBufSize);
|
||||
|
||||
c.ctc_fst_decoder_config = GetCtcFstDecoderConfig(o);
|
||||
|
||||
const SherpaOnnxOnlineRecognizer *recognizer =
|
||||
SherpaOnnxCreateOnlineRecognizer(&c);
|
||||
|
||||
if (c.model_config.transducer.encoder) {
|
||||
delete[] c.model_config.transducer.encoder;
|
||||
}
|
||||
|
||||
if (c.model_config.transducer.decoder) {
|
||||
delete[] c.model_config.transducer.decoder;
|
||||
}
|
||||
|
||||
if (c.model_config.transducer.joiner) {
|
||||
delete[] c.model_config.transducer.joiner;
|
||||
}
|
||||
|
||||
if (c.model_config.paraformer.encoder) {
|
||||
delete[] c.model_config.paraformer.encoder;
|
||||
}
|
||||
|
||||
if (c.model_config.paraformer.decoder) {
|
||||
delete[] c.model_config.paraformer.decoder;
|
||||
}
|
||||
|
||||
if (c.model_config.zipformer2_ctc.model) {
|
||||
delete[] c.model_config.zipformer2_ctc.model;
|
||||
}
|
||||
|
||||
if (c.model_config.tokens) {
|
||||
delete[] c.model_config.tokens;
|
||||
}
|
||||
|
||||
if (c.model_config.provider) {
|
||||
delete[] c.model_config.provider;
|
||||
}
|
||||
|
||||
if (c.model_config.model_type) {
|
||||
delete[] c.model_config.model_type;
|
||||
}
|
||||
|
||||
if (c.model_config.modeling_unit) {
|
||||
delete[] c.model_config.modeling_unit;
|
||||
}
|
||||
|
||||
if (c.model_config.bpe_vocab) {
|
||||
delete[] c.model_config.bpe_vocab;
|
||||
}
|
||||
|
||||
if (c.model_config.tokens_buf) {
|
||||
delete[] c.model_config.tokens_buf;
|
||||
}
|
||||
|
||||
if (c.decoding_method) {
|
||||
delete[] c.decoding_method;
|
||||
}
|
||||
|
||||
if (c.hotwords_file) {
|
||||
delete[] c.hotwords_file;
|
||||
}
|
||||
|
||||
if (c.rule_fsts) {
|
||||
delete[] c.rule_fsts;
|
||||
}
|
||||
|
||||
if (c.rule_fars) {
|
||||
delete[] c.rule_fars;
|
||||
}
|
||||
|
||||
if (c.hotwords_buf) {
|
||||
delete[] c.hotwords_buf;
|
||||
}
|
||||
|
||||
if (c.ctc_fst_decoder_config.graph) {
|
||||
delete[] c.ctc_fst_decoder_config.graph;
|
||||
}
|
||||
|
||||
if (!recognizer) {
|
||||
Napi::TypeError::New(env, "Please check your config!")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
return Napi::External<SherpaOnnxOnlineRecognizer>::New(
|
||||
env, const_cast<SherpaOnnxOnlineRecognizer *>(recognizer),
|
||||
[](Napi::Env env, SherpaOnnxOnlineRecognizer *recognizer) {
|
||||
SherpaOnnxDestroyOnlineRecognizer(recognizer);
|
||||
});
|
||||
}
|
||||
|
||||
static Napi::External<SherpaOnnxOnlineStream> CreateOnlineStreamWrapper(
|
||||
const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() != 1) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 1 argument. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(
|
||||
env,
|
||||
"You should pass an online recognizer pointer as the only argument")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
SherpaOnnxOnlineRecognizer *recognizer =
|
||||
info[0].As<Napi::External<SherpaOnnxOnlineRecognizer>>().Data();
|
||||
|
||||
const SherpaOnnxOnlineStream *stream =
|
||||
SherpaOnnxCreateOnlineStream(recognizer);
|
||||
|
||||
return Napi::External<SherpaOnnxOnlineStream>::New(
|
||||
env, const_cast<SherpaOnnxOnlineStream *>(stream),
|
||||
[](Napi::Env env, SherpaOnnxOnlineStream *stream) {
|
||||
SherpaOnnxDestroyOnlineStream(stream);
|
||||
});
|
||||
}
|
||||
|
||||
static void AcceptWaveformWrapper(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
|
||||
if (info.Length() != 2) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 2 arguments. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(env, "Argument 0 should be an online stream pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
SherpaOnnxOnlineStream *stream =
|
||||
info[0].As<Napi::External<SherpaOnnxOnlineStream>>().Data();
|
||||
|
||||
if (!info[1].IsObject()) {
|
||||
Napi::TypeError::New(env, "Argument 1 should be an object")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Napi::Object obj = info[1].As<Napi::Object>();
|
||||
|
||||
if (!obj.Has("samples")) {
|
||||
Napi::TypeError::New(env, "The argument object should have a field samples")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!obj.Get("samples").IsTypedArray()) {
|
||||
Napi::TypeError::New(env, "The object['samples'] should be a typed array")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!obj.Has("sampleRate")) {
|
||||
Napi::TypeError::New(env,
|
||||
"The argument object should have a field sampleRate")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!obj.Get("sampleRate").IsNumber()) {
|
||||
Napi::TypeError::New(env, "The object['samples'] should be a number")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Napi::Float32Array samples = obj.Get("samples").As<Napi::Float32Array>();
|
||||
int32_t sample_rate = obj.Get("sampleRate").As<Napi::Number>().Int32Value();
|
||||
|
||||
SherpaOnnxOnlineStreamAcceptWaveform(stream, sample_rate, samples.Data(),
|
||||
samples.ElementLength());
|
||||
}
|
||||
|
||||
static Napi::Boolean IsOnlineStreamReadyWrapper(
|
||||
const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() != 2) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 2 arguments. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(env,
|
||||
"Argument 0 should be an online recognizer pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[1].IsExternal()) {
|
||||
Napi::TypeError::New(env, "Argument 1 should be an online stream pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
SherpaOnnxOnlineRecognizer *recognizer =
|
||||
info[0].As<Napi::External<SherpaOnnxOnlineRecognizer>>().Data();
|
||||
|
||||
SherpaOnnxOnlineStream *stream =
|
||||
info[1].As<Napi::External<SherpaOnnxOnlineStream>>().Data();
|
||||
|
||||
int32_t is_ready = SherpaOnnxIsOnlineStreamReady(recognizer, stream);
|
||||
|
||||
return Napi::Boolean::New(env, is_ready);
|
||||
}
|
||||
|
||||
static void DecodeOnlineStreamWrapper(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() != 2) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 2 arguments. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(env,
|
||||
"Argument 0 should be an online recognizer pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!info[1].IsExternal()) {
|
||||
Napi::TypeError::New(env, "Argument 1 should be an online stream pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
SherpaOnnxOnlineRecognizer *recognizer =
|
||||
info[0].As<Napi::External<SherpaOnnxOnlineRecognizer>>().Data();
|
||||
|
||||
SherpaOnnxOnlineStream *stream =
|
||||
info[1].As<Napi::External<SherpaOnnxOnlineStream>>().Data();
|
||||
|
||||
SherpaOnnxDecodeOnlineStream(recognizer, stream);
|
||||
}
|
||||
|
||||
static Napi::String GetOnlineStreamResultAsJsonWrapper(
|
||||
const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() != 2) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 2 arguments. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(env,
|
||||
"Argument 0 should be an online recognizer pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[1].IsExternal()) {
|
||||
Napi::TypeError::New(env, "Argument 1 should be an online stream pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
SherpaOnnxOnlineRecognizer *recognizer =
|
||||
info[0].As<Napi::External<SherpaOnnxOnlineRecognizer>>().Data();
|
||||
|
||||
SherpaOnnxOnlineStream *stream =
|
||||
info[1].As<Napi::External<SherpaOnnxOnlineStream>>().Data();
|
||||
|
||||
const char *json = SherpaOnnxGetOnlineStreamResultAsJson(recognizer, stream);
|
||||
Napi::String s = Napi::String::New(env, json);
|
||||
|
||||
SherpaOnnxDestroyOnlineStreamResultJson(json);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static void InputFinishedWrapper(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
|
||||
if (info.Length() != 1) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 1 argument. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(env, "Argument 0 should be an online stream pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
SherpaOnnxOnlineStream *stream =
|
||||
info[0].As<Napi::External<SherpaOnnxOnlineStream>>().Data();
|
||||
|
||||
SherpaOnnxOnlineStreamInputFinished(stream);
|
||||
}
|
||||
|
||||
static void ResetOnlineStreamWrapper(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() != 2) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 2 arguments. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(env,
|
||||
"Argument 0 should be an online recognizer pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!info[1].IsExternal()) {
|
||||
Napi::TypeError::New(env, "Argument 1 should be an online stream pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
SherpaOnnxOnlineRecognizer *recognizer =
|
||||
info[0].As<Napi::External<SherpaOnnxOnlineRecognizer>>().Data();
|
||||
|
||||
SherpaOnnxOnlineStream *stream =
|
||||
info[1].As<Napi::External<SherpaOnnxOnlineStream>>().Data();
|
||||
|
||||
SherpaOnnxOnlineStreamReset(recognizer, stream);
|
||||
}
|
||||
|
||||
static Napi::Boolean IsEndpointWrapper(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() != 2) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 2 arguments. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(env,
|
||||
"Argument 0 should be an online recognizer pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[1].IsExternal()) {
|
||||
Napi::TypeError::New(env, "Argument 1 should be an online stream pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
SherpaOnnxOnlineRecognizer *recognizer =
|
||||
info[0].As<Napi::External<SherpaOnnxOnlineRecognizer>>().Data();
|
||||
|
||||
SherpaOnnxOnlineStream *stream =
|
||||
info[1].As<Napi::External<SherpaOnnxOnlineStream>>().Data();
|
||||
|
||||
int32_t is_endpoint = SherpaOnnxOnlineStreamIsEndpoint(recognizer, stream);
|
||||
|
||||
return Napi::Boolean::New(env, is_endpoint);
|
||||
}
|
||||
|
||||
static Napi::External<SherpaOnnxDisplay> CreateDisplayWrapper(
|
||||
const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() != 1) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 1 argument. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsNumber()) {
|
||||
Napi::TypeError::New(env, "Expect a number as the argument")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
int32_t max_word_per_line = info[0].As<Napi::Number>().Int32Value();
|
||||
|
||||
const SherpaOnnxDisplay *display = SherpaOnnxCreateDisplay(max_word_per_line);
|
||||
|
||||
return Napi::External<SherpaOnnxDisplay>::New(
|
||||
env, const_cast<SherpaOnnxDisplay *>(display),
|
||||
[](Napi::Env env, SherpaOnnxDisplay *display) {
|
||||
SherpaOnnxDestroyDisplay(display);
|
||||
});
|
||||
}
|
||||
|
||||
static void PrintWrapper(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
|
||||
if (info.Length() != 3) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 3 arguments. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(env, "Argument 0 should be an online stream pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!info[1].IsNumber()) {
|
||||
Napi::TypeError::New(env, "Argument 1 should be a number.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!info[2].IsString()) {
|
||||
Napi::TypeError::New(env, "Argument 2 should be a string.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
SherpaOnnxDisplay *display =
|
||||
info[0].As<Napi::External<SherpaOnnxDisplay>>().Data();
|
||||
|
||||
int32_t idx = info[1].As<Napi::Number>().Int32Value();
|
||||
|
||||
Napi::String text = info[2].As<Napi::String>();
|
||||
std::string s = text.Utf8Value();
|
||||
SherpaOnnxPrint(display, idx, s.c_str());
|
||||
}
|
||||
|
||||
void InitStreamingAsr(Napi::Env env, Napi::Object exports) {
|
||||
exports.Set(Napi::String::New(env, "createOnlineRecognizer"),
|
||||
Napi::Function::New(env, CreateOnlineRecognizerWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "createOnlineStream"),
|
||||
Napi::Function::New(env, CreateOnlineStreamWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "acceptWaveformOnline"),
|
||||
Napi::Function::New(env, AcceptWaveformWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "isOnlineStreamReady"),
|
||||
Napi::Function::New(env, IsOnlineStreamReadyWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "decodeOnlineStream"),
|
||||
Napi::Function::New(env, DecodeOnlineStreamWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "getOnlineStreamResultAsJson"),
|
||||
Napi::Function::New(env, GetOnlineStreamResultAsJsonWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "inputFinished"),
|
||||
Napi::Function::New(env, InputFinishedWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "reset"),
|
||||
Napi::Function::New(env, ResetOnlineStreamWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "isEndpoint"),
|
||||
Napi::Function::New(env, IsEndpointWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "createDisplay"),
|
||||
Napi::Function::New(env, CreateDisplayWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "print"),
|
||||
Napi::Function::New(env, PrintWrapper));
|
||||
}
|
||||
1
scripts/node-addon-api/src/streaming-asr.cc
Symbolic link
1
scripts/node-addon-api/src/streaming-asr.cc
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../harmony-os/SherpaOnnxHar/sherpa_onnx/src/main/cpp/streaming-asr.cc
|
||||
@@ -1,668 +0,0 @@
|
||||
// scripts/node-addon-api/src/vad.cc
|
||||
//
|
||||
// Copyright (c) 2024 Xiaomi Corporation
|
||||
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
|
||||
#include "macros.h" // NOLINT
|
||||
#include "napi.h" // NOLINT
|
||||
#include "sherpa-onnx/c-api/c-api.h"
|
||||
|
||||
static Napi::External<SherpaOnnxCircularBuffer> CreateCircularBufferWrapper(
|
||||
const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() != 1) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 1 argument. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsNumber()) {
|
||||
Napi::TypeError::New(env, "You should pass an integer as the argument.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
SherpaOnnxCircularBuffer *buf =
|
||||
SherpaOnnxCreateCircularBuffer(info[0].As<Napi::Number>().Int32Value());
|
||||
|
||||
return Napi::External<SherpaOnnxCircularBuffer>::New(
|
||||
env, buf, [](Napi::Env env, SherpaOnnxCircularBuffer *p) {
|
||||
SherpaOnnxDestroyCircularBuffer(p);
|
||||
});
|
||||
}
|
||||
|
||||
static void CircularBufferPushWrapper(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
|
||||
if (info.Length() != 2) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 2 arguments. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(env, "Argument 0 should be an CircularBuffer pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
SherpaOnnxCircularBuffer *buf =
|
||||
info[0].As<Napi::External<SherpaOnnxCircularBuffer>>().Data();
|
||||
|
||||
if (!info[1].IsTypedArray()) {
|
||||
Napi::TypeError::New(env, "Argument 1 should be a Float32Array.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Napi::Float32Array data = info[1].As<Napi::Float32Array>();
|
||||
SherpaOnnxCircularBufferPush(buf, data.Data(), data.ElementLength());
|
||||
}
|
||||
|
||||
// see https://github.com/nodejs/node-addon-api/blob/main/doc/typed_array.md
|
||||
// https://github.com/nodejs/node-addon-examples/blob/main/src/2-js-to-native-conversion/typed_array_to_native/node-addon-api/typed_array_to_native.cc
|
||||
static Napi::Float32Array CircularBufferGetWrapper(
|
||||
const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
|
||||
if (info.Length() != 3 && info.Length() != 4) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 3 or 4 arguments. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(env, "Argument 0 should be an CircularBuffer pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
SherpaOnnxCircularBuffer *buf =
|
||||
info[0].As<Napi::External<SherpaOnnxCircularBuffer>>().Data();
|
||||
|
||||
if (!info[1].IsNumber()) {
|
||||
Napi::TypeError::New(env, "Argument 1 should be an integer (startIndex).")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[2].IsNumber()) {
|
||||
Napi::TypeError::New(env, "Argument 2 should be an integer (n).")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
bool enable_external_buffer = true;
|
||||
if (info.Length() == 4) {
|
||||
if (info[3].IsBoolean()) {
|
||||
enable_external_buffer = info[3].As<Napi::Boolean>().Value();
|
||||
} else {
|
||||
Napi::TypeError::New(env, "Argument 3 should be a boolean.")
|
||||
.ThrowAsJavaScriptException();
|
||||
}
|
||||
}
|
||||
|
||||
int32_t start_index = info[1].As<Napi::Number>().Int32Value();
|
||||
int32_t n = info[2].As<Napi::Number>().Int32Value();
|
||||
|
||||
const float *data = SherpaOnnxCircularBufferGet(buf, start_index, n);
|
||||
|
||||
if (enable_external_buffer) {
|
||||
Napi::ArrayBuffer arrayBuffer = Napi::ArrayBuffer::New(
|
||||
env, const_cast<float *>(data), sizeof(float) * n,
|
||||
[](Napi::Env /*env*/, void *p) {
|
||||
SherpaOnnxCircularBufferFree(reinterpret_cast<const float *>(p));
|
||||
});
|
||||
|
||||
Napi::Float32Array float32Array =
|
||||
Napi::Float32Array::New(env, n, arrayBuffer, 0);
|
||||
|
||||
return float32Array;
|
||||
} else {
|
||||
// don't use external buffer
|
||||
Napi::ArrayBuffer arrayBuffer =
|
||||
Napi::ArrayBuffer::New(env, sizeof(float) * n);
|
||||
|
||||
Napi::Float32Array float32Array =
|
||||
Napi::Float32Array::New(env, n, arrayBuffer, 0);
|
||||
|
||||
std::copy(data, data + n, float32Array.Data());
|
||||
|
||||
SherpaOnnxCircularBufferFree(data);
|
||||
|
||||
return float32Array;
|
||||
}
|
||||
}
|
||||
|
||||
static void CircularBufferPopWrapper(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
|
||||
if (info.Length() != 2) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 2 arguments. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(env, "Argument 0 should be an CircularBuffer pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
SherpaOnnxCircularBuffer *buf =
|
||||
info[0].As<Napi::External<SherpaOnnxCircularBuffer>>().Data();
|
||||
|
||||
if (!info[1].IsNumber()) {
|
||||
Napi::TypeError::New(env, "Argument 1 should be an integer (n).")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t n = info[1].As<Napi::Number>().Int32Value();
|
||||
|
||||
SherpaOnnxCircularBufferPop(buf, n);
|
||||
}
|
||||
|
||||
static Napi::Number CircularBufferSizeWrapper(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
|
||||
if (info.Length() != 1) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 1 argument. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(env, "Argument 0 should be an CircularBuffer pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
SherpaOnnxCircularBuffer *buf =
|
||||
info[0].As<Napi::External<SherpaOnnxCircularBuffer>>().Data();
|
||||
|
||||
int32_t size = SherpaOnnxCircularBufferSize(buf);
|
||||
|
||||
return Napi::Number::New(env, size);
|
||||
}
|
||||
|
||||
static Napi::Number CircularBufferHeadWrapper(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
|
||||
if (info.Length() != 1) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 1 argument. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(env, "Argument 0 should be an CircularBuffer pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
SherpaOnnxCircularBuffer *buf =
|
||||
info[0].As<Napi::External<SherpaOnnxCircularBuffer>>().Data();
|
||||
|
||||
int32_t size = SherpaOnnxCircularBufferHead(buf);
|
||||
|
||||
return Napi::Number::New(env, size);
|
||||
}
|
||||
|
||||
static void CircularBufferResetWrapper(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
|
||||
if (info.Length() != 1) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 1 argument. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(env, "Argument 0 should be an CircularBuffer pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
SherpaOnnxCircularBuffer *buf =
|
||||
info[0].As<Napi::External<SherpaOnnxCircularBuffer>>().Data();
|
||||
|
||||
SherpaOnnxCircularBufferReset(buf);
|
||||
}
|
||||
|
||||
static SherpaOnnxSileroVadModelConfig GetSileroVadConfig(
|
||||
const Napi::Object &obj) {
|
||||
SherpaOnnxSileroVadModelConfig c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
|
||||
if (!obj.Has("sileroVad") || !obj.Get("sileroVad").IsObject()) {
|
||||
return c;
|
||||
}
|
||||
|
||||
Napi::Object o = obj.Get("sileroVad").As<Napi::Object>();
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(model, model);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_FLOAT(threshold, threshold);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_FLOAT(min_silence_duration, minSilenceDuration);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_FLOAT(min_speech_duration, minSpeechDuration);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_INT32(window_size, windowSize);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_FLOAT(max_speech_duration, maxSpeechDuration);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static Napi::External<SherpaOnnxVoiceActivityDetector>
|
||||
CreateVoiceActivityDetectorWrapper(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() != 2) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 2 arguments. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsObject()) {
|
||||
Napi::TypeError::New(env,
|
||||
"You should pass an object as the first argument.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[1].IsNumber()) {
|
||||
Napi::TypeError::New(env,
|
||||
"You should pass an integer as the second argument.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
Napi::Object o = info[0].As<Napi::Object>();
|
||||
|
||||
SherpaOnnxVadModelConfig c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
c.silero_vad = GetSileroVadConfig(o);
|
||||
|
||||
SHERPA_ONNX_ASSIGN_ATTR_INT32(sample_rate, sampleRate);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_INT32(num_threads, numThreads);
|
||||
SHERPA_ONNX_ASSIGN_ATTR_STR(provider, provider);
|
||||
|
||||
if (o.Has("debug") &&
|
||||
(o.Get("debug").IsNumber() || o.Get("debug").IsBoolean())) {
|
||||
if (o.Get("debug").IsBoolean()) {
|
||||
c.debug = o.Get("debug").As<Napi::Boolean>().Value();
|
||||
} else {
|
||||
c.debug = o.Get("debug").As<Napi::Number>().Int32Value();
|
||||
}
|
||||
}
|
||||
|
||||
float buffer_size_in_seconds = info[1].As<Napi::Number>().FloatValue();
|
||||
|
||||
SherpaOnnxVoiceActivityDetector *vad =
|
||||
SherpaOnnxCreateVoiceActivityDetector(&c, buffer_size_in_seconds);
|
||||
|
||||
if (c.silero_vad.model) {
|
||||
delete[] c.silero_vad.model;
|
||||
}
|
||||
|
||||
if (c.provider) {
|
||||
delete[] c.provider;
|
||||
}
|
||||
|
||||
return Napi::External<SherpaOnnxVoiceActivityDetector>::New(
|
||||
env, vad, [](Napi::Env env, SherpaOnnxVoiceActivityDetector *p) {
|
||||
SherpaOnnxDestroyVoiceActivityDetector(p);
|
||||
});
|
||||
}
|
||||
|
||||
static void VoiceActivityDetectorAcceptWaveformWrapper(
|
||||
const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
|
||||
if (info.Length() != 2) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 2 arguments. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(env, "Argument 0 should be a VAD pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
SherpaOnnxVoiceActivityDetector *vad =
|
||||
info[0].As<Napi::External<SherpaOnnxVoiceActivityDetector>>().Data();
|
||||
|
||||
if (!info[1].IsTypedArray()) {
|
||||
Napi::TypeError::New(
|
||||
env, "Argument 1 should be a Float32Array containing samples")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Napi::Float32Array samples = info[1].As<Napi::Float32Array>();
|
||||
|
||||
SherpaOnnxVoiceActivityDetectorAcceptWaveform(vad, samples.Data(),
|
||||
samples.ElementLength());
|
||||
}
|
||||
|
||||
static Napi::Boolean VoiceActivityDetectorEmptyWrapper(
|
||||
const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
|
||||
if (info.Length() != 1) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 1 argument. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(env, "Argument 0 should be a VAD pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
SherpaOnnxVoiceActivityDetector *vad =
|
||||
info[0].As<Napi::External<SherpaOnnxVoiceActivityDetector>>().Data();
|
||||
|
||||
int32_t is_empty = SherpaOnnxVoiceActivityDetectorEmpty(vad);
|
||||
|
||||
return Napi::Boolean::New(env, is_empty);
|
||||
}
|
||||
|
||||
static Napi::Boolean VoiceActivityDetectorDetectedWrapper(
|
||||
const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
|
||||
if (info.Length() != 1) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 1 argument. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(env, "Argument 0 should be a VAD pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
SherpaOnnxVoiceActivityDetector *vad =
|
||||
info[0].As<Napi::External<SherpaOnnxVoiceActivityDetector>>().Data();
|
||||
|
||||
int32_t is_detected = SherpaOnnxVoiceActivityDetectorDetected(vad);
|
||||
|
||||
return Napi::Boolean::New(env, is_detected);
|
||||
}
|
||||
|
||||
static void VoiceActivityDetectorPopWrapper(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
|
||||
if (info.Length() != 1) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 1 argument. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(env, "Argument 0 should be a VAD pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
SherpaOnnxVoiceActivityDetector *vad =
|
||||
info[0].As<Napi::External<SherpaOnnxVoiceActivityDetector>>().Data();
|
||||
|
||||
SherpaOnnxVoiceActivityDetectorPop(vad);
|
||||
}
|
||||
|
||||
static void VoiceActivityDetectorClearWrapper(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
|
||||
if (info.Length() != 1) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 1 argument. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(env, "Argument 0 should be a VAD pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
SherpaOnnxVoiceActivityDetector *vad =
|
||||
info[0].As<Napi::External<SherpaOnnxVoiceActivityDetector>>().Data();
|
||||
|
||||
SherpaOnnxVoiceActivityDetectorClear(vad);
|
||||
}
|
||||
|
||||
static Napi::Object VoiceActivityDetectorFrontWrapper(
|
||||
const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
|
||||
if (info.Length() != 1 && info.Length() != 2) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 1 or 2 arguments. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(env, "Argument 0 should be a VAD pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
bool enable_external_buffer = true;
|
||||
if (info.Length() == 2) {
|
||||
if (info[1].IsBoolean()) {
|
||||
enable_external_buffer = info[1].As<Napi::Boolean>().Value();
|
||||
} else {
|
||||
Napi::TypeError::New(env, "Argument 1 should be a boolean.")
|
||||
.ThrowAsJavaScriptException();
|
||||
}
|
||||
}
|
||||
|
||||
SherpaOnnxVoiceActivityDetector *vad =
|
||||
info[0].As<Napi::External<SherpaOnnxVoiceActivityDetector>>().Data();
|
||||
|
||||
const SherpaOnnxSpeechSegment *segment =
|
||||
SherpaOnnxVoiceActivityDetectorFront(vad);
|
||||
|
||||
if (enable_external_buffer) {
|
||||
Napi::ArrayBuffer arrayBuffer = Napi::ArrayBuffer::New(
|
||||
env, const_cast<float *>(segment->samples), sizeof(float) * segment->n,
|
||||
[](Napi::Env /*env*/, void * /*data*/,
|
||||
const SherpaOnnxSpeechSegment *hint) {
|
||||
SherpaOnnxDestroySpeechSegment(hint);
|
||||
},
|
||||
segment);
|
||||
|
||||
Napi::Float32Array float32Array =
|
||||
Napi::Float32Array::New(env, segment->n, arrayBuffer, 0);
|
||||
|
||||
Napi::Object obj = Napi::Object::New(env);
|
||||
obj.Set(Napi::String::New(env, "start"), segment->start);
|
||||
obj.Set(Napi::String::New(env, "samples"), float32Array);
|
||||
|
||||
return obj;
|
||||
} else {
|
||||
Napi::ArrayBuffer arrayBuffer =
|
||||
Napi::ArrayBuffer::New(env, sizeof(float) * segment->n);
|
||||
|
||||
Napi::Float32Array float32Array =
|
||||
Napi::Float32Array::New(env, segment->n, arrayBuffer, 0);
|
||||
|
||||
std::copy(segment->samples, segment->samples + segment->n,
|
||||
float32Array.Data());
|
||||
|
||||
Napi::Object obj = Napi::Object::New(env);
|
||||
obj.Set(Napi::String::New(env, "start"), segment->start);
|
||||
obj.Set(Napi::String::New(env, "samples"), float32Array);
|
||||
|
||||
SherpaOnnxDestroySpeechSegment(segment);
|
||||
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
static void VoiceActivityDetectorResetWrapper(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
|
||||
if (info.Length() != 1) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 1 argument. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(env, "Argument 0 should be a VAD pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
SherpaOnnxVoiceActivityDetector *vad =
|
||||
info[0].As<Napi::External<SherpaOnnxVoiceActivityDetector>>().Data();
|
||||
|
||||
SherpaOnnxVoiceActivityDetectorReset(vad);
|
||||
}
|
||||
|
||||
static void VoiceActivityDetectorFlushWrapper(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
|
||||
if (info.Length() != 1) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 1 argument. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!info[0].IsExternal()) {
|
||||
Napi::TypeError::New(env, "Argument 0 should be a VAD pointer.")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
SherpaOnnxVoiceActivityDetector *vad =
|
||||
info[0].As<Napi::External<SherpaOnnxVoiceActivityDetector>>().Data();
|
||||
|
||||
SherpaOnnxVoiceActivityDetectorFlush(vad);
|
||||
}
|
||||
|
||||
void InitVad(Napi::Env env, Napi::Object exports) {
|
||||
exports.Set(Napi::String::New(env, "createCircularBuffer"),
|
||||
Napi::Function::New(env, CreateCircularBufferWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "circularBufferPush"),
|
||||
Napi::Function::New(env, CircularBufferPushWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "circularBufferGet"),
|
||||
Napi::Function::New(env, CircularBufferGetWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "circularBufferPop"),
|
||||
Napi::Function::New(env, CircularBufferPopWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "circularBufferSize"),
|
||||
Napi::Function::New(env, CircularBufferSizeWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "circularBufferHead"),
|
||||
Napi::Function::New(env, CircularBufferHeadWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "circularBufferReset"),
|
||||
Napi::Function::New(env, CircularBufferResetWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "createVoiceActivityDetector"),
|
||||
Napi::Function::New(env, CreateVoiceActivityDetectorWrapper));
|
||||
|
||||
exports.Set(
|
||||
Napi::String::New(env, "voiceActivityDetectorAcceptWaveform"),
|
||||
Napi::Function::New(env, VoiceActivityDetectorAcceptWaveformWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "voiceActivityDetectorIsEmpty"),
|
||||
Napi::Function::New(env, VoiceActivityDetectorEmptyWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "voiceActivityDetectorIsDetected"),
|
||||
Napi::Function::New(env, VoiceActivityDetectorDetectedWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "voiceActivityDetectorPop"),
|
||||
Napi::Function::New(env, VoiceActivityDetectorPopWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "voiceActivityDetectorClear"),
|
||||
Napi::Function::New(env, VoiceActivityDetectorClearWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "voiceActivityDetectorFront"),
|
||||
Napi::Function::New(env, VoiceActivityDetectorFrontWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "voiceActivityDetectorReset"),
|
||||
Napi::Function::New(env, VoiceActivityDetectorResetWrapper));
|
||||
|
||||
exports.Set(Napi::String::New(env, "voiceActivityDetectorFlush"),
|
||||
Napi::Function::New(env, VoiceActivityDetectorFlushWrapper));
|
||||
}
|
||||
1
scripts/node-addon-api/src/vad.cc
Symbolic link
1
scripts/node-addon-api/src/vad.cc
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../harmony-os/SherpaOnnxHar/sherpa_onnx/src/main/cpp/vad.cc
|
||||
@@ -1,91 +0,0 @@
|
||||
// scripts/node-addon-api/src/wave-reader.cc
|
||||
//
|
||||
// Copyright (c) 2024 Xiaomi Corporation
|
||||
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
|
||||
#include "napi.h" // NOLINT
|
||||
#include "sherpa-onnx/c-api/c-api.h"
|
||||
|
||||
static Napi::Object ReadWaveWrapper(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
if (info.Length() > 2) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 2 arguments. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsString()) {
|
||||
Napi::TypeError::New(env, "Argument 0 should be a string")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string filename = info[0].As<Napi::String>().Utf8Value();
|
||||
|
||||
bool enable_external_buffer = true;
|
||||
if (info.Length() == 2) {
|
||||
if (info[1].IsBoolean()) {
|
||||
enable_external_buffer = info[1].As<Napi::Boolean>().Value();
|
||||
} else {
|
||||
Napi::TypeError::New(env, "Argument 1 should be a boolean")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
const SherpaOnnxWave *wave = SherpaOnnxReadWave(filename.c_str());
|
||||
if (!wave) {
|
||||
std::ostringstream os;
|
||||
os << "Failed to read '" << filename << "'";
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (enable_external_buffer) {
|
||||
Napi::ArrayBuffer arrayBuffer = Napi::ArrayBuffer::New(
|
||||
env, const_cast<float *>(wave->samples),
|
||||
sizeof(float) * wave->num_samples,
|
||||
[](Napi::Env /*env*/, void * /*data*/, const SherpaOnnxWave *hint) {
|
||||
SherpaOnnxFreeWave(hint);
|
||||
},
|
||||
wave);
|
||||
Napi::Float32Array float32Array =
|
||||
Napi::Float32Array::New(env, wave->num_samples, arrayBuffer, 0);
|
||||
|
||||
Napi::Object obj = Napi::Object::New(env);
|
||||
obj.Set(Napi::String::New(env, "samples"), float32Array);
|
||||
obj.Set(Napi::String::New(env, "sampleRate"), wave->sample_rate);
|
||||
return obj;
|
||||
} else {
|
||||
// don't use external buffer
|
||||
Napi::ArrayBuffer arrayBuffer =
|
||||
Napi::ArrayBuffer::New(env, sizeof(float) * wave->num_samples);
|
||||
|
||||
Napi::Float32Array float32Array =
|
||||
Napi::Float32Array::New(env, wave->num_samples, arrayBuffer, 0);
|
||||
|
||||
std::copy(wave->samples, wave->samples + wave->num_samples,
|
||||
float32Array.Data());
|
||||
|
||||
Napi::Object obj = Napi::Object::New(env);
|
||||
obj.Set(Napi::String::New(env, "samples"), float32Array);
|
||||
obj.Set(Napi::String::New(env, "sampleRate"), wave->sample_rate);
|
||||
|
||||
SherpaOnnxFreeWave(wave);
|
||||
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
void InitWaveReader(Napi::Env env, Napi::Object exports) {
|
||||
exports.Set(Napi::String::New(env, "readWave"),
|
||||
Napi::Function::New(env, ReadWaveWrapper));
|
||||
}
|
||||
1
scripts/node-addon-api/src/wave-reader.cc
Symbolic link
1
scripts/node-addon-api/src/wave-reader.cc
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../harmony-os/SherpaOnnxHar/sherpa_onnx/src/main/cpp/wave-reader.cc
|
||||
@@ -1,81 +0,0 @@
|
||||
// scripts/node-addon-api/src/wave-writer.cc
|
||||
//
|
||||
// Copyright (c) 2024 Xiaomi Corporation
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "napi.h" // NOLINT
|
||||
#include "sherpa-onnx/c-api/c-api.h"
|
||||
|
||||
// (filename, {samples: samples, sampleRate: sampleRate}
|
||||
static Napi::Boolean WriteWaveWrapper(const Napi::CallbackInfo &info) {
|
||||
Napi::Env env = info.Env();
|
||||
|
||||
if (info.Length() != 2) {
|
||||
std::ostringstream os;
|
||||
os << "Expect only 2 arguments. Given: " << info.Length();
|
||||
|
||||
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[0].IsString()) {
|
||||
Napi::TypeError::New(env, "Argument 0 should be a string")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!info[1].IsObject()) {
|
||||
Napi::TypeError::New(env, "Argument 1 should be an object")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
Napi::Object obj = info[1].As<Napi::Object>();
|
||||
|
||||
if (!obj.Has("samples")) {
|
||||
Napi::TypeError::New(env, "The argument object should have a field samples")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!obj.Get("samples").IsTypedArray()) {
|
||||
Napi::TypeError::New(env, "The object['samples'] should be a typed array")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!obj.Has("sampleRate")) {
|
||||
Napi::TypeError::New(env,
|
||||
"The argument object should have a field sampleRate")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!obj.Get("sampleRate").IsNumber()) {
|
||||
Napi::TypeError::New(env, "The object['samples'] should be a number")
|
||||
.ThrowAsJavaScriptException();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
Napi::Float32Array samples = obj.Get("samples").As<Napi::Float32Array>();
|
||||
int32_t sample_rate = obj.Get("sampleRate").As<Napi::Number>().Int32Value();
|
||||
|
||||
int32_t ok =
|
||||
SherpaOnnxWriteWave(samples.Data(), samples.ElementLength(), sample_rate,
|
||||
info[0].As<Napi::String>().Utf8Value().c_str());
|
||||
|
||||
return Napi::Boolean::New(env, ok);
|
||||
}
|
||||
|
||||
void InitWaveWriter(Napi::Env env, Napi::Object exports) {
|
||||
exports.Set(Napi::String::New(env, "writeWave"),
|
||||
Napi::Function::New(env, WriteWaveWrapper));
|
||||
}
|
||||
1
scripts/node-addon-api/src/wave-writer.cc
Symbolic link
1
scripts/node-addon-api/src/wave-writer.cc
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../harmony-os/SherpaOnnxHar/sherpa_onnx/src/main/cpp/wave-writer.cc
|
||||
Reference in New Issue
Block a user