Skip to content

Commit ebffe07

Browse files
refactor: destination node initialization and ownership
1 parent bc8c628 commit ebffe07

14 files changed

Lines changed: 47 additions & 157 deletions

packages/react-native-audio-api/common/cpp/audioapi/HostObjects/BaseAudioContextHostObject.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,8 @@ BaseAudioContextHostObject::BaseAudioContextHostObject(
3535
: context_(context),
3636
promiseVendor_(std::make_shared<PromiseVendor>(runtime, callInvoker)),
3737
callInvoker_(callInvoker) {
38-
auto *destinationNode = context_->initialize();
3938
destination_ =
40-
std::make_shared<AudioDestinationNodeHostObject>(destinationNode, context_->getDestination());
39+
std::make_shared<AudioDestinationNodeHostObject>(context_);
4140

4241
addGetters(
4342
JSI_EXPORT_PROPERTY_GETTER(BaseAudioContextHostObject, destination),

packages/react-native-audio-api/common/cpp/audioapi/HostObjects/destinations/AudioDestinationNodeHostObject.cpp

Lines changed: 0 additions & 64 deletions
This file was deleted.
Lines changed: 9 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,24 @@
11
#pragma once
22

3+
#include <audioapi/HostObjects/AudioNodeHostObject.h>
34
#include <audioapi/core/destinations/AudioDestinationNode.h>
4-
#include <audioapi/core/utils/graph/HostGraph.hpp>
5-
#include <audioapi/jsi/JsiHostObject.h>
65
#include <audioapi/types/NodeOptions.h>
76

87
#include <memory>
98

109
namespace audioapi {
1110
using namespace facebook;
1211

13-
/// HostObject for AudiodestinationNode, which is the end point of the audio graph.
14-
/// It is treated differently than other AudioNodes, because it shares ownership of underlying AudioDestinationNode with BaseAudioContext.
15-
/// Hence all AudioNodeHostObject methods and proprties has to be implemented duplicated.
16-
class AudioDestinationNodeHostObject : public JsiHostObject {
12+
class AudioDestinationNodeHostObject : public AudioNodeHostObject {
1713
public:
1814
explicit AudioDestinationNodeHostObject(
19-
utils::graph::HostGraph::Node *node,
20-
std::shared_ptr<AudioDestinationNode> destination,
21-
const AudioDestinationOptions &options = AudioDestinationOptions());
22-
23-
[[nodiscard]] utils::graph::HostGraph::Node *rawNode() const {
24-
return node_;
25-
}
26-
27-
JSI_PROPERTY_GETTER_DECL(numberOfInputs);
28-
JSI_PROPERTY_GETTER_DECL(numberOfOutputs);
29-
JSI_PROPERTY_GETTER_DECL(channelCount);
30-
JSI_PROPERTY_GETTER_DECL(channelCountMode);
31-
JSI_PROPERTY_GETTER_DECL(channelInterpretation);
32-
33-
JSI_HOST_FUNCTION_DECL(connect);
34-
JSI_HOST_FUNCTION_DECL(disconnect);
35-
36-
private:
37-
// borrowed from BaseAudioContext's graph - non-owning
38-
// no risk of dangling pointer here since destination node in TS holds ref to context =>
39-
// destination HO will not outlive context HO => graph is owned by context HO
40-
utils::graph::HostGraph::Node *node_; // borrowed from BaseAudioContext's graph - non-owning
41-
std::shared_ptr<AudioDestinationNode> destination_;
42-
43-
const int numberOfInputs_;
44-
const int numberOfOutputs_;
45-
size_t channelCount_;
46-
const ChannelCountMode channelCountMode_;
47-
const ChannelInterpretation channelInterpretation_;
15+
const std::shared_ptr<BaseAudioContext> &context,
16+
const AudioDestinationOptions &options = AudioDestinationOptions())
17+
: AudioNodeHostObject(context->getGraph(),
18+
std::make_unique<AudioDestinationNode>(context),
19+
options) {
20+
context->initialize(static_cast<AudioDestinationNode*>(node_->handle->audioNode.get()));
21+
}
4822
};
4923

5024
} // namespace audioapi

packages/react-native-audio-api/common/cpp/audioapi/core/AudioContext.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ AudioContext::~AudioContext() {
2222
}
2323
}
2424

25-
utils::graph::HostGraph::Node *AudioContext::initialize() {
26-
auto *destinationNode = BaseAudioContext::initialize();
25+
void AudioContext::initialize(const AudioDestinationNode *destination) {
26+
BaseAudioContext::initialize(destination);
2727
#ifdef ANDROID
2828
audioPlayer_ = std::make_shared<AudioPlayer>(
2929
[this](DSPAudioBuffer *buf, int n) { processGraph(buf, n); },
@@ -35,7 +35,6 @@ utils::graph::HostGraph::Node *AudioContext::initialize() {
3535
getSampleRate(),
3636
destination_->getChannelCount());
3737
#endif
38-
return destinationNode;
3938
}
4039

4140
void AudioContext::close() {

packages/react-native-audio-api/common/cpp/audioapi/core/AudioContext.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
#include <audioapi/core/utils/worklets/SafeIncludes.h>
55
#include <audioapi/utils/AudioBuffer.hpp>
66

7-
#include <functional>
87
#include <memory>
98

109
namespace audioapi {
@@ -26,7 +25,11 @@ class AudioContext : public BaseAudioContext {
2625
bool resume();
2726
bool suspend();
2827
bool start();
29-
utils::graph::HostGraph::Node *initialize() override;
28+
29+
/// @brief Initializes native audio player and assigns the audio destination node to the context.
30+
/// @param destination The audio destination node to be associated with the context.
31+
/// @note This method must be called before the audio context can be used for processing audio.
32+
void initialize(const AudioDestinationNode *destination) final;
3033

3134
private:
3235
#ifdef ANDROID

packages/react-native-audio-api/common/cpp/audioapi/core/BaseAudioContext.cpp

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
#include <audioapi/core/BaseAudioContext.h>
22
#include <audioapi/core/destinations/AudioDestinationNode.h>
33
#include <audioapi/core/utils/AudioDecoder.h>
4-
#include <audioapi/core/utils/graph/DestinationGraphObject.hpp>
54
#include <audioapi/core/utils/worklets/SafeIncludes.h>
65
#include <audioapi/events/AudioEventHandlerRegistry.h>
76
#include <audioapi/utils/AudioArray.hpp>
87
#include <audioapi/utils/CircularArray.hpp>
98
#include <memory>
10-
#include <utility>
119
#include <vector>
1210

1311
namespace audioapi {
@@ -26,9 +24,8 @@ BaseAudioContext::BaseAudioContext(
2624
AUDIO_SCHEDULER_CAPACITY)),
2725
graph_(std::make_shared<utils::graph::Graph>(AUDIO_SCHEDULER_CAPACITY, disposer_.get())) {}
2826

29-
utils::graph::HostGraph::Node *BaseAudioContext::initialize() {
30-
destination_ = std::make_shared<AudioDestinationNode>(shared_from_this());
31-
return graph_->addNode(std::make_unique<DestinationGraphObject>(destination_.get()));
27+
void BaseAudioContext::initialize(const AudioDestinationNode *destination) {
28+
destination_ = destination;
3229
}
3330

3431
ContextState BaseAudioContext::getState() {
@@ -53,10 +50,6 @@ double BaseAudioContext::getCurrentTime() const {
5350
return static_cast<double>(getCurrentSampleFrame()) / getSampleRate();
5451
}
5552

56-
std::shared_ptr<AudioDestinationNode> BaseAudioContext::getDestination() const {
57-
return destination_;
58-
}
59-
6053
void BaseAudioContext::setState(audioapi::ContextState state) {
6154
state_.store(state, std::memory_order_release);
6255
}
@@ -122,7 +115,7 @@ void BaseAudioContext::processGraph(DSPAudioBuffer *buffer, int numFrames) {
122115
auto audioNode = node.asAudioNode();
123116
if (audioNode != nullptr) {
124117
audioNode->process(inputs, numFrames);
125-
if (audioNode == destination_.get()) {
118+
if (audioNode == destination_) {
126119
buffer->copy(*audioNode->getOutputBuffer(), 0, 0, numFrames);
127120
}
128121
}

packages/react-native-audio-api/common/cpp/audioapi/core/BaseAudioContext.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ class BaseAudioContext : public std::enable_shared_from_this<BaseAudioContext> {
3636
[[nodiscard]] float getSampleRate() const;
3737
[[nodiscard]] double getCurrentTime() const;
3838
[[nodiscard]] std::size_t getCurrentSampleFrame() const;
39-
std::shared_ptr<AudioDestinationNode> getDestination() const;
4039

4140
void setState(ContextState state);
4241

@@ -51,9 +50,10 @@ class BaseAudioContext : public std::enable_shared_from_this<BaseAudioContext> {
5150
const RuntimeRegistry &getRuntimeRegistry() const;
5251
utils::DisposerImpl<utils::graph::Graph::kDisposerPayloadSize> *getDisposer() const;
5352

54-
/// @brief Initializes audio destination and its corresponding graph node and adds it to graph. Must be called before using the context.
55-
/// @return The graph node corresponding to the audio destination.
56-
virtual utils::graph::HostGraph::Node *initialize();
53+
/// @brief Assigns the audio destination node to the context.
54+
/// @param destination The audio destination node to be associated with the context.
55+
/// @note This method must be called before the audio context can be used for processing audio.
56+
virtual void initialize(const AudioDestinationNode *destination);
5757

5858
void inline processAudioEvents() {
5959
audioEventScheduler_.processAllEvents(*this);
@@ -74,7 +74,7 @@ class BaseAudioContext : public std::enable_shared_from_this<BaseAudioContext> {
7474

7575
protected:
7676
std::atomic<std::size_t> currentSampleFrame_{0};
77-
std::shared_ptr<AudioDestinationNode> destination_;
77+
const AudioDestinationNode *destination_;
7878

7979
private:
8080
std::atomic<ContextState> state_;

packages/react-native-audio-api/common/cpp/audioapi/core/utils/graph/DestinationGraphObject.hpp

Lines changed: 0 additions & 29 deletions
This file was deleted.

packages/react-native-audio-api/common/cpp/test/src/core/effects/DelayTest.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include <audioapi/core/OfflineAudioContext.h>
2+
#include <audioapi/core/destinations/AudioDestinationNode.h>
23
#include <audioapi/core/effects/DelayNode.h>
34
#include <audioapi/core/utils/worklets/SafeIncludes.h>
45
#include <audioapi/types/NodeOptions.h>
@@ -14,13 +15,15 @@ class DelayTest : public ::testing::Test {
1415
protected:
1516
std::shared_ptr<MockAudioEventHandlerRegistry> eventRegistry;
1617
std::shared_ptr<OfflineAudioContext> context;
18+
std::shared_ptr<AudioDestinationNode> destination;
1719
static constexpr int sampleRate = 44100;
1820

1921
void SetUp() override {
2022
eventRegistry = std::make_shared<MockAudioEventHandlerRegistry>();
2123
context = std::make_shared<OfflineAudioContext>(
2224
2, 5 * sampleRate, sampleRate, eventRegistry, RuntimeRegistry{});
23-
context->initialize();
25+
destination = std::make_shared<AudioDestinationNode>(context);
26+
context->initialize(destination.get());
2427
}
2528
};
2629

packages/react-native-audio-api/common/cpp/test/src/core/effects/GainTest.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include <audioapi/core/OfflineAudioContext.h>
2+
#include <audioapi/core/destinations/AudioDestinationNode.h>
23
#include <audioapi/core/effects/GainNode.h>
34
#include <audioapi/core/utils/worklets/SafeIncludes.h>
45
#include <audioapi/types/NodeOptions.h>
@@ -14,13 +15,15 @@ class GainTest : public ::testing::Test {
1415
protected:
1516
std::shared_ptr<MockAudioEventHandlerRegistry> eventRegistry;
1617
std::shared_ptr<OfflineAudioContext> context;
18+
std::shared_ptr<AudioDestinationNode> destination;
1719
static constexpr int sampleRate = 44100;
1820

1921
void SetUp() override {
2022
eventRegistry = std::make_shared<MockAudioEventHandlerRegistry>();
2123
context = std::make_shared<OfflineAudioContext>(
2224
2, 5 * sampleRate, sampleRate, eventRegistry, RuntimeRegistry{});
23-
context->initialize();
25+
destination = std::make_shared<AudioDestinationNode>(context);
26+
context->initialize(destination.get());
2427
}
2528
};
2629

0 commit comments

Comments
 (0)