react-native-sherpa-onnx 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (175) hide show
  1. package/README.md +232 -236
  2. package/SherpaOnnx.podspec +68 -64
  3. package/android/build.gradle +182 -192
  4. package/android/codegen.gradle +57 -0
  5. package/android/prebuilt-download.gradle +428 -0
  6. package/android/prebuilt-versions.gradle +43 -0
  7. package/android/proguard-rules.pro +10 -0
  8. package/android/src/main/assets/testModels/add_mul_add.onnx +28 -0
  9. package/android/src/main/assets/testModels/nnapi_internal_uint8_support.onnx +0 -0
  10. package/android/src/main/assets/testModels/qnn_multi_ctx_embed.onnx +0 -0
  11. package/android/src/main/cpp/CMakeLists.txt +166 -129
  12. package/android/src/main/cpp/CMakePresets.json +54 -0
  13. package/android/src/main/cpp/crypto/sha256.cpp +174 -0
  14. package/android/src/main/cpp/crypto/sha256.h +16 -0
  15. package/android/src/main/cpp/jni/archive/sherpa-onnx-archive-helper.cpp +404 -0
  16. package/android/src/main/cpp/jni/archive/sherpa-onnx-archive-helper.h +56 -0
  17. package/android/src/main/cpp/jni/archive/sherpa-onnx-archive-jni.cpp +181 -0
  18. package/android/src/main/cpp/jni/audio/sherpa-onnx-audio-convert-jni.cpp +888 -0
  19. package/{ios → android/src/main/cpp/jni/model_detect}/sherpa-onnx-common.h +18 -18
  20. package/android/src/main/cpp/jni/model_detect/sherpa-onnx-detect-jni-common.cpp +86 -0
  21. package/android/src/main/cpp/jni/model_detect/sherpa-onnx-detect-jni-common.h +20 -0
  22. package/android/src/main/cpp/jni/model_detect/sherpa-onnx-model-detect-helper.cpp +423 -0
  23. package/android/src/main/cpp/jni/model_detect/sherpa-onnx-model-detect-helper.h +55 -0
  24. package/android/src/main/cpp/jni/model_detect/sherpa-onnx-model-detect-stt.cpp +399 -0
  25. package/android/src/main/cpp/jni/model_detect/sherpa-onnx-model-detect-tts.cpp +238 -0
  26. package/{ios → android/src/main/cpp/jni/model_detect}/sherpa-onnx-model-detect.h +122 -89
  27. package/android/src/main/cpp/jni/model_detect/sherpa-onnx-stt-wrapper.cpp +99 -0
  28. package/android/src/main/cpp/jni/model_detect/sherpa-onnx-stt-wrapper.h +16 -0
  29. package/android/src/main/cpp/jni/model_detect/sherpa-onnx-tts-wrapper.cpp +78 -0
  30. package/android/src/main/cpp/jni/model_detect/sherpa-onnx-tts-wrapper.h +16 -0
  31. package/android/src/main/cpp/jni/module/sherpa-onnx-module-jni.cpp +190 -0
  32. package/android/src/main/cpp/jni/tts/sherpa-onnx-tts-zipvoice-jni.cpp +301 -0
  33. package/android/src/main/java/com/sherpaonnx/SherpaOnnxArchiveHelper.kt +94 -0
  34. package/android/src/main/java/com/sherpaonnx/{SherpaOnnxCoreHelper.kt → SherpaOnnxAssetHelper.kt} +350 -236
  35. package/android/src/main/java/com/sherpaonnx/SherpaOnnxModule.kt +791 -483
  36. package/android/src/main/java/com/sherpaonnx/SherpaOnnxSttHelper.kt +699 -109
  37. package/android/src/main/java/com/sherpaonnx/SherpaOnnxTtsHelper.kt +1123 -668
  38. package/android/src/main/java/com/sherpaonnx/ZipvoiceTtsWrapper.kt +187 -0
  39. package/ios/SherpaOnnx+Assets.h +11 -0
  40. package/ios/SherpaOnnx+Assets.mm +325 -0
  41. package/ios/SherpaOnnx+STT.mm +455 -118
  42. package/ios/SherpaOnnx+TTS.mm +1101 -712
  43. package/ios/SherpaOnnx.h +17 -6
  44. package/ios/SherpaOnnx.mm +206 -311
  45. package/ios/SherpaOnnx.xcconfig +19 -19
  46. package/ios/SherpaOnnxCoreMLHelper.swift +24 -0
  47. package/ios/archive/sherpa-onnx-archive-helper.h +21 -0
  48. package/ios/archive/sherpa-onnx-archive-helper.mm +296 -0
  49. package/ios/libarchive_darwin_config.h +153 -0
  50. package/{android/src/main/cpp/jni → ios/model_detect}/sherpa-onnx-common.h +18 -18
  51. package/ios/model_detect/sherpa-onnx-model-detect-helper.h +49 -0
  52. package/ios/model_detect/sherpa-onnx-model-detect-helper.mm +210 -0
  53. package/ios/model_detect/sherpa-onnx-model-detect-stt.mm +344 -0
  54. package/ios/model_detect/sherpa-onnx-model-detect-tts.mm +201 -0
  55. package/{android/src/main/cpp/jni → ios/model_detect}/sherpa-onnx-model-detect.h +117 -89
  56. package/ios/scripts/patch-libarchive-includes.sh +61 -0
  57. package/ios/scripts/setup-ios-libarchive.sh +98 -0
  58. package/ios/stt/sherpa-onnx-stt-wrapper.h +129 -0
  59. package/ios/stt/sherpa-onnx-stt-wrapper.mm +523 -0
  60. package/ios/{sherpa-onnx-tts-wrapper.h → tts/sherpa-onnx-tts-wrapper.h} +90 -85
  61. package/ios/{sherpa-onnx-tts-wrapper.mm → tts/sherpa-onnx-tts-wrapper.mm} +376 -345
  62. package/lib/module/NativeSherpaOnnx.js +3 -0
  63. package/lib/module/NativeSherpaOnnx.js.map +1 -1
  64. package/lib/module/audio/index.js +22 -0
  65. package/lib/module/audio/index.js.map +1 -0
  66. package/lib/module/diarization/index.js +1 -1
  67. package/lib/module/diarization/index.js.map +1 -1
  68. package/lib/module/download/ModelDownloadManager.js +918 -0
  69. package/lib/module/download/ModelDownloadManager.js.map +1 -0
  70. package/lib/module/download/extractTarBz2.js +53 -0
  71. package/lib/module/download/extractTarBz2.js.map +1 -0
  72. package/lib/module/download/index.js +6 -0
  73. package/lib/module/download/index.js.map +1 -0
  74. package/lib/module/download/validation.js +178 -0
  75. package/lib/module/download/validation.js.map +1 -0
  76. package/lib/module/enhancement/index.js +1 -1
  77. package/lib/module/enhancement/index.js.map +1 -1
  78. package/lib/module/index.js +41 -3
  79. package/lib/module/index.js.map +1 -1
  80. package/lib/module/separation/index.js +1 -1
  81. package/lib/module/separation/index.js.map +1 -1
  82. package/lib/module/stt/index.js +127 -60
  83. package/lib/module/stt/index.js.map +1 -1
  84. package/lib/module/stt/sttModelLanguages.js +512 -0
  85. package/lib/module/stt/sttModelLanguages.js.map +1 -0
  86. package/lib/module/stt/types.js +53 -1
  87. package/lib/module/stt/types.js.map +1 -1
  88. package/lib/module/tts/index.js +216 -289
  89. package/lib/module/tts/index.js.map +1 -1
  90. package/lib/module/tts/types.js +86 -1
  91. package/lib/module/tts/types.js.map +1 -1
  92. package/lib/module/types.js.map +1 -1
  93. package/lib/module/utils.js +86 -73
  94. package/lib/module/utils.js.map +1 -1
  95. package/lib/module/vad/index.js +1 -1
  96. package/lib/module/vad/index.js.map +1 -1
  97. package/lib/typescript/src/NativeSherpaOnnx.d.ts +192 -38
  98. package/lib/typescript/src/NativeSherpaOnnx.d.ts.map +1 -1
  99. package/lib/typescript/src/audio/index.d.ts +13 -0
  100. package/lib/typescript/src/audio/index.d.ts.map +1 -0
  101. package/lib/typescript/src/diarization/index.d.ts +3 -2
  102. package/lib/typescript/src/diarization/index.d.ts.map +1 -1
  103. package/lib/typescript/src/download/ModelDownloadManager.d.ts +108 -0
  104. package/lib/typescript/src/download/ModelDownloadManager.d.ts.map +1 -0
  105. package/lib/typescript/src/download/extractTarBz2.d.ts +14 -0
  106. package/lib/typescript/src/download/extractTarBz2.d.ts.map +1 -0
  107. package/lib/typescript/src/download/index.d.ts +7 -0
  108. package/lib/typescript/src/download/index.d.ts.map +1 -0
  109. package/lib/typescript/src/download/validation.d.ts +57 -0
  110. package/lib/typescript/src/download/validation.d.ts.map +1 -0
  111. package/lib/typescript/src/enhancement/index.d.ts +3 -2
  112. package/lib/typescript/src/enhancement/index.d.ts.map +1 -1
  113. package/lib/typescript/src/index.d.ts +26 -2
  114. package/lib/typescript/src/index.d.ts.map +1 -1
  115. package/lib/typescript/src/separation/index.d.ts +3 -2
  116. package/lib/typescript/src/separation/index.d.ts.map +1 -1
  117. package/lib/typescript/src/stt/index.d.ts +31 -43
  118. package/lib/typescript/src/stt/index.d.ts.map +1 -1
  119. package/lib/typescript/src/stt/sttModelLanguages.d.ts +52 -0
  120. package/lib/typescript/src/stt/sttModelLanguages.d.ts.map +1 -0
  121. package/lib/typescript/src/stt/types.d.ts +196 -9
  122. package/lib/typescript/src/stt/types.d.ts.map +1 -1
  123. package/lib/typescript/src/tts/index.d.ts +25 -211
  124. package/lib/typescript/src/tts/index.d.ts.map +1 -1
  125. package/lib/typescript/src/tts/types.d.ts +148 -25
  126. package/lib/typescript/src/tts/types.d.ts.map +1 -1
  127. package/lib/typescript/src/types.d.ts +0 -32
  128. package/lib/typescript/src/types.d.ts.map +1 -1
  129. package/lib/typescript/src/utils.d.ts +28 -13
  130. package/lib/typescript/src/utils.d.ts.map +1 -1
  131. package/lib/typescript/src/vad/index.d.ts +3 -2
  132. package/lib/typescript/src/vad/index.d.ts.map +1 -1
  133. package/package.json +250 -222
  134. package/scripts/check-qnn-support.sh +78 -0
  135. package/scripts/setup-ios-framework.sh +379 -282
  136. package/src/NativeSherpaOnnx.ts +474 -251
  137. package/src/audio/index.ts +32 -0
  138. package/src/diarization/index.ts +4 -2
  139. package/src/download/ModelDownloadManager.ts +1325 -0
  140. package/src/download/extractTarBz2.ts +78 -0
  141. package/src/download/index.ts +43 -0
  142. package/src/download/validation.ts +279 -0
  143. package/src/enhancement/index.ts +4 -2
  144. package/src/index.tsx +78 -27
  145. package/src/separation/index.ts +4 -2
  146. package/src/stt/index.ts +249 -89
  147. package/src/stt/sttModelLanguages.ts +237 -0
  148. package/src/stt/types.ts +263 -9
  149. package/src/tts/index.ts +470 -458
  150. package/src/tts/types.ts +373 -218
  151. package/src/types.ts +0 -44
  152. package/src/utils.ts +145 -131
  153. package/src/vad/index.ts +4 -2
  154. package/third_party/ffmpeg_prebuilt/ANDROID_RELEASE_TAG +1 -0
  155. package/third_party/libarchive_prebuilt/ANDROID_RELEASE_TAG +1 -0
  156. package/third_party/libarchive_prebuilt/IOS_RELEASE_TAG +1 -0
  157. package/third_party/sherpa-onnx-prebuilt/ANDROID_RELEASE_TAG +1 -0
  158. package/third_party/sherpa-onnx-prebuilt/IOS_RELEASE_TAG +1 -0
  159. package/android/src/main/cpp/include/sherpa-onnx/c-api/c-api.h +0 -1918
  160. package/android/src/main/cpp/include/sherpa-onnx/c-api/cxx-api.h +0 -841
  161. package/android/src/main/cpp/jni/sherpa-onnx-model-detect.cpp +0 -541
  162. package/android/src/main/cpp/jni/sherpa-onnx-stt-jni.cpp +0 -336
  163. package/android/src/main/cpp/jni/sherpa-onnx-stt-wrapper.cpp +0 -222
  164. package/android/src/main/cpp/jni/sherpa-onnx-stt-wrapper.h +0 -68
  165. package/android/src/main/cpp/jni/sherpa-onnx-tts-jni.cpp +0 -823
  166. package/android/src/main/cpp/jni/sherpa-onnx-tts-wrapper.cpp +0 -387
  167. package/android/src/main/cpp/jni/sherpa-onnx-tts-wrapper.h +0 -147
  168. package/ios/Frameworks/sherpa_onnx.xcframework.zip +0 -0
  169. package/ios/include/sherpa-onnx/c-api/c-api.h +0 -1918
  170. package/ios/include/sherpa-onnx/c-api/cxx-api.h +0 -841
  171. package/ios/sherpa-onnx-model-detect.mm +0 -441
  172. package/ios/sherpa-onnx-stt-wrapper.h +0 -48
  173. package/ios/sherpa-onnx-stt-wrapper.mm +0 -201
  174. package/scripts/copy-headers.js +0 -184
  175. package/scripts/setup-assets.js +0 -323
