react-native-audio-api 0.11.0-alpha.0 → 0.11.0-alpha.2

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 (522) hide show
  1. package/README.md +13 -11
  2. package/RNAudioAPI.podspec +25 -18
  3. package/android/build.gradle +41 -5
  4. package/android/src/main/cpp/audioapi/CMakeLists.txt +6 -3
  5. package/android/src/main/cpp/audioapi/android/AudioAPIModule.cpp +10 -16
  6. package/android/src/main/cpp/audioapi/android/OnLoad.cpp +1 -2
  7. package/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.cpp +257 -74
  8. package/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.h +33 -19
  9. package/android/src/main/cpp/audioapi/android/core/AudioPlayer.cpp +13 -20
  10. package/android/src/main/cpp/audioapi/android/core/utils/AndroidFileWriterBackend.h +15 -15
  11. package/android/src/main/cpp/audioapi/android/core/utils/AndroidRecorderCallback.cpp +170 -0
  12. package/android/src/main/cpp/audioapi/android/core/utils/AndroidRecorderCallback.h +46 -0
  13. package/android/src/main/cpp/audioapi/android/core/utils/AudioDecoder.cpp +47 -47
  14. package/android/src/main/cpp/audioapi/android/core/utils/FileOptions.cpp +83 -0
  15. package/android/src/main/cpp/audioapi/android/core/utils/FileOptions.h +22 -0
  16. package/android/src/main/cpp/audioapi/android/core/utils/MiniaudioImplementation.cpp +5 -0
  17. package/android/src/main/cpp/audioapi/android/core/utils/ffmpegBackend/FFmpegFileWriter.cpp +381 -302
  18. package/android/src/main/cpp/audioapi/android/core/utils/ffmpegBackend/FFmpegFileWriter.h +49 -91
  19. package/android/src/main/cpp/audioapi/android/core/utils/ffmpegBackend/ptrs.hpp +48 -0
  20. package/android/src/main/cpp/audioapi/android/core/utils/ffmpegBackend/utils.cpp +110 -0
  21. package/android/src/main/cpp/audioapi/android/core/utils/ffmpegBackend/utils.h +34 -0
  22. package/android/src/main/cpp/audioapi/android/core/utils/miniaudioBackend/MiniAudioFileWriter.cpp +155 -95
  23. package/android/src/main/cpp/audioapi/android/core/utils/miniaudioBackend/MiniAudioFileWriter.h +9 -16
  24. package/android/src/main/java/com/swmansion/audioapi/AudioAPIModule.kt +28 -1
  25. package/android/src/main/java/com/swmansion/audioapi/system/LockScreenManager.kt +28 -6
  26. package/android/src/main/java/com/swmansion/audioapi/system/MediaNotificationManager.kt +11 -0
  27. package/android/src/main/jniLibs/arm64-v8a/libavcodec.so +0 -0
  28. package/android/src/main/jniLibs/arm64-v8a/libavformat.so +0 -0
  29. package/android/src/main/jniLibs/arm64-v8a/libavutil.so +0 -0
  30. package/android/src/main/jniLibs/arm64-v8a/libswresample.so +0 -0
  31. package/android/src/main/jniLibs/armeabi-v7a/libavcodec.so +0 -0
  32. package/android/src/main/jniLibs/armeabi-v7a/libavformat.so +0 -0
  33. package/android/src/main/jniLibs/armeabi-v7a/libavutil.so +0 -0
  34. package/android/src/main/jniLibs/armeabi-v7a/libswresample.so +0 -0
  35. package/android/src/main/jniLibs/x86/libavcodec.so +0 -0
  36. package/android/src/main/jniLibs/x86/libavformat.so +0 -0
  37. package/android/src/main/jniLibs/x86/libavutil.so +0 -0
  38. package/android/src/main/jniLibs/x86/libswresample.so +0 -0
  39. package/android/src/main/jniLibs/x86_64/libavcodec.so +0 -0
  40. package/android/src/main/jniLibs/x86_64/libavformat.so +0 -0
  41. package/android/src/main/jniLibs/x86_64/libavutil.so +0 -0
  42. package/android/src/main/jniLibs/x86_64/libswresample.so +0 -0
  43. package/android/src/oldarch/NativeAudioAPIModuleSpec.java +4 -0
  44. package/common/cpp/audioapi/AudioAPIModuleInstaller.h +45 -70
  45. package/common/cpp/audioapi/HostObjects/AudioContextHostObject.cpp +20 -22
  46. package/common/cpp/audioapi/HostObjects/AudioNodeHostObject.cpp +3 -4
  47. package/common/cpp/audioapi/HostObjects/AudioParamHostObject.cpp +6 -8
  48. package/common/cpp/audioapi/HostObjects/AudioParamHostObject.h +2 -2
  49. package/common/cpp/audioapi/HostObjects/BaseAudioContextHostObject.cpp +102 -63
  50. package/common/cpp/audioapi/HostObjects/BaseAudioContextHostObject.h +4 -1
  51. package/common/cpp/audioapi/HostObjects/OfflineAudioContextHostObject.cpp +25 -31
  52. package/common/cpp/audioapi/HostObjects/OfflineAudioContextHostObject.h +3 -3
  53. package/common/cpp/audioapi/HostObjects/WorkletNodeHostObject.h +1 -2
  54. package/common/cpp/audioapi/HostObjects/WorkletProcessingNodeHostObject.h +1 -2
  55. package/common/cpp/audioapi/HostObjects/analysis/AnalyserNodeHostObject.cpp +10 -18
  56. package/common/cpp/audioapi/HostObjects/destinations/AudioDestinationNodeHostObject.h +2 -3
  57. package/common/cpp/audioapi/HostObjects/effects/BiquadFilterNodeHostObject.cpp +18 -30
  58. package/common/cpp/audioapi/HostObjects/effects/BiquadFilterNodeHostObject.h +1 -2
  59. package/common/cpp/audioapi/HostObjects/effects/ConvolverNodeHostObject.cpp +50 -0
  60. package/common/cpp/audioapi/HostObjects/effects/ConvolverNodeHostObject.h +20 -0
  61. package/common/cpp/audioapi/HostObjects/effects/DelayNodeHostObject.cpp +27 -0
  62. package/common/cpp/audioapi/HostObjects/effects/DelayNodeHostObject.h +21 -0
  63. package/common/cpp/audioapi/HostObjects/effects/GainNodeHostObject.cpp +2 -2
  64. package/common/cpp/audioapi/HostObjects/effects/IIRFilterNodeHostObject.cpp +33 -0
  65. package/common/cpp/audioapi/HostObjects/effects/IIRFilterNodeHostObject.h +20 -0
  66. package/common/cpp/audioapi/HostObjects/effects/PeriodicWaveHostObject.h +1 -2
  67. package/common/cpp/audioapi/HostObjects/effects/StereoPannerNodeHostObject.cpp +2 -2
  68. package/common/cpp/audioapi/HostObjects/effects/StereoPannerNodeHostObject.h +1 -2
  69. package/common/cpp/audioapi/HostObjects/events/AudioEventHandlerRegistryHostObject.cpp +6 -12
  70. package/common/cpp/audioapi/HostObjects/events/AudioEventHandlerRegistryHostObject.h +7 -7
  71. package/common/cpp/audioapi/HostObjects/inputs/AudioRecorderHostObject.cpp +109 -44
  72. package/common/cpp/audioapi/HostObjects/inputs/AudioRecorderHostObject.h +8 -2
  73. package/common/cpp/audioapi/HostObjects/sources/AudioBufferBaseSourceNodeHostObject.cpp +27 -22
  74. package/common/cpp/audioapi/HostObjects/sources/AudioBufferBaseSourceNodeHostObject.h +12 -10
  75. package/common/cpp/audioapi/HostObjects/sources/AudioBufferHostObject.cpp +17 -22
  76. package/common/cpp/audioapi/HostObjects/sources/AudioBufferHostObject.h +5 -7
  77. package/common/cpp/audioapi/HostObjects/sources/AudioBufferQueueSourceNodeHostObject.cpp +25 -11
  78. package/common/cpp/audioapi/HostObjects/sources/AudioBufferQueueSourceNodeHostObject.h +8 -8
  79. package/common/cpp/audioapi/HostObjects/sources/AudioBufferSourceNodeHostObject.cpp +19 -30
  80. package/common/cpp/audioapi/HostObjects/sources/AudioBufferSourceNodeHostObject.h +2 -4
  81. package/common/cpp/audioapi/HostObjects/sources/AudioScheduledSourceNodeHostObject.cpp +7 -11
  82. package/common/cpp/audioapi/HostObjects/sources/ConstantSourceNodeHostObject.cpp +2 -2
  83. package/common/cpp/audioapi/HostObjects/sources/ConstantSourceNodeHostObject.h +1 -2
  84. package/common/cpp/audioapi/HostObjects/sources/OscillatorNodeHostObject.cpp +6 -8
  85. package/common/cpp/audioapi/HostObjects/sources/OscillatorNodeHostObject.h +1 -2
  86. package/common/cpp/audioapi/HostObjects/sources/RecorderAdapterNodeHostObject.h +4 -5
  87. package/common/cpp/audioapi/HostObjects/sources/StreamerNodeHostObject.cpp +6 -2
  88. package/common/cpp/audioapi/HostObjects/sources/StreamerNodeHostObject.h +5 -6
  89. package/common/cpp/audioapi/HostObjects/sources/WorkletSourceNodeHostObject.h +1 -2
  90. package/common/cpp/audioapi/HostObjects/utils/AudioDecoderHostObject.cpp +39 -60
  91. package/common/cpp/audioapi/HostObjects/utils/AudioStretcherHostObject.cpp +15 -30
  92. package/common/cpp/audioapi/core/AudioContext.cpp +23 -28
  93. package/common/cpp/audioapi/core/AudioContext.h +6 -3
  94. package/common/cpp/audioapi/core/AudioNode.cpp +17 -19
  95. package/common/cpp/audioapi/core/AudioNode.h +19 -8
  96. package/common/cpp/audioapi/core/AudioParam.cpp +68 -100
  97. package/common/cpp/audioapi/core/AudioParam.h +20 -12
  98. package/common/cpp/audioapi/core/BaseAudioContext.cpp +52 -34
  99. package/common/cpp/audioapi/core/BaseAudioContext.h +26 -14
  100. package/common/cpp/audioapi/core/OfflineAudioContext.cpp +12 -17
  101. package/common/cpp/audioapi/core/OfflineAudioContext.h +10 -5
  102. package/common/cpp/audioapi/core/analysis/AnalyserNode.cpp +13 -21
  103. package/common/cpp/audioapi/core/analysis/AnalyserNode.h +8 -6
  104. package/common/cpp/audioapi/core/destinations/AudioDestinationNode.cpp +1 -0
  105. package/common/cpp/audioapi/core/destinations/AudioDestinationNode.h +5 -3
  106. package/common/cpp/audioapi/core/effects/BiquadFilterNode.cpp +84 -66
  107. package/common/cpp/audioapi/core/effects/BiquadFilterNode.h +39 -10
  108. package/common/cpp/audioapi/core/effects/ConvolverNode.cpp +201 -0
  109. package/common/cpp/audioapi/core/effects/ConvolverNode.h +64 -0
  110. package/common/cpp/audioapi/core/effects/DelayNode.cpp +101 -0
  111. package/common/cpp/audioapi/core/effects/DelayNode.h +39 -0
  112. package/common/cpp/audioapi/core/effects/GainNode.cpp +1 -0
  113. package/common/cpp/audioapi/core/effects/GainNode.h +3 -1
  114. package/common/cpp/audioapi/core/effects/IIRFilterNode.cpp +166 -0
  115. package/common/cpp/audioapi/core/effects/IIRFilterNode.h +74 -0
  116. package/common/cpp/audioapi/core/effects/PeriodicWave.cpp +22 -35
  117. package/common/cpp/audioapi/core/effects/PeriodicWave.h +4 -9
  118. package/common/cpp/audioapi/core/effects/StereoPannerNode.cpp +4 -5
  119. package/common/cpp/audioapi/core/effects/StereoPannerNode.h +4 -2
  120. package/common/cpp/audioapi/core/effects/WorkletNode.cpp +11 -13
  121. package/common/cpp/audioapi/core/effects/WorkletNode.h +15 -12
  122. package/common/cpp/audioapi/core/effects/WorkletProcessingNode.cpp +4 -4
  123. package/common/cpp/audioapi/core/effects/WorkletProcessingNode.h +15 -14
  124. package/common/cpp/audioapi/core/inputs/AudioRecorder.cpp +31 -108
  125. package/common/cpp/audioapi/core/inputs/AudioRecorder.h +46 -46
  126. package/common/cpp/audioapi/core/sources/AudioBuffer.cpp +4 -6
  127. package/common/cpp/audioapi/core/sources/AudioBuffer.h +4 -7
  128. package/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.cpp +48 -57
  129. package/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.h +37 -34
  130. package/common/cpp/audioapi/core/sources/AudioBufferQueueSourceNode.cpp +55 -17
  131. package/common/cpp/audioapi/core/sources/AudioBufferQueueSourceNode.h +35 -28
  132. package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp +41 -49
  133. package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.h +8 -6
  134. package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.cpp +29 -24
  135. package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.h +6 -6
  136. package/common/cpp/audioapi/core/sources/ConstantSourceNode.cpp +3 -4
  137. package/common/cpp/audioapi/core/sources/ConstantSourceNode.h +3 -1
  138. package/common/cpp/audioapi/core/sources/OscillatorNode.cpp +12 -23
  139. package/common/cpp/audioapi/core/sources/OscillatorNode.h +6 -4
  140. package/common/cpp/audioapi/core/sources/RecorderAdapterNode.cpp +43 -16
  141. package/common/cpp/audioapi/core/sources/RecorderAdapterNode.h +22 -17
  142. package/common/cpp/audioapi/core/sources/StreamerNode.cpp +104 -87
  143. package/common/cpp/audioapi/core/sources/StreamerNode.h +69 -33
  144. package/common/cpp/audioapi/core/sources/WorkletSourceNode.cpp +5 -7
  145. package/common/cpp/audioapi/core/sources/WorkletSourceNode.h +15 -13
  146. package/common/cpp/audioapi/core/types/AudioFormat.h +1 -11
  147. package/common/cpp/audioapi/core/utils/AudioDecoder.h +15 -6
  148. package/common/cpp/audioapi/core/utils/AudioFileWriter.cpp +41 -0
  149. package/common/cpp/audioapi/core/utils/AudioFileWriter.h +43 -0
  150. package/common/cpp/audioapi/core/utils/AudioNodeDestructor.cpp +5 -6
  151. package/common/cpp/audioapi/core/utils/AudioNodeDestructor.h +7 -10
  152. package/common/cpp/audioapi/core/utils/AudioNodeManager.cpp +17 -19
  153. package/common/cpp/audioapi/core/utils/AudioNodeManager.h +8 -11
  154. package/common/cpp/audioapi/core/utils/AudioParamEventQueue.cpp +3 -3
  155. package/common/cpp/audioapi/core/utils/AudioParamEventQueue.h +5 -5
  156. package/common/cpp/audioapi/core/utils/AudioRecorderCallback.cpp +101 -0
  157. package/common/cpp/audioapi/core/utils/AudioRecorderCallback.h +51 -0
  158. package/common/cpp/audioapi/core/utils/AudioStretcher.cpp +6 -6
  159. package/common/cpp/audioapi/core/utils/Constants.h +7 -3
  160. package/common/cpp/audioapi/core/utils/ParamChangeEvent.cpp +1 -0
  161. package/common/cpp/audioapi/core/utils/ParamChangeEvent.h +9 -9
  162. package/common/cpp/audioapi/core/utils/worklets/SafeIncludes.h +33 -34
  163. package/common/cpp/audioapi/core/utils/worklets/WorkletsRunner.cpp +17 -19
  164. package/common/cpp/audioapi/core/utils/worklets/WorkletsRunner.h +23 -19
  165. package/common/cpp/audioapi/dsp/AudioUtils.cpp +4 -10
  166. package/common/cpp/audioapi/dsp/AudioUtils.h +1 -1
  167. package/common/cpp/audioapi/dsp/Convolver.cpp +201 -0
  168. package/common/cpp/audioapi/dsp/Convolver.h +47 -0
  169. package/common/cpp/audioapi/dsp/FFT.cpp +1 -27
  170. package/common/cpp/audioapi/dsp/FFT.h +19 -3
  171. package/common/cpp/audioapi/dsp/VectorMath.cpp +24 -58
  172. package/common/cpp/audioapi/dsp/VectorMath.h +35 -8
  173. package/common/cpp/audioapi/dsp/Windows.cpp +4 -9
  174. package/common/cpp/audioapi/dsp/Windows.h +24 -23
  175. package/common/cpp/audioapi/events/AudioEventHandlerRegistry.cpp +12 -17
  176. package/common/cpp/audioapi/events/AudioEventHandlerRegistry.h +45 -40
  177. package/common/cpp/audioapi/events/IAudioEventHandlerRegistry.h +15 -7
  178. package/common/cpp/audioapi/external/ffmpeg_include/libavcodec/avcodec.h +4 -4
  179. package/common/cpp/audioapi/external/ffmpeg_include/libavcodec/codec.h +1 -1
  180. package/common/cpp/audioapi/external/ffmpeg_include/libavcodec/codec_desc.h +1 -1
  181. package/common/cpp/audioapi/external/ffmpeg_include/libavcodec/codec_id.h +3 -1
  182. package/common/cpp/audioapi/external/ffmpeg_include/libavcodec/codec_par.h +2 -2
  183. package/common/cpp/audioapi/external/ffmpeg_include/libavcodec/defs.h +3 -0
  184. package/common/cpp/audioapi/external/ffmpeg_include/libavcodec/packet.h +1 -1
  185. package/common/cpp/audioapi/external/ffmpeg_include/libavcodec/smpte_436m.h +254 -0
  186. package/common/cpp/audioapi/external/ffmpeg_include/libavcodec/version.h +1 -1
  187. package/common/cpp/audioapi/external/ffmpeg_include/libavformat/avformat.h +6 -6
  188. package/common/cpp/audioapi/external/ffmpeg_include/libavformat/version.h +2 -2
  189. package/common/cpp/audioapi/external/ffmpeg_include/libavformat/version_major.h +2 -0
  190. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/avassert.h +5 -2
  191. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/avutil.h +2 -2
  192. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/channel_layout.h +2 -2
  193. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/csp.h +1 -1
  194. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/dict.h +1 -1
  195. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/ffversion.h +1 -1
  196. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/film_grain_params.h +1 -1
  197. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/frame.h +1 -1
  198. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/hdr_dynamic_vivid_metadata.h +3 -3
  199. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/hwcontext.h +1 -1
  200. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/hwcontext_opencl.h +1 -1
  201. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/hwcontext_qsv.h +0 -1
  202. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/hwcontext_vulkan.h +1 -1
  203. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/iamf.h +2 -2
  204. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/lfg.h +2 -2
  205. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/log.h +2 -2
  206. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/mathematics.h +1 -1
  207. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/opt.h +4 -4
  208. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/rational.h +1 -1
  209. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/rc4.h +1 -1
  210. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/refstruct.h +1 -1
  211. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/spherical.h +6 -0
  212. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/tdrdi.h +1 -1
  213. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/tx.h +1 -1
  214. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/version.h +3 -3
  215. package/common/cpp/audioapi/external/ffmpeg_include/libavutil/video_hint.h +1 -1
  216. package/common/cpp/audioapi/external/ffmpeg_include/libswresample/swresample.h +1 -1
  217. package/common/cpp/audioapi/external/ffmpeg_include/libswresample/version.h +1 -1
  218. package/common/cpp/audioapi/external/{libavcodec.xcframework → ffmpeg_ios/libavcodec.xcframework}/ios-arm64/libavcodec.framework/libavcodec +0 -0
  219. package/common/cpp/audioapi/external/{libavcodec.xcframework → ffmpeg_ios/libavcodec.xcframework}/ios-arm64_x86_64-simulator/libavcodec.framework/libavcodec +0 -0
  220. package/common/cpp/audioapi/external/{libavformat.xcframework → ffmpeg_ios/libavformat.xcframework}/ios-arm64/libavformat.framework/libavformat +0 -0
  221. package/common/cpp/audioapi/external/{libavformat.xcframework → ffmpeg_ios/libavformat.xcframework}/ios-arm64_x86_64-simulator/libavformat.framework/libavformat +0 -0
  222. package/common/cpp/audioapi/external/{libavutil.xcframework → ffmpeg_ios/libavutil.xcframework}/ios-arm64/libavutil.framework/libavutil +0 -0
  223. package/common/cpp/audioapi/external/{libavutil.xcframework → ffmpeg_ios/libavutil.xcframework}/ios-arm64_x86_64-simulator/libavutil.framework/libavutil +0 -0
  224. package/common/cpp/audioapi/external/{libswresample.xcframework → ffmpeg_ios/libswresample.xcframework}/ios-arm64/libswresample.framework/libswresample +0 -0
  225. package/common/cpp/audioapi/external/{libswresample.xcframework → ffmpeg_ios/libswresample.xcframework}/ios-arm64_x86_64-simulator/libswresample.framework/libswresample +0 -0
  226. package/common/cpp/audioapi/jsi/AudioArrayBuffer.h +4 -5
  227. package/common/cpp/audioapi/jsi/JsiHostObject.cpp +11 -13
  228. package/common/cpp/audioapi/jsi/JsiHostObject.h +26 -33
  229. package/common/cpp/audioapi/jsi/JsiPromise.cpp +34 -67
  230. package/common/cpp/audioapi/jsi/JsiPromise.h +65 -26
  231. package/common/cpp/audioapi/jsi/RuntimeLifecycleMonitor.cpp +7 -10
  232. package/common/cpp/audioapi/jsi/RuntimeLifecycleMonitor.h +1 -3
  233. package/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.cpp +4 -3
  234. package/common/cpp/audioapi/libs/ffmpeg/relinking.md +24 -0
  235. package/common/cpp/audioapi/utils/AlignedAllocator.hpp +50 -0
  236. package/common/cpp/audioapi/utils/AudioArray.cpp +3 -8
  237. package/common/cpp/audioapi/utils/AudioArray.h +3 -11
  238. package/common/cpp/audioapi/utils/AudioBus.cpp +79 -149
  239. package/common/cpp/audioapi/utils/AudioBus.h +17 -14
  240. package/common/cpp/audioapi/utils/AudioFileProperties.cpp +92 -0
  241. package/common/cpp/audioapi/utils/AudioFileProperties.h +76 -0
  242. package/common/cpp/audioapi/utils/CircularAudioArray.cpp +6 -18
  243. package/common/cpp/audioapi/utils/CircularOverflowableAudioArray.cpp +6 -10
  244. package/common/cpp/audioapi/utils/CircularOverflowableAudioArray.h +2 -2
  245. package/common/cpp/audioapi/utils/Result.hpp +286 -0
  246. package/common/cpp/audioapi/utils/ThreadPool.hpp +59 -1
  247. package/common/cpp/audioapi/utils/UnitConversion.h +9 -0
  248. package/common/cpp/test/CMakeLists.txt +20 -14
  249. package/common/cpp/test/src/AudioParamTest.cpp +4 -3
  250. package/common/cpp/test/src/AudioScheduledSourceTest.cpp +113 -0
  251. package/common/cpp/test/src/ConstantSourceTest.cpp +5 -7
  252. package/common/cpp/test/src/DelayTest.cpp +108 -0
  253. package/common/cpp/test/src/GainTest.cpp +4 -5
  254. package/common/cpp/test/src/IIRFilterTest.cpp +153 -0
  255. package/common/cpp/test/src/MockAudioEventHandlerRegistry.h +19 -11
  256. package/common/cpp/test/src/OscillatorTest.cpp +2 -1
  257. package/common/cpp/test/src/StereoPannerTest.cpp +6 -9
  258. package/common/cpp/test/src/biquad/BiquadFilterChromium.cpp +372 -0
  259. package/common/cpp/test/src/biquad/BiquadFilterChromium.h +65 -0
  260. package/common/cpp/test/src/biquad/BiquadFilterTest.cpp +272 -0
  261. package/common/cpp/test/src/biquad/BiquadFilterTest.h +47 -0
  262. package/ios/audioapi/ios/AudioAPIModule.h +2 -1
  263. package/ios/audioapi/ios/AudioAPIModule.mm +44 -20
  264. package/ios/audioapi/ios/core/IOSAudioPlayer.h +2 -2
  265. package/ios/audioapi/ios/core/IOSAudioPlayer.mm +7 -6
  266. package/ios/audioapi/ios/core/IOSAudioRecorder.h +28 -11
  267. package/ios/audioapi/ios/core/IOSAudioRecorder.mm +229 -44
  268. package/ios/audioapi/ios/core/NativeAudioPlayer.m +16 -13
  269. package/ios/audioapi/ios/core/NativeAudioRecorder.h +6 -3
  270. package/ios/audioapi/ios/core/NativeAudioRecorder.m +67 -6
  271. package/ios/audioapi/ios/core/utils/AudioDecoder.mm +22 -4
  272. package/ios/audioapi/ios/core/utils/FileOptions.h +31 -0
  273. package/ios/audioapi/ios/core/utils/FileOptions.mm +177 -0
  274. package/ios/audioapi/ios/core/utils/IOSFileWriter.h +53 -0
  275. package/ios/audioapi/ios/core/utils/IOSFileWriter.mm +224 -0
  276. package/ios/audioapi/ios/core/utils/IOSRecorderCallback.h +47 -0
  277. package/ios/audioapi/ios/core/utils/IOSRecorderCallback.mm +172 -0
  278. package/ios/audioapi/ios/system/AudioEngine.h +19 -16
  279. package/ios/audioapi/ios/system/AudioEngine.mm +101 -134
  280. package/ios/audioapi/ios/system/AudioSessionManager.h +25 -11
  281. package/ios/audioapi/ios/system/AudioSessionManager.mm +273 -202
  282. package/ios/audioapi/ios/system/LockScreenManager.mm +39 -23
  283. package/ios/audioapi/ios/system/NotificationManager.mm +37 -52
  284. package/lib/commonjs/AudioAPIModule/AudioAPIModule.js +90 -0
  285. package/lib/commonjs/AudioAPIModule/AudioAPIModule.js.map +1 -0
  286. package/lib/commonjs/AudioAPIModule/globals.d.js +6 -0
  287. package/lib/commonjs/AudioAPIModule/globals.d.js.map +1 -0
  288. package/lib/commonjs/AudioAPIModule/index.js +14 -0
  289. package/lib/commonjs/AudioAPIModule/index.js.map +1 -0
  290. package/lib/commonjs/api.js +18 -12
  291. package/lib/commonjs/api.js.map +1 -1
  292. package/lib/commonjs/api.web.js +8 -0
  293. package/lib/commonjs/api.web.js.map +1 -1
  294. package/lib/commonjs/core/AudioBufferBaseSourceNode.js +3 -0
  295. package/lib/commonjs/core/AudioBufferBaseSourceNode.js.map +1 -1
  296. package/lib/commonjs/core/AudioBufferQueueSourceNode.js +5 -2
  297. package/lib/commonjs/core/AudioBufferQueueSourceNode.js.map +1 -1
  298. package/lib/commonjs/core/AudioContext.js +5 -8
  299. package/lib/commonjs/core/AudioContext.js.map +1 -1
  300. package/lib/commonjs/core/AudioNode.js +1 -1
  301. package/lib/commonjs/core/AudioNode.js.map +1 -1
  302. package/lib/commonjs/core/AudioParam.js +18 -11
  303. package/lib/commonjs/core/AudioParam.js.map +1 -1
  304. package/lib/commonjs/core/AudioRecorder.js +56 -55
  305. package/lib/commonjs/core/AudioRecorder.js.map +1 -1
  306. package/lib/commonjs/core/BaseAudioContext.js +61 -30
  307. package/lib/commonjs/core/BaseAudioContext.js.map +1 -1
  308. package/lib/commonjs/core/ConvolverNode.js +37 -0
  309. package/lib/commonjs/core/ConvolverNode.js.map +1 -0
  310. package/lib/commonjs/core/DelayNode.js +17 -0
  311. package/lib/commonjs/core/DelayNode.js.map +1 -0
  312. package/lib/commonjs/core/IIRFilterNode.js +19 -0
  313. package/lib/commonjs/core/IIRFilterNode.js.map +1 -0
  314. package/lib/commonjs/core/OfflineAudioContext.js +3 -6
  315. package/lib/commonjs/core/OfflineAudioContext.js.map +1 -1
  316. package/lib/commonjs/plugin/withAudioAPI.js +46 -0
  317. package/lib/commonjs/plugin/withAudioAPI.js.map +1 -1
  318. package/lib/commonjs/specs/NativeAudioAPIModule.js.map +1 -1
  319. package/lib/commonjs/system/AudioManager.js +4 -7
  320. package/lib/commonjs/system/AudioManager.js.map +1 -1
  321. package/lib/commonjs/types.js +16 -23
  322. package/lib/commonjs/types.js.map +1 -1
  323. package/lib/commonjs/utils/filePresets.js +43 -0
  324. package/lib/commonjs/utils/filePresets.js.map +1 -0
  325. package/lib/commonjs/utils/index.js +12 -27
  326. package/lib/commonjs/utils/index.js.map +1 -1
  327. package/lib/commonjs/web-core/AudioContext.js +21 -1
  328. package/lib/commonjs/web-core/AudioContext.js.map +1 -1
  329. package/lib/commonjs/web-core/ConvolverNode.js +40 -0
  330. package/lib/commonjs/web-core/ConvolverNode.js.map +1 -0
  331. package/lib/commonjs/web-core/ConvolverNodeOptions.js +6 -0
  332. package/lib/commonjs/web-core/ConvolverNodeOptions.js.map +1 -0
  333. package/lib/commonjs/web-core/DelayNode.js +17 -0
  334. package/lib/commonjs/web-core/DelayNode.js.map +1 -0
  335. package/lib/commonjs/web-core/IIRFilterNode.js +19 -0
  336. package/lib/commonjs/web-core/IIRFilterNode.js.map +1 -0
  337. package/lib/commonjs/web-core/OfflineAudioContext.js +20 -0
  338. package/lib/commonjs/web-core/OfflineAudioContext.js.map +1 -1
  339. package/lib/module/AudioAPIModule/AudioAPIModule.js +87 -0
  340. package/lib/module/AudioAPIModule/AudioAPIModule.js.map +1 -0
  341. package/lib/module/AudioAPIModule/globals.d.js +4 -0
  342. package/lib/module/AudioAPIModule/globals.d.js.map +1 -0
  343. package/lib/module/AudioAPIModule/index.js +4 -0
  344. package/lib/module/AudioAPIModule/index.js.map +1 -0
  345. package/lib/module/api.js +3 -12
  346. package/lib/module/api.js.map +1 -1
  347. package/lib/module/api.web.js +1 -0
  348. package/lib/module/api.web.js.map +1 -1
  349. package/lib/module/core/AudioBufferBaseSourceNode.js +3 -0
  350. package/lib/module/core/AudioBufferBaseSourceNode.js.map +1 -1
  351. package/lib/module/core/AudioBufferQueueSourceNode.js +5 -2
  352. package/lib/module/core/AudioBufferQueueSourceNode.js.map +1 -1
  353. package/lib/module/core/AudioContext.js +5 -8
  354. package/lib/module/core/AudioContext.js.map +1 -1
  355. package/lib/module/core/AudioNode.js +1 -1
  356. package/lib/module/core/AudioNode.js.map +1 -1
  357. package/lib/module/core/AudioParam.js +18 -11
  358. package/lib/module/core/AudioParam.js.map +1 -1
  359. package/lib/module/core/AudioRecorder.js +57 -56
  360. package/lib/module/core/AudioRecorder.js.map +1 -1
  361. package/lib/module/core/BaseAudioContext.js +63 -32
  362. package/lib/module/core/BaseAudioContext.js.map +1 -1
  363. package/lib/module/core/ConvolverNode.js +31 -0
  364. package/lib/module/core/ConvolverNode.js.map +1 -0
  365. package/lib/module/core/DelayNode.js +11 -0
  366. package/lib/module/core/DelayNode.js.map +1 -0
  367. package/lib/module/core/IIRFilterNode.js +13 -0
  368. package/lib/module/core/IIRFilterNode.js.map +1 -0
  369. package/lib/module/core/OfflineAudioContext.js +3 -6
  370. package/lib/module/core/OfflineAudioContext.js.map +1 -1
  371. package/lib/module/plugin/withAudioAPI.js +47 -1
  372. package/lib/module/plugin/withAudioAPI.js.map +1 -1
  373. package/lib/module/specs/NativeAudioAPIModule.js.map +1 -1
  374. package/lib/module/system/AudioManager.js +4 -7
  375. package/lib/module/system/AudioManager.js.map +1 -1
  376. package/lib/module/types.js +15 -22
  377. package/lib/module/types.js.map +1 -1
  378. package/lib/module/utils/filePresets.js +39 -0
  379. package/lib/module/utils/filePresets.js.map +1 -0
  380. package/lib/module/utils/index.js +10 -10
  381. package/lib/module/utils/index.js.map +1 -1
  382. package/lib/module/web-core/AudioContext.js +21 -1
  383. package/lib/module/web-core/AudioContext.js.map +1 -1
  384. package/lib/module/web-core/ConvolverNode.js +34 -0
  385. package/lib/module/web-core/ConvolverNode.js.map +1 -0
  386. package/lib/module/web-core/ConvolverNodeOptions.js +4 -0
  387. package/lib/module/web-core/ConvolverNodeOptions.js.map +1 -0
  388. package/lib/module/web-core/DelayNode.js +11 -0
  389. package/lib/module/web-core/DelayNode.js.map +1 -0
  390. package/lib/module/web-core/IIRFilterNode.js +13 -0
  391. package/lib/module/web-core/IIRFilterNode.js.map +1 -0
  392. package/lib/module/web-core/OfflineAudioContext.js +20 -0
  393. package/lib/module/web-core/OfflineAudioContext.js.map +1 -1
  394. package/lib/typescript/AudioAPIModule/AudioAPIModule.d.ts +36 -0
  395. package/lib/typescript/AudioAPIModule/AudioAPIModule.d.ts.map +1 -0
  396. package/lib/typescript/AudioAPIModule/index.d.ts +2 -0
  397. package/lib/typescript/AudioAPIModule/index.d.ts.map +1 -0
  398. package/lib/typescript/api.d.ts +3 -9
  399. package/lib/typescript/api.d.ts.map +1 -1
  400. package/lib/typescript/api.web.d.ts +1 -0
  401. package/lib/typescript/api.web.d.ts.map +1 -1
  402. package/lib/typescript/core/AudioBufferBaseSourceNode.d.ts +1 -0
  403. package/lib/typescript/core/AudioBufferBaseSourceNode.d.ts.map +1 -1
  404. package/lib/typescript/core/AudioBufferQueueSourceNode.d.ts +1 -1
  405. package/lib/typescript/core/AudioBufferQueueSourceNode.d.ts.map +1 -1
  406. package/lib/typescript/core/AudioContext.d.ts +1 -1
  407. package/lib/typescript/core/AudioContext.d.ts.map +1 -1
  408. package/lib/typescript/core/AudioNode.d.ts +2 -1
  409. package/lib/typescript/core/AudioNode.d.ts.map +1 -1
  410. package/lib/typescript/core/AudioParam.d.ts.map +1 -1
  411. package/lib/typescript/core/AudioRecorder.d.ts +16 -6
  412. package/lib/typescript/core/AudioRecorder.d.ts.map +1 -1
  413. package/lib/typescript/core/BaseAudioContext.d.ts +9 -3
  414. package/lib/typescript/core/BaseAudioContext.d.ts.map +1 -1
  415. package/lib/typescript/core/ConvolverNode.d.ts +12 -0
  416. package/lib/typescript/core/ConvolverNode.d.ts.map +1 -0
  417. package/lib/typescript/core/DelayNode.d.ts +9 -0
  418. package/lib/typescript/core/DelayNode.d.ts.map +1 -0
  419. package/lib/typescript/core/IIRFilterNode.d.ts +5 -0
  420. package/lib/typescript/core/IIRFilterNode.d.ts.map +1 -0
  421. package/lib/typescript/core/OfflineAudioContext.d.ts +1 -1
  422. package/lib/typescript/core/OfflineAudioContext.d.ts.map +1 -1
  423. package/lib/typescript/events/types.d.ts +4 -0
  424. package/lib/typescript/events/types.d.ts.map +1 -1
  425. package/lib/typescript/interfaces.d.ts +36 -34
  426. package/lib/typescript/interfaces.d.ts.map +1 -1
  427. package/lib/typescript/plugin/withAudioAPI.d.ts +1 -0
  428. package/lib/typescript/plugin/withAudioAPI.d.ts.map +1 -1
  429. package/lib/typescript/specs/NativeAudioAPIModule.d.ts +2 -1
  430. package/lib/typescript/specs/NativeAudioAPIModule.d.ts.map +1 -1
  431. package/lib/typescript/system/AudioManager.d.ts +3 -2
  432. package/lib/typescript/system/AudioManager.d.ts.map +1 -1
  433. package/lib/typescript/types.d.ts +43 -30
  434. package/lib/typescript/types.d.ts.map +1 -1
  435. package/lib/typescript/utils/filePresets.d.ts +9 -0
  436. package/lib/typescript/utils/filePresets.d.ts.map +1 -0
  437. package/lib/typescript/utils/index.d.ts +1 -8
  438. package/lib/typescript/utils/index.d.ts.map +1 -1
  439. package/lib/typescript/web-core/AudioContext.d.ts +9 -2
  440. package/lib/typescript/web-core/AudioContext.d.ts.map +1 -1
  441. package/lib/typescript/web-core/BaseAudioContext.d.ts +7 -1
  442. package/lib/typescript/web-core/BaseAudioContext.d.ts.map +1 -1
  443. package/lib/typescript/web-core/ConvolverNode.d.ts +11 -0
  444. package/lib/typescript/web-core/ConvolverNode.d.ts.map +1 -0
  445. package/lib/typescript/web-core/ConvolverNodeOptions.d.ts +6 -0
  446. package/lib/typescript/web-core/ConvolverNodeOptions.d.ts.map +1 -0
  447. package/lib/typescript/web-core/DelayNode.d.ts +8 -0
  448. package/lib/typescript/web-core/DelayNode.d.ts.map +1 -0
  449. package/lib/typescript/web-core/IIRFilterNode.d.ts +5 -0
  450. package/lib/typescript/web-core/IIRFilterNode.d.ts.map +1 -0
  451. package/lib/typescript/web-core/OfflineAudioContext.d.ts +8 -1
  452. package/lib/typescript/web-core/OfflineAudioContext.d.ts.map +1 -1
  453. package/package.json +11 -4
  454. package/scripts/download-prebuilt-binaries.sh +61 -0
  455. package/scripts/rnaa_utils.rb +8 -0
  456. package/scripts/validate-worklets-version.js +27 -0
  457. package/src/AudioAPIModule/AudioAPIModule.ts +122 -0
  458. package/src/AudioAPIModule/globals.d.ts +33 -0
  459. package/src/AudioAPIModule/index.ts +1 -0
  460. package/src/api.ts +4 -52
  461. package/src/api.web.ts +1 -0
  462. package/src/core/AudioBufferBaseSourceNode.ts +8 -0
  463. package/src/core/AudioBufferQueueSourceNode.ts +8 -2
  464. package/src/core/AudioContext.ts +5 -8
  465. package/src/core/AudioNode.ts +4 -3
  466. package/src/core/AudioParam.ts +18 -11
  467. package/src/core/AudioRecorder.ts +86 -84
  468. package/src/core/BaseAudioContext.ts +120 -54
  469. package/src/core/ConvolverNode.ts +35 -0
  470. package/src/core/DelayNode.ts +13 -0
  471. package/src/core/IIRFilterNode.ts +25 -0
  472. package/src/core/OfflineAudioContext.ts +4 -7
  473. package/src/events/types.ts +5 -0
  474. package/src/interfaces.ts +55 -34
  475. package/src/plugin/withAudioAPI.ts +61 -0
  476. package/src/specs/NativeAudioAPIModule.ts +3 -2
  477. package/src/system/AudioManager.ts +13 -19
  478. package/src/types.ts +47 -32
  479. package/src/utils/filePresets.ts +47 -0
  480. package/src/utils/index.ts +13 -19
  481. package/src/web-core/AudioContext.tsx +40 -1
  482. package/src/web-core/BaseAudioContext.tsx +11 -1
  483. package/src/web-core/ConvolverNode.tsx +43 -0
  484. package/src/web-core/ConvolverNodeOptions.tsx +6 -0
  485. package/src/web-core/DelayNode.tsx +12 -0
  486. package/src/web-core/IIRFilterNode.tsx +25 -0
  487. package/src/web-core/OfflineAudioContext.tsx +39 -0
  488. package/android/src/main/cpp/audioapi/android/core/utils/FileUtils.h +0 -34
  489. package/android/src/main/cpp/audioapi/android/core/utils/FileUtilts.cpp +0 -133
  490. package/android/src/main/cpp/audioapi/android/core/utils/ffmpegBackend/FFmpegAudioFileOptions.cpp +0 -154
  491. package/android/src/main/cpp/audioapi/android/core/utils/ffmpegBackend/FFmpegAudioFileOptions.h +0 -41
  492. package/android/src/main/cpp/audioapi/android/core/utils/miniaudioBackend/MiniAudioFileOptions.cpp +0 -47
  493. package/android/src/main/cpp/audioapi/android/core/utils/miniaudioBackend/MiniAudioFileOptions.h +0 -28
  494. package/common/cpp/audioapi/libs/ffmpeg/INSTRUCTIONS.md +0 -32
  495. package/common/cpp/audioapi/libs/ffmpeg/create_xcframework.sh +0 -111
  496. package/common/cpp/audioapi/libs/ffmpeg/ffmpeg_setup.sh +0 -391
  497. package/ios/audioapi/ios/core/IOSAudioFileOptions.h +0 -35
  498. package/ios/audioapi/ios/core/IOSAudioFileOptions.mm +0 -135
  499. package/ios/audioapi/ios/core/IOSAudioFileWriter.h +0 -38
  500. package/ios/audioapi/ios/core/IOSAudioFileWriter.mm +0 -187
  501. package/lib/commonjs/utils/bitEnums.js +0 -33
  502. package/lib/commonjs/utils/bitEnums.js.map +0 -1
  503. package/lib/module/utils/bitEnums.js +0 -27
  504. package/lib/module/utils/bitEnums.js.map +0 -1
  505. package/lib/typescript/utils/bitEnums.d.ts +0 -4
  506. package/lib/typescript/utils/bitEnums.d.ts.map +0 -1
  507. package/metro-config/index.d.ts +0 -5
  508. package/metro-config/index.js +0 -41
  509. package/metro-config/tsconfig.json +0 -3
  510. package/src/utils/bitEnums.ts +0 -51
  511. package/common/cpp/audioapi/external/{libavcodec.xcframework → ffmpeg_ios/libavcodec.xcframework}/Info.plist +5 -5
  512. package/common/cpp/audioapi/external/{libavcodec.xcframework → ffmpeg_ios/libavcodec.xcframework}/ios-arm64/libavcodec.framework/Info.plist +0 -0
  513. package/common/cpp/audioapi/external/{libavcodec.xcframework → ffmpeg_ios/libavcodec.xcframework}/ios-arm64_x86_64-simulator/libavcodec.framework/Info.plist +0 -0
  514. package/common/cpp/audioapi/external/{libavformat.xcframework → ffmpeg_ios/libavformat.xcframework}/Info.plist +0 -0
  515. package/common/cpp/audioapi/external/{libavformat.xcframework → ffmpeg_ios/libavformat.xcframework}/ios-arm64/libavformat.framework/Info.plist +0 -0
  516. package/common/cpp/audioapi/external/{libavformat.xcframework → ffmpeg_ios/libavformat.xcframework}/ios-arm64_x86_64-simulator/libavformat.framework/Info.plist +0 -0
  517. package/common/cpp/audioapi/external/{libavutil.xcframework → ffmpeg_ios/libavutil.xcframework}/Info.plist +5 -5
  518. package/common/cpp/audioapi/external/{libavutil.xcframework → ffmpeg_ios/libavutil.xcframework}/ios-arm64/libavutil.framework/Info.plist +0 -0
  519. package/common/cpp/audioapi/external/{libavutil.xcframework → ffmpeg_ios/libavutil.xcframework}/ios-arm64_x86_64-simulator/libavutil.framework/Info.plist +0 -0
  520. package/common/cpp/audioapi/external/{libswresample.xcframework → ffmpeg_ios/libswresample.xcframework}/Info.plist +5 -5
  521. /package/common/cpp/audioapi/external/{libswresample.xcframework → ffmpeg_ios/libswresample.xcframework}/ios-arm64/libswresample.framework/Info.plist +0 -0
  522. /package/common/cpp/audioapi/external/{libswresample.xcframework → ffmpeg_ios/libswresample.xcframework}/ios-arm64_x86_64-simulator/libswresample.framework/Info.plist +0 -0
