Skip to content

Commit 59a8293

Browse files
maciejmakowski2003Maciej Makowski
andauthored
Refactor/general context refactoring (#276)
* refactor: moved AudioPlayer to AudioContext * refactor: refactored number of frames render by one call of renderAudio to RENDER_QUANTUM_SIZE * fix: fixed bad access exception * ci: fixed linting --------- Co-authored-by: Maciej Makowski <maciej.makowski2608@gmail.com>
1 parent b58ba39 commit 59a8293

File tree

13 files changed

+90
-103
lines changed

13 files changed

+90
-103
lines changed

apps/fabric-example/ios/Podfile.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1656,7 +1656,7 @@ PODS:
16561656
- React-logger (= 0.76.5)
16571657
- React-perflogger (= 0.76.5)
16581658
- React-utils (= 0.76.5)
1659-
- RNAudioAPI (0.3.2):
1659+
- RNAudioAPI (0.4.0):
16601660
- DoubleConversion
16611661
- glog
16621662
- hermes-engine
@@ -2152,7 +2152,7 @@ SPEC CHECKSUMS:
21522152
React-utils: f584a494ac233c7857bab176416b0c49cb4037ba
21532153
ReactCodegen: 1f59af46efc9351f27046d90d9ceb5e99385f623
21542154
ReactCommon: 5809a8ee421b7219221a475b78180f8f34b5c5ec
2155-
RNAudioAPI: 0672a736922266bbb418cb6481d32204e8136988
2155+
RNAudioAPI: 8a98b4d1149f55f3815919576d50520fbab125f9
21562156
RNGestureHandler: e1dcb274c17ca0680a04d7ff357e35e37c384185
21572157
RNReanimated: 270e2df37d3a18e8270a9c461d9f90a374a97d04
21582158
RNScreens: 351f431ef2a042a1887d4d90e1c1024b8ae9d123

packages/react-native-audio-api/android/src/main/cpp/core/AudioPlayer.cpp

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,14 @@ AudioPlayer::AudioPlayer(
2222
->openStream(mStream_);
2323

2424
mBus_ = std::make_shared<AudioBus>(
25-
getSampleRate(), getBufferSizeInFrames(), CHANNEL_COUNT);
25+
getSampleRate(), RENDER_QUANTUM_SIZE, CHANNEL_COUNT);
2626
isInitialized_ = true;
2727
}
2828

2929
int AudioPlayer::getSampleRate() const {
3030
return mStream_->getSampleRate();
3131
}
3232

