react-native-audio-api 0.8.3 → 0.9.0-nightly-96a5bcd-20251007
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/README.md +40 -39
- package/RNAudioAPI.podspec +17 -12
- package/android/build.gradle +44 -4
- package/android/src/main/cpp/audioapi/CMakeLists.txt +65 -0
- package/android/src/main/cpp/audioapi/android/AudioAPIModule.cpp +29 -1
- package/android/src/main/cpp/audioapi/android/AudioAPIModule.h +14 -0
- package/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.cpp +7 -1
- package/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.h +6 -1
- package/android/src/main/cpp/audioapi/android/core/AudioPlayer.cpp +1 -1
- package/android/src/main/cpp/audioapi/android/core/NativeAudioRecorder.hpp +36 -0
- package/android/src/main/cpp/audioapi/android/core/{AudioDecoder.cpp → utils/AudioDecoder.cpp} +79 -75
- package/android/src/main/java/com/swmansion/audioapi/AudioAPIModule.kt +11 -1
- package/android/src/main/java/com/swmansion/audioapi/core/NativeAudioRecorder.kt +24 -0
- package/android/src/main/java/com/swmansion/audioapi/system/MediaSessionManager.kt +15 -2
- package/common/cpp/audioapi/AudioAPIModuleInstaller.h +129 -38
- package/common/cpp/audioapi/HostObjects/AudioContextHostObject.cpp +57 -0
- package/common/cpp/audioapi/HostObjects/AudioContextHostObject.h +6 -46
- package/common/cpp/audioapi/HostObjects/AudioNodeHostObject.cpp +70 -6
- package/common/cpp/audioapi/HostObjects/AudioNodeHostObject.h +10 -66
- package/common/cpp/audioapi/HostObjects/AudioParamHostObject.cpp +105 -0
- package/common/cpp/audioapi/HostObjects/AudioParamHostObject.h +17 -91
- package/common/cpp/audioapi/HostObjects/BaseAudioContextHostObject.cpp +262 -6
- package/common/cpp/audioapi/HostObjects/BaseAudioContextHostObject.h +26 -241
- package/common/cpp/audioapi/HostObjects/OfflineAudioContextHostObject.cpp +70 -0
- package/common/cpp/audioapi/HostObjects/OfflineAudioContextHostObject.h +6 -50
- package/common/cpp/audioapi/HostObjects/WorkletNodeHostObject.h +18 -0
- package/common/cpp/audioapi/HostObjects/WorkletProcessingNodeHostObject.h +18 -0
- package/common/cpp/audioapi/HostObjects/analysis/AnalyserNodeHostObject.cpp +148 -0
- package/common/cpp/audioapi/HostObjects/analysis/AnalyserNodeHostObject.h +37 -0
- package/common/cpp/audioapi/HostObjects/effects/BiquadFilterNodeHostObject.cpp +92 -0
- package/common/cpp/audioapi/HostObjects/effects/BiquadFilterNodeHostObject.h +29 -0
- package/common/cpp/audioapi/HostObjects/effects/GainNodeHostObject.cpp +20 -0
- package/common/cpp/audioapi/HostObjects/effects/GainNodeHostObject.h +19 -0
- package/common/cpp/audioapi/HostObjects/effects/StereoPannerNodeHostObject.cpp +21 -0
- package/common/cpp/audioapi/HostObjects/effects/StereoPannerNodeHostObject.h +21 -0
- package/common/cpp/audioapi/HostObjects/events/AudioEventHandlerRegistryHostObject.cpp +41 -0
- package/common/cpp/audioapi/HostObjects/events/AudioEventHandlerRegistryHostObject.h +28 -0
- package/common/cpp/audioapi/HostObjects/inputs/AudioRecorderHostObject.cpp +69 -0
- package/common/cpp/audioapi/HostObjects/inputs/AudioRecorderHostObject.h +33 -0
- package/common/cpp/audioapi/HostObjects/sources/AudioBufferBaseSourceNodeHostObject.cpp +73 -0
- package/common/cpp/audioapi/HostObjects/sources/AudioBufferBaseSourceNodeHostObject.h +29 -0
- package/common/cpp/audioapi/HostObjects/sources/AudioBufferHostObject.cpp +94 -0
- package/common/cpp/audioapi/HostObjects/sources/AudioBufferHostObject.h +46 -0
- package/common/cpp/audioapi/HostObjects/sources/AudioBufferQueueSourceNodeHostObject.cpp +60 -0
- package/common/cpp/audioapi/HostObjects/sources/AudioBufferQueueSourceNodeHostObject.h +25 -0
- package/common/cpp/audioapi/HostObjects/sources/AudioBufferSourceNodeHostObject.cpp +152 -0
- package/common/cpp/audioapi/HostObjects/sources/AudioBufferSourceNodeHostObject.h +37 -0
- package/common/cpp/audioapi/HostObjects/sources/AudioScheduledSourceNodeHostObject.cpp +52 -0
- package/common/cpp/audioapi/HostObjects/sources/AudioScheduledSourceNodeHostObject.h +25 -0
- package/common/cpp/audioapi/HostObjects/sources/ConstantSourceNodeHostObject.cpp +19 -0
- package/common/cpp/audioapi/HostObjects/sources/ConstantSourceNodeHostObject.h +21 -0
- package/common/cpp/audioapi/HostObjects/sources/OscillatorNodeHostObject.cpp +55 -0
- package/common/cpp/audioapi/HostObjects/sources/OscillatorNodeHostObject.h +27 -0
- package/common/cpp/audioapi/HostObjects/{RecorderAdapterNodeHostObject.h → sources/RecorderAdapterNodeHostObject.h} +1 -2
- package/common/cpp/audioapi/HostObjects/sources/StreamerNodeHostObject.cpp +22 -0
- package/common/cpp/audioapi/HostObjects/sources/StreamerNodeHostObject.h +28 -0
- package/common/cpp/audioapi/HostObjects/sources/WorkletSourceNodeHostObject.h +18 -0
- package/common/cpp/audioapi/HostObjects/utils/AudioDecoderHostObject.cpp +107 -0
- package/common/cpp/audioapi/HostObjects/utils/AudioDecoderHostObject.h +28 -0
- package/common/cpp/audioapi/core/AudioContext.cpp +3 -4
- package/common/cpp/audioapi/core/AudioContext.h +2 -1
- package/common/cpp/audioapi/core/AudioNode.cpp +3 -3
- package/common/cpp/audioapi/core/AudioNode.h +2 -2
- package/common/cpp/audioapi/core/AudioParam.cpp +2 -2
- package/common/cpp/audioapi/core/AudioParam.h +1 -1
- package/common/cpp/audioapi/core/BaseAudioContext.cpp +47 -38
- package/common/cpp/audioapi/core/BaseAudioContext.h +17 -16
- package/common/cpp/audioapi/core/OfflineAudioContext.cpp +4 -5
- package/common/cpp/audioapi/core/OfflineAudioContext.h +2 -1
- package/common/cpp/audioapi/core/analysis/AnalyserNode.cpp +3 -1
- package/common/cpp/audioapi/core/analysis/AnalyserNode.h +1 -1
- package/common/cpp/audioapi/core/destinations/AudioDestinationNode.h +1 -1
- package/common/cpp/audioapi/core/effects/BiquadFilterNode.cpp +3 -1
- package/common/cpp/audioapi/core/effects/BiquadFilterNode.h +1 -1
- package/common/cpp/audioapi/core/effects/GainNode.cpp +3 -1
- package/common/cpp/audioapi/core/effects/GainNode.h +1 -1
- package/common/cpp/audioapi/core/effects/PeriodicWave.cpp +1 -1
- package/common/cpp/audioapi/core/effects/StereoPannerNode.cpp +18 -13
- package/common/cpp/audioapi/core/effects/StereoPannerNode.h +1 -1
- package/common/cpp/audioapi/core/effects/WorkletNode.cpp +89 -0
- package/common/cpp/audioapi/core/effects/WorkletNode.h +65 -0
- package/common/cpp/audioapi/core/effects/WorkletProcessingNode.cpp +91 -0
- package/common/cpp/audioapi/core/effects/WorkletProcessingNode.h +52 -0
- package/common/cpp/audioapi/core/inputs/AudioRecorder.cpp +1 -1
- package/common/cpp/audioapi/core/inputs/AudioRecorder.h +2 -2
- package/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.cpp +47 -10
- package/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.h +18 -3
- package/common/cpp/audioapi/core/sources/AudioBufferQueueSourceNode.cpp +98 -14
- package/common/cpp/audioapi/core/sources/AudioBufferQueueSourceNode.h +9 -3
- package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp +37 -44
- package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.h +7 -9
- package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.cpp +1 -6
- package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.h +1 -1
- package/common/cpp/audioapi/core/sources/ConstantSourceNode.cpp +53 -0
- package/common/cpp/audioapi/core/sources/ConstantSourceNode.h +26 -0
- package/common/cpp/audioapi/core/sources/OscillatorNode.cpp +7 -2
- package/common/cpp/audioapi/core/sources/OscillatorNode.h +1 -1
- package/common/cpp/audioapi/core/sources/RecorderAdapterNode.cpp +3 -1
- package/common/cpp/audioapi/core/sources/RecorderAdapterNode.h +1 -1
- package/common/cpp/audioapi/core/sources/StreamerNode.cpp +9 -1
- package/common/cpp/audioapi/core/sources/StreamerNode.h +1 -9
- package/common/cpp/audioapi/core/sources/WorkletSourceNode.cpp +84 -0
- package/common/cpp/audioapi/core/sources/WorkletSourceNode.h +47 -0
- package/common/cpp/audioapi/core/types/AudioFormat.h +16 -0
- package/common/cpp/audioapi/core/utils/AudioDecoder.h +36 -90
- package/common/cpp/audioapi/core/{AudioParamEventQueue.cpp → utils/AudioParamEventQueue.cpp} +13 -7
- package/common/cpp/audioapi/core/{Constants.h → utils/Constants.h} +5 -0
- package/common/cpp/audioapi/core/utils/worklets/SafeIncludes.h +52 -0
- package/common/cpp/audioapi/core/utils/worklets/WorkletsRunner.cpp +9 -0
- package/common/cpp/audioapi/core/utils/worklets/WorkletsRunner.h +73 -0
- package/common/cpp/audioapi/dsp/Windows.cpp +1 -1
- package/common/cpp/audioapi/events/AudioEventHandlerRegistry.cpp +1 -1
- package/common/cpp/audioapi/events/AudioEventHandlerRegistry.h +2 -1
- package/common/cpp/audioapi/jsi/AudioArrayBuffer.h +14 -1
- package/common/cpp/audioapi/jsi/JsiHostObject.h +6 -12
- package/common/cpp/audioapi/jsi/JsiPromise.cpp +49 -0
- package/common/cpp/audioapi/jsi/JsiPromise.h +29 -1
- package/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.cpp +241 -282
- package/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.h +57 -19
- package/common/cpp/audioapi/utils/AudioBus.cpp +1 -1
- package/common/cpp/audioapi/utils/ThreadPool.hpp +104 -0
- package/common/cpp/test/AudioParamTest.cpp +204 -0
- package/common/cpp/test/CMakeLists.txt +13 -4
- package/common/cpp/test/GainTest.cpp +11 -10
- package/common/cpp/test/OscillatorTest.cpp +2 -1
- package/common/cpp/test/StereoPannerTest.cpp +129 -0
- package/ios/audioapi/ios/AudioAPIModule.mm +32 -5
- package/ios/audioapi/ios/core/IOSAudioPlayer.mm +1 -1
- package/ios/audioapi/ios/core/IOSAudioRecorder.mm +1 -1
- package/ios/audioapi/ios/core/utils/AudioDecoder.mm +160 -0
- package/lib/commonjs/api.js +50 -3
- package/lib/commonjs/api.js.map +1 -1
- package/lib/commonjs/api.web.js +8 -0
- package/lib/commonjs/api.web.js.map +1 -1
- package/lib/commonjs/core/AudioBufferBaseSourceNode.js +7 -7
- package/lib/commonjs/core/AudioBufferBaseSourceNode.js.map +1 -1
- package/lib/commonjs/core/AudioBufferQueueSourceNode.js +1 -6
- package/lib/commonjs/core/AudioBufferQueueSourceNode.js.map +1 -1
- package/lib/commonjs/core/AudioBufferSourceNode.js +15 -0
- package/lib/commonjs/core/AudioBufferSourceNode.js.map +1 -1
- package/lib/commonjs/core/AudioContext.js +10 -1
- package/lib/commonjs/core/AudioContext.js.map +1 -1
- package/lib/commonjs/core/AudioDecoder.js +48 -0
- package/lib/commonjs/core/AudioDecoder.js.map +1 -0
- package/lib/commonjs/core/AudioScheduledSourceNode.js +4 -4
- package/lib/commonjs/core/AudioScheduledSourceNode.js.map +1 -1
- package/lib/commonjs/core/BaseAudioContext.js +76 -28
- package/lib/commonjs/core/BaseAudioContext.js.map +1 -1
- package/lib/commonjs/core/ConstantSourceNode.js +17 -0
- package/lib/commonjs/core/ConstantSourceNode.js.map +1 -0
- package/lib/commonjs/core/OfflineAudioContext.js +11 -2
- package/lib/commonjs/core/OfflineAudioContext.js.map +1 -1
- package/lib/commonjs/core/OscillatorNode.js +6 -0
- package/lib/commonjs/core/OscillatorNode.js.map +1 -1
- package/lib/commonjs/core/WorkletNode.js +11 -0
- package/lib/commonjs/core/WorkletNode.js.map +1 -0
- package/lib/commonjs/core/WorkletProcessingNode.js +11 -0
- package/lib/commonjs/core/WorkletProcessingNode.js.map +1 -0
- package/lib/commonjs/core/WorkletSourceNode.js +11 -0
- package/lib/commonjs/core/WorkletSourceNode.js.map +1 -0
- package/lib/commonjs/hooks/{useSytemVolume.js → useSystemVolume.js} +1 -1
- package/lib/commonjs/hooks/useSystemVolume.js.map +1 -0
- package/lib/commonjs/utils/index.js +9 -0
- package/lib/commonjs/utils/index.js.map +1 -1
- package/lib/commonjs/web-core/AudioContext.js +4 -0
- package/lib/commonjs/web-core/AudioContext.js.map +1 -1
- package/lib/commonjs/web-core/AudioScheduledSourceNode.js +1 -1
- package/lib/commonjs/web-core/AudioScheduledSourceNode.js.map +1 -1
- package/lib/commonjs/web-core/ConstantSourceNode.js +17 -0
- package/lib/commonjs/web-core/ConstantSourceNode.js.map +1 -0
- package/lib/commonjs/web-core/OfflineAudioContext.js +4 -0
- package/lib/commonjs/web-core/OfflineAudioContext.js.map +1 -1
- package/lib/module/api.js +8 -3
- package/lib/module/api.js.map +1 -1
- package/lib/module/api.web.js +1 -0
- package/lib/module/api.web.js.map +1 -1
- package/lib/module/core/AudioBufferBaseSourceNode.js +7 -7
- package/lib/module/core/AudioBufferBaseSourceNode.js.map +1 -1
- package/lib/module/core/AudioBufferQueueSourceNode.js +1 -6
- package/lib/module/core/AudioBufferQueueSourceNode.js.map +1 -1
- package/lib/module/core/AudioBufferSourceNode.js +15 -0
- package/lib/module/core/AudioBufferSourceNode.js.map +1 -1
- package/lib/module/core/AudioContext.js +10 -1
- package/lib/module/core/AudioContext.js.map +1 -1
- package/lib/module/core/AudioDecoder.js +42 -0
- package/lib/module/core/AudioDecoder.js.map +1 -0
- package/lib/module/core/AudioScheduledSourceNode.js +4 -4
- package/lib/module/core/AudioScheduledSourceNode.js.map +1 -1
- package/lib/module/core/BaseAudioContext.js +76 -28
- package/lib/module/core/BaseAudioContext.js.map +1 -1
- package/lib/module/core/ConstantSourceNode.js +11 -0
- package/lib/module/core/ConstantSourceNode.js.map +1 -0
- package/lib/module/core/OfflineAudioContext.js +11 -2
- package/lib/module/core/OfflineAudioContext.js.map +1 -1
- package/lib/module/core/OscillatorNode.js +6 -0
- package/lib/module/core/OscillatorNode.js.map +1 -1
- package/lib/module/core/WorkletNode.js +5 -0
- package/lib/module/core/WorkletNode.js.map +1 -0
- package/lib/module/core/WorkletProcessingNode.js +5 -0
- package/lib/module/core/WorkletProcessingNode.js.map +1 -0
- package/lib/module/core/WorkletSourceNode.js +5 -0
- package/lib/module/core/WorkletSourceNode.js.map +1 -0
- package/lib/module/hooks/{useSytemVolume.js → useSystemVolume.js} +1 -1
- package/lib/module/hooks/useSystemVolume.js.map +1 -0
- package/lib/module/utils/index.js +8 -0
- package/lib/module/utils/index.js.map +1 -1
- package/lib/module/web-core/AudioContext.js +4 -0
- package/lib/module/web-core/AudioContext.js.map +1 -1
- package/lib/module/web-core/AudioScheduledSourceNode.js +1 -1
- package/lib/module/web-core/AudioScheduledSourceNode.js.map +1 -1
- package/lib/module/web-core/ConstantSourceNode.js +11 -0
- package/lib/module/web-core/ConstantSourceNode.js.map +1 -0
- package/lib/module/web-core/OfflineAudioContext.js +4 -0
- package/lib/module/web-core/OfflineAudioContext.js.map +1 -1
- package/lib/typescript/api.d.ts +11 -5
- package/lib/typescript/api.d.ts.map +1 -1
- package/lib/typescript/api.web.d.ts +1 -0
- package/lib/typescript/api.web.d.ts.map +1 -1
- package/lib/typescript/core/AudioBufferBaseSourceNode.d.ts +2 -2
- package/lib/typescript/core/AudioBufferBaseSourceNode.d.ts.map +1 -1
- package/lib/typescript/core/AudioBufferQueueSourceNode.d.ts +1 -1
- package/lib/typescript/core/AudioBufferQueueSourceNode.d.ts.map +1 -1
- package/lib/typescript/core/AudioBufferSourceNode.d.ts +4 -0
- package/lib/typescript/core/AudioBufferSourceNode.d.ts.map +1 -1
- package/lib/typescript/core/AudioContext.d.ts +1 -0
- package/lib/typescript/core/AudioContext.d.ts.map +1 -1
- package/lib/typescript/core/AudioDecoder.d.ts +4 -0
- package/lib/typescript/core/AudioDecoder.d.ts.map +1 -0
- package/lib/typescript/core/AudioScheduledSourceNode.d.ts +1 -1
- package/lib/typescript/core/BaseAudioContext.d.ts +21 -16
- package/lib/typescript/core/BaseAudioContext.d.ts.map +1 -1
- package/lib/typescript/core/ConstantSourceNode.d.ts +9 -0
- package/lib/typescript/core/ConstantSourceNode.d.ts.map +1 -0
- package/lib/typescript/core/OfflineAudioContext.d.ts +1 -0
- package/lib/typescript/core/OfflineAudioContext.d.ts.map +1 -1
- package/lib/typescript/core/OscillatorNode.d.ts +3 -0
- package/lib/typescript/core/OscillatorNode.d.ts.map +1 -1
- package/lib/typescript/core/WorkletNode.d.ts +4 -0
- package/lib/typescript/core/WorkletNode.d.ts.map +1 -0
- package/lib/typescript/core/WorkletProcessingNode.d.ts +4 -0
- package/lib/typescript/core/WorkletProcessingNode.d.ts.map +1 -0
- package/lib/typescript/core/WorkletSourceNode.d.ts +4 -0
- package/lib/typescript/core/WorkletSourceNode.d.ts.map +1 -0
- package/lib/typescript/events/types.d.ts +2 -0
- package/lib/typescript/events/types.d.ts.map +1 -1
- package/lib/typescript/hooks/{useSytemVolume.d.ts → useSystemVolume.d.ts} +1 -1
- package/lib/typescript/hooks/useSystemVolume.d.ts.map +1 -0
- package/lib/typescript/interfaces.d.ts +27 -6
- package/lib/typescript/interfaces.d.ts.map +1 -1
- package/lib/typescript/types.d.ts +2 -1
- package/lib/typescript/types.d.ts.map +1 -1
- package/lib/typescript/utils/index.d.ts +8 -0
- package/lib/typescript/utils/index.d.ts.map +1 -1
- package/lib/typescript/web-core/AudioBufferSourceNode.d.ts +1 -1
- package/lib/typescript/web-core/AudioContext.d.ts +4 -2
- package/lib/typescript/web-core/AudioContext.d.ts.map +1 -1
- package/lib/typescript/web-core/AudioScheduledSourceNode.d.ts +1 -1
- package/lib/typescript/web-core/BaseAudioContext.d.ts +2 -0
- package/lib/typescript/web-core/BaseAudioContext.d.ts.map +1 -1
- package/lib/typescript/web-core/ConstantSourceNode.d.ts +8 -0
- package/lib/typescript/web-core/ConstantSourceNode.d.ts.map +1 -0
- package/lib/typescript/web-core/OfflineAudioContext.d.ts +4 -2
- package/lib/typescript/web-core/OfflineAudioContext.d.ts.map +1 -1
- package/package.json +3 -2
- package/src/api.ts +17 -3
- package/src/api.web.ts +1 -0
- package/src/core/AudioBufferBaseSourceNode.ts +9 -9
- package/src/core/AudioBufferQueueSourceNode.ts +1 -9
- package/src/core/AudioBufferSourceNode.ts +28 -0
- package/src/core/AudioContext.ts +12 -1
- package/src/core/AudioDecoder.ts +78 -0
- package/src/core/AudioScheduledSourceNode.ts +5 -5
- package/src/core/BaseAudioContext.ts +174 -41
- package/src/core/ConstantSourceNode.ts +13 -0
- package/src/core/OfflineAudioContext.ts +18 -2
- package/src/core/OscillatorNode.ts +11 -0
- package/src/core/WorkletNode.ts +3 -0
- package/src/core/WorkletProcessingNode.ts +3 -0
- package/src/core/WorkletSourceNode.ts +3 -0
- package/src/events/types.ts +2 -0
- package/src/interfaces.ts +77 -11
- package/src/types.ts +3 -1
- package/src/utils/index.ts +21 -0
- package/src/web-core/AudioBufferSourceNode.tsx +1 -1
- package/src/web-core/AudioContext.tsx +7 -2
- package/src/web-core/AudioScheduledSourceNode.tsx +1 -1
- package/src/web-core/BaseAudioContext.tsx +2 -0
- package/src/web-core/ConstantSourceNode.tsx +12 -0
- package/src/web-core/OfflineAudioContext.tsx +7 -2
- package/common/cpp/audioapi/HostObjects/AnalyserNodeHostObject.h +0 -149
- package/common/cpp/audioapi/HostObjects/AudioBufferBaseSourceNodeHostObject.h +0 -76
- package/common/cpp/audioapi/HostObjects/AudioBufferHostObject.h +0 -120
- package/common/cpp/audioapi/HostObjects/AudioBufferQueueSourceNodeHostObject.h +0 -67
- package/common/cpp/audioapi/HostObjects/AudioBufferSourceNodeHostObject.h +0 -142
- package/common/cpp/audioapi/HostObjects/AudioRecorderHostObject.h +0 -86
- package/common/cpp/audioapi/HostObjects/AudioScheduledSourceNodeHostObject.h +0 -56
- package/common/cpp/audioapi/HostObjects/BiquadFilterNodeHostObject.h +0 -89
- package/common/cpp/audioapi/HostObjects/GainNodeHostObject.h +0 -27
- package/common/cpp/audioapi/HostObjects/OscillatorNodeHostObject.h +0 -65
- package/common/cpp/audioapi/HostObjects/StereoPannerNodeHostObject.h +0 -29
- package/common/cpp/audioapi/HostObjects/StreamerNodeHostObject.h +0 -30
- package/common/cpp/audioapi/events/AudioEventHandlerRegistryHostObject.h +0 -48
- package/ios/audioapi/ios/core/AudioDecoder.mm +0 -156
- package/ios/audioapi/ios/events/IOSAudioEventHandlerRegistry.h +0 -7
- package/ios/audioapi/ios/events/IOSAudioEventHandlerRegistry.mm +0 -12
- package/lib/commonjs/hooks/useSytemVolume.js.map +0 -1
- package/lib/module/hooks/useSytemVolume.js.map +0 -1
- package/lib/typescript/hooks/useSytemVolume.d.ts.map +0 -1
- /package/common/cpp/audioapi/HostObjects/{AudioDestinationNodeHostObject.h → destinations/AudioDestinationNodeHostObject.h} +0 -0
- /package/common/cpp/audioapi/HostObjects/{PeriodicWaveHostObject.h → effects/PeriodicWaveHostObject.h} +0 -0
- /package/common/cpp/audioapi/core/{AudioParamEventQueue.h → utils/AudioParamEventQueue.h} +0 -0
- /package/src/hooks/{useSytemVolume.ts → useSystemVolume.ts} +0 -0
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* This file dynamically links to the FFmpeg library, which is licensed under
|
|
3
|
-
* GNU Lesser General Public License (LGPL) version 2.1 or later.
|
|
2
|
+
* This file dynamically links to the FFmpeg library, which is licensed under
|
|
3
|
+
* the GNU Lesser General Public License (LGPL) version 2.1 or later.
|
|
4
4
|
*
|
|
5
|
-
* Our own code in this file is licensed under the MIT License and dynamic
|
|
6
|
-
* allows you to use this code without your entire project being subject
|
|
7
|
-
* terms of the LGPL. However, note that if you link statically to
|
|
8
|
-
* comply with the terms of the LGPL for FFmpeg itself.
|
|
5
|
+
* Our own code in this file is licensed under the MIT License and dynamic
|
|
6
|
+
* linking allows you to use this code without your entire project being subject
|
|
7
|
+
* to the terms of the LGPL. However, note that if you link statically to
|
|
8
|
+
* FFmpeg, you must comply with the terms of the LGPL for FFmpeg itself.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
#include <audioapi/utils/AudioBus.h>
|
|
@@ -14,24 +14,62 @@
|
|
|
14
14
|
#include <vector>
|
|
15
15
|
|
|
16
16
|
extern "C" {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
#include <libavcodec/avcodec.h>
|
|
18
|
+
#include <libavformat/avformat.h>
|
|
19
|
+
#include <libavutil/opt.h>
|
|
20
|
+
#include <libswresample/swresample.h>
|
|
21
21
|
}
|
|
22
|
+
class AudioBuffer;
|
|
22
23
|
|
|
23
|
-
namespace audioapi::
|
|
24
|
+
namespace audioapi::ffmpegdecoder {
|
|
24
25
|
// Custom IO context for reading from memory
|
|
25
26
|
struct MemoryIOContext {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
const uint8_t *data;
|
|
28
|
+
size_t size;
|
|
29
|
+
size_t pos;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
struct AudioStreamContext {
|
|
33
|
+
AVFormatContext *fmt_ctx = nullptr;
|
|
34
|
+
AVCodecContext *codec_ctx = nullptr;
|
|
35
|
+
int audio_stream_index = -1;
|
|
36
|
+
};
|
|
30
37
|
|
|
31
38
|
int read_packet(void *opaque, uint8_t *buf, int buf_size);
|
|
32
39
|
int64_t seek_packet(void *opaque, int64_t offset, int whence);
|
|
33
|
-
|
|
34
|
-
std::vector<
|
|
35
|
-
|
|
40
|
+
inline int findAudioStreamIndex(AVFormatContext *fmt_ctx);
|
|
41
|
+
std::vector<float> readAllPcmFrames(
|
|
42
|
+
AVFormatContext *fmt_ctx,
|
|
43
|
+
AVCodecContext *codec_ctx,
|
|
44
|
+
int out_sample_rate,
|
|
45
|
+
int output_channel_count,
|
|
46
|
+
int audio_stream_index,
|
|
47
|
+
size_t &framesRead);
|
|
48
|
+
|
|
49
|
+
void convertFrameToBuffer(
|
|
50
|
+
SwrContext *swr,
|
|
51
|
+
AVFrame *frame,
|
|
52
|
+
int output_channel_count,
|
|
53
|
+
std::vector<float> &buffer,
|
|
54
|
+
size_t &framesRead,
|
|
55
|
+
uint8_t **&resampled_data,
|
|
56
|
+
int &max_resampled_samples);
|
|
57
|
+
bool setupDecoderContext(
|
|
58
|
+
AVFormatContext *fmt_ctx,
|
|
59
|
+
int &audio_stream_index,
|
|
60
|
+
std::unique_ptr<AVCodecContext, decltype(&avcodec_free_context)>
|
|
61
|
+
&codec_ctx);
|
|
62
|
+
std::shared_ptr<AudioBuffer> decodeAudioFrames(
|
|
63
|
+
AVFormatContext *fmt_ctx,
|
|
64
|
+
AVCodecContext *codec_ctx,
|
|
65
|
+
int audio_stream_index,
|
|
66
|
+
int sample_rate);
|
|
67
|
+
|
|
68
|
+
std::shared_ptr<AudioBuffer>
|
|
69
|
+
decodeWithMemoryBlock(const void *data, size_t size, int sample_rate);
|
|
70
|
+
|
|
71
|
+
std::shared_ptr<AudioBuffer> decodeWithFilePath(
|
|
72
|
+
const std::string &path,
|
|
73
|
+
int sample_rate);
|
|
36
74
|
|
|
37
|
-
} // namespace audioapi::ffmpegdecoder
|
|
75
|
+
} // namespace audioapi::ffmpegdecoder
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
#include <thread>
|
|
3
|
+
#include <vector>
|
|
4
|
+
#include <functional>
|
|
5
|
+
#include <variant>
|
|
6
|
+
#include <audioapi/utils/SpscChannel.hpp>
|
|
7
|
+
|
|
8
|
+
namespace audioapi {
|
|
9
|
+
|
|
10
|
+
/// @brief A simple thread pool implementation using lock-free SPSC channels for task scheduling and execution.
|
|
11
|
+
/// @note The thread pool consists of a load balancer thread and multiple worker threads.
|
|
12
|
+
/// @note The load balancer receives tasks and distributes them to worker threads in a round-robin fashion.
|
|
13
|
+
/// @note Each worker thread has its own SPSC channel to receive tasks from the load balancer.
|
|
14
|
+
/// @note The thread pool can be shut down gracefully by sending a stop event to the load balancer, which then propagates the stop event to all worker threads.
|
|
15
|
+
/// @note IMPORTANT: ThreadPool is not thread-safe and events should be scheduled from a single thread only.
|
|
16
|
+
class ThreadPool {
|
|
17
|
+
struct StopEvent {};
|
|
18
|
+
struct TaskEvent { std::function<void()> task; };
|
|
19
|
+
using Event = std::variant<TaskEvent, StopEvent>;
|
|
20
|
+
|
|
21
|
+
using Sender = channels::spsc::Sender<Event, channels::spsc::OverflowStrategy::WAIT_ON_FULL, channels::spsc::WaitStrategy::ATOMIC_WAIT>;
|
|
22
|
+
using Receiver = channels::spsc::Receiver<Event, channels::spsc::OverflowStrategy::WAIT_ON_FULL, channels::spsc::WaitStrategy::ATOMIC_WAIT>;
|
|
23
|
+
public:
|
|
24
|
+
/// @brief Construct a new ThreadPool
|
|
25
|
+
/// @param numThreads The number of worker threads to create
|
|
26
|
+
/// @param loadBalancerQueueSize The size of the load balancer's queue
|
|
27
|
+
/// @param workerQueueSize The size of each worker thread's queue
|
|
28
|
+
ThreadPool(size_t numThreads, size_t loadBalancerQueueSize = 32, size_t workerQueueSize = 32) {
|
|
29
|
+
auto [sender, receiver] = channels::spsc::channel<Event, channels::spsc::OverflowStrategy::WAIT_ON_FULL, channels::spsc::WaitStrategy::ATOMIC_WAIT>(loadBalancerQueueSize);
|
|
30
|
+
loadBalancerSender = std::move(sender);
|
|
31
|
+
std::vector<Sender> workerSenders;
|
|
32
|
+
workerSenders.reserve(numThreads);
|
|
33
|
+
for (size_t i = 0; i < numThreads; ++i) {
|
|
34
|
+
auto [workerSender, workerReceiver] = channels::spsc::channel<Event, channels::spsc::OverflowStrategy::WAIT_ON_FULL, channels::spsc::WaitStrategy::ATOMIC_WAIT>(workerQueueSize);
|
|
35
|
+
workers.emplace_back(&ThreadPool::workerThreadFunc, this, std::move(workerReceiver));
|
|
36
|
+
workerSenders.emplace_back(std::move(workerSender));
|
|
37
|
+
}
|
|
38
|
+
loadBalancerThread = std::thread(&ThreadPool::loadBalancerThreadFunc, this, std::move(receiver), std::move(workerSenders));
|
|
39
|
+
}
|
|
40
|
+
~ThreadPool() {
|
|
41
|
+
loadBalancerSender.send(StopEvent{});
|
|
42
|
+
loadBalancerThread.join();
|
|
43
|
+
for (auto& worker : workers) {
|
|
44
|
+
worker.join();
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/// @brief Schedule a task to be executed by the thread pool
|
|
49
|
+
/// @param task The task to be executed
|
|
50
|
+
/// @note This function is lock-free and most of the time wait-free, but may block if the load balancer queue is full.
|
|
51
|
+
/// @note Please remember that the task will be executed in a different thread, so make sure to capture any required variables by value.
|
|
52
|
+
/// @note The task should not throw exceptions, as they will not be caught.
|
|
53
|
+
/// @note The task should end at some point, otherwise the thread pool will never be able to shut down.
|
|
54
|
+
/// @note IMPORTANT: This function is not thread-safe and should be called from a single thread only.
|
|
55
|
+
void schedule(std::function<void()> &&task) noexcept {
|
|
56
|
+
loadBalancerSender.send(TaskEvent{std::move(task)});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
private:
|
|
60
|
+
std::thread loadBalancerThread;
|
|
61
|
+
std::vector<std::thread> workers;
|
|
62
|
+
Sender loadBalancerSender;
|
|
63
|
+
|
|
64
|
+
void workerThreadFunc(Receiver &&receiver) {
|
|
65
|
+
Receiver localReceiver = std::move(receiver);
|
|
66
|
+
while (true) {
|
|
67
|
+
auto event = localReceiver.receive();
|
|
68
|
+
/// We use [[unlikely]] and [[likely]] attributes to help the compiler optimize the branching.
|
|
69
|
+
/// we expect most of the time to receive TaskEvent, and rarely StopEvent.
|
|
70
|
+
/// and whenever we receive StopEvent we can burn some cycles as it will not be expected to execute fast.
|
|
71
|
+
if (std::holds_alternative<StopEvent>(event)) [[ unlikely ]] {
|
|
72
|
+
break;
|
|
73
|
+
} else if (std::holds_alternative<TaskEvent>(event)) [[ likely ]] {
|
|
74
|
+
std::get<TaskEvent>(event).task();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
void loadBalancerThreadFunc(Receiver &&receiver, std::vector<Sender> &&workerSenders) {
|
|
80
|
+
Receiver localReceiver = std::move(receiver);
|
|
81
|
+
std::vector<Sender> localWorkerSenders = std::move(workerSenders);
|
|
82
|
+
size_t nextWorker = 0;
|
|
83
|
+
while (true) {
|
|
84
|
+
auto event = localReceiver.receive();
|
|
85
|
+
/// We use [[unlikely]] and [[likely]] attributes to help the compiler optimize the branching.
|
|
86
|
+
/// we expect most of the time to receive TaskEvent, and rarely StopEvent.
|
|
87
|
+
/// and whenever we receive StopEvent we can burn some cycles as it will not be expected to execute fast.
|
|
88
|
+
if (std::holds_alternative<StopEvent>(event)) [[ unlikely ]] {
|
|
89
|
+
// Propagate stop event to all workers
|
|
90
|
+
for (size_t i = 0; i < localWorkerSenders.size(); ++i) {
|
|
91
|
+
localWorkerSenders[i].send(StopEvent{});
|
|
92
|
+
}
|
|
93
|
+
break;
|
|
94
|
+
} else if (std::holds_alternative<TaskEvent>(event)) [[ likely ]] {
|
|
95
|
+
// Dispatch task to the next worker in round-robin fashion
|
|
96
|
+
auto& taskEvent = std::get<TaskEvent>(event);
|
|
97
|
+
localWorkerSenders[nextWorker].send(std::move(taskEvent));
|
|
98
|
+
nextWorker = (nextWorker + 1) % localWorkerSenders.size();
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
}; // namespace audioapi
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
#include <audioapi/core/AudioParam.h>
|
|
2
|
+
#include <audioapi/core/OfflineAudioContext.h>
|
|
3
|
+
#include <audioapi/core/utils/worklets/SafeIncludes.h>
|
|
4
|
+
#include <gtest/gtest.h>
|
|
5
|
+
#include "MockAudioEventHandlerRegistry.h"
|
|
6
|
+
|
|
7
|
+
using namespace audioapi;
|
|
8
|
+
|
|
9
|
+
class AudioParamTest : public ::testing::Test {
|
|
10
|
+
protected:
|
|
11
|
+
std::shared_ptr<IAudioEventHandlerRegistry> eventRegistry;
|
|
12
|
+
std::unique_ptr<OfflineAudioContext> context;
|
|
13
|
+
static constexpr int sampleRate = 44100;
|
|
14
|
+
|
|
15
|
+
void SetUp() override {
|
|
16
|
+
eventRegistry = std::make_shared<MockAudioEventHandlerRegistry>();
|
|
17
|
+
context = std::make_unique<OfflineAudioContext>(
|
|
18
|
+
2, 5 * sampleRate, sampleRate, eventRegistry, RuntimeRegistry{});
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
TEST_F(AudioParamTest, ValueSetters) {
|
|
23
|
+
AudioParam param = AudioParam(0.5, 0.0, 1.0, context.get());
|
|
24
|
+
param.setValue(0.8);
|
|
25
|
+
EXPECT_FLOAT_EQ(param.getValue(), 0.8);
|
|
26
|
+
param.setValue(-0.5);
|
|
27
|
+
EXPECT_FLOAT_EQ(param.getValue(), 0.0);
|
|
28
|
+
param.setValue(1.5);
|
|
29
|
+
EXPECT_FLOAT_EQ(param.getValue(), 1.0);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
TEST_F(AudioParamTest, SetValueAtTime) {
|
|
33
|
+
AudioParam param = AudioParam(0.5, 0.0, 1.0, context.get());
|
|
34
|
+
param.setValueAtTime(0.8, 0.1);
|
|
35
|
+
param.setValueAtTime(0.3, 0.2);
|
|
36
|
+
|
|
37
|
+
float value = param.processKRateParam(1, 0.05);
|
|
38
|
+
EXPECT_FLOAT_EQ(value, 0.5);
|
|
39
|
+
|
|
40
|
+
value = param.processKRateParam(1, 0.1);
|
|
41
|
+
EXPECT_FLOAT_EQ(value, 0.8);
|
|
42
|
+
|
|
43
|
+
value = param.processKRateParam(1, 0.15);
|
|
44
|
+
EXPECT_FLOAT_EQ(value, 0.8);
|
|
45
|
+
|
|
46
|
+
value = param.processKRateParam(1, 0.2);
|
|
47
|
+
EXPECT_FLOAT_EQ(value, 0.3);
|
|
48
|
+
|
|
49
|
+
value = param.processKRateParam(1, 0.25);
|
|
50
|
+
EXPECT_FLOAT_EQ(value, 0.3);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
TEST_F(AudioParamTest, LinearRampToValueAtTime) {
|
|
54
|
+
AudioParam param = AudioParam(0, 0, 1.0, context.get());
|
|
55
|
+
param.linearRampToValueAtTime(1.0, 0.2);
|
|
56
|
+
|
|
57
|
+
float value = param.processKRateParam(1, 0.05);
|
|
58
|
+
EXPECT_FLOAT_EQ(value, 0.25);
|
|
59
|
+
|
|
60
|
+
value = param.processKRateParam(1, 0.1);
|
|
61
|
+
EXPECT_FLOAT_EQ(value, 0.5);
|
|
62
|
+
|
|
63
|
+
value = param.processKRateParam(1, 0.15);
|
|
64
|
+
EXPECT_FLOAT_EQ(value, 0.75);
|
|
65
|
+
|
|
66
|
+
value = param.processKRateParam(1, 0.2);
|
|
67
|
+
EXPECT_FLOAT_EQ(value, 1.0);
|
|
68
|
+
|
|
69
|
+
value = param.processKRateParam(1, 0.25);
|
|
70
|
+
EXPECT_FLOAT_EQ(value, 1.0);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
TEST_F(AudioParamTest, ExponentialRampToValueAtTime) {
|
|
74
|
+
AudioParam param = AudioParam(0.1, 0.0, 1.0, context.get());
|
|
75
|
+
param.exponentialRampToValueAtTime(1.0, 0.2);
|
|
76
|
+
// value(time) = startValue * (endValue/startValue)^((time -
|
|
77
|
+
// startTime)/(endTime - startTime)) value(time) = 0.1 * (1.0/0.1)^((time -
|
|
78
|
+
// 0.0)/(0.2 - 0.0))
|
|
79
|
+
float value = param.processKRateParam(1, 0.05);
|
|
80
|
+
EXPECT_NEAR(value, 0.17783, 1e-5);
|
|
81
|
+
|
|
82
|
+
value = param.processKRateParam(1, 0.1);
|
|
83
|
+
EXPECT_NEAR(value, 0.316228, 1e-5);
|
|
84
|
+
|
|
85
|
+
value = param.processKRateParam(1, 0.15);
|
|
86
|
+
EXPECT_NEAR(value, 0.562341, 1e-5);
|
|
87
|
+
|
|
88
|
+
value = param.processKRateParam(1, 0.2);
|
|
89
|
+
EXPECT_FLOAT_EQ(value, 1.0);
|
|
90
|
+
|
|
91
|
+
value = param.processKRateParam(1, 0.25);
|
|
92
|
+
EXPECT_FLOAT_EQ(value, 1.0);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
TEST_F(AudioParamTest, SetTargetAtTime) {
|
|
96
|
+
AudioParam param = AudioParam(0.0, 0.0, 1.0, context.get());
|
|
97
|
+
param.setTargetAtTime(1.0, 0.1, 0.1);
|
|
98
|
+
// value(time) = target + (startValue - target) * exp(-(time -
|
|
99
|
+
// startTime)/timeConstant) value(time) = 1.0 + (0.0 - 1.0) * exp(-time/0.1)
|
|
100
|
+
float value = param.processKRateParam(1, 0.05);
|
|
101
|
+
EXPECT_FLOAT_EQ(value, 0.0);
|
|
102
|
+
|
|
103
|
+
value = param.processKRateParam(1, 0.1);
|
|
104
|
+
EXPECT_FLOAT_EQ(value, 0.0);
|
|
105
|
+
|
|
106
|
+
value = param.processKRateParam(1, 0.15);
|
|
107
|
+
EXPECT_NEAR(value, 0.393469, 1e-5);
|
|
108
|
+
|
|
109
|
+
value = param.processKRateParam(1, 0.2);
|
|
110
|
+
EXPECT_NEAR(value, 0.632120, 1e-5);
|
|
111
|
+
|
|
112
|
+
value = param.processKRateParam(1, 0.25);
|
|
113
|
+
EXPECT_NEAR(value, 0.776869, 1e-5);
|
|
114
|
+
|
|
115
|
+
value = param.processKRateParam(1, 0.5);
|
|
116
|
+
EXPECT_NEAR(value, 0.981684, 1e-5);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
TEST_F(AudioParamTest, SetValueCurveAtTime) {
|
|
120
|
+
AudioParam param = AudioParam(0.0, 0.0, 1.0, context.get());
|
|
121
|
+
param.setValue(0.5);
|
|
122
|
+
auto curve = std::make_shared<std::vector<float>>(
|
|
123
|
+
std::vector<float>{0.1, 0.4, 0.2, 0.8, 0.5});
|
|
124
|
+
param.setValueCurveAtTime(curve, curve->size(), 0.1, 0.2);
|
|
125
|
+
// 5 elements over 0.2s => each element is 0.04s apart
|
|
126
|
+
|
|
127
|
+
float value = param.processKRateParam(1, 0.05);
|
|
128
|
+
EXPECT_FLOAT_EQ(value, 0.0);
|
|
129
|
+
|
|
130
|
+
value = param.processKRateParam(1, 0.1);
|
|
131
|
+
EXPECT_FLOAT_EQ(value, 0.1);
|
|
132
|
+
|
|
133
|
+
// k = 4/0.2 * (0.14 - 0.1) = 0.8 -> floor is 0
|
|
134
|
+
// linear interpolation between 0 and 1 -> 0.1 + (0.4 - 0.1) * 0.8 = 0.34
|
|
135
|
+
value = param.processKRateParam(1, 0.14);
|
|
136
|
+
EXPECT_FLOAT_EQ(value, 0.34);
|
|
137
|
+
|
|
138
|
+
// k = 4/0.2 * (0.18 - 0.1) = 1.6 -> floor is 1
|
|
139
|
+
// linear interpolation between 1 and 2 -> 0.4 + (0.2 - 0.4) * 0.6 = 0.28
|
|
140
|
+
value = param.processKRateParam(1, 0.18);
|
|
141
|
+
EXPECT_FLOAT_EQ(value, 0.28);
|
|
142
|
+
|
|
143
|
+
// k = 4/0.2 * (0.22 - 0.1) = 2.4 -> floor is 2
|
|
144
|
+
// linear interpolation between 2 and 3 -> 0.2 + (0.8 - 0.2) * 0.4 = 0.44
|
|
145
|
+
value = param.processKRateParam(1, 0.22);
|
|
146
|
+
EXPECT_FLOAT_EQ(value, 0.44);
|
|
147
|
+
|
|
148
|
+
// k = 4/0.2 * (0.26 - 0.1) = 3.2 -> floor is 3
|
|
149
|
+
// linear interpolation between 3 and 4 -> 0.8 + (0.5 - 0.8) * 0.2 = 0.74
|
|
150
|
+
value = param.processKRateParam(1, 0.26);
|
|
151
|
+
EXPECT_FLOAT_EQ(value, 0.74);
|
|
152
|
+
|
|
153
|
+
// k = 4/0.2 * (0.3 - 0.1) = 4.0 -> floor is 4
|
|
154
|
+
// at or after end of curve -> last value
|
|
155
|
+
value = param.processKRateParam(1, 0.35);
|
|
156
|
+
EXPECT_FLOAT_EQ(value, 0.5);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
TEST_F(AudioParamTest, CancelScheduledValues) {
|
|
160
|
+
AudioParam param = AudioParam(0.0, 0.0, 1.0, context.get());
|
|
161
|
+
param.setValueAtTime(0.8, 0.1);
|
|
162
|
+
param.setValueAtTime(0.3, 0.2);
|
|
163
|
+
param.linearRampToValueAtTime(1.0, 0.4);
|
|
164
|
+
param.cancelScheduledValues(0.15);
|
|
165
|
+
|
|
166
|
+
float value = param.processKRateParam(1, 0.05);
|
|
167
|
+
EXPECT_FLOAT_EQ(value, 0.0);
|
|
168
|
+
|
|
169
|
+
value = param.processKRateParam(1, 0.1);
|
|
170
|
+
EXPECT_FLOAT_EQ(value, 0.8);
|
|
171
|
+
|
|
172
|
+
value = param.processKRateParam(1, 0.15);
|
|
173
|
+
EXPECT_FLOAT_EQ(value, 0.8);
|
|
174
|
+
|
|
175
|
+
// Events after cancel time are removed -> stays at last value
|
|
176
|
+
value = param.processKRateParam(1, 0.2);
|
|
177
|
+
EXPECT_FLOAT_EQ(value, 0.8);
|
|
178
|
+
|
|
179
|
+
value = param.processKRateParam(1, 0.25);
|
|
180
|
+
EXPECT_FLOAT_EQ(value, 0.8);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
TEST_F(AudioParamTest, CancelAndHoldAtTime) {
|
|
184
|
+
AudioParam param = AudioParam(0.0, 0.0, 1.0, context.get());
|
|
185
|
+
param.setValueAtTime(0.8, 0.1);
|
|
186
|
+
param.linearRampToValueAtTime(1.0, 0.2);
|
|
187
|
+
param.cancelAndHoldAtTime(0.15);
|
|
188
|
+
|
|
189
|
+
float value = param.processKRateParam(1, 0.05);
|
|
190
|
+
EXPECT_FLOAT_EQ(value, 0.0);
|
|
191
|
+
|
|
192
|
+
value = param.processKRateParam(1, 0.1);
|
|
193
|
+
EXPECT_FLOAT_EQ(value, 0.8);
|
|
194
|
+
|
|
195
|
+
value = param.processKRateParam(1, 0.15);
|
|
196
|
+
EXPECT_FLOAT_EQ(value, 0.9);
|
|
197
|
+
|
|
198
|
+
// Events after cancel time are removed -> stays at last value
|
|
199
|
+
value = param.processKRateParam(1, 0.2);
|
|
200
|
+
EXPECT_FLOAT_EQ(value, 0.9);
|
|
201
|
+
|
|
202
|
+
value = param.processKRateParam(1, 0.25);
|
|
203
|
+
EXPECT_FLOAT_EQ(value, 0.9);
|
|
204
|
+
}
|
|
@@ -21,11 +21,17 @@ enable_testing()
|
|
|
21
21
|
file(GLOB_RECURSE RNAUDIOAPI_SRC
|
|
22
22
|
CONFIGURE_DEPENDS
|
|
23
23
|
"${ROOT}/node_modules/react-native-audio-api/common/cpp/audioapi/*.cpp"
|
|
24
|
-
"${ROOT}/node_modules/react-native-audio-api/android/src/main/cpp/audioapi/android/core/AudioDecoder.cpp"
|
|
24
|
+
"${ROOT}/node_modules/react-native-audio-api/android/src/main/cpp/audioapi/android/core/utils/AudioDecoder.cpp"
|
|
25
25
|
)
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
# exclude HostObjects from tests
|
|
28
|
+
list(FILTER RNAUDIOAPI_SRC EXCLUDE REGEX ".*/audioapi/HostObjects/.*\\.cpp$")
|
|
29
|
+
|
|
30
|
+
list(REMOVE_ITEM RNAUDIOAPI_SRC
|
|
28
31
|
"${ROOT}/node_modules/react-native-audio-api/common/cpp/audioapi/core/AudioContext.cpp"
|
|
32
|
+
"${ROOT}/node_modules/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletNode.cpp"
|
|
33
|
+
"${ROOT}/node_modules/react-native-audio-api/common/cpp/audioapi/core/effects/WorkletProcessingNode.cpp"
|
|
34
|
+
"${ROOT}/node_modules/react-native-audio-api/common/cpp/audioapi/core/sources/WorkletSourceNode.cpp"
|
|
29
35
|
"${ROOT}/node_modules/react-native-audio-api/common/cpp/audioapi/core/sources/StreamerNode.cpp"
|
|
30
36
|
"${ROOT}/node_modules/react-native-audio-api/common/cpp/audioapi/core/sources/StreamerNode.h"
|
|
31
37
|
"${ROOT}/node_modules/react-native-audio-api/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.cpp"
|
|
@@ -56,14 +62,17 @@ target_include_directories(rnaudioapi PUBLIC
|
|
|
56
62
|
target_include_directories(rnaudioapi_libs PUBLIC
|
|
57
63
|
${ROOT}/packages/react-native-audio-api/common/cpp
|
|
58
64
|
)
|
|
59
|
-
|
|
60
65
|
add_executable(
|
|
61
66
|
tests
|
|
62
67
|
OscillatorTest.cpp
|
|
63
68
|
GainTest.cpp
|
|
69
|
+
AudioParamTest.cpp
|
|
70
|
+
StereoPannerTest.cpp
|
|
64
71
|
)
|
|
65
72
|
|
|
66
73
|
add_compile_definitions(AUDIO_API_TEST_SUITE)
|
|
74
|
+
add_compile_definitions(RN_AUDIO_API_ENABLE_WORKLETS=0)
|
|
75
|
+
add_compile_definitions(RN_AUDIO_API_TEST=1)
|
|
67
76
|
|
|
68
77
|
target_link_libraries(tests
|
|
69
78
|
rnaudioapi
|
|
@@ -73,4 +82,4 @@ target_link_libraries(tests
|
|
|
73
82
|
)
|
|
74
83
|
|
|
75
84
|
include(GoogleTest)
|
|
76
|
-
gtest_discover_tests(tests)
|
|
85
|
+
gtest_discover_tests(tests)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#include <audioapi/core/OfflineAudioContext.h>
|
|
2
2
|
#include <audioapi/core/effects/GainNode.h>
|
|
3
|
+
#include <audioapi/core/utils/worklets/SafeIncludes.h>
|
|
3
4
|
#include <audioapi/utils/AudioArray.h>
|
|
4
5
|
#include <audioapi/utils/AudioBus.h>
|
|
5
6
|
#include <gtest/gtest.h>
|
|
@@ -14,7 +15,7 @@ class GainTest : public ::testing::Test {
|
|
|
14
15
|
void SetUp() override {
|
|
15
16
|
eventRegistry = std::make_shared<MockAudioEventHandlerRegistry>();
|
|
16
17
|
context = std::make_unique<audioapi::OfflineAudioContext>(
|
|
17
|
-
2, 5 * sampleRate, sampleRate, eventRegistry);
|
|
18
|
+
2, 5 * sampleRate, sampleRate, eventRegistry, RuntimeRegistry{});
|
|
18
19
|
}
|
|
19
20
|
};
|
|
20
21
|
|
|
@@ -27,10 +28,10 @@ class TestableGainNode : public audioapi::GainNode {
|
|
|
27
28
|
getGainParam()->setValue(value);
|
|
28
29
|
}
|
|
29
30
|
|
|
30
|
-
|
|
31
|
+
std::shared_ptr<audioapi::AudioBus> processNode(
|
|
31
32
|
const std::shared_ptr<audioapi::AudioBus> &processingBus,
|
|
32
33
|
int framesToProcess) override {
|
|
33
|
-
audioapi::GainNode::processNode(processingBus, framesToProcess);
|
|
34
|
+
return audioapi::GainNode::processNode(processingBus, framesToProcess);
|
|
34
35
|
}
|
|
35
36
|
};
|
|
36
37
|
|
|
@@ -51,9 +52,9 @@ TEST_F(GainTest, GainModulatesVolumeCorrectly) {
|
|
|
51
52
|
bus->getChannel(0)->getData()[i] = i + 1;
|
|
52
53
|
}
|
|
53
54
|
|
|
54
|
-
gainNode->processNode(bus, FRAMES_TO_PROCESS);
|
|
55
|
-
for (size_t i = 0; i <
|
|
56
|
-
EXPECT_FLOAT_EQ((*
|
|
55
|
+
auto resultBus = gainNode->processNode(bus, FRAMES_TO_PROCESS);
|
|
56
|
+
for (size_t i = 0; i < FRAMES_TO_PROCESS; ++i) {
|
|
57
|
+
EXPECT_FLOAT_EQ((*resultBus->getChannel(0))[i], (i + 1) * GAIN_VALUE);
|
|
57
58
|
}
|
|
58
59
|
}
|
|
59
60
|
|
|
@@ -70,9 +71,9 @@ TEST_F(GainTest, GainModulatesVolumeCorrectlyMultiChannel) {
|
|
|
70
71
|
bus->getChannel(1)->getData()[i] = -i - 1;
|
|
71
72
|
}
|
|
72
73
|
|
|
73
|
-
gainNode->processNode(bus, FRAMES_TO_PROCESS);
|
|
74
|
-
for (size_t i = 0; i <
|
|
75
|
-
EXPECT_FLOAT_EQ((*
|
|
76
|
-
EXPECT_FLOAT_EQ((*
|
|
74
|
+
auto resultBus = gainNode->processNode(bus, FRAMES_TO_PROCESS);
|
|
75
|
+
for (size_t i = 0; i < FRAMES_TO_PROCESS; ++i) {
|
|
76
|
+
EXPECT_FLOAT_EQ((*resultBus->getChannel(0))[i], (i + 1) * GAIN_VALUE);
|
|
77
|
+
EXPECT_FLOAT_EQ((*resultBus->getChannel(1))[i], (-i - 1) * GAIN_VALUE);
|
|
77
78
|
}
|
|
78
79
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#include <audioapi/core/OfflineAudioContext.h>
|
|
2
2
|
#include <audioapi/core/sources/OscillatorNode.h>
|
|
3
|
+
#include <audioapi/core/utils/worklets/SafeIncludes.h>
|
|
3
4
|
#include <gtest/gtest.h>
|
|
4
5
|
#include "MockAudioEventHandlerRegistry.h"
|
|
5
6
|
|
|
@@ -12,7 +13,7 @@ class OscillatorTest : public ::testing::Test {
|
|
|
12
13
|
void SetUp() override {
|
|
13
14
|
eventRegistry = std::make_shared<MockAudioEventHandlerRegistry>();
|
|
14
15
|
context = std::make_unique<audioapi::OfflineAudioContext>(
|
|
15
|
-
2, 5 * sampleRate, sampleRate, eventRegistry);
|
|
16
|
+
2, 5 * sampleRate, sampleRate, eventRegistry, RuntimeRegistry{});
|
|
16
17
|
}
|
|
17
18
|
};
|
|
18
19
|
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
#include <audioapi/core/OfflineAudioContext.h>
|
|
2
|
+
#include <audioapi/core/effects/StereoPannerNode.h>
|
|
3
|
+
#include <audioapi/core/utils/worklets/SafeIncludes.h>
|
|
4
|
+
#include <audioapi/utils/AudioArray.h>
|
|
5
|
+
#include <audioapi/utils/AudioBus.h>
|
|
6
|
+
#include <gtest/gtest.h>
|
|
7
|
+
#include "MockAudioEventHandlerRegistry.h"
|
|
8
|
+
|
|
9
|
+
using namespace audioapi;
|
|
10
|
+
|
|
11
|
+
class StereoPannerTest : public ::testing::Test {
|
|
12
|
+
protected:
|
|
13
|
+
std::shared_ptr<IAudioEventHandlerRegistry> eventRegistry;
|
|
14
|
+
std::unique_ptr<OfflineAudioContext> context;
|
|
15
|
+
static constexpr int sampleRate = 44100;
|
|
16
|
+
|
|
17
|
+
void SetUp() override {
|
|
18
|
+
eventRegistry = std::make_shared<MockAudioEventHandlerRegistry>();
|
|
19
|
+
context = std::make_unique<OfflineAudioContext>(
|
|
20
|
+
2, 5 * sampleRate, sampleRate, eventRegistry, RuntimeRegistry{});
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
class TestableStereoPannerNode : public StereoPannerNode {
|
|
25
|
+
public:
|
|
26
|
+
explicit TestableStereoPannerNode(BaseAudioContext *context)
|
|
27
|
+
: StereoPannerNode(context) {}
|
|
28
|
+
|
|
29
|
+
void setPanParam(float value) {
|
|
30
|
+
getPanParam()->setValue(value);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
std::shared_ptr<AudioBus> processNode(
|
|
34
|
+
const std::shared_ptr<AudioBus> &processingBus,
|
|
35
|
+
int framesToProcess) override {
|
|
36
|
+
return StereoPannerNode::processNode(processingBus, framesToProcess);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
TEST_F(StereoPannerTest, StereoPannerCanBeCreated) {
|
|
41
|
+
auto panner = context->createStereoPanner();
|
|
42
|
+
ASSERT_NE(panner, nullptr);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
TEST_F(StereoPannerTest, PanModulatesInputMonoCorrectly) {
|
|
46
|
+
static constexpr float PAN_VALUE = 0.5;
|
|
47
|
+
static constexpr int FRAMES_TO_PROCESS = 4;
|
|
48
|
+
auto panNode = std::make_shared<TestableStereoPannerNode>(context.get());
|
|
49
|
+
panNode->setPanParam(PAN_VALUE);
|
|
50
|
+
|
|
51
|
+
auto bus =
|
|
52
|
+
std::make_shared<audioapi::AudioBus>(FRAMES_TO_PROCESS, 1, sampleRate);
|
|
53
|
+
for (size_t i = 0; i < bus->getSize(); ++i) {
|
|
54
|
+
(*bus->getChannelByType(AudioBus::ChannelLeft))[i] = i + 1;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
auto resultBus = panNode->processNode(bus, FRAMES_TO_PROCESS);
|
|
58
|
+
// x = (0.5 + 1) / 2 = 0.75
|
|
59
|
+
// gainL = cos(x * (π / 2)) = cos(0.75 * (π / 2)) = 0.38268343236508984
|
|
60
|
+
// gainR = sin(x * (π / 2)) = sin(0.75 * (π / 2)) = 0.9238795325112867
|
|
61
|
+
for (size_t i = 0; i < FRAMES_TO_PROCESS; ++i) {
|
|
62
|
+
EXPECT_NEAR(
|
|
63
|
+
(*resultBus->getChannelByType(AudioBus::ChannelLeft))[i],
|
|
64
|
+
(i + 1) * 0.38268343236508984,
|
|
65
|
+
1e-4);
|
|
66
|
+
EXPECT_NEAR(
|
|
67
|
+
(*resultBus->getChannelByType(AudioBus::ChannelRight))[i],
|
|
68
|
+
(i + 1) * 0.9238795325112867,
|
|
69
|
+
1e-4);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
TEST_F(StereoPannerTest, PanModulatesInputStereoCorrectlyWithNegativePan) {
|
|
74
|
+
static constexpr float PAN_VALUE = -0.5;
|
|
75
|
+
static constexpr int FRAMES_TO_PROCESS = 4;
|
|
76
|
+
auto panNode = std::make_shared<TestableStereoPannerNode>(context.get());
|
|
77
|
+
panNode->setPanParam(PAN_VALUE);
|
|
78
|
+
|
|
79
|
+
auto bus =
|
|
80
|
+
std::make_shared<audioapi::AudioBus>(FRAMES_TO_PROCESS, 2, sampleRate);
|
|
81
|
+
for (size_t i = 0; i < bus->getSize(); ++i) {
|
|
82
|
+
(*bus->getChannelByType(AudioBus::ChannelLeft))[i] = i + 1;
|
|
83
|
+
(*bus->getChannelByType(AudioBus::ChannelRight))[i] = i + 1;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
auto resultBus = panNode->processNode(bus, FRAMES_TO_PROCESS);
|
|
87
|
+
// x = -0.5 + 1 = 0.5
|
|
88
|
+
// gainL = cos(x * (π / 2)) = cos(0.5 * (π / 2)) = 0.7071067811865476
|
|
89
|
+
// gainR = sin(x * (π / 2)) = sin(0.5 * (π / 2)) = 0.7071067811865476
|
|
90
|
+
for (size_t i = 0; i < FRAMES_TO_PROCESS; ++i) {
|
|
91
|
+
EXPECT_NEAR(
|
|
92
|
+
(*resultBus->getChannelByType(AudioBus::ChannelLeft))[i],
|
|
93
|
+
(i + 1) + (i + 1) * 0.7071067811865476,
|
|
94
|
+
1e-4);
|
|
95
|
+
EXPECT_NEAR(
|
|
96
|
+
(*resultBus->getChannelByType(AudioBus::ChannelRight))[i],
|
|
97
|
+
(i + 1) * 0.7071067811865476,
|
|
98
|
+
1e-4);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
TEST_F(StereoPannerTest, PanModulatesInputStereoCorrectlyWithPositivePan) {
|
|
103
|
+
static constexpr float PAN_VALUE = 0.75;
|
|
104
|
+
static constexpr int FRAMES_TO_PROCESS = 4;
|
|
105
|
+
auto panNode = std::make_shared<TestableStereoPannerNode>(context.get());
|
|
106
|
+
panNode->setPanParam(PAN_VALUE);
|
|
107
|
+
|
|
108
|
+
auto bus =
|
|
109
|
+
std::make_shared<audioapi::AudioBus>(FRAMES_TO_PROCESS, 2, sampleRate);
|
|
110
|
+
for (size_t i = 0; i < bus->getSize(); ++i) {
|
|
111
|
+
(*bus->getChannelByType(AudioBus::ChannelLeft))[i] = i + 1;
|
|
112
|
+
(*bus->getChannelByType(AudioBus::ChannelRight))[i] = i + 1;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
auto resultBus = panNode->processNode(bus, FRAMES_TO_PROCESS);
|
|
116
|
+
// x = 0.75
|
|
117
|
+
// gainL = cos(x * (π / 2)) = cos(0.75 * (π / 2)) = 0.38268343236508984
|
|
118
|
+
// gainR = sin(x * (π / 2)) = sin(0.75 * (π / 2)) = 0.9238795325112867
|
|
119
|
+
for (size_t i = 0; i < FRAMES_TO_PROCESS; ++i) {
|
|
120
|
+
EXPECT_NEAR(
|
|
121
|
+
(*resultBus->getChannelByType(AudioBus::ChannelLeft))[i],
|
|
122
|
+
(i + 1) * 0.38268343236508984,
|
|
123
|
+
1e-4);
|
|
124
|
+
EXPECT_NEAR(
|
|
125
|
+
(*resultBus->getChannelByType(AudioBus::ChannelRight))[i],
|
|
126
|
+
(i + 1) + (i + 1) * 0.9238795325112867,
|
|
127
|
+
1e-4);
|
|
128
|
+
}
|
|
129
|
+
}
|