@@ -1,431 +1,510 @@
1
- #include <android/log.h>
2
- #include <cmath>
3
1
  extern "C" {
4
- #include <libavutil/log.h>
2
+ #include <libavcodec/avcodec.h>
3
+ #include <libavformat/avformat.h>
4
+ #include <libavutil/audio_fifo.h>
5
+ #include <libavutil/opt.h>
6
+ #include <libswresample/swresample.h>
5
7
  }
6
8
 
7
9
  #include <audioapi/android/core/utils/AndroidFileWriterBackend.h>
8
- #include <audioapi/android/core/utils/ffmpegBackend/FFmpegAudioFileOptions.h>
10
+ #include <audioapi/android/core/utils/FileOptions.h>
9
11
  #include <audioapi/android/core/utils/ffmpegBackend/FFmpegFileWriter.h>
12
+ #include <audioapi/android/core/utils/ffmpegBackend/ptrs.hpp>
13
+ #include <audioapi/android/core/utils/ffmpegBackend/utils.h>
14
+ #include <audioapi/utils/AudioFileProperties.h>
15
+ #include <audioapi/utils/UnitConversion.h>
10
16
 
11
- namespace audioapi {
17
+ #include <algorithm>
18
+ #include <memory>
19
+ #include <string>
20
+
21
+ constexpr int defaultFrameRatio = 4;
22
+ constexpr int fallbackFIFOSize = 8192;
23
+ constexpr int defaultFlushInterval = 100;
24
+
25
+ namespace audioapi::android::ffmpeg {
12
26
 
13
27
  FFmpegAudioFileWriter::FFmpegAudioFileWriter(
14
- float sampleRate,
15
- size_t channelCount,
16
- size_t bitRate,
17
- size_t androidFlags)
18
- : AndroidFileWriterBackend(
19
- sampleRate,
20
- channelCount,
21
- bitRate,
22
- androidFlags) {
23
- av_log_set_level(AV_LOG_DEBUG);
24
-
25
- av_log_set_callback([](void *, int level, const char *fmt, va_list vl) {
26
- if (level > av_log_get_level())
27
- return;
28
- char msg[1024];
29
- vsnprintf(msg, sizeof(msg), fmt, vl);
30
- __android_log_print(ANDROID_LOG_INFO, "FFmpeg", "%s", msg);
31
- });
32
-
33
- fileOptions_ = std::make_shared<FFmpegAudioFileOptions>(
34
- sampleRate, channelCount, bitRate, androidFlags);
28
+ const std::shared_ptr<AudioEventHandlerRegistry> &audioEventHandlerRegistry,
29
+ const std::shared_ptr<AudioFileProperties> &fileProperties)
30
+ : AndroidFileWriterBackend(audioEventHandlerRegistry, fileProperties) {
31
+ // Set flush interval from properties, limit minimum to 100ms
32
+ // to avoid people hurting themselves too much
33
+ flushIntervalMs_ = std::min(fileProperties_->androidFlushIntervalMs, defaultFlushInterval);
35
34
  }
36
35
 
37
36
  FFmpegAudioFileWriter::~FFmpegAudioFileWriter() {
38
- isFileOpen_.store(false);
39
- fileOptions_.reset();
37
+ if (isFileOpen()) {
38
+ closeFile();
39
+ }
40
40
  }
41
41
 
42
- void FFmpegAudioFileWriter::openFile(
43
- int32_t streamSampleRate,
42
+ /// @brief Opens a specified audio file for writing and prepares any necessary resources.
43
+ /// such as codecs, conversion buffers or circular AVIO FIFO.
44
+ /// This method should be called from the JS thread only.
45
+ /// @param streamSampleRate The sample rate of the incoming audio stream (aka microphone).
46
+ /// @param streamChannelCount The number of channels in the incoming audio stream.
47
+ /// @param streamMaxBufferSize The estimated maximum buffer size for the incoming audio stream.
48
+ /// @returns Success status with file path or Error status with message.
49
+ OpenFileResult FFmpegAudioFileWriter::openFile(
50
+ float streamSampleRate,
44
51
  int32_t streamChannelCount,
45
52
  int32_t streamMaxBufferSize) {
46
- filePath_ = fileOptions_->getFilePath("audio");
47
-
48
53
  streamSampleRate_ = streamSampleRate;
49
54
  streamChannelCount_ = streamChannelCount;
50
55
  streamMaxBufferSize_ = streamMaxBufferSize;
56
+ framesWritten_.store(0, std::memory_order_release);
51
57
  nextPts_ = 0;
58
+ Result<NoneType, std::string> result = Result<NoneType, std::string>::Ok(None);
59
+ Result<std::string, std::string> filePathResult = fileoptions::getFilePath(fileProperties_);
52
60
 
53
- const AVCodec *codec = fileOptions_->getCodec();
54
- AVFormatContext *rawFormatCtx = nullptr;
55
-
56
- if (avformat_alloc_output_context2(
57
- &rawFormatCtx,
58
- nullptr,
59
- fileOptions_->getMuxerName().c_str(),
60
- filePath_.c_str()) < 0 ||
61
- !rawFormatCtx) {
62
- __android_log_print(
63
- ANDROID_LOG_ERROR,
64
- "FFmpegFileWriter",
65
- "Failed to allocate FFmpeg format context for file: %s",
66
- filePath_.c_str());
67
- return;
61
+ if (!filePathResult.is_ok()) {
62
+ return OpenFileResult::Err(filePathResult.unwrap_err());
68
63
  }
69
64
 
70
- formatCtx_ = AVFormatContextPtr(rawFormatCtx);
71
- stream_ = avformat_new_stream(formatCtx_.get(), codec);
65
+ filePath_ = filePathResult.unwrap();
72
66
 
73
- encoderCtx_ = AVCodecContextPtr(avcodec_alloc_context3(codec));
67
+ const AVCodec *codec = getCodec(fileProperties_);
74
68
 
75
- if (!encoderCtx_) {
76
- __android_log_print(
77
- ANDROID_LOG_ERROR,
78
- "FFmpegFileWriter",
79
- "Failed to allocate FFmpeg codec context for file");
80
- return;
69
+ if (!codec) {
70
+ return OpenFileResult::Err("Unsupported codec for the given file format");
81
71
  }
82
72
 
83
- AVDictionary *codecOptions = nullptr;
84
- size_t bitRate = fileOptions_->getBitRate();
85
- int flacCompressionLevel = fileOptions_->getFlacCompressionLevel();
86
- av_channel_layout_default(
87
- &encoderCtx_->ch_layout, fileOptions_->getChannelCount());
88
-
89
- encoderCtx_->sample_rate = fileOptions_->getSampleRate();
90
- encoderCtx_->sample_fmt = fileOptions_->getSampleFormat();
73
+ result = initializeFormatContext(codec);
91
74
 
92
- if (bitRate > 0) {
93
- encoderCtx_->bit_rate = bitRate;
75
+ if (!result.is_ok()) {
76
+ return OpenFileResult::Err(result.unwrap_err());
94
77
  }
95
78
 
96
- if (flacCompressionLevel >= 0) {
97
- av_dict_set_int(
98
- &codecOptions, "compression_level", flacCompressionLevel, 0);
99
- }
79
+ result = configureAndOpenCodec(codec);
100
80
 
101
- if (avcodec_open2(encoderCtx_.get(), codec, &codecOptions) < 0) {
102
- __android_log_print(
103
- ANDROID_LOG_ERROR,
104
- "FFmpegFileWriter",
105
- "Failed to open FFmpeg codec for file");
106
- av_dict_free(&codecOptions);
107
- return;
81
+ if (!result.is_ok()) {
82
+ return OpenFileResult::Err(result.unwrap_err());
108
83
  }
109
84
 
110
- av_dict_free(&codecOptions);
85
+ result = initializeStream();
111
86
 
112
- if (avcodec_parameters_from_context(stream_->codecpar, encoderCtx_.get()) <
113
- 0) {
114
- __android_log_print(
115
- ANDROID_LOG_ERROR,
116
- "FFmpegFileWriter",
117
- "Failed to copy codec parameters to stream for file");
118
- return;
87
+ if (!result.is_ok()) {
88
+ return OpenFileResult::Err(result.unwrap_err());
119
89
  }
120
90
 
121
- if (!(formatCtx_->oformat->flags & AVFMT_NOFILE)) {
122
- if (avio_open(&formatCtx_->pb, filePath_.c_str(), AVIO_FLAG_WRITE) < 0) {
123
- __android_log_print(
124
- ANDROID_LOG_ERROR,
125
- "FFmpegFileWriter",
126
- "Failed to open output file: %s",
127
- filePath_.c_str());
128
- return;
129
- }
91
+ result = openIOAndWriteHeader();
92
+
93
+ if (!result.is_ok()) {
94
+ return OpenFileResult::Err(result.unwrap_err());
130
95
  }
131
96
 
132
- stream_->time_base =
133
- AVRational{1, static_cast<int>(encoderCtx_->sample_rate)};
97
+ result = initializeResampler(streamSampleRate, streamChannelCount);
134
98
 
135
- if (avformat_write_header(formatCtx_.get(), nullptr) < 0) {
136
- __android_log_print(
137
- ANDROID_LOG_ERROR,
138
- "FFmpegFileWriter",
139
- "Failed to write header to file: %s",
140
- filePath_.c_str());
141
- return;
99
+ if (!result.is_ok()) {
100
+ return OpenFileResult::Err(result.unwrap_err());
142
101
  }
143
102
 
144
- frame_ = AVFramePtr(av_frame_alloc());
145
- packet_ = AVPacketPtr(av_packet_alloc());
103
+ initializeBuffers(streamMaxBufferSize);
146
104
 
147
- resampleCtx_ = SwrContextPtr(swr_alloc());
105
+ isFileOpen_.store(true, std::memory_order_release);
106
+ return OpenFileResult::Ok(filePath_);
107
+ }
148
108
 
149
- AVChannelLayout inChannelLayout;
150
- av_channel_layout_default(&inChannelLayout, streamChannelCount_);
109
+ /// @brief Closes the currently opened audio file, flushing any remaining data and finalizing the file.
110
+ /// This method should called from the JS thread only.
111
+ /// @returns CloseFileStatus indicating success with file path, size and duration, or error with message.
112
+ CloseFileResult FFmpegAudioFileWriter::closeFile() {
113
+ int result = 0;
151
114
 
152
- av_opt_set_chlayout(resampleCtx_.get(), "in_chlayout", &inChannelLayout, 0);
115
+ if (!isFileOpen()) {
116
+ return CloseFileResult::Err("File is not open");
117
+ }
153
118
 
154
- av_opt_set_chlayout(
155
- resampleCtx_.get(), "out_chlayout", &encoderCtx_->ch_layout, 0);
119
+ result = processFifo(true);
156
120
 
157
- av_opt_set_int(resampleCtx_.get(), "in_sample_rate", streamSampleRate, 0);
121
+ if (result < 0) {
122
+ auto finalStatus = finalizeOutput();
158
123
 
159
- av_opt_set_int(
160
- resampleCtx_.get(), "out_sample_rate", encoderCtx_->sample_rate, 0);
124
+ return CloseFileResult::Err(
125
+ "Failed to flush FIFO to encoder. error code: " + parseErrorCode(result) +
126
+ ", finalization status: " + (finalStatus.is_ok() ? "success" : finalStatus.unwrap_err()));
127
+ }
161
128
 
162
- av_opt_set_sample_fmt(
163
- resampleCtx_.get(), "in_sample_fmt", AV_SAMPLE_FMT_FLT, 0);
129
+ result = avcodec_send_frame(encoderCtx_.get(), nullptr);
164
130
 
165
- av_opt_set_sample_fmt(
166
- resampleCtx_.get(), "out_sample_fmt", encoderCtx_->sample_fmt, 0);
131
+ if (result < 0) {
132
+ return CloseFileResult::Err("Failed to send EOF to encoder");
133
+ }
167
134
 
168
- if (swr_init(resampleCtx_.get()) < 0) {
169
- __android_log_print(
170
- ANDROID_LOG_ERROR,
171
- "FFmpegFileWriter",
172
- "Failed to initialize resampler for file: %s",
173
- filePath_.c_str());
174
- return;
135
+ if (writeEncodedPackets() < 0) {
136
+ return CloseFileResult::Err("Failed to drain encoder packets");
175
137
  }
176
138
 
177
- int contextFrameRatio = 2;
139
+ return finalizeOutput();
140
+ }
178
141
 
179
- if (encoderCtx_->frame_size > 0) {
180
- contextFrameRatio = static_cast<int>(std::ceil(
181
- static_cast<double>(streamMaxBufferSize_) /
182
- static_cast<double>(encoderCtx_->frame_size)));
142
+ /// @brief Writes audio data to the currently opened file.
143
+ /// This method should be called only from the audio thread (or audio side-effect thread in the future).
144
+ /// @param data Pointer to the audio data buffer (interleaved float samples) as returned by Oboe stream.
145
+ /// @param numFrames Number of audio frames in the data buffer.
146
+ /// @returns True if the data was written successfully, false otherwise.
147
+ bool FFmpegAudioFileWriter::writeAudioData(void *data, int numFrames) {
148
+ if (!isFileOpen()) {
149
+ return false;
183
150
  }
184
151
 
185
- int fifoSize = std::max(
186
- encoderCtx_->frame_size > 0
187
- ? encoderCtx_->frame_size * contextFrameRatio * 2
188
- : streamMaxBufferSize_ * 2,
189
- 4096);
152
+ if (!resampleAndPushToFifo(data, numFrames)) {
153
+ return false;
154
+ }
190
155
 
191
- audioFifo_ = AVAudioFifoPtr(av_audio_fifo_alloc(
192
- encoderCtx_->sample_fmt, encoderCtx_->ch_layout.nb_channels, fifoSize));
156
+ framesWritten_.fetch_add(numFrames, std::memory_order_acq_rel);
193
157
 
194
- __android_log_print(
195
- ANDROID_LOG_INFO,
196
- "FFmpegFileWriter",
197
- "Using audio FIFO size of %d frames",
198
- fifoSize);
158
+ if (processFifo(false) < 0) {
159
+ return false;
160
+ }
199
161
 
200
- isFileOpen_.store(true);
162
+ return true;
201
163
  }
202
164
 
203
- std::string FFmpegAudioFileWriter::closeFile() {
204
- if (!isFileOpen()) {
205
- return "";
165
+ /// @brief Initializes the FFmpeg format context for the output file.
166
+ /// @param codec The codec to be used for encoding.
167
+ /// @returns Success status or Error status with message.
168
+ Result<NoneType, std::string> FFmpegAudioFileWriter::initializeFormatContext(const AVCodec *codec) {
169
+ AVFormatContext *rawFormatCtx = nullptr;
170
+
171
+ int result = avformat_alloc_output_context2(
172
+ &rawFormatCtx, nullptr, getMuxerName(fileProperties_).c_str(), filePath_.c_str());
173
+
174
+ if (result < 0 || !rawFormatCtx) {
175
+ return Result<NoneType, std::string>::Err(
176
+ "Failed to allocate FFmpeg format context with error: " + parseErrorCode(result));
206
177
  }
207
178
 
208
- isFileOpen_.store(false);
179
+ formatCtx_ = av_unique_ptr<AVFormatContext>(rawFormatCtx);
180
+ return Result<NoneType, std::string>::Ok(None);
181
+ }
209
182
 
210
- const int frameSize =
211
- encoderCtx_->frame_size > 0 ? encoderCtx_->frame_size : 512;
183
+ /// @brief Configures and opens the codec context for encoding.
184
+ /// @param codec The codec to be used for encoding.
185
+ /// @returns Success status or Error status with message.
186
+ Result<NoneType, std::string> FFmpegAudioFileWriter::configureAndOpenCodec(const AVCodec *codec) {
187
+ encoderCtx_ = av_unique_ptr<AVCodecContext>(avcodec_alloc_context3(codec));
212
188
 
213
- while (av_audio_fifo_size(audioFifo_.get()) > 0) {
214
- const int chunkSize =
215
- std::min(av_audio_fifo_size(audioFifo_.get()), frameSize);
189
+ if (!encoderCtx_) {
190
+ return Result<NoneType, std::string>::Err("Failed to allocate FFmpeg codec context");
191
+ }
216
192
 
217
- frame_->nb_samples = chunkSize;
218
- av_channel_layout_copy(&frame_->ch_layout, &encoderCtx_->ch_layout);
219
- frame_->format = encoderCtx_->sample_fmt;
220
- frame_->sample_rate = encoderCtx_->sample_rate;
193
+ av_channel_layout_default(&encoderCtx_->ch_layout, fileProperties_->channelCount);
194
+ encoderCtx_->sample_rate = static_cast<int>(fileProperties_->sampleRate);
195
+ encoderCtx_->sample_fmt = getSampleFormat(fileProperties_);
221
196
 
222
- if (av_frame_get_buffer(frame_.get(), 0) < 0) {
223
- __android_log_print(
224
- ANDROID_LOG_ERROR,
225
- "FFmpegFileWriter",
226
- "Failed to allocate audio frame buffer during flushing");
227
- break;
228
- }
197
+ if (fileProperties_->bitRate > 0) {
198
+ encoderCtx_->bit_rate = fileProperties_->bitRate;
199
+ }
229
200
 
230
- int fifoReadFrameCount =
231
- av_audio_fifo_read(audioFifo_.get(), (void **)frame_->data, chunkSize);
201
+ AVDictionary *codecOptions = nullptr;
232
202
 
233
- if (fifoReadFrameCount != chunkSize) {
234
- __android_log_print(
235
- ANDROID_LOG_ERROR,
236
- "FFmpegFileWriter",
237
- "Failed to read audio samples from FIFO during flushing");
238
- break;
239
- }
203
+ if (fileProperties_->flacCompressionLevel >= 0) {
204
+ av_dict_set_int(&codecOptions, "compression_level", fileProperties_->flacCompressionLevel, 0);
205
+ }
240
206
 
241
- frame_->pts = nextPts_;
242
- nextPts_ += chunkSize;
207
+ int result = avcodec_open2(encoderCtx_.get(), codec, &codecOptions);
208
+ av_dict_free(&codecOptions);
243
209
 
244
- if (avcodec_send_frame(encoderCtx_.get(), frame_.get()) < 0) {
245
- __android_log_print(
246
- ANDROID_LOG_ERROR,
247
- "FFmpegFileWriter",
248
- "Failed to send audio frame to encoder during flushing");
249
- av_frame_unref(frame_.get());
250
- break;
251
- }
210
+ if (result < 0) {
211
+ return Result<NoneType, std::string>::Err(
212
+ "Failed to open FFmpeg codec with error: " + parseErrorCode(result));
213
+ }
252
214
 
253
- av_frame_unref(frame_.get());
215
+ return Result<NoneType, std::string>::Ok(None);
216
+ }
217
+
218
+ /// @brief Initializes a new stream in the format context.
219
+ /// @returns Success status or Error status with message.
220
+ Result<NoneType, std::string> FFmpegAudioFileWriter::initializeStream() {
221
+ stream_ = avformat_new_stream(formatCtx_.get(), nullptr);
222
+
223
+ if (!stream_) {
224
+ return Result<NoneType, std::string>::Err("Failed to create new stream in format context");
254
225
  }
255
226
 
256
- avcodec_send_frame(encoderCtx_.get(), nullptr);
227
+ int result = avcodec_parameters_from_context(stream_->codecpar, encoderCtx_.get());
257
228
 
258
- while (avcodec_receive_packet(encoderCtx_.get(), packet_.get()) == 0) {
259
- av_packet_rescale_ts(
260
- packet_.get(),
261
- AVRational{1, encoderCtx_->sample_rate},
262
- stream_->time_base);
263
- packet_->stream_index = stream_->index;
264
- av_interleaved_write_frame(formatCtx_.get(), packet_.get());
265
- av_packet_unref(packet_.get());
229
+ if (result < 0) {
230
+ return Result<NoneType, std::string>::Err(
231
+ "Failed to copy codec parameters to stream with error: " + parseErrorCode(result));
266
232
  }
267
233
 
268
- if (av_write_trailer(formatCtx_.get()) < 0) {
269
- __android_log_print(
270
- ANDROID_LOG_ERROR,
271
- "FFmpegFileWriter",
272
- "Failed to write trailer to file: %s",
273
- filePath_.c_str());
234
+ stream_->time_base = AVRational{1, static_cast<int>(encoderCtx_->sample_rate)};
235
+ return Result<NoneType, std::string>::Ok(None);
236
+ }
237
+
238
+ /// @brief Opens the file and writes the basic header (depends on the codec/format used).
239
+ /// @returns Success status or Error status with message.
240
+ Result<NoneType, std::string> FFmpegAudioFileWriter::openIOAndWriteHeader() {
241
+ int result = 0;
242
+
243
+ if (!(formatCtx_->oformat->flags & AVFMT_NOFILE)) {
244
+ result = avio_open(&formatCtx_->pb, filePath_.c_str(), AVIO_FLAG_WRITE);
245
+
246
+ if (result < 0) {
247
+ return Result<NoneType, std::string>::Err(
248
+ "Failed to open output file with error: " + parseErrorCode(result));
249
+ }
274
250
  }
275
251
 
276
- if (formatCtx_ && formatCtx_->pb) {
277
- avio_closep(&formatCtx_->pb);
252
+ result = avformat_write_header(formatCtx_.get(), nullptr);
253
+
254
+ if (result < 0) {
255
+ return Result<NoneType, std::string>::Err("Failed to write header to file: " + filePath_);
278
256
  }
279
257
 
280
- resampleCtx_.reset();
281
- frame_.reset();
282
- packet_.reset();
283
- encoderCtx_.reset();
284
- formatCtx_.reset();
285
- audioFifo_.reset();
258
+ return Result<NoneType, std::string>::Ok(None);
259
+ }
286
260
 
287
- std::string closedFilePath = filePath_;
288
- filePath_ = "";
261
+ /// @brief Initializes the resampler context for audio conversion.
262
+ /// @param inputRate The sample rate of the input audio.
263
+ /// @param inputChannels The number of channels in the input audio.
264
+ /// @returns Success status or Error status with message.
265
+ Result<NoneType, std::string> FFmpegAudioFileWriter::initializeResampler(
266
+ float inputRate,
267
+ int inputChannels) {
268
+ resampleCtx_ = av_unique_ptr<SwrContext>(swr_alloc());
269
+
270
+ if (!resampleCtx_) {
271
+ return Result<NoneType, std::string>::Err("Failed to allocate resampler context");
272
+ }
289
273
 
290
- return closedFilePath;
274
+ AVChannelLayout inChannelLayout;
275
+ av_channel_layout_default(&inChannelLayout, inputChannels);
276
+
277
+ av_opt_set_chlayout(resampleCtx_.get(), "in_chlayout", &inChannelLayout, 0);
278
+ av_opt_set_chlayout(resampleCtx_.get(), "out_chlayout", &encoderCtx_->ch_layout, 0);
279
+
280
+ av_opt_set_int(resampleCtx_.get(), "in_sample_rate", static_cast<int64_t>(inputRate), 0);
281
+ av_opt_set_int(resampleCtx_.get(), "out_sample_rate", encoderCtx_->sample_rate, 0);
282
+
283
+ av_opt_set_sample_fmt(resampleCtx_.get(), "in_sample_fmt", AV_SAMPLE_FMT_FLT, 0);
284
+ av_opt_set_sample_fmt(resampleCtx_.get(), "out_sample_fmt", encoderCtx_->sample_fmt, 0);
285
+
286
+ int result = swr_init(resampleCtx_.get());
287
+
288
+ if (result < 0) {
289
+ return Result<NoneType, std::string>::Err(
290
+ "Failed to initialize resampler for file: " + parseErrorCode(result));
291
+ }
292
+
293
+ return Result<NoneType, std::string>::Ok(None);
291
294
  }
292
295
 
293
- bool FFmpegAudioFileWriter::writeAudioData(void *data, int numFrames) {
294
- if (!isFileOpen()) {
295
- return false;
296
+ /// @brief Initializes frame and packet buffers as well as the audio FIFO,
297
+ /// that might be needed for storing intermediate audio data or buffering before encoding.
298
+ /// @param maxBufferSize The maximum buffer size to allocate.
299
+ void FFmpegAudioFileWriter::initializeBuffers(int32_t maxBufferSize) {
300
+ frame_ = av_unique_ptr<AVFrame>(av_frame_alloc());
301
+ packet_ = av_unique_ptr<AVPacket>(av_packet_alloc());
302
+
303
+ int frameRatio = defaultFrameRatio;
304
+ if (encoderCtx_->frame_size > 0) {
305
+ frameRatio = static_cast<int>(std::ceil(
306
+ static_cast<double>(maxBufferSize) / static_cast<double>(encoderCtx_->frame_size)));
296
307
  }
297
308
 
298
- int outputLength = av_rescale_rnd(
299
- numFrames, encoderCtx_->sample_rate, streamSampleRate_, AV_ROUND_UP);
309
+ int calculatedSize =
310
+ (encoderCtx_->frame_size > 0 ? encoderCtx_->frame_size * frameRatio
311
+ : maxBufferSize * frameRatio);
300
312
 
301
- frame_->nb_samples = outputLength;
302
- av_channel_layout_copy(&frame_->ch_layout, &encoderCtx_->ch_layout);
303
- frame_->format = encoderCtx_->sample_fmt;
304
- frame_->sample_rate = encoderCtx_->sample_rate;
313
+ int fifoSize = std::max(calculatedSize, fallbackFIFOSize);
305
314
 
306
- if (av_frame_get_buffer(frame_.get(), 0) < 0) {
307
- __android_log_print(
308
- ANDROID_LOG_ERROR,
309
- "FFmpegFileWriter",
310
- "Failed to allocate audio frame buffer, outputLength: %d, format: %d, sample_rate: %d, channels: %d",
311
- outputLength,
312
- encoderCtx_->sample_fmt,
313
- encoderCtx_->sample_rate,
314
- encoderCtx_->ch_layout.nb_channels);
315
+ audioFifo_ = av_unique_ptr<AVAudioFifo>(
316
+ av_audio_fifo_alloc(encoderCtx_->sample_fmt, encoderCtx_->ch_layout.nb_channels, fifoSize));
317
+ }
315
318
 
319
+ /// @brief Resamples input audio data and pushes it to the audio FIFO.
320
+ /// @param inputData Pointer to the input audio data.
321
+ /// @param inputFrameCount Number of input frames.
322
+ /// @returns True if successful, false otherwise.
323
+ bool FFmpegAudioFileWriter::resampleAndPushToFifo(void *inputData, int inputFrameCount) {
324
+ int result = 0;
325
+ int64_t outputLength = av_rescale_rnd(
326
+ inputFrameCount, encoderCtx_->sample_rate, static_cast<int>(streamSampleRate_), AV_ROUND_UP);
327
+
328
+ result = prepareFrameForEncoding(outputLength);
329
+
330
+ if (result < 0) {
331
+ invokeOnErrorCallback("Failed to prepare frame for resampling: " + parseErrorCode(result));
316
332
  return false;
317
333
  }
318
334
 
319
- const uint8_t *inputData[1] = {reinterpret_cast<const uint8_t *>(data)};
335
+ const uint8_t *inputs[1] = {reinterpret_cast<const uint8_t *>(inputData)};
320
336
 
321
337
  int convertedSamples = swr_convert(
322
- resampleCtx_.get(), frame_->data, outputLength, inputData, numFrames);
338
+ resampleCtx_.get(), frame_->data, static_cast<int>(outputLength), inputs, inputFrameCount);
323
339
 
324
340
  if (convertedSamples < 0) {
325
- __android_log_print(
326
- ANDROID_LOG_ERROR,
327
- "FFmpegFileWriter",
328
- "Failed to convert audio samples for file: %s",
329
- filePath_.c_str());
341
+ invokeOnErrorCallback("Failed to convert audio samples: " + parseErrorCode(convertedSamples));
330
342
  av_frame_unref(frame_.get());
331
343
  return false;
332
344
  }
333
345
 
334
- int fifoWrittenFrameCount = av_audio_fifo_write(
335
- audioFifo_.get(), (void **)frame_->data, convertedSamples);
346
+ int written = av_audio_fifo_write(
347
+ audioFifo_.get(), reinterpret_cast<void **>(frame_->data), convertedSamples);
336
348
 
337
- if (fifoWrittenFrameCount < convertedSamples) {
338
- __android_log_print(
339
- ANDROID_LOG_ERROR,
340
- "FFmpegFileWriter",
341
- "Failed to write audio samples to FIFO");
349
+ if (written < convertedSamples) {
350
+ invokeOnErrorCallback("Failed to write all samples to FIFO");
342
351
  av_frame_unref(frame_.get());
343
352
  return false;
344
353
  }
345
354
 
346
- av_frame_unref(frame_.get());
347
- const int frameSize =
348
- encoderCtx_->frame_size > 0 ? encoderCtx_->frame_size : 512;
355
+ return true;
356
+ }
349
357
 
350
- while (av_audio_fifo_size(audioFifo_.get()) >= frameSize) {
351
- frame_->nb_samples = frameSize;
352
- av_channel_layout_copy(&frame_->ch_layout, &encoderCtx_->ch_layout);
353
- frame_->format = encoderCtx_->sample_fmt;
354
- frame_->sample_rate = encoderCtx_->sample_rate;
358
+ /// @brief pushes the audio data from FIFO to the encoder in chunks,
359
+ // defined by the encoder (512 samples by default) or flushes the FIFO if requested.
360
+ /// Note: flush might be called only when writing the final data batch, otherwise
361
+ // the codec will crash (especially in case of defined size frames like AAC).
362
+ /// @param flush Indicates whether to flush the FIFO.
363
+ /// @returns 0 on success, -1 or AV_ERROR code on failure
364
+ int FFmpegAudioFileWriter::processFifo(bool flush) {
365
+ int result = 0;
366
+ int frameSize = encoderCtx_->frame_size > 0 ? encoderCtx_->frame_size : 512;
367
+
368
+ while (av_audio_fifo_size(audioFifo_.get()) >= (flush ? 1 : frameSize)) {
369
+ const int chunkSize = std::min(av_audio_fifo_size(audioFifo_.get()), frameSize);
370
+
371
+ if (prepareFrameForEncoding(chunkSize) < 0) {
372
+ invokeOnErrorCallback("Failed to prepare frame for encoding");
373
+ return -1;
374
+ }
355
375
 
356
- if (av_frame_get_buffer(frame_.get(), 0) < 0) {
357
- __android_log_print(
358
- ANDROID_LOG_ERROR,
359
- "FFmpegFileWriter",
360
- "Failed to allocate audio frame buffer");
361
- return false;
376
+ if (av_audio_fifo_read(audioFifo_.get(), reinterpret_cast<void **>(frame_->data), chunkSize) !=
377
+ chunkSize) {
378
+ invokeOnErrorCallback("Failed to read data from FIFO");
379
+ return -1;
362
380
  }
363
381
 
364
- int fifoReadFrameCount =
365
- av_audio_fifo_read(audioFifo_.get(), (void **)frame_->data, frameSize);
382
+ frame_->pts = nextPts_;
383
+ nextPts_ += chunkSize;
366
384
 
367
- if (fifoReadFrameCount != frameSize) {
368
- __android_log_print(
369
- ANDROID_LOG_ERROR,
370
- "FFmpegFileWriter",
371
- "Failed to read audio samples from FIFO");
372
- return false;
385
+ result = avcodec_send_frame(encoderCtx_.get(), frame_.get());
386
+
387
+ if (result < 0) {
388
+ invokeOnErrorCallback("Failed to send frame to encoder: " + parseErrorCode(result));
389
+ return result;
373
390
  }
374
391
 
375
- frame_->pts = nextPts_;
376
- nextPts_ += frameSize;
377
-
378
- if (avcodec_send_frame(encoderCtx_.get(), frame_.get()) < 0) {
379
- __android_log_print(
380
- ANDROID_LOG_ERROR,
381
- "FFmpegFileWriter",
382
- "Failed to send audio frame to encoder");
383
- av_frame_unref(frame_.get());
384
- return false;
392
+ result = writeEncodedPackets();
393
+
394
+ if (result < 0) {
395
+ invokeOnErrorCallback("Failed to write encoded packets: " + parseErrorCode(result));
396
+ return result;
397
+ }
398
+ }
399
+
400
+ return 0;
401
+ }
402
+
403
+ /// @brief Takes ready encoded packets from the encoder and writes them to the output file.
404
+ /// Also in order to optimize file writing vs file resilience from crashes, it periodically
405
+ /// forces the AVIO buffer to flush data to disk, by default every 0,5 second.
406
+ /// @returns 0 on success, AV_ERROR code on failure
407
+ int FFmpegAudioFileWriter::writeEncodedPackets() {
408
+ int result = 0;
409
+
410
+ while (true) {
411
+ result = avcodec_receive_packet(encoderCtx_.get(), packet_.get());
412
+
413
+ if (result == AVERROR(EAGAIN) || result == AVERROR_EOF) {
414
+ return 0;
415
+ } else if (result < 0) {
416
+ invokeOnErrorCallback("Failed to receive packet from encoder: " + parseErrorCode(result));
417
+ return result;
385
418
  }
386
419
 
387
- while (avcodec_receive_packet(encoderCtx_.get(), packet_.get()) == 0) {
388
- av_packet_rescale_ts(
389
- packet_.get(),
390
- AVRational{1, encoderCtx_->sample_rate},
391
- stream_->time_base);
420
+ av_packet_rescale_ts(packet_.get(), encoderCtx_->time_base, stream_->time_base);
421
+ packet_->stream_index = stream_->index;
392
422
 
393
- packet_->stream_index = stream_->index;
423
+ result = av_interleaved_write_frame(formatCtx_.get(), packet_.get());
394
424
 
395
- if (av_interleaved_write_frame(formatCtx_.get(), packet_.get()) < 0) {
396
- __android_log_print(
397
- ANDROID_LOG_ERROR,
398
- "FFmpegFileWriter",
399
- "Failed to write audio packet to file");
425
+ auto now = std::chrono::steady_clock::now();
426
+ auto elapsedMs =
427
+ std::chrono::duration_cast<std::chrono::milliseconds>(now - lastFlushTime_).count();
400
428
 
401
- av_packet_unref(packet_.get());
402
- av_frame_unref(frame_.get());
403
- return false;
404
- }
429
+ if (formatCtx_->pb && elapsedMs >= flushIntervalMs_) {
430
+ avio_flush(formatCtx_->pb);
431
+ lastFlushTime_ = now;
432
+ }
405
433
 
406
- av_packet_unref(packet_.get());
434
+ if (result < 0) {
435
+ return result;
407
436
  }
437
+ }
438
+ }
439
+
440
+ /// @brief Prepares the frame for next encoding phase,
441
+ /// if frame is same size as previously used one (99.9% cases) try to reuse it.
442
+ /// Otherwise resize the frame and in the worst case allocate new frame to use.
443
+ /// @param samplesToRead Number of samples to prepare the frame for.
444
+ /// @returns 0 on success, AV_ERROR code on failure
445
+ int FFmpegAudioFileWriter::prepareFrameForEncoding(int64_t samplesToRead) {
446
+ int result = 0;
447
+
448
+ if (frame_->data[0] && frame_->nb_samples == samplesToRead &&
449
+ av_frame_is_writable(frame_.get())) {
450
+ return 0;
451
+ }
452
+
453
+ frame_->nb_samples = static_cast<int>(samplesToRead);
454
+ frame_->format = encoderCtx_->sample_fmt;
455
+ frame_->sample_rate = encoderCtx_->sample_rate;
456
+
457
+ if (av_channel_layout_compare(&frame_->ch_layout, &encoderCtx_->ch_layout) != 0) {
458
+ av_channel_layout_uninit(&frame_->ch_layout);
459
+
460
+ result = av_channel_layout_copy(&frame_->ch_layout, &encoderCtx_->ch_layout);
461
+
462
+ if (result < 0) {
463
+ invokeOnErrorCallback("Failed to copy channel layout: " + parseErrorCode(result));
464
+ return result;
465
+ }
466
+ }
467
+
468
+ result = av_frame_make_writable(frame_.get());
408
469
 
470
+ if (result < 0) {
409
471
  av_frame_unref(frame_.get());
472
+
473
+ frame_->nb_samples = static_cast<int>(samplesToRead);
474
+ ;
475
+ frame_->format = encoderCtx_->sample_fmt;
476
+ frame_->sample_rate = encoderCtx_->sample_rate;
477
+ av_channel_layout_copy(&frame_->ch_layout, &encoderCtx_->ch_layout);
478
+
479
+ result = av_frame_get_buffer(frame_.get(), 0);
410
480
  }
411
481
 
412
- return true;
482
+ return result;
413
483
  }
414
484
 
415
- bool FFmpegAudioFileWriter::initializeConverterIfNeeded() {
416
- return false;
417
- }
485
+ /// @brief Closes the currently opened audio file, flushing any remaining data and finalizing the file.
486
+ /// Method checks the file size and duration for convenience.
487
+ /// @returns CloseFileResult indicating success or error details
488
+ CloseFileResult FFmpegAudioFileWriter::finalizeOutput() {
489
+ int result = av_write_trailer(formatCtx_.get());
418
490
 
419
- bool FFmpegAudioFileWriter::initializeEncoder() {
420
- return false;
421
- }
491
+ if (result < 0) {
492
+ return CloseFileResult::Err("Failed to write trailer: " + parseErrorCode(result));
493
+ }
422
494
 
423
- bool FFmpegAudioFileWriter::isFileOpen() {
424
- return isFileOpen_.load();
425
- }
495
+ double fileSizeInMB = 0;
496
+
497
+ if (formatCtx_->pb) {
498
+ fileSizeInMB = static_cast<double>(avio_size(formatCtx_->pb)) / MB_IN_BYTES;
499
+ avio_closep(&formatCtx_->pb);
500
+ }
501
+
502
+ double durationInSeconds = getCurrentDuration();
503
+
504
+ filePath_ = "";
505
+ isFileOpen_.store(false, std::memory_order_release);
426
506
 
427
- bool FFmpegAudioFileWriter::isConverterRequired() {
428
- return isConverterRequired_.load();
507
+ return CloseFileResult::Ok({fileSizeInMB, durationInSeconds});
429
508
  }
430
509
 
431
- } // namespace audioapi
510
+ } // namespace audioapi::android::ffmpeg