@siteed/audio-studio 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 (375) hide show
  1. package/CHANGELOG.md +535 -0
  2. package/LICENSE +21 -0
  3. package/README.md +167 -0
  4. package/android/build.gradle +143 -0
  5. package/android/src/androidTest/assets/chorus.wav +0 -0
  6. package/android/src/androidTest/assets/jfk.wav +0 -0
  7. package/android/src/androidTest/assets/osr_us_000_0010_8k.wav +0 -0
  8. package/android/src/androidTest/assets/recorder_hello_world.wav +0 -0
  9. package/android/src/androidTest/java/net/siteed/audiostudio/AudioProcessorInstrumentedTest.kt +197 -0
  10. package/android/src/androidTest/java/net/siteed/audiostudio/AudioRecorderInstrumentedTest.kt +541 -0
  11. package/android/src/androidTest/java/net/siteed/audiostudio/AudioRecorderPerformanceInstrumentedTest.kt +234 -0
  12. package/android/src/androidTest/java/net/siteed/audiostudio/integration/AudioFocusStrategyIntegrationTest.kt +332 -0
  13. package/android/src/androidTest/java/net/siteed/audiostudio/integration/BufferDurationIntegrationTest.kt +324 -0
  14. package/android/src/androidTest/java/net/siteed/audiostudio/integration/CompressedOnlyOutputTest.kt +253 -0
  15. package/android/src/androidTest/java/net/siteed/audiostudio/integration/DeviceDisconnectionFallbackTest.kt +218 -0
  16. package/android/src/androidTest/java/net/siteed/audiostudio/integration/EventEmissionIntervalTest.kt +120 -0
  17. package/android/src/androidTest/java/net/siteed/audiostudio/integration/M4aFormatTest.kt +345 -0
  18. package/android/src/androidTest/java/net/siteed/audiostudio/integration/OutputControlIntegrationTest.kt +340 -0
  19. package/android/src/androidTest/java/net/siteed/audiostudio/integration/PcmStreamingDurationTest.kt +252 -0
  20. package/android/src/androidTest/java/net/siteed/audiostudio/integration/README.md +95 -0
  21. package/android/src/androidTest/java/net/siteed/audiostudio/integration/run_integration_tests.sh +43 -0
  22. package/android/src/main/AndroidManifest.xml +30 -0
  23. package/android/src/main/CMakeLists.txt +29 -0
  24. package/android/src/main/java/net/siteed/audiostudio/AudioAnalysisData.kt +188 -0
  25. package/android/src/main/java/net/siteed/audiostudio/AudioDataEncoder.kt +9 -0
  26. package/android/src/main/java/net/siteed/audiostudio/AudioDeviceManager.kt +1741 -0
  27. package/android/src/main/java/net/siteed/audiostudio/AudioFeaturesNative.kt +26 -0
  28. package/android/src/main/java/net/siteed/audiostudio/AudioFileHandler.kt +136 -0
  29. package/android/src/main/java/net/siteed/audiostudio/AudioFormatUtils.kt +354 -0
  30. package/android/src/main/java/net/siteed/audiostudio/AudioNotificationsManager.kt +439 -0
  31. package/android/src/main/java/net/siteed/audiostudio/AudioProcessor.kt +2237 -0
  32. package/android/src/main/java/net/siteed/audiostudio/AudioRecorderManager.kt +2163 -0
  33. package/android/src/main/java/net/siteed/audiostudio/AudioRecordingService.kt +167 -0
  34. package/android/src/main/java/net/siteed/audiostudio/AudioStudioModule.kt +1112 -0
  35. package/android/src/main/java/net/siteed/audiostudio/AudioTrimmer.kt +1099 -0
  36. package/android/src/main/java/net/siteed/audiostudio/Constants.kt +37 -0
  37. package/android/src/main/java/net/siteed/audiostudio/EventSender.kt +7 -0
  38. package/android/src/main/java/net/siteed/audiostudio/FFT.kt +100 -0
  39. package/android/src/main/java/net/siteed/audiostudio/Features.kt +98 -0
  40. package/android/src/main/java/net/siteed/audiostudio/LogUtils.kt +93 -0
  41. package/android/src/main/java/net/siteed/audiostudio/MelSpectrogramNative.kt +36 -0
  42. package/android/src/main/java/net/siteed/audiostudio/NotificationConfig.kt +72 -0
  43. package/android/src/main/java/net/siteed/audiostudio/PermissionUtils.kt +68 -0
  44. package/android/src/main/java/net/siteed/audiostudio/RecordingActionReceiver.kt +59 -0
  45. package/android/src/main/java/net/siteed/audiostudio/RecordingConfig.kt +259 -0
  46. package/android/src/main/java/net/siteed/audiostudio/WaveformConfig.kt +19 -0
  47. package/android/src/main/java/net/siteed/audiostudio/WaveformRenderer.kt +159 -0
  48. package/android/src/main/jni/AudioFeaturesJNI.cpp +152 -0
  49. package/android/src/main/jni/MelSpectrogramJNI.cpp +165 -0
  50. package/android/src/main/res/drawable/ic_default_action_icon.xml +16 -0
  51. package/android/src/main/res/drawable/ic_microphone.xml +13 -0
  52. package/android/src/main/res/drawable/ic_pause.xml +10 -0
  53. package/android/src/main/res/drawable/ic_play.xml +10 -0
  54. package/android/src/main/res/drawable/ic_stop.xml +10 -0
  55. package/android/src/main/res/layout/notification_recording.xml +37 -0
  56. package/android/src/test/java/net/siteed/audiostudio/AudioFileHandlerTest.kt +279 -0
  57. package/android/src/test/java/net/siteed/audiostudio/AudioFocusStrategyTest.kt +249 -0
  58. package/android/src/test/java/net/siteed/audiostudio/AudioFormatTest.kt +151 -0
  59. package/android/src/test/java/net/siteed/audiostudio/AudioFormatUtilsTest.kt +273 -0
  60. package/android/src/test/java/net/siteed/audiostudio/DeviceDisconnectionFallbackUnitTest.kt +140 -0
  61. package/android/src/test/resources/chorus.wav +0 -0
  62. package/android/src/test/resources/generate_test_audio.py +94 -0
  63. package/android/src/test/resources/jfk.wav +0 -0
  64. package/android/src/test/resources/osr_us_000_0010_8k.wav +0 -0
  65. package/android/src/test/resources/recorder_hello_world.wav +0 -0
  66. package/app.plugin.js +3 -0
  67. package/build/cjs/AudioAnalysis/AudioAnalysis.types.js +4 -0
  68. package/build/cjs/AudioAnalysis/AudioAnalysis.types.js.map +1 -0
  69. package/build/cjs/AudioAnalysis/audioFeaturesWasm.js +164 -0
  70. package/build/cjs/AudioAnalysis/audioFeaturesWasm.js.map +1 -0
  71. package/build/cjs/AudioAnalysis/extractAudioAnalysis.js +213 -0
  72. package/build/cjs/AudioAnalysis/extractAudioAnalysis.js.map +1 -0
  73. package/build/cjs/AudioAnalysis/extractAudioData.js +21 -0
  74. package/build/cjs/AudioAnalysis/extractAudioData.js.map +1 -0
  75. package/build/cjs/AudioAnalysis/extractMelSpectrogram.js +90 -0
  76. package/build/cjs/AudioAnalysis/extractMelSpectrogram.js.map +1 -0
  77. package/build/cjs/AudioAnalysis/extractPreview.js +28 -0
  78. package/build/cjs/AudioAnalysis/extractPreview.js.map +1 -0
  79. package/build/cjs/AudioAnalysis/extractWaveform.js +18 -0
  80. package/build/cjs/AudioAnalysis/extractWaveform.js.map +1 -0
  81. package/build/cjs/AudioAnalysis/melSpectrogramWasm.js +149 -0
  82. package/build/cjs/AudioAnalysis/melSpectrogramWasm.js.map +1 -0
  83. package/build/cjs/AudioDeviceManager.js +688 -0
  84. package/build/cjs/AudioDeviceManager.js.map +1 -0
  85. package/build/cjs/AudioRecorder.provider.js +78 -0
  86. package/build/cjs/AudioRecorder.provider.js.map +1 -0
  87. package/build/cjs/AudioStudio.native.js +8 -0
  88. package/build/cjs/AudioStudio.native.js.map +1 -0
  89. package/build/cjs/AudioStudio.types.js +11 -0
  90. package/build/cjs/AudioStudio.types.js.map +1 -0
  91. package/build/cjs/AudioStudio.web.js +708 -0
  92. package/build/cjs/AudioStudio.web.js.map +1 -0
  93. package/build/cjs/AudioStudioModule.js +718 -0
  94. package/build/cjs/AudioStudioModule.js.map +1 -0
  95. package/build/cjs/WebRecorder.web.js +865 -0
  96. package/build/cjs/WebRecorder.web.js.map +1 -0
  97. package/build/cjs/constants/platformLimitations.js +99 -0
  98. package/build/cjs/constants/platformLimitations.js.map +1 -0
  99. package/build/cjs/constants.js +20 -0
  100. package/build/cjs/constants.js.map +1 -0
  101. package/build/cjs/events.js +29 -0
  102. package/build/cjs/events.js.map +1 -0
  103. package/build/cjs/hooks/useAudioDevices.js +179 -0
  104. package/build/cjs/hooks/useAudioDevices.js.map +1 -0
  105. package/build/cjs/index.js +64 -0
  106. package/build/cjs/index.js.map +1 -0
  107. package/build/cjs/trimAudio.js +76 -0
  108. package/build/cjs/trimAudio.js.map +1 -0
  109. package/build/cjs/useAudioRecorder.js +535 -0
  110. package/build/cjs/useAudioRecorder.js.map +1 -0
  111. package/build/cjs/utils/BlobFix.js +502 -0
  112. package/build/cjs/utils/BlobFix.js.map +1 -0
  113. package/build/cjs/utils/audioProcessing.js +136 -0
  114. package/build/cjs/utils/audioProcessing.js.map +1 -0
  115. package/build/cjs/utils/cleanNativeOptions.js +22 -0
  116. package/build/cjs/utils/cleanNativeOptions.js.map +1 -0
  117. package/build/cjs/utils/concatenateBuffers.js +25 -0
  118. package/build/cjs/utils/concatenateBuffers.js.map +1 -0
  119. package/build/cjs/utils/convertPCMToFloat32.js +124 -0
  120. package/build/cjs/utils/convertPCMToFloat32.js.map +1 -0
  121. package/build/cjs/utils/crc32.js +52 -0
  122. package/build/cjs/utils/crc32.js.map +1 -0
  123. package/build/cjs/utils/encodingToBitDepth.js +17 -0
  124. package/build/cjs/utils/encodingToBitDepth.js.map +1 -0
  125. package/build/cjs/utils/getWavFileInfo.js +96 -0
  126. package/build/cjs/utils/getWavFileInfo.js.map +1 -0
  127. package/build/cjs/utils/writeWavHeader.js +88 -0
  128. package/build/cjs/utils/writeWavHeader.js.map +1 -0
  129. package/build/cjs/workers/InlineFeaturesExtractor.web.js +294 -0
  130. package/build/cjs/workers/InlineFeaturesExtractor.web.js.map +1 -0
  131. package/build/cjs/workers/inlineAudioWebWorker.web.js +190 -0
  132. package/build/cjs/workers/inlineAudioWebWorker.web.js.map +1 -0
  133. package/build/cjs/workers/wasmGlueString.web.js +27 -0
  134. package/build/cjs/workers/wasmGlueString.web.js.map +1 -0
  135. package/build/esm/AudioAnalysis/AudioAnalysis.types.js +3 -0
  136. package/build/esm/AudioAnalysis/AudioAnalysis.types.js.map +1 -0
  137. package/build/esm/AudioAnalysis/audioFeaturesWasm.js +126 -0
  138. package/build/esm/AudioAnalysis/audioFeaturesWasm.js.map +1 -0
  139. package/build/esm/AudioAnalysis/extractAudioAnalysis.js +205 -0
  140. package/build/esm/AudioAnalysis/extractAudioAnalysis.js.map +1 -0
  141. package/build/esm/AudioAnalysis/extractAudioData.js +14 -0
  142. package/build/esm/AudioAnalysis/extractAudioData.js.map +1 -0
  143. package/build/esm/AudioAnalysis/extractMelSpectrogram.js +86 -0
  144. package/build/esm/AudioAnalysis/extractMelSpectrogram.js.map +1 -0
  145. package/build/esm/AudioAnalysis/extractPreview.js +25 -0
  146. package/build/esm/AudioAnalysis/extractPreview.js.map +1 -0
  147. package/build/esm/AudioAnalysis/extractWaveform.js +11 -0
  148. package/build/esm/AudioAnalysis/extractWaveform.js.map +1 -0
  149. package/build/esm/AudioAnalysis/melSpectrogramWasm.js +111 -0
  150. package/build/esm/AudioAnalysis/melSpectrogramWasm.js.map +1 -0
  151. package/build/esm/AudioDeviceManager.js +681 -0
  152. package/build/esm/AudioDeviceManager.js.map +1 -0
  153. package/build/esm/AudioRecorder.provider.js +40 -0
  154. package/build/esm/AudioRecorder.provider.js.map +1 -0
  155. package/build/esm/AudioStudio.native.js +6 -0
  156. package/build/esm/AudioStudio.native.js.map +1 -0
  157. package/build/esm/AudioStudio.types.js +8 -0
  158. package/build/esm/AudioStudio.types.js.map +1 -0
  159. package/build/esm/AudioStudio.web.js +704 -0
  160. package/build/esm/AudioStudio.web.js.map +1 -0
  161. package/build/esm/AudioStudioModule.js +713 -0
  162. package/build/esm/AudioStudioModule.js.map +1 -0
  163. package/build/esm/WebRecorder.web.js +861 -0
  164. package/build/esm/WebRecorder.web.js.map +1 -0
  165. package/build/esm/constants/platformLimitations.js +90 -0
  166. package/build/esm/constants/platformLimitations.js.map +1 -0
  167. package/build/esm/constants.js +17 -0
  168. package/build/esm/constants.js.map +1 -0
  169. package/build/esm/events.js +21 -0
  170. package/build/esm/events.js.map +1 -0
  171. package/build/esm/hooks/useAudioDevices.js +176 -0
  172. package/build/esm/hooks/useAudioDevices.js.map +1 -0
  173. package/build/esm/index.js +23 -0
  174. package/build/esm/index.js.map +1 -0
  175. package/build/esm/trimAudio.js +69 -0
  176. package/build/esm/trimAudio.js.map +1 -0
  177. package/build/esm/useAudioRecorder.js +529 -0
  178. package/build/esm/useAudioRecorder.js.map +1 -0
  179. package/build/esm/utils/BlobFix.js +498 -0
  180. package/build/esm/utils/BlobFix.js.map +1 -0
  181. package/build/esm/utils/audioProcessing.js +133 -0
  182. package/build/esm/utils/audioProcessing.js.map +1 -0
  183. package/build/esm/utils/cleanNativeOptions.js +19 -0
  184. package/build/esm/utils/cleanNativeOptions.js.map +1 -0
  185. package/build/esm/utils/concatenateBuffers.js +21 -0
  186. package/build/esm/utils/concatenateBuffers.js.map +1 -0
  187. package/build/esm/utils/convertPCMToFloat32.js +120 -0
  188. package/build/esm/utils/convertPCMToFloat32.js.map +1 -0
  189. package/build/esm/utils/crc32.js +50 -0
  190. package/build/esm/utils/crc32.js.map +1 -0
  191. package/build/esm/utils/encodingToBitDepth.js +13 -0
  192. package/build/esm/utils/encodingToBitDepth.js.map +1 -0
  193. package/build/esm/utils/getWavFileInfo.js +92 -0
  194. package/build/esm/utils/getWavFileInfo.js.map +1 -0
  195. package/build/esm/utils/writeWavHeader.js +84 -0
  196. package/build/esm/utils/writeWavHeader.js.map +1 -0
  197. package/build/esm/workers/InlineFeaturesExtractor.web.js +291 -0
  198. package/build/esm/workers/InlineFeaturesExtractor.web.js.map +1 -0
  199. package/build/esm/workers/inlineAudioWebWorker.web.js +187 -0
  200. package/build/esm/workers/inlineAudioWebWorker.web.js.map +1 -0
  201. package/build/esm/workers/wasmGlueString.web.js +24 -0
  202. package/build/esm/workers/wasmGlueString.web.js.map +1 -0
  203. package/build/types/AudioAnalysis/AudioAnalysis.types.d.ts +198 -0
  204. package/build/types/AudioAnalysis/AudioAnalysis.types.d.ts.map +1 -0
  205. package/build/types/AudioAnalysis/audioFeaturesWasm.d.ts +24 -0
  206. package/build/types/AudioAnalysis/audioFeaturesWasm.d.ts.map +1 -0
  207. package/build/types/AudioAnalysis/extractAudioAnalysis.d.ts +74 -0
  208. package/build/types/AudioAnalysis/extractAudioAnalysis.d.ts.map +1 -0
  209. package/build/types/AudioAnalysis/extractAudioData.d.ts +3 -0
  210. package/build/types/AudioAnalysis/extractAudioData.d.ts.map +1 -0
  211. package/build/types/AudioAnalysis/extractMelSpectrogram.d.ts +20 -0
  212. package/build/types/AudioAnalysis/extractMelSpectrogram.d.ts.map +1 -0
  213. package/build/types/AudioAnalysis/extractPreview.d.ts +11 -0
  214. package/build/types/AudioAnalysis/extractPreview.d.ts.map +1 -0
  215. package/build/types/AudioAnalysis/extractWaveform.d.ts +8 -0
  216. package/build/types/AudioAnalysis/extractWaveform.d.ts.map +1 -0
  217. package/build/types/AudioAnalysis/melSpectrogramWasm.d.ts +16 -0
  218. package/build/types/AudioAnalysis/melSpectrogramWasm.d.ts.map +1 -0
  219. package/build/types/AudioDeviceManager.d.ts +187 -0
  220. package/build/types/AudioDeviceManager.d.ts.map +1 -0
  221. package/build/types/AudioRecorder.provider.d.ts +11 -0
  222. package/build/types/AudioRecorder.provider.d.ts.map +1 -0
  223. package/build/types/AudioStudio.native.d.ts +3 -0
  224. package/build/types/AudioStudio.native.d.ts.map +1 -0
  225. package/build/types/AudioStudio.types.d.ts +760 -0
  226. package/build/types/AudioStudio.types.d.ts.map +1 -0
  227. package/build/types/AudioStudio.web.d.ts +96 -0
  228. package/build/types/AudioStudio.web.d.ts.map +1 -0
  229. package/build/types/AudioStudioModule.d.ts +3 -0
  230. package/build/types/AudioStudioModule.d.ts.map +1 -0
  231. package/build/types/WebRecorder.web.d.ts +208 -0
  232. package/build/types/WebRecorder.web.d.ts.map +1 -0
  233. package/build/types/constants/platformLimitations.d.ts +40 -0
  234. package/build/types/constants/platformLimitations.d.ts.map +1 -0
  235. package/build/types/constants.d.ts +14 -0
  236. package/build/types/constants.d.ts.map +1 -0
  237. package/build/types/events.d.ts +29 -0
  238. package/build/types/events.d.ts.map +1 -0
  239. package/build/types/hooks/useAudioDevices.d.ts +15 -0
  240. package/build/types/hooks/useAudioDevices.d.ts.map +1 -0
  241. package/build/types/index.d.ts +21 -0
  242. package/build/types/index.d.ts.map +1 -0
  243. package/build/types/trimAudio.d.ts +25 -0
  244. package/build/types/trimAudio.d.ts.map +1 -0
  245. package/build/types/useAudioRecorder.d.ts +22 -0
  246. package/build/types/useAudioRecorder.d.ts.map +1 -0
  247. package/build/types/utils/BlobFix.d.ts +9 -0
  248. package/build/types/utils/BlobFix.d.ts.map +1 -0
  249. package/build/types/utils/audioProcessing.d.ts +24 -0
  250. package/build/types/utils/audioProcessing.d.ts.map +1 -0
  251. package/build/types/utils/cleanNativeOptions.d.ts +15 -0
  252. package/build/types/utils/cleanNativeOptions.d.ts.map +1 -0
  253. package/build/types/utils/concatenateBuffers.d.ts +8 -0
  254. package/build/types/utils/concatenateBuffers.d.ts.map +1 -0
  255. package/build/types/utils/convertPCMToFloat32.d.ts +13 -0
  256. package/build/types/utils/convertPCMToFloat32.d.ts.map +1 -0
  257. package/build/types/utils/crc32.d.ts +7 -0
  258. package/build/types/utils/crc32.d.ts.map +1 -0
  259. package/build/types/utils/encodingToBitDepth.d.ts +5 -0
  260. package/build/types/utils/encodingToBitDepth.d.ts.map +1 -0
  261. package/build/types/utils/getWavFileInfo.d.ts +26 -0
  262. package/build/types/utils/getWavFileInfo.d.ts.map +1 -0
  263. package/build/types/utils/writeWavHeader.d.ts +34 -0
  264. package/build/types/utils/writeWavHeader.d.ts.map +1 -0
  265. package/build/types/workers/InlineFeaturesExtractor.web.d.ts +2 -0
  266. package/build/types/workers/InlineFeaturesExtractor.web.d.ts.map +1 -0
  267. package/build/types/workers/inlineAudioWebWorker.web.d.ts +2 -0
  268. package/build/types/workers/inlineAudioWebWorker.web.d.ts.map +1 -0
  269. package/build/types/workers/wasmGlueString.web.d.ts +2 -0
  270. package/build/types/workers/wasmGlueString.web.d.ts.map +1 -0
  271. package/cpp/AudioFeatures.cpp +274 -0
  272. package/cpp/AudioFeatures.h +85 -0
  273. package/cpp/AudioFeaturesBridge.cpp +146 -0
  274. package/cpp/AudioFeaturesBridge.h +47 -0
  275. package/cpp/MelSpectrogram.cpp +227 -0
  276. package/cpp/MelSpectrogram.h +82 -0
  277. package/cpp/MelSpectrogramBridge.cpp +112 -0
  278. package/cpp/MelSpectrogramBridge.h +33 -0
  279. package/cpp/kiss_fft/COPYING +11 -0
  280. package/cpp/kiss_fft/_kiss_fft_guts.h +167 -0
  281. package/cpp/kiss_fft/kiss_fft.c +424 -0
  282. package/cpp/kiss_fft/kiss_fft.h +160 -0
  283. package/cpp/kiss_fft/kiss_fft_log.h +36 -0
  284. package/cpp/kiss_fft/kiss_fftr.c +155 -0
  285. package/cpp/kiss_fft/kiss_fftr.h +54 -0
  286. package/expo-module.config.json +10 -0
  287. package/ios/AudioAnalysisData.swift +74 -0
  288. package/ios/AudioDeviceManager.swift +670 -0
  289. package/ios/AudioFeaturesWrapper.h +21 -0
  290. package/ios/AudioFeaturesWrapper.mm +63 -0
  291. package/ios/AudioNotificationManager.swift +154 -0
  292. package/ios/AudioProcessingHelpers.swift +797 -0
  293. package/ios/AudioProcessor.swift +1191 -0
  294. package/ios/AudioStreamError.swift +7 -0
  295. package/ios/AudioStreamManager.swift +2369 -0
  296. package/ios/AudioStreamManagerDelegate.swift +16 -0
  297. package/ios/AudioStudio.podspec +39 -0
  298. package/ios/AudioStudioModule.swift +1111 -0
  299. package/ios/AudioStudioTests/AudioFileHandlerTests.swift +338 -0
  300. package/ios/AudioStudioTests/AudioFormatUtilsTests.swift +331 -0
  301. package/ios/AudioStudioTests/AudioTestHelpers.swift +130 -0
  302. package/ios/AudioStudioTests/CompressedOnlyOutputTests.swift +294 -0
  303. package/ios/AudioStudioTests/EventEmissionIntervalTests.swift +105 -0
  304. package/ios/AudioStudioTests/Info.plist +22 -0
  305. package/ios/AudioStudioTests/README.md +39 -0
  306. package/ios/AudioStudioTests/SimpleAudioTest.swift +98 -0
  307. package/ios/AudioStudioTests/TestAudioGenerator.swift +75 -0
  308. package/ios/DataPoint.swift +54 -0
  309. package/ios/DecodingConfig.swift +59 -0
  310. package/ios/FFT.swift +62 -0
  311. package/ios/Features.swift +95 -0
  312. package/ios/ISSUE_IOS.md +68 -0
  313. package/ios/Logger.swift +39 -0
  314. package/ios/MelSpectrogramWrapper.h +30 -0
  315. package/ios/MelSpectrogramWrapper.mm +97 -0
  316. package/ios/NotificationExtension.swift +15 -0
  317. package/ios/RecordingResult.swift +22 -0
  318. package/ios/RecordingSettings.swift +311 -0
  319. package/ios/WaveformExtractor.swift +105 -0
  320. package/ios/tests/README.md +41 -0
  321. package/ios/tests/integration/buffer_and_fallback_test.swift +178 -0
  322. package/ios/tests/integration/buffer_duration_test.swift +185 -0
  323. package/ios/tests/integration/compressed_only_output_test.swift +271 -0
  324. package/ios/tests/integration/output_control_test.swift +322 -0
  325. package/ios/tests/integration/run_integration_tests.sh +37 -0
  326. package/ios/tests/opus_support_test_macos.swift +154 -0
  327. package/ios/tests/standalone/audio_processing_test.swift +144 -0
  328. package/ios/tests/standalone/audio_recording_test.swift +277 -0
  329. package/ios/tests/standalone/audio_streaming_test.swift +249 -0
  330. package/ios/tests/standalone/standalone_test.swift +144 -0
  331. package/package.json +146 -0
  332. package/plugin/build/index.cjs +194 -0
  333. package/plugin/build/index.d.cts +22 -0
  334. package/plugin/build/index.js +194 -0
  335. package/plugin/src/index.ts +285 -0
  336. package/plugin/tsconfig.json +10 -0
  337. package/plugin/tsconfig.tsbuildinfo +1 -0
  338. package/prebuilt/wasm/mel-spectrogram.js +18 -0
  339. package/src/AudioAnalysis/AudioAnalysis.types.ts +226 -0
  340. package/src/AudioAnalysis/audio-features-wasm.d.ts +37 -0
  341. package/src/AudioAnalysis/audioFeaturesWasm.ts +200 -0
  342. package/src/AudioAnalysis/extractAudioAnalysis.ts +350 -0
  343. package/src/AudioAnalysis/extractAudioData.ts +17 -0
  344. package/src/AudioAnalysis/extractMelSpectrogram.ts +140 -0
  345. package/src/AudioAnalysis/extractPreview.ts +34 -0
  346. package/src/AudioAnalysis/extractWaveform.ts +22 -0
  347. package/src/AudioAnalysis/mel-spectrogram-wasm.d.ts +48 -0
  348. package/src/AudioAnalysis/melSpectrogramWasm.ts +179 -0
  349. package/src/AudioDeviceManager.ts +800 -0
  350. package/src/AudioRecorder.provider.tsx +57 -0
  351. package/src/AudioStudio.native.ts +6 -0
  352. package/src/AudioStudio.types.ts +899 -0
  353. package/src/AudioStudio.web.ts +911 -0
  354. package/src/AudioStudioModule.ts +984 -0
  355. package/src/WebRecorder.web.ts +1114 -0
  356. package/src/constants/platformLimitations.ts +118 -0
  357. package/src/constants.ts +21 -0
  358. package/src/events.ts +63 -0
  359. package/src/hooks/useAudioDevices.ts +213 -0
  360. package/src/index.ts +67 -0
  361. package/src/trimAudio.ts +94 -0
  362. package/src/types/crc-32.d.ts +9 -0
  363. package/src/useAudioRecorder.tsx +784 -0
  364. package/src/utils/BlobFix.ts +561 -0
  365. package/src/utils/audioProcessing.ts +205 -0
  366. package/src/utils/cleanNativeOptions.ts +18 -0
  367. package/src/utils/concatenateBuffers.ts +24 -0
  368. package/src/utils/convertPCMToFloat32.ts +170 -0
  369. package/src/utils/crc32.ts +59 -0
  370. package/src/utils/encodingToBitDepth.ts +18 -0
  371. package/src/utils/getWavFileInfo.ts +132 -0
  372. package/src/utils/writeWavHeader.ts +115 -0
  373. package/src/workers/InlineFeaturesExtractor.web.tsx +291 -0
  374. package/src/workers/inlineAudioWebWorker.web.tsx +186 -0
  375. package/src/workers/wasmGlueString.web.ts +23 -0
