Publish sherpa_onnx.har for HarmonyOS (#1572)

This commit is contained in:
Fangjun Kuang
2024-11-28 17:30:16 +08:00
committed by GitHub
parent 109fb799ca
commit 315d8e2a47
104 changed files with 6257 additions and 4378 deletions

View File

@@ -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));
}

View File

@@ -0,0 +1 @@
../../../harmony-os/SherpaOnnxHar/sherpa_onnx/src/main/cpp/audio-tagging.cc

View File

@@ -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));
}

View File

@@ -0,0 +1 @@
../../../harmony-os/SherpaOnnxHar/sherpa_onnx/src/main/cpp/keyword-spotting.cc

View File

@@ -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_

View File

@@ -0,0 +1 @@
../../../harmony-os/SherpaOnnxHar/sherpa_onnx/src/main/cpp/macros.h

View File

@@ -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));
}

View File

@@ -0,0 +1 @@
../../../harmony-os/SherpaOnnxHar/sherpa_onnx/src/main/cpp/non-streaming-asr.cc

View File

@@ -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));
}

View File

@@ -0,0 +1 @@
../../../harmony-os/SherpaOnnxHar/sherpa_onnx/src/main/cpp/non-streaming-speaker-diarization.cc

View File

@@ -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));
}

View File

@@ -0,0 +1 @@
../../../harmony-os/SherpaOnnxHar/sherpa_onnx/src/main/cpp/non-streaming-tts.cc

View File

@@ -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));
}

View File

@@ -0,0 +1 @@
../../../harmony-os/SherpaOnnxHar/sherpa_onnx/src/main/cpp/punctuation.cc

View File

@@ -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)

View File

@@ -0,0 +1 @@
../../../harmony-os/SherpaOnnxHar/sherpa_onnx/src/main/cpp/sherpa-onnx-node-addon-api.cc

View File

@@ -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));
}

View File

@@ -0,0 +1 @@
../../../harmony-os/SherpaOnnxHar/sherpa_onnx/src/main/cpp/speaker-identification.cc

View File

@@ -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));
}

View File

@@ -0,0 +1 @@
../../../harmony-os/SherpaOnnxHar/sherpa_onnx/src/main/cpp/spoken-language-identification.cc

View File

@@ -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));
}

View File

@@ -0,0 +1 @@
../../../harmony-os/SherpaOnnxHar/sherpa_onnx/src/main/cpp/streaming-asr.cc

View File

@@ -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));
}

View File

@@ -0,0 +1 @@
../../../harmony-os/SherpaOnnxHar/sherpa_onnx/src/main/cpp/vad.cc

View File

@@ -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));
}

View File

@@ -0,0 +1 @@
../../../harmony-os/SherpaOnnxHar/sherpa_onnx/src/main/cpp/wave-reader.cc

View File

@@ -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));
}

View File

@@ -0,0 +1 @@
../../../harmony-os/SherpaOnnxHar/sherpa_onnx/src/main/cpp/wave-writer.cc