33-
int AudioPlayer::getBufferSizeInFrames() const {
34-
return mStream_->getBufferSizeInFrames();
35-
}
36-
3733
void AudioPlayer::start() {
3834
if (mStream_) {
3935
mStream_->requestStart();
@@ -59,14 +55,22 @@ DataCallbackResult AudioPlayer::onAudioReady(
5955
}
6056

6157
auto buffer = static_cast<float *>(audioData);
62-
renderAudio_(mBus_.get(), numFrames);
58+
int processedFrames = 0;
6359

64-
// TODO: optimize this with SIMD?
65-
for (int32_t i = 0; i < numFrames; i += 1) {
66-
for (int channel = 0; channel < CHANNEL_COUNT; channel += 1) {
67-
buffer[i * CHANNEL_COUNT + channel] =
68-
mBus_->getChannel(channel)->getData()[i];
60+
while (processedFrames < numFrames) {
61+
int framesToProcess =
62+
std::min(numFrames - processedFrames, RENDER_QUANTUM_SIZE);
63+
renderAudio_(mBus_.get(), framesToProcess);
64+
65+
// TODO: optimize this with SIMD?
66+
for (int i = 0; i < framesToProcess; i++) {
67+
for (int channel = 0; channel < CHANNEL_COUNT; channel += 1) {
68+
buffer[(processedFrames + i) * CHANNEL_COUNT + channel] =
69+
mBus_->getChannel(channel)->getData()[i];
70+
}
6971
}
72+
73+
processedFrames += framesToProcess;
7074
}
7175

7276
return DataCallbackResult::Continue;

packages/react-native-audio-api/android/src/main/cpp/core/AudioPlayer.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ class AudioPlayer : public AudioStreamDataCallback {
1515
explicit AudioPlayer(const std::function<void(AudioBus *, int)> &renderAudio);
1616

1717
[[nodiscard]] int getSampleRate() const;
18-
[[nodiscard]] int getBufferSizeInFrames() const;
1918
void start();
2019
void stop();
2120

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

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,42 @@
55
#endif
66

77
#include "AudioContext.h"
8+
#include "AudioDestinationNode.h"
89

910
namespace audioapi {
1011

1112
AudioContext::AudioContext() : BaseAudioContext() {
13+
#ifdef ANDROID
14+
audioPlayer_ = std::make_shared<AudioPlayer>(this->renderAudio());
15+
#else
16+
audioPlayer_ = std::make_shared<IOSAudioPlayer>(this->renderAudio());
17+
#endif
18+
sampleRate_ = audioPlayer_->getSampleRate();
19+
1220
audioPlayer_->start();
1321
}
1422

23+
AudioContext::~AudioContext() {
24+
if (isRunning()) {
25+
return;
26+
}
27+
28+
close();
29+
}
30+
1531
void AudioContext::close() {
1632
state_ = ContextState::CLOSED;
1733
audioPlayer_->stop();
1834
}
1935

36+
std::function<void(AudioBus *, int)> AudioContext::renderAudio() {
37+
if (!isRunning()) {
38+
return [](AudioBus *, int) {};
39+
}
40+
41+
return [this](AudioBus *data, int frames) {
42+
destination_->renderAudio(data, frames);
43+
};
44+
}
45+
2046
} // namespace audioapi

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,27 @@
55
#include "BaseAudioContext.h"
66

77
namespace audioapi {
8+
#ifdef ANDROID
9+
class AudioPlayer;
10+
#else
11+
class IOSAudioPlayer;
12+
#endif
813

914
class AudioContext : public BaseAudioContext {
1015
public:
1116
AudioContext();
17+
~AudioContext() override;
1218

1319
void close();
20+
21+
std::function<void(AudioBus *, int)> renderAudio();
22+
23+
private:
24+
#ifdef ANDROID
25+
std::shared_ptr<AudioPlayer> audioPlayer_;
26+
#else
27+
std::shared_ptr<IOSAudioPlayer> audioPlayer_;
28+
#endif
1429
};
1530

1631
} // namespace audioapi

packages/react-native-audio-api/common/cpp/core/AudioNode.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,7 @@ namespace audioapi {
99

1010
AudioNode::AudioNode(BaseAudioContext *context) : context_(context) {
1111
audioBus_ = std::make_shared<AudioBus>(
12-
context->getSampleRate(),
13-
context->getBufferSizeInFrames(),
14-
channelCount_);
12+
context->getSampleRate(), RENDER_QUANTUM_SIZE, channelCount_);
1513
}
1614

1715
AudioNode::~AudioNode() {
@@ -207,6 +205,10 @@ void AudioNode::onInputDisabled() {
207205
}
208206

209207
void AudioNode::onInputConnected(AudioNode *node) {
208+
if (!isInitialized_) {
209+
return;
210+
}
211+
210212
inputNodes_.push_back(node);
211213

212214
if (node->isEnabled()) {
@@ -215,6 +217,10 @@ void AudioNode::onInputConnected(AudioNode *node) {
215217
}
216218

217219
void AudioNode::onInputDisconnected(AudioNode *node) {
220+
if (!isInitialized_) {
221+
return;
222+
}
223+
218224
auto position = std::find(inputNodes_.begin(), inputNodes_.end(), node);
219225

220226
if (position != inputNodes_.end()) {

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

Lines changed: 2 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,3 @@
1-
#ifdef ANDROID
2-
#include "AudioPlayer.h"
3-
#else
4-
#include "IOSAudioPlayer.h"
5-
#endif
6-
71
#include "BaseAudioContext.h"
82

93
#include "AnalyserNode.h"
@@ -22,31 +16,13 @@
2216

2317
namespace audioapi {
2418

25-
BaseAudioContext::BaseAudioContext() {
26-
#ifdef ANDROID
27-
audioPlayer_ = std::make_shared<AudioPlayer>(this->renderAudio());
28-
#else
29-
audioPlayer_ = std::make_shared<IOSAudioPlayer>(this->renderAudio());
30-
#endif
31-
32-
audioDecoder_ = std::make_shared<AudioDecoder>(audioPlayer_->getSampleRate());
33-
34-
sampleRate_ = audioPlayer_->getSampleRate();
35-
bufferSizeInFrames_ = audioPlayer_->getBufferSizeInFrames();
19+
BaseAudioContext::BaseAudioContext() : sampleRate_(DEFAULT_SAMPLE_RATE) {
20+
audioDecoder_ = std::make_shared<AudioDecoder>(sampleRate_);
3621

3722
nodeManager_ = std::make_shared<AudioNodeManager>();
3823
destination_ = std::make_shared<AudioDestinationNode>(this);
3924
}
4025

41-
BaseAudioContext::~BaseAudioContext() {
42-
if (isRunning()) {
43-
return;
44-
}
45-
46-
state_ = ContextState::CLOSED;
47-
audioPlayer_->stop();
48-
}
49-
5026
std::string BaseAudioContext::getState() {
5127
return BaseAudioContext::toString(state_);
5228
}
@@ -55,10 +31,6 @@ int BaseAudioContext::getSampleRate() const {
5531
return sampleRate_;
5632
}
5733

58-
int BaseAudioContext::getBufferSizeInFrames() const {
59-
return bufferSizeInFrames_;
60-
}
61-
6234
std::size_t BaseAudioContext::getCurrentSampleFrame() const {
6335
return destination_->getCurrentSampleFrame();
6436
}
@@ -117,16 +89,6 @@ std::shared_ptr<AudioBuffer> BaseAudioContext::decodeAudioDataSource(
11789
return std::make_shared<AudioBuffer>(audioBus);
11890
}
11991

120-
std::function<void(AudioBus *, int)> BaseAudioContext::renderAudio() {
121-
if (!isRunning()) {
122-
return [](AudioBus *, int) {};
123-
}
124-
125-
return [this](AudioBus *data, int frames) {
126-
destination_->renderAudio(data, frames);
127-
};
128-
}
129-
13092
AudioNodeManager *BaseAudioContext::getNodeManager() {
13193
return nodeManager_.get();
13294
}

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

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,21 +24,14 @@ class AudioBufferSourceNode;
2424
class AudioDecoder;
2525
class AnalyserNode;
2626

27-
#ifdef ANDROID
28-
class AudioPlayer;
29-
#else
30-
class IOSAudioPlayer;
31-
#endif
32-
3327
class BaseAudioContext {
3428
public:
3529
BaseAudioContext();
36-
~BaseAudioContext();
30+
virtual ~BaseAudioContext() = default;
3731

3832
std::string getState();
3933
[[nodiscard]] int getSampleRate() const;
4034
[[nodiscard]] double getCurrentTime() const;
41-
[[nodiscard]] int getBufferSizeInFrames() const;
4235
[[nodiscard]] std::size_t getCurrentSampleFrame() const;
4336
std::shared_ptr<AudioDestinationNode> getDestination();
4437

@@ -58,7 +51,6 @@ class BaseAudioContext {
5851

5952
std::shared_ptr<AudioBuffer> decodeAudioDataSource(const std::string &path);
6053
std::shared_ptr<PeriodicWave> getBasicWaveForm(OscillatorType type);
61-
std::function<void(AudioBus *, int)> renderAudio();
6254
AudioNodeManager *getNodeManager();
6355
[[nodiscard]] bool isRunning() const;
6456
[[nodiscard]] bool isClosed() const;
@@ -68,14 +60,7 @@ class BaseAudioContext {
6860
std::shared_ptr<AudioDestinationNode> destination_;
6961
std::shared_ptr<AudioDecoder> audioDecoder_;
7062

71-
#ifdef ANDROID
72-
std::shared_ptr<AudioPlayer> audioPlayer_;
73-
#else
74-
std::shared_ptr<IOSAudioPlayer> audioPlayer_;
75-
#endif
76-
7763
int sampleRate_;
78-
int bufferSizeInFrames_;
7964
ContextState state_ = ContextState::RUNNING;
8065
std::shared_ptr<AudioNodeManager> nodeManager_;
8166

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@
66
// https://webaudio.github.io/web-audio-api/
77

88
namespace audioapi {
9-
constexpr int SAMPLE_RATE = 48000;
9+
constexpr int DEFAULT_SAMPLE_RATE = 48000;
10+
constexpr int RENDER_QUANTUM_SIZE = 128;
1011
constexpr int CHANNEL_COUNT = 2;
1112

1213
constexpr float MOST_POSITIVE_SINGLE_FLOAT = static_cast<float>(std::numeric_limits<float>::max());
1314
constexpr float MOST_NEGATIVE_SINGLE_FLOAT = static_cast<float>(std::numeric_limits<float>::lowest());
1415

15-
constexpr float NYQUIST_FREQUENCY = SAMPLE_RATE / 2.0;
16+
constexpr float NYQUIST_FREQUENCY = DEFAULT_SAMPLE_RATE / 2.0;
1617
static float MAX_DETUNE = 1200 * std::log2(MOST_POSITIVE_SINGLE_FLOAT);
1718
constexpr float MAX_GAIN = MOST_POSITIVE_SINGLE_FLOAT;
1819
constexpr float MAX_PAN = 1.0;

packages/react-native-audio-api/ios/core/AudioPlayer.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@ typedef void (^RenderAudioBlock)(AudioBufferList *outputBuffer, int numFrames);
1717

1818
- (int)getSampleRate;
1919

20-
- (int)getBufferSizeInFrames;
21-
2220
- (void)start;
2321

2422
- (void)stop;

0 commit comments

Comments
 (0)