react-native-audio-api 0.11.0-nightly-568a154-20251222 → 0.11.0-nightly-9548557-20251223
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/common/cpp/audioapi/AudioAPIModuleInstaller.h +2 -0
- package/common/cpp/audioapi/HostObjects/effects/DelayNodeHostObject.cpp +6 -2
- package/common/cpp/audioapi/core/AudioContext.cpp +15 -13
- package/common/cpp/audioapi/core/AudioContext.h +2 -1
- package/common/cpp/audioapi/core/AudioNode.cpp +39 -24
- package/common/cpp/audioapi/core/AudioNode.h +3 -3
- package/common/cpp/audioapi/core/AudioParam.cpp +9 -6
- package/common/cpp/audioapi/core/AudioParam.h +2 -2
- package/common/cpp/audioapi/core/BaseAudioContext.cpp +25 -21
- package/common/cpp/audioapi/core/BaseAudioContext.h +3 -1
- package/common/cpp/audioapi/core/analysis/AnalyserNode.cpp +8 -11
- package/common/cpp/audioapi/core/analysis/AnalyserNode.h +1 -1
- package/common/cpp/audioapi/core/destinations/AudioDestinationNode.cpp +9 -3
- package/common/cpp/audioapi/core/destinations/AudioDestinationNode.h +1 -1
- package/common/cpp/audioapi/core/effects/BiquadFilterNode.cpp +18 -9
- package/common/cpp/audioapi/core/effects/BiquadFilterNode.h +1 -1
- package/common/cpp/audioapi/core/effects/ConvolverNode.cpp +4 -4
- package/common/cpp/audioapi/core/effects/ConvolverNode.h +1 -1
- package/common/cpp/audioapi/core/effects/DelayNode.cpp +20 -11
- package/common/cpp/audioapi/core/effects/DelayNode.h +1 -1
- package/common/cpp/audioapi/core/effects/GainNode.cpp +12 -4
- package/common/cpp/audioapi/core/effects/GainNode.h +1 -1
- package/common/cpp/audioapi/core/effects/IIRFilterNode.cpp +6 -3
- package/common/cpp/audioapi/core/effects/IIRFilterNode.h +1 -1
- package/common/cpp/audioapi/core/effects/StereoPannerNode.cpp +7 -4
- package/common/cpp/audioapi/core/effects/StereoPannerNode.h +1 -1
- package/common/cpp/audioapi/core/effects/WorkletNode.cpp +3 -3
- package/common/cpp/audioapi/core/effects/WorkletNode.h +2 -2
- package/common/cpp/audioapi/core/effects/WorkletProcessingNode.cpp +7 -4
- package/common/cpp/audioapi/core/effects/WorkletProcessingNode.h +6 -2
- package/common/cpp/audioapi/core/sources/AudioBuffer.cpp +2 -3
- package/common/cpp/audioapi/core/sources/AudioBuffer.h +1 -1
- package/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.cpp +59 -25
- package/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.h +4 -2
- package/common/cpp/audioapi/core/sources/AudioBufferQueueSourceNode.cpp +18 -11
- package/common/cpp/audioapi/core/sources/AudioBufferQueueSourceNode.h +3 -1
- package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp +37 -21
- package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.h +3 -3
- package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.cpp +11 -11
- package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.h +4 -2
- package/common/cpp/audioapi/core/sources/ConstantSourceNode.cpp +16 -8
- package/common/cpp/audioapi/core/sources/ConstantSourceNode.h +1 -1
- package/common/cpp/audioapi/core/sources/OscillatorNode.cpp +30 -18
- package/common/cpp/audioapi/core/sources/OscillatorNode.h +1 -1
- package/common/cpp/audioapi/core/sources/RecorderAdapterNode.cpp +4 -4
- package/common/cpp/audioapi/core/sources/RecorderAdapterNode.h +1 -1
- package/common/cpp/audioapi/core/sources/StreamerNode.cpp +24 -10
- package/common/cpp/audioapi/core/sources/StreamerNode.h +4 -3
- package/common/cpp/audioapi/core/sources/WorkletSourceNode.cpp +11 -4
- package/common/cpp/audioapi/core/sources/WorkletSourceNode.h +6 -2
- package/common/cpp/test/RunTests.sh +1 -1
- package/common/cpp/test/src/AudioParamTest.cpp +10 -10
- package/common/cpp/test/src/AudioScheduledSourceTest.cpp +31 -15
- package/common/cpp/test/src/ConstantSourceTest.cpp +16 -14
- package/common/cpp/test/src/DelayTest.cpp +14 -13
- package/common/cpp/test/src/GainTest.cpp +10 -9
- package/common/cpp/test/src/IIRFilterTest.cpp +4 -4
- package/common/cpp/test/src/OscillatorTest.cpp +2 -2
- package/common/cpp/test/src/StereoPannerTest.cpp +14 -12
- package/common/cpp/test/src/biquad/BiquadFilterTest.cpp +25 -25
- package/common/cpp/test/src/biquad/BiquadFilterTest.h +3 -5
- package/package.json +1 -1
|
@@ -82,6 +82,7 @@ class AudioAPIModuleInstaller {
|
|
|
82
82
|
|
|
83
83
|
audioContext = std::make_shared<AudioContext>(
|
|
84
84
|
sampleRate, audioEventHandlerRegistry, runtimeRegistry);
|
|
85
|
+
audioContext->initialize();
|
|
85
86
|
|
|
86
87
|
auto audioContextHostObject =
|
|
87
88
|
std::make_shared<AudioContextHostObject>(audioContext, &runtime, jsCallInvoker);
|
|
@@ -118,6 +119,7 @@ class AudioAPIModuleInstaller {
|
|
|
118
119
|
|
|
119
120
|
auto offlineAudioContext = std::make_shared<OfflineAudioContext>(
|
|
120
121
|
numberOfChannels, length, sampleRate, audioEventHandlerRegistry, runtimeRegistry);
|
|
122
|
+
offlineAudioContext->initialize();
|
|
121
123
|
|
|
122
124
|
auto audioContextHostObject = std::make_shared<OfflineAudioContextHostObject>(
|
|
123
125
|
offlineAudioContext, &runtime, jsCallInvoker);
|
|
@@ -14,8 +14,12 @@ DelayNodeHostObject::DelayNodeHostObject(const std::shared_ptr<DelayNode> &node)
|
|
|
14
14
|
|
|
15
15
|
size_t DelayNodeHostObject::getSizeInBytes() const {
|
|
16
16
|
auto delayNode = std::static_pointer_cast<DelayNode>(node_);
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
auto base = sizeof(float) * delayNode->getDelayTimeParam()->getMaxValue();
|
|
18
|
+
if (std::shared_ptr<BaseAudioContext> context = delayNode->context_.lock()) {
|
|
19
|
+
return base * context->getSampleRate();
|
|
20
|
+
} else {
|
|
21
|
+
return base * 44100; // Fallback to common sample rate
|
|
22
|
+
}
|
|
19
23
|
}
|
|
20
24
|
|
|
21
25
|
JSI_PROPERTY_GETTER_IMPL(DelayNodeHostObject, delayTime) {
|
|
@@ -15,17 +15,8 @@ AudioContext::AudioContext(
|
|
|
15
15
|
float sampleRate,
|
|
16
16
|
const std::shared_ptr<IAudioEventHandlerRegistry> &audioEventHandlerRegistry,
|
|
17
17
|
const RuntimeRegistry &runtimeRegistry)
|
|
18
|
-
: BaseAudioContext(audioEventHandlerRegistry, runtimeRegistry) {
|
|
19
|
-
#ifdef ANDROID
|
|
20
|
-
audioPlayer_ = std::make_shared<AudioPlayer>(
|
|
21
|
-
this->renderAudio(), sampleRate, destination_->getChannelCount());
|
|
22
|
-
#else
|
|
23
|
-
audioPlayer_ = std::make_shared<IOSAudioPlayer>(
|
|
24
|
-
this->renderAudio(), sampleRate, destination_->getChannelCount());
|
|
25
|
-
#endif
|
|
26
|
-
|
|
18
|
+
: BaseAudioContext(audioEventHandlerRegistry, runtimeRegistry), isInitialized_(false) {
|
|
27
19
|
sampleRate_ = sampleRate;
|
|
28
|
-
playerHasBeenStarted_ = false;
|
|
29
20
|
state_ = ContextState::SUSPENDED;
|
|
30
21
|
}
|
|
31
22
|
|
|
@@ -35,6 +26,17 @@ AudioContext::~AudioContext() {
|
|
|
35
26
|
}
|
|
36
27
|
}
|
|
37
28
|
|
|
29
|
+
void AudioContext::initialize() {
|
|
30
|
+
BaseAudioContext::initialize();
|
|
31
|
+
#ifdef ANDROID
|
|
32
|
+
audioPlayer_ = std::make_shared<AudioPlayer>(
|
|
33
|
+
this->renderAudio(), sampleRate_, destination_->getChannelCount());
|
|
34
|
+
#else
|
|
35
|
+
audioPlayer_ = std::make_shared<IOSAudioPlayer>(
|
|
36
|
+
this->renderAudio(), sampleRate_, destination_->getChannelCount());
|
|
37
|
+
#endif
|
|
38
|
+
}
|
|
39
|
+
|
|
38
40
|
void AudioContext::close() {
|
|
39
41
|
state_ = ContextState::CLOSED;
|
|
40
42
|
|
|
@@ -52,7 +54,7 @@ bool AudioContext::resume() {
|
|
|
52
54
|
return true;
|
|
53
55
|
}
|
|
54
56
|
|
|
55
|
-
if (
|
|
57
|
+
if (isInitialized_ && audioPlayer_->resume()) {
|
|
56
58
|
state_ = ContextState::RUNNING;
|
|
57
59
|
return true;
|
|
58
60
|
}
|
|
@@ -80,8 +82,8 @@ bool AudioContext::start() {
|
|
|
80
82
|
return false;
|
|
81
83
|
}
|
|
82
84
|
|
|
83
|
-
if (!
|
|
84
|
-
|
|
85
|
+
if (!isInitialized_ && audioPlayer_->start()) {
|
|
86
|
+
isInitialized_ = true;
|
|
85
87
|
state_ = ContextState::RUNNING;
|
|
86
88
|
|
|
87
89
|
return true;
|
|
@@ -25,6 +25,7 @@ class AudioContext : public BaseAudioContext {
|
|
|
25
25
|
bool resume();
|
|
26
26
|
bool suspend();
|
|
27
27
|
bool start();
|
|
28
|
+
void initialize() override;
|
|
28
29
|
|
|
29
30
|
private:
|
|
30
31
|
#ifdef ANDROID
|
|
@@ -32,7 +33,7 @@ class AudioContext : public BaseAudioContext {
|
|
|
32
33
|
#else
|
|
33
34
|
std::shared_ptr<IOSAudioPlayer> audioPlayer_;
|
|
34
35
|
#endif
|
|
35
|
-
bool
|
|
36
|
+
bool isInitialized_;
|
|
36
37
|
|
|
37
38
|
bool isDriverRunning() const override;
|
|
38
39
|
|
|
@@ -10,10 +10,13 @@
|
|
|
10
10
|
|
|
11
11
|
namespace audioapi {
|
|
12
12
|
|
|
13
|
-
AudioNode::AudioNode(BaseAudioContext
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
AudioNode::AudioNode(std::shared_ptr<BaseAudioContext> context)
|
|
14
|
+
: context_(context),
|
|
15
|
+
audioBus_(
|
|
16
|
+
std::make_shared<AudioBus>(
|
|
17
|
+
RENDER_QUANTUM_SIZE,
|
|
18
|
+
channelCount_,
|
|
19
|
+
context->getSampleRate())) {}
|
|
17
20
|
|
|
18
21
|
AudioNode::~AudioNode() {
|
|
19
22
|
if (isInitialized_) {
|
|
@@ -42,28 +45,38 @@ std::string AudioNode::getChannelInterpretation() const {
|
|
|
42
45
|
}
|
|
43
46
|
|
|
44
47
|
void AudioNode::connect(const std::shared_ptr<AudioNode> &node) {
|
|
45
|
-
context_
|
|
46
|
-
|
|
48
|
+
if (std::shared_ptr<BaseAudioContext> context = context_.lock()) {
|
|
49
|
+
context->getNodeManager()->addPendingNodeConnection(
|
|
50
|
+
shared_from_this(), node, AudioNodeManager::ConnectionType::CONNECT);
|
|
51
|
+
}
|
|
47
52
|
}
|
|
48
53
|
|
|
49
54
|
void AudioNode::connect(const std::shared_ptr<AudioParam> ¶m) {
|
|
50
|
-
context_
|
|
51
|
-
|
|
55
|
+
if (std::shared_ptr<BaseAudioContext> context = context_.lock()) {
|
|
56
|
+
context->getNodeManager()->addPendingParamConnection(
|
|
57
|
+
shared_from_this(), param, AudioNodeManager::ConnectionType::CONNECT);
|
|
58
|
+
}
|
|
52
59
|
}
|
|
53
60
|
|
|
54
61
|
void AudioNode::disconnect() {
|
|
55
|
-
context_
|
|
56
|
-
|
|
62
|
+
if (std::shared_ptr<BaseAudioContext> context = context_.lock()) {
|
|
63
|
+
context->getNodeManager()->addPendingNodeConnection(
|
|
64
|
+
shared_from_this(), nullptr, AudioNodeManager::ConnectionType::DISCONNECT_ALL);
|
|
65
|
+
}
|
|
57
66
|
}
|
|
58
67
|
|
|
59
68
|
void AudioNode::disconnect(const std::shared_ptr<AudioNode> &node) {
|
|
60
|
-
context_
|
|
61
|
-
|
|
69
|
+
if (std::shared_ptr<BaseAudioContext> context = context_.lock()) {
|
|
70
|
+
context->getNodeManager()->addPendingNodeConnection(
|
|
71
|
+
shared_from_this(), node, AudioNodeManager::ConnectionType::DISCONNECT);
|
|
72
|
+
}
|
|
62
73
|
}
|
|
63
74
|
|
|
64
75
|
void AudioNode::disconnect(const std::shared_ptr<AudioParam> ¶m) {
|
|
65
|
-
context_
|
|
66
|
-
|
|
76
|
+
if (std::shared_ptr<BaseAudioContext> context = context_.lock()) {
|
|
77
|
+
context->getNodeManager()->addPendingParamConnection(
|
|
78
|
+
shared_from_this(), param, AudioNodeManager::ConnectionType::DISCONNECT);
|
|
79
|
+
}
|
|
67
80
|
}
|
|
68
81
|
|
|
69
82
|
bool AudioNode::isEnabled() const {
|
|
@@ -147,23 +160,25 @@ std::shared_ptr<AudioBus> AudioNode::processAudio(
|
|
|
147
160
|
|
|
148
161
|
// Finally, process the node itself.
|
|
149
162
|
return processNode(processingBus, framesToProcess);
|
|
150
|
-
;
|
|
151
163
|
}
|
|
152
164
|
|
|
153
165
|
bool AudioNode::isAlreadyProcessed() {
|
|
154
|
-
|
|
166
|
+
if (std::shared_ptr<BaseAudioContext> context = context_.lock()) {
|
|
167
|
+
std::size_t currentSampleFrame = context->getCurrentSampleFrame();
|
|
168
|
+
|
|
169
|
+
// check if the node has already been processed for this rendering quantum
|
|
170
|
+
if (currentSampleFrame == lastRenderedFrame_) {
|
|
171
|
+
return true;
|
|
172
|
+
}
|
|
155
173
|
|
|
156
|
-
|
|
174
|
+
// Update the last rendered frame before processing node and its inputs.
|
|
175
|
+
lastRenderedFrame_ = currentSampleFrame;
|
|
157
176
|
|
|
158
|
-
|
|
159
|
-
if (currentSampleFrame == lastRenderedFrame_) {
|
|
160
|
-
return true;
|
|
177
|
+
return false;
|
|
161
178
|
}
|
|
162
179
|
|
|
163
|
-
//
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
return false;
|
|
180
|
+
// If context is invalid, consider it as already processed to avoid processing
|
|
181
|
+
return true;
|
|
167
182
|
}
|
|
168
183
|
|
|
169
184
|
std::shared_ptr<AudioBus> AudioNode::processInputs(
|
|
@@ -19,7 +19,7 @@ class AudioParam;
|
|
|
19
19
|
|
|
20
20
|
class AudioNode : public std::enable_shared_from_this<AudioNode> {
|
|
21
21
|
public:
|
|
22
|
-
explicit AudioNode(BaseAudioContext
|
|
22
|
+
explicit AudioNode(std::shared_ptr<BaseAudioContext> context);
|
|
23
23
|
virtual ~AudioNode();
|
|
24
24
|
|
|
25
25
|
int getNumberOfInputs() const;
|
|
@@ -47,13 +47,13 @@ class AudioNode : public std::enable_shared_from_this<AudioNode> {
|
|
|
47
47
|
friend class AudioDestinationNode;
|
|
48
48
|
friend class ConvolverNode;
|
|
49
49
|
friend class DelayNodeHostObject;
|
|
50
|
+
int channelCount_ = 2;
|
|
50
51
|
|
|
51
|
-
BaseAudioContext
|
|
52
|
+
std::weak_ptr<BaseAudioContext> context_;
|
|
52
53
|
std::shared_ptr<AudioBus> audioBus_;
|
|
53
54
|
|
|
54
55
|
int numberOfInputs_ = 1;
|
|
55
56
|
int numberOfOutputs_ = 1;
|
|
56
|
-
int channelCount_ = 2;
|
|
57
57
|
ChannelCountMode channelCountMode_ = ChannelCountMode::MAX;
|
|
58
58
|
ChannelInterpretation channelInterpretation_ =
|
|
59
59
|
|
|
@@ -12,7 +12,7 @@ AudioParam::AudioParam(
|
|
|
12
12
|
float defaultValue,
|
|
13
13
|
float minValue,
|
|
14
14
|
float maxValue,
|
|
15
|
-
BaseAudioContext
|
|
15
|
+
std::shared_ptr<BaseAudioContext> context)
|
|
16
16
|
: context_(context),
|
|
17
17
|
value_(defaultValue),
|
|
18
18
|
defaultValue_(defaultValue),
|
|
@@ -20,13 +20,13 @@ AudioParam::AudioParam(
|
|
|
20
20
|
maxValue_(maxValue),
|
|
21
21
|
eventsQueue_(),
|
|
22
22
|
eventScheduler_(32),
|
|
23
|
+
startTime_(0),
|
|
24
|
+
endTime_(0),
|
|
25
|
+
startValue_(defaultValue),
|
|
26
|
+
endValue_(defaultValue),
|
|
23
27
|
audioBus_(std::make_shared<AudioBus>(RENDER_QUANTUM_SIZE, 1, context->getSampleRate())) {
|
|
24
28
|
inputBuses_.reserve(4);
|
|
25
29
|
inputNodes_.reserve(4);
|
|
26
|
-
startTime_ = 0;
|
|
27
|
-
endTime_ = 0;
|
|
28
|
-
startValue_ = value_;
|
|
29
|
-
endValue_ = value_;
|
|
30
30
|
// Default calculation function just returns the static value
|
|
31
31
|
calculateValue_ = [this](double, double, float, float, double) {
|
|
32
32
|
return value_;
|
|
@@ -258,7 +258,10 @@ std::shared_ptr<AudioBus> AudioParam::processARateParam(int framesToProcess, dou
|
|
|
258
258
|
processScheduledEvents();
|
|
259
259
|
auto processingBus = calculateInputs(audioBus_, framesToProcess);
|
|
260
260
|
|
|
261
|
-
|
|
261
|
+
std::shared_ptr<BaseAudioContext> context = context_.lock();
|
|
262
|
+
if (context == nullptr)
|
|
263
|
+
return processingBus;
|
|
264
|
+
float sampleRate = context->getSampleRate();
|
|
262
265
|
float *busData = processingBus->getChannel(0)->getData();
|
|
263
266
|
float timeCache = time;
|
|
264
267
|
float timeStep = 1.0f / sampleRate;
|
|
@@ -21,7 +21,7 @@ class AudioParam {
|
|
|
21
21
|
float defaultValue,
|
|
22
22
|
float minValue,
|
|
23
23
|
float maxValue,
|
|
24
|
-
BaseAudioContext
|
|
24
|
+
std::shared_ptr<BaseAudioContext> context);
|
|
25
25
|
|
|
26
26
|
/// JS-Thread only methods
|
|
27
27
|
/// These methods are called only from HostObjects invoked on the JS thread.
|
|
@@ -93,7 +93,7 @@ class AudioParam {
|
|
|
93
93
|
|
|
94
94
|
private:
|
|
95
95
|
// Core parameter state
|
|
96
|
-
BaseAudioContext
|
|
96
|
+
std::weak_ptr<BaseAudioContext> context_;
|
|
97
97
|
float value_;
|
|
98
98
|
float defaultValue_;
|
|
99
99
|
float minValue_;
|
|
@@ -35,12 +35,13 @@ namespace audioapi {
|
|
|
35
35
|
|
|
36
36
|
BaseAudioContext::BaseAudioContext(
|
|
37
37
|
const std::shared_ptr<IAudioEventHandlerRegistry> &audioEventHandlerRegistry,
|
|
38
|
-
const RuntimeRegistry &runtimeRegistry)
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
const RuntimeRegistry &runtimeRegistry)
|
|
39
|
+
: nodeManager_(std::make_shared<AudioNodeManager>()),
|
|
40
|
+
audioEventHandlerRegistry_(audioEventHandlerRegistry),
|
|
41
|
+
runtimeRegistry_(runtimeRegistry) {}
|
|
41
42
|
|
|
42
|
-
|
|
43
|
-
|
|
43
|
+
void BaseAudioContext::initialize() {
|
|
44
|
+
destination_ = std::make_shared<AudioDestinationNode>(shared_from_this());
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
std::string BaseAudioContext::getState() {
|
|
@@ -78,7 +79,8 @@ std::shared_ptr<WorkletSourceNode> BaseAudioContext::createWorkletSourceNode(
|
|
|
78
79
|
std::weak_ptr<worklets::WorkletRuntime> runtime,
|
|
79
80
|
bool shouldLockRuntime) {
|
|
80
81
|
WorkletsRunner workletRunner(runtime, shareableWorklet, shouldLockRuntime);
|
|
81
|
-
auto workletSourceNode =
|
|
82
|
+
auto workletSourceNode =
|
|
83
|
+
std::make_shared<WorkletSourceNode>(shared_from_this(), std::move(workletRunner));
|
|
82
84
|
nodeManager_->addSourceNode(workletSourceNode);
|
|
83
85
|
return workletSourceNode;
|
|
84
86
|
}
|
|
@@ -91,7 +93,7 @@ std::shared_ptr<WorkletNode> BaseAudioContext::createWorkletNode(
|
|
|
91
93
|
bool shouldLockRuntime) {
|
|
92
94
|
WorkletsRunner workletRunner(runtime, shareableWorklet, shouldLockRuntime);
|
|
93
95
|
auto workletNode = std::make_shared<WorkletNode>(
|
|
94
|
-
|
|
96
|
+
shared_from_this(), bufferLength, inputChannelCount, std::move(workletRunner));
|
|
95
97
|
nodeManager_->addProcessingNode(workletNode);
|
|
96
98
|
return workletNode;
|
|
97
99
|
}
|
|
@@ -102,32 +104,32 @@ std::shared_ptr<WorkletProcessingNode> BaseAudioContext::createWorkletProcessing
|
|
|
102
104
|
bool shouldLockRuntime) {
|
|
103
105
|
WorkletsRunner workletRunner(runtime, shareableWorklet, shouldLockRuntime);
|
|
104
106
|
auto workletProcessingNode =
|
|
105
|
-
std::make_shared<WorkletProcessingNode>(
|
|
107
|
+
std::make_shared<WorkletProcessingNode>(shared_from_this(), std::move(workletRunner));
|
|
106
108
|
nodeManager_->addProcessingNode(workletProcessingNode);
|
|
107
109
|
return workletProcessingNode;
|
|
108
110
|
}
|
|
109
111
|
|
|
110
112
|
std::shared_ptr<RecorderAdapterNode> BaseAudioContext::createRecorderAdapter() {
|
|
111
|
-
auto recorderAdapter = std::make_shared<RecorderAdapterNode>(
|
|
113
|
+
auto recorderAdapter = std::make_shared<RecorderAdapterNode>(shared_from_this());
|
|
112
114
|
nodeManager_->addProcessingNode(recorderAdapter);
|
|
113
115
|
return recorderAdapter;
|
|
114
116
|
}
|
|
115
117
|
|
|
116
118
|
std::shared_ptr<OscillatorNode> BaseAudioContext::createOscillator() {
|
|
117
|
-
auto oscillator = std::make_shared<OscillatorNode>(
|
|
119
|
+
auto oscillator = std::make_shared<OscillatorNode>(shared_from_this());
|
|
118
120
|
nodeManager_->addSourceNode(oscillator);
|
|
119
121
|
return oscillator;
|
|
120
122
|
}
|
|
121
123
|
|
|
122
124
|
std::shared_ptr<ConstantSourceNode> BaseAudioContext::createConstantSource() {
|
|
123
|
-
auto constantSource = std::make_shared<ConstantSourceNode>(
|
|
125
|
+
auto constantSource = std::make_shared<ConstantSourceNode>(shared_from_this());
|
|
124
126
|
nodeManager_->addSourceNode(constantSource);
|
|
125
127
|
return constantSource;
|
|
126
128
|
}
|
|
127
129
|
|
|
128
130
|
std::shared_ptr<StreamerNode> BaseAudioContext::createStreamer() {
|
|
129
131
|
#if !RN_AUDIO_API_FFMPEG_DISABLED
|
|
130
|
-
auto streamer = std::make_shared<StreamerNode>(
|
|
132
|
+
auto streamer = std::make_shared<StreamerNode>(shared_from_this());
|
|
131
133
|
nodeManager_->addSourceNode(streamer);
|
|
132
134
|
return streamer;
|
|
133
135
|
#else
|
|
@@ -136,25 +138,25 @@ std::shared_ptr<StreamerNode> BaseAudioContext::createStreamer() {
|
|
|
136
138
|
}
|
|
137
139
|
|
|
138
140
|
std::shared_ptr<GainNode> BaseAudioContext::createGain() {
|
|
139
|
-
auto gain = std::make_shared<GainNode>(
|
|
141
|
+
auto gain = std::make_shared<GainNode>(shared_from_this());
|
|
140
142
|
nodeManager_->addProcessingNode(gain);
|
|
141
143
|
return gain;
|
|
142
144
|
}
|
|
143
145
|
|
|
144
146
|
std::shared_ptr<DelayNode> BaseAudioContext::createDelay(float maxDelayTime) {
|
|
145
|
-
auto delay = std::make_shared<DelayNode>(
|
|
147
|
+
auto delay = std::make_shared<DelayNode>(shared_from_this(), maxDelayTime);
|
|
146
148
|
nodeManager_->addProcessingNode(delay);
|
|
147
149
|
return delay;
|
|
148
150
|
}
|
|
149
151
|
|
|
150
152
|
std::shared_ptr<StereoPannerNode> BaseAudioContext::createStereoPanner() {
|
|
151
|
-
auto stereoPanner = std::make_shared<StereoPannerNode>(
|
|
153
|
+
auto stereoPanner = std::make_shared<StereoPannerNode>(shared_from_this());
|
|
152
154
|
nodeManager_->addProcessingNode(stereoPanner);
|
|
153
155
|
return stereoPanner;
|
|
154
156
|
}
|
|
155
157
|
|
|
156
158
|
std::shared_ptr<BiquadFilterNode> BaseAudioContext::createBiquadFilter() {
|
|
157
|
-
auto biquadFilter = std::make_shared<BiquadFilterNode>(
|
|
159
|
+
auto biquadFilter = std::make_shared<BiquadFilterNode>(shared_from_this());
|
|
158
160
|
nodeManager_->addProcessingNode(biquadFilter);
|
|
159
161
|
return biquadFilter;
|
|
160
162
|
}
|
|
@@ -162,20 +164,21 @@ std::shared_ptr<BiquadFilterNode> BaseAudioContext::createBiquadFilter() {
|
|
|
162
164
|
std::shared_ptr<IIRFilterNode> BaseAudioContext::createIIRFilter(
|
|
163
165
|
const std::vector<float> &feedforward,
|
|
164
166
|
const std::vector<float> &feedback) {
|
|
165
|
-
auto iirFilter = std::make_shared<IIRFilterNode>(
|
|
167
|
+
auto iirFilter = std::make_shared<IIRFilterNode>(shared_from_this(), feedforward, feedback);
|
|
166
168
|
nodeManager_->addProcessingNode(iirFilter);
|
|
167
169
|
return iirFilter;
|
|
168
170
|
}
|
|
169
171
|
|
|
170
172
|
std::shared_ptr<AudioBufferSourceNode> BaseAudioContext::createBufferSource(bool pitchCorrection) {
|
|
171
|
-
auto bufferSource = std::make_shared<AudioBufferSourceNode>(
|
|
173
|
+
auto bufferSource = std::make_shared<AudioBufferSourceNode>(shared_from_this(), pitchCorrection);
|
|
172
174
|
nodeManager_->addSourceNode(bufferSource);
|
|
173
175
|
return bufferSource;
|
|
174
176
|
}
|
|
175
177
|
|
|
176
178
|
std::shared_ptr<AudioBufferQueueSourceNode> BaseAudioContext::createBufferQueueSource(
|
|
177
179
|
bool pitchCorrection) {
|
|
178
|
-
auto bufferSource =
|
|
180
|
+
auto bufferSource =
|
|
181
|
+
std::make_shared<AudioBufferQueueSourceNode>(shared_from_this(), pitchCorrection);
|
|
179
182
|
nodeManager_->addSourceNode(bufferSource);
|
|
180
183
|
return bufferSource;
|
|
181
184
|
}
|
|
@@ -193,7 +196,7 @@ std::shared_ptr<PeriodicWave> BaseAudioContext::createPeriodicWave(
|
|
|
193
196
|
}
|
|
194
197
|
|
|
195
198
|
std::shared_ptr<AnalyserNode> BaseAudioContext::createAnalyser() {
|
|
196
|
-
auto analyser = std::make_shared<AnalyserNode>(
|
|
199
|
+
auto analyser = std::make_shared<AnalyserNode>(shared_from_this());
|
|
197
200
|
nodeManager_->addProcessingNode(analyser);
|
|
198
201
|
return analyser;
|
|
199
202
|
}
|
|
@@ -201,7 +204,8 @@ std::shared_ptr<AnalyserNode> BaseAudioContext::createAnalyser() {
|
|
|
201
204
|
std::shared_ptr<ConvolverNode> BaseAudioContext::createConvolver(
|
|
202
205
|
std::shared_ptr<AudioBuffer> buffer,
|
|
203
206
|
bool disableNormalization) {
|
|
204
|
-
auto convolver =
|
|
207
|
+
auto convolver =
|
|
208
|
+
std::make_shared<ConvolverNode>(shared_from_this(), buffer, disableNormalization);
|
|
205
209
|
nodeManager_->addProcessingNode(convolver);
|
|
206
210
|
return convolver;
|
|
207
211
|
}
|
|
@@ -38,13 +38,15 @@ class WorkletNode;
|
|
|
38
38
|
class WorkletProcessingNode;
|
|
39
39
|
class StreamerNode;
|
|
40
40
|
|
|
41
|
-
class BaseAudioContext {
|
|
41
|
+
class BaseAudioContext : public std::enable_shared_from_this<BaseAudioContext> {
|
|
42
42
|
public:
|
|
43
43
|
explicit BaseAudioContext(
|
|
44
44
|
const std::shared_ptr<IAudioEventHandlerRegistry> &audioEventHandlerRegistry,
|
|
45
45
|
const RuntimeRegistry &runtimeRegistry);
|
|
46
46
|
virtual ~BaseAudioContext() = default;
|
|
47
47
|
|
|
48
|
+
virtual void initialize();
|
|
49
|
+
|
|
48
50
|
std::string getState();
|
|
49
51
|
[[nodiscard]] float getSampleRate() const;
|
|
50
52
|
[[nodiscard]] double getCurrentTime() const;
|
|
@@ -12,23 +12,20 @@
|
|
|
12
12
|
#include <vector>
|
|
13
13
|
|
|
14
14
|
namespace audioapi {
|
|
15
|
-
AnalyserNode::AnalyserNode(
|
|
15
|
+
AnalyserNode::AnalyserNode(std::shared_ptr<BaseAudioContext> context)
|
|
16
16
|
: AudioNode(context),
|
|
17
17
|
fftSize_(2048),
|
|
18
18
|
minDecibels_(-100),
|
|
19
19
|
maxDecibels_(-30),
|
|
20
20
|
smoothingTimeConstant_(0.8),
|
|
21
|
-
windowType_(WindowType::BLACKMAN)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
complexData_ = std::vector<std::complex<float>>(fftSize_);
|
|
29
|
-
|
|
21
|
+
windowType_(WindowType::BLACKMAN),
|
|
22
|
+
inputBuffer_(std::make_unique<CircularAudioArray>(MAX_FFT_SIZE * 2)),
|
|
23
|
+
tempBuffer_(std::make_unique<AudioArray>(fftSize_)),
|
|
24
|
+
magnitudeBuffer_(std::make_unique<AudioArray>(fftSize_ / 2)),
|
|
25
|
+
downMixBus_(std::make_unique<AudioBus>(RENDER_QUANTUM_SIZE, 1, context->getSampleRate())),
|
|
26
|
+
fft_(std::make_unique<dsp::FFT>(fftSize_)),
|
|
27
|
+
complexData_(std::vector<std::complex<float>>(fftSize_)) {
|
|
30
28
|
setWindowData(windowType_, fftSize_);
|
|
31
|
-
|
|
32
29
|
isInitialized_ = true;
|
|
33
30
|
}
|
|
34
31
|
|
|
@@ -19,7 +19,7 @@ class CircularAudioArray;
|
|
|
19
19
|
class AnalyserNode : public AudioNode {
|
|
20
20
|
public:
|
|
21
21
|
enum class WindowType { BLACKMAN, HANN };
|
|
22
|
-
explicit AnalyserNode(BaseAudioContext
|
|
22
|
+
explicit AnalyserNode(std::shared_ptr<BaseAudioContext> context);
|
|
23
23
|
|
|
24
24
|
int getFftSize() const;
|
|
25
25
|
int getFrequencyBinCount() const;
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
namespace audioapi {
|
|
9
9
|
|
|
10
|
-
AudioDestinationNode::AudioDestinationNode(BaseAudioContext
|
|
10
|
+
AudioDestinationNode::AudioDestinationNode(std::shared_ptr<BaseAudioContext> context)
|
|
11
11
|
: AudioNode(context), currentSampleFrame_(0) {
|
|
12
12
|
numberOfOutputs_ = 0;
|
|
13
13
|
numberOfInputs_ = 1;
|
|
@@ -20,7 +20,11 @@ std::size_t AudioDestinationNode::getCurrentSampleFrame() const {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
double AudioDestinationNode::getCurrentTime() const {
|
|
23
|
-
|
|
23
|
+
if (std::shared_ptr<BaseAudioContext> context = context_.lock()) {
|
|
24
|
+
return static_cast<double>(currentSampleFrame_) / context->getSampleRate();
|
|
25
|
+
} else {
|
|
26
|
+
return 0.0;
|
|
27
|
+
}
|
|
24
28
|
}
|
|
25
29
|
|
|
26
30
|
void AudioDestinationNode::renderAudio(
|
|
@@ -30,7 +34,9 @@ void AudioDestinationNode::renderAudio(
|
|
|
30
34
|
return;
|
|
31
35
|
}
|
|
32
36
|
|
|
33
|
-
context_
|
|
37
|
+
if (std::shared_ptr<BaseAudioContext> context = context_.lock()) {
|
|
38
|
+
context->getNodeManager()->preProcessGraph();
|
|
39
|
+
}
|
|
34
40
|
|
|
35
41
|
destinationBus->zero();
|
|
36
42
|
|
|
@@ -14,7 +14,7 @@ class BaseAudioContext;
|
|
|
14
14
|
|
|
15
15
|
class AudioDestinationNode : public AudioNode {
|
|
16
16
|
public:
|
|
17
|
-
explicit AudioDestinationNode(BaseAudioContext
|
|
17
|
+
explicit AudioDestinationNode(std::shared_ptr<BaseAudioContext> context);
|
|
18
18
|
|
|
19
19
|
std::size_t getCurrentSampleFrame() const;
|
|
20
20
|
double getCurrentTime() const;
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
|
|
39
39
|
namespace audioapi {
|
|
40
40
|
|
|
41
|
-
BiquadFilterNode::BiquadFilterNode(BaseAudioContext
|
|
41
|
+
BiquadFilterNode::BiquadFilterNode(std::shared_ptr<BaseAudioContext> context) : AudioNode(context) {
|
|
42
42
|
frequencyParam_ =
|
|
43
43
|
std::make_shared<AudioParam>(350.0, 0.0f, context->getNyquistFrequency(), context);
|
|
44
44
|
detuneParam_ = std::make_shared<AudioParam>(
|
|
@@ -57,6 +57,7 @@ BiquadFilterNode::BiquadFilterNode(BaseAudioContext *context) : AudioNode(contex
|
|
|
57
57
|
y2_.resize(MAX_CHANNEL_COUNT, 0.0f);
|
|
58
58
|
isInitialized_ = true;
|
|
59
59
|
channelCountMode_ = ChannelCountMode::MAX;
|
|
60
|
+
isInitialized_ = true;
|
|
60
61
|
}
|
|
61
62
|
|
|
62
63
|
std::string BiquadFilterNode::getType() {
|
|
@@ -118,7 +119,10 @@ void BiquadFilterNode::getFrequencyResponse(
|
|
|
118
119
|
double a1 = static_cast<double>(a1_);
|
|
119
120
|
double a2 = static_cast<double>(a2_);
|
|
120
121
|
|
|
121
|
-
|
|
122
|
+
std::shared_ptr<BaseAudioContext> context = context_.lock();
|
|
123
|
+
if (!context)
|
|
124
|
+
return;
|
|
125
|
+
float nyquist = context->getNyquistFrequency();
|
|
122
126
|
|
|
123
127
|
for (size_t i = 0; i < length; i++) {
|
|
124
128
|
// Convert from frequency in Hz to normalized frequency [0, 1]
|
|
@@ -330,17 +334,22 @@ void BiquadFilterNode::setAllpassCoefficients(float frequency, float Q) {
|
|
|
330
334
|
}
|
|
331
335
|
|
|
332
336
|
void BiquadFilterNode::applyFilter() {
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
337
|
+
// NyquistFrequency is half of the sample rate.
|
|
338
|
+
// Normalized frequency is therefore:
|
|
339
|
+
// frequency / (sampleRate / 2) = (2 * frequency) / sampleRate
|
|
340
|
+
float normalizedFrequency;
|
|
341
|
+
double currentTime;
|
|
342
|
+
if (std::shared_ptr<BaseAudioContext> context = context_.lock()) {
|
|
343
|
+
currentTime = context->getCurrentTime();
|
|
344
|
+
float frequency = frequencyParam_->processKRateParam(RENDER_QUANTUM_SIZE, currentTime);
|
|
345
|
+
normalizedFrequency = frequency / context->getNyquistFrequency();
|
|
346
|
+
} else {
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
336
349
|
float detune = detuneParam_->processKRateParam(RENDER_QUANTUM_SIZE, currentTime);
|
|
337
350
|
auto Q = QParam_->processKRateParam(RENDER_QUANTUM_SIZE, currentTime);
|
|
338
351
|
auto gain = gainParam_->processKRateParam(RENDER_QUANTUM_SIZE, currentTime);
|
|
339
352
|
|
|
340
|
-
// NyquistFrequency is half of the sample rate.
|
|
341
|
-
// Normalized frequency is therefore:
|
|
342
|
-
// frequency / (sampleRate / 2) = (2 * frequency) / sampleRate
|
|
343
|
-
float normalizedFrequency = frequency / context_->getNyquistFrequency();
|
|
344
353
|
if (detune != 0.0f) {
|
|
345
354
|
normalizedFrequency *= std::pow(2.0f, detune / 1200.0f);
|
|
346
355
|
}
|
|
@@ -54,7 +54,7 @@ class BiquadFilterNode : public AudioNode {
|
|
|
54
54
|
#endif // RN_AUDIO_API_TEST
|
|
55
55
|
|
|
56
56
|
public:
|
|
57
|
-
explicit BiquadFilterNode(BaseAudioContext
|
|
57
|
+
explicit BiquadFilterNode(std::shared_ptr<BaseAudioContext> context);
|
|
58
58
|
|
|
59
59
|
[[nodiscard]] std::string getType();
|
|
60
60
|
void setType(const std::string &type);
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
namespace audioapi {
|
|
14
14
|
ConvolverNode::ConvolverNode(
|
|
15
|
-
BaseAudioContext
|
|
15
|
+
std::shared_ptr<BaseAudioContext> context,
|
|
16
16
|
const std::shared_ptr<AudioBuffer> &buffer,
|
|
17
17
|
bool disableNormalization)
|
|
18
18
|
: AudioNode(context),
|
|
@@ -22,11 +22,11 @@ ConvolverNode::ConvolverNode(
|
|
|
22
22
|
scaleFactor_(1.0f),
|
|
23
23
|
intermediateBus_(nullptr),
|
|
24
24
|
buffer_(nullptr),
|
|
25
|
-
internalBuffer_(nullptr)
|
|
25
|
+
internalBuffer_(nullptr),
|
|
26
|
+
gainCalibrationSampleRate_(context->getSampleRate()),
|
|
27
|
+
normalize_(!disableNormalization) {
|
|
26
28
|
channelCount_ = 2;
|
|
27
29
|
channelCountMode_ = ChannelCountMode::CLAMPED_MAX;
|
|
28
|
-
normalize_ = !disableNormalization;
|
|
29
|
-
gainCalibrationSampleRate_ = context->getSampleRate();
|
|
30
30
|
setBuffer(buffer);
|
|
31
31
|
audioBus_ =
|
|
32
32
|
std::make_shared<AudioBus>(RENDER_QUANTUM_SIZE, channelCount_, context->getSampleRate());
|