@@ -1,823 +0,0 @@
1
- // Include standard library headers first to avoid conflicts with jni.h
2
- #include <atomic>
3
- #include <cmath>
4
- #include <memory>
5
- #include <sstream>
6
- #include <string>
7
- #include <vector>
8
-
9
- // Then include JNI headers
10
- #include <android/log.h>
11
- #include <jni.h>
12
-
13
- // TTS wrapper
14
- #include "sherpa-onnx-tts-wrapper.h"
15
-
16
- #define LOG_TAG "SherpaOnnxJNI"
17
- #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
18
- #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
19
-
20
- using namespace sherpaonnx;
21
-
22
- namespace {
23
- std::vector<std::string> SplitTtsTokens(const std::string &text) {
24
- std::vector<std::string> tokens;
25
- std::istringstream iss(text);
26
- std::string token;
27
- while (iss >> token) {
28
- tokens.push_back(token);
29
- }
30
- if (tokens.empty() && !text.empty()) {
31
- tokens.push_back(text);
32
- }
33
- return tokens;
34
- }
35
- }
36
-
37
- // Global TTS wrapper instance
38
- static std::unique_ptr<TtsWrapper> g_tts_wrapper = nullptr;
39
- static std::atomic<bool> g_tts_stream_cancelled{false};
40
- static std::atomic<uint64_t> g_tts_active_stream_id{0};
41
-
42
- extern "C" {
43
-
44
- JNIEXPORT jobject JNICALL
45
- Java_com_sherpaonnx_SherpaOnnxModule_nativeTtsInitialize(
46
- JNIEnv *env,
47
- jobject /* this */,
48
- jstring modelDir,
49
- jstring modelType,
50
- jint numThreads,
51
- jboolean debug,
52
- jdouble noiseScale,
53
- jdouble noiseScaleW,
54
- jdouble lengthScale) {
55
- try {
56
- if (g_tts_wrapper == nullptr) {
57
- g_tts_wrapper = std::make_unique<TtsWrapper>();
58
- }
59
-
60
- const char *modelDirStr = env->GetStringUTFChars(modelDir, nullptr);
61
- if (modelDirStr == nullptr) {
62
- LOGE("TTS JNI: Failed to get modelDir string from JNI");
63
- return nullptr;
64
- }
65
-
66
- const char *modelTypeStr = env->GetStringUTFChars(modelType, nullptr);
67
- if (modelTypeStr == nullptr) {
68
- LOGE("TTS JNI: Failed to get modelType string from JNI");
69
- env->ReleaseStringUTFChars(modelDir, modelDirStr);
70
- return nullptr;
71
- }
72
-
73
- std::string modelDirPath(modelDirStr);
74
- std::string modelTypePath(modelTypeStr);
75
-
76
- std::optional<float> noiseScaleOpt = std::nullopt;
77
- std::optional<float> noiseScaleWOpt = std::nullopt;
78
- std::optional<float> lengthScaleOpt = std::nullopt;
79
- if (!std::isnan(noiseScale)) {
80
- noiseScaleOpt = static_cast<float>(noiseScale);
81
- }
82
- if (!std::isnan(noiseScaleW)) {
83
- noiseScaleWOpt = static_cast<float>(noiseScaleW);
84
- }
85
- if (!std::isnan(lengthScale)) {
86
- lengthScaleOpt = static_cast<float>(lengthScale);
87
- }
88
-
89
- TtsInitializeResult result = g_tts_wrapper->initialize(
90
- modelDirPath,
91
- modelTypePath,
92
- static_cast<int32_t>(numThreads),
93
- debug == JNI_TRUE,
94
- noiseScaleOpt,
95
- noiseScaleWOpt,
96
- lengthScaleOpt
97
- );
98
-
99
- env->ReleaseStringUTFChars(modelDir, modelDirStr);
100
- env->ReleaseStringUTFChars(modelType, modelTypeStr);
101
-
102
- LOGI("TTS JNI: Initialization result: success=%d, detected models=%zu", result.success, result.detectedModels.size());
103
- if (!result.success) {
104
- LOGE("TTS JNI: Native initialization failed for: %s", modelDirPath.c_str());
105
- } else {
106
- LOGI("TTS JNI: Successfully initialized model at: %s", modelDirPath.c_str());
107
- }
108
-
109
- // Create HashMap to return (same structure as STT)
110
- LOGI("TTS JNI: Creating HashMap for result");
111
- jclass hashMapClass = env->FindClass("java/util/HashMap");
112
- if (hashMapClass == nullptr || env->ExceptionCheck()) {
113
- LOGE("TTS JNI: Failed to find HashMap class");
114
- if (env->ExceptionCheck()) {
115
- env->ExceptionDescribe();
116
- env->ExceptionClear();
117
- }
118
- return nullptr;
119
- }
120
-
121
- jmethodID hashMapConstructor = env->GetMethodID(hashMapClass, "<init>", "()V");
122
- if (hashMapConstructor == nullptr || env->ExceptionCheck()) {
123
- LOGE("TTS JNI: Failed to get HashMap constructor");
124
- if (env->ExceptionCheck()) {
125
- env->ExceptionDescribe();
126
- env->ExceptionClear();
127
- }
128
- env->DeleteLocalRef(hashMapClass);
129
- return nullptr;
130
- }
131
-
132
- jmethodID putMethod = env->GetMethodID(hashMapClass, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
133
- if (putMethod == nullptr || env->ExceptionCheck()) {
134
- LOGE("TTS JNI: Failed to get HashMap put method");
135
- if (env->ExceptionCheck()) {
136
- env->ExceptionDescribe();
137
- env->ExceptionClear();
138
- }
139
- env->DeleteLocalRef(hashMapClass);
140
- return nullptr;
141
- }
142
-
143
- jobject hashMap = env->NewObject(hashMapClass, hashMapConstructor);
144
- if (hashMap == nullptr || env->ExceptionCheck()) {
145
- LOGE("TTS JNI: Failed to create HashMap object");
146
- if (env->ExceptionCheck()) {
147
- env->ExceptionDescribe();
148
- env->ExceptionClear();
149
- }
150
- env->DeleteLocalRef(hashMapClass);
151
- return nullptr;
152
- }
153
-
154
- // Put success boolean
155
- LOGI("TTS JNI: Adding success field to HashMap");
156
- jclass booleanClass = env->FindClass("java/lang/Boolean");
157
- if (booleanClass == nullptr || env->ExceptionCheck()) {
158
- LOGE("TTS JNI: Failed to find Boolean class");
159
- if (env->ExceptionCheck()) {
160
- env->ExceptionDescribe();
161
- env->ExceptionClear();
162
- }
163
- env->DeleteLocalRef(hashMap);
164
- env->DeleteLocalRef(hashMapClass);
165
- return nullptr;
166
- }
167
-
168
- jmethodID booleanConstructor = env->GetMethodID(booleanClass, "<init>", "(Z)V");
169
- if (booleanConstructor == nullptr || env->ExceptionCheck()) {
170
- LOGE("TTS JNI: Failed to get Boolean constructor");
171
- if (env->ExceptionCheck()) {
172
- env->ExceptionDescribe();
173
- env->ExceptionClear();
174
- }
175
- env->DeleteLocalRef(booleanClass);
176
- env->DeleteLocalRef(hashMap);
177
- env->DeleteLocalRef(hashMapClass);
178
- return nullptr;
179
- }
180
-
181
- jobject successObj = env->NewObject(booleanClass, booleanConstructor, result.success ? JNI_TRUE : JNI_FALSE);
182
- jstring successKey = env->NewStringUTF("success");
183
- env->CallObjectMethod(hashMap, putMethod, successKey, successObj);
184
- if (env->ExceptionCheck()) {
185
- LOGE("TTS JNI: Exception while putting success field");
186
- env->ExceptionDescribe();
187
- env->ExceptionClear();
188
- env->DeleteLocalRef(successKey);
189
- env->DeleteLocalRef(successObj);
190
- env->DeleteLocalRef(booleanClass);
191
- env->DeleteLocalRef(hashMap);
192
- env->DeleteLocalRef(hashMapClass);
193
- return nullptr;
194
- }
195
- env->DeleteLocalRef(successKey);
196
- env->DeleteLocalRef(successObj);
197
- env->DeleteLocalRef(booleanClass);
198
-
199
- // Put detectedModels array
200
- LOGI("TTS JNI: Adding detectedModels array (%zu models)", result.detectedModels.size());
201
- jclass arrayListClass = env->FindClass("java/util/ArrayList");
202
- if (arrayListClass == nullptr || env->ExceptionCheck()) {
203
- LOGE("TTS JNI: Failed to find ArrayList class");
204
- if (env->ExceptionCheck()) {
205
- env->ExceptionDescribe();
206
- env->ExceptionClear();
207
- }
208
- env->DeleteLocalRef(hashMap);
209
- env->DeleteLocalRef(hashMapClass);
210
- return nullptr;
211
- }
212
-
213
- jmethodID arrayListConstructor = env->GetMethodID(arrayListClass, "<init>", "()V");
214
- if (arrayListConstructor == nullptr || env->ExceptionCheck()) {
215
- LOGE("TTS JNI: Failed to get ArrayList constructor");
216
- if (env->ExceptionCheck()) {
217
- env->ExceptionDescribe();
218
- env->ExceptionClear();
219
- }
220
- env->DeleteLocalRef(arrayListClass);
221
- env->DeleteLocalRef(hashMap);
222
- env->DeleteLocalRef(hashMapClass);
223
- return nullptr;
224
- }
225
-
226
- jmethodID addMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
227
- if (addMethod == nullptr || env->ExceptionCheck()) {
228
- LOGE("TTS JNI: Failed to get ArrayList add method");
229
- if (env->ExceptionCheck()) {
230
- env->ExceptionDescribe();
231
- env->ExceptionClear();
232
- }
233
- env->DeleteLocalRef(arrayListClass);
234
- env->DeleteLocalRef(hashMap);
235
- env->DeleteLocalRef(hashMapClass);
236
- return nullptr;
237
- }
238
-
239
- jobject detectedModelsList = env->NewObject(arrayListClass, arrayListConstructor);
240
- if (detectedModelsList == nullptr || env->ExceptionCheck()) {
241
- LOGE("TTS JNI: Failed to create ArrayList object");
242
- if (env->ExceptionCheck()) {
243
- env->ExceptionDescribe();
244
- env->ExceptionClear();
245
- }
246
- env->DeleteLocalRef(arrayListClass);
247
- env->DeleteLocalRef(hashMap);
248
- env->DeleteLocalRef(hashMapClass);
249
- return nullptr;
250
- }
251
-
252
- for (const auto& model : result.detectedModels) {
253
- // Create HashMap for each model with type and modelDir
254
- jobject modelMap = env->NewObject(hashMapClass, hashMapConstructor);
255
- if (modelMap == nullptr || env->ExceptionCheck()) {
256
- LOGE("TTS JNI: Failed to create model HashMap");
257
- if (env->ExceptionCheck()) {
258
- env->ExceptionDescribe();
259
- env->ExceptionClear();
260
- }
261
- env->DeleteLocalRef(detectedModelsList);
262
- env->DeleteLocalRef(arrayListClass);
263
- env->DeleteLocalRef(hashMap);
264
- env->DeleteLocalRef(hashMapClass);
265
- return nullptr;
266
- }
267
-
268
- jstring typeKey = env->NewStringUTF("type");
269
- jstring typeValue = env->NewStringUTF(model.type.c_str());
270
- env->CallObjectMethod(modelMap, putMethod, typeKey, typeValue);
271
- env->DeleteLocalRef(typeKey);
272
- env->DeleteLocalRef(typeValue);
273
-
274
- jstring dirKey = env->NewStringUTF("modelDir");
275
- jstring dirValue = env->NewStringUTF(model.modelDir.c_str());
276
- env->CallObjectMethod(modelMap, putMethod, dirKey, dirValue);
277
- env->DeleteLocalRef(dirKey);
278
- env->DeleteLocalRef(dirValue);
279
-
280
- env->CallBooleanMethod(detectedModelsList, addMethod, modelMap);
281
- env->DeleteLocalRef(modelMap);
282
- }
283
-
284
- jstring detectedModelsKey = env->NewStringUTF("detectedModels");
285
- env->CallObjectMethod(hashMap, putMethod, detectedModelsKey, detectedModelsList);
286
- if (env->ExceptionCheck()) {
287
- LOGE("TTS JNI: Exception while putting detectedModels field");
288
- env->ExceptionDescribe();
289
- env->ExceptionClear();
290
- env->DeleteLocalRef(detectedModelsKey);
291
- env->DeleteLocalRef(detectedModelsList);
292
- env->DeleteLocalRef(arrayListClass);
293
- env->DeleteLocalRef(hashMap);
294
- env->DeleteLocalRef(hashMapClass);
295
- return nullptr;
296
- }
297
- env->DeleteLocalRef(detectedModelsKey);
298
- env->DeleteLocalRef(detectedModelsList);
299
- env->DeleteLocalRef(arrayListClass);
300
- env->DeleteLocalRef(hashMapClass);
301
-
302
- LOGI("TTS JNI: Successfully created result HashMap, returning to Java");
303
- return hashMap;
304
- } catch (const std::exception &e) {
305
- LOGE("TTS JNI: Exception in nativeInitializeTts: %s", e.what());
306
- if (env->ExceptionCheck()) {
307
- env->ExceptionDescribe();
308
- env->ExceptionClear();
309
- }
310
- return nullptr;
311
- } catch (...) {
312
- LOGE("TTS JNI: Unknown exception in nativeInitializeTts");
313
- if (env->ExceptionCheck()) {
314
- env->ExceptionDescribe();
315
- env->ExceptionClear();
316
- }
317
- return nullptr;
318
- }
319
- }
320
-
321
- JNIEXPORT jobject JNICALL
322
- Java_com_sherpaonnx_SherpaOnnxModule_nativeTtsGenerate(
323
- JNIEnv *env,
324
- jobject /* this */,
325
- jstring text,
326
- jint sid,
327
- jfloat speed) {
328
- try {
329
- if (g_tts_wrapper == nullptr || !g_tts_wrapper->isInitialized()) {
330
- LOGE("TTS JNI: Not initialized. Call initialize() first.");
331
- return nullptr;
332
- }
333
-
334
- const char *textStr = env->GetStringUTFChars(text, nullptr);
335
- if (textStr == nullptr) {
336
- LOGE("TTS JNI: Failed to get text string");
337
- return nullptr;
338
- }
339
-
340
- auto result = g_tts_wrapper->generate(
341
- std::string(textStr),
342
- static_cast<int32_t>(sid),
343
- static_cast<float>(speed)
344
- );
345
-
346
- env->ReleaseStringUTFChars(text, textStr);
347
-
348
- if (result.samples.empty() || result.sampleRate == 0) {
349
- LOGE("TTS JNI: Generation returned empty result");
350
- return nullptr;
351
- }
352
-
353
- // Create Java HashMap for result
354
- jclass hashMapClass = env->FindClass("java/util/HashMap");
355
- if (hashMapClass == nullptr) {
356
- LOGE("TTS JNI: Failed to find HashMap class");
357
- return nullptr;
358
- }
359
-
360
- jmethodID hashMapInit = env->GetMethodID(hashMapClass, "<init>", "()V");
361
- jmethodID hashMapPut = env->GetMethodID(hashMapClass, "put",
362
- "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
363
-
364
- if (hashMapInit == nullptr || hashMapPut == nullptr) {
365
- LOGE("TTS JNI: Failed to get HashMap methods");
366
- return nullptr;
367
- }
368
-
369
- jobject hashMap = env->NewObject(hashMapClass, hashMapInit);
370
- if (hashMap == nullptr) {
371
- LOGE("TTS JNI: Failed to create HashMap object");
372
- return nullptr;
373
- }
374
-
375
- // Convert samples to Java float array
376
- jfloatArray samplesArray = env->NewFloatArray(result.samples.size());
377
- if (samplesArray == nullptr) {
378
- LOGE("TTS JNI: Failed to create float array");
379
- return nullptr;
380
- }
381
-
382
- env->SetFloatArrayRegion(samplesArray, 0, result.samples.size(), result.samples.data());
383
-
384
- // Put samples in map
385
- jstring samplesKey = env->NewStringUTF("samples");
386
- env->CallObjectMethod(hashMap, hashMapPut, samplesKey, samplesArray);
387
- env->DeleteLocalRef(samplesKey);
388
- env->DeleteLocalRef(samplesArray);
389
-
390
- // Put sampleRate in map
391
- jclass integerClass = env->FindClass("java/lang/Integer");
392
- jmethodID integerInit = env->GetMethodID(integerClass, "<init>", "(I)V");
393
- jobject sampleRateObj = env->NewObject(integerClass, integerInit, result.sampleRate);
394
-
395
- jstring sampleRateKey = env->NewStringUTF("sampleRate");
396
- env->CallObjectMethod(hashMap, hashMapPut, sampleRateKey, sampleRateObj);
397
- env->DeleteLocalRef(sampleRateKey);
398
- env->DeleteLocalRef(sampleRateObj);
399
-
400
- // Clean up local class refs
401
- env->DeleteLocalRef(integerClass);
402
-
403
- return hashMap;
404
- } catch (const std::exception &e) {
405
- LOGE("TTS JNI: Exception in nativeGenerateTts: %s", e.what());
406
- return nullptr;
407
- } catch (...) {
408
- LOGE("TTS JNI: Unknown exception in nativeGenerateTts");
409
- return nullptr;
410
- }
411
- }
412
-
413
- JNIEXPORT jobject JNICALL
414
- Java_com_sherpaonnx_SherpaOnnxModule_nativeTtsGenerateWithTimestamps(
415
- JNIEnv *env,
416
- jobject /* this */,
417
- jstring text,
418
- jint sid,
419
- jfloat speed) {
420
- try {
421
- if (g_tts_wrapper == nullptr || !g_tts_wrapper->isInitialized()) {
422
- LOGE("TTS JNI: Not initialized. Call initialize() first.");
423
- return nullptr;
424
- }
425
-
426
- const char *textStr = env->GetStringUTFChars(text, nullptr);
427
- if (textStr == nullptr) {
428
- LOGE("TTS JNI: Failed to get text string");
429
- return nullptr;
430
- }
431
-
432
- std::string textValue(textStr);
433
- auto result = g_tts_wrapper->generate(
434
- textValue,
435
- static_cast<int32_t>(sid),
436
- static_cast<float>(speed)
437
- );
438
-
439
- env->ReleaseStringUTFChars(text, textStr);
440
-
441
- if (result.samples.empty() || result.sampleRate == 0) {
442
- LOGE("TTS JNI: Generation returned empty result");
443
- return nullptr;
444
- }
445
-
446
- jclass hashMapClass = env->FindClass("java/util/HashMap");
447
- if (hashMapClass == nullptr) {
448
- LOGE("TTS JNI: Failed to find HashMap class");
449
- return nullptr;
450
- }
451
-
452
- jmethodID hashMapInit = env->GetMethodID(hashMapClass, "<init>", "()V");
453
- jmethodID hashMapPut = env->GetMethodID(
454
- hashMapClass,
455
- "put",
456
- "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"
457
- );
458
- if (hashMapInit == nullptr || hashMapPut == nullptr) {
459
- LOGE("TTS JNI: Failed to get HashMap methods");
460
- return nullptr;
461
- }
462
-
463
- jobject hashMap = env->NewObject(hashMapClass, hashMapInit);
464
- if (hashMap == nullptr) {
465
- LOGE("TTS JNI: Failed to create HashMap object");
466
- return nullptr;
467
- }
468
-
469
- jfloatArray samplesArray = env->NewFloatArray(result.samples.size());
470
- if (samplesArray == nullptr) {
471
- LOGE("TTS JNI: Failed to create float array");
472
- return nullptr;
473
- }
474
- env->SetFloatArrayRegion(samplesArray, 0, result.samples.size(), result.samples.data());
475
-
476
- jstring samplesKey = env->NewStringUTF("samples");
477
- env->CallObjectMethod(hashMap, hashMapPut, samplesKey, samplesArray);
478
- env->DeleteLocalRef(samplesKey);
479
- env->DeleteLocalRef(samplesArray);
480
-
481
- jclass integerClass = env->FindClass("java/lang/Integer");
482
- jmethodID integerInit = env->GetMethodID(integerClass, "<init>", "(I)V");
483
- jobject sampleRateObj = env->NewObject(integerClass, integerInit, result.sampleRate);
484
-
485
- jstring sampleRateKey = env->NewStringUTF("sampleRate");
486
- env->CallObjectMethod(hashMap, hashMapPut, sampleRateKey, sampleRateObj);
487
- env->DeleteLocalRef(sampleRateKey);
488
- env->DeleteLocalRef(sampleRateObj);
489
-
490
- jclass arrayListClass = env->FindClass("java/util/ArrayList");
491
- jmethodID arrayListInit = env->GetMethodID(arrayListClass, "<init>", "()V");
492
- jmethodID arrayListAdd = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
493
-
494
- jobject subtitlesList = env->NewObject(arrayListClass, arrayListInit);
495
- auto tokens = SplitTtsTokens(textValue);
496
- jclass doubleClass = nullptr;
497
- if (!tokens.empty()) {
498
- const double totalSeconds = static_cast<double>(result.samples.size()) /
499
- static_cast<double>(result.sampleRate);
500
- const double perToken = totalSeconds / static_cast<double>(tokens.size());
501
-
502
- doubleClass = env->FindClass("java/lang/Double");
503
- jmethodID doubleInit = env->GetMethodID(doubleClass, "<init>", "(D)V");
504
-
505
- for (size_t i = 0; i < tokens.size(); ++i) {
506
- double start = perToken * static_cast<double>(i);
507
- double end = perToken * static_cast<double>(i + 1);
508
-
509
- jobject subtitleMap = env->NewObject(hashMapClass, hashMapInit);
510
- jstring textKey = env->NewStringUTF("text");
511
- jstring textValueKey = env->NewStringUTF(tokens[i].c_str());
512
- env->CallObjectMethod(subtitleMap, hashMapPut, textKey, textValueKey);
513
- env->DeleteLocalRef(textKey);
514
- env->DeleteLocalRef(textValueKey);
515
-
516
- jstring startKey = env->NewStringUTF("start");
517
- jobject startObj = env->NewObject(doubleClass, doubleInit, start);
518
- env->CallObjectMethod(subtitleMap, hashMapPut, startKey, startObj);
519
- env->DeleteLocalRef(startKey);
520
- env->DeleteLocalRef(startObj);
521
-
522
- jstring endKey = env->NewStringUTF("end");
523
- jobject endObj = env->NewObject(doubleClass, doubleInit, end);
524
- env->CallObjectMethod(subtitleMap, hashMapPut, endKey, endObj);
525
- env->DeleteLocalRef(endKey);
526
- env->DeleteLocalRef(endObj);
527
-
528
- env->CallBooleanMethod(subtitlesList, arrayListAdd, subtitleMap);
529
- env->DeleteLocalRef(subtitleMap);
530
- }
531
- }
532
-
533
- jstring subtitlesKey = env->NewStringUTF("subtitles");
534
- env->CallObjectMethod(hashMap, hashMapPut, subtitlesKey, subtitlesList);
535
- env->DeleteLocalRef(subtitlesKey);
536
- env->DeleteLocalRef(subtitlesList);
537
-
538
- jclass booleanClass = env->FindClass("java/lang/Boolean");
539
- jmethodID booleanInit = env->GetMethodID(booleanClass, "<init>", "(Z)V");
540
- jobject estimatedObj = env->NewObject(booleanClass, booleanInit, JNI_TRUE);
541
- jstring estimatedKey = env->NewStringUTF("estimated");
542
- env->CallObjectMethod(hashMap, hashMapPut, estimatedKey, estimatedObj);
543
- env->DeleteLocalRef(estimatedKey);
544
- env->DeleteLocalRef(estimatedObj);
545
-
546
- // Clean up local class refs used above
547
- env->DeleteLocalRef(booleanClass);
548
- env->DeleteLocalRef(arrayListClass);
549
- env->DeleteLocalRef(integerClass);
550
- if (doubleClass) env->DeleteLocalRef(doubleClass);
551
- env->DeleteLocalRef(hashMapClass);
552
-
553
- return hashMap;
554
- } catch (const std::exception &e) {
555
- LOGE("TTS JNI: Exception in nativeGenerateTtsWithTimestamps: %s", e.what());
556
- return nullptr;
557
- } catch (...) {
558
- LOGE("TTS JNI: Unknown exception in nativeGenerateTtsWithTimestamps");
559
- return nullptr;
560
- }
561
- }
562
-
563
- JNIEXPORT jboolean JNICALL
564
- Java_com_sherpaonnx_SherpaOnnxModule_nativeTtsGenerateStream(
565
- JNIEnv *env,
566
- jobject /* this */,
567
- jstring text,
568
- jint sid,
569
- jfloat speed) {
570
- try {
571
- if (g_tts_wrapper == nullptr || !g_tts_wrapper->isInitialized()) {
572
- LOGE("TTS JNI: Not initialized. Call initialize() first.");
573
- return JNI_FALSE;
574
- }
575
-
576
- const char *textStr = env->GetStringUTFChars(text, nullptr);
577
- if (textStr == nullptr) {
578
- LOGE("TTS JNI: Failed to get text string");
579
- return JNI_FALSE;
580
- }
581
-
582
- g_tts_stream_cancelled.store(false);
583
-
584
- jclass moduleClassLocal = env->FindClass("com/sherpaonnx/SherpaOnnxModule");
585
- if (moduleClassLocal == nullptr) {
586
- LOGE("TTS JNI: Failed to find SherpaOnnxModule class");
587
- env->ReleaseStringUTFChars(text, textStr);
588
- return JNI_FALSE;
589
- }
590
-
591
- jmethodID onChunk = env->GetStaticMethodID(
592
- moduleClassLocal,
593
- "onTtsStreamChunk",
594
- "([FIFZ)V"
595
- );
596
- jmethodID onError = env->GetStaticMethodID(
597
- moduleClassLocal,
598
- "onTtsStreamError",
599
- "(Ljava/lang/String;)V"
600
- );
601
-
602
- if (onChunk == nullptr) {
603
- LOGE("TTS JNI: Failed to get onTtsStreamChunk method");
604
- env->ReleaseStringUTFChars(text, textStr);
605
- env->DeleteLocalRef(moduleClassLocal);
606
- return JNI_FALSE;
607
- }
608
-
609
- // Make a global ref for the class to be safe if the callback runs on another thread
610
- JavaVM *jvm = nullptr;
611
- if (env->GetJavaVM(&jvm) != JNI_OK) {
612
- LOGE("TTS JNI: Failed to get JavaVM");
613
- env->ReleaseStringUTFChars(text, textStr);
614
- env->DeleteLocalRef(moduleClassLocal);
615
- return JNI_FALSE;
616
- }
617
-
618
- jclass moduleClass = reinterpret_cast<jclass>(env->NewGlobalRef(moduleClassLocal));
619
- // we can drop the local ref now
620
- env->DeleteLocalRef(moduleClassLocal);
621
-
622
- const int32_t sampleRate = g_tts_wrapper->getSampleRate();
623
- auto finalSent = std::make_shared<std::atomic<bool>>(false);
624
- const uint64_t streamId = g_tts_active_stream_id.fetch_add(1) + 1;
625
- g_tts_active_stream_id.store(streamId);
626
- const bool ok = g_tts_wrapper->generateStream(
627
- std::string(textStr),
628
- static_cast<int32_t>(sid),
629
- static_cast<float>(speed),
630
- streamId,
631
- [jvm, moduleClass, onChunk, sampleRate, finalSent, streamId](
632
- const float *samples,
633
- int32_t numSamples,
634
- float progress
635
- ) -> int32_t {
636
- if (g_tts_stream_cancelled.load()) {
637
- return 0;
638
- }
639
-
640
- JNIEnv *callbackEnv = nullptr;
641
- bool attached = false;
642
- if (jvm->GetEnv(reinterpret_cast<void **>(&callbackEnv), JNI_VERSION_1_6) != JNI_OK) {
643
- if (jvm->AttachCurrentThread(reinterpret_cast<JNIEnv **>(&callbackEnv), nullptr) != 0) {
644
- // Failed to attach
645
- return 0;
646
- }
647
- attached = true;
648
- }
649
-
650
- jfloatArray floatArray = callbackEnv->NewFloatArray(numSamples);
651
- if (floatArray == nullptr) {
652
- if (attached) jvm->DetachCurrentThread();
653
- return 0;
654
- }
655
- callbackEnv->SetFloatArrayRegion(floatArray, 0, numSamples, samples);
656
-
657
- const bool isFinal = progress >= 0.999f;
658
- callbackEnv->CallStaticVoidMethod(
659
- moduleClass,
660
- onChunk,
661
- floatArray,
662
- sampleRate,
663
- progress,
664
- isFinal ? JNI_TRUE : JNI_FALSE
665
- );
666
- callbackEnv->DeleteLocalRef(floatArray);
667
-
668
- if (isFinal && !finalSent->exchange(true)) {
669
- if (g_tts_wrapper) {
670
- g_tts_wrapper->endStream(streamId);
671
- }
672
- }
673
-
674
- if (attached) jvm->DetachCurrentThread();
675
- return 1;
676
- }
677
- );
678
-
679
- env->ReleaseStringUTFChars(text, textStr);
680
-
681
- if (!ok && !g_tts_stream_cancelled.load()) {
682
- // Ensure we have a JNIEnv for calling the error callback
683
- JNIEnv *errEnv = nullptr;
684
- bool errAttached = false;
685
- if (jvm->GetEnv(reinterpret_cast<void **>(&errEnv), JNI_VERSION_1_6) != JNI_OK) {
686
- if (jvm->AttachCurrentThread(reinterpret_cast<JNIEnv **>(&errEnv), nullptr) == 0) {
687
- errAttached = true;
688
- } else {
689
- errEnv = nullptr;
690
- }
691
- }
692
-
693
- if (errEnv != nullptr && onError != nullptr) {
694
- jstring errorMsg = errEnv->NewStringUTF("TTS: Streaming generation failed");
695
- errEnv->CallStaticVoidMethod(moduleClass, onError, errorMsg);
696
- errEnv->DeleteLocalRef(errorMsg);
697
- }
698
-
699
- if (errAttached) jvm->DetachCurrentThread();
700
- }
701
-
702
- if (!ok && g_tts_wrapper) {
703
- g_tts_wrapper->endStream(streamId);
704
- }
705
-
706
- // cleanup global ref
707
- env->DeleteGlobalRef(moduleClass);
708
- return ok ? JNI_TRUE : JNI_FALSE;
709
- } catch (const std::exception &e) {
710
- LOGE("TTS JNI: Exception in nativeTtsGenerateStream: %s", e.what());
711
- return JNI_FALSE;
712
- } catch (...) {
713
- LOGE("TTS JNI: Unknown exception in nativeTtsGenerateStream");
714
- return JNI_FALSE;
715
- }
716
- }
717
-
718
- JNIEXPORT void JNICALL
719
- Java_com_sherpaonnx_SherpaOnnxModule_nativeTtsCancelStream(
720
- JNIEnv * /* env */,
721
- jobject /* this */) {
722
- g_tts_stream_cancelled.store(true);
723
- if (g_tts_wrapper) {
724
- g_tts_wrapper->cancelStream(g_tts_active_stream_id.load());
725
- }
726
- g_tts_active_stream_id.store(0);
727
- }
728
-
729
- JNIEXPORT jint JNICALL
730
- Java_com_sherpaonnx_SherpaOnnxModule_nativeTtsGetSampleRate(
731
- JNIEnv * /* env */,
732
- jobject /* this */) {
733
- try {
734
- if (g_tts_wrapper == nullptr || !g_tts_wrapper->isInitialized()) {
735
- LOGE("TTS JNI: Not initialized. Call initialize() first.");
736
- return 0;
737
- }
738
- return g_tts_wrapper->getSampleRate();
739
- } catch (const std::exception &e) {
740
- LOGE("TTS JNI: Exception in nativeGetTtsSampleRate: %s", e.what());
741
- return 0;
742
- } catch (...) {
743
- LOGE("TTS JNI: Unknown exception in nativeGetTtsSampleRate");
744
- return 0;
745
- }
746
- }
747
-
748
- JNIEXPORT jint JNICALL
749
- Java_com_sherpaonnx_SherpaOnnxModule_nativeTtsGetNumSpeakers(
750
- JNIEnv * /* env */,
751
- jobject /* this */) {
752
- try {
753
- if (g_tts_wrapper == nullptr || !g_tts_wrapper->isInitialized()) {
754
- LOGE("TTS JNI: Not initialized. Call initialize() first.");
755
- return 0;
756
- }
757
- return g_tts_wrapper->getNumSpeakers();
758
- } catch (const std::exception &e) {
759
- LOGE("TTS JNI: Exception in nativeGetTtsNumSpeakers: %s", e.what());
760
- return 0;
761
- } catch (...) {
762
- LOGE("TTS JNI: Unknown exception in nativeGetTtsNumSpeakers");
763
- return 0;
764
- }
765
- }
766
-
767
- JNIEXPORT void JNICALL
768
- Java_com_sherpaonnx_SherpaOnnxModule_nativeTtsRelease(
769
- JNIEnv * /* env */,
770
- jobject /* this */) {
771
- try {
772
- if (g_tts_wrapper != nullptr) {
773
- g_tts_wrapper->release();
774
- g_tts_wrapper.reset();
775
- }
776
- } catch (const std::exception &e) {
777
- LOGE("TTS JNI: Exception in nativeReleaseTts: %s", e.what());
778
- } catch (...) {
779
- LOGE("TTS JNI: Unknown exception in nativeReleaseTts");
780
- }
781
- }
782
-
783
- JNIEXPORT jboolean JNICALL
784
- Java_com_sherpaonnx_SherpaOnnxModule_nativeTtsSaveToWavFile(
785
- JNIEnv *env,
786
- jobject /* this */,
787
- jfloatArray samples,
788
- jint sampleRate,
789
- jstring filePath) {
790
- try {
791
- if (samples == nullptr || filePath == nullptr) {
792
- LOGE("TTS JNI: samples or filePath is null");
793
- return JNI_FALSE;
794
- }
795
-
796
- // Convert jfloatArray to std::vector<float>
797
- jsize len = env->GetArrayLength(samples);
798
- std::vector<float> samplesVec(len);
799
- env->GetFloatArrayRegion(samples, 0, len, samplesVec.data());
800
-
801
- // Convert jstring to std::string
802
- const char *filePathCStr = env->GetStringUTFChars(filePath, nullptr);
803
- std::string filePathStr(filePathCStr);
804
- env->ReleaseStringUTFChars(filePath, filePathCStr);
805
-
806
- // Call the static method
807
- bool success = sherpaonnx::TtsWrapper::saveToWavFile(
808
- samplesVec,
809
- static_cast<int32_t>(sampleRate),
810
- filePathStr
811
- );
812
-
813
- return success ? JNI_TRUE : JNI_FALSE;
814
- } catch (const std::exception &e) {
815
- LOGE("TTS JNI: Exception in nativeTtsSaveToWavFile: %s", e.what());
816
- return JNI_FALSE;
817
- } catch (...) {
818
- LOGE("TTS JNI: Unknown exception in nativeTtsSaveToWavFile");
819
- return JNI_FALSE;
820
- }
821
- }
822
-
823
- } // extern "C"