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.
Files changed (62) hide show
  1. package/common/cpp/audioapi/AudioAPIModuleInstaller.h +2 -0
  2. package/common/cpp/audioapi/HostObjects/effects/DelayNodeHostObject.cpp +6 -2
  3. package/common/cpp/audioapi/core/AudioContext.cpp +15 -13
  4. package/common/cpp/audioapi/core/AudioContext.h +2 -1
  5. package/common/cpp/audioapi/core/AudioNode.cpp +39 -24
  6. package/common/cpp/audioapi/core/AudioNode.h +3 -3
  7. package/common/cpp/audioapi/core/AudioParam.cpp +9 -6
  8. package/common/cpp/audioapi/core/AudioParam.h +2 -2
  9. package/common/cpp/audioapi/core/BaseAudioContext.cpp +25 -21
  10. package/common/cpp/audioapi/core/BaseAudioContext.h +3 -1
  11. package/common/cpp/audioapi/core/analysis/AnalyserNode.cpp +8 -11
  12. package/common/cpp/audioapi/core/analysis/AnalyserNode.h +1 -1
  13. package/common/cpp/audioapi/core/destinations/AudioDestinationNode.cpp +9 -3
  14. package/common/cpp/audioapi/core/destinations/AudioDestinationNode.h +1 -1
  15. package/common/cpp/audioapi/core/effects/BiquadFilterNode.cpp +18 -9
  16. package/common/cpp/audioapi/core/effects/BiquadFilterNode.h +1 -1
  17. package/common/cpp/audioapi/core/effects/ConvolverNode.cpp +4 -4
  18. package/common/cpp/audioapi/core/effects/ConvolverNode.h +1 -1
  19. package/common/cpp/audioapi/core/effects/DelayNode.cpp +20 -11
  20. package/common/cpp/audioapi/core/effects/DelayNode.h +1 -1
  21. package/common/cpp/audioapi/core/effects/GainNode.cpp +12 -4
  22. package/common/cpp/audioapi/core/effects/GainNode.h +1 -1
  23. package/common/cpp/audioapi/core/effects/IIRFilterNode.cpp +6 -3
  24. package/common/cpp/audioapi/core/effects/IIRFilterNode.h +1 -1
  25. package/common/cpp/audioapi/core/effects/StereoPannerNode.cpp +7 -4
  26. package/common/cpp/audioapi/core/effects/StereoPannerNode.h +1 -1
  27. package/common/cpp/audioapi/core/effects/WorkletNode.cpp +3 -3
  28. package/common/cpp/audioapi/core/effects/WorkletNode.h +2 -2
  29. package/common/cpp/audioapi/core/effects/WorkletProcessingNode.cpp +7 -4
  30. package/common/cpp/audioapi/core/effects/WorkletProcessingNode.h +6 -2
  31. package/common/cpp/audioapi/core/sources/AudioBuffer.cpp +2 -3
  32. package/common/cpp/audioapi/core/sources/AudioBuffer.h +1 -1
  33. package/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.cpp +59 -25
  34. package/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.h +4 -2
  35. package/common/cpp/audioapi/core/sources/AudioBufferQueueSourceNode.cpp +18 -11
  36. package/common/cpp/audioapi/core/sources/AudioBufferQueueSourceNode.h +3 -1
  37. package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp +37 -21
  38. package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.h +3 -3
  39. package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.cpp +11 -11
  40. package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.h +4 -2
  41. package/common/cpp/audioapi/core/sources/ConstantSourceNode.cpp +16 -8
  42. package/common/cpp/audioapi/core/sources/ConstantSourceNode.h +1 -1
  43. package/common/cpp/audioapi/core/sources/OscillatorNode.cpp +30 -18
  44. package/common/cpp/audioapi/core/sources/OscillatorNode.h +1 -1
  45. package/common/cpp/audioapi/core/sources/RecorderAdapterNode.cpp +4 -4
  46. package/common/cpp/audioapi/core/sources/RecorderAdapterNode.h +1 -1
  47. package/common/cpp/audioapi/core/sources/StreamerNode.cpp +24 -10
  48. package/common/cpp/audioapi/core/sources/StreamerNode.h +4 -3
  49. package/common/cpp/audioapi/core/sources/WorkletSourceNode.cpp +11 -4
  50. package/common/cpp/audioapi/core/sources/WorkletSourceNode.h +6 -2
  51. package/common/cpp/test/RunTests.sh +1 -1
  52. package/common/cpp/test/src/AudioParamTest.cpp +10 -10
  53. package/common/cpp/test/src/AudioScheduledSourceTest.cpp +31 -15
  54. package/common/cpp/test/src/ConstantSourceTest.cpp +16 -14
  55. package/common/cpp/test/src/DelayTest.cpp +14 -13
  56. package/common/cpp/test/src/GainTest.cpp +10 -9
  57. package/common/cpp/test/src/IIRFilterTest.cpp +4 -4
  58. package/common/cpp/test/src/OscillatorTest.cpp +2 -2
  59. package/common/cpp/test/src/StereoPannerTest.cpp +14 -12
  60. package/common/cpp/test/src/biquad/BiquadFilterTest.cpp +25 -25
  61. package/common/cpp/test/src/biquad/BiquadFilterTest.h +3 -5
  62. 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
