react-native-audio-api 0.13.0 → 1.0.0-nightly-a9a9810-20260702
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.
- package/RNAudioAPI.podspec +2 -1
- package/android/src/main/cpp/audioapi/CMakeLists.txt +10 -0
- package/android/src/main/cpp/audioapi/android/AudioAPIModule.cpp +4 -0
- package/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.cpp +139 -95
- package/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.h +6 -5
- package/android/src/main/cpp/audioapi/android/core/AudioPlayer.cpp +2 -2
- package/android/src/main/cpp/audioapi/android/core/AudioPlayer.h +2 -2
- package/android/src/main/cpp/audioapi/android/core/utils/AndroidRotatingFileWriter.cpp +3 -1
- package/android/src/main/cpp/audioapi/android/system/NativeFileInfo.cpp +48 -0
- package/android/src/main/cpp/audioapi/android/system/NativeFileInfo.hpp +6 -8
- package/common/cpp/audioapi/HostObjects/AudioContextHostObject.cpp +9 -11
- package/common/cpp/audioapi/HostObjects/AudioNodeHostObject.cpp +34 -13
- package/common/cpp/audioapi/HostObjects/AudioNodeHostObject.h +14 -4
- package/common/cpp/audioapi/HostObjects/AudioParamHostObject.cpp +29 -2
- package/common/cpp/audioapi/HostObjects/AudioParamHostObject.h +36 -1
- package/common/cpp/audioapi/HostObjects/BaseAudioContextHostObject.cpp +67 -59
- package/common/cpp/audioapi/HostObjects/OfflineAudioContextHostObject.cpp +2 -0
- package/common/cpp/audioapi/HostObjects/TypedAudioNodePtr.h +16 -0
- package/common/cpp/audioapi/HostObjects/analysis/AnalyserNodeHostObject.cpp +18 -31
- package/common/cpp/audioapi/HostObjects/analysis/AnalyserNodeHostObject.h +14 -0
- package/common/cpp/audioapi/HostObjects/destinations/AudioDestinationNodeHostObject.h +15 -2
- package/common/cpp/audioapi/HostObjects/effects/BiquadFilterNodeHostObject.cpp +22 -16
- package/common/cpp/audioapi/HostObjects/effects/BiquadFilterNodeHostObject.h +10 -0
- package/common/cpp/audioapi/HostObjects/effects/ConvolverNodeHostObject.cpp +18 -12
- package/common/cpp/audioapi/HostObjects/effects/ConvolverNodeHostObject.h +10 -0
- package/common/cpp/audioapi/HostObjects/effects/DelayNodeHostObject.cpp +45 -7
- package/common/cpp/audioapi/HostObjects/effects/DelayNodeHostObject.h +10 -1
- package/common/cpp/audioapi/HostObjects/effects/GainNodeHostObject.cpp +7 -3
- package/common/cpp/audioapi/HostObjects/effects/GainNodeHostObject.h +8 -0
- package/common/cpp/audioapi/HostObjects/effects/IIRFilterNodeHostObject.cpp +10 -6
- package/common/cpp/audioapi/HostObjects/effects/IIRFilterNodeHostObject.h +13 -0
- package/common/cpp/audioapi/HostObjects/effects/StereoPannerNodeHostObject.cpp +8 -3
- package/common/cpp/audioapi/HostObjects/effects/StereoPannerNodeHostObject.h +8 -0
- package/common/cpp/audioapi/HostObjects/effects/WaveShaperNodeHostObject.cpp +31 -12
- package/common/cpp/audioapi/HostObjects/effects/WaveShaperNodeHostObject.h +10 -0
- package/common/cpp/audioapi/HostObjects/effects/WorkletNodeHostObject.h +16 -2
- package/common/cpp/audioapi/HostObjects/effects/WorkletProcessingNodeHostObject.h +18 -2
- package/common/cpp/audioapi/HostObjects/inputs/AudioRecorderHostObject.cpp +1 -2
- package/common/cpp/audioapi/HostObjects/sources/AudioBufferBaseSourceNodeHostObject.cpp +20 -17
- package/common/cpp/audioapi/HostObjects/sources/AudioBufferBaseSourceNodeHostObject.h +4 -1
- package/common/cpp/audioapi/HostObjects/sources/AudioBufferQueueSourceNodeHostObject.cpp +31 -31
- package/common/cpp/audioapi/HostObjects/sources/AudioBufferQueueSourceNodeHostObject.h +10 -0
- package/common/cpp/audioapi/HostObjects/sources/AudioBufferSourceNodeHostObject.cpp +39 -36
- package/common/cpp/audioapi/HostObjects/sources/AudioBufferSourceNodeHostObject.h +11 -0
- package/common/cpp/audioapi/HostObjects/sources/AudioFileSourceNodeHostObject.cpp +29 -32
- package/common/cpp/audioapi/HostObjects/sources/AudioFileSourceNodeHostObject.h +11 -2
- package/common/cpp/audioapi/HostObjects/sources/AudioScheduledSourceNodeHostObject.cpp +23 -18
- package/common/cpp/audioapi/HostObjects/sources/AudioScheduledSourceNodeHostObject.h +5 -1
- package/common/cpp/audioapi/HostObjects/sources/ConstantSourceNodeHostObject.cpp +8 -3
- package/common/cpp/audioapi/HostObjects/sources/ConstantSourceNodeHostObject.h +8 -0
- package/common/cpp/audioapi/HostObjects/sources/MediaElementAudioSourceNodeHostObject.h +9 -5
- package/common/cpp/audioapi/HostObjects/sources/OscillatorNodeHostObject.cpp +19 -12
- package/common/cpp/audioapi/HostObjects/sources/OscillatorNodeHostObject.h +11 -0
- package/common/cpp/audioapi/HostObjects/sources/RecorderAdapterNodeHostObject.h +16 -2
- package/common/cpp/audioapi/HostObjects/sources/StreamerNodeHostObject.h +4 -1
- package/common/cpp/audioapi/HostObjects/sources/WorkletSourceNodeHostObject.h +15 -2
- package/common/cpp/audioapi/core/AudioContext.cpp +7 -31
- package/common/cpp/audioapi/core/AudioContext.h +4 -7
- package/common/cpp/audioapi/core/AudioNode.cpp +77 -248
- package/common/cpp/audioapi/core/AudioNode.h +140 -53
- package/common/cpp/audioapi/core/AudioParam.cpp +26 -75
- package/common/cpp/audioapi/core/AudioParam.h +8 -18
- package/common/cpp/audioapi/core/BaseAudioContext.cpp +43 -174
- package/common/cpp/audioapi/core/BaseAudioContext.h +51 -79
- package/common/cpp/audioapi/core/OfflineAudioContext.cpp +1 -6
- package/common/cpp/audioapi/core/OfflineAudioContext.h +1 -1
- package/common/cpp/audioapi/core/analysis/AnalyserNode.cpp +4 -8
- package/common/cpp/audioapi/core/analysis/AnalyserNode.h +1 -3
- package/common/cpp/audioapi/core/destinations/AudioDestinationNode.h +6 -20
- package/common/cpp/audioapi/core/effects/BiquadFilterNode.cpp +35 -11
- package/common/cpp/audioapi/core/effects/BiquadFilterNode.h +28 -3
- package/common/cpp/audioapi/core/effects/ConvolverNode.cpp +66 -44
- package/common/cpp/audioapi/core/effects/ConvolverNode.h +11 -8
- package/common/cpp/audioapi/core/effects/DelayNode.cpp +21 -87
- package/common/cpp/audioapi/core/effects/DelayNode.h +10 -13
- package/common/cpp/audioapi/core/effects/GainNode.cpp +5 -11
- package/common/cpp/audioapi/core/effects/GainNode.h +1 -3
- package/common/cpp/audioapi/core/effects/IIRFilterNode.cpp +100 -11
- package/common/cpp/audioapi/core/effects/IIRFilterNode.h +27 -3
- package/common/cpp/audioapi/core/effects/StereoPannerNode.cpp +19 -15
- package/common/cpp/audioapi/core/effects/StereoPannerNode.h +6 -3
- package/common/cpp/audioapi/core/effects/WaveShaperNode.cpp +18 -13
- package/common/cpp/audioapi/core/effects/WaveShaperNode.h +18 -5
- package/common/cpp/audioapi/core/effects/WorkletNode.cpp +5 -10
- package/common/cpp/audioapi/core/effects/WorkletNode.h +2 -8
- package/common/cpp/audioapi/core/effects/WorkletProcessingNode.cpp +4 -10
- package/common/cpp/audioapi/core/effects/WorkletProcessingNode.h +2 -8
- package/common/cpp/audioapi/core/effects/delay/DelayLine.h +63 -0
- package/common/cpp/audioapi/core/effects/delay/DelayReader.cpp +34 -0
- package/common/cpp/audioapi/core/effects/delay/DelayReader.h +27 -0
- package/common/cpp/audioapi/core/effects/delay/DelayRingBufferOp.h +52 -0
- package/common/cpp/audioapi/core/effects/delay/DelayWriter.cpp +47 -0
- package/common/cpp/audioapi/core/effects/delay/DelayWriter.h +36 -0
- package/common/cpp/audioapi/core/effects/delay/host_nodes/DelayReaderHostNode.h +18 -0
- package/common/cpp/audioapi/core/effects/delay/host_nodes/DelayWriterHostNode.h +20 -0
- package/common/cpp/audioapi/core/inputs/AudioRecorder.cpp +18 -125
- package/common/cpp/audioapi/core/inputs/AudioRecorder.h +10 -63
- package/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.cpp +9 -10
- package/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.h +1 -3
- package/common/cpp/audioapi/core/sources/AudioBufferQueueSourceNode.cpp +7 -12
- package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp +9 -6
- package/common/cpp/audioapi/core/sources/AudioFileSourceNode.cpp +28 -35
- package/common/cpp/audioapi/core/sources/AudioFileSourceNode.h +9 -10
- package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.cpp +12 -13
- package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.h +7 -5
- package/common/cpp/audioapi/core/sources/ConstantSourceNode.cpp +9 -16
- package/common/cpp/audioapi/core/sources/ConstantSourceNode.h +1 -3
- package/common/cpp/audioapi/core/sources/MediaElementAudioSourceNode.cpp +22 -25
- package/common/cpp/audioapi/core/sources/MediaElementAudioSourceNode.h +4 -5
- package/common/cpp/audioapi/core/sources/OscillatorNode.cpp +9 -15
- package/common/cpp/audioapi/core/sources/OscillatorNode.h +1 -3
- package/common/cpp/audioapi/core/sources/RecorderAdapterNode.cpp +4 -7
- package/common/cpp/audioapi/core/sources/RecorderAdapterNode.h +3 -3
- package/common/cpp/audioapi/core/sources/StreamerNode.cpp +23 -34
- package/common/cpp/audioapi/core/sources/StreamerNode.h +11 -10
- package/common/cpp/audioapi/core/sources/WorkletSourceNode.cpp +14 -20
- package/common/cpp/audioapi/core/sources/WorkletSourceNode.h +2 -8
- package/common/cpp/audioapi/core/utils/Constants.h +7 -0
- package/common/cpp/audioapi/core/utils/{graph/Disposer.hpp → Disposer.hpp} +5 -6
- package/common/cpp/audioapi/core/utils/graph/AudioGraph.cpp +210 -0
- package/common/cpp/audioapi/core/utils/graph/AudioGraph.h +188 -0
- package/common/cpp/audioapi/core/utils/graph/BridgeNode.cpp +36 -0
- package/common/cpp/audioapi/core/utils/graph/BridgeNode.h +52 -0
- package/common/cpp/audioapi/core/utils/graph/Graph.cpp +174 -0
- package/common/cpp/audioapi/core/utils/graph/Graph.h +202 -0
- package/common/cpp/audioapi/core/utils/graph/GraphObject.cpp +36 -0
- package/common/cpp/audioapi/core/utils/graph/GraphObject.h +98 -0
- package/common/cpp/audioapi/core/utils/graph/HostGraph.cpp +471 -0
- package/common/cpp/audioapi/core/utils/graph/HostGraph.h +162 -0
- package/common/cpp/audioapi/core/utils/graph/HostNode.cpp +56 -0
- package/common/cpp/audioapi/core/utils/graph/{HostNode.hpp → HostNode.h} +32 -49
- package/common/cpp/audioapi/core/utils/graph/InputPool.cpp +123 -0
- package/common/cpp/audioapi/core/utils/graph/{InputPool.hpp → InputPool.h} +3 -126
- package/common/cpp/audioapi/core/utils/graph/NodeHandle.cpp +10 -0
- package/common/cpp/audioapi/core/utils/graph/{NodeHandle.hpp → NodeHandle.h} +5 -6
- package/common/cpp/audioapi/dsp/Convolver.cpp +14 -10
- package/common/cpp/audioapi/dsp/WaveShaper.cpp +33 -14
- package/common/cpp/audioapi/dsp/WaveShaper.h +23 -4
- package/common/cpp/audioapi/dsp/r8brain/Resampler.hpp +11 -9
- package/common/cpp/audioapi/jsi/JsiPromise.h +2 -2
- package/common/cpp/audioapi/jsi/RuntimeLifecycleMonitor.cpp +15 -5
- package/common/cpp/audioapi/types/NodeOptions.h +20 -4
- package/common/cpp/audioapi/utils/SpscChannel.hpp +80 -0
- package/common/cpp/audioapi/utils/ThreadPool.hpp +29 -13
- package/ios/audioapi/ios/core/IOSAudioPlayer.h +2 -2
- package/ios/audioapi/ios/core/IOSAudioPlayer.mm +2 -6
- package/ios/audioapi/ios/core/IOSAudioRecorder.h +7 -3
- package/ios/audioapi/ios/core/IOSAudioRecorder.mm +180 -92
- package/ios/audioapi/ios/core/utils/IOSRotatingFileWriter.mm +3 -1
- package/lib/commonjs/Audio/AudioFileSourceNode.js +3 -0
- package/lib/commonjs/Audio/AudioFileSourceNode.js.map +1 -1
- package/lib/commonjs/api.js +0 -8
- package/lib/commonjs/api.js.map +1 -1
- package/lib/commonjs/core/AudioBufferBaseSourceNode.js +2 -2
- package/lib/commonjs/core/AudioBufferBaseSourceNode.js.map +1 -1
- package/lib/commonjs/core/AudioNode.js +7 -1
- package/lib/commonjs/core/AudioNode.js.map +1 -1
- package/lib/commonjs/core/AudioParam.js +4 -1
- package/lib/commonjs/core/AudioParam.js.map +1 -1
- package/lib/commonjs/core/AudioRecorder.js +7 -16
- package/lib/commonjs/core/AudioRecorder.js.map +1 -1
- package/lib/commonjs/core/BaseAudioContext.js +0 -4
- package/lib/commonjs/core/BaseAudioContext.js.map +1 -1
- package/lib/commonjs/core/BiquadFilterNode.js +4 -4
- package/lib/commonjs/core/BiquadFilterNode.js.map +1 -1
- package/lib/commonjs/core/ConstantSourceNode.js +1 -1
- package/lib/commonjs/core/ConstantSourceNode.js.map +1 -1
- package/lib/commonjs/core/DelayNode.js +1 -1
- package/lib/commonjs/core/DelayNode.js.map +1 -1
- package/lib/commonjs/core/GainNode.js +1 -1
- package/lib/commonjs/core/GainNode.js.map +1 -1
- package/lib/commonjs/core/MediaElementAudioSourceNode.js +8 -0
- package/lib/commonjs/core/MediaElementAudioSourceNode.js.map +1 -1
- package/lib/commonjs/core/OscillatorNode.js +2 -2
- package/lib/commonjs/core/OscillatorNode.js.map +1 -1
- package/lib/commonjs/core/StereoPannerNode.js +1 -1
- package/lib/commonjs/core/StereoPannerNode.js.map +1 -1
- package/lib/commonjs/web-core/AudioBufferSourceNode.web.js +7 -1
- package/lib/commonjs/web-core/AudioBufferSourceNode.web.js.map +1 -1
- package/lib/commonjs/web-core/AudioContext.web.js +2 -4
- package/lib/commonjs/web-core/AudioContext.web.js.map +1 -1
- package/lib/commonjs/web-core/AudioParam.web.js.map +1 -1
- package/lib/commonjs/web-core/OfflineAudioContext.web.js +2 -4
- package/lib/commonjs/web-core/OfflineAudioContext.web.js.map +1 -1
- package/lib/commonjs/web-core/custom/index.js +7 -0
- package/lib/commonjs/web-core/custom/index.js.map +1 -1
- package/lib/commonjs/web-core/custom/wasm-audio-bufffer-source-node-stretcher/AudioBufferSourceNodeStretcher.js +58 -6
- package/lib/commonjs/web-core/custom/wasm-audio-bufffer-source-node-stretcher/AudioBufferSourceNodeStretcher.js.map +1 -1
- package/lib/commonjs/web-core/custom/wasm-audio-bufffer-source-node-stretcher/LoadCustomWasm.js +37 -0
- package/lib/commonjs/web-core/custom/wasm-audio-bufffer-source-node-stretcher/LoadCustomWasm.js.map +1 -0
- package/lib/{module/web-core/custom/wasm-audio-bufffer-source-node-stretcher/signalsmithStretch/SignalsmithStretch.js → commonjs/web-core/custom/wasm-audio-bufffer-source-node-stretcher/signalsmithStretch/SignalsmithStretch.mjs} +1 -1
- package/lib/commonjs/web-core/custom/wasm-audio-bufffer-source-node-stretcher/signalsmithStretch/SignalsmithStretch.mjs.map +1 -0
- package/lib/commonjs/web-core/utils/AudioBufferSourceNodeStandard.js +8 -2
- package/lib/commonjs/web-core/utils/AudioBufferSourceNodeStandard.js.map +1 -1
- package/lib/module/Audio/AudioFileSourceNode.js +3 -0
- package/lib/module/Audio/AudioFileSourceNode.js.map +1 -1
- package/lib/module/api.js +0 -1
- package/lib/module/api.js.map +1 -1
- package/lib/module/core/AudioBufferBaseSourceNode.js +2 -2
- package/lib/module/core/AudioBufferBaseSourceNode.js.map +1 -1
- package/lib/module/core/AudioNode.js +8 -2
- package/lib/module/core/AudioNode.js.map +1 -1
- package/lib/module/core/AudioParam.js +4 -1
- package/lib/module/core/AudioParam.js.map +1 -1
- package/lib/module/core/AudioRecorder.js +7 -16
- package/lib/module/core/AudioRecorder.js.map +1 -1
- package/lib/module/core/BaseAudioContext.js +0 -4
- package/lib/module/core/BaseAudioContext.js.map +1 -1
- package/lib/module/core/BiquadFilterNode.js +4 -4
- package/lib/module/core/BiquadFilterNode.js.map +1 -1
- package/lib/module/core/ConstantSourceNode.js +1 -1
- package/lib/module/core/ConstantSourceNode.js.map +1 -1
- package/lib/module/core/DelayNode.js +1 -1
- package/lib/module/core/DelayNode.js.map +1 -1
- package/lib/module/core/GainNode.js +1 -1
- package/lib/module/core/GainNode.js.map +1 -1
- package/lib/module/core/MediaElementAudioSourceNode.js +8 -0
- package/lib/module/core/MediaElementAudioSourceNode.js.map +1 -1
- package/lib/module/core/OscillatorNode.js +2 -2
- package/lib/module/core/OscillatorNode.js.map +1 -1
- package/lib/module/core/StereoPannerNode.js +1 -1
- package/lib/module/core/StereoPannerNode.js.map +1 -1
- package/lib/module/web-core/AudioBufferSourceNode.web.js +7 -1
- package/lib/module/web-core/AudioBufferSourceNode.web.js.map +1 -1
- package/lib/module/web-core/AudioContext.web.js +2 -4
- package/lib/module/web-core/AudioContext.web.js.map +1 -1
- package/lib/module/web-core/AudioParam.web.js.map +1 -1
- package/lib/module/web-core/OfflineAudioContext.web.js +2 -4
- package/lib/module/web-core/OfflineAudioContext.web.js.map +1 -1
- package/lib/module/web-core/custom/index.js +1 -0
- package/lib/module/web-core/custom/index.js.map +1 -1
- package/lib/module/web-core/custom/wasm-audio-bufffer-source-node-stretcher/AudioBufferSourceNodeStretcher.js +57 -6
- package/lib/module/web-core/custom/wasm-audio-bufffer-source-node-stretcher/AudioBufferSourceNodeStretcher.js.map +1 -1
- package/lib/module/web-core/custom/wasm-audio-bufffer-source-node-stretcher/LoadCustomWasm.js +33 -0
- package/lib/module/web-core/custom/wasm-audio-bufffer-source-node-stretcher/LoadCustomWasm.js.map +1 -0
- package/lib/{commonjs/web-core/custom/wasm-audio-bufffer-source-node-stretcher/signalsmithStretch/SignalsmithStretch.js → module/web-core/custom/wasm-audio-bufffer-source-node-stretcher/signalsmithStretch/SignalsmithStretch.mjs} +6 -10
- package/lib/module/web-core/custom/wasm-audio-bufffer-source-node-stretcher/signalsmithStretch/SignalsmithStretch.mjs.map +1 -0
- package/lib/module/web-core/utils/AudioBufferSourceNodeStandard.js +8 -2
- package/lib/module/web-core/utils/AudioBufferSourceNodeStandard.js.map +1 -1
- package/lib/typescript/Audio/AudioFileSourceNode.d.ts.map +1 -1
- package/lib/typescript/api.d.ts +0 -1
- package/lib/typescript/api.d.ts.map +1 -1
- package/lib/typescript/core/AudioNode.d.ts.map +1 -1
- package/lib/typescript/core/AudioParam.d.ts +3 -1
- package/lib/typescript/core/AudioParam.d.ts.map +1 -1
- package/lib/typescript/core/AudioRecorder.d.ts +4 -11
- package/lib/typescript/core/AudioRecorder.d.ts.map +1 -1
- package/lib/typescript/core/BaseAudioContext.d.ts +0 -2
- package/lib/typescript/core/BaseAudioContext.d.ts.map +1 -1
- package/lib/typescript/core/MediaElementAudioSourceNode.d.ts +2 -0
- package/lib/typescript/core/MediaElementAudioSourceNode.d.ts.map +1 -1
- package/lib/typescript/jsi-interfaces.d.ts +2 -2
- package/lib/typescript/jsi-interfaces.d.ts.map +1 -1
- package/lib/typescript/web-core/AudioBufferSourceNode.web.d.ts +2 -0
- package/lib/typescript/web-core/AudioBufferSourceNode.web.d.ts.map +1 -1
- package/lib/typescript/web-core/AudioContext.web.d.ts +3 -1
- package/lib/typescript/web-core/AudioContext.web.d.ts.map +1 -1
- package/lib/typescript/web-core/AudioParam.web.d.ts +1 -1
- package/lib/typescript/web-core/AudioParam.web.d.ts.map +1 -1
- package/lib/typescript/web-core/BaseAudioContext.web.d.ts +3 -1
- package/lib/typescript/web-core/BaseAudioContext.web.d.ts.map +1 -1
- package/lib/typescript/web-core/OfflineAudioContext.web.d.ts +3 -1
- package/lib/typescript/web-core/OfflineAudioContext.web.d.ts.map +1 -1
- package/lib/typescript/web-core/custom/index.d.ts +1 -0
- package/lib/typescript/web-core/custom/index.d.ts.map +1 -1
- package/lib/typescript/web-core/custom/wasm-audio-bufffer-source-node-stretcher/AudioBufferSourceNodeStretcher.d.ts +5 -1
- package/lib/typescript/web-core/custom/wasm-audio-bufffer-source-node-stretcher/AudioBufferSourceNodeStretcher.d.ts.map +1 -1
- package/lib/typescript/web-core/custom/wasm-audio-bufffer-source-node-stretcher/LoadCustomWasm.d.ts +5 -0
- package/lib/typescript/web-core/custom/wasm-audio-bufffer-source-node-stretcher/LoadCustomWasm.d.ts.map +1 -0
- package/lib/typescript/web-core/types.web.d.ts +3 -1
- package/lib/typescript/web-core/types.web.d.ts.map +1 -1
- package/lib/typescript/web-core/utils/AudioBufferSourceNodeStandard.d.ts +2 -0
- package/lib/typescript/web-core/utils/AudioBufferSourceNodeStandard.d.ts.map +1 -1
- package/package.json +1 -1
- package/scripts/setup-rn-audio-api-web.js +4 -4
- package/src/Audio/AudioFileSourceNode.ts +3 -0
- package/src/api.ts +0 -1
- package/src/core/AudioBufferBaseSourceNode.ts +2 -2
- package/src/core/AudioNode.ts +12 -2
- package/src/core/AudioParam.ts +5 -1
- package/src/core/AudioRecorder.ts +9 -20
- package/src/core/BaseAudioContext.ts +0 -5
- package/src/core/BiquadFilterNode.ts +4 -4
- package/src/core/ConstantSourceNode.ts +1 -1
- package/src/core/DelayNode.ts +1 -1
- package/src/core/GainNode.ts +1 -1
- package/src/core/MediaElementAudioSourceNode.ts +13 -0
- package/src/core/OscillatorNode.ts +2 -2
- package/src/core/StereoPannerNode.ts +1 -1
- package/src/jsi-interfaces.ts +2 -2
- package/src/web-core/AudioBufferSourceNode.web.ts +9 -1
- package/src/web-core/AudioContext.web.ts +4 -2
- package/src/web-core/AudioParam.web.ts +1 -2
- package/src/web-core/BaseAudioContext.web.ts +3 -1
- package/src/web-core/OfflineAudioContext.web.ts +4 -2
- package/src/web-core/custom/index.ts +1 -0
- package/src/web-core/custom/wasm-audio-bufffer-source-node-stretcher/AudioBufferSourceNodeStretcher.ts +72 -12
- package/src/web-core/custom/wasm-audio-bufffer-source-node-stretcher/LoadCustomWasm.ts +39 -0
- package/src/web-core/types.web.ts +4 -1
- package/src/web-core/utils/AudioBufferSourceNodeStandard.ts +12 -2
- package/common/cpp/audioapi/core/destinations/AudioDestinationNode.cpp +0 -49
- package/common/cpp/audioapi/core/utils/AudioDestructor.hpp +0 -76
- package/common/cpp/audioapi/core/utils/AudioGraphManager.cpp +0 -248
- package/common/cpp/audioapi/core/utils/AudioGraphManager.h +0 -207
- package/common/cpp/audioapi/core/utils/graph/AudioGraph.hpp +0 -360
- package/common/cpp/audioapi/core/utils/graph/Graph.hpp +0 -227
- package/common/cpp/audioapi/core/utils/graph/HostGraph.hpp +0 -331
- package/common/cpp/audioapi/utils/MoveOnlyFunction.hpp +0 -93
- package/lib/commonjs/core/RecorderAdapterNode.js +0 -22
- package/lib/commonjs/core/RecorderAdapterNode.js.map +0 -1
- package/lib/commonjs/web-core/custom/wasm-audio-bufffer-source-node-stretcher/signalsmithStretch/SignalsmithStretch.d.js +0 -6
- package/lib/commonjs/web-core/custom/wasm-audio-bufffer-source-node-stretcher/signalsmithStretch/SignalsmithStretch.d.js.map +0 -1
- package/lib/commonjs/web-core/custom/wasm-audio-bufffer-source-node-stretcher/signalsmithStretch/SignalsmithStretch.js.map +0 -1
- package/lib/module/core/RecorderAdapterNode.js +0 -16
- package/lib/module/core/RecorderAdapterNode.js.map +0 -1
- package/lib/module/web-core/custom/wasm-audio-bufffer-source-node-stretcher/signalsmithStretch/SignalsmithStretch.d.js +0 -4
- package/lib/module/web-core/custom/wasm-audio-bufffer-source-node-stretcher/signalsmithStretch/SignalsmithStretch.d.js.map +0 -1
- package/lib/module/web-core/custom/wasm-audio-bufffer-source-node-stretcher/signalsmithStretch/SignalsmithStretch.js.map +0 -1
- package/lib/typescript/core/RecorderAdapterNode.d.ts +0 -11
- package/lib/typescript/core/RecorderAdapterNode.d.ts.map +0 -1
- package/src/core/RecorderAdapterNode.ts +0 -17
- package/src/web-core/custom/wasm-audio-bufffer-source-node-stretcher/signalsmithStretch/SignalsmithStretch.d.ts +0 -4
- /package/src/web-core/custom/wasm-audio-bufffer-source-node-stretcher/signalsmithStretch/{SignalsmithStretch.js → SignalsmithStretch.mjs} +0 -0
package/RNAudioAPI.podspec
CHANGED
|
@@ -32,7 +32,7 @@ Pod::Spec.new do |s|
|
|
|
32
32
|
s.source = { :git => "https://github.com/software-mansion/react-native-audio-api.git", :tag => "#{s.version}" }
|
|
33
33
|
|
|
34
34
|
s.subspec "audioapi" do |ss|
|
|
35
|
-
ss.source_files = "common/cpp/audioapi/**/*.{cpp,c,h,hpp}"
|
|
35
|
+
ss.source_files = "common/cpp/audioapi/**/*.{cpp,c,h,hpp}", "common/cpp/test/src/graph/AudioThreadGuard.cpp"
|
|
36
36
|
ss.exclude_files = $RN_AUDIO_API_FFMPEG_DISABLED ? ["common/cpp/audioapi/libs/ffmpeg/**"] : []
|
|
37
37
|
ss.header_dir = "audioapi"
|
|
38
38
|
ss.header_mappings_dir = "common/cpp/audioapi"
|
|
@@ -107,6 +107,7 @@ Pod::Spec.new do |s|
|
|
|
107
107
|
.join(' '),
|
|
108
108
|
"CLANG_CXX_LANGUAGE_STANDARD" => "c++20",
|
|
109
109
|
"GCC_PREPROCESSOR_DEFINITIONS" => '$(inherited) HAVE_ACCELERATE=1',
|
|
110
|
+
"GCC_PREPROCESSOR_DEFINITIONS[config=Debug]" => '$(inherited) HAVE_ACCELERATE=1 DEBUG=1',
|
|
110
111
|
'OTHER_CFLAGS' => "$(inherited) #{fabric_flags} #{version_flag} #{worklets_preprocessor_flag} #{ffmpeg_flag} #{static_external_libs_flag}",
|
|
111
112
|
}
|
|
112
113
|
|
|
@@ -44,6 +44,11 @@ set(JNI_LIBS_DIR ${CMAKE_SOURCE_DIR}/src/main/jniLibs)
|
|
|
44
44
|
|
|
45
45
|
add_library(react-native-audio-api SHARED ${ANDROID_CPP_SOURCES} ${COMMON_CPP_SOURCES})
|
|
46
46
|
|
|
47
|
+
# Debug-only allocation auditor used by BaseAudioContext::processGraph (mirrors iOS podspec).
|
|
48
|
+
target_sources(react-native-audio-api PRIVATE
|
|
49
|
+
$<$<CONFIG:Debug>:${COMMON_CPP_DIR}/test/src/graph/AudioThreadGuard.cpp>
|
|
50
|
+
)
|
|
51
|
+
|
|
47
52
|
if (NOT RN_AUDIO_API_STATIC_EXTERNAL_LIBS_DISABLED)
|
|
48
53
|
foreach(lib IN ITEMS opus opusfile ogg vorbis vorbisenc vorbisfile crypto ssl)
|
|
49
54
|
add_library(${lib} STATIC IMPORTED)
|
|
@@ -165,6 +170,11 @@ if (RN_AUDIO_API_FFMPEG_DISABLED)
|
|
|
165
170
|
)
|
|
166
171
|
endif()
|
|
167
172
|
|
|
173
|
+
target_compile_definitions(
|
|
174
|
+
react-native-audio-api
|
|
175
|
+
PRIVATE $<$<CONFIG:Debug>:DEBUG>
|
|
176
|
+
)
|
|
177
|
+
|
|
168
178
|
if (RN_AUDIO_API_STATIC_EXTERNAL_LIBS_DISABLED)
|
|
169
179
|
target_compile_definitions(
|
|
170
180
|
react-native-audio-api
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#include <audioapi/android/AudioAPIModule.h>
|
|
2
2
|
#include <audioapi/android/JniEventPayloadParser.h>
|
|
3
|
+
#include <audioapi/android/system/NativeFileInfo.hpp>
|
|
3
4
|
#include <memory>
|
|
4
5
|
|
|
5
6
|
namespace audioapi {
|
|
@@ -53,6 +54,9 @@ void AudioAPIModule::registerNatives() {
|
|
|
53
54
|
}
|
|
54
55
|
|
|
55
56
|
void AudioAPIModule::injectJSIBindings() {
|
|
57
|
+
// cache app directory paths on the attached thread
|
|
58
|
+
NativeFileInfo::warmCache();
|
|
59
|
+
|
|
56
60
|
#if RN_AUDIO_API_ENABLE_WORKLETS
|
|
57
61
|
auto uiWorkletRuntime = weakWorkletsModuleProxy_.lock()->getUIWorkletRuntime();
|
|
58
62
|
#else
|
|
@@ -47,8 +47,8 @@ AndroidAudioRecorder::~AndroidAudioRecorder() {
|
|
|
47
47
|
if (dataCallback_ != nullptr) {
|
|
48
48
|
dataCallback_->cleanup();
|
|
49
49
|
}
|
|
50
|
-
if (
|
|
51
|
-
|
|
50
|
+
if (adapterNodeHandle_ != nullptr) {
|
|
51
|
+
static_cast<RecorderAdapterNode *>(adapterNodeHandle_->audioNode.get())->adapterCleanup();
|
|
52
52
|
}
|
|
53
53
|
// oboe could be handling stopping and closing the stream, sanity check just in case
|
|
54
54
|
if (mStream_ != nullptr) {
|
|
@@ -73,7 +73,7 @@ Result<NoneType, std::string> AndroidAudioRecorder::openAudioStream() {
|
|
|
73
73
|
->setDirection(oboe::Direction::Input)
|
|
74
74
|
->setFormat(oboe::AudioFormat::Float)
|
|
75
75
|
->setFormatConversionAllowed(true)
|
|
76
|
-
->setPerformanceMode(oboe::PerformanceMode::
|
|
76
|
+
->setPerformanceMode(oboe::PerformanceMode::None)
|
|
77
77
|
->setSampleRateConversionQuality(oboe::SampleRateConversionQuality::Medium)
|
|
78
78
|
->setDataCallback(shared_from_this())
|
|
79
79
|
->setErrorCallback(shared_from_this());
|
|
@@ -95,8 +95,7 @@ Result<NoneType, std::string> AndroidAudioRecorder::openAudioStream() {
|
|
|
95
95
|
/// @brief prepares and starts the audio recording process.
|
|
96
96
|
/// If audio stream is opened correctly, it will set up any output configured
|
|
97
97
|
/// (file writing, callback, adapter node) and start the stream.
|
|
98
|
-
///
|
|
99
|
-
/// all shared state is guarded by the recorder locks and atomics.
|
|
98
|
+
/// This method should be called from the JS thread only.
|
|
100
99
|
/// NOTE: I've noticed some possibly invalid file paths being returned on Android,
|
|
101
100
|
/// RN side requires their "file://" prefix, but sometimes it returned raw path.
|
|
102
101
|
/// Most likely this was due to alpha version mistakes, but in case of problems leaving this here. (ㆆ _ ㆆ)
|
|
@@ -133,25 +132,20 @@ Result<NoneType, std::string> AndroidAudioRecorder::start(const std::string &fil
|
|
|
133
132
|
|
|
134
133
|
if (wantsCallback()) {
|
|
135
134
|
if (dataCallback_ == nullptr) {
|
|
136
|
-
|
|
137
|
-
audioEventHandlerRegistry_,
|
|
138
|
-
dataCallbackMetadata_.sampleRate,
|
|
139
|
-
dataCallbackMetadata_.bufferLength,
|
|
140
|
-
dataCallbackMetadata_.channelCount,
|
|
141
|
-
dataCallbackMetadata_.callbackId);
|
|
142
|
-
|
|
143
|
-
dataCallback_->setOnErrorCallback(errorCallbackId_.load(std::memory_order_acquire));
|
|
135
|
+
return Result<NoneType, std::string>::Err("Callback output is unavailable.");
|
|
144
136
|
}
|
|
145
137
|
|
|
138
|
+
dataCallback_->setOnErrorCallback(errorCallbackId_.load(std::memory_order_acquire));
|
|
146
139
|
std::static_pointer_cast<AndroidRecorderCallback>(dataCallback_)
|
|
147
140
|
->prepare(streamSampleRate_, streamChannelCount_, streamMaxBufferSizeInFrames_);
|
|
148
141
|
callbackOutputConfigured_.store(true, std::memory_order_release);
|
|
149
142
|
}
|
|
150
143
|
|
|
151
|
-
if (wantsConnection() &&
|
|
144
|
+
if (wantsConnection() && adapterNodeHandle_ != nullptr) {
|
|
152
145
|
deinterleavingBuffer_ = std::make_shared<AudioBuffer>(
|
|
153
146
|
streamMaxBufferSizeInFrames_, streamChannelCount_, streamSampleRate_);
|
|
154
|
-
|
|
147
|
+
static_cast<RecorderAdapterNode *>(adapterNodeHandle_->audioNode.get())
|
|
148
|
+
->init(streamMaxBufferSizeInFrames_, streamChannelCount_, streamSampleRate_);
|
|
155
149
|
connectedConfigured_.store(true, std::memory_order_release);
|
|
156
150
|
}
|
|
157
151
|
|
|
@@ -167,41 +161,41 @@ Result<NoneType, std::string> AndroidAudioRecorder::start(const std::string &fil
|
|
|
167
161
|
}
|
|
168
162
|
|
|
169
163
|
/// @brief Stops the audio stream and finalizes any output (file writing, callback, adapter node).
|
|
170
|
-
///
|
|
171
|
-
/// all shared state is guarded by the recorder locks and atomics.
|
|
164
|
+
/// This method should be called from the JS thread only.
|
|
172
165
|
/// @returns On success, returns the file URI, size in MB and duration in seconds of the recorded file (if file output is enabled).
|
|
173
166
|
/// NOTE: due to the file access nature on Android, the size might sometimes be zeroed (really long files).
|
|
174
|
-
|
|
167
|
+
Result<std::tuple<std::vector<std::string>, double, double>, std::string>
|
|
168
|
+
AndroidAudioRecorder::stop() {
|
|
175
169
|
std::shared_ptr<AudioFileWriter> fileWriter;
|
|
176
170
|
std::shared_ptr<AudioRecorderCallback> dataCallback;
|
|
177
|
-
std::shared_ptr<
|
|
171
|
+
std::shared_ptr<utils::graph::NodeHandle> adapterNodeHandle;
|
|
178
172
|
std::vector<std::string> outputPaths;
|
|
179
173
|
|
|
174
|
+
double outputFileSize = 0.0;
|
|
175
|
+
double outputDuration = 0.0;
|
|
176
|
+
bool hadFileOutput = false;
|
|
177
|
+
|
|
180
178
|
{
|
|
181
179
|
std::scoped_lock stopLock(callbackMutex_, fileWriterMutex_, adapterNodeMutex_);
|
|
182
180
|
|
|
183
181
|
if (isIdle()) {
|
|
184
|
-
return
|
|
182
|
+
return Result<std::tuple<std::vector<std::string>, double, double>, std::string>::Err(
|
|
183
|
+
"Recorder is not in recording state.");
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (mStream_ == nullptr) {
|
|
187
|
+
return Result<std::tuple<std::vector<std::string>, double, double>, std::string>::Err(
|
|
188
|
+
"Audio stream is not initialized.");
|
|
185
189
|
}
|
|
186
190
|
|
|
187
191
|
state_.store(RecorderState::Idle, std::memory_order_release);
|
|
192
|
+
mStream_->requestStop();
|
|
188
193
|
|
|
189
|
-
|
|
190
|
-
// stream keeps the data/error callbacks registered, so a later device
|
|
191
|
-
// disconnect fires onErrorAfterClose and resurrects the stream (the mic
|
|
192
|
-
// stays hot after stop()), and the stream's shared_ptr to this recorder
|
|
193
|
-
// keeps the recorder alive forever once JS drops it (reference cycle).
|
|
194
|
-
// start() reopens the stream when mStream_ is null.
|
|
195
|
-
if (mStream_ != nullptr) {
|
|
196
|
-
mStream_->requestStop();
|
|
197
|
-
mStream_->close();
|
|
198
|
-
mStream_.reset();
|
|
199
|
-
}
|
|
194
|
+
hadFileOutput = usesFileOutput();
|
|
200
195
|
|
|
201
|
-
if (
|
|
196
|
+
if (hadFileOutput) {
|
|
202
197
|
fileOutputConfigured_.store(false, std::memory_order_release);
|
|
203
198
|
fileWriter = std::move(fileWriter_);
|
|
204
|
-
outputPaths = buildOutputPaths(recordingSegmentPaths_, filePath_);
|
|
205
199
|
}
|
|
206
200
|
|
|
207
201
|
if (usesCallback()) {
|
|
@@ -211,16 +205,44 @@ AudioRecorder::StopResult AndroidAudioRecorder::stop() {
|
|
|
211
205
|
|
|
212
206
|
if (isConnected()) {
|
|
213
207
|
connectedConfigured_.store(false, std::memory_order_release);
|
|
214
|
-
|
|
215
|
-
deinterleavingBuffer_ = nullptr;
|
|
216
|
-
adapterNode = std::move(adapterNode_);
|
|
208
|
+
adapterNodeHandle = std::move(adapterNodeHandle_);
|
|
217
209
|
}
|
|
210
|
+
}
|
|
218
211
|
|
|
219
|
-
|
|
220
|
-
|
|
212
|
+
for (const auto &raw : recordingSegmentPaths_) {
|
|
213
|
+
if (!raw.empty()) {
|
|
214
|
+
outputPaths.push_back(std::format("file://{}", raw));
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
if (hadFileOutput && outputPaths.empty() && !filePath_.empty()) {
|
|
218
|
+
outputPaths.push_back(std::format("file://{}", filePath_));
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
recordingSegmentPaths_.clear();
|
|
222
|
+
filePath_ = "";
|
|
223
|
+
|
|
224
|
+
if (fileWriter != nullptr) {
|
|
225
|
+
auto fileResult = fileWriter->closeFile();
|
|
226
|
+
|
|
227
|
+
if (!fileResult.is_ok()) {
|
|
228
|
+
return Result<std::tuple<std::vector<std::string>, double, double>, std::string>::Err(
|
|
229
|
+
"Failed to close file: " + fileResult.unwrap_err());
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
outputFileSize = std::get<0>(fileResult.unwrap());
|
|
233
|
+
outputDuration = std::get<1>(fileResult.unwrap());
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
if (dataCallback != nullptr) {
|
|
237
|
+
dataCallback->cleanup();
|
|
221
238
|
}
|
|
222
239
|
|
|
223
|
-
|
|
240
|
+
if (adapterNodeHandle != nullptr) {
|
|
241
|
+
static_cast<RecorderAdapterNode *>(adapterNodeHandle->audioNode.get())->adapterCleanup();
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return Result<std::tuple<std::vector<std::string>, double, double>, std::string>::Ok(
|
|
245
|
+
std::make_tuple(std::move(outputPaths), outputFileSize, outputDuration));
|
|
224
246
|
}
|
|
225
247
|
|
|
226
248
|
/// @brief Enables file output for the recorder with the specified properties.
|
|
@@ -295,7 +317,7 @@ Result<NoneType, std::string> AndroidAudioRecorder::setupFileWriter(
|
|
|
295
317
|
fileWriter_ = createFileWriter(properties);
|
|
296
318
|
}
|
|
297
319
|
|
|
298
|
-
fileWriter_->
|
|
320
|
+
fileWriter_->setOnErrorCallback(errorCallbackId_.load(std::memory_order_acquire));
|
|
299
321
|
|
|
300
322
|
auto backend = std::static_pointer_cast<AndroidFileWriterBackend>(fileWriter_);
|
|
301
323
|
auto fileResult = backend->openFile(
|
|
@@ -316,12 +338,27 @@ Result<NoneType, std::string> AndroidAudioRecorder::setupFileWriter(
|
|
|
316
338
|
return Result<NoneType, std::string>::Ok(None);
|
|
317
339
|
}
|
|
318
340
|
|
|
341
|
+
/// @brief Disables file output for the recorder.
|
|
342
|
+
/// If the recorder is currently active, it will finalize and close the file immediately.
|
|
343
|
+
/// This method should be called from the JS thread only.
|
|
344
|
+
void AndroidAudioRecorder::disableFileOutput() {
|
|
345
|
+
std::shared_ptr<AudioFileWriter> fileWriter;
|
|
346
|
+
{
|
|
347
|
+
std::scoped_lock fileWriterLock(fileWriterMutex_);
|
|
348
|
+
fileOutputConfigured_.store(false, std::memory_order_release);
|
|
349
|
+
fileOutputEnabled_.store(false, std::memory_order_release);
|
|
350
|
+
fileWriter = std::move(fileWriter_);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
if (fileWriter != nullptr) {
|
|
354
|
+
fileWriter->closeFile();
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
319
358
|
/// @brief Pauses the audio recording stream.
|
|
320
359
|
/// For session without active file output, this method acts same as stop().
|
|
321
360
|
/// This method should be called from the JS thread only.
|
|
322
361
|
void AndroidAudioRecorder::pause() {
|
|
323
|
-
std::scoped_lock pauseLock(callbackMutex_, fileWriterMutex_, adapterNodeMutex_);
|
|
324
|
-
|
|
325
362
|
if (!isRecording()) {
|
|
326
363
|
return;
|
|
327
364
|
}
|
|
@@ -333,9 +370,7 @@ void AndroidAudioRecorder::pause() {
|
|
|
333
370
|
/// @brief Resumes the audio recording stream if it was previously paused.
|
|
334
371
|
/// This method should be called from the JS thread only.
|
|
335
372
|
void AndroidAudioRecorder::resume() {
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
if (!isPaused() || mStream_ == nullptr) {
|
|
373
|
+
if (!isPaused()) {
|
|
339
374
|
return;
|
|
340
375
|
}
|
|
341
376
|
|
|
@@ -357,16 +392,9 @@ Result<NoneType, std::string> AndroidAudioRecorder::setOnAudioReadyCallback(
|
|
|
357
392
|
int channelCount,
|
|
358
393
|
uint64_t callbackId) {
|
|
359
394
|
std::scoped_lock callbackLock(callbackMutex_, errorCallbackMutex_);
|
|
360
|
-
|
|
361
|
-
dataCallbackMetadata_ = {
|
|
362
|
-
.sampleRate = sampleRate,
|
|
363
|
-
.bufferLength = bufferLength,
|
|
364
|
-
.channelCount = channelCount,
|
|
365
|
-
.callbackId = callbackId};
|
|
366
|
-
|
|
367
395
|
dataCallback_ = std::make_shared<AndroidRecorderCallback>(
|
|
368
396
|
audioEventHandlerRegistry_, sampleRate, bufferLength, channelCount, callbackId);
|
|
369
|
-
dataCallback_->setOnErrorCallback(
|
|
397
|
+
dataCallback_->setOnErrorCallback(errorCallbackId_.load(std::memory_order_acquire));
|
|
370
398
|
callbackOutputEnabled_.store(true, std::memory_order_release);
|
|
371
399
|
callbackOutputConfigured_.store(false, std::memory_order_release);
|
|
372
400
|
|
|
@@ -379,29 +407,53 @@ Result<NoneType, std::string> AndroidAudioRecorder::setOnAudioReadyCallback(
|
|
|
379
407
|
return Result<NoneType, std::string>::Ok(None);
|
|
380
408
|
}
|
|
381
409
|
|
|
410
|
+
/// @brief Clears the audio data callback.
|
|
411
|
+
/// If the recorder is currently active, it will stop invoking the callback immediately.
|
|
412
|
+
/// This method should be called from the JS thread only.
|
|
413
|
+
void AndroidAudioRecorder::clearOnAudioReadyCallback() {
|
|
414
|
+
std::scoped_lock callbackLock(callbackMutex_);
|
|
415
|
+
callbackOutputConfigured_.store(false, std::memory_order_release);
|
|
416
|
+
callbackOutputEnabled_.store(false, std::memory_order_release);
|
|
417
|
+
dataCallback_ = nullptr;
|
|
418
|
+
}
|
|
419
|
+
|
|
382
420
|
/// @brief Connects a RecorderAdapterNode to the recorder for audio data routing.
|
|
383
421
|
/// If the recorder is already active, it will initialize the adapter node immediately.
|
|
384
422
|
/// This method should be called from the JS thread only.
|
|
385
423
|
/// @param node Shared pointer to the RecorderAdapterNode to connect.
|
|
386
|
-
void AndroidAudioRecorder::connect(const std::shared_ptr<
|
|
424
|
+
void AndroidAudioRecorder::connect(const std::shared_ptr<utils::graph::NodeHandle> &node) {
|
|
387
425
|
std::scoped_lock adapterLock(adapterNodeMutex_);
|
|
388
|
-
|
|
426
|
+
adapterNodeHandle_ = node;
|
|
389
427
|
isConnected_.store(true, std::memory_order_release);
|
|
390
428
|
connectedConfigured_.store(false, std::memory_order_release);
|
|
391
429
|
|
|
392
430
|
if (!isIdle()) {
|
|
393
431
|
deinterleavingBuffer_ = std::make_shared<AudioBuffer>(
|
|
394
432
|
streamMaxBufferSizeInFrames_, streamChannelCount_, streamSampleRate_);
|
|
395
|
-
|
|
433
|
+
static_cast<RecorderAdapterNode *>(adapterNodeHandle_->audioNode.get())
|
|
434
|
+
->init(streamMaxBufferSizeInFrames_, streamChannelCount_, streamSampleRate_);
|
|
396
435
|
connectedConfigured_.store(true, std::memory_order_release);
|
|
397
436
|
}
|
|
398
437
|
}
|
|
399
438
|
|
|
400
|
-
/// @brief
|
|
401
|
-
///
|
|
402
|
-
///
|
|
403
|
-
void AndroidAudioRecorder::
|
|
404
|
-
|
|
439
|
+
/// @brief Disconnects the currently connected RecorderAdapterNode from the recorder.
|
|
440
|
+
/// If the recorder is currently active, it will stop routing audio data immediately.
|
|
441
|
+
/// This method should be called from the JS thread only.
|
|
442
|
+
void AndroidAudioRecorder::disconnect() {
|
|
443
|
+
std::shared_ptr<utils::graph::NodeHandle> adapterNodeHandle;
|
|
444
|
+
bool hadConnection = false;
|
|
445
|
+
{
|
|
446
|
+
std::scoped_lock adapterLock(adapterNodeMutex_);
|
|
447
|
+
hadConnection = isConnected();
|
|
448
|
+
connectedConfigured_.store(false, std::memory_order_release);
|
|
449
|
+
isConnected_.store(false, std::memory_order_release);
|
|
450
|
+
deinterleavingBuffer_ = nullptr;
|
|
451
|
+
adapterNodeHandle = std::move(adapterNodeHandle_);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
if (hadConnection && adapterNodeHandle != nullptr) {
|
|
455
|
+
static_cast<RecorderAdapterNode *>(adapterNodeHandle->audioNode.get())->adapterCleanup();
|
|
456
|
+
}
|
|
405
457
|
}
|
|
406
458
|
|
|
407
459
|
/// @brief onAudioReady callback that is invoked by the Oboe stream when new audio data is available.
|
|
@@ -441,12 +493,14 @@ oboe::DataCallbackResult AndroidAudioRecorder::onAudioReady(
|
|
|
441
493
|
|
|
442
494
|
if (isConnected()) {
|
|
443
495
|
if (auto adapterLock = Locker::tryLock(adapterNodeMutex_)) {
|
|
444
|
-
auto
|
|
496
|
+
auto adapterNodeHandle = adapterNodeHandle_;
|
|
445
497
|
auto deinterleavingBuffer = deinterleavingBuffer_;
|
|
446
|
-
if (!isConnected() ||
|
|
498
|
+
if (!isConnected() || adapterNodeHandle == nullptr || deinterleavingBuffer == nullptr) {
|
|
447
499
|
return oboe::DataCallbackResult::Continue;
|
|
448
500
|
}
|
|
449
501
|
|
|
502
|
+
auto *adapterNode = static_cast<RecorderAdapterNode *>(adapterNodeHandle->audioNode.get());
|
|
503
|
+
|
|
450
504
|
auto const data = static_cast<float *>(audioData);
|
|
451
505
|
deinterleavingBuffer->deinterleaveFrom(data, numFrames);
|
|
452
506
|
|
|
@@ -461,13 +515,17 @@ oboe::DataCallbackResult AndroidAudioRecorder::onAudioReady(
|
|
|
461
515
|
|
|
462
516
|
bool AndroidAudioRecorder::isRecording() const {
|
|
463
517
|
return state_.load(std::memory_order_acquire) == RecorderState::Recording &&
|
|
464
|
-
mStream_
|
|
518
|
+
mStream_->getState() == oboe::StreamState::Started;
|
|
465
519
|
}
|
|
466
520
|
|
|
467
521
|
bool AndroidAudioRecorder::isPaused() const {
|
|
468
522
|
return state_.load(std::memory_order_acquire) == RecorderState::Paused;
|
|
469
523
|
}
|
|
470
524
|
|
|
525
|
+
bool AndroidAudioRecorder::isIdle() const {
|
|
526
|
+
return state_.load(std::memory_order_acquire) == RecorderState::Idle;
|
|
527
|
+
}
|
|
528
|
+
|
|
471
529
|
void AndroidAudioRecorder::cleanup() {
|
|
472
530
|
state_.store(RecorderState::Idle, std::memory_order_release);
|
|
473
531
|
|
|
@@ -483,43 +541,29 @@ void AndroidAudioRecorder::cleanup() {
|
|
|
483
541
|
/// @param oboeStream Pointer to the Oboe audio stream.
|
|
484
542
|
/// @param error The oboe::Result error code.
|
|
485
543
|
void AndroidAudioRecorder::onErrorAfterClose(oboe::AudioStream *stream, oboe::Result error) {
|
|
486
|
-
if (error
|
|
487
|
-
|
|
488
|
-
errorEvent().dispatch(StringPayload{.name = "message", .reason = std::move(message)});
|
|
489
|
-
return;
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
// Only restart if the recorder is still supposed to be running. Restarting
|
|
493
|
-
// unconditionally resurrected stopped recorders, so any audio route change
|
|
494
|
-
// (e.g. a Bluetooth headset connecting or disconnecting) turned the mic
|
|
495
|
-
// back on after stop().
|
|
496
|
-
if (isIdle() || isPaused()) {
|
|
497
|
-
return;
|
|
498
|
-
}
|
|
544
|
+
if (error == oboe::Result::ErrorDisconnected) {
|
|
545
|
+
cleanup();
|
|
499
546
|
|
|
500
|
-
|
|
501
|
-
// the JS thread while this runs on oboe's (detached) error thread.
|
|
502
|
-
std::scoped_lock restartLock(callbackMutex_, fileWriterMutex_, adapterNodeMutex_);
|
|
547
|
+
auto streamResult = openAudioStream();
|
|
503
548
|
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
// healthy new stream.
|
|
507
|
-
if (stream != mStream_.get()) {
|
|
508
|
-
return;
|
|
509
|
-
}
|
|
549
|
+
if (!streamResult.is_ok()) {
|
|
550
|
+
uint64_t callbackId = errorCallbackId_.load(std::memory_order_acquire);
|
|
510
551
|
|
|
511
|
-
|
|
552
|
+
if (audioEventHandlerRegistry_ == nullptr || callbackId == 0) {
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
512
555
|
|
|
513
|
-
|
|
556
|
+
std::string message = "Android recorder error: " + streamResult.unwrap_err();
|
|
557
|
+
audioEventHandlerRegistry_->dispatchEvent(
|
|
558
|
+
AudioEvent::RECORDER_ERROR,
|
|
559
|
+
callbackId,
|
|
560
|
+
StringPayload{.name = "message", .reason = std::move(message)});
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
514
563
|
|
|
515
|
-
|
|
516
|
-
std::
|
|
517
|
-
errorEvent().dispatch(StringPayload{.name = "message", .reason = std::move(message)});
|
|
518
|
-
return;
|
|
564
|
+
mStream_->requestStart();
|
|
565
|
+
state_.store(RecorderState::Recording, std::memory_order_release);
|
|
519
566
|
}
|
|
520
|
-
|
|
521
|
-
mStream_->requestStart();
|
|
522
|
-
state_.store(RecorderState::Recording, std::memory_order_release);
|
|
523
567
|
}
|
|
524
568
|
|
|
525
569
|
} // namespace audioapi
|
|
@@ -27,31 +27,32 @@ class AndroidAudioRecorder : public oboe::AudioStreamCallback,
|
|
|
27
27
|
void cleanup();
|
|
28
28
|
|
|
29
29
|
Result<NoneType, std::string> start(const std::string &fileNameOverride) override;
|
|
30
|
-
|
|
30
|
+
Result<std::tuple<std::vector<std::string>, double, double>, std::string> stop() override;
|
|
31
31
|
|
|
32
32
|
Result<NoneType, std::string> enableFileOutput(
|
|
33
33
|
std::shared_ptr<AudioFileProperties> properties) override;
|
|
34
|
+
void disableFileOutput() override;
|
|
34
35
|
|
|
35
36
|
void pause() override;
|
|
36
37
|
void resume() override;
|
|
37
38
|
bool isRecording() const override;
|
|
38
39
|
bool isPaused() const override;
|
|
40
|
+
bool isIdle() const override;
|
|
39
41
|
|
|
40
42
|
Result<NoneType, std::string> setOnAudioReadyCallback(
|
|
41
43
|
float sampleRate,
|
|
42
44
|
size_t bufferLength,
|
|
43
45
|
int channelCount,
|
|
44
46
|
uint64_t callbackId) override;
|
|
47
|
+
void clearOnAudioReadyCallback() override;
|
|
45
48
|
|
|
46
|
-
void connect(const std::shared_ptr<
|
|
49
|
+
void connect(const std::shared_ptr<utils::graph::NodeHandle> &node) override;
|
|
50
|
+
void disconnect() override;
|
|
47
51
|
|
|
48
52
|
oboe::DataCallbackResult
|
|
49
53
|
onAudioReady(oboe::AudioStream *oboeStream, void *audioData, int32_t numFrames) override;
|
|
50
54
|
void onErrorAfterClose(oboe::AudioStream *oboeStream, oboe::Result error) override;
|
|
51
55
|
|
|
52
|
-
protected:
|
|
53
|
-
void clearAdapterScratchState() override;
|
|
54
|
-
|
|
55
56
|
private:
|
|
56
57
|
std::shared_ptr<AudioBuffer> deinterleavingBuffer_;
|
|
57
58
|
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
namespace audioapi {
|
|
15
15
|
|
|
16
16
|
AudioPlayer::AudioPlayer(
|
|
17
|
-
const std::function<void(
|
|
17
|
+
const std::function<void(DSPAudioBuffer *, int)> &renderAudio,
|
|
18
18
|
float sampleRate,
|
|
19
19
|
int channelCount,
|
|
20
20
|
std::mutex *driverMutex,
|
|
@@ -121,7 +121,7 @@ AudioPlayer::onAudioReady(AudioStream *oboeStream, void *audioData, int32_t numF
|
|
|
121
121
|
auto framesToProcess = std::min(numFrames - processedFrames, RENDER_QUANTUM_SIZE);
|
|
122
122
|
|
|
123
123
|
if (isRunning_.load(std::memory_order_acquire)) {
|
|
124
|
-
renderAudio_(buffer_, framesToProcess);
|
|
124
|
+
renderAudio_(buffer_.get(), framesToProcess);
|
|
125
125
|
} else {
|
|
126
126
|
buffer_->zero();
|
|
127
127
|
}
|
|
@@ -21,7 +21,7 @@ class AudioPlayer : public AudioStreamDataCallback,
|
|
|
21
21
|
public:
|
|
22
22
|
friend class AudioContext;
|
|
23
23
|
AudioPlayer(
|
|
24
|
-
const std::function<void(
|
|
24
|
+
const std::function<void(DSPAudioBuffer *, int)> &renderAudio,
|
|
25
25
|
float sampleRate,
|
|
26
26
|
int channelCount,
|
|
27
27
|
std::mutex *driverMutex,
|
|
@@ -47,7 +47,7 @@ class AudioPlayer : public AudioStreamDataCallback,
|
|
|
47
47
|
void onErrorAfterClose(AudioStream *audioStream, Result error) override;
|
|
48
48
|
|
|
49
49
|
private:
|
|
50
|
-
std::function<void(
|
|
50
|
+
std::function<void(DSPAudioBuffer *, int)> renderAudio_;
|
|
51
51
|
std::atomic<uint32_t> ¤tRenders_;
|
|
52
52
|
std::shared_ptr<AudioStream> mStream_;
|
|
53
53
|
std::shared_ptr<DSPAudioBuffer> buffer_;
|
|
@@ -28,7 +28,9 @@ OpenFileResult AndroidRotatingFileWriter::openFile(
|
|
|
28
28
|
streamSampleRate_ = streamSampleRate;
|
|
29
29
|
streamChannelCount_ = streamChannelCount;
|
|
30
30
|
streamMaxBufferSize_ = streamMaxBufferSizeInFrames;
|
|
31
|
-
|
|
31
|
+
if (!fileNameOverride.empty()) {
|
|
32
|
+
fileProperties_->fileNamePrefix = fileNameOverride + fileProperties_->fileNamePrefix;
|
|
33
|
+
}
|
|
32
34
|
if (currentWriter_ == nullptr) {
|
|
33
35
|
currentWriter_ = writerFactory_(fileProperties_);
|
|
34
36
|
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#include <audioapi/android/system/NativeFileInfo.hpp>
|
|
2
|
+
|
|
3
|
+
#include <atomic>
|
|
4
|
+
#include <string>
|
|
5
|
+
|
|
6
|
+
namespace audioapi {
|
|
7
|
+
|
|
8
|
+
namespace {
|
|
9
|
+
|
|
10
|
+
std::string cachedFilesDir;
|
|
11
|
+
std::string cachedCacheDir;
|
|
12
|
+
std::atomic<bool> cacheReady{false};
|
|
13
|
+
|
|
14
|
+
std::string fetchFilesDirFromJava() {
|
|
15
|
+
static const auto method =
|
|
16
|
+
NativeFileInfo::javaClassStatic()->getStaticMethod<jni::JString()>("getFilesDir");
|
|
17
|
+
return method(NativeFileInfo::javaClassStatic())->toStdString();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
std::string fetchCacheDirFromJava() {
|
|
21
|
+
static const auto method =
|
|
22
|
+
NativeFileInfo::javaClassStatic()->getStaticMethod<jni::JString()>("getCacheDir");
|
|
23
|
+
return method(NativeFileInfo::javaClassStatic())->toStdString();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
} // namespace
|
|
27
|
+
|
|
28
|
+
void NativeFileInfo::warmCache() {
|
|
29
|
+
cachedFilesDir = fetchFilesDirFromJava();
|
|
30
|
+
cachedCacheDir = fetchCacheDirFromJava();
|
|
31
|
+
cacheReady.store(true, std::memory_order_release);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
std::string NativeFileInfo::getFilesDir() {
|
|
35
|
+
if (cacheReady.load(std::memory_order_acquire)) {
|
|
36
|
+
return cachedFilesDir;
|
|
37
|
+
}
|
|
38
|
+
return fetchFilesDirFromJava();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
std::string NativeFileInfo::getCacheDir() {
|
|
42
|
+
if (cacheReady.load(std::memory_order_acquire)) {
|
|
43
|
+
return cachedCacheDir;
|
|
44
|
+
}
|
|
45
|
+
return fetchCacheDirFromJava();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
} // namespace audioapi
|
|
@@ -7,19 +7,17 @@ namespace audioapi {
|
|
|
7
7
|
|
|
8
8
|
using namespace facebook;
|
|
9
9
|
|
|
10
|
+
/// @brief JNI bridge to Kotlin paths for recorder file output.
|
|
11
|
+
/// @note Call warmCache() from a JNI-attached thread
|
|
10
12
|
class NativeFileInfo : public jni::JavaClass<NativeFileInfo> {
|
|
11
13
|
public:
|
|
12
14
|
static auto constexpr kJavaDescriptor = "Lcom/swmansion/audioapi/system/NativeFileInfo;";
|
|
13
15
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
return method(javaClassStatic())->toStdString();
|
|
17
|
-
}
|
|
16
|
+
/// @brief Fetches and caches directory paths via JNI. Must run before recording.
|
|
17
|
+
static void warmCache();
|
|
18
18
|
|
|
19
|
-
static std::string
|
|
20
|
-
|
|
21
|
-
return method(javaClassStatic())->toStdString();
|
|
22
|
-
}
|
|
19
|
+
static std::string getFilesDir();
|
|
20
|
+
static std::string getCacheDir();
|
|
23
21
|
};
|
|
24
22
|
|
|
25
23
|
} // namespace audioapi
|
|
@@ -27,6 +27,7 @@ AudioContextHostObject::AudioContextHostObject(
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
JSI_HOST_FUNCTION_IMPL(AudioContextHostObject, close) {
|
|
30
|
+
context_->getGraph()->collectDisposedNodes();
|
|
30
31
|
auto audioContext = std::static_pointer_cast<AudioContext>(context_);
|
|
31
32
|
auto promise = promiseVendor_->createAsyncPromise([audioContext = std::move(audioContext)]() {
|
|
32
33
|
return [audioContext](jsi::Runtime &runtime) {
|
|
@@ -39,6 +40,7 @@ JSI_HOST_FUNCTION_IMPL(AudioContextHostObject, close) {
|
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
JSI_HOST_FUNCTION_IMPL(AudioContextHostObject, resume) {
|
|
43
|
+
context_->getGraph()->collectDisposedNodes();
|
|
42
44
|
auto audioContext = std::static_pointer_cast<AudioContext>(context_);
|
|
43
45
|
auto promise = promiseVendor_->createAsyncPromise([audioContext = std::move(audioContext)]() {
|
|
44
46
|
const auto result = audioContext->resume();
|
|
@@ -53,6 +55,7 @@ JSI_HOST_FUNCTION_IMPL(AudioContextHostObject, resume) {
|
|
|
53
55
|
}
|
|
54
56
|
|
|
55
57
|
JSI_HOST_FUNCTION_IMPL(AudioContextHostObject, suspend) {
|
|
58
|
+
context_->getGraph()->collectDisposedNodes();
|
|
56
59
|
auto audioContext = std::static_pointer_cast<AudioContext>(context_);
|
|
57
60
|
auto promise = promiseVendor_->createAsyncPromise([audioContext = std::move(audioContext)]() {
|
|
58
61
|
const auto result = audioContext->suspend();
|
|
@@ -70,17 +73,12 @@ JSI_HOST_FUNCTION_IMPL(AudioContextHostObject, suspend) {
|
|
|
70
73
|
JSI_HOST_FUNCTION_IMPL(AudioContextHostObject, createMediaElementSource) {
|
|
71
74
|
auto sourceObject = args[0].asObject(runtime);
|
|
72
75
|
auto fileSourceHostObject = sourceObject.getHostObject<AudioFileSourceNodeHostObject>(runtime);
|
|
73
|
-
auto
|
|
74
|
-
auto
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
auto mediaElementSourceHostObject =
|
|
82
|
-
std::make_shared<MediaElementAudioSourceNodeHostObject>(mediaElementSourceNode);
|
|
83
|
-
return jsi::Object::createFromHostObject(runtime, mediaElementSourceHostObject);
|
|
76
|
+
auto *fileSourceRaw = fileSourceHostObject->audioFileSourceNode();
|
|
77
|
+
auto mediaElementHostObject = std::make_shared<MediaElementAudioSourceNodeHostObject>(
|
|
78
|
+
std::static_pointer_cast<AudioContext>(context_), fileSourceRaw);
|
|
79
|
+
auto object = jsi::Object::createFromHostObject(runtime, mediaElementHostObject);
|
|
80
|
+
object.setExternalMemoryPressure(runtime, mediaElementHostObject->getMemoryPressure());
|
|
81
|
+
return object;
|
|
84
82
|
}
|
|
85
83
|
|
|
86
84
|
} // namespace audioapi
|