react-native-audio-api 0.10.0-nightly-e16d7ff-20251030 → 0.11.0-alpha.1
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 +11 -16
- package/android/build.gradle +3 -33
- package/android/src/main/cpp/audioapi/CMakeLists.txt +0 -6
- package/android/src/main/cpp/audioapi/android/AudioAPIModule.cpp +0 -5
- package/android/src/main/cpp/audioapi/android/AudioAPIModule.h +0 -1
- package/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.cpp +142 -28
- package/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.h +40 -13
- package/android/src/main/cpp/audioapi/android/core/AudioPlayer.cpp +2 -4
- package/android/src/main/cpp/audioapi/android/core/NativeAudioRecorder.hpp +9 -9
- package/android/src/main/cpp/audioapi/android/core/utils/AndroidFileWriterBackend.h +37 -0
- package/android/src/main/cpp/audioapi/android/core/utils/AndroidRecorderCallback.cpp +187 -0
- package/android/src/main/cpp/audioapi/android/core/utils/AndroidRecorderCallback.h +57 -0
- package/android/src/main/cpp/audioapi/android/core/utils/AudioDecoder.cpp +0 -6
- package/android/src/main/cpp/audioapi/android/core/utils/FileUtils.h +34 -0
- package/android/src/main/cpp/audioapi/android/core/utils/FileUtilts.cpp +133 -0
- package/android/src/main/cpp/audioapi/android/core/utils/MiniaudioImplementation.cpp +3 -0
- package/android/src/main/cpp/audioapi/android/core/utils/ffmpegBackend/FFmpegAudioFileOptions.cpp +154 -0
- package/android/src/main/cpp/audioapi/android/core/utils/ffmpegBackend/FFmpegAudioFileOptions.h +41 -0
- package/android/src/main/cpp/audioapi/android/core/utils/ffmpegBackend/FFmpegFileWriter.cpp +429 -0
- package/android/src/main/cpp/audioapi/android/core/utils/ffmpegBackend/FFmpegFileWriter.h +113 -0
- package/android/src/main/cpp/audioapi/android/core/utils/miniaudioBackend/MiniAudioFileOptions.cpp +47 -0
- package/android/src/main/cpp/audioapi/android/core/utils/miniaudioBackend/MiniAudioFileOptions.h +28 -0
- package/android/src/main/cpp/audioapi/android/core/utils/miniaudioBackend/MiniAudioFileWriter.cpp +269 -0
- package/android/src/main/cpp/audioapi/android/core/utils/miniaudioBackend/MiniAudioFileWriter.h +47 -0
- package/android/src/main/cpp/audioapi/android/system/NativeFileInfo.hpp +31 -0
- package/android/src/main/java/com/swmansion/audioapi/AudioAPIModule.kt +3 -29
- package/android/src/main/java/com/swmansion/audioapi/system/AudioFocusListener.kt +9 -21
- package/android/src/main/java/com/swmansion/audioapi/system/LockScreenManager.kt +6 -27
- package/android/src/main/java/com/swmansion/audioapi/system/MediaNotificationManager.kt +0 -11
- package/android/src/main/java/com/swmansion/audioapi/system/NativeFileInfo.kt +18 -0
- package/android/src/main/jniLibs/arm64-v8a/libavcodec.so +0 -0
- package/android/src/main/jniLibs/arm64-v8a/libavformat.so +0 -0
- package/android/src/main/jniLibs/arm64-v8a/libavutil.so +0 -0
- package/android/src/main/jniLibs/arm64-v8a/libswresample.so +0 -0
- package/android/src/main/jniLibs/armeabi-v7a/libavcodec.so +0 -0
- package/android/src/main/jniLibs/armeabi-v7a/libavformat.so +0 -0
- package/android/src/main/jniLibs/armeabi-v7a/libavutil.so +0 -0
- package/android/src/main/jniLibs/armeabi-v7a/libswresample.so +0 -0
- package/android/src/main/jniLibs/x86/libavcodec.so +0 -0
- package/android/src/main/jniLibs/x86/libavformat.so +0 -0
- package/android/src/main/jniLibs/x86/libavutil.so +0 -0
- package/android/src/main/jniLibs/x86/libswresample.so +0 -0
- package/android/src/main/jniLibs/x86_64/libavcodec.so +0 -0
- package/android/src/main/jniLibs/x86_64/libavformat.so +0 -0
- package/android/src/main/jniLibs/x86_64/libavutil.so +0 -0
- package/android/src/main/jniLibs/x86_64/libswresample.so +0 -0
- package/common/cpp/audioapi/AudioAPIModuleInstaller.h +2 -30
- package/common/cpp/audioapi/HostObjects/BaseAudioContextHostObject.cpp +0 -18
- package/common/cpp/audioapi/HostObjects/BaseAudioContextHostObject.h +0 -1
- package/common/cpp/audioapi/HostObjects/effects/BiquadFilterNodeHostObject.cpp +1 -1
- package/common/cpp/audioapi/HostObjects/inputs/AudioRecorderHostObject.cpp +97 -18
- package/common/cpp/audioapi/HostObjects/inputs/AudioRecorderHostObject.h +18 -6
- package/common/cpp/audioapi/core/AudioNode.h +2 -3
- package/common/cpp/audioapi/core/AudioParam.cpp +2 -2
- package/common/cpp/audioapi/core/BaseAudioContext.cpp +0 -10
- package/common/cpp/audioapi/core/BaseAudioContext.h +0 -2
- package/common/cpp/audioapi/core/effects/BiquadFilterNode.cpp +32 -69
- package/common/cpp/audioapi/core/effects/BiquadFilterNode.h +1 -37
- package/common/cpp/audioapi/core/inputs/AudioRecorder.cpp +36 -82
- package/common/cpp/audioapi/core/inputs/AudioRecorder.h +52 -31
- package/common/cpp/audioapi/core/sources/StreamerNode.cpp +58 -59
- package/common/cpp/audioapi/core/sources/StreamerNode.h +8 -37
- package/common/cpp/audioapi/core/utils/AudioNodeManager.cpp +0 -5
- package/common/cpp/audioapi/core/utils/Constants.h +1 -2
- package/common/cpp/audioapi/core/utils/worklets/SafeIncludes.h +10 -0
- package/common/cpp/audioapi/dsp/AudioUtils.cpp +1 -1
- package/common/cpp/audioapi/dsp/FFT.cpp +26 -0
- package/common/cpp/audioapi/dsp/FFT.h +2 -26
- package/common/cpp/audioapi/external/arm64-v8a/libcrypto.a +0 -0
- package/common/cpp/audioapi/external/arm64-v8a/libogg.a +0 -0
- package/common/cpp/audioapi/external/arm64-v8a/libopus.a +0 -0
- package/common/cpp/audioapi/external/arm64-v8a/libopusfile.a +0 -0
- package/common/cpp/audioapi/external/arm64-v8a/libssl.a +0 -0
- package/common/cpp/audioapi/external/arm64-v8a/libvorbis.a +0 -0
- package/common/cpp/audioapi/external/arm64-v8a/libvorbisenc.a +0 -0
- package/common/cpp/audioapi/external/arm64-v8a/libvorbisfile.a +0 -0
- package/common/cpp/audioapi/external/armeabi-v7a/libcrypto.a +0 -0
- package/common/cpp/audioapi/external/armeabi-v7a/libogg.a +0 -0
- package/common/cpp/audioapi/external/armeabi-v7a/libopus.a +0 -0
- package/common/cpp/audioapi/external/armeabi-v7a/libopusfile.a +0 -0
- package/common/cpp/audioapi/external/armeabi-v7a/libssl.a +0 -0
- package/common/cpp/audioapi/external/armeabi-v7a/libvorbis.a +0 -0
- package/common/cpp/audioapi/external/armeabi-v7a/libvorbisenc.a +0 -0
- package/common/cpp/audioapi/external/armeabi-v7a/libvorbisfile.a +0 -0
- package/common/cpp/audioapi/external/ffmpeg_include/libavcodec/avcodec.h +2 -2
- package/common/cpp/audioapi/external/ffmpeg_include/libavcodec/codec.h +1 -1
- package/common/cpp/audioapi/external/ffmpeg_include/libavcodec/codec_desc.h +1 -1
- package/common/cpp/audioapi/external/ffmpeg_include/libavcodec/codec_id.h +1 -1
- package/common/cpp/audioapi/external/ffmpeg_include/libavcodec/codec_par.h +1 -1
- package/common/cpp/audioapi/external/ffmpeg_include/libavformat/avformat.h +2 -2
- package/common/cpp/audioapi/external/ffmpeg_include/libavutil/avutil.h +2 -2
- package/common/cpp/audioapi/external/iphoneos/libcrypto.a +0 -0
- package/common/cpp/audioapi/external/iphoneos/libogg.a +0 -0
- package/common/cpp/audioapi/external/iphoneos/libopus.a +0 -0
- package/common/cpp/audioapi/external/iphoneos/libopusfile.a +0 -0
- package/common/cpp/audioapi/external/iphoneos/libssl.a +0 -0
- package/common/cpp/audioapi/external/iphoneos/libvorbis.a +0 -0
- package/common/cpp/audioapi/external/iphoneos/libvorbisenc.a +0 -0
- package/common/cpp/audioapi/external/iphoneos/libvorbisfile.a +0 -0
- package/common/cpp/audioapi/external/iphonesimulator/libcrypto.a +0 -0
- package/common/cpp/audioapi/external/iphonesimulator/libogg.a +0 -0
- package/common/cpp/audioapi/external/iphonesimulator/libopus.a +0 -0
- package/common/cpp/audioapi/external/iphonesimulator/libopusfile.a +0 -0
- package/common/cpp/audioapi/external/iphonesimulator/libssl.a +0 -0
- package/common/cpp/audioapi/external/iphonesimulator/libvorbis.a +0 -0
- package/common/cpp/audioapi/external/iphonesimulator/libvorbisenc.a +0 -0
- package/common/cpp/audioapi/external/iphonesimulator/libvorbisfile.a +0 -0
- package/common/cpp/audioapi/external/libavcodec.xcframework/Info.plist +44 -0
- package/common/cpp/audioapi/external/libavcodec.xcframework/ios-arm64/libavcodec.framework/Info.plist +1 -0
- package/common/cpp/audioapi/external/libavcodec.xcframework/ios-arm64/libavcodec.framework/libavcodec +0 -0
- package/common/cpp/audioapi/external/libavcodec.xcframework/ios-arm64_x86_64-simulator/libavcodec.framework/Info.plist +1 -0
- package/common/cpp/audioapi/external/libavcodec.xcframework/ios-arm64_x86_64-simulator/libavcodec.framework/libavcodec +0 -0
- package/common/cpp/audioapi/external/libavformat.xcframework/Info.plist +44 -0
- package/common/cpp/audioapi/external/libavformat.xcframework/ios-arm64/libavformat.framework/Info.plist +1 -0
- package/common/cpp/audioapi/external/libavformat.xcframework/ios-arm64/libavformat.framework/libavformat +0 -0
- package/common/cpp/audioapi/external/libavformat.xcframework/ios-arm64_x86_64-simulator/libavformat.framework/Info.plist +1 -0
- package/common/cpp/audioapi/external/libavformat.xcframework/ios-arm64_x86_64-simulator/libavformat.framework/libavformat +0 -0
- package/common/cpp/audioapi/external/libavutil.xcframework/Info.plist +44 -0
- package/common/cpp/audioapi/external/libavutil.xcframework/ios-arm64/libavutil.framework/Info.plist +1 -0
- package/common/cpp/audioapi/external/libavutil.xcframework/ios-arm64/libavutil.framework/libavutil +0 -0
- package/common/cpp/audioapi/external/libavutil.xcframework/ios-arm64_x86_64-simulator/libavutil.framework/Info.plist +1 -0
- package/common/cpp/audioapi/external/libavutil.xcframework/ios-arm64_x86_64-simulator/libavutil.framework/libavutil +0 -0
- package/common/cpp/audioapi/external/libswresample.xcframework/Info.plist +44 -0
- package/common/cpp/audioapi/external/libswresample.xcframework/ios-arm64/libswresample.framework/Info.plist +1 -0
- package/common/cpp/audioapi/external/libswresample.xcframework/ios-arm64/libswresample.framework/libswresample +0 -0
- package/common/cpp/audioapi/external/libswresample.xcframework/ios-arm64_x86_64-simulator/libswresample.framework/Info.plist +1 -0
- package/common/cpp/audioapi/external/libswresample.xcframework/ios-arm64_x86_64-simulator/libswresample.framework/libswresample +0 -0
- package/common/cpp/audioapi/external/x86/libcrypto.a +0 -0
- package/common/cpp/audioapi/external/x86/libogg.a +0 -0
- package/common/cpp/audioapi/external/x86/libopus.a +0 -0
- package/common/cpp/audioapi/external/x86/libopusfile.a +0 -0
- package/common/cpp/audioapi/external/x86/libssl.a +0 -0
- package/common/cpp/audioapi/external/x86/libvorbis.a +0 -0
- package/common/cpp/audioapi/external/x86/libvorbisenc.a +0 -0
- package/common/cpp/audioapi/external/x86/libvorbisfile.a +0 -0
- package/common/cpp/audioapi/external/x86_64/libcrypto.a +0 -0
- package/common/cpp/audioapi/external/x86_64/libogg.a +0 -0
- package/common/cpp/audioapi/external/x86_64/libopus.a +0 -0
- package/common/cpp/audioapi/external/x86_64/libopusfile.a +0 -0
- package/common/cpp/audioapi/external/x86_64/libssl.a +0 -0
- package/common/cpp/audioapi/external/x86_64/libvorbis.a +0 -0
- package/common/cpp/audioapi/external/x86_64/libvorbisenc.a +0 -0
- package/common/cpp/audioapi/external/x86_64/libvorbisfile.a +0 -0
- package/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.cpp +3 -2
- package/common/cpp/audioapi/libs/ffmpeg/INSTRUCTIONS.md +32 -0
- package/common/cpp/audioapi/libs/ffmpeg/create_xcframework.sh +111 -0
- package/common/cpp/audioapi/libs/ffmpeg/ffmpeg_setup.sh +391 -0
- package/common/cpp/audioapi/utils/AudioBus.cpp +0 -28
- package/common/cpp/audioapi/utils/AudioBus.h +0 -3
- package/common/cpp/audioapi/utils/ThreadPool.hpp +1 -59
- package/common/cpp/test/CMakeLists.txt +14 -19
- package/ios/audioapi/ios/AudioAPIModule.h +1 -2
- package/ios/audioapi/ios/AudioAPIModule.mm +0 -2
- package/ios/audioapi/ios/core/IOSAudioFileOptions.h +36 -0
- package/ios/audioapi/ios/core/IOSAudioFileOptions.mm +140 -0
- package/ios/audioapi/ios/core/IOSAudioFileWriter.h +51 -0
- package/ios/audioapi/ios/core/IOSAudioFileWriter.mm +223 -0
- package/ios/audioapi/ios/core/IOSAudioRecorder.h +28 -10
- package/ios/audioapi/ios/core/IOSAudioRecorder.mm +117 -30
- package/ios/audioapi/ios/core/IOSRecorderCallback.h +57 -0
- package/ios/audioapi/ios/core/IOSRecorderCallback.mm +189 -0
- package/ios/audioapi/ios/core/NativeAudioRecorder.h +4 -9
- package/ios/audioapi/ios/core/NativeAudioRecorder.m +29 -71
- package/ios/audioapi/ios/core/utils/AudioDecoder.mm +1 -0
- package/ios/audioapi/ios/system/AudioEngine.mm +3 -3
- package/ios/audioapi/ios/system/AudioSessionManager.mm +0 -9
- package/ios/audioapi/ios/system/LockScreenManager.h +1 -0
- package/ios/audioapi/ios/system/LockScreenManager.mm +19 -6
- package/lib/commonjs/api.js +76 -141
- package/lib/commonjs/api.js.map +1 -1
- package/lib/commonjs/api.web.js +0 -8
- package/lib/commonjs/api.web.js.map +1 -1
- package/lib/commonjs/core/AudioContext.js +1 -1
- package/lib/commonjs/core/AudioContext.js.map +1 -1
- package/lib/commonjs/core/AudioRecorder.js +171 -13
- package/lib/commonjs/core/AudioRecorder.js.map +1 -1
- package/lib/commonjs/core/BaseAudioContext.js +25 -28
- package/lib/commonjs/core/BaseAudioContext.js.map +1 -1
- package/lib/commonjs/core/OfflineAudioContext.js +1 -1
- package/lib/commonjs/core/OfflineAudioContext.js.map +1 -1
- package/lib/commonjs/types.js +46 -0
- package/lib/commonjs/types.js.map +1 -1
- package/lib/commonjs/utils/bitEnums.js +33 -0
- package/lib/commonjs/utils/bitEnums.js.map +1 -0
- package/lib/commonjs/utils/index.js +21 -19
- package/lib/commonjs/utils/index.js.map +1 -1
- package/lib/commonjs/web-core/AudioContext.js +0 -12
- package/lib/commonjs/web-core/AudioContext.js.map +1 -1
- package/lib/commonjs/web-core/OfflineAudioContext.js +0 -12
- package/lib/commonjs/web-core/OfflineAudioContext.js.map +1 -1
- package/lib/module/api.js +15 -16
- package/lib/module/api.js.map +1 -1
- package/lib/module/api.web.js +0 -1
- package/lib/module/api.web.js.map +1 -1
- package/lib/module/core/AudioContext.js +2 -2
- package/lib/module/core/AudioContext.js.map +1 -1
- package/lib/module/core/AudioRecorder.js +171 -13
- package/lib/module/core/AudioRecorder.js.map +1 -1
- package/lib/module/core/BaseAudioContext.js +26 -29
- package/lib/module/core/BaseAudioContext.js.map +1 -1
- package/lib/module/core/OfflineAudioContext.js +2 -2
- package/lib/module/core/OfflineAudioContext.js.map +1 -1
- package/lib/module/types.js +45 -1
- package/lib/module/types.js.map +1 -1
- package/lib/module/utils/bitEnums.js +27 -0
- package/lib/module/utils/bitEnums.js.map +1 -0
- package/lib/module/utils/index.js +2 -15
- package/lib/module/utils/index.js.map +1 -1
- package/lib/module/web-core/AudioContext.js +0 -12
- package/lib/module/web-core/AudioContext.js.map +1 -1
- package/lib/module/web-core/OfflineAudioContext.js +0 -12
- package/lib/module/web-core/OfflineAudioContext.js.map +1 -1
- package/lib/typescript/api.d.ts +17 -19
- package/lib/typescript/api.d.ts.map +1 -1
- package/lib/typescript/api.web.d.ts +0 -1
- package/lib/typescript/api.web.d.ts.map +1 -1
- package/lib/typescript/core/AudioContext.d.ts.map +1 -1
- package/lib/typescript/core/AudioRecorder.d.ts +62 -7
- package/lib/typescript/core/AudioRecorder.d.ts.map +1 -1
- package/lib/typescript/core/BaseAudioContext.d.ts +1 -3
- package/lib/typescript/core/BaseAudioContext.d.ts.map +1 -1
- package/lib/typescript/events/types.d.ts +16 -0
- package/lib/typescript/events/types.d.ts.map +1 -1
- package/lib/typescript/interfaces.d.ts +42 -9
- package/lib/typescript/interfaces.d.ts.map +1 -1
- package/lib/typescript/types.d.ts +79 -8
- package/lib/typescript/types.d.ts.map +1 -1
- package/lib/typescript/utils/bitEnums.d.ts +4 -0
- package/lib/typescript/utils/bitEnums.d.ts.map +1 -0
- package/lib/typescript/utils/index.d.ts +2 -5
- package/lib/typescript/utils/index.d.ts.map +1 -1
- package/lib/typescript/web-core/AudioContext.d.ts +0 -3
- package/lib/typescript/web-core/AudioContext.d.ts.map +1 -1
- package/lib/typescript/web-core/BaseAudioContext.d.ts +0 -2
- package/lib/typescript/web-core/BaseAudioContext.d.ts.map +1 -1
- package/lib/typescript/web-core/OfflineAudioContext.d.ts +0 -3
- package/lib/typescript/web-core/OfflineAudioContext.d.ts.map +1 -1
- package/package.json +4 -7
- package/src/api.ts +18 -45
- package/src/api.web.ts +0 -1
- package/src/core/AudioContext.ts +2 -3
- package/src/core/AudioRecorder.ts +211 -24
- package/src/core/BaseAudioContext.ts +60 -67
- package/src/core/OfflineAudioContext.ts +2 -2
- package/src/events/types.ts +18 -0
- package/src/interfaces.ts +52 -16
- package/src/types.ts +90 -9
- package/src/utils/bitEnums.ts +51 -0
- package/src/utils/index.ts +2 -22
- package/src/web-core/AudioContext.tsx +0 -25
- package/src/web-core/BaseAudioContext.tsx +0 -2
- package/src/web-core/OfflineAudioContext.tsx +0 -25
- package/common/cpp/audioapi/HostObjects/effects/ConvolverNodeHostObject.cpp +0 -47
- package/common/cpp/audioapi/HostObjects/effects/ConvolverNodeHostObject.h +0 -20
- package/common/cpp/audioapi/core/effects/ConvolverNode.cpp +0 -210
- package/common/cpp/audioapi/core/effects/ConvolverNode.h +0 -55
- package/common/cpp/audioapi/dsp/Convolver.cpp +0 -213
- package/common/cpp/audioapi/dsp/Convolver.h +0 -45
- package/common/cpp/audioapi/libs/ffmpeg/relinking.md +0 -24
- package/common/cpp/audioapi/utils/AlignedAllocator.hpp +0 -50
- package/common/cpp/test/src/biquad/BiquadFilterChromium.cpp +0 -389
- package/common/cpp/test/src/biquad/BiquadFilterChromium.h +0 -64
- package/common/cpp/test/src/biquad/BiquadFilterTest.cpp +0 -284
- package/common/cpp/test/src/biquad/BiquadFilterTest.h +0 -40
- package/lib/commonjs/core/ConvolverNode.js +0 -37
- package/lib/commonjs/core/ConvolverNode.js.map +0 -1
- package/lib/commonjs/web-core/ConvolverNode.js +0 -40
- package/lib/commonjs/web-core/ConvolverNode.js.map +0 -1
- package/lib/commonjs/web-core/ConvolverNodeOptions.js +0 -6
- package/lib/commonjs/web-core/ConvolverNodeOptions.js.map +0 -1
- package/lib/module/core/ConvolverNode.js +0 -31
- package/lib/module/core/ConvolverNode.js.map +0 -1
- package/lib/module/web-core/ConvolverNode.js +0 -34
- package/lib/module/web-core/ConvolverNode.js.map +0 -1
- package/lib/module/web-core/ConvolverNodeOptions.js +0 -4
- package/lib/module/web-core/ConvolverNodeOptions.js.map +0 -1
- package/lib/typescript/core/ConvolverNode.d.ts +0 -12
- package/lib/typescript/core/ConvolverNode.d.ts.map +0 -1
- package/lib/typescript/web-core/ConvolverNode.d.ts +0 -11
- package/lib/typescript/web-core/ConvolverNode.d.ts.map +0 -1
- package/lib/typescript/web-core/ConvolverNodeOptions.d.ts +0 -6
- package/lib/typescript/web-core/ConvolverNodeOptions.d.ts.map +0 -1
- package/scripts/download-prebuilt-binaries.sh +0 -52
- package/scripts/rnaa_utils.rb +0 -8
- package/scripts/validate-worklets-version.js +0 -28
- package/src/core/ConvolverNode.ts +0 -35
- package/src/web-core/ConvolverNode.tsx +0 -43
- package/src/web-core/ConvolverNodeOptions.tsx +0 -6
|
@@ -1,210 +0,0 @@
|
|
|
1
|
-
#include <audioapi/core/BaseAudioContext.h>
|
|
2
|
-
#include <audioapi/core/effects/ConvolverNode.h>
|
|
3
|
-
#include <audioapi/core/sources/AudioBuffer.h>
|
|
4
|
-
#include <audioapi/core/utils/Constants.h>
|
|
5
|
-
#include <audioapi/dsp/AudioUtils.h>
|
|
6
|
-
#include <audioapi/dsp/FFT.h>
|
|
7
|
-
#include <audioapi/utils/AudioArray.h>
|
|
8
|
-
#include <iostream>
|
|
9
|
-
#include <thread>
|
|
10
|
-
|
|
11
|
-
namespace audioapi {
|
|
12
|
-
ConvolverNode::ConvolverNode(
|
|
13
|
-
BaseAudioContext *context,
|
|
14
|
-
std::shared_ptr<AudioBuffer> buffer,
|
|
15
|
-
bool disableNormalization)
|
|
16
|
-
: AudioNode(context),
|
|
17
|
-
buffer_(nullptr),
|
|
18
|
-
internalBuffer_(nullptr),
|
|
19
|
-
signalledToStop_(false),
|
|
20
|
-
remainingSegments_(0),
|
|
21
|
-
internalBufferIndex_(0),
|
|
22
|
-
scaleFactor_(1.0f),
|
|
23
|
-
intermediateBus_(nullptr) {
|
|
24
|
-
channelCount_ = 2;
|
|
25
|
-
channelCountMode_ = ChannelCountMode::CLAMPED_MAX;
|
|
26
|
-
normalize_ = !disableNormalization;
|
|
27
|
-
gainCalibrationSampleRate_ = context->getSampleRate();
|
|
28
|
-
setBuffer(buffer);
|
|
29
|
-
audioBus_ = std::make_shared<AudioBus>(
|
|
30
|
-
RENDER_QUANTUM_SIZE, channelCount_, context->getSampleRate());
|
|
31
|
-
isInitialized_ = true;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
bool ConvolverNode::getNormalize_() const {
|
|
35
|
-
return normalize_;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const std::shared_ptr<AudioBuffer> &ConvolverNode::getBuffer() const {
|
|
39
|
-
return buffer_;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
void ConvolverNode::setNormalize(bool normalize) {
|
|
43
|
-
if (normalize_ != normalize) {
|
|
44
|
-
normalize_ = normalize;
|
|
45
|
-
if (normalize_ && buffer_)
|
|
46
|
-
calculateNormalizationScale();
|
|
47
|
-
}
|
|
48
|
-
if (!normalize_) {
|
|
49
|
-
scaleFactor_ = 1.0f;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
void ConvolverNode::setBuffer(const std::shared_ptr<AudioBuffer> &buffer) {
|
|
54
|
-
if (buffer_ != buffer && buffer != nullptr) {
|
|
55
|
-
buffer_ = buffer;
|
|
56
|
-
if (normalize_)
|
|
57
|
-
calculateNormalizationScale();
|
|
58
|
-
threadPool_ = std::make_shared<ThreadPool>(4);
|
|
59
|
-
convolvers_.clear();
|
|
60
|
-
for (int i = 0; i < buffer->getNumberOfChannels(); ++i) {
|
|
61
|
-
convolvers_.emplace_back();
|
|
62
|
-
AudioArray channelData(buffer->getLength());
|
|
63
|
-
memcpy(
|
|
64
|
-
channelData.getData(),
|
|
65
|
-
buffer->getChannelData(i),
|
|
66
|
-
buffer->getLength() * sizeof(float));
|
|
67
|
-
convolvers_.back().init(
|
|
68
|
-
RENDER_QUANTUM_SIZE, channelData, buffer->getLength());
|
|
69
|
-
}
|
|
70
|
-
if (buffer->getNumberOfChannels() == 1) {
|
|
71
|
-
// add one more convolver, because right now input is always stereo
|
|
72
|
-
convolvers_.emplace_back();
|
|
73
|
-
AudioArray channelData(buffer->getLength());
|
|
74
|
-
memcpy(
|
|
75
|
-
channelData.getData(),
|
|
76
|
-
buffer->getChannelData(0),
|
|
77
|
-
buffer->getLength() * sizeof(float));
|
|
78
|
-
convolvers_.back().init(
|
|
79
|
-
RENDER_QUANTUM_SIZE, channelData, buffer->getLength());
|
|
80
|
-
}
|
|
81
|
-
internalBuffer_ = std::make_shared<AudioBus>(
|
|
82
|
-
RENDER_QUANTUM_SIZE * 2, channelCount_, buffer->getSampleRate());
|
|
83
|
-
intermediateBus_ = std::make_shared<AudioBus>(
|
|
84
|
-
RENDER_QUANTUM_SIZE, convolvers_.size(), buffer->getSampleRate());
|
|
85
|
-
internalBufferIndex_ = 0;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
void ConvolverNode::onInputDisabled() {
|
|
90
|
-
numberOfEnabledInputNodes_ -= 1;
|
|
91
|
-
if (isEnabled() && numberOfEnabledInputNodes_ == 0) {
|
|
92
|
-
signalledToStop_ = true;
|
|
93
|
-
remainingSegments_ = convolvers_.at(0).getSegCount();
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
std::shared_ptr<AudioBus> ConvolverNode::processInputs(
|
|
98
|
-
const std::shared_ptr<AudioBus> &outputBus,
|
|
99
|
-
int framesToProcess,
|
|
100
|
-
bool checkIsAlreadyProcessed) {
|
|
101
|
-
if (internalBufferIndex_ < framesToProcess) {
|
|
102
|
-
return AudioNode::processInputs(outputBus, RENDER_QUANTUM_SIZE, false);
|
|
103
|
-
}
|
|
104
|
-
return AudioNode::processInputs(outputBus, 0, false);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// processing pipeline: processingBus -> intermediateBus_ -> audioBus_ (mixing
|
|
108
|
-
// with intermediateBus_)
|
|
109
|
-
std::shared_ptr<AudioBus> ConvolverNode::processNode(
|
|
110
|
-
const std::shared_ptr<AudioBus> &processingBus,
|
|
111
|
-
int framesToProcess) {
|
|
112
|
-
if (signalledToStop_) {
|
|
113
|
-
if (remainingSegments_ > 0) {
|
|
114
|
-
remainingSegments_--;
|
|
115
|
-
} else {
|
|
116
|
-
disable();
|
|
117
|
-
signalledToStop_ = false;
|
|
118
|
-
internalBufferIndex_ = 0;
|
|
119
|
-
return processingBus;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
if (internalBufferIndex_ < framesToProcess) {
|
|
123
|
-
performConvolution(processingBus); // result returned to intermediateBus_
|
|
124
|
-
audioBus_->sum(intermediateBus_.get());
|
|
125
|
-
|
|
126
|
-
internalBuffer_->copy(
|
|
127
|
-
audioBus_.get(), 0, internalBufferIndex_, RENDER_QUANTUM_SIZE);
|
|
128
|
-
internalBufferIndex_ += RENDER_QUANTUM_SIZE;
|
|
129
|
-
}
|
|
130
|
-
audioBus_->zero();
|
|
131
|
-
audioBus_->copy(internalBuffer_.get(), 0, 0, framesToProcess);
|
|
132
|
-
int remainingFrames = internalBufferIndex_ - framesToProcess;
|
|
133
|
-
if (remainingFrames > 0) {
|
|
134
|
-
for (int i = 0; i < internalBuffer_->getNumberOfChannels(); ++i) {
|
|
135
|
-
memmove(
|
|
136
|
-
internalBuffer_->getChannel(i)->getData(),
|
|
137
|
-
internalBuffer_->getChannel(i)->getData() + framesToProcess,
|
|
138
|
-
remainingFrames * sizeof(float));
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
internalBufferIndex_ -= framesToProcess;
|
|
142
|
-
|
|
143
|
-
for (int i = 0; i < audioBus_->getNumberOfChannels(); ++i) {
|
|
144
|
-
dsp::multiplyByScalar(
|
|
145
|
-
audioBus_->getChannel(i)->getData(),
|
|
146
|
-
scaleFactor_,
|
|
147
|
-
audioBus_->getChannel(i)->getData(),
|
|
148
|
-
framesToProcess);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
return audioBus_;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
void ConvolverNode::calculateNormalizationScale() {
|
|
155
|
-
int numberOfChannels = buffer_->getNumberOfChannels();
|
|
156
|
-
int length = buffer_->getLength();
|
|
157
|
-
|
|
158
|
-
float power = 0;
|
|
159
|
-
|
|
160
|
-
for (int channel = 0; channel < numberOfChannels; ++channel) {
|
|
161
|
-
float channelPower = 0;
|
|
162
|
-
auto channelData = buffer_->getChannelData(channel);
|
|
163
|
-
for (int i = 0; i < length; ++i) {
|
|
164
|
-
float sample = channelData[i];
|
|
165
|
-
channelPower += sample * sample;
|
|
166
|
-
}
|
|
167
|
-
power += channelPower;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
power = std::sqrt(power / (numberOfChannels * length));
|
|
171
|
-
if (power < MIN_IR_POWER) {
|
|
172
|
-
power = MIN_IR_POWER;
|
|
173
|
-
}
|
|
174
|
-
scaleFactor_ = 1 / power;
|
|
175
|
-
scaleFactor_ *= std::pow(10, GAIN_CALIBRATION * 0.05f);
|
|
176
|
-
scaleFactor_ *= gainCalibrationSampleRate_ / buffer_->getSampleRate();
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
void ConvolverNode::performConvolution(
|
|
180
|
-
const std::shared_ptr<AudioBus> &processingBus) {
|
|
181
|
-
if (processingBus->getNumberOfChannels() == 1) {
|
|
182
|
-
for (int i = 0; i < convolvers_.size(); ++i) {
|
|
183
|
-
threadPool_->schedule([&, i] {
|
|
184
|
-
convolvers_[i].process(
|
|
185
|
-
processingBus->getChannel(0)->getData(),
|
|
186
|
-
intermediateBus_->getChannel(i)->getData());
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
} else if (processingBus->getNumberOfChannels() == 2) {
|
|
190
|
-
std::vector<int> inputChannelMap;
|
|
191
|
-
std::vector<int> outputChannelMap;
|
|
192
|
-
if (convolvers_.size() == 2) {
|
|
193
|
-
inputChannelMap = {0, 1};
|
|
194
|
-
outputChannelMap = {0, 1};
|
|
195
|
-
} else { // 4 channel IR
|
|
196
|
-
inputChannelMap = {0, 0, 1, 1};
|
|
197
|
-
outputChannelMap = {0, 3, 2, 1};
|
|
198
|
-
}
|
|
199
|
-
for (int i = 0; i < convolvers_.size(); ++i) {
|
|
200
|
-
threadPool_->schedule(
|
|
201
|
-
[this, i, inputChannelMap, outputChannelMap, &processingBus] {
|
|
202
|
-
convolvers_[i].process(
|
|
203
|
-
processingBus->getChannel(inputChannelMap[i])->getData(),
|
|
204
|
-
intermediateBus_->getChannel(outputChannelMap[i])->getData());
|
|
205
|
-
});
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
threadPool_->wait();
|
|
209
|
-
}
|
|
210
|
-
} // namespace audioapi
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
#pragma once
|
|
2
|
-
|
|
3
|
-
#include <audioapi/core/AudioNode.h>
|
|
4
|
-
#include <audioapi/core/AudioParam.h>
|
|
5
|
-
#include <audioapi/dsp/Convolver.h>
|
|
6
|
-
|
|
7
|
-
#include <memory>
|
|
8
|
-
#include <vector>
|
|
9
|
-
|
|
10
|
-
#include <audioapi/utils/ThreadPool.hpp>
|
|
11
|
-
|
|
12
|
-
static constexpr int GAIN_CALIBRATION = -58; // magic number so that processed signal and dry signal have roughly the same volume
|
|
13
|
-
static constexpr double MIN_IR_POWER = 0.000125;
|
|
14
|
-
|
|
15
|
-
namespace audioapi {
|
|
16
|
-
|
|
17
|
-
class AudioBus;
|
|
18
|
-
class AudioBuffer;
|
|
19
|
-
|
|
20
|
-
class ConvolverNode : public AudioNode {
|
|
21
|
-
public:
|
|
22
|
-
explicit ConvolverNode(BaseAudioContext *context, std::shared_ptr<AudioBuffer> buffer, bool disableNormalization);
|
|
23
|
-
|
|
24
|
-
[[nodiscard]] bool getNormalize_() const;
|
|
25
|
-
[[nodiscard]] const std::shared_ptr<AudioBuffer> &getBuffer() const;
|
|
26
|
-
void setNormalize(bool normalize);
|
|
27
|
-
void setBuffer(const std::shared_ptr<AudioBuffer> &buffer);
|
|
28
|
-
|
|
29
|
-
protected:
|
|
30
|
-
std::shared_ptr<AudioBus> processNode(const std::shared_ptr<AudioBus>& processingBus, int framesToProcess) override;
|
|
31
|
-
|
|
32
|
-
private:
|
|
33
|
-
std::shared_ptr<AudioBus> processInputs(const std::shared_ptr<AudioBus>& outputBus, int framesToProcess, bool checkIsAlreadyProcessed) override;
|
|
34
|
-
void onInputDisabled() override;
|
|
35
|
-
float gainCalibrationSampleRate_;
|
|
36
|
-
size_t remainingSegments_;
|
|
37
|
-
size_t internalBufferIndex_;
|
|
38
|
-
bool normalize_;
|
|
39
|
-
bool signalledToStop_;
|
|
40
|
-
float scaleFactor_;
|
|
41
|
-
std::shared_ptr<AudioBus>intermediateBus_;
|
|
42
|
-
|
|
43
|
-
// impulse response buffer
|
|
44
|
-
std::shared_ptr<AudioBuffer> buffer_;
|
|
45
|
-
// buffer to hold internal processed data
|
|
46
|
-
std::shared_ptr<AudioBus> internalBuffer_;
|
|
47
|
-
// vectors of convolvers, one per channel
|
|
48
|
-
std::vector<Convolver> convolvers_;
|
|
49
|
-
std::shared_ptr<ThreadPool> threadPool_;
|
|
50
|
-
|
|
51
|
-
void calculateNormalizationScale();
|
|
52
|
-
void performConvolution(const std::shared_ptr<AudioBus>& processingBus);
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
} // namespace audioapi
|
|
@@ -1,213 +0,0 @@
|
|
|
1
|
-
// implementation of linear convolution algorithm described in this paper:
|
|
2
|
-
// https://publications.rwth-aachen.de/record/466561/files/466561.pdf page 110
|
|
3
|
-
|
|
4
|
-
#if defined(__ARM_NEON)
|
|
5
|
-
#include <arm_neon.h>
|
|
6
|
-
#endif
|
|
7
|
-
|
|
8
|
-
#include <audioapi/core/sources/AudioBuffer.h>
|
|
9
|
-
#include <audioapi/dsp/Convolver.h>
|
|
10
|
-
#include <audioapi/dsp/VectorMath.h>
|
|
11
|
-
#include <audioapi/utils/AudioArray.h>
|
|
12
|
-
#include <chrono>
|
|
13
|
-
#include <iostream>
|
|
14
|
-
|
|
15
|
-
namespace audioapi {
|
|
16
|
-
|
|
17
|
-
Convolver::Convolver()
|
|
18
|
-
: _blockSize(0),
|
|
19
|
-
_segSize(0),
|
|
20
|
-
_segCount(0),
|
|
21
|
-
_fftComplexSize(0),
|
|
22
|
-
_segments(),
|
|
23
|
-
_segmentsIR(),
|
|
24
|
-
_fftBuffer(0),
|
|
25
|
-
_fft(nullptr),
|
|
26
|
-
_preMultiplied(),
|
|
27
|
-
_current(0),
|
|
28
|
-
_inputBuffer(0) {}
|
|
29
|
-
|
|
30
|
-
void Convolver::reset() {
|
|
31
|
-
_blockSize = 0;
|
|
32
|
-
_segSize = 0;
|
|
33
|
-
_segCount = 0;
|
|
34
|
-
_fftComplexSize = 0;
|
|
35
|
-
_current = 0;
|
|
36
|
-
_fft = nullptr;
|
|
37
|
-
_segments.clear();
|
|
38
|
-
_segmentsIR.clear();
|
|
39
|
-
_preMultiplied.clear();
|
|
40
|
-
_fftBuffer.zero();
|
|
41
|
-
_inputBuffer.zero();
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
bool Convolver::init(
|
|
45
|
-
size_t blockSize,
|
|
46
|
-
const audioapi::AudioArray &ir,
|
|
47
|
-
size_t irLen) {
|
|
48
|
-
reset();
|
|
49
|
-
// blockSize must be a power of two
|
|
50
|
-
if ((blockSize & (blockSize - 1))) {
|
|
51
|
-
return false;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// Ignore zeros at the end of the impulse response because they only waste
|
|
55
|
-
// computation time
|
|
56
|
-
_blockSize = blockSize;
|
|
57
|
-
_trueSegmentCount = (size_t)(std::ceil((float)irLen / (float)_blockSize));
|
|
58
|
-
while (irLen > 0 && ::fabs(ir[irLen - 1]) < 10e-3) {
|
|
59
|
-
--irLen;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
if (irLen == 0) {
|
|
63
|
-
return true;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// The length-N is split into P = N/B length-B sub filters
|
|
67
|
-
_segCount = (size_t)(std::ceil((float)irLen / (float)_blockSize));
|
|
68
|
-
_segSize = 2 * _blockSize;
|
|
69
|
-
// size of the FFT is 2B, so the complex size is B+1, due to the
|
|
70
|
-
// complex-conjugate symmetricity
|
|
71
|
-
_fftComplexSize = _segSize / 2 + 1;
|
|
72
|
-
_fft = std::make_shared<dsp::FFT>((int)_segSize);
|
|
73
|
-
_fftBuffer.resize(_segSize);
|
|
74
|
-
|
|
75
|
-
// segments preparation
|
|
76
|
-
for (int i = 0; i < _segCount; ++i) {
|
|
77
|
-
aligned_vec_complex vec(_fftComplexSize, std::complex<float>(0.0f, 0.0f));
|
|
78
|
-
_segments.push_back(vec);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// ir preparation
|
|
82
|
-
for (int i = 0; i < _segCount; ++i) {
|
|
83
|
-
aligned_vec_complex segment(_fftComplexSize);
|
|
84
|
-
const size_t remainingSamples = irLen - (i * _blockSize);
|
|
85
|
-
const size_t samplesToCopy = std::min(_blockSize, remainingSamples);
|
|
86
|
-
|
|
87
|
-
if (samplesToCopy > 0) {
|
|
88
|
-
memcpy(
|
|
89
|
-
_fftBuffer.getData(),
|
|
90
|
-
ir.getData() + i * _blockSize,
|
|
91
|
-
samplesToCopy * sizeof(float));
|
|
92
|
-
}
|
|
93
|
-
// Each sub filter is zero-padded to length 2B and transformed using a
|
|
94
|
-
// 2B-point real-to-complex FFT.
|
|
95
|
-
memset(_fftBuffer.getData() + _blockSize, 0, _blockSize * sizeof(float));
|
|
96
|
-
_fft->doFFT(_fftBuffer.getData(), segment);
|
|
97
|
-
segment.at(0).imag(0.0f); // ensure DC component is real
|
|
98
|
-
_segmentsIR.push_back(segment);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
_preMultiplied = aligned_vec_complex(_fftComplexSize);
|
|
102
|
-
_inputBuffer.resize(_segSize);
|
|
103
|
-
_current = 0;
|
|
104
|
-
|
|
105
|
-
return true;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/// @brief Fast pairwise complex multiplication using ARM NEON intrinsics
|
|
109
|
-
/// @param ir Impulse response
|
|
110
|
-
/// @param audio Input audio signal
|
|
111
|
-
/// @param pre Output buffer for pre-multiplied results
|
|
112
|
-
/// @note IMPORTANT: ir, audio, and pre must be the same size and should be
|
|
113
|
-
/// aligned to 16 bytes for optimal performance
|
|
114
|
-
void pairwise_complex_multiply_fast(
|
|
115
|
-
const Convolver::aligned_vec_complex &ir,
|
|
116
|
-
const Convolver::aligned_vec_complex &audio,
|
|
117
|
-
Convolver::aligned_vec_complex &pre) {
|
|
118
|
-
size_t n = ir.size();
|
|
119
|
-
|
|
120
|
-
/// @note Using ARM NEON intrinsics for SIMD optimization
|
|
121
|
-
/// This implementation is on average 2x faster than the scalar version on ARM
|
|
122
|
-
/// architectures With 16-byte alignment it can be even faster up to 2.5x
|
|
123
|
-
#ifdef __ARM_NEON
|
|
124
|
-
size_t j = 0;
|
|
125
|
-
|
|
126
|
-
// Main vector loop: process 4 complex samples (8 floats) per iteration using
|
|
127
|
-
// vld2q/vst2q deinterleave
|
|
128
|
-
for (; j <= n - 4; j += 4) {
|
|
129
|
-
// load de-interleaved real/imag for 4 complex values
|
|
130
|
-
float32x4x2_t ir_de = vld2q_f32(reinterpret_cast<const float *>(&ir[j]));
|
|
131
|
-
float32x4x2_t a_de = vld2q_f32(reinterpret_cast<const float *>(&audio[j]));
|
|
132
|
-
float32x4x2_t pre_de = vld2q_f32(reinterpret_cast<float *>(&pre[j]));
|
|
133
|
-
|
|
134
|
-
float32x4_t ir_re = ir_de.val[0];
|
|
135
|
-
float32x4_t ir_im = ir_de.val[1];
|
|
136
|
-
float32x4_t a_re = a_de.val[0];
|
|
137
|
-
float32x4_t a_im = a_de.val[1];
|
|
138
|
-
|
|
139
|
-
// real = ir_re * a_re - ir_im * a_im
|
|
140
|
-
float32x4_t real = vmulq_f32(ir_re, a_re);
|
|
141
|
-
real = vmlsq_f32(real, ir_im, a_im);
|
|
142
|
-
// imag = ir_re * a_im + ir_im * a_re
|
|
143
|
-
float32x4_t imag = vmulq_f32(ir_re, a_im);
|
|
144
|
-
imag = vmlaq_f32(imag, ir_im, a_re);
|
|
145
|
-
|
|
146
|
-
// accumulate into pre
|
|
147
|
-
float32x4_t new_re = vaddq_f32(pre_de.val[0], real);
|
|
148
|
-
float32x4_t new_im = vaddq_f32(pre_de.val[1], imag);
|
|
149
|
-
|
|
150
|
-
float32x4x2_t out_de;
|
|
151
|
-
out_de.val[0] = new_re;
|
|
152
|
-
out_de.val[1] = new_im;
|
|
153
|
-
|
|
154
|
-
vst2q_f32(reinterpret_cast<float *>(&pre[j]), out_de);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// Tail
|
|
158
|
-
for (; j < n; ++j) {
|
|
159
|
-
pre[j] += ir[j] * audio[j];
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
#else
|
|
163
|
-
// Fallback scalar implementation
|
|
164
|
-
for (size_t i = 0; i < n; ++i) {
|
|
165
|
-
pre[i] += ir[i] * audio[i];
|
|
166
|
-
}
|
|
167
|
-
#endif
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
void Convolver::process(float *data, float *outputData) {
|
|
171
|
-
// The input buffer acts as a 2B-point sliding window of the input signal.
|
|
172
|
-
// With each new input block, the right half of the input buffer is shifted
|
|
173
|
-
// to the left and the new block is stored in the right half.
|
|
174
|
-
memmove(
|
|
175
|
-
_inputBuffer.getData(),
|
|
176
|
-
_inputBuffer.getData() + _blockSize,
|
|
177
|
-
_blockSize * sizeof(float));
|
|
178
|
-
memcpy(_inputBuffer.getData() + _blockSize, data, _blockSize * sizeof(float));
|
|
179
|
-
|
|
180
|
-
// All contents (DFT spectra) in the FDL are shifted up by one slot.
|
|
181
|
-
_current = (_current > 0) ? _current - 1 : _segCount - 1;
|
|
182
|
-
// A 2B-point real-to-complex FFT is computed from the input buffer,
|
|
183
|
-
// resulting in B+1 complex-conjugate symmetric DFT coefficients. The
|
|
184
|
-
// result is stored in the first FDL slot.
|
|
185
|
-
// _current marks first FDL slot, which is the current input block.
|
|
186
|
-
_fft->doFFT(_inputBuffer.getData(), _segments[_current]);
|
|
187
|
-
_segments[_current][0].imag(0.0f); // ensure DC component is real
|
|
188
|
-
|
|
189
|
-
// The P sub filter spectra are pairwisely multiplied with the input spectra
|
|
190
|
-
// in the FDL. The results are accumulated in the frequency-domain.
|
|
191
|
-
memset(
|
|
192
|
-
_preMultiplied.data(),
|
|
193
|
-
0,
|
|
194
|
-
_preMultiplied.size() * sizeof(std::complex<float>));
|
|
195
|
-
// this is a bottleneck of the algorithm
|
|
196
|
-
for (int i = 0; i < _segCount; ++i) {
|
|
197
|
-
const int indexAudio = (_current + i) % _segCount;
|
|
198
|
-
const auto &impulseResponseSegment = _segmentsIR[i];
|
|
199
|
-
const auto &audioSegment = _segments[indexAudio];
|
|
200
|
-
pairwise_complex_multiply_fast(
|
|
201
|
-
impulseResponseSegment, audioSegment, _preMultiplied);
|
|
202
|
-
}
|
|
203
|
-
// Of the accumulated spectral convolutions, an 2B-point complex-to-real
|
|
204
|
-
// IFFT is computed. From the resulting 2B samples, the left half is
|
|
205
|
-
// discarded and the right half is returned as the next output block.
|
|
206
|
-
_fft->doInverseFFT(_preMultiplied, _fftBuffer.getData());
|
|
207
|
-
|
|
208
|
-
memcpy(
|
|
209
|
-
outputData,
|
|
210
|
-
_fftBuffer.getData() + _blockSize,
|
|
211
|
-
_blockSize * sizeof(float));
|
|
212
|
-
}
|
|
213
|
-
} // namespace audioapi
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
#pragma once
|
|
2
|
-
|
|
3
|
-
#include <audioapi/utils/AudioArray.h>
|
|
4
|
-
#include <audioapi/dsp/FFT.h>
|
|
5
|
-
#include <vector>
|
|
6
|
-
#include <cstring>
|
|
7
|
-
#include <complex>
|
|
8
|
-
#include <memory>
|
|
9
|
-
#include <audioapi/utils/AlignedAllocator.hpp>
|
|
10
|
-
|
|
11
|
-
namespace audioapi {
|
|
12
|
-
|
|
13
|
-
class AudioBuffer;
|
|
14
|
-
|
|
15
|
-
class Convolver {
|
|
16
|
-
using aligned_vec_complex =
|
|
17
|
-
std::vector<std::complex<float>, AlignedAllocator<std::complex<float>, 16>>;
|
|
18
|
-
|
|
19
|
-
public:
|
|
20
|
-
Convolver();
|
|
21
|
-
bool init(size_t blockSize, const AudioArray &ir, size_t irLen);
|
|
22
|
-
void process(float* inputData, float* outputData);
|
|
23
|
-
void reset();
|
|
24
|
-
inline size_t getSegCount() const { return _trueSegmentCount; }
|
|
25
|
-
|
|
26
|
-
private:
|
|
27
|
-
size_t _trueSegmentCount;
|
|
28
|
-
size_t _blockSize;
|
|
29
|
-
size_t _segSize;
|
|
30
|
-
size_t _segCount;
|
|
31
|
-
size_t _fftComplexSize;
|
|
32
|
-
std::vector<aligned_vec_complex> _segments;
|
|
33
|
-
std::vector<aligned_vec_complex> _segmentsIR;
|
|
34
|
-
AudioArray _fftBuffer;
|
|
35
|
-
std::shared_ptr<dsp::FFT> _fft;
|
|
36
|
-
aligned_vec_complex _preMultiplied;
|
|
37
|
-
size_t _current;
|
|
38
|
-
AudioArray _inputBuffer;
|
|
39
|
-
|
|
40
|
-
friend void pairwise_complex_multiply_fast(
|
|
41
|
-
const aligned_vec_complex& ir,
|
|
42
|
-
const aligned_vec_complex& audio,
|
|
43
|
-
aligned_vec_complex& pre);
|
|
44
|
-
};
|
|
45
|
-
} // namespace audioapi
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
## If you would like to relink ffmpeg to your implementation there are two options:
|
|
2
|
-
|
|
3
|
-
### Option A)
|
|
4
|
-
|
|
5
|
-
you can modify script in scripts/download-prebuilt-binaries.sh
|
|
6
|
-
|
|
7
|
-
- ios dynamic frameworks are in `ffmpeg_ios.zip` directory
|
|
8
|
-
- android shared libraries are in `jniLibs.zip`
|
|
9
|
-
|
|
10
|
-
just replace way of downloading them that links to your binaries
|
|
11
|
-
|
|
12
|
-
### Option B)
|
|
13
|
-
|
|
14
|
-
directly modify libraries in source code
|
|
15
|
-
|
|
16
|
-
- ios dynamic frameworks are placed in `common/cpp/audioapi/external`
|
|
17
|
-
- android shared libraries are placed in `android/src/main/jniLibs`
|
|
18
|
-
|
|
19
|
-
---
|
|
20
|
-
`USED_LIBRARIES`:
|
|
21
|
-
- libavcodec
|
|
22
|
-
- libavformat
|
|
23
|
-
- libavutil
|
|
24
|
-
- libswresample
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
#pragma once
|
|
2
|
-
#include <cstddef>
|
|
3
|
-
#include <new>
|
|
4
|
-
|
|
5
|
-
template<typename T, std::size_t Align = 16>
|
|
6
|
-
class AlignedAllocator {
|
|
7
|
-
public:
|
|
8
|
-
using value_type = T;
|
|
9
|
-
using size_type = std::size_t;
|
|
10
|
-
using difference_type = std::ptrdiff_t;
|
|
11
|
-
|
|
12
|
-
AlignedAllocator() noexcept = default;
|
|
13
|
-
template<class U> AlignedAllocator(const AlignedAllocator<U, Align>&) noexcept {}
|
|
14
|
-
|
|
15
|
-
T* allocate(std::size_t n) {
|
|
16
|
-
// We want to maximize performance on hot paths, so we hint unlikely branches
|
|
17
|
-
if (n == 0) [[ unlikely ]] {
|
|
18
|
-
return nullptr;
|
|
19
|
-
}
|
|
20
|
-
std::size_t bytes = n * sizeof(T);
|
|
21
|
-
// C++17 aligned new
|
|
22
|
-
void* p = ::operator new(bytes, std::align_val_t(Align));
|
|
23
|
-
|
|
24
|
-
// We have more serious problems if this happens than speed concerns
|
|
25
|
-
// so we can opt the branch prediction
|
|
26
|
-
if (!p) [[ unlikely ]] {
|
|
27
|
-
throw std::bad_alloc();
|
|
28
|
-
}
|
|
29
|
-
return static_cast<T*>(p);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
void deallocate(T* p, std::size_t) noexcept {
|
|
33
|
-
::operator delete(p, std::align_val_t(Align));
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// Rebind allocator to type U (required by std::vector)
|
|
37
|
-
template<class U>
|
|
38
|
-
struct rebind { using other = AlignedAllocator<U, Align>; };
|
|
39
|
-
|
|
40
|
-
// Comparison operators (required by std::vector)
|
|
41
|
-
template<typename U, std::size_t UAlign>
|
|
42
|
-
bool operator==(const AlignedAllocator<U, UAlign>&) const noexcept {
|
|
43
|
-
return Align == UAlign;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
template<typename U, std::size_t UAlign>
|
|
47
|
-
bool operator!=(const AlignedAllocator<U, UAlign>&) const noexcept {
|
|
48
|
-
return Align != UAlign;
|
|
49
|
-
}
|
|
50
|
-
};
|