@siteed/expo-audio-studio 2.18.6 → 3.0.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 (329) hide show
  1. package/README.md +13 -297
  2. package/index.d.ts +1 -0
  3. package/index.js +1 -0
  4. package/package.json +6 -135
  5. package/CHANGELOG.md +0 -501
  6. package/LICENSE +0 -21
  7. package/android/build.gradle +0 -129
  8. package/android/src/androidTest/assets/chorus.wav +0 -0
  9. package/android/src/androidTest/assets/jfk.wav +0 -0
  10. package/android/src/androidTest/assets/osr_us_000_0010_8k.wav +0 -0
  11. package/android/src/androidTest/assets/recorder_hello_world.wav +0 -0
  12. package/android/src/androidTest/java/net/siteed/audiostream/AudioProcessorInstrumentedTest.kt +0 -197
  13. package/android/src/androidTest/java/net/siteed/audiostream/AudioRecorderInstrumentedTest.kt +0 -541
  14. package/android/src/androidTest/java/net/siteed/audiostream/AudioRecorderPerformanceInstrumentedTest.kt +0 -234
  15. package/android/src/androidTest/java/net/siteed/audiostream/integration/AudioFocusStrategyIntegrationTest.kt +0 -332
  16. package/android/src/androidTest/java/net/siteed/audiostream/integration/BufferDurationIntegrationTest.kt +0 -324
  17. package/android/src/androidTest/java/net/siteed/audiostream/integration/CompressedOnlyOutputTest.kt +0 -253
  18. package/android/src/androidTest/java/net/siteed/audiostream/integration/DeviceDisconnectionFallbackTest.kt +0 -218
  19. package/android/src/androidTest/java/net/siteed/audiostream/integration/EventEmissionIntervalTest.kt +0 -120
  20. package/android/src/androidTest/java/net/siteed/audiostream/integration/M4aFormatTest.kt +0 -345
  21. package/android/src/androidTest/java/net/siteed/audiostream/integration/OutputControlIntegrationTest.kt +0 -340
  22. package/android/src/androidTest/java/net/siteed/audiostream/integration/PcmStreamingDurationTest.kt +0 -252
  23. package/android/src/androidTest/java/net/siteed/audiostream/integration/README.md +0 -95
  24. package/android/src/androidTest/java/net/siteed/audiostream/integration/run_integration_tests.sh +0 -43
  25. package/android/src/main/AndroidManifest.xml +0 -30
  26. package/android/src/main/java/net/siteed/audiostream/AudioAnalysisData.kt +0 -188
  27. package/android/src/main/java/net/siteed/audiostream/AudioDataEncoder.kt +0 -9
  28. package/android/src/main/java/net/siteed/audiostream/AudioDeviceManager.kt +0 -1741
  29. package/android/src/main/java/net/siteed/audiostream/AudioFileHandler.kt +0 -136
  30. package/android/src/main/java/net/siteed/audiostream/AudioFormatUtils.kt +0 -354
  31. package/android/src/main/java/net/siteed/audiostream/AudioNotificationsManager.kt +0 -439
  32. package/android/src/main/java/net/siteed/audiostream/AudioProcessor.kt +0 -2237
  33. package/android/src/main/java/net/siteed/audiostream/AudioRecorderManager.kt +0 -2141
  34. package/android/src/main/java/net/siteed/audiostream/AudioRecordingService.kt +0 -167
  35. package/android/src/main/java/net/siteed/audiostream/AudioTrimmer.kt +0 -1099
  36. package/android/src/main/java/net/siteed/audiostream/Constants.kt +0 -37
  37. package/android/src/main/java/net/siteed/audiostream/EventSender.kt +0 -7
  38. package/android/src/main/java/net/siteed/audiostream/ExpoAudioStreamModule.kt +0 -1113
  39. package/android/src/main/java/net/siteed/audiostream/FFT.kt +0 -99
  40. package/android/src/main/java/net/siteed/audiostream/Features.kt +0 -98
  41. package/android/src/main/java/net/siteed/audiostream/LogUtils.kt +0 -93
  42. package/android/src/main/java/net/siteed/audiostream/NotificationConfig.kt +0 -72
  43. package/android/src/main/java/net/siteed/audiostream/PermissionUtils.kt +0 -68
  44. package/android/src/main/java/net/siteed/audiostream/RecordingActionReceiver.kt +0 -59
  45. package/android/src/main/java/net/siteed/audiostream/RecordingConfig.kt +0 -257
  46. package/android/src/main/java/net/siteed/audiostream/WaveformConfig.kt +0 -19
  47. package/android/src/main/java/net/siteed/audiostream/WaveformRenderer.kt +0 -159
  48. package/android/src/main/res/drawable/ic_default_action_icon.xml +0 -16
  49. package/android/src/main/res/drawable/ic_microphone.xml +0 -13
  50. package/android/src/main/res/drawable/ic_pause.xml +0 -10
  51. package/android/src/main/res/drawable/ic_play.xml +0 -10
  52. package/android/src/main/res/drawable/ic_stop.xml +0 -10
  53. package/android/src/main/res/layout/notification_recording.xml +0 -37
  54. package/android/src/test/java/net/siteed/audiostream/AudioFileHandlerTest.kt +0 -279
  55. package/android/src/test/java/net/siteed/audiostream/AudioFocusStrategyTest.kt +0 -249
  56. package/android/src/test/java/net/siteed/audiostream/AudioFormatTest.kt +0 -151
  57. package/android/src/test/java/net/siteed/audiostream/AudioFormatUtilsTest.kt +0 -273
  58. package/android/src/test/java/net/siteed/audiostream/DeviceDisconnectionFallbackUnitTest.kt +0 -140
  59. package/android/src/test/resources/chorus.wav +0 -0
  60. package/android/src/test/resources/generate_test_audio.py +0 -94
  61. package/android/src/test/resources/jfk.wav +0 -0
  62. package/android/src/test/resources/osr_us_000_0010_8k.wav +0 -0
  63. package/android/src/test/resources/recorder_hello_world.wav +0 -0
  64. package/app.plugin.js +0 -3
  65. package/build/cjs/AudioAnalysis/AudioAnalysis.types.js +0 -4
  66. package/build/cjs/AudioAnalysis/AudioAnalysis.types.js.map +0 -1
  67. package/build/cjs/AudioAnalysis/extractAudioAnalysis.js +0 -210
  68. package/build/cjs/AudioAnalysis/extractAudioAnalysis.js.map +0 -1
  69. package/build/cjs/AudioAnalysis/extractAudioData.js +0 -21
  70. package/build/cjs/AudioAnalysis/extractAudioData.js.map +0 -1
  71. package/build/cjs/AudioAnalysis/extractMelSpectrogram.js +0 -92
  72. package/build/cjs/AudioAnalysis/extractMelSpectrogram.js.map +0 -1
  73. package/build/cjs/AudioAnalysis/extractPreview.js +0 -28
  74. package/build/cjs/AudioAnalysis/extractPreview.js.map +0 -1
  75. package/build/cjs/AudioAnalysis/extractWaveform.js +0 -18
  76. package/build/cjs/AudioAnalysis/extractWaveform.js.map +0 -1
  77. package/build/cjs/AudioDeviceManager.js +0 -689
  78. package/build/cjs/AudioDeviceManager.js.map +0 -1
  79. package/build/cjs/AudioRecorder.provider.js +0 -78
  80. package/build/cjs/AudioRecorder.provider.js.map +0 -1
  81. package/build/cjs/ExpoAudioStream.native.js +0 -8
  82. package/build/cjs/ExpoAudioStream.native.js.map +0 -1
  83. package/build/cjs/ExpoAudioStream.types.js +0 -11
  84. package/build/cjs/ExpoAudioStream.types.js.map +0 -1
  85. package/build/cjs/ExpoAudioStream.web.js +0 -708
  86. package/build/cjs/ExpoAudioStream.web.js.map +0 -1
  87. package/build/cjs/ExpoAudioStreamModule.js +0 -718
  88. package/build/cjs/ExpoAudioStreamModule.js.map +0 -1
  89. package/build/cjs/WebRecorder.web.js +0 -777
  90. package/build/cjs/WebRecorder.web.js.map +0 -1
  91. package/build/cjs/constants/platformLimitations.js +0 -99
  92. package/build/cjs/constants/platformLimitations.js.map +0 -1
  93. package/build/cjs/constants.js +0 -17
  94. package/build/cjs/constants.js.map +0 -1
  95. package/build/cjs/events.js +0 -29
  96. package/build/cjs/events.js.map +0 -1
  97. package/build/cjs/hooks/useAudioDevices.js +0 -179
  98. package/build/cjs/hooks/useAudioDevices.js.map +0 -1
  99. package/build/cjs/index.js +0 -58
  100. package/build/cjs/index.js.map +0 -1
  101. package/build/cjs/trimAudio.js +0 -76
  102. package/build/cjs/trimAudio.js.map +0 -1
  103. package/build/cjs/useAudioRecorder.js +0 -518
  104. package/build/cjs/useAudioRecorder.js.map +0 -1
  105. package/build/cjs/utils/BlobFix.js +0 -502
  106. package/build/cjs/utils/BlobFix.js.map +0 -1
  107. package/build/cjs/utils/audioProcessing.js +0 -136
  108. package/build/cjs/utils/audioProcessing.js.map +0 -1
  109. package/build/cjs/utils/cleanNativeOptions.js +0 -22
  110. package/build/cjs/utils/cleanNativeOptions.js.map +0 -1
  111. package/build/cjs/utils/concatenateBuffers.js +0 -25
  112. package/build/cjs/utils/concatenateBuffers.js.map +0 -1
  113. package/build/cjs/utils/convertPCMToFloat32.js +0 -124
  114. package/build/cjs/utils/convertPCMToFloat32.js.map +0 -1
  115. package/build/cjs/utils/crc32.js +0 -52
  116. package/build/cjs/utils/crc32.js.map +0 -1
  117. package/build/cjs/utils/encodingToBitDepth.js +0 -17
  118. package/build/cjs/utils/encodingToBitDepth.js.map +0 -1
  119. package/build/cjs/utils/getWavFileInfo.js +0 -96
  120. package/build/cjs/utils/getWavFileInfo.js.map +0 -1
  121. package/build/cjs/utils/writeWavHeader.js +0 -88
  122. package/build/cjs/utils/writeWavHeader.js.map +0 -1
  123. package/build/cjs/workers/InlineFeaturesExtractor.web.js +0 -859
  124. package/build/cjs/workers/InlineFeaturesExtractor.web.js.map +0 -1
  125. package/build/cjs/workers/inlineAudioWebWorker.web.js +0 -184
  126. package/build/cjs/workers/inlineAudioWebWorker.web.js.map +0 -1
  127. package/build/esm/AudioAnalysis/AudioAnalysis.types.js +0 -3
  128. package/build/esm/AudioAnalysis/AudioAnalysis.types.js.map +0 -1
  129. package/build/esm/AudioAnalysis/extractAudioAnalysis.js +0 -202
  130. package/build/esm/AudioAnalysis/extractAudioAnalysis.js.map +0 -1
  131. package/build/esm/AudioAnalysis/extractAudioData.js +0 -14
  132. package/build/esm/AudioAnalysis/extractAudioData.js.map +0 -1
  133. package/build/esm/AudioAnalysis/extractMelSpectrogram.js +0 -89
  134. package/build/esm/AudioAnalysis/extractMelSpectrogram.js.map +0 -1
  135. package/build/esm/AudioAnalysis/extractPreview.js +0 -25
  136. package/build/esm/AudioAnalysis/extractPreview.js.map +0 -1
  137. package/build/esm/AudioAnalysis/extractWaveform.js +0 -11
  138. package/build/esm/AudioAnalysis/extractWaveform.js.map +0 -1
  139. package/build/esm/AudioDeviceManager.js +0 -682
  140. package/build/esm/AudioDeviceManager.js.map +0 -1
  141. package/build/esm/AudioRecorder.provider.js +0 -40
  142. package/build/esm/AudioRecorder.provider.js.map +0 -1
  143. package/build/esm/ExpoAudioStream.native.js +0 -6
  144. package/build/esm/ExpoAudioStream.native.js.map +0 -1
  145. package/build/esm/ExpoAudioStream.types.js +0 -8
  146. package/build/esm/ExpoAudioStream.types.js.map +0 -1
  147. package/build/esm/ExpoAudioStream.web.js +0 -704
  148. package/build/esm/ExpoAudioStream.web.js.map +0 -1
  149. package/build/esm/ExpoAudioStreamModule.js +0 -713
  150. package/build/esm/ExpoAudioStreamModule.js.map +0 -1
  151. package/build/esm/WebRecorder.web.js +0 -773
  152. package/build/esm/WebRecorder.web.js.map +0 -1
  153. package/build/esm/constants/platformLimitations.js +0 -90
  154. package/build/esm/constants/platformLimitations.js.map +0 -1
  155. package/build/esm/constants.js +0 -14
  156. package/build/esm/constants.js.map +0 -1
  157. package/build/esm/events.js +0 -21
  158. package/build/esm/events.js.map +0 -1
  159. package/build/esm/hooks/useAudioDevices.js +0 -176
  160. package/build/esm/hooks/useAudioDevices.js.map +0 -1
  161. package/build/esm/index.js +0 -20
  162. package/build/esm/index.js.map +0 -1
  163. package/build/esm/trimAudio.js +0 -69
  164. package/build/esm/trimAudio.js.map +0 -1
  165. package/build/esm/useAudioRecorder.js +0 -512
  166. package/build/esm/useAudioRecorder.js.map +0 -1
  167. package/build/esm/utils/BlobFix.js +0 -498
  168. package/build/esm/utils/BlobFix.js.map +0 -1
  169. package/build/esm/utils/audioProcessing.js +0 -133
  170. package/build/esm/utils/audioProcessing.js.map +0 -1
  171. package/build/esm/utils/cleanNativeOptions.js +0 -19
  172. package/build/esm/utils/cleanNativeOptions.js.map +0 -1
  173. package/build/esm/utils/concatenateBuffers.js +0 -21
  174. package/build/esm/utils/concatenateBuffers.js.map +0 -1
  175. package/build/esm/utils/convertPCMToFloat32.js +0 -120
  176. package/build/esm/utils/convertPCMToFloat32.js.map +0 -1
  177. package/build/esm/utils/crc32.js +0 -50
  178. package/build/esm/utils/crc32.js.map +0 -1
  179. package/build/esm/utils/encodingToBitDepth.js +0 -13
  180. package/build/esm/utils/encodingToBitDepth.js.map +0 -1
  181. package/build/esm/utils/getWavFileInfo.js +0 -92
  182. package/build/esm/utils/getWavFileInfo.js.map +0 -1
  183. package/build/esm/utils/writeWavHeader.js +0 -84
  184. package/build/esm/utils/writeWavHeader.js.map +0 -1
  185. package/build/esm/workers/InlineFeaturesExtractor.web.js +0 -856
  186. package/build/esm/workers/InlineFeaturesExtractor.web.js.map +0 -1
  187. package/build/esm/workers/inlineAudioWebWorker.web.js +0 -181
  188. package/build/esm/workers/inlineAudioWebWorker.web.js.map +0 -1
  189. package/build/types/AudioAnalysis/AudioAnalysis.types.d.ts +0 -196
  190. package/build/types/AudioAnalysis/AudioAnalysis.types.d.ts.map +0 -1
  191. package/build/types/AudioAnalysis/extractAudioAnalysis.d.ts +0 -74
  192. package/build/types/AudioAnalysis/extractAudioAnalysis.d.ts.map +0 -1
  193. package/build/types/AudioAnalysis/extractAudioData.d.ts +0 -3
  194. package/build/types/AudioAnalysis/extractAudioData.d.ts.map +0 -1
  195. package/build/types/AudioAnalysis/extractMelSpectrogram.d.ts +0 -14
  196. package/build/types/AudioAnalysis/extractMelSpectrogram.d.ts.map +0 -1
  197. package/build/types/AudioAnalysis/extractPreview.d.ts +0 -11
  198. package/build/types/AudioAnalysis/extractPreview.d.ts.map +0 -1
  199. package/build/types/AudioAnalysis/extractWaveform.d.ts +0 -8
  200. package/build/types/AudioAnalysis/extractWaveform.d.ts.map +0 -1
  201. package/build/types/AudioDeviceManager.d.ts +0 -187
  202. package/build/types/AudioDeviceManager.d.ts.map +0 -1
  203. package/build/types/AudioRecorder.provider.d.ts +0 -11
  204. package/build/types/AudioRecorder.provider.d.ts.map +0 -1
  205. package/build/types/ExpoAudioStream.native.d.ts +0 -3
  206. package/build/types/ExpoAudioStream.native.d.ts.map +0 -1
  207. package/build/types/ExpoAudioStream.types.d.ts +0 -738
  208. package/build/types/ExpoAudioStream.types.d.ts.map +0 -1
  209. package/build/types/ExpoAudioStream.web.d.ts +0 -96
  210. package/build/types/ExpoAudioStream.web.d.ts.map +0 -1
  211. package/build/types/ExpoAudioStreamModule.d.ts +0 -3
  212. package/build/types/ExpoAudioStreamModule.d.ts.map +0 -1
  213. package/build/types/WebRecorder.web.d.ts +0 -198
  214. package/build/types/WebRecorder.web.d.ts.map +0 -1
  215. package/build/types/constants/platformLimitations.d.ts +0 -40
  216. package/build/types/constants/platformLimitations.d.ts.map +0 -1
  217. package/build/types/constants.d.ts +0 -11
  218. package/build/types/constants.d.ts.map +0 -1
  219. package/build/types/events.d.ts +0 -26
  220. package/build/types/events.d.ts.map +0 -1
  221. package/build/types/hooks/useAudioDevices.d.ts +0 -15
  222. package/build/types/hooks/useAudioDevices.d.ts.map +0 -1
  223. package/build/types/index.d.ts +0 -18
  224. package/build/types/index.d.ts.map +0 -1
  225. package/build/types/trimAudio.d.ts +0 -25
  226. package/build/types/trimAudio.d.ts.map +0 -1
  227. package/build/types/useAudioRecorder.d.ts +0 -22
  228. package/build/types/useAudioRecorder.d.ts.map +0 -1
  229. package/build/types/utils/BlobFix.d.ts +0 -9
  230. package/build/types/utils/BlobFix.d.ts.map +0 -1
  231. package/build/types/utils/audioProcessing.d.ts +0 -24
  232. package/build/types/utils/audioProcessing.d.ts.map +0 -1
  233. package/build/types/utils/cleanNativeOptions.d.ts +0 -15
  234. package/build/types/utils/cleanNativeOptions.d.ts.map +0 -1
  235. package/build/types/utils/concatenateBuffers.d.ts +0 -8
  236. package/build/types/utils/concatenateBuffers.d.ts.map +0 -1
  237. package/build/types/utils/convertPCMToFloat32.d.ts +0 -13
  238. package/build/types/utils/convertPCMToFloat32.d.ts.map +0 -1
  239. package/build/types/utils/crc32.d.ts +0 -7
  240. package/build/types/utils/crc32.d.ts.map +0 -1
  241. package/build/types/utils/encodingToBitDepth.d.ts +0 -5
  242. package/build/types/utils/encodingToBitDepth.d.ts.map +0 -1
  243. package/build/types/utils/getWavFileInfo.d.ts +0 -26
  244. package/build/types/utils/getWavFileInfo.d.ts.map +0 -1
  245. package/build/types/utils/writeWavHeader.d.ts +0 -34
  246. package/build/types/utils/writeWavHeader.d.ts.map +0 -1
  247. package/build/types/workers/InlineFeaturesExtractor.web.d.ts +0 -2
  248. package/build/types/workers/InlineFeaturesExtractor.web.d.ts.map +0 -1
  249. package/build/types/workers/inlineAudioWebWorker.web.d.ts +0 -2
  250. package/build/types/workers/inlineAudioWebWorker.web.d.ts.map +0 -1
  251. package/expo-module.config.json +0 -10
  252. package/ios/AudioAnalysisData.swift +0 -74
  253. package/ios/AudioDeviceManager.swift +0 -670
  254. package/ios/AudioNotificationManager.swift +0 -154
  255. package/ios/AudioProcessingHelpers.swift +0 -743
  256. package/ios/AudioProcessor.swift +0 -1151
  257. package/ios/AudioStreamError.swift +0 -7
  258. package/ios/AudioStreamManager.swift +0 -2369
  259. package/ios/AudioStreamManagerDelegate.swift +0 -16
  260. package/ios/DataPoint.swift +0 -54
  261. package/ios/DecodingConfig.swift +0 -59
  262. package/ios/ExpoAudioStream.podspec +0 -33
  263. package/ios/ExpoAudioStreamModule.swift +0 -1019
  264. package/ios/ExpoAudioStudioTests/AudioFileHandlerTests.swift +0 -338
  265. package/ios/ExpoAudioStudioTests/AudioFormatUtilsTests.swift +0 -331
  266. package/ios/ExpoAudioStudioTests/AudioTestHelpers.swift +0 -130
  267. package/ios/ExpoAudioStudioTests/CompressedOnlyOutputTests.swift +0 -294
  268. package/ios/ExpoAudioStudioTests/EventEmissionIntervalTests.swift +0 -105
  269. package/ios/ExpoAudioStudioTests/Info.plist +0 -22
  270. package/ios/ExpoAudioStudioTests/README.md +0 -39
  271. package/ios/ExpoAudioStudioTests/SimpleAudioTest.swift +0 -98
  272. package/ios/ExpoAudioStudioTests/TestAudioGenerator.swift +0 -75
  273. package/ios/FFT.swift +0 -62
  274. package/ios/Features.swift +0 -95
  275. package/ios/ISSUE_IOS.md +0 -68
  276. package/ios/Logger.swift +0 -39
  277. package/ios/NotificationExtension.swift +0 -15
  278. package/ios/RecordingResult.swift +0 -22
  279. package/ios/RecordingSettings.swift +0 -308
  280. package/ios/WaveformExtractor.swift +0 -105
  281. package/ios/tests/README.md +0 -41
  282. package/ios/tests/integration/buffer_and_fallback_test.swift +0 -178
  283. package/ios/tests/integration/buffer_duration_test.swift +0 -185
  284. package/ios/tests/integration/compressed_only_output_test.swift +0 -271
  285. package/ios/tests/integration/output_control_test.swift +0 -322
  286. package/ios/tests/integration/run_integration_tests.sh +0 -37
  287. package/ios/tests/opus_support_test_macos.swift +0 -154
  288. package/ios/tests/standalone/audio_processing_test.swift +0 -144
  289. package/ios/tests/standalone/audio_recording_test.swift +0 -277
  290. package/ios/tests/standalone/audio_streaming_test.swift +0 -249
  291. package/ios/tests/standalone/standalone_test.swift +0 -144
  292. package/plugin/build/index.cjs +0 -194
  293. package/plugin/build/index.d.cts +0 -22
  294. package/plugin/build/index.js +0 -194
  295. package/plugin/src/index.ts +0 -285
  296. package/plugin/tsconfig.json +0 -10
  297. package/plugin/tsconfig.tsbuildinfo +0 -1
  298. package/src/AudioAnalysis/AudioAnalysis.types.ts +0 -224
  299. package/src/AudioAnalysis/extractAudioAnalysis.ts +0 -344
  300. package/src/AudioAnalysis/extractAudioData.ts +0 -17
  301. package/src/AudioAnalysis/extractMelSpectrogram.ts +0 -154
  302. package/src/AudioAnalysis/extractPreview.ts +0 -34
  303. package/src/AudioAnalysis/extractWaveform.ts +0 -22
  304. package/src/AudioDeviceManager.ts +0 -803
  305. package/src/AudioRecorder.provider.tsx +0 -57
  306. package/src/ExpoAudioStream.native.ts +0 -6
  307. package/src/ExpoAudioStream.types.ts +0 -874
  308. package/src/ExpoAudioStream.web.ts +0 -905
  309. package/src/ExpoAudioStreamModule.ts +0 -990
  310. package/src/WebRecorder.web.ts +0 -1005
  311. package/src/constants/platformLimitations.ts +0 -118
  312. package/src/constants.ts +0 -18
  313. package/src/events.ts +0 -60
  314. package/src/hooks/useAudioDevices.ts +0 -213
  315. package/src/index.ts +0 -54
  316. package/src/trimAudio.ts +0 -94
  317. package/src/types/crc-32.d.ts +0 -9
  318. package/src/useAudioRecorder.tsx +0 -766
  319. package/src/utils/BlobFix.ts +0 -561
  320. package/src/utils/audioProcessing.ts +0 -205
  321. package/src/utils/cleanNativeOptions.ts +0 -18
  322. package/src/utils/concatenateBuffers.ts +0 -24
  323. package/src/utils/convertPCMToFloat32.ts +0 -170
  324. package/src/utils/crc32.ts +0 -59
  325. package/src/utils/encodingToBitDepth.ts +0 -18
  326. package/src/utils/getWavFileInfo.ts +0 -132
  327. package/src/utils/writeWavHeader.ts +0 -115
  328. package/src/workers/InlineFeaturesExtractor.web.tsx +0 -855
  329. package/src/workers/inlineAudioWebWorker.web.tsx +0 -180
