Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add HarmonyOS support for text-to-speech. #1584

Merged
merged 7 commits into from
Dec 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/lazarus.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ jobs:
key: ${{ matrix.os }}

# See https://github.com/gcarreno/setup-lazarus
- uses: gcarreno/setup-lazarus@v3
- uses: gcarreno/setup-lazarus@v3.3.1
with:
lazarus-version: "stable"
with-cache: true
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test-nodejs-npm.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-2019]
python-version: ["3.8"]
python-version: ["3.10"]

steps:
- uses: actions/checkout@v4
Expand Down
4 changes: 2 additions & 2 deletions harmony-os/SherpaOnnxHar/sherpa_onnx/BuildProfile.ets
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
* Use these variables when you tailor your ArkTS code. They must be of the const type.
*/
export const HAR_VERSION = '1.10.32';
export const BUILD_MODE_NAME = 'release';
export const DEBUG = false;
export const BUILD_MODE_NAME = 'debug';
export const DEBUG = true;
export const TARGET_NAME = 'default';

/**
Expand Down
9 changes: 9 additions & 0 deletions harmony-os/SherpaOnnxHar/sherpa_onnx/Index.ets
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,12 @@ export {
OnlineRecognizerResult,
OnlineRecognizer,
} from './src/main/ets/components/StreamingAsr';

export {
OfflineTtsVitsModelConfig,
OfflineTtsModelConfig,
OfflineTtsConfig,
OfflineTts,
TtsOutput,
TtsInput,
} from './src/main/ets/components/NonStreamingTts';
2 changes: 1 addition & 1 deletion harmony-os/SherpaOnnxHar/sherpa_onnx/src/main/cpp/macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
#include <string>

#if __OHOS__
#include "rawfile/raw_file_manager.h"
#include "hilog/log.h"
#include "rawfile/raw_file_manager.h"

#undef LOG_DOMAIN
#undef LOG_TAG
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,10 @@ CreateOfflineRecognizerWrapper(const Napi::CallbackInfo &info) {
SHERPA_ONNX_ASSIGN_ATTR_FLOAT(blank_penalty, blankPenalty);

#if __OHOS__
std::unique_ptr<NativeResourceManager, decltype(&OH_ResourceManager_ReleaseNativeResourceManager)> mgr (OH_ResourceManager_InitNativeResourceManager(env, info[1]), &OH_ResourceManager_ReleaseNativeResourceManager);
std::unique_ptr<NativeResourceManager,
decltype(&OH_ResourceManager_ReleaseNativeResourceManager)>
mgr(OH_ResourceManager_InitNativeResourceManager(env, info[1]),
&OH_ResourceManager_ReleaseNativeResourceManager);

const SherpaOnnxOfflineRecognizer *recognizer =
SherpaOnnxCreateOfflineRecognizerOHOS(&c, mgr.get());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,17 @@ static SherpaOnnxOfflineTtsModelConfig GetOfflineTtsModelConfig(
static Napi::External<SherpaOnnxOfflineTts> CreateOfflineTtsWrapper(
const Napi::CallbackInfo &info) {
Napi::Env env = info.Env();
#if __OHOS__
// the last argument is the NativeResourceManager
if (info.Length() != 2) {
std::ostringstream os;
os << "Expect only 2 arguments. Given: " << info.Length();

Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();

return {};
}
#else
if (info.Length() != 1) {
std::ostringstream os;
os << "Expect only 1 argument. Given: " << info.Length();
Expand All @@ -71,6 +82,7 @@ static Napi::External<SherpaOnnxOfflineTts> CreateOfflineTtsWrapper(

return {};
}
#endif

if (!info[0].IsObject()) {
Napi::TypeError::New(env, "Expect an object as the argument")
Expand All @@ -90,7 +102,15 @@ static Napi::External<SherpaOnnxOfflineTts> CreateOfflineTtsWrapper(
SHERPA_ONNX_ASSIGN_ATTR_INT32(max_num_sentences, maxNumSentences);
SHERPA_ONNX_ASSIGN_ATTR_STR(rule_fars, ruleFars);

#if __OHOS__
std::unique_ptr<NativeResourceManager,
decltype(&OH_ResourceManager_ReleaseNativeResourceManager)>
mgr(OH_ResourceManager_InitNativeResourceManager(env, info[1]),
&OH_ResourceManager_ReleaseNativeResourceManager);
SherpaOnnxOfflineTts *tts = SherpaOnnxCreateOfflineTtsOHOS(&c, mgr.get());
#else
SherpaOnnxOfflineTts *tts = SherpaOnnxCreateOfflineTts(&c);
#endif

if (c.model.vits.model) {
delete[] c.model.vits.model;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,10 @@ static Napi::External<SherpaOnnxOnlineRecognizer> CreateOnlineRecognizerWrapper(
c.ctc_fst_decoder_config = GetCtcFstDecoderConfig(o);

#if __OHOS__
std::unique_ptr<NativeResourceManager, decltype(&OH_ResourceManager_ReleaseNativeResourceManager)> mgr (OH_ResourceManager_InitNativeResourceManager(env, info[1]), &OH_ResourceManager_ReleaseNativeResourceManager);
std::unique_ptr<NativeResourceManager,
decltype(&OH_ResourceManager_ReleaseNativeResourceManager)>
mgr(OH_ResourceManager_InitNativeResourceManager(env, info[1]),
&OH_ResourceManager_ReleaseNativeResourceManager);

const SherpaOnnxOnlineRecognizer *recognizer =
SherpaOnnxCreateOnlineRecognizerOHOS(&c, mgr.get());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,8 @@ export const decodeOnlineStream: (handle: object, streamHandle: object) => void;
export const isEndpoint: (handle: object, streamHandle: object) => boolean;
export const reset: (handle: object, streamHandle: object) => void;
export const getOnlineStreamResultAsJson: (handle: object, streamHandle: object) => string;

export const createOfflineTts: (config: object, mgr?: object) => object;
export const getOfflineTtsNumSpeakers: (handle: object) => number;
export const getOfflineTtsSampleRate: (handle: object) => number;
export const offlineTtsGenerate: (handle: object, input: object) => object;
21 changes: 14 additions & 7 deletions harmony-os/SherpaOnnxHar/sherpa_onnx/src/main/cpp/vad.cc
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,10 @@ static void CircularBufferPushWrapper(const Napi::CallbackInfo &info) {

#if __OHOS__
// Note(fangjun): Normally, we don't need to divied it by sizeof(float).
// However, data.ElementLength() here returns number of bytes, not number of elements.
SherpaOnnxCircularBufferPush(buf, data.Data(), data.ElementLength() / sizeof(float));
// However, data.ElementLength() here returns number of bytes, not number of
// elements.
SherpaOnnxCircularBufferPush(buf, data.Data(),
data.ElementLength() / sizeof(float));
#else
SherpaOnnxCircularBufferPush(buf, data.Data(), data.ElementLength());
#endif
Expand Down Expand Up @@ -353,10 +355,14 @@ CreateVoiceActivityDetectorWrapper(const Napi::CallbackInfo &info) {
float buffer_size_in_seconds = info[1].As<Napi::Number>().FloatValue();

#if __OHOS__
std::unique_ptr<NativeResourceManager, decltype(&OH_ResourceManager_ReleaseNativeResourceManager)> mgr(OH_ResourceManager_InitNativeResourceManager(env, info[2]), &OH_ResourceManager_ReleaseNativeResourceManager);
std::unique_ptr<NativeResourceManager,
decltype(&OH_ResourceManager_ReleaseNativeResourceManager)>
mgr(OH_ResourceManager_InitNativeResourceManager(env, info[2]),
&OH_ResourceManager_ReleaseNativeResourceManager);

SherpaOnnxVoiceActivityDetector *vad =
SherpaOnnxCreateVoiceActivityDetectorOHOS(&c, buffer_size_in_seconds, mgr.get());
SherpaOnnxCreateVoiceActivityDetectorOHOS(&c, buffer_size_in_seconds,
mgr.get());
#else
SherpaOnnxVoiceActivityDetector *vad =
SherpaOnnxCreateVoiceActivityDetector(&c, buffer_size_in_seconds);
Expand Down Expand Up @@ -410,9 +416,10 @@ static void VoiceActivityDetectorAcceptWaveformWrapper(
Napi::Float32Array samples = info[1].As<Napi::Float32Array>();

#if __OHOS__
// Note(fangjun): For unknown reasons, we need to use `/sizeof(float)` here for Huawei
SherpaOnnxVoiceActivityDetectorAcceptWaveform(vad, samples.Data(),
samples.ElementLength() / sizeof(float));
// Note(fangjun): For unknown reasons, we need to use `/sizeof(float)` here
// for Huawei
SherpaOnnxVoiceActivityDetectorAcceptWaveform(
vad, samples.Data(), samples.ElementLength() / sizeof(float));
#else
SherpaOnnxVoiceActivityDetectorAcceptWaveform(vad, samples.Data(),
samples.ElementLength());
Expand Down
13 changes: 7 additions & 6 deletions harmony-os/SherpaOnnxHar/sherpa_onnx/src/main/cpp/wave-reader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -102,18 +102,19 @@ static Napi::Object ReadWaveFromBinaryWrapper(const Napi::CallbackInfo &info) {

return {};
}

Napi::Uint8Array data = info[0].As<Napi::Uint8Array>();
int32_t n = data.ElementLength();
const SherpaOnnxWave *wave = SherpaOnnxReadWaveFromBinaryData(reinterpret_cast<const char*>(data.Data()), n);
const SherpaOnnxWave *wave = SherpaOnnxReadWaveFromBinaryData(
reinterpret_cast<const char *>(data.Data()), n);
if (!wave) {
std::ostringstream os;
os << "Failed to read wave";
Napi::TypeError::New(env, os.str()).ThrowAsJavaScriptException();

return {};
}

bool enable_external_buffer = true;
if (info.Length() == 2) {
if (info[1].IsBoolean()) {
Expand Down Expand Up @@ -165,7 +166,7 @@ static Napi::Object ReadWaveFromBinaryWrapper(const Napi::CallbackInfo &info) {
void InitWaveReader(Napi::Env env, Napi::Object exports) {
exports.Set(Napi::String::New(env, "readWave"),
Napi::Function::New(env, ReadWaveWrapper));

exports.Set(Napi::String::New(env, "readWaveFromBinary"),
Napi::Function::New(env, ReadWaveFromBinaryWrapper));
}
Napi::Function::New(env, ReadWaveFromBinaryWrapper));
}
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export class OfflineModelConfig {
public tokens: string = '';
public numThreads: number = 1;
public debug: boolean = false;
public provider: string = "cpu";
public provider: string = 'cpu';
public modelType: string = '';
public modelingUnit: string = "cjkchar";
public bpeVocab: string = '';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import {
createOfflineTts,
getOfflineTtsNumSpeakers,
getOfflineTtsSampleRate,
offlineTtsGenerate,
} from "libsherpa_onnx.so";

export class OfflineTtsVitsModelConfig {
public model: string = '';
public lexicon: string = '';
public tokens: string = '';
public dataDir: string = '';
public dictDir: String = '';
public noiseScale: number = 0.667;
public noiseScaleW: number = 0.8;
public lengthScale: number = 1.0;
}

export class OfflineTtsModelConfig{
public vits: OfflineTtsVitsModelConfig = new OfflineTtsVitsModelConfig();
public numThreads: number = 1;
public debug: boolean = false;
public provider: string = 'cpu';
}

export class OfflineTtsConfig{
public model: OfflineTtsModelConfig = new OfflineTtsModelConfig();
public ruleFsts: string = '';
public ruleFars: string = '';
public maxNumSentences: number = 1;
}

export class TtsOutput {
public samples: Float32Array = new Float32Array(0);
public sampleRate: number = 0;
}

export class TtsInput {
public text: string = '';
public sid: number = 0;
public speed: number = 1.0;
}

export class OfflineTts {
private handle: object;
public config: OfflineTtsConfig;
public numSpeakers: number;
public sampleRate: number;
constructor(config: OfflineTtsConfig, mgr?: object) {
this.handle = createOfflineTts(config, mgr);
this.config = config;

this.numSpeakers = getOfflineTtsNumSpeakers(this.handle);
this.sampleRate = getOfflineTtsSampleRate(this.handle);
}

/*
input obj: {text: "xxxx", sid: 0, speed: 1.0}
where text is a string, sid is a int32, speed is a float

return an object {samples: Float32Array, sampleRate: <a number>}
*/
generate(input: TtsInput): TtsOutput {
return offlineTtsGenerate(this.handle, input) as TtsOutput;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export class OnlineModelConfig {
public zipformer2_ctc: OnlineZipformer2CtcModelConfig = new OnlineZipformer2CtcModelConfig();
public tokens: string = '';
public numThreads: number = 1;
public provider: string = "cpu";
public provider: string = 'cpu';
public debug: boolean = false;
public modelType: string = '';
public modelingUnit: string = "cjkchar";
Expand All @@ -67,7 +67,7 @@ export class OnlineCtcFstDecoderConfig {
export class OnlineRecognizerConfig {
public featConfig: FeatureConfig = new FeatureConfig();
public modelConfig: OnlineModelConfig = new OnlineModelConfig();
public decodingMethod: string = "greedy_search";
public decodingMethod: string = 'greedy_search';
public maxActivePaths: number = 4;
public enableEndpoint: boolean = false;
public rule1MinTrailingSilence: number = 2.4;
Expand Down
6 changes: 3 additions & 3 deletions harmony-os/SherpaOnnxVadAsr/entry/src/main/module.json5
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@
"reason": "$string:mic_reason",
"usedScene": {
"abilities": [
"FormAbility",
"EntryAbility",
],
"when": "always",
"when": "inuse",
}
}
]
}
}
}
3 changes: 2 additions & 1 deletion scripts/check_style_cpplint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -103,14 +103,15 @@ function do_check() {
2)
echo "Check all files"
files=$(find $sherpa_onnx_dir/cxx-api-examples $sherpa_onnx_dir/c-api-examples $sherpa_onnx_dir/sherpa-onnx/csrc $sherpa_onnx_dir/sherpa-onnx/python $sherpa_onnx_dir/scripts/node-addon-api/src $sherpa_onnx_dir/sherpa-onnx/jni $sherpa_onnx_dir/sherpa-onnx/c-api -name "*.h" -o -name "*.cc")
files2=$(find $sherpa_onnx_dir/harmony-os/SherpaOnnxHar/sherpa_onnx/src/main/cpp/ -name "*.cc")
;;
*)
echo "Check last commit"
files=$(check_last_commit)
;;
esac

for f in $files; do
for f in $files $files2; do
need_check=$(is_source_code_file $f)
if $need_check; then
[[ -f $f ]] && check_style $f
Expand Down
Loading
Loading