react-native-audio-api 0.1.0 → 0.3.0-rc1
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 +10 -8
- package/RNAudioAPI.podspec +5 -0
- package/android/CMakeLists.txt +21 -10
- package/android/libs/fftw3/arm64-v8a/libfftw3.a +0 -0
- package/android/libs/fftw3/armeabi-v7a/libfftw3.a +0 -0
- package/android/libs/fftw3/x86/libfftw3.a +0 -0
- package/android/libs/fftw3/x86_64/libfftw3.a +0 -0
- package/android/libs/include/fftw3/fftw3.h +413 -0
- package/android/src/main/cpp/AudioPlayer/AudioPlayer.cpp +32 -2
- package/android/src/main/cpp/AudioPlayer/AudioPlayer.h +6 -2
- package/common/cpp/AudioAPIInstaller/AudioAPIInstallerHostObject.cpp +5 -3
- package/common/cpp/AudioAPIInstaller/AudioAPIInstallerHostObject.h +5 -1
- package/common/cpp/HostObjects/AudioBufferHostObject.cpp +6 -0
- package/common/cpp/HostObjects/AudioBufferSourceNodeHostObject.cpp +13 -1
- package/common/cpp/HostObjects/AudioContextHostObject.cpp +12 -149
- package/common/cpp/HostObjects/AudioContextHostObject.h +8 -14
- package/common/cpp/HostObjects/AudioNodeHostObject.cpp +0 -6
- package/common/cpp/HostObjects/BaseAudioContextHostObject.cpp +240 -0
- package/common/cpp/HostObjects/BaseAudioContextHostObject.h +41 -0
- package/common/cpp/HostObjects/BiquadFilterNodeHostObject.cpp +44 -0
- package/common/cpp/HostObjects/OscillatorNodeHostObject.cpp +21 -0
- package/common/cpp/HostObjects/OscillatorNodeHostObject.h +1 -0
- package/common/cpp/HostObjects/PeriodicWaveHostObject.cpp +33 -0
- package/common/cpp/HostObjects/PeriodicWaveHostObject.h +33 -0
- package/common/cpp/core/AudioArray.cpp +117 -0
- package/common/cpp/core/AudioArray.h +48 -0
- package/common/cpp/core/AudioBuffer.cpp +23 -80
- package/common/cpp/core/AudioBuffer.h +12 -13
- package/common/cpp/core/AudioBufferSourceNode.cpp +112 -25
- package/common/cpp/core/AudioBufferSourceNode.h +10 -6
- package/common/cpp/core/AudioBus.cpp +518 -0
- package/common/cpp/core/AudioBus.h +83 -0
- package/common/cpp/core/AudioContext.cpp +7 -77
- package/common/cpp/core/AudioContext.h +3 -60
- package/common/cpp/core/AudioDestinationNode.cpp +27 -15
- package/common/cpp/core/AudioDestinationNode.h +13 -5
- package/common/cpp/core/AudioNode.cpp +184 -22
- package/common/cpp/core/AudioNode.h +37 -37
- package/common/cpp/core/AudioNodeManager.cpp +75 -0
- package/common/cpp/core/AudioNodeManager.h +42 -0
- package/common/cpp/core/AudioParam.cpp +8 -11
- package/common/cpp/core/AudioParam.h +8 -8
- package/common/cpp/core/AudioScheduledSourceNode.cpp +19 -5
- package/common/cpp/core/AudioScheduledSourceNode.h +6 -2
- package/common/cpp/core/BaseAudioContext.cpp +191 -0
- package/common/cpp/core/BaseAudioContext.h +87 -0
- package/common/cpp/core/BiquadFilterNode.cpp +92 -69
- package/common/cpp/core/BiquadFilterNode.h +53 -57
- package/common/cpp/core/GainNode.cpp +12 -12
- package/common/cpp/core/GainNode.h +5 -3
- package/common/cpp/core/OscillatorNode.cpp +38 -29
- package/common/cpp/core/OscillatorNode.h +29 -69
- package/common/cpp/core/ParamChange.h +6 -6
- package/common/cpp/core/PeriodicWave.cpp +362 -0
- package/common/cpp/core/PeriodicWave.h +119 -0
- package/common/cpp/core/StereoPannerNode.cpp +31 -30
- package/common/cpp/core/StereoPannerNode.h +6 -6
- package/common/cpp/types/BiquadFilterType.h +19 -0
- package/common/cpp/types/ChannelCountMode.h +10 -0
- package/common/cpp/types/ChannelInterpretation.h +10 -0
- package/common/cpp/types/ContextState.h +10 -0
- package/common/cpp/types/OscillatorType.h +11 -0
- package/common/cpp/utils/FFTFrame.h +67 -0
- package/common/cpp/utils/JsiPromise.cpp +59 -0
- package/common/cpp/utils/JsiPromise.h +42 -0
- package/common/cpp/utils/Locker.h +49 -0
- package/common/cpp/utils/VectorMath.cpp +88 -3
- package/common/cpp/utils/VectorMath.h +7 -1
- package/common/cpp/utils/android/FFTFrame.cpp +23 -0
- package/common/cpp/utils/ios/FFTFrame.cpp +29 -0
- package/common/cpp/wrappers/AudioBufferSourceNodeWrapper.cpp +10 -0
- package/common/cpp/wrappers/AudioBufferSourceNodeWrapper.h +3 -2
- package/common/cpp/wrappers/AudioBufferWrapper.h +5 -5
- package/common/cpp/wrappers/AudioContextWrapper.cpp +7 -60
- package/common/cpp/wrappers/AudioContextWrapper.h +5 -26
- package/common/cpp/wrappers/AudioNodeWrapper.h +5 -5
- package/common/cpp/wrappers/AudioParamWrapper.h +4 -4
- package/common/cpp/wrappers/BaseAudioContextWrapper.cpp +83 -0
- package/common/cpp/wrappers/BaseAudioContextWrapper.h +50 -0
- package/common/cpp/wrappers/BiquadFilterNodeWrapper.cpp +9 -0
- package/common/cpp/wrappers/BiquadFilterNodeWrapper.h +9 -4
- package/common/cpp/wrappers/GainNodeWrapper.h +1 -1
- package/common/cpp/wrappers/OscillatorNodeWrapper.cpp +6 -0
- package/common/cpp/wrappers/OscillatorNodeWrapper.h +5 -2
- package/common/cpp/wrappers/PeriodicWaveWrapper.h +17 -0
- package/common/cpp/wrappers/StereoPannerNodeWrapper.h +1 -1
- package/ios/AudioAPIModule.h +20 -1
- package/ios/AudioAPIModule.mm +6 -4
- package/ios/AudioDecoder/AudioDecoder.h +17 -0
- package/ios/AudioDecoder/AudioDecoder.m +167 -0
- package/ios/AudioDecoder/IOSAudioDecoder.h +26 -0
- package/ios/AudioDecoder/IOSAudioDecoder.mm +40 -0
- package/ios/AudioPlayer/AudioPlayer.h +3 -2
- package/ios/AudioPlayer/AudioPlayer.m +14 -17
- package/ios/AudioPlayer/IOSAudioPlayer.h +7 -3
- package/ios/AudioPlayer/IOSAudioPlayer.mm +31 -7
- package/lib/module/core/AudioBuffer.js +37 -0
- package/lib/module/core/AudioBuffer.js.map +1 -0
- package/lib/module/core/AudioBufferSourceNode.js +28 -0
- package/lib/module/core/AudioBufferSourceNode.js.map +1 -0
- package/lib/module/core/AudioContext.js +10 -0
- package/lib/module/core/AudioContext.js.map +1 -0
- package/lib/module/core/AudioDestinationNode.js +7 -0
- package/lib/module/core/AudioDestinationNode.js.map +1 -0
- package/lib/module/core/AudioNode.js +22 -0
- package/lib/module/core/AudioNode.js.map +1 -0
- package/lib/module/core/AudioParam.js +35 -0
- package/lib/module/core/AudioParam.js.map +1 -0
- package/lib/module/core/AudioScheduledSourceNode.js +28 -0
- package/lib/module/core/AudioScheduledSourceNode.js.map +1 -0
- package/lib/module/core/BaseAudioContext.js +62 -0
- package/lib/module/core/BaseAudioContext.js.map +1 -0
- package/lib/module/core/BiquadFilterNode.js +25 -0
- package/lib/module/core/BiquadFilterNode.js.map +1 -0
- package/lib/module/core/GainNode.js +9 -0
- package/lib/module/core/GainNode.js.map +1 -0
- package/lib/module/core/OscillatorNode.js +24 -0
- package/lib/module/core/OscillatorNode.js.map +1 -0
- package/lib/module/core/PeriodicWave.js +8 -0
- package/lib/module/core/PeriodicWave.js.map +1 -0
- package/lib/module/core/StereoPannerNode.js +9 -0
- package/lib/module/core/StereoPannerNode.js.map +1 -0
- package/lib/module/core/types.js.map +1 -0
- package/lib/module/errors/IndexSizeError.js +8 -0
- package/lib/module/errors/IndexSizeError.js.map +1 -0
- package/lib/module/errors/InvalidAccessError.js +8 -0
- package/lib/module/errors/InvalidAccessError.js.map +1 -0
- package/lib/module/errors/InvalidStateError.js +8 -0
- package/lib/module/errors/InvalidStateError.js.map +1 -0
- package/lib/module/errors/RangeError.js +8 -0
- package/lib/module/errors/RangeError.js.map +1 -0
- package/lib/module/errors/index.js +5 -0
- package/lib/module/errors/index.js.map +1 -0
- package/lib/module/index.js +212 -15
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.native.js +18 -0
- package/lib/module/index.native.js.map +1 -0
- package/lib/module/interfaces.js +2 -0
- package/lib/module/interfaces.js.map +1 -0
- package/lib/module/utils/resolveAudioSource.js +10 -0
- package/lib/module/utils/resolveAudioSource.js.map +1 -0
- package/lib/typescript/core/AudioBuffer.d.ts +12 -0
- package/lib/typescript/core/AudioBuffer.d.ts.map +1 -0
- package/lib/typescript/core/AudioBufferSourceNode.d.ts +12 -0
- package/lib/typescript/core/AudioBufferSourceNode.d.ts.map +1 -0
- package/lib/typescript/core/AudioContext.d.ts +6 -0
- package/lib/typescript/core/AudioContext.d.ts.map +1 -0
- package/lib/typescript/core/AudioDestinationNode.d.ts +7 -0
- package/lib/typescript/core/AudioDestinationNode.d.ts.map +1 -0
- package/lib/typescript/core/AudioNode.d.ts +16 -0
- package/lib/typescript/core/AudioNode.d.ts.map +1 -0
- package/lib/typescript/core/AudioParam.d.ts +14 -0
- package/lib/typescript/core/AudioParam.d.ts.map +1 -0
- package/lib/typescript/core/AudioScheduledSourceNode.d.ts +10 -0
- package/lib/typescript/core/AudioScheduledSourceNode.d.ts.map +1 -0
- package/lib/typescript/core/BaseAudioContext.d.ts +27 -0
- package/lib/typescript/core/BaseAudioContext.d.ts.map +1 -0
- package/lib/typescript/core/BiquadFilterNode.d.ts +16 -0
- package/lib/typescript/core/BiquadFilterNode.d.ts.map +1 -0
- package/lib/typescript/core/GainNode.d.ts +9 -0
- package/lib/typescript/core/GainNode.d.ts.map +1 -0
- package/lib/typescript/core/OscillatorNode.d.ts +15 -0
- package/lib/typescript/core/OscillatorNode.d.ts.map +1 -0
- package/lib/typescript/core/PeriodicWave.d.ts +5 -0
- package/lib/typescript/core/PeriodicWave.d.ts.map +1 -0
- package/lib/typescript/core/StereoPannerNode.d.ts +9 -0
- package/lib/typescript/core/StereoPannerNode.d.ts.map +1 -0
- package/lib/typescript/core/types.d.ts +15 -0
- package/lib/typescript/core/types.d.ts.map +1 -0
- package/lib/typescript/errors/IndexSizeError.d.ts +5 -0
- package/lib/typescript/errors/IndexSizeError.d.ts.map +1 -0
- package/lib/typescript/errors/InvalidAccessError.d.ts +5 -0
- package/lib/typescript/errors/InvalidAccessError.d.ts.map +1 -0
- package/lib/typescript/errors/InvalidStateError.d.ts +5 -0
- package/lib/typescript/errors/InvalidStateError.d.ts.map +1 -0
- package/lib/typescript/errors/RangeError.d.ts +5 -0
- package/lib/typescript/errors/RangeError.d.ts.map +1 -0
- package/lib/typescript/errors/index.d.ts +5 -0
- package/lib/typescript/errors/index.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +88 -5
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/index.native.d.ts +14 -0
- package/lib/typescript/index.native.d.ts.map +1 -0
- package/lib/typescript/interfaces.d.ts +79 -0
- package/lib/typescript/interfaces.d.ts.map +1 -0
- package/lib/typescript/utils/resolveAudioSource.d.ts +3 -0
- package/lib/typescript/utils/resolveAudioSource.d.ts.map +1 -0
- package/package.json +4 -2
- package/src/core/AudioBuffer.ts +68 -0
- package/src/core/AudioBufferSourceNode.ts +35 -0
- package/src/core/AudioContext.ts +12 -0
- package/src/core/AudioDestinationNode.ts +9 -0
- package/src/core/AudioNode.ts +38 -0
- package/src/core/AudioParam.ts +55 -0
- package/src/core/AudioScheduledSourceNode.ts +43 -0
- package/src/core/BaseAudioContext.ts +108 -0
- package/src/core/BiquadFilterNode.ts +49 -0
- package/src/core/GainNode.ts +13 -0
- package/src/core/OscillatorNode.ts +37 -0
- package/src/core/PeriodicWave.ts +10 -0
- package/src/core/StereoPannerNode.ts +13 -0
- package/src/core/types.ts +33 -0
- package/src/errors/IndexSizeError.ts +8 -0
- package/src/errors/InvalidAccessError.ts +8 -0
- package/src/errors/InvalidStateError.ts +8 -0
- package/src/errors/RangeError.ts +8 -0
- package/src/errors/index.ts +4 -0
- package/src/index.native.ts +25 -0
- package/src/index.ts +380 -40
- package/src/interfaces.ts +121 -0
- package/src/modules/global.d.ts +3 -3
- package/src/utils/resolveAudioSource.ts +14 -0
- package/lib/module/types.js.map +0 -1
- package/lib/typescript/types.d.ts +0 -76
- package/lib/typescript/types.d.ts.map +0 -1
- package/src/types.ts +0 -108
- /package/lib/module/{types.js → core/types.js} +0 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
#include "BaseAudioContextWrapper.h"
|
|
2
|
+
|
|
3
|
+
namespace audioapi {
|
|
4
|
+
|
|
5
|
+
BaseAudioContextWrapper::BaseAudioContextWrapper(
|
|
6
|
+
const std::shared_ptr<BaseAudioContext> &context)
|
|
7
|
+
: context_(context) {
|
|
8
|
+
auto destination = context_->getDestination();
|
|
9
|
+
destination_ = std::make_shared<AudioDestinationNodeWrapper>(destination);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
std::shared_ptr<AudioDestinationNodeWrapper>
|
|
13
|
+
BaseAudioContextWrapper::getDestination() const {
|
|
14
|
+
return destination_;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
std::string BaseAudioContextWrapper::getState() const {
|
|
18
|
+
return context_->getState();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
int BaseAudioContextWrapper::getSampleRate() const {
|
|
22
|
+
return context_->getSampleRate();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
double BaseAudioContextWrapper::getCurrentTime() const {
|
|
26
|
+
return context_->getCurrentTime();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
std::shared_ptr<OscillatorNodeWrapper>
|
|
30
|
+
BaseAudioContextWrapper::createOscillator() const {
|
|
31
|
+
auto oscillator = context_->createOscillator();
|
|
32
|
+
return std::make_shared<OscillatorNodeWrapper>(oscillator);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
std::shared_ptr<GainNodeWrapper> BaseAudioContextWrapper::createGain() const {
|
|
36
|
+
auto gain = context_->createGain();
|
|
37
|
+
return std::make_shared<GainNodeWrapper>(gain);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
std::shared_ptr<StereoPannerNodeWrapper>
|
|
41
|
+
BaseAudioContextWrapper::createStereoPanner() const {
|
|
42
|
+
auto panner = context_->createStereoPanner();
|
|
43
|
+
return std::make_shared<StereoPannerNodeWrapper>(panner);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
std::shared_ptr<BiquadFilterNodeWrapper>
|
|
47
|
+
BaseAudioContextWrapper::createBiquadFilter() const {
|
|
48
|
+
auto filter = context_->createBiquadFilter();
|
|
49
|
+
return std::make_shared<BiquadFilterNodeWrapper>(filter);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
std::shared_ptr<AudioBufferSourceNodeWrapper>
|
|
53
|
+
BaseAudioContextWrapper::createBufferSource() const {
|
|
54
|
+
auto bufferSource = context_->createBufferSource();
|
|
55
|
+
return std::make_shared<AudioBufferSourceNodeWrapper>(bufferSource);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
std::shared_ptr<AudioBufferWrapper> BaseAudioContextWrapper::createBuffer(
|
|
59
|
+
int numberOfChannels,
|
|
60
|
+
int length,
|
|
61
|
+
int sampleRate) const {
|
|
62
|
+
auto buffer = context_->createBuffer(numberOfChannels, length, sampleRate);
|
|
63
|
+
return std::make_shared<AudioBufferWrapper>(buffer);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
std::shared_ptr<PeriodicWaveWrapper>
|
|
67
|
+
BaseAudioContextWrapper::createPeriodicWave(
|
|
68
|
+
float *real,
|
|
69
|
+
float *imag,
|
|
70
|
+
bool disableNormalization,
|
|
71
|
+
int length) {
|
|
72
|
+
auto periodicWave =
|
|
73
|
+
context_->createPeriodicWave(real, imag, disableNormalization, length);
|
|
74
|
+
return std::make_shared<PeriodicWaveWrapper>(periodicWave);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
std::shared_ptr<AudioBufferWrapper>
|
|
78
|
+
BaseAudioContextWrapper::decodeAudioDataSource(const std::string &source) {
|
|
79
|
+
return std::make_shared<AudioBufferWrapper>(
|
|
80
|
+
context_->decodeAudioDataSource(source));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
} // namespace audioapi
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <memory>
|
|
4
|
+
#include <string>
|
|
5
|
+
#include <utility>
|
|
6
|
+
|
|
7
|
+
#include "AudioBufferSourceNodeWrapper.h"
|
|
8
|
+
#include "AudioBufferWrapper.h"
|
|
9
|
+
#include "AudioDestinationNodeWrapper.h"
|
|
10
|
+
#include "BaseAudioContext.h"
|
|
11
|
+
#include "BiquadFilterNodeWrapper.h"
|
|
12
|
+
#include "GainNodeWrapper.h"
|
|
13
|
+
#include "OscillatorNodeWrapper.h"
|
|
14
|
+
#include "PeriodicWaveWrapper.h"
|
|
15
|
+
#include "StereoPannerNodeWrapper.h"
|
|
16
|
+
|
|
17
|
+
namespace audioapi {
|
|
18
|
+
|
|
19
|
+
class BaseAudioContextWrapper {
|
|
20
|
+
public:
|
|
21
|
+
explicit BaseAudioContextWrapper(
|
|
22
|
+
const std::shared_ptr<BaseAudioContext> &context);
|
|
23
|
+
|
|
24
|
+
[[nodiscard]] std::shared_ptr<AudioDestinationNodeWrapper> getDestination()
|
|
25
|
+
const;
|
|
26
|
+
[[nodiscard]] std::string getState() const;
|
|
27
|
+
[[nodiscard]] int getSampleRate() const;
|
|
28
|
+
[[nodiscard]] double getCurrentTime() const;
|
|
29
|
+
[[nodiscard]] std::shared_ptr<OscillatorNodeWrapper> createOscillator() const;
|
|
30
|
+
[[nodiscard]] std::shared_ptr<GainNodeWrapper> createGain() const;
|
|
31
|
+
[[nodiscard]] std::shared_ptr<StereoPannerNodeWrapper> createStereoPanner()
|
|
32
|
+
const;
|
|
33
|
+
[[nodiscard]] std::shared_ptr<BiquadFilterNodeWrapper> createBiquadFilter()
|
|
34
|
+
const;
|
|
35
|
+
[[nodiscard]] std::shared_ptr<AudioBufferSourceNodeWrapper>
|
|
36
|
+
createBufferSource() const;
|
|
37
|
+
[[nodiscard]] std::shared_ptr<AudioBufferWrapper>
|
|
38
|
+
createBuffer(int numberOfChannels, int length, int sampleRate) const;
|
|
39
|
+
[[nodiscard]] std::shared_ptr<PeriodicWaveWrapper> createPeriodicWave(
|
|
40
|
+
float *real,
|
|
41
|
+
float *imag,
|
|
42
|
+
bool disableNormalization,
|
|
43
|
+
int length);
|
|
44
|
+
std::shared_ptr<AudioBufferWrapper> decodeAudioDataSource(const std::string &source);
|
|
45
|
+
|
|
46
|
+
protected:
|
|
47
|
+
std::shared_ptr<AudioDestinationNodeWrapper> destination_;
|
|
48
|
+
std::shared_ptr<BaseAudioContext> context_;
|
|
49
|
+
};
|
|
50
|
+
} // namespace audioapi
|
|
@@ -48,4 +48,13 @@ void BiquadFilterNodeWrapper::setType(const std::string &filterType) {
|
|
|
48
48
|
auto biquadFilterNode_ = getBiquadFilterNodeFromAudioNode();
|
|
49
49
|
biquadFilterNode_->setType(filterType);
|
|
50
50
|
}
|
|
51
|
+
|
|
52
|
+
void BiquadFilterNodeWrapper::getFrequencyResponse(
|
|
53
|
+
const std::vector<float> &frequencyArray,
|
|
54
|
+
std::vector<float> &magResponseOutput,
|
|
55
|
+
std::vector<float> &phaseResponseOutput) {
|
|
56
|
+
auto biquadFilterNode_ = getBiquadFilterNodeFromAudioNode();
|
|
57
|
+
biquadFilterNode_->getFrequencyResponse(
|
|
58
|
+
frequencyArray, magResponseOutput, phaseResponseOutput);
|
|
59
|
+
}
|
|
51
60
|
} // namespace audioapi
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
#include <memory>
|
|
4
4
|
#include <string>
|
|
5
|
+
#include <vector>
|
|
5
6
|
|
|
6
7
|
#include "AudioNodeWrapper.h"
|
|
7
8
|
#include "AudioParamWrapper.h"
|
|
@@ -14,12 +15,16 @@ class BiquadFilterNodeWrapper : public AudioNodeWrapper {
|
|
|
14
15
|
explicit BiquadFilterNodeWrapper(
|
|
15
16
|
const std::shared_ptr<BiquadFilterNode> &biquadFilterNode);
|
|
16
17
|
|
|
17
|
-
std::shared_ptr<AudioParamWrapper> getFrequencyParam() const;
|
|
18
|
-
std::shared_ptr<AudioParamWrapper> getDetuneParam() const;
|
|
19
|
-
std::shared_ptr<AudioParamWrapper> getQParam() const;
|
|
20
|
-
std::shared_ptr<AudioParamWrapper> getGainParam() const;
|
|
18
|
+
[[nodiscard]] std::shared_ptr<AudioParamWrapper> getFrequencyParam() const;
|
|
19
|
+
[[nodiscard]] std::shared_ptr<AudioParamWrapper> getDetuneParam() const;
|
|
20
|
+
[[nodiscard]] std::shared_ptr<AudioParamWrapper> getQParam() const;
|
|
21
|
+
[[nodiscard]] std::shared_ptr<AudioParamWrapper> getGainParam() const;
|
|
21
22
|
std::string getType();
|
|
22
23
|
void setType(const std::string &filterType);
|
|
24
|
+
void getFrequencyResponse(
|
|
25
|
+
const std::vector<float> &frequencyArray,
|
|
26
|
+
std::vector<float> &magResponseOutput,
|
|
27
|
+
std::vector<float> &phaseResponseOutput);
|
|
23
28
|
|
|
24
29
|
private:
|
|
25
30
|
std::shared_ptr<AudioParamWrapper> frequencyParam_;
|
|
@@ -12,7 +12,7 @@ class GainNodeWrapper : public AudioNodeWrapper {
|
|
|
12
12
|
public:
|
|
13
13
|
explicit GainNodeWrapper(const std::shared_ptr<GainNode> &gainNode);
|
|
14
14
|
|
|
15
|
-
std::shared_ptr<AudioParamWrapper> getGainParam() const;
|
|
15
|
+
[[nodiscard]] std::shared_ptr<AudioParamWrapper> getGainParam() const;
|
|
16
16
|
|
|
17
17
|
private:
|
|
18
18
|
std::shared_ptr<AudioParamWrapper> gainParam_;
|
|
@@ -35,4 +35,10 @@ void OscillatorNodeWrapper::setType(const std::string &type) {
|
|
|
35
35
|
auto oscillatorNode_ = getOscillatorNodeFromAudioNode();
|
|
36
36
|
oscillatorNode_->setType(type);
|
|
37
37
|
}
|
|
38
|
+
|
|
39
|
+
void OscillatorNodeWrapper::setPeriodicWave(
|
|
40
|
+
const std::shared_ptr<PeriodicWaveWrapper> &periodicWave) {
|
|
41
|
+
auto oscillatorNode_ = getOscillatorNodeFromAudioNode();
|
|
42
|
+
oscillatorNode_->setPeriodicWave(periodicWave->periodicWave_);
|
|
43
|
+
}
|
|
38
44
|
} // namespace audioapi
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
#include "AudioParamWrapper.h"
|
|
7
7
|
#include "AudioScheduledSourceNodeWrapper.h"
|
|
8
8
|
#include "OscillatorNode.h"
|
|
9
|
+
#include "PeriodicWaveWrapper.h"
|
|
9
10
|
|
|
10
11
|
namespace audioapi {
|
|
11
12
|
|
|
@@ -14,10 +15,12 @@ class OscillatorNodeWrapper : public AudioScheduledSourceNodeWrapper {
|
|
|
14
15
|
explicit OscillatorNodeWrapper(
|
|
15
16
|
const std::shared_ptr<OscillatorNode> &oscillatorNode);
|
|
16
17
|
|
|
17
|
-
std::shared_ptr<AudioParamWrapper> getFrequencyParam() const;
|
|
18
|
-
std::shared_ptr<AudioParamWrapper> getDetuneParam() const;
|
|
18
|
+
[[nodiscard]] std::shared_ptr<AudioParamWrapper> getFrequencyParam() const;
|
|
19
|
+
[[nodiscard]] std::shared_ptr<AudioParamWrapper> getDetuneParam() const;
|
|
19
20
|
std::string getType();
|
|
20
21
|
void setType(const std::string &type);
|
|
22
|
+
void setPeriodicWave(
|
|
23
|
+
const std::shared_ptr<PeriodicWaveWrapper> &periodicWave);
|
|
21
24
|
|
|
22
25
|
private:
|
|
23
26
|
std::shared_ptr<AudioParamWrapper> frequencyParam_;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <memory>
|
|
4
|
+
|
|
5
|
+
#include "PeriodicWave.h"
|
|
6
|
+
|
|
7
|
+
namespace audioapi {
|
|
8
|
+
|
|
9
|
+
class PeriodicWaveWrapper {
|
|
10
|
+
public:
|
|
11
|
+
explicit PeriodicWaveWrapper(
|
|
12
|
+
const std::shared_ptr<PeriodicWave> &periodicWave)
|
|
13
|
+
: periodicWave_(periodicWave) {}
|
|
14
|
+
|
|
15
|
+
std::shared_ptr<PeriodicWave> periodicWave_;
|
|
16
|
+
};
|
|
17
|
+
} // namespace audioapi
|
|
@@ -13,7 +13,7 @@ class StereoPannerNodeWrapper : public AudioNodeWrapper {
|
|
|
13
13
|
explicit StereoPannerNodeWrapper(
|
|
14
14
|
const std::shared_ptr<StereoPannerNode> &stereoPannerNode);
|
|
15
15
|
|
|
16
|
-
std::shared_ptr<AudioParamWrapper> getPanParam() const;
|
|
16
|
+
[[nodiscard]] std::shared_ptr<AudioParamWrapper> getPanParam() const;
|
|
17
17
|
|
|
18
18
|
private:
|
|
19
19
|
std::shared_ptr<AudioParamWrapper> panParam_;
|
package/ios/AudioAPIModule.h
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
2
|
+
#import <React/RCTInitializing.h>
|
|
3
|
+
#if REACT_NATIVE_MINOR_VERSION >= 74
|
|
4
|
+
#import <React/RCTRuntimeExecutorModule.h>
|
|
5
|
+
#import <ReactCommon/RCTRuntimeExecutor.h>
|
|
6
|
+
#endif // REACT_NATIVE_MINOR_VERSION >= 74
|
|
7
|
+
#else // RCT_NEW_ARCH_ENABLED
|
|
1
8
|
#import <React/RCTBridgeModule.h>
|
|
9
|
+
#endif // RCT_NEW_ARCH_ENABLED
|
|
2
10
|
|
|
3
|
-
|
|
11
|
+
#import <React/RCTEventEmitter.h>
|
|
4
12
|
|
|
13
|
+
@interface AudioAPIModule : RCTEventEmitter
|
|
14
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
15
|
+
<RCTInitializing
|
|
16
|
+
#if REACT_NATIVE_MINOR_VERSION >= 74
|
|
17
|
+
,
|
|
18
|
+
RCTRuntimeExecutorModule
|
|
19
|
+
#endif // REACT_NATIVE_MINOR_VERSION >= 74
|
|
20
|
+
#else
|
|
21
|
+
<RCTBridgeModule
|
|
22
|
+
#endif // RCT_NEW_ARCH_ENABLED
|
|
23
|
+
>
|
|
5
24
|
@end
|
package/ios/AudioAPIModule.mm
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
#import "AudioAPIModule.h"
|
|
2
2
|
|
|
3
|
+
#import <ReactCommon/RCTTurboModule.h>
|
|
3
4
|
#import <React/RCTBridge+Private.h>
|
|
5
|
+
#import <React/RCTBridge.h>
|
|
4
6
|
#import <React/RCTUtils.h>
|
|
5
7
|
#import <jsi/jsi.h>
|
|
6
8
|
|
|
7
|
-
#import "
|
|
8
|
-
#import "
|
|
9
|
+
#import "AudioAPIInstallerHostObject.h"
|
|
10
|
+
#import "AudioAPIInstallerWrapper.h"
|
|
9
11
|
|
|
10
12
|
@implementation AudioAPIModule
|
|
11
13
|
|
|
@@ -14,7 +16,7 @@ RCT_EXPORT_MODULE(AudioAPIModule)
|
|
|
14
16
|
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(install)
|
|
15
17
|
{
|
|
16
18
|
NSLog(@"Installing JSI bindings for react-native-audio-api...");
|
|
17
|
-
RCTCxxBridge *cxxBridge = (RCTCxxBridge *)
|
|
19
|
+
RCTCxxBridge *cxxBridge = (RCTCxxBridge *)self.bridge;
|
|
18
20
|
|
|
19
21
|
if (cxxBridge == nil) {
|
|
20
22
|
NSLog(@"Error during getting bridge!");
|
|
@@ -33,7 +35,7 @@ RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(install)
|
|
|
33
35
|
auto &runtime = *jsRuntime;
|
|
34
36
|
|
|
35
37
|
auto wrapper = std::make_shared<audioapi::AudioAPIInstallerWrapper>();
|
|
36
|
-
auto hostObject = std::make_shared<audioapi::AudioAPIInstallerHostObject>(wrapper);
|
|
38
|
+
auto hostObject = std::make_shared<audioapi::AudioAPIInstallerHostObject>(wrapper, jsRuntime, cxxBridge.jsCallInvoker);
|
|
37
39
|
auto object = jsi::Object::createFromHostObject(runtime, hostObject);
|
|
38
40
|
runtime.global().setProperty(runtime, "__AudioAPIInstaller", std::move(object));
|
|
39
41
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#import <AVFoundation/AVFoundation.h>
|
|
4
|
+
#import <Foundation/Foundation.h>
|
|
5
|
+
|
|
6
|
+
@interface AudioDecoder : NSObject
|
|
7
|
+
|
|
8
|
+
@property (nonatomic, strong) AVAudioPCMBuffer *buffer;
|
|
9
|
+
@property (nonatomic, assign) int sampleRate;
|
|
10
|
+
|
|
11
|
+
- (instancetype)initWithSampleRate:(int)sampleRate;
|
|
12
|
+
|
|
13
|
+
- (const AudioBufferList *)decode:(NSString *)pathOrURL;
|
|
14
|
+
|
|
15
|
+
- (void)cleanup;
|
|
16
|
+
|
|
17
|
+
@end
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
#import <AudioDecoder.h>
|
|
2
|
+
|
|
3
|
+
@implementation AudioDecoder
|
|
4
|
+
|
|
5
|
+
- (instancetype)initWithSampleRate:(int)sampleRate
|
|
6
|
+
{
|
|
7
|
+
if (self = [super init]) {
|
|
8
|
+
self.sampleRate = sampleRate;
|
|
9
|
+
}
|
|
10
|
+
return self;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
- (const AudioBufferList *)decode:(NSString *)pathOrURL
|
|
14
|
+
{
|
|
15
|
+
// check if the input is a URL or a local file path
|
|
16
|
+
NSURL *url = [NSURL URLWithString:pathOrURL];
|
|
17
|
+
|
|
18
|
+
if (url && url.scheme) {
|
|
19
|
+
self.buffer = [self decodeWithURL:url];
|
|
20
|
+
} else {
|
|
21
|
+
self.buffer = [self decodeWithFilePath:pathOrURL];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return self.buffer.audioBufferList;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
- (AVAudioPCMBuffer *)decodeWithFilePath:(NSString *)path
|
|
28
|
+
{
|
|
29
|
+
NSError *error = nil;
|
|
30
|
+
NSURL *fileURL = [NSURL fileURLWithPath:path];
|
|
31
|
+
AVAudioFile *audioFile = [[AVAudioFile alloc] initForReading:fileURL error:&error];
|
|
32
|
+
|
|
33
|
+
if (error) {
|
|
34
|
+
NSLog(@"Error occurred while opening the audio file: %@", [error localizedDescription]);
|
|
35
|
+
return nil;
|
|
36
|
+
}
|
|
37
|
+
AVAudioPCMBuffer *buffer = [[AVAudioPCMBuffer alloc] initWithPCMFormat:[audioFile processingFormat]
|
|
38
|
+
frameCapacity:[audioFile length]];
|
|
39
|
+
|
|
40
|
+
AVAudioFormat *format = [[AVAudioFormat alloc] initWithCommonFormat:AVAudioPCMFormatFloat32
|
|
41
|
+
sampleRate:self.sampleRate
|
|
42
|
+
channels:buffer.audioBufferList->mNumberBuffers
|
|
43
|
+
interleaved:NO];
|
|
44
|
+
|
|
45
|
+
[audioFile readIntoBuffer:buffer error:&error];
|
|
46
|
+
if (error) {
|
|
47
|
+
NSLog(@"Error occurred while reading the audio file: %@", [error localizedDescription]);
|
|
48
|
+
return nil;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (self.sampleRate != audioFile.processingFormat.sampleRate) {
|
|
52
|
+
return [self convertBuffer:buffer ToFormat:format];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return buffer;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
- (AVAudioPCMBuffer *)decodeWithURL:(NSURL *)url
|
|
59
|
+
{
|
|
60
|
+
__block NSURL *tempFileURL = nil;
|
|
61
|
+
|
|
62
|
+
dispatch_group_t group = dispatch_group_create();
|
|
63
|
+
|
|
64
|
+
dispatch_group_enter(group);
|
|
65
|
+
|
|
66
|
+
[self downloadFileFromURL:url
|
|
67
|
+
completion:^(NSURL *downloadedFileURL, NSError *downloadError) {
|
|
68
|
+
if (downloadError) {
|
|
69
|
+
NSLog(@"Error downloading file: %@", downloadError.localizedDescription);
|
|
70
|
+
tempFileURL = nil;
|
|
71
|
+
} else {
|
|
72
|
+
tempFileURL = downloadedFileURL;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
dispatch_group_leave(group);
|
|
76
|
+
}];
|
|
77
|
+
|
|
78
|
+
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
|
|
79
|
+
|
|
80
|
+
if (!tempFileURL) {
|
|
81
|
+
NSLog(@"Cannot process given url");
|
|
82
|
+
return nil;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return [self decodeWithFilePath:tempFileURL.path];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
- (void)downloadFileFromURL:(NSURL *)url completion:(void (^)(NSURL *tempFileURL, NSError *error))completion
|
|
89
|
+
{
|
|
90
|
+
// get unique file path in temporary dir
|
|
91
|
+
NSString *tempDirectory = NSTemporaryDirectory();
|
|
92
|
+
NSString *timestamp = [NSString stringWithFormat:@"_%@", @((long long)[[NSDate date] timeIntervalSince1970])];
|
|
93
|
+
NSString *fileNameWithTimestamp = [url.lastPathComponent stringByDeletingPathExtension];
|
|
94
|
+
fileNameWithTimestamp = [fileNameWithTimestamp stringByAppendingString:timestamp];
|
|
95
|
+
NSString *fileExtension =
|
|
96
|
+
[url.pathExtension length] > 0 ? [NSString stringWithFormat:@".%@", url.pathExtension] : @"";
|
|
97
|
+
NSString *tempFilePath =
|
|
98
|
+
[tempDirectory stringByAppendingPathComponent:[fileNameWithTimestamp stringByAppendingString:fileExtension]];
|
|
99
|
+
NSURL *tempFileURL = [NSURL fileURLWithPath:tempFilePath];
|
|
100
|
+
|
|
101
|
+
// download file
|
|
102
|
+
NSURLSession *session = [NSURLSession sharedSession];
|
|
103
|
+
NSURLSessionDownloadTask *downloadTask = [session
|
|
104
|
+
downloadTaskWithURL:url
|
|
105
|
+
completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
|
|
106
|
+
if (error) {
|
|
107
|
+
NSLog(@"Error downloading file: %@", error.localizedDescription);
|
|
108
|
+
if (completion) {
|
|
109
|
+
completion(nil, error);
|
|
110
|
+
}
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// move to generated file path in temporary dir
|
|
115
|
+
NSError *fileError = nil;
|
|
116
|
+
BOOL success = [[NSFileManager defaultManager] moveItemAtURL:location toURL:tempFileURL error:&fileError];
|
|
117
|
+
if (success) {
|
|
118
|
+
NSLog(@"File downloaded successfully to %@", tempFileURL.path);
|
|
119
|
+
if (completion) {
|
|
120
|
+
completion(tempFileURL, nil);
|
|
121
|
+
}
|
|
122
|
+
} else {
|
|
123
|
+
NSLog(@"Error moving downloaded file: %@", fileError.localizedDescription);
|
|
124
|
+
if (completion) {
|
|
125
|
+
completion(nil, fileError);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}];
|
|
129
|
+
|
|
130
|
+
[downloadTask resume];
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
- (AVAudioPCMBuffer *)convertBuffer:(AVAudioPCMBuffer *)buffer ToFormat:(AVAudioFormat *)format
|
|
134
|
+
{
|
|
135
|
+
NSError *error = nil;
|
|
136
|
+
AVAudioConverter *converter = [[AVAudioConverter alloc] initFromFormat:buffer.format toFormat:format];
|
|
137
|
+
AVAudioPCMBuffer *convertedBuffer =
|
|
138
|
+
[[AVAudioPCMBuffer alloc] initWithPCMFormat:format frameCapacity:(AVAudioFrameCount)buffer.frameCapacity];
|
|
139
|
+
|
|
140
|
+
AVAudioConverterInputBlock inputBlock =
|
|
141
|
+
^AVAudioBuffer *(AVAudioPacketCount inNumberOfPackets, AVAudioConverterInputStatus *outStatus)
|
|
142
|
+
{
|
|
143
|
+
if (buffer.frameLength > 0) {
|
|
144
|
+
*outStatus = AVAudioConverterInputStatus_HaveData;
|
|
145
|
+
return buffer;
|
|
146
|
+
} else {
|
|
147
|
+
*outStatus = AVAudioConverterInputStatus_NoDataNow;
|
|
148
|
+
return nil;
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
[converter convertToBuffer:convertedBuffer error:&error withInputFromBlock:inputBlock];
|
|
153
|
+
|
|
154
|
+
if (error) {
|
|
155
|
+
NSLog(@"Error occurred while converting the audio file: %@", [error localizedDescription]);
|
|
156
|
+
return nil;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return convertedBuffer;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
- (void)cleanup
|
|
163
|
+
{
|
|
164
|
+
self.buffer = nil;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
@end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <string>
|
|
4
|
+
|
|
5
|
+
#ifdef __OBJC__ // when compiled as Objective-C++
|
|
6
|
+
#import <AudioDecoder.h>
|
|
7
|
+
#else // when compiled as C++
|
|
8
|
+
typedef struct objc_object AudioDecoder;
|
|
9
|
+
#endif // __OBJC__
|
|
10
|
+
|
|
11
|
+
namespace audioapi {
|
|
12
|
+
|
|
13
|
+
class AudioBus;
|
|
14
|
+
|
|
15
|
+
class IOSAudioDecoder {
|
|
16
|
+
protected:
|
|
17
|
+
AudioDecoder *audioDecoder_;
|
|
18
|
+
int sampleRate_;
|
|
19
|
+
|
|
20
|
+
public:
|
|
21
|
+
IOSAudioDecoder(int sampleRate);
|
|
22
|
+
~IOSAudioDecoder();
|
|
23
|
+
|
|
24
|
+
AudioBus *decodeWithFilePath(const std::string &path);
|
|
25
|
+
};
|
|
26
|
+
} // namespace audioapi
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#import <AVFoundation/AVFoundation.h>
|
|
2
|
+
|
|
3
|
+
#include <AudioArray.h>
|
|
4
|
+
#include <AudioBus.h>
|
|
5
|
+
#include <IOSAudioDecoder.h>
|
|
6
|
+
|
|
7
|
+
namespace audioapi {
|
|
8
|
+
|
|
9
|
+
IOSAudioDecoder::IOSAudioDecoder(int sampleRate) : sampleRate_(sampleRate)
|
|
10
|
+
{
|
|
11
|
+
audioDecoder_ = [[AudioDecoder alloc] initWithSampleRate:sampleRate_];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
IOSAudioDecoder::~IOSAudioDecoder()
|
|
15
|
+
{
|
|
16
|
+
[audioDecoder_ cleanup];
|
|
17
|
+
audioDecoder_ = nullptr;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
AudioBus *IOSAudioDecoder::decodeWithFilePath(const std::string &path)
|
|
21
|
+
{
|
|
22
|
+
auto bufferList = [audioDecoder_ decode:[NSString stringWithUTF8String:path.c_str()]];
|
|
23
|
+
AudioBus *audioBus;
|
|
24
|
+
if (bufferList) {
|
|
25
|
+
auto numberOfChannels = bufferList->mNumberBuffers;
|
|
26
|
+
auto size = bufferList->mBuffers[0].mDataByteSize / sizeof(float);
|
|
27
|
+
|
|
28
|
+
audioBus = new AudioBus(sampleRate_, size, numberOfChannels);
|
|
29
|
+
|
|
30
|
+
for (int i = 0; i < numberOfChannels; i++) {
|
|
31
|
+
float *data = (float *)bufferList->mBuffers[i].mData;
|
|
32
|
+
memcpy(audioBus->getChannel(i)->getData(), data, sizeof(float) * size);
|
|
33
|
+
}
|
|
34
|
+
} else {
|
|
35
|
+
audioBus = new AudioBus(sampleRate_, 1, 1);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return audioBus;
|
|
39
|
+
}
|
|
40
|
+
} // namespace audioapi
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
#import <AVFoundation/AVFoundation.h>
|
|
4
4
|
#import <Foundation/Foundation.h>
|
|
5
5
|
|
|
6
|
-
typedef void (^RenderAudioBlock)(
|
|
6
|
+
typedef void (^RenderAudioBlock)(AudioBufferList *outputBuffer, int numFrames);
|
|
7
7
|
|
|
8
8
|
@interface AudioPlayer : NSObject
|
|
9
9
|
|
|
@@ -12,12 +12,13 @@ typedef void (^RenderAudioBlock)(float *audioData, int numFrames);
|
|
|
12
12
|
@property (nonatomic, strong) AVAudioFormat *format;
|
|
13
13
|
@property (nonatomic, strong) AVAudioSourceNode *sourceNode;
|
|
14
14
|
@property (nonatomic, copy) RenderAudioBlock renderAudio;
|
|
15
|
-
@property (nonatomic, assign) float *buffer;
|
|
16
15
|
|
|
17
16
|
- (instancetype)initWithRenderAudioBlock:(RenderAudioBlock)renderAudio;
|
|
18
17
|
|
|
19
18
|
- (int)getSampleRate;
|
|
20
19
|
|
|
20
|
+
- (int)getBufferSizeInFrames;
|
|
21
|
+
|
|
21
22
|
- (void)start;
|
|
22
23
|
|
|
23
24
|
- (void)stop;
|
|
@@ -42,8 +42,6 @@
|
|
|
42
42
|
frameCount:frameCount
|
|
43
43
|
outputData:outputData];
|
|
44
44
|
}];
|
|
45
|
-
|
|
46
|
-
self.buffer = nil;
|
|
47
45
|
}
|
|
48
46
|
|
|
49
47
|
return self;
|
|
@@ -54,6 +52,19 @@
|
|
|
54
52
|
return [self.audioSession sampleRate];
|
|
55
53
|
}
|
|
56
54
|
|
|
55
|
+
- (int)getBufferSizeInFrames
|
|
56
|
+
{
|
|
57
|
+
// Note: might be important in the future.
|
|
58
|
+
// For some reason audioSession.IOBufferDuration is always 0.01, which for sample rate of 48k
|
|
59
|
+
// gives exactly 480 frames, while at the same time frameCount requested by AVAudioSourceEngine
|
|
60
|
+
// might vary f.e. between 555-560.
|
|
61
|
+
// preferredIOBufferDuration seems to be double the value (resulting in 960 frames),
|
|
62
|
+
// which is safer to base our internal AudioBus sizes.
|
|
63
|
+
// Buut no documentation => no guarantee :)
|
|
64
|
+
// If something is crackling when it should play silence, start here 📻
|
|
65
|
+
return (int)(self.audioSession.preferredIOBufferDuration * self.audioSession.sampleRate);
|
|
66
|
+
}
|
|
67
|
+
|
|
57
68
|
- (void)start
|
|
58
69
|
{
|
|
59
70
|
[self.audioEngine attachNode:self.sourceNode];
|
|
@@ -88,8 +99,6 @@
|
|
|
88
99
|
self.audioEngine = nil;
|
|
89
100
|
self.audioSession = nil;
|
|
90
101
|
self.renderAudio = nil;
|
|
91
|
-
|
|
92
|
-
free(_buffer);
|
|
93
102
|
}
|
|
94
103
|
|
|
95
104
|
- (OSStatus)renderCallbackWithIsSilence:(BOOL *)isSilence
|
|
@@ -101,19 +110,7 @@
|
|
|
101
110
|
return noErr; // Ensure we have stereo output
|
|
102
111
|
}
|
|
103
112
|
|
|
104
|
-
|
|
105
|
-
self.buffer = malloc(frameCount * 2 * sizeof(float));
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
float *leftBuffer = (float *)outputData->mBuffers[0].mData;
|
|
109
|
-
float *rightBuffer = (float *)outputData->mBuffers[1].mData;
|
|
110
|
-
|
|
111
|
-
self.renderAudio(self.buffer, frameCount);
|
|
112
|
-
|
|
113
|
-
for (int frame = 0; frame < frameCount; frame += 1) {
|
|
114
|
-
leftBuffer[frame] = self.buffer[frame * 2];
|
|
115
|
-
rightBuffer[frame] = self.buffer[frame * 2 + 1];
|
|
116
|
-
}
|
|
113
|
+
self.renderAudio(outputData, frameCount);
|
|
117
114
|
|
|
118
115
|
return noErr;
|
|
119
116
|
}
|
|
@@ -11,19 +11,23 @@ typedef struct objc_object AudioPlayer;
|
|
|
11
11
|
namespace audioapi {
|
|
12
12
|
|
|
13
13
|
class AudioContext;
|
|
14
|
+
class AudioBus;
|
|
14
15
|
|
|
15
16
|
class IOSAudioPlayer {
|
|
16
17
|
protected:
|
|
18
|
+
AudioBus *audioBus_;
|
|
17
19
|
AudioPlayer *audioPlayer_;
|
|
18
|
-
std::function<void(
|
|
20
|
+
std::function<void(AudioBus *, int)> renderAudio_;
|
|
19
21
|
|
|
20
22
|
public:
|
|
21
|
-
explicit IOSAudioPlayer(
|
|
23
|
+
explicit IOSAudioPlayer(
|
|
24
|
+
const std::function<void(AudioBus *, int)> &renderAudio);
|
|
22
25
|
~IOSAudioPlayer();
|
|
23
26
|
|
|
24
27
|
int getSampleRate() const;
|
|
28
|
+
int getBufferSizeInFrames() const;
|
|
29
|
+
|
|
25
30
|
void start();
|
|
26
31
|
void stop();
|
|
27
|
-
void renderAudio(float *audioData, int32_t numFrames);
|
|
28
32
|
};
|
|
29
33
|
} // namespace audioapi
|