package/package.json ADDED
@@ -0,0 +1,146 @@
1
+ {
2
+ "name": "@siteed/audio-studio",
3
+ "version": "3.0.0",
4
+ "description": "Comprehensive audio processing library for React Native and Expo with recording, analysis, visualization, and streaming capabilities across iOS, Android, and web",
5
+ "license": "MIT",
6
+ "type": "commonjs",
7
+ "main": "./build/cjs/index.js",
8
+ "module": "./build/esm/index.js",
9
+ "types": "./build/types/index.d.ts",
10
+ "expo": {
11
+ "plugin": "./app.plugin.js"
12
+ },
13
+ "author": "Arthur Breton <abreton@siteed.net> (https://github.com/deeeed)",
14
+ "homepage": "https://github.com/deeeed/audiolab/blob/main/packages/audio-studio/README.md",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/deeeed/audiolab.git",
18
+ "directory": "packages/audio-studio"
19
+ },
20
+ "bugs": {
21
+ "url": "https://github.com/deeeed/audiolab/issues"
22
+ },
23
+ "keywords": [
24
+ "react-native",
25
+ "expo",
26
+ "audio",
27
+ "recording",
28
+ "audio-analysis",
29
+ "audio-processing",
30
+ "audio-visualization",
31
+ "waveform",
32
+ "spectrogram",
33
+ "mel-spectrogram",
34
+ "mfcc",
35
+ "audio-features",
36
+ "audio-compression",
37
+ "opus",
38
+ "aac",
39
+ "pcm",
40
+ "wav",
41
+ "cross-platform",
42
+ "background-recording",
43
+ "audio-trimming",
44
+ "dual-stream"
45
+ ],
46
+ "files": [
47
+ "src",
48
+ "android",
49
+ "ios",
50
+ "cpp",
51
+ "plugin",
52
+ "app.plugin.js",
53
+ "LICENSE",
54
+ "CHANGELOG.md",
55
+ "generated",
56
+ "expo-module.config.json",
57
+ "README.md",
58
+ "package.json",
59
+ "*.podspec",
60
+ "prebuilt",
61
+ "build",
62
+ "!ios/build",
63
+ "!android/build",
64
+ "!android/gradle",
65
+ "!android/gradlew",
66
+ "!android/gradlew.bat",
67
+ "!android/local.properties",
68
+ "!**/__tests__",
69
+ "!**/__fixtures__",
70
+ "!**/__mocks__",
71
+ "!**/.*"
72
+ ],
73
+ "scripts": {
74
+ "build:wasm": "bash scripts/build-wasm.sh",
75
+ "build": "rimraf build && yarn build:types && yarn build:cjs && yarn build:esm && yarn build:plugin",
76
+ "build:cjs": "tsc -p tsconfig.cjs.json",
77
+ "build:esm": "tsc -p tsconfig.esm.json",
78
+ "build:types": "tsc -p tsconfig.types.json",
79
+ "build:plugin": "tsc --project plugin/tsconfig.json && cp plugin/build/index.js plugin/build/index.cjs",
80
+ "build:plugin:dev": "expo-module build plugin",
81
+ "build:dev": "expo-module build",
82
+ "clean": "expo-module clean && rimraf build plugin/build",
83
+ "lint": "expo-module lint",
84
+ "lint:fix": "expo-module lint --fix",
85
+ "test": "expo-module test",
86
+ "test:android": "yarn test:android:unit && yarn test:android:instrumented",
87
+ "test:android:unit": "cd ../../apps/playground/android && ./gradlew :siteed-expo-audio-studio:test",
88
+ "test:android:instrumented": "cd ../../apps/playground/android && ./gradlew :siteed-expo-audio-studio:connectedAndroidTest",
89
+ "test:android:unit:watch": "cd ../../apps/playground/android && ./gradlew :siteed-expo-audio-studio:test --continuous",
90
+ "test:ios": "cd ../../apps/playground/ios && xcodebuild -workspace AudioDevPlayground.xcworkspace -scheme AudioDevPlayground -destination 'platform=iOS Simulator,name=iPhone 15' build",
91
+ "test:coverage": "cd ../../apps/playground/android && ./gradlew :siteed-expo-audio-studio:jacocoTestReport",
92
+ "typecheck": "tsc --noEmit",
93
+ "docgen": "typedoc src/index.ts --plugin typedoc-plugin-markdown --readme none --out ../../documentation_site/docs/api-reference/API && node ../../scripts/escape-mdx-generics.js ../../documentation_site/docs/api-reference",
94
+ "prepare": "yarn build && node -e \"require('fs').renameSync('./plugin/build/index.d.ts', './plugin/build/index.d.cts')\"",
95
+ "prepublishOnly.disabled": "expo-module prepublishOnly",
96
+ "expo-module": "expo-module",
97
+ "open:ios": "open -a \"Xcode\" ../../apps/playground/ios",
98
+ "open:android": "open -a \"Android Studio\" ../../apps/playground/android",
99
+ "size": "bundle-size && size-limit",
100
+ "release": "./publish.sh",
101
+ "agent:test:unit": "yarn test:android:unit",
102
+ "agent:test:integration": "yarn test:android:instrumented",
103
+ "agent:compilation:check": "yarn typecheck && yarn build"
104
+ },
105
+ "devDependencies": {
106
+ "@expo/config-plugins": "~54.0.0",
107
+ "@expo/npm-proofread": "^1.0.1",
108
+ "@siteed/publisher": "^0.4.18",
109
+ "@size-limit/preset-big-lib": "^11.1.4",
110
+ "@types/jest": "^29.5.12",
111
+ "@types/node": "^20.12.7",
112
+ "@types/react": "~19.0.10",
113
+ "@typescript-eslint/eslint-plugin": "^7.7.0",
114
+ "@typescript-eslint/parser": "^7.7.0",
115
+ "bundle-size": "^1.1.5",
116
+ "eslint": "^8.56.0",
117
+ "eslint-config-prettier": "^9.1.0",
118
+ "eslint-config-universe": "^12.0.0",
119
+ "eslint-plugin-import": "^2.29.1",
120
+ "eslint-plugin-prettier": "^5.1.3",
121
+ "eslint-plugin-promise": "^6.1.1",
122
+ "eslint-plugin-react": "^7.34.1",
123
+ "expo": "^54.0.0",
124
+ "expo-module-scripts": "^4.1.7",
125
+ "expo-modules-core": "~3.0.0",
126
+ "jest": "^29.7.0",
127
+ "prettier": "^3.2.5",
128
+ "react": "19.1.0",
129
+ "react-native": "0.81.5",
130
+ "rimraf": "^6.0.1",
131
+ "size-limit": "^11.1.4",
132
+ "ts-node": "^10.9.2",
133
+ "typedoc": "^0.27.4",
134
+ "typedoc-plugin-markdown": "~4.4.2",
135
+ "typescript": "~5.8.3"
136
+ },
137
+ "peerDependencies": {
138
+ "expo": ">=52.0.0",
139
+ "react": "*",
140
+ "react-native": "*"
141
+ },
142
+ "publishConfig": {
143
+ "access": "public",
144
+ "registry": "https://registry.npmjs.org"
145
+ }
146
+ }
@@ -0,0 +1,194 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const config_plugins_1 = require("@expo/config-plugins");
4
+ const MICROPHONE_USAGE = 'Allow $(PRODUCT_NAME) to access your microphone';
5
+ const NOTIFICATION_USAGE = 'Show recording notifications and controls';
6
+ const LOG_PREFIX = '[@siteed/expo-audio-studio]';
7
+ function debugLog(message, ...args) {
8
+ if (process.env.EXPO_DEBUG) {
9
+ console.log(`${LOG_PREFIX} ${message}`, ...args);
10
+ }
11
+ }
12
+ const withRecordingPermission = (config, props) => {
13
+ const options = {
14
+ enablePhoneStateHandling: true, // Default to true for backward compatibility
15
+ enableNotifications: true,
16
+ enableBackgroundAudio: true,
17
+ enableDeviceDetection: true, // Default to true for backward compatibility
18
+ iosBackgroundModes: {
19
+ useVoIP: false,
20
+ useAudio: false,
21
+ useProcessing: false,
22
+ useLocation: false,
23
+ useExternalAccessory: false,
24
+ },
25
+ iosConfig: {
26
+ microphoneUsageDescription: MICROPHONE_USAGE,
27
+ notificationUsageDescription: NOTIFICATION_USAGE,
28
+ },
29
+ ...(props || {}),
30
+ };
31
+ const { enablePhoneStateHandling, enableNotifications, enableBackgroundAudio, enableDeviceDetection, } = options;
32
+ debugLog('📱 Configuring Recording Permissions Plugin...', options);
33
+ // iOS Configuration
34
+ config = (0, config_plugins_1.withInfoPlist)(config, (config) => {
35
+ // Always set the microphone usage description from options first
36
+ config.modResults['NSMicrophoneUsageDescription'] =
37
+ options.iosConfig?.microphoneUsageDescription ||
38
+ config.modResults['NSMicrophoneUsageDescription'] ||
39
+ MICROPHONE_USAGE;
40
+ if (enableNotifications) {
41
+ config.modResults['NSUserNotificationsUsageDescription'] =
42
+ options.iosConfig?.notificationUsageDescription ||
43
+ config.modResults['NSUserNotificationsUsageDescription'] ||
44
+ NOTIFICATION_USAGE;
45
+ config.modResults['NSUserNotificationAlertStyle'] = 'alert';
46
+ }
47
+ const existingBackgroundModes = config.modResults.UIBackgroundModes || [];
48
+ // If background audio is enabled with useAudio, add the audio background mode
49
+ if (options.iosBackgroundModes?.useAudio === true &&
50
+ enableBackgroundAudio === true &&
51
+ !existingBackgroundModes.includes('audio')) {
52
+ // Add 'audio' background mode - REQUIRED for background recording
53
+ existingBackgroundModes.push('audio');
54
+ debugLog('✅ Added audio background mode for iOS background recording');
55
+ // Also ensure processing mode is recommended
56
+ if (options.iosBackgroundModes?.useProcessing !== true) {
57
+ console.warn(`${LOG_PREFIX} Warning: Background audio recording works best with both 'audio' and 'processing' background modes. Consider enabling 'useProcessing' in iosBackgroundModes.`);
58
+ }
59
+ }
60
+ if (options.iosBackgroundModes?.useVoIP === true &&
61
+ enablePhoneStateHandling === true) {
62
+ if (!existingBackgroundModes.includes('voip')) {
63
+ existingBackgroundModes.push('voip');
64
+ }
65
+ const existingCapabilities = (config.modResults
66
+ .UIRequiredDeviceCapabilities || []);
67
+ if (!existingCapabilities.includes('telephony')) {
68
+ existingCapabilities.push('telephony');
69
+ }
70
+ config.modResults.UIRequiredDeviceCapabilities =
71
+ existingCapabilities;
72
+ }
73
+ // Add additional background modes only if explicitly set to true
74
+ if (options.iosBackgroundModes?.useProcessing === true) {
75
+ if (!existingBackgroundModes.includes('processing')) {
76
+ existingBackgroundModes.push('processing');
77
+ }
78
+ // Add processing info if enabled
79
+ // Note: We keep the 'audiostream' namespace for native modules to maintain compatibility
80
+ config.modResults.BGTaskSchedulerPermittedIdentifiers = [
81
+ 'com.siteed.audiostream.processing',
82
+ ];
83
+ }
84
+ if (options.iosBackgroundModes?.useLocation === true) {
85
+ if (!existingBackgroundModes.includes('location')) {
86
+ existingBackgroundModes.push('location');
87
+ }
88
+ }
89
+ if (options.iosBackgroundModes?.useExternalAccessory === true) {
90
+ if (!existingBackgroundModes.includes('external-accessory')) {
91
+ existingBackgroundModes.push('external-accessory');
92
+ }
93
+ }
94
+ // Configure background processing info if enabled
95
+ if (options.iosConfig?.backgroundProcessingTitle) {
96
+ config.modResults.BGProcessingTaskTitle =
97
+ options.iosConfig.backgroundProcessingTitle;
98
+ }
99
+ // Configure audio session behavior
100
+ if (options.iosConfig?.allowBackgroundAudioControls) {
101
+ config.modResults.UIBackgroundModes = [
102
+ ...existingBackgroundModes,
103
+ 'remote-notification',
104
+ ];
105
+ config.modResults.MPNowPlayingInfoPropertyPlaybackRate = true;
106
+ }
107
+ config.modResults.UIBackgroundModes = existingBackgroundModes;
108
+ return config;
109
+ });
110
+ // Android Configuration
111
+ config = (0, config_plugins_1.withAndroidManifest)(config, (config) => {
112
+ const basePermissions = ['android.permission.RECORD_AUDIO'];
113
+ const optionalPermissions = [
114
+ enableNotifications && 'android.permission.POST_NOTIFICATIONS',
115
+ enablePhoneStateHandling && 'android.permission.READ_PHONE_STATE', // Only add if enabled
116
+ enableBackgroundAudio && 'android.permission.FOREGROUND_SERVICE',
117
+ enableBackgroundAudio &&
118
+ 'android.permission.FOREGROUND_SERVICE_MICROPHONE',
119
+ enableBackgroundAudio && 'android.permission.WAKE_LOCK', // Keep device awake during background recording
120
+ // Device detection permissions (only if enabled)
121
+ enableDeviceDetection && 'android.permission.BLUETOOTH',
122
+ enableDeviceDetection && 'android.permission.BLUETOOTH_ADMIN',
123
+ enableDeviceDetection && 'android.permission.BLUETOOTH_CONNECT',
124
+ enableDeviceDetection && 'android.permission.USB_PERMISSION',
125
+ ].filter(Boolean);
126
+ const permissionsToAdd = [...basePermissions, ...optionalPermissions];
127
+ debugLog('📋 Existing Android permissions:', config.modResults.manifest['uses-permission']?.map((p) => p.$?.['android:name']) || []);
128
+ debugLog('➕ Adding Android permissions:', permissionsToAdd);
129
+ // Add each permission only if it doesn't exist
130
+ permissionsToAdd.forEach((permission) => {
131
+ config_plugins_1.AndroidConfig.Permissions.addPermission(config.modResults, permission);
132
+ });
133
+ // Get the main application node
134
+ const mainApplication = config.modResults.manifest.application?.[0];
135
+ if (mainApplication) {
136
+ debugLog('📱 Configuring Android application components...');
137
+ // Add RecordingActionReceiver
138
+ if (!mainApplication.receiver) {
139
+ mainApplication.receiver = [];
140
+ }
141
+ const receiverConfig = {
142
+ $: {
143
+ 'android:name': '.RecordingActionReceiver',
144
+ 'android:exported': 'false',
145
+ },
146
+ 'intent-filter': [
147
+ {
148
+ action: [
149
+ { $: { 'android:name': 'PAUSE_RECORDING' } },
150
+ { $: { 'android:name': 'RESUME_RECORDING' } },
151
+ { $: { 'android:name': 'STOP_RECORDING' } },
152
+ ],
153
+ },
154
+ ],
155
+ };
156
+ const receiverIndex = mainApplication.receiver.findIndex((receiver) => receiver.$?.['android:name'] === '.RecordingActionReceiver');
157
+ if (receiverIndex >= 0) {
158
+ mainApplication.receiver[receiverIndex] = receiverConfig;
159
+ }
160
+ else {
161
+ mainApplication.receiver.push(receiverConfig);
162
+ }
163
+ debugLog('✅ RecordingActionReceiver configured');
164
+ // Add AudioRecordingService
165
+ if (!mainApplication.service) {
166
+ mainApplication.service = [];
167
+ }
168
+ const serviceConfig = {
169
+ $: {
170
+ 'android:name': '.AudioRecordingService',
171
+ 'android:enabled': 'true',
172
+ 'android:exported': 'false',
173
+ 'android:foregroundServiceType': 'microphone',
174
+ },
175
+ };
176
+ const serviceIndex = mainApplication.service.findIndex((service) => service.$?.['android:name'] === '.AudioRecordingService');
177
+ if (serviceIndex >= 0) {
178
+ mainApplication.service[serviceIndex] = serviceConfig;
179
+ }
180
+ else {
181
+ mainApplication.service.push(serviceConfig);
182
+ }
183
+ debugLog('✅ AudioRecordingService configured');
184
+ }
185
+ else {
186
+ console.error(`${LOG_PREFIX} ❌ Main application node not found in Android Manifest`);
187
+ }
188
+ return config;
189
+ });
190
+ debugLog('✨ Recording Permissions Plugin configuration completed');
191
+ return config;
192
+ };
193
+ // Export as default
194
+ exports.default = withRecordingPermission;
@@ -0,0 +1,22 @@
1
+ import { ConfigPlugin } from '@expo/config-plugins';
2
+ interface AudioStreamPluginOptions {
3
+ enablePhoneStateHandling?: boolean;
4
+ enableNotifications?: boolean;
5
+ enableBackgroundAudio?: boolean;
6
+ enableDeviceDetection?: boolean;
7
+ iosBackgroundModes?: {
8
+ useVoIP?: boolean;
9
+ useAudio?: boolean;
10
+ useProcessing?: boolean;
11
+ useLocation?: boolean;
12
+ useExternalAccessory?: boolean;
13
+ };
14
+ iosConfig?: {
15
+ allowBackgroundAudioControls?: boolean;
16
+ backgroundProcessingTitle?: string;
17
+ microphoneUsageDescription?: string;
18
+ notificationUsageDescription?: string;
19
+ };
20
+ }
21
+ declare const withRecordingPermission: ConfigPlugin<AudioStreamPluginOptions>;
22
+ export default withRecordingPermission;
@@ -0,0 +1,194 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const config_plugins_1 = require("@expo/config-plugins");
4
+ const MICROPHONE_USAGE = 'Allow $(PRODUCT_NAME) to access your microphone';
5
+ const NOTIFICATION_USAGE = 'Show recording notifications and controls';
6
+ const LOG_PREFIX = '[@siteed/expo-audio-studio]';
7
+ function debugLog(message, ...args) {
8
+ if (process.env.EXPO_DEBUG) {
9
+ console.log(`${LOG_PREFIX} ${message}`, ...args);
10
+ }
11
+ }
12
+ const withRecordingPermission = (config, props) => {
13
+ const options = {
14
+ enablePhoneStateHandling: true, // Default to true for backward compatibility
15
+ enableNotifications: true,
16
+ enableBackgroundAudio: true,
17
+ enableDeviceDetection: true, // Default to true for backward compatibility
18
+ iosBackgroundModes: {
19
+ useVoIP: false,
20
+ useAudio: false,
21
+ useProcessing: false,
22
+ useLocation: false,
23
+ useExternalAccessory: false,
24
+ },
25
+ iosConfig: {
26
+ microphoneUsageDescription: MICROPHONE_USAGE,
27
+ notificationUsageDescription: NOTIFICATION_USAGE,
28
+ },
29
+ ...(props || {}),
30
+ };
31
+ const { enablePhoneStateHandling, enableNotifications, enableBackgroundAudio, enableDeviceDetection, } = options;
32
+ debugLog('📱 Configuring Recording Permissions Plugin...', options);
33
+ // iOS Configuration
34
+ config = (0, config_plugins_1.withInfoPlist)(config, (config) => {
35
+ // Always set the microphone usage description from options first
36
+ config.modResults['NSMicrophoneUsageDescription'] =
37
+ options.iosConfig?.microphoneUsageDescription ||
38
+ config.modResults['NSMicrophoneUsageDescription'] ||
39
+ MICROPHONE_USAGE;
40
+ if (enableNotifications) {
41
+ config.modResults['NSUserNotificationsUsageDescription'] =
42
+ options.iosConfig?.notificationUsageDescription ||
43
+ config.modResults['NSUserNotificationsUsageDescription'] ||
44
+ NOTIFICATION_USAGE;
45
+ config.modResults['NSUserNotificationAlertStyle'] = 'alert';
46
+ }
47
+ const existingBackgroundModes = config.modResults.UIBackgroundModes || [];
48
+ // If background audio is enabled with useAudio, add the audio background mode
49
+ if (options.iosBackgroundModes?.useAudio === true &&
50
+ enableBackgroundAudio === true &&
51
+ !existingBackgroundModes.includes('audio')) {
52
+ // Add 'audio' background mode - REQUIRED for background recording
53
+ existingBackgroundModes.push('audio');
54
+ debugLog('✅ Added audio background mode for iOS background recording');
55
+ // Also ensure processing mode is recommended
56
+ if (options.iosBackgroundModes?.useProcessing !== true) {
57
+ console.warn(`${LOG_PREFIX} Warning: Background audio recording works best with both 'audio' and 'processing' background modes. Consider enabling 'useProcessing' in iosBackgroundModes.`);
58
+ }
59
+ }
60
+ if (options.iosBackgroundModes?.useVoIP === true &&
61
+ enablePhoneStateHandling === true) {
62
+ if (!existingBackgroundModes.includes('voip')) {
63
+ existingBackgroundModes.push('voip');
64
+ }
65
+ const existingCapabilities = (config.modResults
66
+ .UIRequiredDeviceCapabilities || []);
67
+ if (!existingCapabilities.includes('telephony')) {
68
+ existingCapabilities.push('telephony');
69
+ }
70
+ config.modResults.UIRequiredDeviceCapabilities =
71
+ existingCapabilities;
72
+ }
73
+ // Add additional background modes only if explicitly set to true
74
+ if (options.iosBackgroundModes?.useProcessing === true) {
75
+ if (!existingBackgroundModes.includes('processing')) {
76
+ existingBackgroundModes.push('processing');
77
+ }
78
+ // Add processing info if enabled
79
+ // Note: We keep the 'audiostream' namespace for native modules to maintain compatibility
80
+ config.modResults.BGTaskSchedulerPermittedIdentifiers = [
81
+ 'com.siteed.audiostream.processing',
82
+ ];
83
+ }
84
+ if (options.iosBackgroundModes?.useLocation === true) {
85
+ if (!existingBackgroundModes.includes('location')) {
86
+ existingBackgroundModes.push('location');
87
+ }
88
+ }
89
+ if (options.iosBackgroundModes?.useExternalAccessory === true) {
90
+ if (!existingBackgroundModes.includes('external-accessory')) {
91
+ existingBackgroundModes.push('external-accessory');
92
+ }
93
+ }
94
+ // Configure background processing info if enabled
95
+ if (options.iosConfig?.backgroundProcessingTitle) {
96
+ config.modResults.BGProcessingTaskTitle =
97
+ options.iosConfig.backgroundProcessingTitle;
98
+ }
99
+ // Configure audio session behavior
100
+ if (options.iosConfig?.allowBackgroundAudioControls) {
101
+ config.modResults.UIBackgroundModes = [
102
+ ...existingBackgroundModes,
103
+ 'remote-notification',
104
+ ];
105
+ config.modResults.MPNowPlayingInfoPropertyPlaybackRate = true;
106
+ }
107
+ config.modResults.UIBackgroundModes = existingBackgroundModes;
108
+ return config;
109
+ });
110
+ // Android Configuration
111
+ config = (0, config_plugins_1.withAndroidManifest)(config, (config) => {
112
+ const basePermissions = ['android.permission.RECORD_AUDIO'];
113
+ const optionalPermissions = [
114
+ enableNotifications && 'android.permission.POST_NOTIFICATIONS',
115
+ enablePhoneStateHandling && 'android.permission.READ_PHONE_STATE', // Only add if enabled
116
+ enableBackgroundAudio && 'android.permission.FOREGROUND_SERVICE',
117
+ enableBackgroundAudio &&
118
+ 'android.permission.FOREGROUND_SERVICE_MICROPHONE',
119
+ enableBackgroundAudio && 'android.permission.WAKE_LOCK', // Keep device awake during background recording
120
+ // Device detection permissions (only if enabled)
121
+ enableDeviceDetection && 'android.permission.BLUETOOTH',
122
+ enableDeviceDetection && 'android.permission.BLUETOOTH_ADMIN',
123
+ enableDeviceDetection && 'android.permission.BLUETOOTH_CONNECT',
124
+ enableDeviceDetection && 'android.permission.USB_PERMISSION',
125
+ ].filter(Boolean);
126
+ const permissionsToAdd = [...basePermissions, ...optionalPermissions];
127
+ debugLog('📋 Existing Android permissions:', config.modResults.manifest['uses-permission']?.map((p) => p.$?.['android:name']) || []);
128
+ debugLog('➕ Adding Android permissions:', permissionsToAdd);
129
+ // Add each permission only if it doesn't exist
130
+ permissionsToAdd.forEach((permission) => {
131
+ config_plugins_1.AndroidConfig.Permissions.addPermission(config.modResults, permission);
132
+ });
133
+ // Get the main application node
134
+ const mainApplication = config.modResults.manifest.application?.[0];
135
+ if (mainApplication) {
136
+ debugLog('📱 Configuring Android application components...');
137
+ // Add RecordingActionReceiver
138
+ if (!mainApplication.receiver) {
139
+ mainApplication.receiver = [];
140
+ }
141
+ const receiverConfig = {
142
+ $: {
143
+ 'android:name': '.RecordingActionReceiver',
144
+ 'android:exported': 'false',
145
+ },
146
+ 'intent-filter': [
147
+ {
148
+ action: [
149
+ { $: { 'android:name': 'PAUSE_RECORDING' } },
150
+ { $: { 'android:name': 'RESUME_RECORDING' } },
151
+ { $: { 'android:name': 'STOP_RECORDING' } },
152
+ ],
153
+ },
154
+ ],
155
+ };
156
+ const receiverIndex = mainApplication.receiver.findIndex((receiver) => receiver.$?.['android:name'] === '.RecordingActionReceiver');
157
+ if (receiverIndex >= 0) {
158
+ mainApplication.receiver[receiverIndex] = receiverConfig;
159
+ }
160
+ else {
161
+ mainApplication.receiver.push(receiverConfig);
162
+ }
163
+ debugLog('✅ RecordingActionReceiver configured');
164
+ // Add AudioRecordingService
165
+ if (!mainApplication.service) {
166
+ mainApplication.service = [];
167
+ }
168
+ const serviceConfig = {
169
+ $: {
170
+ 'android:name': '.AudioRecordingService',
171
+ 'android:enabled': 'true',
172
+ 'android:exported': 'false',
173
+ 'android:foregroundServiceType': 'microphone',
174
+ },
175
+ };
176
+ const serviceIndex = mainApplication.service.findIndex((service) => service.$?.['android:name'] === '.AudioRecordingService');
177
+ if (serviceIndex >= 0) {
178
+ mainApplication.service[serviceIndex] = serviceConfig;
179
+ }
180
+ else {
181
+ mainApplication.service.push(serviceConfig);
182
+ }
183
+ debugLog('✅ AudioRecordingService configured');
184
+ }
185
+ else {
186
+ console.error(`${LOG_PREFIX} ❌ Main application node not found in Android Manifest`);
187
+ }
188
+ return config;
189
+ });
190
+ debugLog('✨ Recording Permissions Plugin configuration completed');
191
+ return config;
192
+ };
193
+ // Export as default
194
+ exports.default = withRecordingPermission;