- return sizeof(float) * delayNode->context_->getSampleRate() *
18
- delayNode->getDelayTimeParam()->getMaxValue();
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 (playerHasBeenStarted_ && audioPlayer_->resume()) {
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 (!playerHasBeenStarted_ && audioPlayer_->start()) {
84
- playerHasBeenStarted_ = true;
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 playerHasBeenStarted_;
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 *context) : context_(context) {
14
- audioBus_ =
15
- std::make_shared<AudioBus>(RENDER_QUANTUM_SIZE, channelCount_, context->getSampleRate());
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_->getNodeManager()->addPendingNodeConnection(
46
- shared_from_this(), node, AudioNodeManager::ConnectionType::CONNECT);
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> &param) {
50
- context_->getNodeManager()->addPendingParamConnection(
51
- shared_from_this(), param, AudioNodeManager::ConnectionType::CONNECT);
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_->getNodeManager()->addPendingNodeConnection(
56
- shared_from_this(), nullptr, AudioNodeManager::ConnectionType::DISCONNECT_ALL);
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_->getNodeManager()->addPendingNodeConnection(
61
- shared_from_this(), node, AudioNodeManager::ConnectionType::DISCONNECT);
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> &param) {
65
- context_->getNodeManager()->addPendingParamConnection(
66
- shared_from_this(), param, AudioNodeManager::ConnectionType::DISCONNECT);
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
- assert(context_ != nullptr);
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
- std::size_t currentSampleFrame = context_->getCurrentSampleFrame();
174
+ // Update the last rendered frame before processing node and its inputs.
175
+ lastRenderedFrame_ = currentSampleFrame;
157
176
 
158
- // check if the node has already been processed for this rendering quantum
159
- if (currentSampleFrame == lastRenderedFrame_) {
160
- return true;
177
+ return false;
161
178
  }
162
179
 
163
- // Update the last rendered frame before processing node and its inputs.
164
- lastRenderedFrame_ = currentSampleFrame;
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 *context);
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 *context_;
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 *context)
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
- float sampleRate = context_->getSampleRate();
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 *context);
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 *context_;
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
- nodeManager_ = std::make_shared<AudioNodeManager>();
40
- destination_ = std::make_shared<AudioDestinationNode>(this);
38
+ const RuntimeRegistry &runtimeRegistry)
39
+ : nodeManager_(std::make_shared<AudioNodeManager>()),
40
+ audioEventHandlerRegistry_(audioEventHandlerRegistry),
41
+ runtimeRegistry_(runtimeRegistry) {}
41
42
 
42
- audioEventHandlerRegistry_ = audioEventHandlerRegistry;
43
- runtimeRegistry_ = runtimeRegistry;
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 = std::make_shared<WorkletSourceNode>(this, std::move(workletRunner));
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
- this, bufferLength, inputChannelCount, std::move(workletRunner));
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>(this, std::move(workletRunner));
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>(this);
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>(this);
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>(this);
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>(this);
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>(this);
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>(this, maxDelayTime);
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>(this);
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>(this);
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>(this, feedforward, feedback);
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>(this, pitchCorrection);
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 = std::make_shared<AudioBufferQueueSourceNode>(this, pitchCorrection);
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>(this);
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 = std::make_shared<ConvolverNode>(this, buffer, disableNormalization);
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(audioapi::BaseAudioContext *context)
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
- 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
-
27
- fft_ = std::make_unique<dsp::FFT>(fftSize_);
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 *context);
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 *context)
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
- return static_cast<double>(currentSampleFrame_) / context_->getSampleRate();
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_->getNodeManager()->preProcessGraph();
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 *context);
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 *context) : AudioNode(context) {
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
- float nyquist = context_->getNyquistFrequency();
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
- double currentTime = context_->getCurrentTime();
334
-
335
- float frequency = frequencyParam_->processKRateParam(RENDER_QUANTUM_SIZE, currentTime);
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 *context);
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 *context,
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());
@@ -21,7 +21,7 @@ class AudioBuffer;
21
21
  class ConvolverNode : public AudioNode {
22
22
  public:
23
23
  explicit ConvolverNode(
24
- BaseAudioContext *context,
24
+ std::shared_ptr<BaseAudioContext> context,
25
25
  const std::shared_ptr<AudioBuffer> &buffer,
26
26
  bool disableNormalization);
27
27