@mentra/bluetooth-sdk 0.1.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 (278) hide show
  1. package/README.md +278 -0
  2. package/android/build.gradle +167 -0
  3. package/android/lc3Lib/CMakeLists.txt +6 -0
  4. package/android/lc3Lib/build.gradle +109 -0
  5. package/android/lc3Lib/proguard-rules.pro +33 -0
  6. package/android/lc3Lib/src/main/AndroidManifest.xml +2 -0
  7. package/android/lc3Lib/src/main/cpp/CMakeLists.txt +8 -0
  8. package/android/lc3Lib/src/main/cpp/google_opus_stuff/CMakeLists.txt +30 -0
  9. package/android/lc3Lib/src/main/cpp/google_opus_stuff/jni/CMakeLists.txt +7 -0
  10. package/android/lc3Lib/src/main/cpp/google_opus_stuff/jni/ogg_opus_encoder.cc +96 -0
  11. package/android/lc3Lib/src/main/cpp/google_opus_stuff/jni/ogg_opus_encoder.h +53 -0
  12. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/Makefile.am +6 -0
  13. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/config_types.h +26 -0
  14. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/config_types.h.in +26 -0
  15. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/ogg.h +209 -0
  16. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libogg/os_types.h +158 -0
  17. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus.h +981 -0
  18. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_custom.h +342 -0
  19. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_defines.h +799 -0
  20. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_multistream.h +660 -0
  21. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_projection.h +568 -0
  22. package/android/lc3Lib/src/main/cpp/google_opus_stuff/libopus/opus_types.h +166 -0
  23. package/android/lc3Lib/src/main/cpp/google_opus_stuff/ogg_opus_encoder.cc +268 -0
  24. package/android/lc3Lib/src/main/cpp/google_opus_stuff/ogg_opus_encoder.h +115 -0
  25. package/android/lc3Lib/src/main/cpp/google_opus_stuff/opus_tools/opus_header.h +59 -0
  26. package/android/lc3Lib/src/main/cpp/liblc3/CMakeLists.txt +38 -0
  27. package/android/lc3Lib/src/main/cpp/liblc3/include/lc3.h +309 -0
  28. package/android/lc3Lib/src/main/cpp/liblc3/include/lc3_private.h +162 -0
  29. package/android/lc3Lib/src/main/cpp/liblc3/include/rnnoise.h +114 -0
  30. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/CMakeLists.txt +19 -0
  31. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/attdet.c +92 -0
  32. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/attdet.h +44 -0
  33. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/bits.c +375 -0
  34. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/bits.h +315 -0
  35. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/bwdet.c +129 -0
  36. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/bwdet.h +69 -0
  37. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/common.h +148 -0
  38. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/energy.c +70 -0
  39. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/energy.h +43 -0
  40. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/fastmath.h +158 -0
  41. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/lc3.c +702 -0
  42. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/ltpf.c +893 -0
  43. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/ltpf.h +111 -0
  44. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/ltpf_arm.h +506 -0
  45. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/ltpf_neon.h +281 -0
  46. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/makefile.mk +35 -0
  47. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/mdct.c +452 -0
  48. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/mdct.h +57 -0
  49. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/mdct_neon.h +296 -0
  50. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/meson.build +46 -0
  51. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/plc.c +61 -0
  52. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/plc.h +57 -0
  53. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/sns.c +880 -0
  54. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/sns.h +103 -0
  55. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/spec.c +904 -0
  56. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/spec.h +119 -0
  57. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/tables.c +3457 -0
  58. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/tables.h +94 -0
  59. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/tns.c +457 -0
  60. package/android/lc3Lib/src/main/cpp/liblc3/liblc3/tns.h +99 -0
  61. package/android/lc3Lib/src/main/cpp/liblc3/liblc3.cpp +159 -0
  62. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/_kiss_fft_guts.h +182 -0
  63. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/arch.h +261 -0
  64. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/celt_lpc.c +279 -0
  65. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/celt_lpc.h +59 -0
  66. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/common.h +48 -0
  67. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/compile.sh +3 -0
  68. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/denoise.c +646 -0
  69. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/kiss_fft.c +601 -0
  70. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/kiss_fft.h +203 -0
  71. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/opus_types.h +159 -0
  72. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/pitch.c +526 -0
  73. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/pitch.h +149 -0
  74. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn.c +178 -0
  75. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn.h +69 -0
  76. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn_data.c +11051 -0
  77. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn_data.h +34 -0
  78. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn_reader.c +168 -0
  79. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/rnn_train.py +66 -0
  80. package/android/lc3Lib/src/main/cpp/liblc3/rnnoise/tansig_table.h +45 -0
  81. package/android/lc3Lib/src/main/java/com/mentra/lc3Lib/Lc3Cpp.java +38 -0
  82. package/android/lc3Lib/third_party/CMakeLists.txt +23 -0
  83. package/android/lc3Lib/third_party/CMakeLists_libogg.txt +18 -0
  84. package/android/lc3Lib/third_party/CMakeLists_libopus.txt +18 -0
  85. package/android/lc3Lib/third_party/CMakeLists_opus-tools.txt +23 -0
  86. package/android/lc3Lib/third_party/opus_tools/src/AUTHORS +5 -0
  87. package/android/lc3Lib/third_party/opus_tools/src/CMakeLists.txt +4 -0
  88. package/android/lc3Lib/third_party/opus_tools/src/COPYING +371 -0
  89. package/android/lc3Lib/third_party/opus_tools/src/ChangeLog +3 -0
  90. package/android/lc3Lib/third_party/opus_tools/src/Makefile.am +42 -0
  91. package/android/lc3Lib/third_party/opus_tools/src/Makefile.unix +23 -0
  92. package/android/lc3Lib/third_party/opus_tools/src/NEWS +0 -0
  93. package/android/lc3Lib/third_party/opus_tools/src/README +0 -0
  94. package/android/lc3Lib/third_party/opus_tools/src/autogen.sh +115 -0
  95. package/android/lc3Lib/third_party/opus_tools/src/configure.ac +293 -0
  96. package/android/lc3Lib/third_party/opus_tools/src/src/arch.h +239 -0
  97. package/android/lc3Lib/third_party/opus_tools/src/src/audio-in.c +1046 -0
  98. package/android/lc3Lib/third_party/opus_tools/src/src/diag_range.c +245 -0
  99. package/android/lc3Lib/third_party/opus_tools/src/src/diag_range.h +28 -0
  100. package/android/lc3Lib/third_party/opus_tools/src/src/info_opus.c +320 -0
  101. package/android/lc3Lib/third_party/opus_tools/src/src/info_opus.h +51 -0
  102. package/android/lc3Lib/third_party/opus_tools/src/src/lpc.c +157 -0
  103. package/android/lc3Lib/third_party/opus_tools/src/src/lpc.h +27 -0
  104. package/android/lc3Lib/third_party/opus_tools/src/src/opus_header.c +286 -0
  105. package/android/lc3Lib/third_party/opus_tools/src/src/opus_header.h +59 -0
  106. package/android/lc3Lib/third_party/opus_tools/src/src/opusdec.c +884 -0
  107. package/android/lc3Lib/third_party/opus_tools/src/src/opusenc.c +1021 -0
  108. package/android/lc3Lib/third_party/opus_tools/src/src/opusenc.h +101 -0
  109. package/android/lc3Lib/third_party/opus_tools/src/src/opusinfo.c +639 -0
  110. package/android/lc3Lib/third_party/opus_tools/src/src/opusinfo.h +51 -0
  111. package/android/lc3Lib/third_party/opus_tools/src/src/os_support.h +167 -0
  112. package/android/lc3Lib/third_party/opus_tools/src/src/resample.c +1137 -0
  113. package/android/lc3Lib/third_party/opus_tools/src/src/speex_resampler.h +344 -0
  114. package/android/lc3Lib/third_party/opus_tools/src/src/stack_alloc.h +115 -0
  115. package/android/lc3Lib/third_party/opus_tools/src/src/wav_io.c +125 -0
  116. package/android/lc3Lib/third_party/opus_tools/src/src/wav_io.h +62 -0
  117. package/android/lc3Lib/third_party/opus_tools/src/src/wave_out.c +223 -0
  118. package/android/lc3Lib/third_party/opus_tools/src/src/wave_out.h +60 -0
  119. package/android/settings.gradle +1 -0
  120. package/android/src/main/AndroidManifest.xml +40 -0
  121. package/android/src/main/java/com/mentra/bluetoothsdk/BluetoothSdkModule.kt +528 -0
  122. package/android/src/main/java/com/mentra/bluetoothsdk/Bridge.kt +610 -0
  123. package/android/src/main/java/com/mentra/bluetoothsdk/DeviceManager.kt +1616 -0
  124. package/android/src/main/java/com/mentra/bluetoothsdk/DeviceStore.kt +314 -0
  125. package/android/src/main/java/com/mentra/bluetoothsdk/MentraBluetoothModels.kt +1710 -0
  126. package/android/src/main/java/com/mentra/bluetoothsdk/MentraBluetoothSdk.kt +554 -0
  127. package/android/src/main/java/com/mentra/bluetoothsdk/ObservableStore.kt +68 -0
  128. package/android/src/main/java/com/mentra/bluetoothsdk/controllers/ControllerManager.kt +158 -0
  129. package/android/src/main/java/com/mentra/bluetoothsdk/controllers/R1.kt +934 -0
  130. package/android/src/main/java/com/mentra/bluetoothsdk/services/Foreground.kt +175 -0
  131. package/android/src/main/java/com/mentra/bluetoothsdk/services/PhoneMic.kt +1109 -0
  132. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/G1.java +3974 -0
  133. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/G2.kt +3551 -0
  134. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/Mach1.java +1327 -0
  135. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraLive.java +6959 -0
  136. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraNex.kt +1655 -0
  137. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/MentraosBle.java +53675 -0
  138. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/SGCManager.kt +202 -0
  139. package/android/src/main/java/com/mentra/bluetoothsdk/sgcs/Simulated.kt +224 -0
  140. package/android/src/main/java/com/mentra/bluetoothsdk/stt/STTTools.kt +340 -0
  141. package/android/src/main/java/com/mentra/bluetoothsdk/stt/SherpaOnnxTranscriber.kt +465 -0
  142. package/android/src/main/java/com/mentra/bluetoothsdk/stt/VadGateSpeechPolicy.kt +221 -0
  143. package/android/src/main/java/com/mentra/bluetoothsdk/utils/AES.java +106 -0
  144. package/android/src/main/java/com/mentra/bluetoothsdk/utils/AudioSessionMonitor.kt +189 -0
  145. package/android/src/main/java/com/mentra/bluetoothsdk/utils/BitmapJavaUtils.java +169 -0
  146. package/android/src/main/java/com/mentra/bluetoothsdk/utils/BlePhotoUploadService.java +179 -0
  147. package/android/src/main/java/com/mentra/bluetoothsdk/utils/Constants.kt +44 -0
  148. package/android/src/main/java/com/mentra/bluetoothsdk/utils/G1Text.kt +436 -0
  149. package/android/src/main/java/com/mentra/bluetoothsdk/utils/IncidentLogBleRelayNaming.java +29 -0
  150. package/android/src/main/java/com/mentra/bluetoothsdk/utils/IncidentLogBleUploadService.java +76 -0
  151. package/android/src/main/java/com/mentra/bluetoothsdk/utils/K900ProtocolUtils.java +791 -0
  152. package/android/src/main/java/com/mentra/bluetoothsdk/utils/MessageChunker.java +186 -0
  153. package/android/src/main/java/com/mentra/bluetoothsdk/utils/NexSGCUtils.kt +589 -0
  154. package/android/src/main/java/com/mentra/bluetoothsdk/utils/PhoneAudioMonitor.kt +303 -0
  155. package/android/src/main/java/com/mentra/bluetoothsdk/utils/SmartGlassesConnectionState.java +9 -0
  156. package/android/src/main/java/com/mentra/bluetoothsdk/utils/audio/ByteUtilAudioPlayer.java +655 -0
  157. package/android/src/main/java/com/mentra/bluetoothsdk/utils/audio/Lc3Player.java +441 -0
  158. package/android/src/main/java/com/mentra/bluetoothsdk/utils/audio/PCMAudioPlayer.java +431 -0
  159. package/android/src/main/res/values/strings.xml +4 -0
  160. package/app.plugin.js +1 -0
  161. package/build/BluetoothSdk.types.d.ts +498 -0
  162. package/build/BluetoothSdk.types.d.ts.map +1 -0
  163. package/build/BluetoothSdk.types.js +23 -0
  164. package/build/BluetoothSdk.types.js.map +1 -0
  165. package/build/BluetoothSdkModule.d.ts +71 -0
  166. package/build/BluetoothSdkModule.d.ts.map +1 -0
  167. package/build/BluetoothSdkModule.js +106 -0
  168. package/build/BluetoothSdkModule.js.map +1 -0
  169. package/build/index.d.ts +3 -0
  170. package/build/index.d.ts.map +1 -0
  171. package/build/index.js +5 -0
  172. package/build/index.js.map +1 -0
  173. package/expo-module.config.json +9 -0
  174. package/ios/BluetoothSdkModule.swift +665 -0
  175. package/ios/MentraBluetoothSDK.podspec +77 -0
  176. package/ios/Packages/CoreObjC/CoreObjC.xcodeproj/project.pbxproj +213 -0
  177. package/ios/Packages/CoreObjC/PcmConverter.h +22 -0
  178. package/ios/Packages/CoreObjC/PcmConverter.m +266 -0
  179. package/ios/Packages/CoreObjC/attdet.c +92 -0
  180. package/ios/Packages/CoreObjC/attdet.h +44 -0
  181. package/ios/Packages/CoreObjC/bits.c +375 -0
  182. package/ios/Packages/CoreObjC/bits.h +315 -0
  183. package/ios/Packages/CoreObjC/bwdet.c +129 -0
  184. package/ios/Packages/CoreObjC/bwdet.h +69 -0
  185. package/ios/Packages/CoreObjC/common.h +151 -0
  186. package/ios/Packages/CoreObjC/energy.c +70 -0
  187. package/ios/Packages/CoreObjC/energy.h +43 -0
  188. package/ios/Packages/CoreObjC/fastmath.h +158 -0
  189. package/ios/Packages/CoreObjC/lc3.c +704 -0
  190. package/ios/Packages/CoreObjC/lc3.h +313 -0
  191. package/ios/Packages/CoreObjC/lc3_cpp.h +283 -0
  192. package/ios/Packages/CoreObjC/lc3_private.h +163 -0
  193. package/ios/Packages/CoreObjC/ltpf.c +905 -0
  194. package/ios/Packages/CoreObjC/ltpf.h +111 -0
  195. package/ios/Packages/CoreObjC/ltpf_arm.h +506 -0
  196. package/ios/Packages/CoreObjC/ltpf_neon.h +281 -0
  197. package/ios/Packages/CoreObjC/makefile.mk +35 -0
  198. package/ios/Packages/CoreObjC/mdct.c +469 -0
  199. package/ios/Packages/CoreObjC/mdct.h +57 -0
  200. package/ios/Packages/CoreObjC/mdct_neon.h +296 -0
  201. package/ios/Packages/CoreObjC/meson.build +61 -0
  202. package/ios/Packages/CoreObjC/plc.c +61 -0
  203. package/ios/Packages/CoreObjC/plc.h +57 -0
  204. package/ios/Packages/CoreObjC/rnnoise.h +114 -0
  205. package/ios/Packages/CoreObjC/sns.c +880 -0
  206. package/ios/Packages/CoreObjC/sns.h +103 -0
  207. package/ios/Packages/CoreObjC/spec.c +907 -0
  208. package/ios/Packages/CoreObjC/spec.h +119 -0
  209. package/ios/Packages/CoreObjC/tables.c +3457 -0
  210. package/ios/Packages/CoreObjC/tables.h +94 -0
  211. package/ios/Packages/CoreObjC/tns.c +457 -0
  212. package/ios/Packages/CoreObjC/tns.h +99 -0
  213. package/ios/Packages/SherpaOnnx/Model/joiner.onnx +0 -0
  214. package/ios/Packages/SherpaOnnx/Model/tokens.txt +502 -0
  215. package/ios/Packages/SherpaOnnx/SherpaOnnx.swift +1659 -0
  216. package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/Headers/cargs.h +162 -0
  217. package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/Headers/sherpa-onnx/c-api/c-api.h +1852 -0
  218. package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/Headers/sherpa-onnx/c-api/cxx-api.h +674 -0
  219. package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/Info.plist +44 -0
  220. package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64/libsherpa-onnx.a +0 -0
  221. package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64/sherpa-onnx.a +0 -0
  222. package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64_x86_64-simulator/libsherpa-onnx.a +0 -0
  223. package/ios/Packages/SherpaOnnx/sherpa-onnx.xcframework/ios-arm64_x86_64-simulator/sherpa-onnx.a +0 -0
  224. package/ios/Packages/VAD/Common/VAD/VADQuality.swift +41 -0
  225. package/ios/Packages/VAD/Common/VAD/VADState.swift +26 -0
  226. package/ios/Packages/VAD/Common/VAD/VADStrategy.swift +29 -0
  227. package/ios/Packages/VAD/Common/VAD/VADType.swift +14 -0
  228. package/ios/Packages/VAD/Data/Configuration.swift +68 -0
  229. package/ios/Packages/VAD/Data/FrameSize.swift +39 -0
  230. package/ios/Packages/VAD/Data/Record.swift +13 -0
  231. package/ios/Packages/VAD/Data/Result.swift +22 -0
  232. package/ios/Packages/VAD/Data/SampleRate.swift +48 -0
  233. package/ios/Packages/VAD/Silero/Model/silero_vad.onnx +0 -0
  234. package/ios/Packages/VAD/Silero/SileroVAD.swift +284 -0
  235. package/ios/Packages/VAD/Silero/SileroVADStrategy.swift +64 -0
  236. package/ios/Packages/libbz2/module.modulemap +5 -0
  237. package/ios/Packages/libbz2/shim.h +1 -0
  238. package/ios/Source/Bridge.swift +353 -0
  239. package/ios/Source/Bridging-Header.h +16 -0
  240. package/ios/Source/DeviceManager.swift +1478 -0
  241. package/ios/Source/DeviceStore.swift +295 -0
  242. package/ios/Source/MentraBluetoothSDK.swift +2439 -0
  243. package/ios/Source/ObservableStore.swift +88 -0
  244. package/ios/Source/PrivacyInfo.xcprivacy +23 -0
  245. package/ios/Source/controllers/ControllerManager.swift +187 -0
  246. package/ios/Source/controllers/R1.swift +827 -0
  247. package/ios/Source/services/PhoneMic.swift +662 -0
  248. package/ios/Source/sgcs/Frame.swift +651 -0
  249. package/ios/Source/sgcs/G1.swift +2505 -0
  250. package/ios/Source/sgcs/G2.swift +3730 -0
  251. package/ios/Source/sgcs/Mach1.swift +543 -0
  252. package/ios/Source/sgcs/MentraLive.swift +4708 -0
  253. package/ios/Source/sgcs/MentraNex.swift +2479 -0
  254. package/ios/Source/sgcs/SGCManager.swift +243 -0
  255. package/ios/Source/sgcs/Simulated.swift +270 -0
  256. package/ios/Source/sgcs/mentraos_ble.pb.swift +3811 -0
  257. package/ios/Source/stt/STTTools.swift +154 -0
  258. package/ios/Source/stt/SherpaOnnxTranscriber.swift +401 -0
  259. package/ios/Source/utils/AudioSessionMonitor.swift +283 -0
  260. package/ios/Source/utils/Constants.swift +74 -0
  261. package/ios/Source/utils/Enums.swift +95 -0
  262. package/ios/Source/utils/G1Text.swift +2067 -0
  263. package/ios/Source/utils/JSCExperiment.swift +241 -0
  264. package/ios/Source/utils/MemoryMonitor.swift +44 -0
  265. package/ios/Source/utils/MessageChunker.swift +164 -0
  266. package/ios/Source/utils/Models.swift +135 -0
  267. package/ios/Source/utils/PhoneAudioMonitor.swift +226 -0
  268. package/ios/Source/utils/TarBz2Extractor.swift +206 -0
  269. package/package.json +78 -0
  270. package/plugin/build/index.d.ts +6 -0
  271. package/plugin/build/index.js +12 -0
  272. package/plugin/build/withAndroid.d.ts +4 -0
  273. package/plugin/build/withAndroid.js +80 -0
  274. package/plugin/build/withIos.d.ts +4 -0
  275. package/plugin/build/withIos.js +64 -0
  276. package/src/BluetoothSdk.types.ts +581 -0
  277. package/src/BluetoothSdkModule.ts +259 -0
  278. package/src/index.ts +4 -0
