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
|
@@ -1,73 +1,16 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
|
|
3
|
-
#include <functional>
|
|
4
3
|
#include <memory>
|
|
5
|
-
#include <string>
|
|
6
|
-
#include <utility>
|
|
7
|
-
#include <vector>
|
|
8
4
|
|
|
9
|
-
#include "
|
|
10
|
-
#include "AudioBufferSourceNode.h"
|
|
11
|
-
#include "AudioDestinationNode.h"
|
|
12
|
-
#include "AudioScheduledSourceNode.h"
|
|
13
|
-
#include "BiquadFilterNode.h"
|
|
14
|
-
#include "Constants.h"
|
|
15
|
-
#include "GainNode.h"
|
|
16
|
-
#include "OscillatorNode.h"
|
|
17
|
-
#include "StereoPannerNode.h"
|
|
18
|
-
|
|
19
|
-
#ifdef ANDROID
|
|
20
|
-
#include "AudioPlayer.h"
|
|
21
|
-
#else
|
|
22
|
-
#include "IOSAudioPlayer.h"
|
|
23
|
-
#endif
|
|
5
|
+
#include "BaseAudioContext.h"
|
|
24
6
|
|
|
25
7
|
namespace audioapi {
|
|
26
8
|
|
|
27
|
-
class AudioContext {
|
|
9
|
+
class AudioContext : public BaseAudioContext {
|
|
28
10
|
public:
|
|
29
11
|
AudioContext();
|
|
30
|
-
std::string getState();
|
|
31
|
-
int getSampleRate() const;
|
|
32
|
-
double getCurrentTime() const;
|
|
33
|
-
void close();
|
|
34
|
-
|
|
35
|
-
std::shared_ptr<AudioDestinationNode> getDestination();
|
|
36
|
-
std::shared_ptr<OscillatorNode> createOscillator();
|
|
37
|
-
std::shared_ptr<GainNode> createGain();
|
|
38
|
-
std::shared_ptr<StereoPannerNode> createStereoPanner();
|
|
39
|
-
std::shared_ptr<BiquadFilterNode> createBiquadFilter();
|
|
40
|
-
std::shared_ptr<AudioBufferSourceNode> createBufferSource();
|
|
41
|
-
static std::shared_ptr<AudioBuffer>
|
|
42
|
-
createBuffer(int numberOfChannels, int length, int sampleRate);
|
|
43
|
-
std::function<void(float *, int)> renderAudio();
|
|
44
12
|
|
|
45
|
-
|
|
46
|
-
enum class State { SUSPENDED, RUNNING, CLOSED };
|
|
47
|
-
|
|
48
|
-
static std::string toString(State state) {
|
|
49
|
-
switch (state) {
|
|
50
|
-
case State::SUSPENDED:
|
|
51
|
-
return "suspended";
|
|
52
|
-
case State::RUNNING:
|
|
53
|
-
return "running";
|
|
54
|
-
case State::CLOSED:
|
|
55
|
-
return "closed";
|
|
56
|
-
default:
|
|
57
|
-
throw std::invalid_argument("Unknown context state");
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
private:
|
|
62
|
-
std::shared_ptr<AudioDestinationNode> destination_;
|
|
63
|
-
#ifdef ANDROID
|
|
64
|
-
std::shared_ptr<AudioPlayer> audioPlayer_;
|
|
65
|
-
#else
|
|
66
|
-
std::shared_ptr<IOSAudioPlayer> audioPlayer_;
|
|
67
|
-
#endif
|
|
68
|
-
State state_ = State::RUNNING;
|
|
69
|
-
int sampleRate_;
|
|
70
|
-
double contextStartTime_;
|
|
13
|
+
void close();
|
|
71
14
|
};
|
|
72
15
|
|
|
73
16
|
} // namespace audioapi
|
|
@@ -1,35 +1,47 @@
|
|
|
1
1
|
#include "AudioDestinationNode.h"
|
|
2
|
-
#include "
|
|
2
|
+
#include "AudioBus.h"
|
|
3
|
+
#include "AudioNode.h"
|
|
4
|
+
#include "AudioNodeManager.h"
|
|
5
|
+
#include "BaseAudioContext.h"
|
|
6
|
+
#include "VectorMath.h"
|
|
3
7
|
|
|
4
8
|
namespace audioapi {
|
|
5
9
|
|
|
6
|
-
AudioDestinationNode::AudioDestinationNode(
|
|
7
|
-
: AudioNode(context) {
|
|
10
|
+
AudioDestinationNode::AudioDestinationNode(BaseAudioContext *context)
|
|
11
|
+
: AudioNode(context), currentSampleFrame_(0) {
|
|
8
12
|
numberOfOutputs_ = 0;
|
|
9
13
|
numberOfInputs_ = INT_MAX;
|
|
10
14
|
channelCountMode_ = ChannelCountMode::EXPLICIT;
|
|
15
|
+
isInitialized_ = true;
|
|
11
16
|
}
|
|
12
17
|
|
|
13
|
-
|
|
14
|
-
|
|
18
|
+
std::size_t AudioDestinationNode::getCurrentSampleFrame() const {
|
|
19
|
+
return currentSampleFrame_;
|
|
15
20
|
}
|
|
16
21
|
|
|
17
|
-
|
|
18
|
-
|
|
22
|
+
double AudioDestinationNode::getCurrentTime() const {
|
|
23
|
+
return static_cast<double>(currentSampleFrame_) / context_->getSampleRate();
|
|
24
|
+
}
|
|
19
25
|
|
|
20
|
-
|
|
21
|
-
|
|
26
|
+
void AudioDestinationNode::renderAudio(
|
|
27
|
+
AudioBus *destinationBus,
|
|
28
|
+
int32_t numFrames) {
|
|
29
|
+
if (!numFrames || !destinationBus || !isInitialized_) {
|
|
30
|
+
return;
|
|
22
31
|
}
|
|
23
32
|
|
|
24
|
-
|
|
33
|
+
context_->getNodeManager()->preProcessGraph();
|
|
34
|
+
destinationBus->zero();
|
|
35
|
+
|
|
36
|
+
AudioBus *processedBus = processAudio(destinationBus, numFrames);
|
|
25
37
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
VectorMath::add(audioData, mixingBuffer.get(), audioData, numSamples);
|
|
29
|
-
}
|
|
38
|
+
if (processedBus && processedBus != destinationBus) {
|
|
39
|
+
destinationBus->copy(processedBus);
|
|
30
40
|
}
|
|
31
41
|
|
|
32
|
-
|
|
42
|
+
destinationBus->normalize();
|
|
43
|
+
|
|
44
|
+
currentSampleFrame_ += numFrames;
|
|
33
45
|
}
|
|
34
46
|
|
|
35
47
|
} // namespace audioapi
|
|
@@ -5,20 +5,28 @@
|
|
|
5
5
|
#include <vector>
|
|
6
6
|
|
|
7
7
|
#include "AudioNode.h"
|
|
8
|
-
#include "VectorMath.h"
|
|
9
8
|
|
|
10
9
|
namespace audioapi {
|
|
11
10
|
|
|
11
|
+
class AudioBus;
|
|
12
|
+
class BaseAudioContext;
|
|
13
|
+
|
|
12
14
|
class AudioDestinationNode : public AudioNode {
|
|
13
15
|
public:
|
|
14
|
-
explicit AudioDestinationNode(
|
|
16
|
+
explicit AudioDestinationNode(BaseAudioContext *context);
|
|
17
|
+
|
|
18
|
+
void renderAudio(AudioBus *audioData, int32_t numFrames);
|
|
15
19
|
|
|
16
|
-
|
|
20
|
+
std::size_t getCurrentSampleFrame() const;
|
|
21
|
+
double getCurrentTime() const;
|
|
17
22
|
|
|
18
23
|
protected:
|
|
19
|
-
|
|
24
|
+
// DestinationNode is triggered by AudioContext using renderAudio
|
|
25
|
+
// processNode function is not necessary and is never called.
|
|
26
|
+
void processNode(AudioBus *, int) final{};
|
|
20
27
|
|
|
21
28
|
private:
|
|
22
|
-
std::
|
|
29
|
+
std::size_t currentSampleFrame_;
|
|
23
30
|
};
|
|
31
|
+
|
|
24
32
|
} // namespace audioapi
|
|
@@ -1,11 +1,21 @@
|
|
|
1
|
+
#include <memory>
|
|
2
|
+
|
|
3
|
+
#include "AudioBus.h"
|
|
1
4
|
#include "AudioNode.h"
|
|
2
|
-
#include "
|
|
5
|
+
#include "AudioNodeManager.h"
|
|
6
|
+
#include "BaseAudioContext.h"
|
|
3
7
|
|
|
4
8
|
namespace audioapi {
|
|
5
9
|
|
|
6
|
-
AudioNode::AudioNode(
|
|
10
|
+
AudioNode::AudioNode(BaseAudioContext *context) : context_(context) {
|
|
11
|
+
audioBus_ = std::make_shared<AudioBus>(
|
|
12
|
+
context->getSampleRate(),
|
|
13
|
+
context->getBufferSizeInFrames(),
|
|
14
|
+
channelCount_);
|
|
15
|
+
}
|
|
7
16
|
|
|
8
17
|
AudioNode::~AudioNode() {
|
|
18
|
+
isInitialized_ = false;
|
|
9
19
|
cleanup();
|
|
10
20
|
}
|
|
11
21
|
|
|
@@ -30,23 +40,142 @@ std::string AudioNode::getChannelInterpretation() const {
|
|
|
30
40
|
}
|
|
31
41
|
|
|
32
42
|
void AudioNode::connect(const std::shared_ptr<AudioNode> &node) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
43
|
+
context_->getNodeManager()->addPendingConnection(
|
|
44
|
+
shared_from_this(), node, AudioNodeManager::ConnectionType::CONNECT);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
void AudioNode::connectNode(const std::shared_ptr<AudioNode> &node) {
|
|
48
|
+
outputNodes_.push_back(node);
|
|
49
|
+
node->onInputConnected(this);
|
|
38
50
|
}
|
|
39
51
|
|
|
40
52
|
void AudioNode::disconnect(const std::shared_ptr<AudioNode> &node) {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
53
|
+
context_->getNodeManager()->addPendingConnection(
|
|
54
|
+
shared_from_this(), node, AudioNodeManager::ConnectionType::DISCONNECT);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
void AudioNode::disconnectNode(const std::shared_ptr<AudioNode> &node) {
|
|
58
|
+
node->onInputDisconnected(this);
|
|
59
|
+
|
|
60
|
+
auto position = std::find(outputNodes_.begin(), outputNodes_.end(), node);
|
|
61
|
+
|
|
62
|
+
if (position != outputNodes_.end()) {
|
|
63
|
+
outputNodes_.erase(position);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
bool AudioNode::isEnabled() const {
|
|
68
|
+
return isEnabled_;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
void AudioNode::enable() {
|
|
72
|
+
isEnabled_ = true;
|
|
73
|
+
|
|
74
|
+
for (auto it = outputNodes_.begin(); it != outputNodes_.end(); ++it) {
|
|
75
|
+
it->get()->onInputEnabled();
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
void AudioNode::disable() {
|
|
80
|
+
isEnabled_ = false;
|
|
81
|
+
|
|
82
|
+
for (auto it = outputNodes_.begin(); it != outputNodes_.end(); ++it) {
|
|
83
|
+
it->get()->onInputDisabled();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
std::string AudioNode::toString(ChannelCountMode mode) {
|
|
88
|
+
switch (mode) {
|
|
89
|
+
case ChannelCountMode::MAX:
|
|
90
|
+
return "max";
|
|
91
|
+
case ChannelCountMode::CLAMPED_MAX:
|
|
92
|
+
return "clamped-max";
|
|
93
|
+
case ChannelCountMode::EXPLICIT:
|
|
94
|
+
return "explicit";
|
|
95
|
+
default:
|
|
96
|
+
throw std::invalid_argument("Unknown channel count mode");
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
std::string AudioNode::toString(ChannelInterpretation interpretation) {
|
|
101
|
+
switch (interpretation) {
|
|
102
|
+
case ChannelInterpretation::SPEAKERS:
|
|
103
|
+
return "speakers";
|
|
104
|
+
case ChannelInterpretation::DISCRETE:
|
|
105
|
+
return "discrete";
|
|
106
|
+
default:
|
|
107
|
+
throw std::invalid_argument("Unknown channel interpretation");
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
AudioBus *AudioNode::processAudio(AudioBus *outputBus, int framesToProcess) {
|
|
112
|
+
if (!isInitialized_) {
|
|
113
|
+
return outputBus;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
std::size_t currentSampleFrame = context_->getCurrentSampleFrame();
|
|
117
|
+
|
|
118
|
+
// check if the node has already been processed for this rendering quantum
|
|
119
|
+
bool isAlreadyProcessed = currentSampleFrame == lastRenderedFrame_;
|
|
120
|
+
|
|
121
|
+
// Node can't use output bus if:
|
|
122
|
+
// - outputBus is not provided, which means that next node is doing a
|
|
123
|
+
// multi-node summing.
|
|
124
|
+
// - it has more than one input, which means that it has to sum all inputs
|
|
125
|
+
// using internal bus.
|
|
126
|
+
// - it has more than one output, so each output node can get the processed
|
|
127
|
+
// data without re-calculating the node.
|
|
128
|
+
bool canUseOutputBus =
|
|
129
|
+
outputBus != 0 && inputNodes_.size() < 2 && outputNodes_.size() < 2;
|
|
130
|
+
|
|
131
|
+
if (isAlreadyProcessed) {
|
|
132
|
+
// If it was already processed in the rendering quantum, return it.
|
|
133
|
+
return audioBus_.get();
|
|
49
134
|
}
|
|
135
|
+
|
|
136
|
+
// Update the last rendered frame before processing node and its inputs.
|
|
137
|
+
lastRenderedFrame_ = currentSampleFrame;
|
|
138
|
+
|
|
139
|
+
AudioBus *processingBus = canUseOutputBus ? outputBus : audioBus_.get();
|
|
140
|
+
|
|
141
|
+
if (!canUseOutputBus) {
|
|
142
|
+
// Clear the bus before summing all connected nodes.
|
|
143
|
+
processingBus->zero();
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (inputNodes_.empty()) {
|
|
147
|
+
// If there are no connected inputs, process the node just to advance the
|
|
148
|
+
// audio params. The node will output silence anyway.
|
|
149
|
+
processNode(processingBus, framesToProcess);
|
|
150
|
+
return processingBus;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
for (auto it = inputNodes_.begin(); it != inputNodes_.end(); ++it) {
|
|
154
|
+
if (!(*it)->isEnabled()) {
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Process first connected node, it can be directly connected to the
|
|
159
|
+
// processingBus, resulting in one less summing operation.
|
|
160
|
+
if (it == inputNodes_.begin()) {
|
|
161
|
+
AudioBus *inputBus = (*it)->processAudio(processingBus, framesToProcess);
|
|
162
|
+
|
|
163
|
+
if (inputBus != processingBus) {
|
|
164
|
+
processingBus->sum(inputBus);
|
|
165
|
+
}
|
|
166
|
+
} else {
|
|
167
|
+
// Enforce the summing to be done using the internal bus.
|
|
168
|
+
AudioBus *inputBus = (*it)->processAudio(0, framesToProcess);
|
|
169
|
+
if (inputBus) {
|
|
170
|
+
processingBus->sum(inputBus);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Finally, process the node itself.
|
|
176
|
+
processNode(processingBus, framesToProcess);
|
|
177
|
+
|
|
178
|
+
return processingBus;
|
|
50
179
|
}
|
|
51
180
|
|
|
52
181
|
void AudioNode::cleanup() {
|
|
@@ -54,15 +183,48 @@ void AudioNode::cleanup() {
|
|
|
54
183
|
inputNodes_.clear();
|
|
55
184
|
}
|
|
56
185
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
186
|
+
void AudioNode::onInputEnabled() {
|
|
187
|
+
numberOfEnabledInputNodes_ += 1;
|
|
188
|
+
|
|
189
|
+
if (!isEnabled()) {
|
|
190
|
+
enable();
|
|
63
191
|
}
|
|
192
|
+
}
|
|
64
193
|
|
|
65
|
-
|
|
194
|
+
void AudioNode::onInputDisabled() {
|
|
195
|
+
numberOfEnabledInputNodes_ -= 1;
|
|
196
|
+
|
|
197
|
+
if (isEnabled() && numberOfEnabledInputNodes_ == 0) {
|
|
198
|
+
disable();
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
void AudioNode::onInputConnected(AudioNode *node) {
|
|
203
|
+
inputNodes_.push_back(node);
|
|
204
|
+
|
|
205
|
+
if (node->isEnabled()) {
|
|
206
|
+
onInputEnabled();
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
void AudioNode::onInputDisconnected(AudioNode *node) {
|
|
211
|
+
auto position = std::find(inputNodes_.begin(), inputNodes_.end(), node);
|
|
212
|
+
|
|
213
|
+
if (position != inputNodes_.end()) {
|
|
214
|
+
inputNodes_.erase(position);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
if (inputNodes_.size() > 0) {
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (isEnabled()) {
|
|
222
|
+
node->onInputDisabled();
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
for (auto outputNode : outputNodes_) {
|
|
226
|
+
disconnectNode(outputNode);
|
|
227
|
+
}
|
|
66
228
|
}
|
|
67
229
|
|
|
68
230
|
} // namespace audioapi
|
|
@@ -3,17 +3,19 @@
|
|
|
3
3
|
#include <memory>
|
|
4
4
|
#include <string>
|
|
5
5
|
#include <vector>
|
|
6
|
-
#include "Constants.h"
|
|
7
6
|
|
|
8
|
-
|
|
7
|
+
#include "ChannelCountMode.h"
|
|
8
|
+
#include "ChannelInterpretation.h"
|
|
9
|
+
#include "Constants.h"
|
|
9
10
|
|
|
10
11
|
namespace audioapi {
|
|
11
12
|
|
|
12
|
-
class
|
|
13
|
+
class AudioBus;
|
|
14
|
+
class BaseAudioContext;
|
|
13
15
|
|
|
14
16
|
class AudioNode : public std::enable_shared_from_this<AudioNode> {
|
|
15
17
|
public:
|
|
16
|
-
explicit AudioNode(
|
|
18
|
+
explicit AudioNode(BaseAudioContext *context);
|
|
17
19
|
virtual ~AudioNode();
|
|
18
20
|
int getNumberOfInputs() const;
|
|
19
21
|
int getNumberOfOutputs() const;
|
|
@@ -23,52 +25,50 @@ class AudioNode : public std::enable_shared_from_this<AudioNode> {
|
|
|
23
25
|
void connect(const std::shared_ptr<AudioNode> &node);
|
|
24
26
|
void disconnect(const std::shared_ptr<AudioNode> &node);
|
|
25
27
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
bool isEnabled() const;
|
|
29
|
+
void enable();
|
|
30
|
+
void disable();
|
|
28
31
|
|
|
29
32
|
protected:
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
return "clamped-max";
|
|
38
|
-
case ChannelCountMode::EXPLICIT:
|
|
39
|
-
return "explicit";
|
|
40
|
-
default:
|
|
41
|
-
throw std::invalid_argument("Unknown channel count mode");
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
enum class ChannelInterpretation { SPEAKERS, DISCRETE };
|
|
46
|
-
|
|
47
|
-
static std::string toString(ChannelInterpretation interpretation) {
|
|
48
|
-
switch (interpretation) {
|
|
49
|
-
case ChannelInterpretation::SPEAKERS:
|
|
50
|
-
return "speakers";
|
|
51
|
-
case ChannelInterpretation::DISCRETE:
|
|
52
|
-
return "discrete";
|
|
53
|
-
default:
|
|
54
|
-
throw std::invalid_argument("Unknown channel interpretation");
|
|
55
|
-
}
|
|
56
|
-
}
|
|
33
|
+
friend class AudioNodeManager;
|
|
34
|
+
friend class AudioDestinationNode;
|
|
35
|
+
|
|
36
|
+
BaseAudioContext *context_;
|
|
37
|
+
std::shared_ptr<AudioBus> audioBus_;
|
|
38
|
+
|
|
39
|
+
int channelCount_ = CHANNEL_COUNT;
|
|
57
40
|
|
|
58
|
-
protected:
|
|
59
|
-
AudioContext *context_;
|
|
60
41
|
int numberOfInputs_ = 1;
|
|
61
42
|
int numberOfOutputs_ = 1;
|
|
62
|
-
int
|
|
43
|
+
int numberOfEnabledInputNodes_ = 0;
|
|
44
|
+
|
|
45
|
+
bool isInitialized_ = false;
|
|
46
|
+
bool isEnabled_ = true;
|
|
47
|
+
|
|
48
|
+
std::size_t lastRenderedFrame_{SIZE_MAX};
|
|
49
|
+
|
|
63
50
|
ChannelCountMode channelCountMode_ = ChannelCountMode::MAX;
|
|
64
51
|
ChannelInterpretation channelInterpretation_ =
|
|
65
52
|
ChannelInterpretation::SPEAKERS;
|
|
66
53
|
|
|
67
|
-
std::vector<
|
|
54
|
+
std::vector<AudioNode *> inputNodes_ = {};
|
|
68
55
|
std::vector<std::shared_ptr<AudioNode>> outputNodes_ = {};
|
|
69
56
|
|
|
70
57
|
private:
|
|
58
|
+
static std::string toString(ChannelCountMode mode);
|
|
59
|
+
static std::string toString(ChannelInterpretation interpretation);
|
|
60
|
+
|
|
71
61
|
void cleanup();
|
|
62
|
+
AudioBus *processAudio(AudioBus *outputBus, int framesToProcess);
|
|
63
|
+
virtual void processNode(AudioBus *processingBus, int framesToProcess) = 0;
|
|
64
|
+
|
|
65
|
+
void connectNode(const std::shared_ptr<AudioNode> &node);
|
|
66
|
+
void disconnectNode(const std::shared_ptr<AudioNode> &node);
|
|
67
|
+
|
|
68
|
+
void onInputEnabled();
|
|
69
|
+
void onInputDisabled();
|
|
70
|
+
void onInputConnected(AudioNode *node);
|
|
71
|
+
void onInputDisconnected(AudioNode *node);
|
|
72
72
|
};
|
|
73
73
|
|
|
74
74
|
} // namespace audioapi
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
|
|
2
|
+
#include "AudioNodeManager.h"
|
|
3
|
+
#include "AudioNode.h"
|
|
4
|
+
#include "Locker.h"
|
|
5
|
+
|
|
6
|
+
namespace audioapi {
|
|
7
|
+
|
|
8
|
+
AudioNodeManager::AudioNodeManager() {}
|
|
9
|
+
|
|
10
|
+
AudioNodeManager::~AudioNodeManager() {
|
|
11
|
+
audioNodesToConnect_.clear();
|
|
12
|
+
sourceNodes_.clear();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
void AudioNodeManager::addPendingConnection(
|
|
16
|
+
const std::shared_ptr<AudioNode> &from,
|
|
17
|
+
const std::shared_ptr<AudioNode> &to,
|
|
18
|
+
ConnectionType type) {
|
|
19
|
+
Locker lock(getGraphLock());
|
|
20
|
+
|
|
21
|
+
audioNodesToConnect_.push_back(std::make_tuple(from, to, type));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
void AudioNodeManager::addSourceNode(const std::shared_ptr<AudioNode> &node) {
|
|
25
|
+
Locker lock(getGraphLock());
|
|
26
|
+
|
|
27
|
+
sourceNodes_.push_back(node);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
void AudioNodeManager::preProcessGraph() {
|
|
31
|
+
if (!Locker::tryLock(getGraphLock())) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
settlePendingConnections();
|
|
36
|
+
removeFinishedSourceNodes();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
std::mutex &AudioNodeManager::getGraphLock() {
|
|
40
|
+
return graphLock_;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
void AudioNodeManager::settlePendingConnections() {
|
|
44
|
+
for (auto &connection : audioNodesToConnect_) {
|
|
45
|
+
std::shared_ptr<AudioNode> from = std::get<0>(connection);
|
|
46
|
+
std::shared_ptr<AudioNode> to = std::get<1>(connection);
|
|
47
|
+
ConnectionType type = std::get<2>(connection);
|
|
48
|
+
|
|
49
|
+
if (type == ConnectionType::CONNECT) {
|
|
50
|
+
from->connectNode(to);
|
|
51
|
+
} else {
|
|
52
|
+
from->disconnectNode(to);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
audioNodesToConnect_.clear();
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
void AudioNodeManager::removeFinishedSourceNodes() {
|
|
60
|
+
for (auto it = sourceNodes_.begin(); it != sourceNodes_.end();) {
|
|
61
|
+
auto currentNode = it->get();
|
|
62
|
+
// Release the source node if use count is equal to 1 (this vector)
|
|
63
|
+
if (!currentNode->isEnabled() && it->use_count() == 1) {
|
|
64
|
+
for (auto &outputNode : currentNode->outputNodes_) {
|
|
65
|
+
currentNode->disconnectNode(outputNode);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
it = sourceNodes_.erase(it);
|
|
69
|
+
} else {
|
|
70
|
+
++it;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
} // namespace audioapi
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <memory>
|
|
4
|
+
#include <mutex>
|
|
5
|
+
#include <tuple>
|
|
6
|
+
#include <vector>
|
|
7
|
+
|
|
8
|
+
namespace audioapi {
|
|
9
|
+
|
|
10
|
+
class AudioNode;
|
|
11
|
+
|
|
12
|
+
class AudioNodeManager {
|
|
13
|
+
public:
|
|
14
|
+
enum class ConnectionType { CONNECT, DISCONNECT };
|
|
15
|
+
AudioNodeManager();
|
|
16
|
+
~AudioNodeManager();
|
|
17
|
+
|
|
18
|
+
void preProcessGraph();
|
|
19
|
+
void addPendingConnection(
|
|
20
|
+
const std::shared_ptr<AudioNode> &from,
|
|
21
|
+
const std::shared_ptr<AudioNode> &to,
|
|
22
|
+
ConnectionType type);
|
|
23
|
+
|
|
24
|
+
void addSourceNode(const std::shared_ptr<AudioNode> &node);
|
|
25
|
+
|
|
26
|
+
std::mutex &getGraphLock();
|
|
27
|
+
|
|
28
|
+
private:
|
|
29
|
+
std::mutex graphLock_;
|
|
30
|
+
|
|
31
|
+
std::vector<std::shared_ptr<AudioNode>> sourceNodes_;
|
|
32
|
+
std::vector<std::tuple<
|
|
33
|
+
std::shared_ptr<AudioNode>,
|
|
34
|
+
std::shared_ptr<AudioNode>,
|
|
35
|
+
ConnectionType>>
|
|
36
|
+
audioNodesToConnect_;
|
|
37
|
+
|
|
38
|
+
void settlePendingConnections();
|
|
39
|
+
void removeFinishedSourceNodes();
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
} // namespace audioapi
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#include "AudioParam.h"
|
|
2
|
-
#include "
|
|
2
|
+
#include "BaseAudioContext.h"
|
|
3
3
|
|
|
4
4
|
namespace audioapi {
|
|
5
5
|
|
|
6
6
|
AudioParam::AudioParam(
|
|
7
|
-
|
|
7
|
+
BaseAudioContext *context,
|
|
8
8
|
float defaultValue,
|
|
9
9
|
float minValue,
|
|
10
10
|
float maxValue)
|
|
@@ -40,8 +40,7 @@ float AudioParam::getMaxValue() const {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
void AudioParam::setValue(float value) {
|
|
43
|
-
checkValue(value);
|
|
44
|
-
value_ = value;
|
|
43
|
+
value_ = checkValue(value);
|
|
45
44
|
}
|
|
46
45
|
|
|
47
46
|
float AudioParam::getValueAtTime(double time) {
|
|
@@ -66,7 +65,7 @@ float AudioParam::getValueAtTime(double time) {
|
|
|
66
65
|
}
|
|
67
66
|
|
|
68
67
|
void AudioParam::setValueAtTime(float value, double time) {
|
|
69
|
-
checkValue(value);
|
|
68
|
+
value = checkValue(value);
|
|
70
69
|
auto calculateValue = [](double, double, float, float endValue, double) {
|
|
71
70
|
return endValue;
|
|
72
71
|
};
|
|
@@ -76,7 +75,7 @@ void AudioParam::setValueAtTime(float value, double time) {
|
|
|
76
75
|
}
|
|
77
76
|
|
|
78
77
|
void AudioParam::linearRampToValueAtTime(float value, double time) {
|
|
79
|
-
checkValue(value);
|
|
78
|
+
value = checkValue(value);
|
|
80
79
|
auto calculateValue = [](double startTime,
|
|
81
80
|
double endTime,
|
|
82
81
|
float startValue,
|
|
@@ -94,7 +93,7 @@ void AudioParam::linearRampToValueAtTime(float value, double time) {
|
|
|
94
93
|
}
|
|
95
94
|
|
|
96
95
|
void AudioParam::exponentialRampToValueAtTime(float value, double time) {
|
|
97
|
-
checkValue(value);
|
|
96
|
+
value = checkValue(value);
|
|
98
97
|
auto calculateValue = [](double startTime,
|
|
99
98
|
double endTime,
|
|
100
99
|
float startValue,
|
|
@@ -111,10 +110,8 @@ void AudioParam::exponentialRampToValueAtTime(float value, double time) {
|
|
|
111
110
|
changesQueue_.emplace(paramChange);
|
|
112
111
|
}
|
|
113
112
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
throw std::invalid_argument("Value out of range");
|
|
117
|
-
}
|
|
113
|
+
float AudioParam::checkValue(float value) const {
|
|
114
|
+
return std::clamp(value, minValue_, maxValue_);
|
|
118
115
|
}
|
|
119
116
|
|
|
120
117
|
double AudioParam::getStartTime() {
|