@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,218 +0,0 @@
1
- package net.siteed.audiostream.integration
2
-
3
- import android.content.Context
4
- import androidx.test.ext.junit.runners.AndroidJUnit4
5
- import androidx.test.platform.app.InstrumentationRegistry
6
- import net.siteed.audiostream.OutputConfig
7
- import net.siteed.audiostream.RecordingConfig
8
- import org.junit.After
9
- import org.junit.Assert.*
10
- import org.junit.Before
11
- import org.junit.Test
12
- import org.junit.runner.RunWith
13
- import java.io.File
14
-
15
- /**
16
- * Integration test for device disconnection fallback behavior.
17
- * Tests various scenarios when audio devices are disconnected during recording.
18
- */
19
- @RunWith(AndroidJUnit4::class)
20
- class DeviceDisconnectionFallbackTest {
21
-
22
- private lateinit var context: Context
23
- private lateinit var testDir: File
24
-
25
- @Before
26
- fun setup() {
27
- context = InstrumentationRegistry.getInstrumentation().targetContext
28
-
29
- // Create test directory
30
- testDir = File(context.getExternalFilesDir(null), "fallback_test")
31
- testDir.mkdirs()
32
-
33
- // Clear any existing test files
34
- testDir.listFiles()?.forEach { it.delete() }
35
- }
36
-
37
- @After
38
- fun tearDown() {
39
- // Clean up test files
40
- testDir.listFiles()?.forEach { it.delete() }
41
- testDir.delete()
42
- }
43
-
44
- @Test
45
- fun testDeviceDisconnectionBehavior_Fallback() {
46
- println("🧪 Test: Device Disconnection with Fallback Behavior")
47
- println("--------------------------------------------------")
48
-
49
- // Create recording config with fallback behavior
50
- val config = RecordingConfig(
51
- sampleRate = 44100,
52
- channels = 1,
53
- encoding = "pcm_16bit",
54
- deviceDisconnectionBehavior = "fallback",
55
- output = OutputConfig(
56
- primary = OutputConfig.PrimaryOutput(
57
- enabled = true,
58
- format = "wav"
59
- )
60
- ),
61
- outputDirectory = testDir.absolutePath,
62
- filename = "fallback_test.wav"
63
- )
64
-
65
- // Verify device disconnection behavior is set
66
- assertEquals("Device disconnection behavior should be fallback",
67
- "fallback", config.deviceDisconnectionBehavior)
68
-
69
- println("✅ RecordingConfig correctly configured with fallback behavior")
70
-
71
- // Note: Actual device disconnection simulation would require running the full
72
- // ExpoAudioStreamModule with device connection/disconnection events
73
- }
74
-
75
- @Test
76
- fun testDeviceDisconnectionBehavior_Pause() {
77
- println("🧪 Test: Device Disconnection with Pause Behavior")
78
- println("-----------------------------------------------")
79
-
80
- val config = RecordingConfig(
81
- sampleRate = 44100,
82
- channels = 1,
83
- encoding = "pcm_16bit",
84
- deviceDisconnectionBehavior = "pause",
85
- output = OutputConfig(
86
- primary = OutputConfig.PrimaryOutput(
87
- enabled = true,
88
- format = "wav"
89
- )
90
- ),
91
- outputDirectory = testDir.absolutePath,
92
- filename = "pause_test.wav"
93
- )
94
-
95
- // Verify device disconnection behavior is set to pause
96
- assertEquals("Device disconnection behavior should be pause",
97
- "pause", config.deviceDisconnectionBehavior)
98
-
99
- println("✅ RecordingConfig correctly configured with pause behavior")
100
- }
101
-
102
- @Test
103
- fun testDefaultDeviceDisconnectionBehavior() {
104
- println("🧪 Test: Default Device Disconnection Behavior")
105
- println("--------------------------------------------")
106
-
107
- // Create config without specifying deviceDisconnectionBehavior
108
- val config = RecordingConfig(
109
- sampleRate = 44100,
110
- channels = 1,
111
- encoding = "pcm_16bit",
112
- output = OutputConfig(
113
- primary = OutputConfig.PrimaryOutput(
114
- enabled = true,
115
- format = "wav"
116
- )
117
- ),
118
- outputDirectory = testDir.absolutePath,
119
- filename = "default_test.wav"
120
- )
121
-
122
- // Default behavior should be null (handled as pause in implementation)
123
- assertNull("Default device disconnection behavior should be null",
124
- config.deviceDisconnectionBehavior)
125
-
126
- println("✅ Default device disconnection behavior is null (treated as 'pause')")
127
- }
128
-
129
- @Test
130
- fun testInterruptionEventReasons() {
131
- println("🧪 Test: Interruption Event Reasons")
132
- println("----------------------------------")
133
-
134
- // Test that the expected event reasons are valid
135
- val fallbackReasons = listOf("deviceFallback", "deviceSwitchFailed")
136
- val pauseReasons = listOf("deviceDisconnected")
137
-
138
- println("📋 Expected reasons for fallback behavior:")
139
- fallbackReasons.forEach { reason ->
140
- println(" - $reason")
141
- assertNotNull("Reason should not be null", reason)
142
- assertTrue("Reason should not be empty", reason.isNotEmpty())
143
- }
144
-
145
- println("📋 Expected reasons for pause behavior:")
146
- pauseReasons.forEach { reason ->
147
- println(" - $reason")
148
- assertNotNull("Reason should not be null", reason)
149
- assertTrue("Reason should not be empty", reason.isNotEmpty())
150
- }
151
-
152
- println("✅ All interruption event reasons are valid")
153
- }
154
-
155
- @Test
156
- fun testAllDeviceDisconnectionBehaviors() {
157
- println("🧪 Test: All Device Disconnection Behaviors")
158
- println("-----------------------------------------")
159
-
160
- val behaviors = listOf("fallback", "pause")
161
-
162
- behaviors.forEach { behavior ->
163
- val config = RecordingConfig(
164
- sampleRate = 44100,
165
- channels = 1,
166
- encoding = "pcm_16bit",
167
- deviceDisconnectionBehavior = behavior,
168
- output = OutputConfig(
169
- primary = OutputConfig.PrimaryOutput(
170
- enabled = true,
171
- format = "wav"
172
- )
173
- ),
174
- outputDirectory = testDir.absolutePath,
175
- filename = "${behavior}_test.wav"
176
- )
177
-
178
- // Verify configuration
179
- assertEquals("Device disconnection behavior should be $behavior",
180
- behavior, config.deviceDisconnectionBehavior)
181
-
182
- println("✅ Behavior '$behavior' correctly configured")
183
- }
184
- }
185
-
186
- @Test
187
- fun testDeviceDisconnectionWithCompressedOutput() {
188
- println("🧪 Test: Device Disconnection with Compressed Output")
189
- println("--------------------------------------------------")
190
-
191
- // Test fallback behavior with compressed output enabled
192
- val config = RecordingConfig(
193
- sampleRate = 44100,
194
- channels = 1,
195
- encoding = "pcm_16bit",
196
- deviceDisconnectionBehavior = "fallback",
197
- output = OutputConfig(
198
- primary = OutputConfig.PrimaryOutput(
199
- enabled = false
200
- ),
201
- compressed = OutputConfig.CompressedOutput(
202
- enabled = true,
203
- format = "aac",
204
- bitrate = 128000
205
- )
206
- ),
207
- outputDirectory = testDir.absolutePath,
208
- filename = "compressed_fallback_test"
209
- )
210
-
211
- assertEquals("Device disconnection behavior should be fallback",
212
- "fallback", config.deviceDisconnectionBehavior)
213
- assertTrue("Compressed output should be enabled", config.output.compressed.enabled)
214
- assertFalse("Primary output should be disabled", config.output.primary.enabled)
215
-
216
- println("✅ Fallback behavior configured with compressed-only output")
217
- }
218
- }
@@ -1,120 +0,0 @@
1
- package net.siteed.audiostream.integration
2
-
3
- import android.os.Bundle
4
- import android.util.Log
5
- import androidx.test.ext.junit.runners.AndroidJUnit4
6
- import androidx.test.platform.app.InstrumentationRegistry
7
- import org.junit.Test
8
- import org.junit.runner.RunWith
9
- import org.junit.Assert.*
10
- import java.io.File
11
- import kotlin.math.abs
12
-
13
- /**
14
- * Integration test to validate event emission interval enforcement.
15
- *
16
- * This test verifies that the configured intervals respect platform
17
- * minimums to prevent excessive CPU usage.
18
- */
19
- @RunWith(AndroidJUnit4::class)
20
- class EventEmissionIntervalTest {
21
-
22
- private val TAG = "EventEmissionIntervalTest"
23
- private val context = InstrumentationRegistry.getInstrumentation().targetContext
24
-
25
- @Test
26
- fun testMinimumIntervalEnforcement() {
27
- println("🧪 Test: Minimum Interval Enforcement")
28
- println("------------------------------------")
29
-
30
- // Test cases for different requested intervals
31
- val testCases = listOf(
32
- 5 to 10, // 5ms should be clamped to MIN_INTERVAL (10ms)
33
- 10 to 10, // 10ms should remain 10ms
34
- 50 to 50, // 50ms should remain 50ms
35
- 100 to 100 // 100ms should remain 100ms
36
- )
37
-
38
- for ((requested, expected) in testCases) {
39
- val config = Bundle().apply {
40
- putInt("sampleRate", 48000)
41
- putInt("channels", 1)
42
- putLong("interval", requested.toLong())
43
- putLong("intervalAnalysis", requested.toLong())
44
- }
45
-
46
- // Parse the config to validate interval enforcement
47
- val configMap = bundleToMap(config)
48
- val result = net.siteed.audiostream.RecordingConfig.fromMap(configMap)
49
-
50
- assertTrue("Config parsing should succeed", result.isSuccess)
51
- val (recordingConfig, _) = result.getOrNull()!!
52
-
53
- println("Requested interval: ${requested}ms")
54
- println("Actual interval: ${recordingConfig.interval}ms")
55
- println("Expected interval: ${expected}ms")
56
-
57
- assertEquals(
58
- "Interval should be clamped to minimum if below MIN_INTERVAL",
59
- expected.toLong(),
60
- recordingConfig.interval
61
- )
62
-
63
- assertEquals(
64
- "Analysis interval should be clamped to minimum if below MIN_INTERVAL",
65
- expected.toLong(),
66
- recordingConfig.intervalAnalysis
67
- )
68
-
69
- println("✓ Passed\n")
70
- }
71
- }
72
-
73
- @Test
74
- fun testIntervalConsistencyAcrossPlatforms() {
75
- println("🧪 Test: Platform Consistency Check")
76
- println("----------------------------------")
77
-
78
- // Document the expected behavior across platforms
79
- println("Expected behavior after fix:")
80
- println("- iOS: Minimum interval = 10ms")
81
- println("- Android: Minimum interval = 10ms (enforced)")
82
- println("")
83
-
84
- // Verify Android enforces the minimum
85
- val intervals = listOf(1, 5, 10, 50, 100)
86
- for (interval in intervals) {
87
- val config = Bundle().apply {
88
- putLong("interval", interval.toLong())
89
- putLong("intervalAnalysis", interval.toLong())
90
- }
91
-
92
- val configMap = bundleToMap(config)
93
- val result = net.siteed.audiostream.RecordingConfig.fromMap(configMap)
94
- val (recordingConfig, _) = result.getOrNull()!!
95
-
96
- val expectedInterval = maxOf(10, interval).toLong()
97
- assertEquals(
98
- "Android should enforce MIN_INTERVAL of 10ms",
99
- expectedInterval,
100
- recordingConfig.interval
101
- )
102
-
103
- println("✓ Interval ${interval}ms -> ${recordingConfig.interval}ms")
104
- }
105
- }
106
-
107
- /**
108
- * Helper to convert Bundle to Map for RecordingConfig
109
- */
110
- private fun bundleToMap(bundle: Bundle): Map<String, Any?> {
111
- val map = mutableMapOf<String, Any?>()
112
- for (key in bundle.keySet()) {
113
- when (val value = bundle.get(key)) {
114
- is Bundle -> map[key] = bundleToMap(value)
115
- else -> map[key] = value
116
- }
117
- }
118
- return map
119
- }
120
- }
@@ -1,345 +0,0 @@
1
- package net.siteed.audiostream.integration
2
-
3
- import android.Manifest
4
- import android.content.Context
5
- import android.media.MediaExtractor
6
- import android.media.MediaFormat
7
- import androidx.test.ext.junit.runners.AndroidJUnit4
8
- import androidx.test.platform.app.InstrumentationRegistry
9
- import androidx.test.rule.GrantPermissionRule
10
- import expo.modules.kotlin.Promise
11
- import net.siteed.audiostream.*
12
- import org.junit.After
13
- import org.junit.Assert.*
14
- import org.junit.Before
15
- import org.junit.Rule
16
- import org.junit.Test
17
- import org.junit.runner.RunWith
18
- import java.io.File
19
- import java.util.concurrent.CountDownLatch
20
- import java.util.concurrent.TimeUnit
21
-
22
- @RunWith(AndroidJUnit4::class)
23
- class M4aFormatTest {
24
-
25
- @get:Rule
26
- val grantPermissionRule: GrantPermissionRule = GrantPermissionRule.grant(
27
- Manifest.permission.RECORD_AUDIO
28
- )
29
-
30
- private lateinit var context: Context
31
- private lateinit var filesDir: File
32
- private lateinit var audioRecorderManager: AudioRecorderManager
33
- private lateinit var testEventSender: TestEventSender
34
- private lateinit var permissionUtils: PermissionUtils
35
- private lateinit var audioDataEncoder: AudioDataEncoder
36
-
37
- // Test event sender to capture events
38
- private class TestEventSender : EventSender {
39
- override fun sendExpoEvent(eventName: String, params: android.os.Bundle) {
40
- // No-op for tests
41
- }
42
- }
43
-
44
- @Before
45
- fun setUp() {
46
- context = InstrumentationRegistry.getInstrumentation().targetContext
47
- filesDir = context.filesDir
48
- testEventSender = TestEventSender()
49
- permissionUtils = PermissionUtils(context)
50
- audioDataEncoder = AudioDataEncoder()
51
-
52
- // Initialize AudioRecorderManager
53
- audioRecorderManager = AudioRecorderManager.initialize(
54
- context = context,
55
- filesDir = filesDir,
56
- permissionUtils = permissionUtils,
57
- audioDataEncoder = audioDataEncoder,
58
- eventSender = testEventSender,
59
- enablePhoneStateHandling = false,
60
- enableBackgroundAudio = false
61
- )
62
-
63
- // Clean up any existing audio files
64
- cleanupAudioFiles()
65
- }
66
-
67
- @After
68
- fun tearDown() {
69
- // Stop any ongoing recording
70
- if (audioRecorderManager.isRecording) {
71
- stopRecordingSync()
72
- }
73
-
74
- // Clean up
75
- AudioRecorderManager.destroy()
76
- cleanupAudioFiles()
77
- }
78
-
79
- private fun cleanupAudioFiles() {
80
- filesDir.listFiles()?.forEach { file ->
81
- if (file.name.endsWith(".wav") || file.name.endsWith(".aac") ||
82
- file.name.endsWith(".m4a") || file.name.endsWith(".opus")) {
83
- file.delete()
84
- }
85
- }
86
- }
87
-
88
- @Test
89
- fun testAacFormat_producesM4aByDefault() {
90
- // Skip test if API level is too low for compressed recording
91
- if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.Q) {
92
- println("Skipping M4A test - requires API 29+, current API: ${android.os.Build.VERSION.SDK_INT}")
93
- return
94
- }
95
-
96
- // Given
97
- val recordingOptions = mapOf(
98
- "sampleRate" to 44100,
99
- "channels" to 1,
100
- "encoding" to "pcm_16bit",
101
- "interval" to 100,
102
- "showNotification" to false,
103
- "output" to mapOf(
104
- "primary" to mapOf("enabled" to false),
105
- "compressed" to mapOf(
106
- "enabled" to true,
107
- "format" to "aac"
108
- // preferRawStream not specified = defaults to false = M4A
109
- )
110
- )
111
- )
112
-
113
- // When - Record for 1 second
114
- startRecordingSync(recordingOptions)
115
- Thread.sleep(1000)
116
- val result = stopRecordingSync()
117
-
118
- // Then
119
- val compression = when (val comp = result["compression"]) {
120
- is android.os.Bundle -> bundleToMap(comp)
121
- is Map<*, *> -> comp
122
- else -> null
123
- }
124
-
125
- val compressedUri = compression?.get("compressedFileUri") as? String
126
- assertNotNull("Compressed file URI should not be null", compressedUri)
127
-
128
- val file = when {
129
- compressedUri!!.startsWith("file://") -> File(java.net.URI(compressedUri))
130
- compressedUri.startsWith("file:") -> File(java.net.URI(compressedUri))
131
- else -> File(compressedUri)
132
- }
133
-
134
- assertTrue("File should exist", file.exists())
135
- assertTrue("File should have .m4a extension", file.name.endsWith(".m4a"))
136
-
137
- // Verify it's actually an M4A file
138
- verifyM4aFormat(file)
139
- }
140
-
141
- @Test
142
- fun testAacFormat_withPreferRawStream_producesAac() {
143
- // Skip test if API level is too low for compressed recording
144
- if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.Q) {
145
- println("Skipping raw AAC test - requires API 29+, current API: ${android.os.Build.VERSION.SDK_INT}")
146
- return
147
- }
148
-
149
- // Given
150
- val recordingOptions = mapOf(
151
- "sampleRate" to 44100,
152
- "channels" to 1,
153
- "encoding" to "pcm_16bit",
154
- "interval" to 100,
155
- "showNotification" to false,
156
- "output" to mapOf(
157
- "primary" to mapOf("enabled" to false),
158
- "compressed" to mapOf(
159
- "enabled" to true,
160
- "format" to "aac",
161
- "preferRawStream" to true // NEW: Request raw AAC stream
162
- )
163
- )
164
- )
165
-
166
- // When - Record for 1 second
167
- startRecordingSync(recordingOptions)
168
- Thread.sleep(1000)
169
- val result = stopRecordingSync()
170
-
171
- // Then
172
- val compression = when (val comp = result["compression"]) {
173
- is android.os.Bundle -> bundleToMap(comp)
174
- is Map<*, *> -> comp
175
- else -> null
176
- }
177
-
178
- val compressedUri = compression?.get("compressedFileUri") as? String
179
- assertNotNull("Compressed file URI should not be null", compressedUri)
180
-
181
- val file = when {
182
- compressedUri!!.startsWith("file://") -> File(java.net.URI(compressedUri))
183
- compressedUri.startsWith("file:") -> File(java.net.URI(compressedUri))
184
- else -> File(compressedUri)
185
- }
186
-
187
- assertTrue("File should exist", file.exists())
188
- assertTrue("File should have .aac extension", file.name.endsWith(".aac"))
189
-
190
- // Verify it's actually an AAC ADTS file
191
- verifyAacAdtsFormat(file)
192
- }
193
-
194
- @Test
195
- fun testOpusFormat_producesOpus() {
196
- // Skip test if API level is too low for Opus recording
197
- if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.Q) {
198
- println("Skipping Opus test - requires API 29+, current API: ${android.os.Build.VERSION.SDK_INT}")
199
- return
200
- }
201
-
202
- // Given
203
- val recordingOptions = mapOf(
204
- "sampleRate" to 48000,
205
- "channels" to 1,
206
- "encoding" to "pcm_16bit",
207
- "interval" to 100,
208
- "showNotification" to false,
209
- "output" to mapOf(
210
- "primary" to mapOf("enabled" to false),
211
- "compressed" to mapOf(
212
- "enabled" to true,
213
- "format" to "opus"
214
- )
215
- )
216
- )
217
-
218
- // When - Record for 1 second
219
- startRecordingSync(recordingOptions)
220
- Thread.sleep(1000)
221
- val result = stopRecordingSync()
222
-
223
- // Then
224
- val compression = when (val comp = result["compression"]) {
225
- is android.os.Bundle -> bundleToMap(comp)
226
- is Map<*, *> -> comp
227
- else -> null
228
- }
229
-
230
- val compressedUri = compression?.get("compressedFileUri") as? String
231
- assertNotNull("Compressed file URI should not be null", compressedUri)
232
-
233
- val file = when {
234
- compressedUri!!.startsWith("file://") -> File(java.net.URI(compressedUri))
235
- compressedUri.startsWith("file:") -> File(java.net.URI(compressedUri))
236
- else -> File(compressedUri)
237
- }
238
-
239
- assertTrue("File should exist", file.exists())
240
- assertTrue("File should have .opus extension", file.name.endsWith(".opus"))
241
- }
242
-
243
- // Helper methods from existing tests
244
- private fun startRecordingSync(recordingOptions: Map<String, Any?>): Map<String, Any?> {
245
- val startLatch = CountDownLatch(1)
246
- var recordingResult: Map<String, Any?>? = null
247
-
248
- audioRecorderManager.startRecording(recordingOptions, object : Promise {
249
- override fun resolve(value: Any?) {
250
- when (value) {
251
- is android.os.Bundle -> recordingResult = bundleToMap(value)
252
- is Map<*, *> -> {
253
- @Suppress("UNCHECKED_CAST")
254
- recordingResult = value as? Map<String, Any>
255
- }
256
- else -> {
257
- fail("Unexpected start result type: ${value?.javaClass?.name}")
258
- }
259
- }
260
- startLatch.countDown()
261
- }
262
-
263
- override fun reject(code: String, message: String?, cause: Throwable?) {
264
- fail("Recording start failed: $code - $message")
265
- }
266
- })
267
-
268
- assertTrue("Recording should start within 2 seconds", startLatch.await(2, TimeUnit.SECONDS))
269
- return recordingResult ?: throw AssertionError("Recording result should not be null")
270
- }
271
-
272
- private fun stopRecordingSync(): Map<String, Any?> {
273
- val stopLatch = CountDownLatch(1)
274
- var stopResult: Map<String, Any?>? = null
275
-
276
- audioRecorderManager.stopRecording(object : Promise {
277
- override fun resolve(value: Any?) {
278
- when (value) {
279
- is android.os.Bundle -> stopResult = bundleToMap(value)
280
- is Map<*, *> -> {
281
- @Suppress("UNCHECKED_CAST")
282
- stopResult = value as? Map<String, Any>
283
- }
284
- else -> {
285
- fail("Unexpected stop result type: ${value?.javaClass?.name}")
286
- }
287
- }
288
- stopLatch.countDown()
289
- }
290
-
291
- override fun reject(code: String, message: String?, cause: Throwable?) {
292
- fail("Recording stop failed: $code - $message")
293
- }
294
- })
295
-
296
- assertTrue("Recording should stop within 2 seconds", stopLatch.await(2, TimeUnit.SECONDS))
297
- return stopResult ?: throw AssertionError("Stop result should not be null")
298
- }
299
-
300
- private fun bundleToMap(bundle: android.os.Bundle): Map<String, Any?> {
301
- val map = mutableMapOf<String, Any?>()
302
- for (key in bundle.keySet()) {
303
- map[key] = bundle.get(key)
304
- }
305
- return map
306
- }
307
-
308
- private fun verifyM4aFormat(file: File) {
309
- val extractor = MediaExtractor()
310
- try {
311
- extractor.setDataSource(file.absolutePath)
312
- assertTrue("Should have at least one track", extractor.trackCount > 0)
313
-
314
- val format = extractor.getTrackFormat(0)
315
- val mimeType = format.getString(MediaFormat.KEY_MIME)
316
-
317
- // Debug output
318
- println("Detected MIME type: $mimeType")
319
-
320
- // For M4A files, the MIME type should be audio/mp4 or contain aac
321
- val isValidM4aMimeType = mimeType?.let { mime ->
322
- mime.contains("mp4", ignoreCase = true) ||
323
- mime.contains("aac", ignoreCase = true) ||
324
- mime.contains("audio/", ignoreCase = true)
325
- } ?: false
326
-
327
- assertTrue("MIME type should be valid for M4A format, got: $mimeType", isValidM4aMimeType)
328
-
329
- // Read file header to verify MP4 container
330
- val header = file.inputStream().use { it.readNBytes(20) }
331
- val headerString = String(header, Charsets.ISO_8859_1)
332
- val hasFtyp = headerString.contains("ftyp")
333
- assertTrue("File should contain ftyp box (MP4 container)", hasFtyp)
334
- } finally {
335
- extractor.release()
336
- }
337
- }
338
-
339
- private fun verifyAacAdtsFormat(file: File) {
340
- // ADTS header starts with 0xFFF
341
- val header = file.inputStream().use { it.readNBytes(2) }
342
- val syncWord = ((header[0].toInt() and 0xFF) shl 4) or ((header[1].toInt() and 0xF0) shr 4)
343
- assertEquals("ADTS sync word should be 0xFFF", 0xFFF, syncWord)
344
- }
345
- }