@@ -0,0 +1,154 @@
1
+ import Foundation
2
+
3
+ class STTTools {
4
+ // MARK: - SherpaOnnxTranscriber / STT Model Management
5
+
6
+ static func didReceivePartialTranscription(_ text: String) {
7
+ // Send partial result to server witgetConnectedBluetoothNameh proper formatting
8
+ let transcriptionLanguage =
9
+ UserDefaults.standard.string(forKey: "STTModelLanguageCode") ?? "en-US"
10
+ Bridge.log("Mentra: Sending partial transcription: \(text), \(transcriptionLanguage)")
11
+ let transcription: [String: Any] = [
12
+ "type": "local_transcription",
13
+ "text": transcriptionLanguage == "en-US" ? text.lowercased() : text,
14
+ "isFinal": false,
15
+ "startTime": Int(Date().timeIntervalSince1970 * 1000) - 1000, // 1 second ago
16
+ "endTime": Int(Date().timeIntervalSince1970 * 1000),
17
+ "speakerId": 0,
18
+ "transcribeLanguage": transcriptionLanguage,
19
+ "provider": "sherpa-onnx",
20
+ ]
21
+
22
+ Bridge.sendLocalTranscription(transcription: transcription)
23
+ }
24
+
25
+ static func didReceiveFinalTranscription(_ text: String) {
26
+ // Send final result to server with proper formatting
27
+ let transcriptionLanguage =
28
+ UserDefaults.standard.string(forKey: "STTModelLanguageCode") ?? "en-US"
29
+ Bridge.log("Mentra: Sending final transcription: \(text), \(transcriptionLanguage)")
30
+ if !text.isEmpty {
31
+ let transcription: [String: Any] = [
32
+ "type": "local_transcription",
33
+ "text": transcriptionLanguage == "en-US" ? text.lowercased() : text,
34
+ "isFinal": true,
35
+ "startTime": Int(Date().timeIntervalSince1970 * 1000) - 2000, // 2 seconds ago
36
+ "endTime": Int(Date().timeIntervalSince1970 * 1000),
37
+ "speakerId": 0,
38
+ "transcribeLanguage": transcriptionLanguage,
39
+ "provider": "sherpa-onnx",
40
+ ]
41
+
42
+ Bridge.sendLocalTranscription(transcription: transcription)
43
+ }
44
+ }
45
+
46
+ static func setSttModelDetails(_ path: String, _ languageCode: String) {
47
+ UserDefaults.standard.set(path, forKey: "STTModelPath")
48
+ UserDefaults.standard.set(languageCode, forKey: "STTModelLanguageCode")
49
+ UserDefaults.standard.synchronize()
50
+ }
51
+
52
+ static func getSttModelPath() -> String {
53
+ return UserDefaults.standard.string(forKey: "STTModelPath") ?? ""
54
+ }
55
+
56
+ static func checkSTTModelAvailable() -> Bool {
57
+ guard let modelPath = UserDefaults.standard.string(forKey: "STTModelPath") else {
58
+ return false
59
+ }
60
+
61
+ let fileManager = FileManager.default
62
+
63
+ // Check for tokens.txt (required for all models)
64
+ let tokensPath = (modelPath as NSString).appendingPathComponent("tokens.txt")
65
+ if !fileManager.fileExists(atPath: tokensPath) {
66
+ return false
67
+ }
68
+
69
+ // Check for CTC model
70
+ let ctcModelPath = (modelPath as NSString).appendingPathComponent("model.int8.onnx")
71
+ if fileManager.fileExists(atPath: ctcModelPath) {
72
+ return true
73
+ }
74
+
75
+ // Check for transducer model
76
+ let transducerFiles = ["encoder.onnx", "decoder.onnx", "joiner.onnx"]
77
+ for file in transducerFiles {
78
+ let filePath = (modelPath as NSString).appendingPathComponent(file)
79
+ if !fileManager.fileExists(atPath: filePath) {
80
+ return false
81
+ }
82
+ }
83
+
84
+ return true
85
+ }
86
+
87
+ static func validateSTTModel(_ path: String) -> Bool {
88
+ // do {
89
+ let fileManager = FileManager.default
90
+
91
+ // Check for tokens.txt (required for all models)
92
+ let tokensPath = (path as NSString).appendingPathComponent("tokens.txt")
93
+ if !fileManager.fileExists(atPath: tokensPath) {
94
+ return false
95
+ }
96
+
97
+ // Check for CTC model
98
+ let ctcModelPath = (path as NSString).appendingPathComponent("model.int8.onnx")
99
+ if fileManager.fileExists(atPath: ctcModelPath) {
100
+ return true
101
+ }
102
+
103
+ // Check for transducer model
104
+ let transducerFiles = ["encoder.onnx", "decoder.onnx", "joiner.onnx"]
105
+ var allTransducerFilesPresent = true
106
+
107
+ for file in transducerFiles {
108
+ let filePath = (path as NSString).appendingPathComponent(file)
109
+ if !fileManager.fileExists(atPath: filePath) {
110
+ allTransducerFilesPresent = false
111
+ break
112
+ }
113
+ }
114
+
115
+ return allTransducerFilesPresent
116
+ // } catch {
117
+ // Bridge.log("STT_ERROR: \(error.localizedDescription)")
118
+ // return false
119
+ // }
120
+ }
121
+
122
+ static func extractTarBz2(sourcePath: String, destinationPath: String) -> Bool {
123
+ do {
124
+ let fileManager = FileManager.default
125
+
126
+ // Create destination directory if it doesn't exist
127
+ try fileManager.createDirectory(
128
+ atPath: destinationPath,
129
+ withIntermediateDirectories: true,
130
+ attributes: nil
131
+ )
132
+
133
+ // Use the Swift TarBz2Extractor with SWCompression
134
+ var extractionError: NSError?
135
+ let success = TarBz2Extractor.extractTarBz2From(
136
+ sourcePath,
137
+ to: destinationPath,
138
+ error: &extractionError
139
+ )
140
+
141
+ if !success || extractionError != nil {
142
+ print(
143
+ "EXTRACTION_ERROR: \(extractionError?.localizedDescription ?? "Failed to extract tar.bz2")"
144
+ )
145
+ return false
146
+ }
147
+
148
+ } catch {
149
+ Bridge.log("EXTRACTION_ERROR: \(error.localizedDescription)")
150
+ return false
151
+ }
152
+ return true
153
+ }
154
+ }
@@ -0,0 +1,401 @@
1
+ import Foundation
2
+ import UIKit
3
+
4
+ /**
5
+ * SherpaOnnxTranscriber handles real-time audio transcription using Sherpa-ONNX.
6
+ *
7
+ * It works fully offline and processes PCM audio in real-time to provide partial and final ASR results.
8
+ * This class runs on a background thread, processes short PCM chunks, and emits transcribed text using a delegate.
9
+ */
10
+ class SherpaOnnxTranscriber {
11
+ private static let TAG = "SherpaOnnxTranscriber"
12
+
13
+ private static let SAMPLE_RATE = 16000 // Sherpa-ONNX model's required sample rate
14
+ private static let QUEUE_CAPACITY = 100 // Max number of audio buffers to keep in queue
15
+
16
+ private let pcmQueue = DispatchQueue(label: "com.augmentos.sherpaonnx.pcmQueue", qos: .userInteractive)
17
+ private var pcmBuffers = [Data]()
18
+ private var isRunning = false
19
+ private var processingQueue: DispatchQueue?
20
+ private var processingTask: DispatchWorkItem?
21
+
22
+ /// The underlying Sherpa-ONNX objects
23
+ private var recognizer: SherpaOnnxRecognizer?
24
+
25
+ private var lastPartialResult = ""
26
+
27
+ /// Parent context
28
+ private weak var context: UIViewController?
29
+
30
+ /// Session start time for relative timestamps
31
+ private var transcriptionSessionStart: Date
32
+
33
+ /// Dynamic model path support
34
+ private static var customModelPath: String? {
35
+ guard let storedPath = UserDefaults.standard.string(forKey: "STTModelPath") else {
36
+ return nil
37
+ }
38
+
39
+ // Always resolve current Documents directory
40
+ let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
41
+
42
+ // Extract relative subpath after "Documents/"
43
+ // NOTE: Doing this because the application id changes between the development builds and files can't be found.
44
+ if let range = storedPath.range(of: "/Documents/") {
45
+ let relativePath = String(storedPath[range.upperBound...]) // e.g. "stt_models/..."
46
+ let fixedPath = documentsURL.appendingPathComponent(relativePath).path
47
+
48
+ Bridge.log("Reconstructed STTModelPath: \(fixedPath)")
49
+ return fixedPath
50
+ }
51
+
52
+ // If nothing matched, just return as-is
53
+ Bridge.log("STTModelPath (raw): \(storedPath)")
54
+ return storedPath
55
+ }
56
+
57
+ /**
58
+ * Constructor that accepts a UIViewController to load model assets.
59
+ */
60
+ init(context: UIViewController) {
61
+ self.context = context
62
+ transcriptionSessionStart = Date()
63
+ }
64
+
65
+ deinit {
66
+ shutdown()
67
+ }
68
+
69
+ /**
70
+ * Initialize the Sherpa-ONNX recognizer.
71
+ * Loads models and configuration, sets up processing thread.
72
+ */
73
+ func initialize() {
74
+ do {
75
+ var tokensPath: String
76
+ var modelType = "unknown"
77
+ let fileManager = FileManager.default
78
+
79
+ // Check if we have a custom model path set
80
+ if let customPath = SherpaOnnxTranscriber.customModelPath {
81
+ // Detect model type based on available files
82
+ let ctcModelPath = (customPath as NSString).appendingPathComponent("model.int8.onnx")
83
+ let transducerEncoderPath = (customPath as NSString).appendingPathComponent("encoder.onnx")
84
+
85
+ tokensPath = (customPath as NSString).appendingPathComponent("tokens.txt")
86
+
87
+ // Verify tokens file exists
88
+ guard fileManager.fileExists(atPath: tokensPath) else {
89
+ throw NSError(domain: "SherpaOnnxTranscriber", code: 1, userInfo: [
90
+ NSLocalizedDescriptionKey: "tokens.txt not found at path: \(customPath)",
91
+ ])
92
+ }
93
+
94
+ if fileManager.fileExists(atPath: ctcModelPath) {
95
+ // CTC model detected
96
+ modelType = "ctc"
97
+ Bridge.log("Detected CTC model at \(customPath)")
98
+
99
+ // Create CTC model config using Zipformer2Ctc
100
+ var nemoCtc = sherpaOnnxOnlineNemoCtcModelConfig(
101
+ model: ctcModelPath
102
+ )
103
+
104
+ // Create model config with CTC
105
+ var modelConfig = sherpaOnnxOnlineModelConfig(
106
+ tokens: tokensPath,
107
+ numThreads: 1,
108
+ nemoCtc: nemoCtc
109
+ )
110
+
111
+ // Configure recognizer
112
+ var featureConfig = sherpaOnnxFeatureConfig()
113
+
114
+ var config = sherpaOnnxOnlineRecognizerConfig(
115
+ featConfig: featureConfig,
116
+ modelConfig: modelConfig,
117
+ enableEndpoint: true,
118
+ rule1MinTrailingSilence: 1.2,
119
+ rule2MinTrailingSilence: 0.8,
120
+ rule3MinUtteranceLength: 10.0
121
+ )
122
+
123
+ // Create recognizer with the wrapper
124
+ recognizer = SherpaOnnxRecognizer(config: &config)
125
+
126
+ } else if fileManager.fileExists(atPath: transducerEncoderPath) {
127
+ // Transducer model detected
128
+ modelType = "transducer"
129
+ Bridge.log("Detected transducer model at \(customPath)")
130
+
131
+ let decoderPath = (customPath as NSString).appendingPathComponent("decoder.onnx")
132
+ let joinerPath = (customPath as NSString).appendingPathComponent("joiner.onnx")
133
+
134
+ // Verify all transducer files exist
135
+ guard fileManager.fileExists(atPath: decoderPath),
136
+ fileManager.fileExists(atPath: joinerPath)
137
+ else {
138
+ throw NSError(domain: "SherpaOnnxTranscriber", code: 1, userInfo: [
139
+ NSLocalizedDescriptionKey: "Transducer model files incomplete at path: \(customPath)",
140
+ ])
141
+ }
142
+
143
+ // Create Sherpa-ONNX transducer model config
144
+ var transducer = sherpaOnnxOnlineTransducerModelConfig(
145
+ encoder: transducerEncoderPath,
146
+ decoder: decoderPath,
147
+ joiner: joinerPath
148
+ )
149
+
150
+ // Create model config
151
+ var modelConfig = sherpaOnnxOnlineModelConfig(
152
+ tokens: tokensPath,
153
+ transducer: transducer,
154
+ numThreads: 1
155
+ )
156
+
157
+ // Configure recognizer
158
+ var featureConfig = sherpaOnnxFeatureConfig()
159
+
160
+ var config = sherpaOnnxOnlineRecognizerConfig(
161
+ featConfig: featureConfig,
162
+ modelConfig: modelConfig,
163
+ enableEndpoint: true,
164
+ rule1MinTrailingSilence: 1.2,
165
+ rule2MinTrailingSilence: 0.8,
166
+ rule3MinUtteranceLength: 10.0
167
+ )
168
+
169
+ // Create recognizer with the wrapper
170
+ recognizer = SherpaOnnxRecognizer(config: &config)
171
+
172
+ } else {
173
+ throw NSError(domain: "SherpaOnnxTranscriber", code: 1, userInfo: [
174
+ NSLocalizedDescriptionKey: "No valid model files found at path: \(customPath)",
175
+ ])
176
+ }
177
+ } else {
178
+ Bridge.log("No Sherpa ONNX model available. Transcription will be disabled.")
179
+ Bridge.log("Please download a model using the model downloader in settings.")
180
+ recognizer = nil
181
+ isRunning = false
182
+ return
183
+ }
184
+
185
+ if recognizer == nil {
186
+ throw NSError(domain: "SherpaOnnxTranscriber", code: 2, userInfo: [NSLocalizedDescriptionKey: "Failed to create recognizer"])
187
+ }
188
+
189
+ startProcessingTask()
190
+ isRunning = true
191
+
192
+ Bridge.log("Sherpa-ONNX ASR initialized successfully with \(modelType) model")
193
+
194
+ } catch {
195
+ Bridge.log("Failed to initialize Sherpa-ONNX: \(error.localizedDescription)")
196
+ }
197
+ }
198
+
199
+ /**
200
+ * Handle transcription results - send only to delegate
201
+ */
202
+ private func handleTranscriptionResult(text: String, isFinal: Bool) {
203
+ // Forward to delegate if set
204
+ DispatchQueue.main.async { [weak self] in
205
+ if isFinal {
206
+ STTTools.didReceiveFinalTranscription(text)
207
+ } else {
208
+ STTTools.didReceivePartialTranscription(text)
209
+ }
210
+ }
211
+ }
212
+
213
+ /**
214
+ * Feed PCM audio data (16-bit little endian) into the transcriber.
215
+ * This method should be called continuously with short chunks (e.g., 100-300ms).
216
+ *
217
+ * Note: Audio passed to this method is assumed to have already passed VAD elsewhere,
218
+ * so it's directly queued for processing without additional VAD checks.
219
+ */
220
+ func acceptAudio(pcm16le: Data) {
221
+ guard isRunning else {
222
+ return
223
+ }
224
+
225
+ // Directly queue the audio data for processing
226
+ // No VAD check here as it's assumed to be done upstream
227
+ queueAudioData(pcm16le)
228
+ }
229
+
230
+ private func queueAudioData(_ pcm16le: Data) {
231
+ pcmQueue.async { [weak self] in
232
+ guard let self = self else { return }
233
+
234
+ let queueSizeBefore = self.pcmBuffers.count
235
+ self.pcmBuffers.append(pcm16le)
236
+
237
+ // Keep queue size manageable
238
+ if self.pcmBuffers.count > Self.QUEUE_CAPACITY {
239
+ let removedBuffer = self.pcmBuffers.removeFirst()
240
+ Bridge.log("โš ๏ธ Audio queue overflow - dropped buffer of \(removedBuffer.count) bytes")
241
+ }
242
+ }
243
+ }
244
+
245
+ /**
246
+ * Start a background task to continuously consume audio and decode using Sherpa.
247
+ */
248
+ private func startProcessingTask() {
249
+ Bridge.log("๐Ÿš€ Starting Sherpa-ONNX processing task...")
250
+
251
+ processingQueue = DispatchQueue(label: "com.augmentos.sherpaonnx.processor", qos: .userInitiated)
252
+
253
+ let workItem = DispatchWorkItem { [weak self] in
254
+ self?.runLoop()
255
+ }
256
+
257
+ processingTask = workItem
258
+ processingQueue?.async(execute: workItem)
259
+ }
260
+
261
+ /**
262
+ * Main processing loop that handles transcription in real-time.
263
+ * Pulls audio from queue, feeds into Sherpa, emits partial/final results.
264
+ */
265
+ private func runLoop() {
266
+ Bridge.log("๐Ÿ”„ Sherpa-ONNX processing loop started")
267
+
268
+ while isRunning {
269
+ // Pull data from queue
270
+ var audioData: Data?
271
+
272
+ pcmQueue.sync {
273
+ if !self.pcmBuffers.isEmpty {
274
+ audioData = self.pcmBuffers.removeFirst()
275
+ }
276
+ }
277
+
278
+ if let data = audioData {
279
+ // Synchronize access to recognizer to prevent race conditions
280
+ objc_sync_enter(self)
281
+ defer { objc_sync_exit(self) }
282
+
283
+ guard let recognizer = recognizer else {
284
+ Bridge.log("โš ๏ธ Recognizer not available, skipping audio chunk")
285
+ continue
286
+ }
287
+
288
+ do {
289
+ // Convert PCM to float [-1.0, 1.0]
290
+ let floatBuf = toFloatArray(from: data)
291
+
292
+ // Pass audio data to the Sherpa-ONNX stream
293
+ recognizer.acceptWaveform(samples: floatBuf, sampleRate: Self.SAMPLE_RATE)
294
+
295
+ // Decode continuously while model is ready
296
+ var decodeCount = 0
297
+ while recognizer.isReady() {
298
+ recognizer.decode()
299
+ decodeCount += 1
300
+ }
301
+
302
+ // If utterance endpoint detected
303
+ if recognizer.isEndpoint() {
304
+ let result = recognizer.getResult()
305
+ let finalText = result.text.trimmingCharacters(in: .whitespacesAndNewlines)
306
+
307
+ if !finalText.isEmpty {
308
+ handleTranscriptionResult(text: finalText, isFinal: true)
309
+ }
310
+
311
+ recognizer.reset() // Start new utterance
312
+ lastPartialResult = ""
313
+ } else {
314
+ // Emit partial results if changed
315
+ let result = recognizer.getResult()
316
+ let partial = result.text.trimmingCharacters(in: .whitespacesAndNewlines)
317
+
318
+ if partial != lastPartialResult, !partial.isEmpty {
319
+ handleTranscriptionResult(text: partial, isFinal: false)
320
+ lastPartialResult = partial
321
+ }
322
+ }
323
+ } catch {
324
+ Bridge.log("โŒ Error processing audio: \(error.localizedDescription)")
325
+ }
326
+ } else {
327
+ // Sleep briefly to avoid tight CPU loop if no audio is available
328
+ Thread.sleep(forTimeInterval: 0.01)
329
+ }
330
+ }
331
+
332
+ Bridge.log("ASR processing thread stopped")
333
+ }
334
+
335
+ /**
336
+ * Convert 16-bit PCM byte data (little-endian) to float array [-1.0, 1.0].
337
+ */
338
+ private func toFloatArray(from pcmData: Data) -> [Float] {
339
+ let count = pcmData.count / 2
340
+ var samples = [Float](repeating: 0, count: count)
341
+
342
+ pcmData.withUnsafeBytes { (bufferPointer: UnsafeRawBufferPointer) in
343
+ if let address = bufferPointer.baseAddress {
344
+ let int16Pointer = address.bindMemory(to: Int16.self, capacity: count)
345
+
346
+ for i in 0 ..< count {
347
+ // Convert from little-endian if needed
348
+ var sample = int16Pointer[i]
349
+ if CFByteOrderGetCurrent() == CFByteOrder(CFByteOrderBigEndian.rawValue) {
350
+ sample = Int16(littleEndian: sample)
351
+ }
352
+ samples[i] = Float(sample) / 32768.0
353
+ }
354
+ }
355
+ }
356
+
357
+ return samples
358
+ }
359
+
360
+ /**
361
+ * Stop transcription processing.
362
+ * This shuts down the processing thread and releases Sherpa-ONNX resources.
363
+ */
364
+ func shutdown() {
365
+ Bridge.log("๐Ÿ›‘ Shutting down SherpaOnnxTranscriber...")
366
+
367
+ isRunning = false
368
+ processingTask?.cancel()
369
+
370
+ // Synchronize access to recognizer during shutdown
371
+ objc_sync_enter(self)
372
+ defer { objc_sync_exit(self) }
373
+
374
+ // The recognizer will be automatically cleaned up by ARC when set to nil
375
+ if recognizer != nil {
376
+ Bridge.log("๐Ÿงน Cleaning up Sherpa-ONNX recognizer")
377
+ recognizer = nil
378
+ }
379
+
380
+ // Clear any remaining audio buffers
381
+ pcmQueue.sync {
382
+ let remainingBuffers = self.pcmBuffers.count
383
+ if remainingBuffers > 0 {
384
+ Bridge.log("๐Ÿ—‘๏ธ Clearing \(remainingBuffers) remaining audio buffers")
385
+ }
386
+ self.pcmBuffers.removeAll()
387
+ }
388
+
389
+ Bridge.log("โœ… SherpaOnnxTranscriber shutdown complete")
390
+ }
391
+
392
+ /**
393
+ * Restarts the transcriber after a model change.
394
+ * Shuts down existing resources, clears buffers, and reinitializes the recognizer.
395
+ */
396
+ func restart() {
397
+ Bridge.log("โ™ป๏ธ Restarting SherpaOnnxTranscriber...")
398
+ shutdown()
399
+ initialize()
400
+ }
401
+ }