@@ -1,713 +0,0 @@
1
- import { requireNativeModule } from 'expo-modules-core';
2
- import { Platform } from 'react-native';
3
- import { ExpoAudioStreamWeb, } from './ExpoAudioStream.web';
4
- import { processAudioBuffer } from './utils/audioProcessing';
5
- import crc32 from './utils/crc32';
6
- import { writeWavHeader } from './utils/writeWavHeader';
7
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
8
- let ExpoAudioStreamModule;
9
- if (Platform.OS === 'web') {
10
- let instance = null;
11
- ExpoAudioStreamModule = (webProps) => {
12
- if (!instance) {
13
- instance = new ExpoAudioStreamWeb(webProps);
14
- }
15
- return instance;
16
- };
17
- ExpoAudioStreamModule.requestPermissionsAsync = async () => {
18
- try {
19
- const stream = await navigator.mediaDevices.getUserMedia({
20
- audio: true,
21
- });
22
- stream.getTracks().forEach((track) => track.stop());
23
- return {
24
- status: 'granted',
25
- expires: 'never',
26
- canAskAgain: true,
27
- granted: true,
28
- };
29
- }
30
- catch {
31
- return {
32
- status: 'denied',
33
- expires: 'never',
34
- canAskAgain: true,
35
- granted: false,
36
- };
37
- }
38
- };
39
- ExpoAudioStreamModule.getPermissionsAsync = async () => {
40
- let maybeStatus = null;
41
- if (navigator?.permissions?.query) {
42
- try {
43
- const { state } = await navigator.permissions.query({
44
- name: 'microphone',
45
- });
46
- maybeStatus = state;
47
- }
48
- catch {
49
- maybeStatus = null;
50
- }
51
- }
52
- switch (maybeStatus) {
53
- case 'granted':
54
- return {
55
- status: 'granted',
56
- expires: 'never',
57
- canAskAgain: true,
58
- granted: true,
59
- };
60
- case 'denied':
61
- return {
62
- status: 'denied',
63
- expires: 'never',
64
- canAskAgain: true,
65
- granted: false,
66
- };
67
- default:
68
- return await ExpoAudioStreamModule.requestPermissionsAsync();
69
- }
70
- };
71
- ExpoAudioStreamModule.extractAudioData = async (options) => {
72
- try {
73
- const { fileUri, position, length, startTimeMs, endTimeMs, decodingOptions, includeNormalizedData, includeBase64Data, includeWavHeader = false, logger, } = options;
74
- logger?.debug('EXTRACT AUDIO - Step 1: Initial request', {
75
- fileUri,
76
- extractionParams: {
77
- position,
78
- length,
79
- startTimeMs,
80
- endTimeMs,
81
- },
82
- decodingOptions: {
83
- targetSampleRate: decodingOptions?.targetSampleRate ?? 16000,
84
- targetChannels: decodingOptions?.targetChannels ?? 1,
85
- targetBitDepth: decodingOptions?.targetBitDepth ?? 16,
86
- normalizeAudio: decodingOptions?.normalizeAudio ?? false,
87
- },
88
- outputOptions: {
89
- includeNormalizedData,
90
- includeBase64Data,
91
- includeWavHeader,
92
- },
93
- });
94
- // Process the audio using shared helper function
95
- const processedBuffer = await processAudioBuffer({
96
- fileUri,
97
- targetSampleRate: decodingOptions?.targetSampleRate ?? 16000,
98
- targetChannels: decodingOptions?.targetChannels ?? 1,
99
- normalizeAudio: decodingOptions?.normalizeAudio ?? false,
100
- position,
101
- length,
102
- startTimeMs,
103
- endTimeMs,
104
- logger,
105
- });
106
- logger?.debug('EXTRACT AUDIO - Step 2: Audio processing complete', {
107
- processedData: {
108
- samples: processedBuffer.samples,
109
- sampleRate: processedBuffer.sampleRate,
110
- channels: processedBuffer.channels,
111
- durationMs: processedBuffer.durationMs,
112
- },
113
- });
114
- const channelData = processedBuffer.channelData;
115
- const bitDepth = (decodingOptions?.targetBitDepth ?? 16);
116
- const bytesPerSample = bitDepth / 8;
117
- const numSamples = processedBuffer.samples;
118
- logger?.debug('EXTRACT AUDIO - Step 3: PCM conversion setup', {
119
- channelData: {
120
- length: channelData.length,
121
- first: channelData[0],
122
- last: channelData[channelData.length - 1],
123
- },
124
- calculation: {
125
- bitDepth,
126
- bytesPerSample,
127
- numSamples,
128
- expectedBytes: numSamples * bytesPerSample,
129
- },
130
- });
131
- // Create PCM data with correct length based on original byte length
132
- const pcmData = new Uint8Array(numSamples * bytesPerSample);
133
- let offset = 0;
134
- // Convert Float32 samples to PCM format
135
- for (let i = 0; i < numSamples; i++) {
136
- const sample = channelData[i];
137
- const value = Math.max(-1, Math.min(1, sample));
138
- // Convert to 16-bit signed integer
139
- let intValue = Math.round(value * 32767);
140
- // Handle negative values correctly
141
- if (intValue < 0) {
142
- intValue = 65536 + intValue;
143
- }
144
- // Write as little-endian
145
- pcmData[offset++] = intValue & 255; // Low byte
146
- pcmData[offset++] = (intValue >> 8) & 255; // High byte
147
- }
148
- const durationMs = Math.round((numSamples / processedBuffer.sampleRate) * 1000);
149
- logger?.debug('EXTRACT AUDIO - Step 4: Final output', {
150
- pcmData: {
151
- length: pcmData.length,
152
- first: pcmData[0],
153
- last: pcmData[pcmData.length - 1],
154
- },
155
- timing: {
156
- numSamples,
157
- sampleRate: processedBuffer.sampleRate,
158
- durationMs,
159
- shouldBe3000ms: endTimeMs
160
- ? endTimeMs - (startTimeMs ?? 0) === 3000
161
- : undefined,
162
- },
163
- });
164
- const result = {
165
- pcmData: new Uint8Array(pcmData.buffer),
166
- sampleRate: processedBuffer.sampleRate,
167
- channels: processedBuffer.channels,
168
- bitDepth,
169
- durationMs,
170
- format: `pcm_${bitDepth}bit`,
171
- samples: numSamples,
172
- };
173
- // Add WAV header if requested
174
- if (includeWavHeader) {
175
- logger?.debug('EXTRACT AUDIO - Step 4: Adding WAV header', {
176
- originalLength: pcmData.length,
177
- newLength: result.pcmData.length,
178
- firstBytes: Array.from(result.pcmData.slice(0, 44)), // WAV header is 44 bytes
179
- });
180
- const wavBuffer = writeWavHeader({
181
- buffer: pcmData.buffer.slice(0, pcmData.length),
182
- sampleRate: processedBuffer.sampleRate,
183
- numChannels: processedBuffer.channels,
184
- bitDepth,
185
- });
186
- result.pcmData = new Uint8Array(wavBuffer);
187
- result.hasWavHeader = true;
188
- }
189
- if (includeNormalizedData) {
190
- // // Simple approach: Create normalized data directly from the PCM data
191
- // // Just convert to -1 to 1 range without any amplification
192
- // const normalizedData = new Float32Array(numSamples)
193
- // // Convert the PCM data to float values
194
- // for (let i = 0; i < numSamples; i++) {
195
- // // Get the 16-bit PCM value (little endian)
196
- // const lowByte = pcmData[i * 2]
197
- // const highByte = pcmData[i * 2 + 1]
198
- // const pcmValue = (highByte << 8) | lowByte
199
- // // Convert to signed 16-bit value
200
- // const signedValue =
201
- // pcmValue > 32767 ? pcmValue - 65536 : pcmValue
202
- // // Normalize to float between -1 and 1
203
- // normalizedData[i] = signedValue / 32768.0
204
- // }
205
- // Store the normalized data in the result
206
- result.normalizedData = channelData;
207
- }
208
- if (includeBase64Data) {
209
- // Convert the PCM data to a base64 string
210
- const binary = Array.from(new Uint8Array(pcmData.buffer))
211
- .map((b) => String.fromCharCode(b))
212
- .join('');
213
- result.base64Data = btoa(binary);
214
- }
215
- if (options.computeChecksum) {
216
- result.checksum = crc32.buf(pcmData);
217
- }
218
- logger?.debug('EXTRACT AUDIO - Step 3: PCM conversion complete', {
219
- pcmStats: {
220
- length: pcmData.length,
221
- bytesPerSample,
222
- totalSamples: numSamples,
223
- firstBytes: Array.from(pcmData.slice(0, 16)),
224
- lastBytes: Array.from(pcmData.slice(-16)),
225
- },
226
- });
227
- return result;
228
- }
229
- catch (error) {
230
- options.logger?.error('EXTRACT AUDIO - Error:', error);
231
- throw error;
232
- }
233
- };
234
- ExpoAudioStreamModule.trimAudio = async (options) => {
235
- try {
236
- const startTime = performance.now();
237
- const { fileUri, mode = 'single', startTimeMs, endTimeMs, ranges, outputFileName, outputFormat, } = options;
238
- // Validate inputs
239
- if (!fileUri) {
240
- throw new Error('fileUri is required');
241
- }
242
- if (mode === 'single' &&
243
- startTimeMs === undefined &&
244
- endTimeMs === undefined) {
245
- throw new Error('At least one of startTimeMs or endTimeMs must be provided in single mode');
246
- }
247
- if ((mode === 'keep' || mode === 'remove') &&
248
- (!ranges || ranges.length === 0)) {
249
- throw new Error('ranges must be provided and non-empty for keep or remove modes');
250
- }
251
- // Create AudioContext
252
- const audioContext = new (window.AudioContext ||
253
- window.webkitAudioContext)();
254
- // First, load the entire audio file to get its properties
255
- const response = await fetch(fileUri);
256
- const arrayBuffer = await response.arrayBuffer();
257
- const originalAudioBuffer = await audioContext.decodeAudioData(arrayBuffer);
258
- // Get original audio properties
259
- const originalSampleRate = originalAudioBuffer.sampleRate;
260
- const originalChannels = originalAudioBuffer.numberOfChannels;
261
- // Add more detailed logging
262
- console.log(`Original audio details:`, {
263
- sampleRate: originalSampleRate,
264
- channels: originalChannels,
265
- duration: originalAudioBuffer.duration,
266
- length: originalAudioBuffer.length,
267
- // Log a few samples to verify content
268
- firstSamples: Array.from(originalAudioBuffer.getChannelData(0).slice(0, 5)),
269
- });
270
- // Determine output format - use original values as defaults if not specified
271
- let format = outputFormat?.format || 'wav';
272
- const targetSampleRate = outputFormat?.sampleRate || originalSampleRate;
273
- const targetChannels = outputFormat?.channels || originalChannels;
274
- const targetBitDepth = outputFormat?.bitDepth || 16;
275
- // Get file info from the URL
276
- const filename = outputFileName ||
277
- fileUri.split('/').pop() ||
278
- 'trimmed-audio.wav';
279
- // Process based on mode
280
- let resultBuffer;
281
- // Report initial progress
282
- ExpoAudioStreamModule.sendEvent('TrimProgress', {
283
- progress: 10,
284
- });
285
- if (mode === 'single') {
286
- // Single mode: extract a single range
287
- // Use original sample rate and channels for extraction to preserve quality
288
- const { buffer } = await processAudioBuffer({
289
- fileUri,
290
- targetSampleRate, // Use the requested sample rate
291
- targetChannels,
292
- normalizeAudio: false,
293
- startTimeMs,
294
- endTimeMs,
295
- audioContext,
296
- });
297
- console.log(`Processed buffer details:`, {
298
- sampleRate: buffer.sampleRate,
299
- channels: buffer.numberOfChannels,
300
- duration: buffer.duration,
301
- length: buffer.length,
302
- // Log a few samples to verify content
303
- firstSamples: Array.from(buffer.getChannelData(0).slice(0, 5)),
304
- });
305
- resultBuffer = buffer;
306
- // If we need to change sample rate or channels, do it after extraction
307
- if (targetSampleRate !== originalSampleRate ||
308
- targetChannels !== originalChannels) {
309
- console.log(`Resampling from ${originalSampleRate}Hz to ${targetSampleRate}Hz`);
310
- resultBuffer = await resampleAudioBuffer(audioContext, buffer, targetSampleRate, targetChannels);
311
- }
312
- }
313
- else {
314
- // For keep or remove modes
315
- const fullDuration = originalAudioBuffer.duration * 1000; // in ms
316
- let segmentsToProcess = [];
317
- if (mode === 'keep') {
318
- // For keep mode, use the ranges directly
319
- segmentsToProcess = ranges;
320
- }
321
- else {
322
- // mode === 'remove'
323
- // For remove mode, invert the ranges
324
- const sortedRanges = [...ranges].sort((a, b) => a.startTimeMs - b.startTimeMs);
325
- // Add segment from start to first range if needed
326
- if (sortedRanges.length > 0 &&
327
- sortedRanges[0].startTimeMs > 0) {
328
- segmentsToProcess.push({
329
- startTimeMs: 0,
330
- endTimeMs: sortedRanges[0].startTimeMs,
331
- });
332
- }
333
- // Add segments between ranges
334
- for (let i = 0; i < sortedRanges.length - 1; i++) {
335
- segmentsToProcess.push({
336
- startTimeMs: sortedRanges[i].endTimeMs,
337
- endTimeMs: sortedRanges[i + 1].startTimeMs,
338
- });
339
- }
340
- // Add segment from last range to end if needed
341
- if (sortedRanges.length > 0 &&
342
- sortedRanges[sortedRanges.length - 1].endTimeMs <
343
- fullDuration) {
344
- segmentsToProcess.push({
345
- startTimeMs: sortedRanges[sortedRanges.length - 1].endTimeMs,
346
- endTimeMs: fullDuration,
347
- });
348
- }
349
- }
350
- // Filter out empty or invalid segments
351
- segmentsToProcess = segmentsToProcess.filter((segment) => segment.startTimeMs < segment.endTimeMs &&
352
- segment.endTimeMs - segment.startTimeMs > 1); // 1ms minimum
353
- if (segmentsToProcess.length === 0) {
354
- throw new Error('No valid segments to process after filtering ranges');
355
- }
356
- // Process each segment using original sample rate and channels
357
- const segmentBuffers = [];
358
- for (let i = 0; i < segmentsToProcess.length; i++) {
359
- const segment = segmentsToProcess[i];
360
- // Report progress for each segment
361
- ExpoAudioStreamModule.sendEvent('TrimProgress', {
362
- progress: 10 +
363
- Math.round((i / segmentsToProcess.length) * 40),
364
- });
365
- // Use processAudioBuffer to extract this segment
366
- const { buffer: segmentBuffer } = await processAudioBuffer({
367
- fileUri,
368
- targetSampleRate: originalSampleRate, // Use original sample rate
369
- targetChannels: originalChannels, // Use original channels
370
- normalizeAudio: false,
371
- startTimeMs: segment.startTimeMs,
372
- endTimeMs: segment.endTimeMs,
373
- audioContext,
374
- });
375
- segmentBuffers.push(segmentBuffer);
376
- }
377
- // Concatenate all segments
378
- const totalSamples = segmentBuffers.reduce((sum, buffer) => sum + buffer.length, 0);
379
- // Create buffer with original properties first
380
- const concatenatedBuffer = audioContext.createBuffer(originalChannels, totalSamples, originalSampleRate);
381
- let offset = 0;
382
- for (const segmentBuffer of segmentBuffers) {
383
- for (let channel = 0; channel < originalChannels; channel++) {
384
- const outputData = concatenatedBuffer.getChannelData(channel);
385
- const segmentData = segmentBuffer.getChannelData(channel);
386
- for (let i = 0; i < segmentBuffer.length; i++) {
387
- outputData[offset + i] = segmentData[i];
388
- }
389
- }
390
- offset += segmentBuffer.length;
391
- }
392
- resultBuffer = concatenatedBuffer;
393
- // If we need to change sample rate or channels, do it after concatenation
394
- if (targetSampleRate !== originalSampleRate ||
395
- targetChannels !== originalChannels) {
396
- console.log(`Resampling concatenated buffer from ${originalSampleRate}Hz to ${targetSampleRate}Hz`);
397
- resultBuffer = await resampleAudioBuffer(audioContext, concatenatedBuffer, targetSampleRate, targetChannels);
398
- }
399
- }
400
- // Report progress (50% - processing complete)
401
- ExpoAudioStreamModule.sendEvent('TrimProgress', {
402
- progress: 50,
403
- });
404
- // Encode the result based on the requested format
405
- let outputData;
406
- let outputMimeType;
407
- let compressionInfo = null;
408
- // Check if AAC was requested on web and show a warning
409
- if (format === 'aac' && Platform.OS === 'web') {
410
- console.warn('AAC format is not supported on web platforms. Falling back to OPUS format.');
411
- format = 'opus';
412
- }
413
- if (format === 'wav') {
414
- // Create a properly interleaved buffer for WAV format
415
- // For WAV, we need to convert Float32Array to Int16Array (for 16-bit audio)
416
- const numSamples = resultBuffer.length * resultBuffer.numberOfChannels;
417
- const interleavedData = new Int16Array(numSamples);
418
- // Log detailed information about the buffer before encoding
419
- console.log(`Creating WAV file:`, {
420
- bufferSampleRate: resultBuffer.sampleRate,
421
- bufferChannels: resultBuffer.numberOfChannels,
422
- bufferLength: resultBuffer.length,
423
- targetSampleRate,
424
- targetChannels,
425
- targetBitDepth,
426
- // Log a few samples to verify content
427
- firstSamples: Array.from(resultBuffer.getChannelData(0).slice(0, 5)),
428
- });
429
- // Interleave channels properly
430
- for (let i = 0; i < resultBuffer.length; i++) {
431
- for (let channel = 0; channel < resultBuffer.numberOfChannels; channel++) {
432
- // Convert float (-1.0 to 1.0) to int16 (-32768 to 32767)
433
- const floatSample = resultBuffer.getChannelData(channel)[i];
434
- // Clamp the value to -1.0 to 1.0
435
- const clampedSample = Math.max(-1.0, Math.min(1.0, floatSample));
436
- // Convert to int16
437
- const intSample = Math.round(clampedSample * 32767);
438
- // Store in interleaved buffer
439
- interleavedData[i * resultBuffer.numberOfChannels + channel] = intSample;
440
- }
441
- }
442
- // Convert Int16Array to ArrayBuffer for WAV header
443
- const rawBuffer = interleavedData.buffer;
444
- // IMPORTANT: Make sure we're using the ACTUAL sample rate of the buffer
445
- // not just what was requested in the options
446
- console.log(`Creating WAV with ${resultBuffer.numberOfChannels} channels at ${resultBuffer.sampleRate}Hz`);
447
- outputData = writeWavHeader({
448
- buffer: rawBuffer,
449
- sampleRate: resultBuffer.sampleRate, // Use the actual buffer's sample rate
450
- numChannels: resultBuffer.numberOfChannels,
451
- bitDepth: targetBitDepth,
452
- });
453
- outputMimeType = 'audio/wav';
454
- }
455
- else if (format === 'opus' || format === 'aac') {
456
- try {
457
- // Try to use MediaRecorder for compressed formats
458
- const { data, bitrate } = await encodeCompressedAudio(resultBuffer, format, outputFormat?.bitrate);
459
- outputData = data;
460
- outputMimeType =
461
- format === 'opus' ? 'audio/webm' : 'audio/aac';
462
- compressionInfo = {
463
- format,
464
- bitrate,
465
- size: data.byteLength,
466
- };
467
- }
468
- catch (error) {
469
- console.warn(`Failed to encode to ${format}, falling back to WAV: ${error}`);
470
- // Same WAV encoding as above
471
- const wavData = new Float32Array(resultBuffer.length * resultBuffer.numberOfChannels);
472
- for (let i = 0; i < resultBuffer.length; i++) {
473
- for (let channel = 0; channel < resultBuffer.numberOfChannels; channel++) {
474
- wavData[i * resultBuffer.numberOfChannels + channel] = resultBuffer.getChannelData(channel)[i];
475
- }
476
- }
477
- outputData = writeWavHeader({
478
- buffer: wavData.buffer,
479
- sampleRate: resultBuffer.sampleRate,
480
- numChannels: resultBuffer.numberOfChannels,
481
- bitDepth: targetBitDepth,
482
- });
483
- outputMimeType = 'audio/wav';
484
- }
485
- }
486
- else {
487
- // Default to WAV for unsupported formats
488
- console.warn(`Format ${format} not supported on web, using WAV instead`);
489
- // Same WAV encoding as above
490
- const wavData = new Float32Array(resultBuffer.length * resultBuffer.numberOfChannels);
491
- for (let i = 0; i < resultBuffer.length; i++) {
492
- for (let channel = 0; channel < resultBuffer.numberOfChannels; channel++) {
493
- wavData[i * resultBuffer.numberOfChannels + channel] =
494
- resultBuffer.getChannelData(channel)[i];
495
- }
496
- }
497
- outputData = writeWavHeader({
498
- buffer: wavData.buffer,
499
- sampleRate: resultBuffer.sampleRate,
500
- numChannels: resultBuffer.numberOfChannels,
501
- bitDepth: targetBitDepth,
502
- });
503
- outputMimeType = 'audio/wav';
504
- }
505
- // Report progress (90% - encoding complete)
506
- ExpoAudioStreamModule.sendEvent('TrimProgress', {
507
- progress: 90,
508
- });
509
- // Create a blob and URL for the result
510
- const blob = new Blob([outputData], { type: outputMimeType });
511
- const outputUri = URL.createObjectURL(blob);
512
- // Calculate processing time
513
- const processingTimeMs = performance.now() - startTime;
514
- // Report progress (100% - complete)
515
- ExpoAudioStreamModule.sendEvent('TrimProgress', {
516
- progress: 100,
517
- });
518
- // Create result object
519
- const result = {
520
- uri: outputUri,
521
- filename,
522
- durationMs: Math.round(resultBuffer.duration * 1000),
523
- size: outputData.byteLength,
524
- sampleRate: resultBuffer.sampleRate,
525
- channels: resultBuffer.numberOfChannels,
526
- bitDepth: targetBitDepth,
527
- mimeType: outputMimeType,
528
- processingInfo: {
529
- durationMs: processingTimeMs,
530
- },
531
- };
532
- // Add compression info if available
533
- if (compressionInfo) {
534
- result.compression = compressionInfo;
535
- }
536
- return result;
537
- }
538
- catch (error) {
539
- console.error('Error in trimAudio:', error);
540
- throw error;
541
- }
542
- };
543
- // Add a sendEvent method for web
544
- ExpoAudioStreamModule.sendEvent = (eventName, params) => {
545
- // This will be picked up by the LegacyEventEmitter in trimAudio.ts
546
- if (ExpoAudioStreamModule.listeners &&
547
- ExpoAudioStreamModule.listeners[eventName]) {
548
- ExpoAudioStreamModule.listeners[eventName].forEach((listener) => {
549
- listener(params);
550
- });
551
- }
552
- };
553
- // Initialize listeners object
554
- ExpoAudioStreamModule.listeners = {};
555
- // Add methods for event listeners that LegacyEventEmitter will use
556
- ExpoAudioStreamModule.addListener = (eventName, listener) => {
557
- if (!ExpoAudioStreamModule.listeners[eventName]) {
558
- ExpoAudioStreamModule.listeners[eventName] = [];
559
- }
560
- ExpoAudioStreamModule.listeners[eventName].push(listener);
561
- // Return an object with a remove method
562
- return {
563
- remove: () => {
564
- const index = ExpoAudioStreamModule.listeners[eventName].indexOf(listener);
565
- if (index !== -1) {
566
- ExpoAudioStreamModule.listeners[eventName].splice(index, 1);
567
- }
568
- },
569
- };
570
- };
571
- ExpoAudioStreamModule.removeAllListeners = (eventName) => {
572
- if (ExpoAudioStreamModule.listeners[eventName]) {
573
- delete ExpoAudioStreamModule.listeners[eventName];
574
- }
575
- };
576
- ExpoAudioStreamModule.prepareRecording = async (options) => {
577
- // For web platform, we'll implement a simplified version that just checks permissions
578
- // and does minimal setup. The actual recording setup will still happen in startRecording.
579
- try {
580
- // Check for microphone permissions
581
- const permissionsResult = await ExpoAudioStreamModule.getPermissionsAsync();
582
- if (!permissionsResult.granted) {
583
- throw new Error('Microphone permission not granted');
584
- }
585
- // If using a web instance, call its prepareRecording method
586
- if (instance) {
587
- return await instance.prepareRecording(options);
588
- }
589
- return true;
590
- }
591
- catch (error) {
592
- console.error('Error preparing recording:', error);
593
- throw error;
594
- }
595
- };
596
- }
597
- // Move the encodeCompressedAudio function outside the if block to fix the ESLint error
598
- async function encodeCompressedAudio(buffer, format, bitrate) {
599
- return new Promise((resolve, reject) => {
600
- try {
601
- // On web, always use opus if aac is requested
602
- const actualFormat = Platform.OS === 'web' && format === 'aac' ? 'opus' : format;
603
- // Check if MediaRecorder supports the requested format
604
- const mimeType = actualFormat === 'opus' ? 'audio/webm;codecs=opus' : 'audio/aac';
605
- if (!MediaRecorder.isTypeSupported(mimeType)) {
606
- throw new Error(`MediaRecorder does not support ${mimeType}`);
607
- }
608
- // Create a new AudioContext and source
609
- const ctx = new (window.AudioContext ||
610
- window.webkitAudioContext)();
611
- const source = ctx.createBufferSource();
612
- source.buffer = buffer;
613
- // Create a MediaStreamDestination to capture the audio
614
- const destination = ctx.createMediaStreamDestination();
615
- source.connect(destination);
616
- // Create a MediaRecorder with the requested format
617
- const recorder = new MediaRecorder(destination.stream, {
618
- mimeType,
619
- audioBitsPerSecond: bitrate || (actualFormat === 'opus' ? 32000 : 64000),
620
- });
621
- const chunks = [];
622
- recorder.ondataavailable = (e) => {
623
- if (e.data.size > 0) {
624
- chunks.push(e.data);
625
- }
626
- };
627
- recorder.onstop = async () => {
628
- try {
629
- const blob = new Blob(chunks, { type: mimeType });
630
- const arrayBuffer = await blob.arrayBuffer();
631
- // Get the actual bitrate used
632
- const actualBitrate = Math.round((arrayBuffer.byteLength * 8) / buffer.duration);
633
- resolve({
634
- data: arrayBuffer,
635
- bitrate: actualBitrate / 1000, // Convert to kbps
636
- });
637
- // Clean up
638
- ctx.close();
639
- }
640
- catch (error) {
641
- reject(error);
642
- }
643
- };
644
- // Start recording and playback
645
- recorder.start();
646
- source.start(0);
647
- // Stop recording when the buffer finishes playing
648
- setTimeout(() => {
649
- recorder.stop();
650
- source.stop();
651
- }, buffer.duration * 1000);
652
- }
653
- catch (error) {
654
- reject(error);
655
- }
656
- });
657
- }
658
- // Improved resampleAudioBuffer function
659
- async function resampleAudioBuffer(context, buffer, targetSampleRate, targetChannels) {
660
- // If no change needed, return the original buffer
661
- if (buffer.sampleRate === targetSampleRate &&
662
- buffer.numberOfChannels === targetChannels) {
663
- return buffer;
664
- }
665
- console.log(`Resampling: ${buffer.sampleRate}Hz → ${targetSampleRate}Hz, ${buffer.numberOfChannels} → ${targetChannels} channels`);
666
- // Calculate the new length based on the sample rate change
667
- const newLength = Math.round((buffer.length * targetSampleRate) / buffer.sampleRate);
668
- // Create an offline context for resampling
669
- const offlineContext = new OfflineAudioContext(targetChannels, newLength, targetSampleRate);
670
- // Create a source node
671
- const source = offlineContext.createBufferSource();
672
- source.buffer = buffer;
673
- // If we need to change channel count
674
- if (buffer.numberOfChannels !== targetChannels) {
675
- if (targetChannels === 1 && buffer.numberOfChannels > 1) {
676
- // Downmix to mono
677
- const merger = offlineContext.createChannelMerger(1);
678
- // Create a gain node to reduce volume when downmixing to prevent clipping
679
- const gainNode = offlineContext.createGain();
680
- gainNode.gain.value = 1.0 / buffer.numberOfChannels;
681
- source.connect(gainNode);
682
- gainNode.connect(merger);
683
- merger.connect(offlineContext.destination);
684
- }
685
- else if (targetChannels === 2 && buffer.numberOfChannels === 1) {
686
- // Upmix mono to stereo (duplicate the channel)
687
- const splitter = offlineContext.createChannelSplitter(1);
688
- const merger = offlineContext.createChannelMerger(2);
689
- source.connect(splitter);
690
- splitter.connect(merger, 0, 0);
691
- splitter.connect(merger, 0, 1);
692
- merger.connect(offlineContext.destination);
693
- }
694
- else {
695
- // For other cases, just connect and let the system handle it
696
- source.connect(offlineContext.destination);
697
- }
698
- }
699
- else {
700
- // No channel conversion needed
701
- source.connect(offlineContext.destination);
702
- }
703
- // Start rendering
704
- source.start(0);
705
- const resampledBuffer = await offlineContext.startRendering();
706
- console.log(`Resampling complete: ${resampledBuffer.length} samples at ${resampledBuffer.sampleRate}Hz`);
707
- return resampledBuffer;
708
- }
709
- if (Platform.OS !== 'web') {
710
- ExpoAudioStreamModule = requireNativeModule('ExpoAudioStream');
711
- }
712
- export default ExpoAudioStreamModule;
713
- //# sourceMappingURL=ExpoAudioStreamModule.js.map