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
@@ -0,0 +1,296 @@
1
+ /**
2
+ * sherpa-onnx-archive-helper.mm
3
+ *
4
+ * Purpose: Extracts .tar.bz2 archives (e.g. downloaded model bundles) to a target directory and
5
+ * computes file SHA-256. Used by the main module for model download and verification on iOS.
6
+ */
7
+
8
+ #import "sherpa-onnx-archive-helper.h"
9
+ #import <archive.h>
10
+ #import <archive_entry.h>
11
+ #import <CommonCrypto/CommonCrypto.h>
12
+ #include <array>
13
+ #include <atomic>
14
+ #include <cstdio>
15
+ #include <string>
16
+
17
+ static std::atomic_bool g_cancelExtract(false);
18
+
19
+ namespace {
20
+ struct ArchiveReadContext {
21
+ FILE* file = nullptr;
22
+ std::array<unsigned char, 64 * 1024> buffer{};
23
+ CC_SHA256_CTX sha_ctx{};
24
+ long long bytes_read = 0;
25
+ };
26
+
27
+ static la_ssize_t ArchiveReadCallback(struct archive* archive, void* client_data, const void** buff) {
28
+ auto* ctx = static_cast<ArchiveReadContext*>(client_data);
29
+ if (!ctx || !ctx->file) {
30
+ archive_set_error(archive, EINVAL, "Invalid read context");
31
+ return -1;
32
+ }
33
+
34
+ size_t bytes = fread(ctx->buffer.data(), 1, ctx->buffer.size(), ctx->file);
35
+ if (bytes > 0) {
36
+ CC_SHA256_Update(&ctx->sha_ctx, ctx->buffer.data(), (CC_LONG)bytes);
37
+ ctx->bytes_read += (long long)bytes;
38
+ *buff = ctx->buffer.data();
39
+ return (la_ssize_t)bytes;
40
+ }
41
+
42
+ if (feof(ctx->file)) {
43
+ return 0;
44
+ }
45
+
46
+ archive_set_error(archive, errno, "Read error");
47
+ return -1;
48
+ }
49
+
50
+ static int ArchiveCloseCallback(struct archive* /* archive */, void* client_data) {
51
+ (void)client_data;
52
+ return ARCHIVE_OK;
53
+ }
54
+
55
+ static void DrainRemainingAndClose(ArchiveReadContext* ctx) {
56
+ if (!ctx || !ctx->file) {
57
+ return;
58
+ }
59
+
60
+ size_t bytes = 0;
61
+ while ((bytes = fread(ctx->buffer.data(), 1, ctx->buffer.size(), ctx->file)) > 0) {
62
+ CC_SHA256_Update(&ctx->sha_ctx, ctx->buffer.data(), (CC_LONG)bytes);
63
+ ctx->bytes_read += (long long)bytes;
64
+ }
65
+
66
+ fclose(ctx->file);
67
+ ctx->file = nullptr;
68
+ }
69
+
70
+ static NSString* HexStringFromDigest(const unsigned char* digest, size_t size) {
71
+ static const char* kHex = "0123456789abcdef";
72
+ std::string out;
73
+ out.reserve(size * 2);
74
+ for (size_t i = 0; i < size; ++i) {
75
+ unsigned char value = digest[i];
76
+ out.push_back(kHex[value >> 4]);
77
+ out.push_back(kHex[value & 0x0F]);
78
+ }
79
+ return [NSString stringWithUTF8String:out.c_str()];
80
+ }
81
+
82
+ static NSString* ComputeFileSha256(NSString* filePath, NSError** error) {
83
+ const char* path = [filePath UTF8String];
84
+ FILE* file = fopen(path, "rb");
85
+ if (!file) {
86
+ if (error) {
87
+ *error = [NSError errorWithDomain:@"SherpaOnnx"
88
+ code:5
89
+ userInfo:@{NSLocalizedDescriptionKey: @"Failed to open file"}];
90
+ }
91
+ return nil;
92
+ }
93
+
94
+ CC_SHA256_CTX sha_ctx;
95
+ CC_SHA256_Init(&sha_ctx);
96
+
97
+ std::array<unsigned char, 64 * 1024> buffer{};
98
+ size_t bytes = 0;
99
+ while ((bytes = fread(buffer.data(), 1, buffer.size(), file)) > 0) {
100
+ CC_SHA256_Update(&sha_ctx, buffer.data(), (CC_LONG)bytes);
101
+ }
102
+
103
+ if (ferror(file)) {
104
+ fclose(file);
105
+ if (error) {
106
+ *error = [NSError errorWithDomain:@"SherpaOnnx"
107
+ code:6
108
+ userInfo:@{NSLocalizedDescriptionKey: @"Read error while hashing file"}];
109
+ }
110
+ return nil;
111
+ }
112
+
113
+ fclose(file);
114
+
115
+ unsigned char digest[CC_SHA256_DIGEST_LENGTH];
116
+ CC_SHA256_Final(digest, &sha_ctx);
117
+ return HexStringFromDigest(digest, CC_SHA256_DIGEST_LENGTH);
118
+ }
119
+ } // namespace
120
+
121
+ @implementation SherpaOnnxArchiveHelper
122
+
123
+ + (void)cancelExtractTarBz2
124
+ {
125
+ g_cancelExtract.store(true);
126
+ }
127
+
128
+ - (NSDictionary *)extractTarBz2:(NSString *)sourcePath
129
+ targetPath:(NSString *)targetPath
130
+ force:(BOOL)force
131
+ progress:(SherpaOnnxArchiveProgressBlock)progress
132
+ {
133
+ g_cancelExtract.store(false);
134
+ NSFileManager *fileManager = [NSFileManager defaultManager];
135
+
136
+ if (![fileManager fileExistsAtPath:sourcePath]) {
137
+ return @{ @"success": @NO, @"reason": @"Source file does not exist" };
138
+ }
139
+
140
+ if ([fileManager fileExistsAtPath:targetPath]) {
141
+ if (force) {
142
+ NSError *removeError = nil;
143
+ [fileManager removeItemAtPath:targetPath error:&removeError];
144
+ if (removeError) {
145
+ return @{ @"success": @NO, @"reason": removeError.localizedDescription ?: @"Failed to remove target" };
146
+ }
147
+ } else {
148
+ return @{ @"success": @NO, @"reason": @"Target path already exists" };
149
+ }
150
+ }
151
+
152
+ NSError *mkdirError = nil;
153
+ [fileManager createDirectoryAtPath:targetPath withIntermediateDirectories:YES attributes:nil error:&mkdirError];
154
+ if (mkdirError) {
155
+ return @{ @"success": @NO, @"reason": mkdirError.localizedDescription ?: @"Failed to create target directory" };
156
+ }
157
+
158
+ NSString *canonicalTarget = [[targetPath stringByStandardizingPath] stringByAppendingString:@"/"];
159
+
160
+ NSDictionary *fileAttributes = [fileManager attributesOfItemAtPath:sourcePath error:nil];
161
+ long long totalBytes = [[fileAttributes objectForKey:NSFileSize] longLongValue];
162
+
163
+ struct archive *archive = archive_read_new();
164
+ archive_read_support_format_tar(archive);
165
+ archive_read_support_filter_bzip2(archive);
166
+
167
+ ArchiveReadContext read_ctx;
168
+ read_ctx.file = fopen([sourcePath UTF8String], "rb");
169
+ if (!read_ctx.file) {
170
+ return @{ @"success": @NO, @"reason": @"Failed to open archive file" };
171
+ }
172
+ auto close_reader = [&read_ctx]() {
173
+ DrainRemainingAndClose(&read_ctx);
174
+ };
175
+ CC_SHA256_Init(&read_ctx.sha_ctx);
176
+
177
+ if (archive_read_open(archive, &read_ctx, nullptr, ArchiveReadCallback, ArchiveCloseCallback) != ARCHIVE_OK) {
178
+ const char *errorStr = archive_error_string(archive);
179
+ NSString *reason = errorStr ? [NSString stringWithUTF8String:errorStr] : @"Failed to open archive";
180
+ close_reader();
181
+ archive_read_free(archive);
182
+ return @{ @"success": @NO, @"reason": reason };
183
+ }
184
+
185
+ struct archive *disk = archive_write_disk_new();
186
+ archive_write_disk_set_options(disk, ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_ACL | ARCHIVE_EXTRACT_FFLAGS);
187
+ archive_write_disk_set_standard_lookup(disk);
188
+
189
+ struct archive_entry *entry = nullptr;
190
+ int result = ARCHIVE_OK;
191
+ long long extractedBytes = 0;
192
+ int lastPercent = -1;
193
+ long long lastEmitBytes = 0;
194
+ while ((result = archive_read_next_header(archive, &entry)) == ARCHIVE_OK) {
195
+ if (g_cancelExtract.load()) {
196
+ archive_read_free(archive);
197
+ archive_write_free(disk);
198
+ close_reader();
199
+ return @{ @"success": @NO, @"reason": @"Extraction cancelled" };
200
+ }
201
+ const char *currentPath = archive_entry_pathname(entry);
202
+ NSString *entryPath = currentPath ? [NSString stringWithUTF8String:currentPath] : @"";
203
+ NSString *fullPath = [[targetPath stringByAppendingPathComponent:entryPath] stringByStandardizingPath];
204
+
205
+ if (![fullPath hasPrefix:canonicalTarget]) {
206
+ archive_read_free(archive);
207
+ archive_write_free(disk);
208
+ close_reader();
209
+ return @{ @"success": @NO, @"reason": @"Blocked path traversal" };
210
+ }
211
+
212
+ archive_entry_set_pathname(entry, [fullPath UTF8String]);
213
+ result = archive_write_header(disk, entry);
214
+ if (result != ARCHIVE_OK) {
215
+ const char *errorStr = archive_error_string(disk);
216
+ NSString *reason = errorStr ? [NSString stringWithUTF8String:errorStr] : @"Failed to write entry";
217
+ archive_read_free(archive);
218
+ archive_write_free(disk);
219
+ close_reader();
220
+ return @{ @"success": @NO, @"reason": reason };
221
+ }
222
+
223
+ const void *buff = nullptr;
224
+ size_t size = 0;
225
+ la_int64_t offset = 0;
226
+ while ((result = archive_read_data_block(archive, &buff, &size, &offset)) == ARCHIVE_OK) {
227
+ if (g_cancelExtract.load()) {
228
+ archive_read_free(archive);
229
+ archive_write_free(disk);
230
+ close_reader();
231
+ return @{ @"success": @NO, @"reason": @"Extraction cancelled" };
232
+ }
233
+ la_ssize_t writeResult = archive_write_data_block(disk, buff, size, offset);
234
+ if (writeResult != ARCHIVE_OK) {
235
+ const char *errorStr = archive_error_string(disk);
236
+ NSString *reason = errorStr ? [NSString stringWithUTF8String:errorStr] : @"Failed to write data";
237
+ archive_read_free(archive);
238
+ archive_write_free(disk);
239
+ close_reader();
240
+ return @{ @"success": @NO, @"reason": reason };
241
+ }
242
+
243
+ extractedBytes += (long long)size;
244
+ if (progress) {
245
+ if (totalBytes > 0) {
246
+ long long compressedBytes = archive_filter_bytes(archive, -1);
247
+ int percent = (int)((compressedBytes * 100) / totalBytes);
248
+ if (percent > 100) {
249
+ percent = 100;
250
+ } else if (percent < 0) {
251
+ percent = 0;
252
+ }
253
+ if (percent != lastPercent) {
254
+ lastPercent = percent;
255
+ progress(compressedBytes, totalBytes, (double)percent);
256
+ }
257
+ } else if (extractedBytes - lastEmitBytes >= 1024 * 1024) {
258
+ lastEmitBytes = extractedBytes;
259
+ progress(extractedBytes, totalBytes, 0.0);
260
+ }
261
+ }
262
+ }
263
+
264
+ if (result != ARCHIVE_EOF && result != ARCHIVE_OK) {
265
+ const char *errorStr = archive_error_string(archive);
266
+ NSString *reason = errorStr ? [NSString stringWithUTF8String:errorStr] : @"Failed to read data";
267
+ archive_read_free(archive);
268
+ archive_write_free(disk);
269
+ close_reader();
270
+ return @{ @"success": @NO, @"reason": reason };
271
+ }
272
+ }
273
+
274
+ archive_read_free(archive);
275
+ archive_write_free(disk);
276
+
277
+ if (progress) {
278
+ progress(extractedBytes, extractedBytes, 100.0);
279
+ }
280
+
281
+ close_reader();
282
+
283
+ unsigned char digest[CC_SHA256_DIGEST_LENGTH];
284
+ CC_SHA256_Final(digest, &read_ctx.sha_ctx);
285
+ NSString *sha256Hex = HexStringFromDigest(digest, CC_SHA256_DIGEST_LENGTH);
286
+
287
+ return @{ @"success": @YES, @"path": targetPath, @"sha256": sha256Hex ?: @"" };
288
+ }
289
+
290
+ - (NSString *)computeFileSha256:(NSString *)filePath
291
+ error:(NSError * _Nullable * _Nullable)error
292
+ {
293
+ return ComputeFileSha256(filePath, error);
294
+ }
295
+
296
+ @end
@@ -0,0 +1,153 @@
1
+ /* Configuration for libarchive when building on Apple platforms (iOS/macOS).
2
+ * iOS does not ship libarchive; we vendor and build it. This config is based on
3
+ * the Android contrib config with Apple-appropriate settings.
4
+ */
5
+ #ifndef ARCHIVE_PLATFORM_H_DARWIN_INCLUDED
6
+ #define ARCHIVE_PLATFORM_H_DARWIN_INCLUDED
7
+
8
+ #define __LIBARCHIVE_CONFIG_H_INCLUDED 1
9
+
10
+ #define HAVE_CHOWN 1
11
+ #define HAVE_CHROOT 1
12
+ #define HAVE_CLOSEFROM 0
13
+ #define HAVE_CLOSE_RANGE 0
14
+ #define HAVE_CTIME_R 1
15
+ #define HAVE_CTYPE_H 1
16
+ #define HAVE_DECL_EXTATTR_NAMESPACE_USER 0
17
+ #define HAVE_DECL_INTMAX_MIN 1
18
+ #define HAVE_DECL_INTMAX_MAX 1
19
+ #define HAVE_DECL_INT64_MAX 1
20
+ #define HAVE_DECL_INT64_MIN 1
21
+ #define HAVE_DECL_SIZE_MAX 1
22
+ #define HAVE_DECL_SSIZE_MAX 1
23
+ #define HAVE_DECL_STRERROR_R 1
24
+ #define HAVE_DECL_UINTMAX_MAX 1
25
+ #define HAVE_DECL_UINT32_MAX 1
26
+ #define HAVE_DECL_UINT64_MAX 1
27
+ #define HAVE_DECL_INT32_MAX 1
28
+ #define HAVE_DECL_INT32_MIN 1
29
+ #define HAVE_DIRENT_H 1
30
+ #define HAVE_DIRFD 1
31
+ #define HAVE_DLFCN_H 1
32
+ #define HAVE_EILSEQ 1
33
+ #define HAVE_ERRNO_H 1
34
+ #define HAVE_FCHDIR 1
35
+ #define HAVE_FCHMOD 1
36
+ #define HAVE_FCHOWN 1
37
+ #define HAVE_FCNTL 1
38
+ #define HAVE_FCNTL_H 1
39
+ #define HAVE_FDOPENDIR 1
40
+ #define HAVE_FGETXATTR 1
41
+ #define HAVE_FLISTXATTR 1
42
+ #define HAVE_FORK 1
43
+ #define HAVE_FSEEKO 1
44
+ #define HAVE_FSETXATTR 1
45
+ #define HAVE_FSTAT 1
46
+ #define HAVE_FSTATAT 1
47
+ #define HAVE_FSTATFS 1
48
+ #define HAVE_FTRUNCATE 1
49
+ #define HAVE_GETEUID 1
50
+ #define HAVE_GETPID 1
51
+ #define HAVE_GETPWNAM_R 1
52
+ #define HAVE_GETPWUID_R 1
53
+ #define HAVE_GETXATTR 1
54
+ #define HAVE_GMTIME_R 1
55
+ #define HAVE_GRP_H 1
56
+ #define HAVE_INTMAX_T 1
57
+ #define HAVE_INTTYPES_H 1
58
+ #define HAVE_LCHOWN 1
59
+ #define HAVE_LGETXATTR 1
60
+ #define HAVE_LIBLZMA 0
61
+ #define HAVE_LIBZ 1
62
+ #define HAVE_LIMITS_H 1
63
+ #define HAVE_LINK 1
64
+ #define HAVE_LISTXATTR 1
65
+ #define HAVE_LLISTXATTR 1
66
+ #define HAVE_LOCALE_H 1
67
+ #define HAVE_LOCALTIME_R 1
68
+ #define HAVE_LONG_LONG_INT 1
69
+ #define HAVE_LSETXATTR 1
70
+ #define HAVE_LSTAT 1
71
+ #define HAVE_MBRTOWC 1
72
+ #define HAVE_MEMMOVE 1
73
+ #define HAVE_MEMSET 1
74
+ #define HAVE_MKDIR 1
75
+ #define HAVE_MKFIFO 1
76
+ #define HAVE_MKNOD 1
77
+ #define HAVE_MKSTEMP 1
78
+ #define HAVE_OPENAT 1
79
+ #define HAVE_PIPE 1
80
+ #define HAVE_POLL 1
81
+ #define HAVE_POLL_H 1
82
+ #define HAVE_PTHREAD_H 1
83
+ #define HAVE_PWD_H 1
84
+ #define HAVE_READLINK 1
85
+ #define HAVE_READLINKAT 1
86
+ #define HAVE_READDIR_R 1
87
+ #define HAVE_REGEX_H 1
88
+ #define HAVE_SELECT 1
89
+ #define HAVE_STATVFS 1
90
+ #define HAVE_FSTATVFS 1
91
+ #define HAVE_SYS_STATVFS_H 1
92
+ #define HAVE_SETENV 1
93
+ #define HAVE_SETLOCALE 1
94
+ #define HAVE_SIGACTION 1
95
+ #define HAVE_SIGNAL_H 1
96
+ #define HAVE_STATFS 1
97
+ #define HAVE_STDARG_H 1
98
+ #define HAVE_STDINT_H 1
99
+ #define HAVE_STDLIB_H 1
100
+ #define HAVE_STRCHR 1
101
+ #define HAVE_STRDUP 1
102
+ #define HAVE_STRERROR 1
103
+ #define HAVE_STRERROR_R 1
104
+ #define HAVE_STRFTIME 1
105
+ #define HAVE_STRINGS_H 1
106
+ #define HAVE_STRING_H 1
107
+ #define HAVE_STRRCHR 1
108
+ #define HAVE_STRUCT_STAT_ST_BLKSIZE 1
109
+ /* Darwin uses struct timespec (st_atimespec etc.), not st_*time_nsec */
110
+ #define HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC 1
111
+ #define HAVE_STRUCT_STAT_ST_MTIME_NSEC 0
112
+ #define HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC 1
113
+ #define HAVE_STRUCT_TM_TM_GMTOFF 1
114
+ #define HAVE_SYMLINK 1
115
+ #define HAVE_SYS_CDEFS_H 1
116
+ #define HAVE_SYS_STAT_H 1
117
+ #define HAVE_SYS_TIME_H 1
118
+ #define HAVE_SYS_TYPES_H 1
119
+ #define HAVE_SYS_WAIT_H 1
120
+ #define HAVE_TCGETATTR 1
121
+ #define HAVE_TCSETATTR 1
122
+ #define HAVE_TIME_H 1
123
+ #define HAVE_TZSET 1
124
+ #define HAVE_UINTMAX_T 1
125
+ #define HAVE_UNISTD_H 1
126
+ #define HAVE_UNSETENV 1
127
+ #define HAVE_UNSIGNED_LONG_LONG 1
128
+ #define HAVE_UNSIGNED_LONG_LONG_INT 1
129
+ #define HAVE_UTIME 1
130
+ #define HAVE_UTIMES 1
131
+ #define HAVE_UTIME_H 1
132
+ #define HAVE_VFORK 1
133
+ #define HAVE_VPRINTF 1
134
+ #define HAVE_WCHAR_H 1
135
+ #define HAVE_WCHAR_T 1
136
+ #define HAVE_WCRTOMB 1
137
+ #define HAVE_WCSCMP 1
138
+ #define HAVE_WCSCPY 1
139
+ #define HAVE_WCSLEN 1
140
+ #define HAVE_WCTOMB 1
141
+ #define HAVE_WCTYPE_H 1
142
+ #define HAVE_WMEMCMP 1
143
+ #define HAVE_WMEMCPY 1
144
+ #define HAVE_ARC4RANDOM_BUF 1
145
+ #define HAVE_ZLIB_H 1
146
+ #define LSTAT_FOLLOWS_SLASHED_SYMLINK 1
147
+ #define STDC_HEADERS 1
148
+ /* macOS/iOS use XSI strerror_r (returns int), not GNU (returns char*) */
149
+ #define STRERROR_R_CHAR_P 0
150
+ /* wchar_t size: 4 on iOS/ARM, 4 on macOS ARM, 4 on Intel */
151
+ #define SIZEOF_WCHAR_T 4
152
+
153
+ #endif
@@ -1,18 +1,18 @@
1
- #ifndef SHERPA_ONNX_COMMON_H
2
- #define SHERPA_ONNX_COMMON_H
3
-
4
- #include <string>
5
-
6
- namespace sherpaonnx {
7
-
8
- /**
9
- * Information about a detected model.
10
- */
11
- struct DetectedModel {
12
- std::string type; // Model type (e.g., "transducer", "paraformer", "nemo_ctc")
13
- std::string modelDir; // Directory path where the model is located
14
- };
15
-
16
- } // namespace sherpaonnx
17
-
18
- #endif // SHERPA_ONNX_COMMON_H
1
+ #ifndef SHERPA_ONNX_COMMON_H
2
+ #define SHERPA_ONNX_COMMON_H
3
+
4
+ #include <string>
5
+
6
+ namespace sherpaonnx {
7
+
8
+ /**
9
+ * Information about a detected model.
10
+ */
11
+ struct DetectedModel {
12
+ std::string type; // Model type (e.g., "transducer", "paraformer", "nemo_ctc")
13
+ std::string modelDir; // Directory path where the model is located
14
+ };
15
+
16
+ } // namespace sherpaonnx
17
+
18
+ #endif // SHERPA_ONNX_COMMON_H
@@ -0,0 +1,49 @@
1
+ #ifndef SHERPA_ONNX_MODEL_DETECT_HELPER_H
2
+ #define SHERPA_ONNX_MODEL_DETECT_HELPER_H
3
+
4
+ #include <cstdint>
5
+ #include <optional>
6
+ #include <string>
7
+ #include <vector>
8
+
9
+ namespace sherpaonnx {
10
+ namespace model_detect {
11
+
12
+ struct FileEntry {
13
+ std::string path;
14
+ std::string nameLower;
15
+ std::uint64_t size = 0;
16
+ };
17
+
18
+ bool FileExists(const std::string& path);
19
+ bool IsDirectory(const std::string& path);
20
+ std::vector<std::string> ListDirectories(const std::string& path);
21
+ std::vector<FileEntry> ListFiles(const std::string& path);
22
+ std::vector<FileEntry> ListFilesRecursive(const std::string& path, int maxDepth);
23
+ std::string ToLower(std::string value);
24
+ std::string ResolveTokenizerDir(const std::string& modelDir);
25
+
26
+ std::string FindFileByName(const std::string& baseDir, const std::string& fileName, int maxDepth);
27
+ /** Find file whose name equals or ends with suffix (e.g. tokens.txt, tiny-tokens.txt) in a pre-built file list. */
28
+ std::string FindFileEndingWith(const std::vector<FileEntry>& files, const std::string& suffix);
29
+ std::string FindDirectoryByName(const std::string& baseDir, const std::string& dirName, int maxDepth);
30
+
31
+ std::string FindOnnxByToken(
32
+ const std::vector<FileEntry>& files,
33
+ const std::string& token,
34
+ const std::optional<bool>& preferInt8
35
+ );
36
+ std::string FindOnnxByAnyToken(
37
+ const std::vector<FileEntry>& files,
38
+ const std::vector<std::string>& tokens,
39
+ const std::optional<bool>& preferInt8
40
+ );
41
+ std::string FindLargestOnnxExcludingTokens(
42
+ const std::vector<FileEntry>& files,
43
+ const std::vector<std::string>& excludeTokens
44
+ );
45
+
46
+ } // namespace model_detect
47
+ } // namespace sherpaonnx
48
+
49
+ #endif // SHERPA_ONNX_MODEL_DETECT_HELPER_H