react-native-audio-api 0.4.3 → 0.4.5
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/android/build.gradle +1 -1
- package/android/libs/x86/libfftw3.a +0 -0
- package/common/cpp/HostObjects/BaseAudioContextHostObject.h +9 -13
- package/common/cpp/core/AudioContext.cpp +2 -2
- package/common/cpp/core/AudioNode.cpp +23 -31
- package/common/cpp/core/AudioNode.h +4 -3
- package/common/cpp/core/AudioNodeManager.cpp +14 -18
- package/common/cpp/core/AudioNodeManager.h +10 -5
- package/common/cpp/core/AudioScheduledSourceNode.cpp +0 -2
- package/common/cpp/core/BaseAudioContext.cpp +18 -6
- package/common/cpp/jsi/JsiPromise.cpp +6 -3
- package/common/cpp/jsi/JsiPromise.h +7 -14
- package/package.json +1 -1
package/android/build.gradle
CHANGED
|
@@ -15,7 +15,7 @@ buildscript {
|
|
|
15
15
|
|
|
16
16
|
def reactNativeArchitectures() {
|
|
17
17
|
def value = rootProject.getProperties().get("reactNativeArchitectures")
|
|
18
|
-
return value ? value.split(",") : ["armeabi-v7a", "arm64-v8a", "x86_64"]
|
|
18
|
+
return value ? value.split(",") : ["armeabi-v7a", "arm64-v8a", "x86_64", "x86"]
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
def isNewArchitectureEnabled() {
|
|
Binary file
|
|
@@ -143,20 +143,16 @@ class BaseAudioContextHostObject : public JsiHostObject {
|
|
|
143
143
|
JSI_HOST_FUNCTION(decodeAudioDataSource) {
|
|
144
144
|
auto sourcePath = args[0].getString(runtime).utf8(runtime);
|
|
145
145
|
|
|
146
|
-
auto promise = promiseVendor_->createPromise(
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
auto audioBufferHostObject =
|
|
154
|
-
std::make_shared<AudioBufferHostObject>(results);
|
|
155
|
-
|
|
156
|
-
promise->resolve(jsi::Object::createFromHostObject(
|
|
157
|
-
runtime, audioBufferHostObject));
|
|
158
|
-
}).detach();
|
|
146
|
+
auto promise = promiseVendor_->createPromise([this, sourcePath](std::shared_ptr<Promise> promise) {
|
|
147
|
+
std::thread([this, sourcePath, promise = std::move(promise)]() {
|
|
148
|
+
auto results = context_->decodeAudioDataSource(sourcePath);
|
|
149
|
+
auto audioBufferHostObject = std::make_shared<AudioBufferHostObject>(results);
|
|
150
|
+
|
|
151
|
+
promise->resolve([audioBufferHostObject = std::move(audioBufferHostObject)](jsi::Runtime &runtime) {
|
|
152
|
+
return jsi::Object::createFromHostObject(runtime, audioBufferHostObject);
|
|
159
153
|
});
|
|
154
|
+
}).detach();
|
|
155
|
+
});
|
|
160
156
|
|
|
161
157
|
return promise;
|
|
162
158
|
}
|
|
@@ -35,7 +35,7 @@ AudioContext::AudioContext(float sampleRate) : BaseAudioContext() {
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
AudioContext::~AudioContext() {
|
|
38
|
-
if (
|
|
38
|
+
if (isClosed()) {
|
|
39
39
|
return;
|
|
40
40
|
}
|
|
41
41
|
|
|
@@ -48,7 +48,7 @@ void AudioContext::close() {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
std::function<void(AudioBus *, int)> AudioContext::renderAudio() {
|
|
51
|
-
if (!isRunning()) {
|
|
51
|
+
if (!isRunning() || !destination_) {
|
|
52
52
|
return [](AudioBus *, int) {};
|
|
53
53
|
}
|
|
54
54
|
|
|
@@ -13,7 +13,6 @@ AudioNode::AudioNode(BaseAudioContext *context) : context_(context) {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
AudioNode::~AudioNode() {
|
|
16
|
-
isInitialized_ = false;
|
|
17
16
|
cleanup();
|
|
18
17
|
}
|
|
19
18
|
|
|
@@ -42,14 +41,9 @@ void AudioNode::connect(const std::shared_ptr<AudioNode> &node) {
|
|
|
42
41
|
shared_from_this(), node, AudioNodeManager::ConnectionType::CONNECT);
|
|
43
42
|
}
|
|
44
43
|
|
|
45
|
-
void AudioNode::connectNode(const std::shared_ptr<AudioNode> &node) {
|
|
46
|
-
outputNodes_.push_back(node);
|
|
47
|
-
node->onInputConnected(this);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
44
|
void AudioNode::disconnect() {
|
|
51
45
|
for (auto &outputNode : outputNodes_) {
|
|
52
|
-
|
|
46
|
+
disconnect(outputNode);
|
|
53
47
|
}
|
|
54
48
|
}
|
|
55
49
|
|
|
@@ -58,16 +52,6 @@ void AudioNode::disconnect(const std::shared_ptr<AudioNode> &node) {
|
|
|
58
52
|
shared_from_this(), node, AudioNodeManager::ConnectionType::DISCONNECT);
|
|
59
53
|
}
|
|
60
54
|
|
|
61
|
-
void AudioNode::disconnectNode(const std::shared_ptr<AudioNode> &node) {
|
|
62
|
-
node->onInputDisconnected(this);
|
|
63
|
-
|
|
64
|
-
auto position = std::find(outputNodes_.begin(), outputNodes_.end(), node);
|
|
65
|
-
|
|
66
|
-
if (position != outputNodes_.end()) {
|
|
67
|
-
outputNodes_.erase(position);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
55
|
bool AudioNode::isEnabled() const {
|
|
72
56
|
return isEnabled_;
|
|
73
57
|
}
|
|
@@ -186,10 +170,30 @@ AudioBus *AudioNode::processAudio(AudioBus *outputBus, int framesToProcess) {
|
|
|
186
170
|
}
|
|
187
171
|
|
|
188
172
|
void AudioNode::cleanup() {
|
|
173
|
+
isInitialized_ = false;
|
|
174
|
+
|
|
175
|
+
for (const auto &outputNode : outputNodes_) {
|
|
176
|
+
outputNode->onInputDisconnected(this);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
for (const auto &inputNode : inputNodes_) {
|
|
180
|
+
inputNode->disconnectNode(shared_from_this());
|
|
181
|
+
}
|
|
182
|
+
|
|
189
183
|
outputNodes_.clear();
|
|
190
184
|
inputNodes_.clear();
|
|
191
185
|
}
|
|
192
186
|
|
|
187
|
+
void AudioNode::connectNode(const std::shared_ptr<AudioNode> &node) {
|
|
188
|
+
outputNodes_.insert(node);
|
|
189
|
+
node->onInputConnected(this);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
void AudioNode::disconnectNode(const std::shared_ptr<AudioNode> &node) {
|
|
193
|
+
outputNodes_.erase(node);
|
|
194
|
+
node->onInputDisconnected(this);
|
|
195
|
+
}
|
|
196
|
+
|
|
193
197
|
void AudioNode::onInputEnabled() {
|
|
194
198
|
numberOfEnabledInputNodes_ += 1;
|
|
195
199
|
|
|
@@ -211,7 +215,7 @@ void AudioNode::onInputConnected(AudioNode *node) {
|
|
|
211
215
|
return;
|
|
212
216
|
}
|
|
213
217
|
|
|
214
|
-
inputNodes_.
|
|
218
|
+
inputNodes_.insert(node);
|
|
215
219
|
|
|
216
220
|
if (node->isEnabled()) {
|
|
217
221
|
onInputEnabled();
|
|
@@ -223,23 +227,11 @@ void AudioNode::onInputDisconnected(AudioNode *node) {
|
|
|
223
227
|
return;
|
|
224
228
|
}
|
|
225
229
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
if (position != inputNodes_.end()) {
|
|
229
|
-
inputNodes_.erase(position);
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
if (!inputNodes_.empty()) {
|
|
233
|
-
return;
|
|
234
|
-
}
|
|
230
|
+
inputNodes_.erase(node);
|
|
235
231
|
|
|
236
232
|
if (isEnabled()) {
|
|
237
233
|
node->onInputDisabled();
|
|
238
234
|
}
|
|
239
|
-
|
|
240
|
-
for (const auto &outputNode : outputNodes_) {
|
|
241
|
-
disconnectNode(outputNode);
|
|
242
|
-
}
|
|
243
235
|
}
|
|
244
236
|
|
|
245
237
|
} // namespace audioapi
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
#include <memory>
|
|
4
4
|
#include <string>
|
|
5
|
-
#include <
|
|
5
|
+
#include <unordered_set>
|
|
6
6
|
#include <cstddef>
|
|
7
7
|
|
|
8
8
|
#include "ChannelCountMode.h"
|
|
@@ -18,6 +18,7 @@ class AudioNode : public std::enable_shared_from_this<AudioNode> {
|
|
|
18
18
|
public:
|
|
19
19
|
explicit AudioNode(BaseAudioContext *context);
|
|
20
20
|
virtual ~AudioNode();
|
|
21
|
+
|
|
21
22
|
int getNumberOfInputs() const;
|
|
22
23
|
int getNumberOfOutputs() const;
|
|
23
24
|
int getChannelCount() const;
|
|
@@ -45,8 +46,8 @@ class AudioNode : public std::enable_shared_from_this<AudioNode> {
|
|
|
45
46
|
ChannelInterpretation channelInterpretation_ =
|
|
46
47
|
ChannelInterpretation::SPEAKERS;
|
|
47
48
|
|
|
48
|
-
|
|
49
|
-
|
|
49
|
+
std::unordered_set<AudioNode *> inputNodes_ = {};
|
|
50
|
+
std::unordered_set<std::shared_ptr<AudioNode>> outputNodes_ = {};
|
|
50
51
|
|
|
51
52
|
int numberOfEnabledInputNodes_ = 0;
|
|
52
53
|
bool isInitialized_ = false;
|
|
@@ -7,7 +7,6 @@ namespace audioapi {
|
|
|
7
7
|
|
|
8
8
|
AudioNodeManager::~AudioNodeManager() {
|
|
9
9
|
audioNodesToConnect_.clear();
|
|
10
|
-
sourceNodes_.clear();
|
|
11
10
|
}
|
|
12
11
|
|
|
13
12
|
void AudioNodeManager::addPendingConnection(
|
|
@@ -19,31 +18,33 @@ void AudioNodeManager::addPendingConnection(
|
|
|
19
18
|
audioNodesToConnect_.emplace_back(from, to, type);
|
|
20
19
|
}
|
|
21
20
|
|
|
22
|
-
void AudioNodeManager::addSourceNode(const std::shared_ptr<AudioNode> &node) {
|
|
23
|
-
Locker lock(getGraphLock());
|
|
24
|
-
|
|
25
|
-
sourceNodes_.push_back(node);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
21
|
void AudioNodeManager::preProcessGraph() {
|
|
29
22
|
if (!Locker::tryLock(getGraphLock())) {
|
|
30
23
|
return;
|
|
31
24
|
}
|
|
32
25
|
|
|
33
26
|
settlePendingConnections();
|
|
34
|
-
|
|
27
|
+
prepareNodesForDestruction();
|
|
35
28
|
}
|
|
36
29
|
|
|
37
30
|
std::mutex &AudioNodeManager::getGraphLock() {
|
|
38
31
|
return graphLock_;
|
|
39
32
|
}
|
|
40
33
|
|
|
34
|
+
void AudioNodeManager::addNode(const std::shared_ptr<AudioNode> &node) {
|
|
35
|
+
Locker lock(getGraphLock());
|
|
36
|
+
|
|
37
|
+
nodes_.insert(node);
|
|
38
|
+
}
|
|
39
|
+
|
|
41
40
|
void AudioNodeManager::settlePendingConnections() {
|
|
42
41
|
for (auto &connection : audioNodesToConnect_) {
|
|
43
42
|
std::shared_ptr<AudioNode> from = std::get<0>(connection);
|
|
44
43
|
std::shared_ptr<AudioNode> to = std::get<1>(connection);
|
|
45
44
|
ConnectionType type = std::get<2>(connection);
|
|
46
45
|
|
|
46
|
+
// add assert to check if from and to are neither null nor uninitialized
|
|
47
|
+
|
|
47
48
|
if (type == ConnectionType::CONNECT) {
|
|
48
49
|
from->connectNode(to);
|
|
49
50
|
} else {
|
|
@@ -54,16 +55,11 @@ void AudioNodeManager::settlePendingConnections() {
|
|
|
54
55
|
audioNodesToConnect_.clear();
|
|
55
56
|
}
|
|
56
57
|
|
|
57
|
-
void AudioNodeManager::
|
|
58
|
-
for (auto it =
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
for (auto &outputNode : currentNode->outputNodes_) {
|
|
63
|
-
currentNode->disconnectNode(outputNode);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
it = sourceNodes_.erase(it);
|
|
58
|
+
void AudioNodeManager::prepareNodesForDestruction() {
|
|
59
|
+
for (auto it = nodes_.begin(); it != nodes_.end();) {
|
|
60
|
+
if (it->use_count() == 1) {
|
|
61
|
+
it->get()->cleanup();
|
|
62
|
+
it = nodes_.erase(it);
|
|
67
63
|
} else {
|
|
68
64
|
++it;
|
|
69
65
|
}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
#include <mutex>
|
|
5
5
|
#include <tuple>
|
|
6
6
|
#include <vector>
|
|
7
|
+
#include <unordered_set>
|
|
7
8
|
|
|
8
9
|
namespace audioapi {
|
|
9
10
|
|
|
@@ -15,20 +16,24 @@ class AudioNodeManager {
|
|
|
15
16
|
AudioNodeManager() = default;
|
|
16
17
|
~AudioNodeManager();
|
|
17
18
|
|
|
19
|
+
std::mutex &getGraphLock();
|
|
20
|
+
|
|
18
21
|
void preProcessGraph();
|
|
22
|
+
|
|
19
23
|
void addPendingConnection(
|
|
20
24
|
const std::shared_ptr<AudioNode> &from,
|
|
21
25
|
const std::shared_ptr<AudioNode> &to,
|
|
22
26
|
ConnectionType type);
|
|
23
27
|
|
|
24
|
-
void
|
|
25
|
-
|
|
26
|
-
std::mutex &getGraphLock();
|
|
28
|
+
void addNode(const std::shared_ptr<AudioNode> &node);
|
|
27
29
|
|
|
28
30
|
private:
|
|
29
31
|
std::mutex graphLock_;
|
|
30
32
|
|
|
31
|
-
|
|
33
|
+
// all nodes created in the context
|
|
34
|
+
std::unordered_set<std::shared_ptr<AudioNode>> nodes_;
|
|
35
|
+
|
|
36
|
+
// connections to be settled
|
|
32
37
|
std::vector<std::tuple<
|
|
33
38
|
std::shared_ptr<AudioNode>,
|
|
34
39
|
std::shared_ptr<AudioNode>,
|
|
@@ -36,7 +41,7 @@ class AudioNodeManager {
|
|
|
36
41
|
audioNodesToConnect_;
|
|
37
42
|
|
|
38
43
|
void settlePendingConnections();
|
|
39
|
-
void
|
|
44
|
+
void prepareNodesForDestruction();
|
|
40
45
|
};
|
|
41
46
|
|
|
42
47
|
} // namespace audioapi
|
|
@@ -18,8 +18,6 @@ AudioScheduledSourceNode::AudioScheduledSourceNode(BaseAudioContext *context)
|
|
|
18
18
|
void AudioScheduledSourceNode::start(double time) {
|
|
19
19
|
playbackState_ = PlaybackState::SCHEDULED;
|
|
20
20
|
startTime_ = time;
|
|
21
|
-
|
|
22
|
-
context_->getNodeManager()->addSourceNode(shared_from_this());
|
|
23
21
|
}
|
|
24
22
|
|
|
25
23
|
void AudioScheduledSourceNode::stop(double time) {
|
|
@@ -42,23 +42,33 @@ std::shared_ptr<AudioDestinationNode> BaseAudioContext::getDestination() {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
std::shared_ptr<OscillatorNode> BaseAudioContext::createOscillator() {
|
|
45
|
-
|
|
45
|
+
auto oscillator = std::make_shared<OscillatorNode>(this);
|
|
46
|
+
nodeManager_->addNode(oscillator);
|
|
47
|
+
return oscillator;
|
|
46
48
|
}
|
|
47
49
|
|
|
48
50
|
std::shared_ptr<GainNode> BaseAudioContext::createGain() {
|
|
49
|
-
|
|
51
|
+
auto gain = std::make_shared<GainNode>(this);
|
|
52
|
+
nodeManager_->addNode(gain);
|
|
53
|
+
return gain;
|
|
50
54
|
}
|
|
51
55
|
|
|
52
56
|
std::shared_ptr<StereoPannerNode> BaseAudioContext::createStereoPanner() {
|
|
53
|
-
|
|
57
|
+
auto stereoPanner = std::make_shared<StereoPannerNode>(this);
|
|
58
|
+
nodeManager_->addNode(stereoPanner);
|
|
59
|
+
return stereoPanner;
|
|
54
60
|
}
|
|
55
61
|
|
|
56
62
|
std::shared_ptr<BiquadFilterNode> BaseAudioContext::createBiquadFilter() {
|
|
57
|
-
|
|
63
|
+
auto biquadFilter = std::make_shared<BiquadFilterNode>(this);
|
|
64
|
+
nodeManager_->addNode(biquadFilter);
|
|
65
|
+
return biquadFilter;
|
|
58
66
|
}
|
|
59
67
|
|
|
60
68
|
std::shared_ptr<AudioBufferSourceNode> BaseAudioContext::createBufferSource() {
|
|
61
|
-
|
|
69
|
+
auto bufferSource = std::make_shared<AudioBufferSourceNode>(this);
|
|
70
|
+
nodeManager_->addNode(bufferSource);
|
|
71
|
+
return bufferSource;
|
|
62
72
|
}
|
|
63
73
|
|
|
64
74
|
std::shared_ptr<AudioBuffer> BaseAudioContext::createBuffer(
|
|
@@ -78,7 +88,9 @@ std::shared_ptr<PeriodicWave> BaseAudioContext::createPeriodicWave(
|
|
|
78
88
|
}
|
|
79
89
|
|
|
80
90
|
std::shared_ptr<AnalyserNode> BaseAudioContext::createAnalyser() {
|
|
81
|
-
|
|
91
|
+
auto analyser = std::make_shared<AnalyserNode>(this);
|
|
92
|
+
nodeManager_->addNode(analyser);
|
|
93
|
+
return analyser;
|
|
82
94
|
}
|
|
83
95
|
|
|
84
96
|
std::shared_ptr<AudioBuffer> BaseAudioContext::decodeAudioDataSource(
|
|
@@ -36,9 +36,12 @@ jsi::Value PromiseVendor::createPromise(
|
|
|
36
36
|
auto reject = std::make_shared<jsi::Function>(std::move(rejectLocal));
|
|
37
37
|
|
|
38
38
|
auto resolveWrapper =
|
|
39
|
-
[resolve, &runtime, callInvoker](
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
[resolve, &runtime, callInvoker](
|
|
40
|
+
const std::function<jsi::Value(jsi::Runtime &)> resolver)
|
|
41
|
+
-> void {
|
|
42
|
+
callInvoker->invokeAsync([resolve, &runtime, resolver]() -> void {
|
|
43
|
+
auto valueShared = std::make_shared<jsi::Value>(resolver(runtime));
|
|
44
|
+
|
|
42
45
|
resolve->call(runtime, *valueShared);
|
|
43
46
|
});
|
|
44
47
|
};
|
|
@@ -13,33 +13,26 @@ using namespace facebook;
|
|
|
13
13
|
|
|
14
14
|
class Promise {
|
|
15
15
|
public:
|
|
16
|
-
Promise(
|
|
17
|
-
std::function<void(jsi::Value)> resolve,
|
|
18
|
-
std::function<void(const std::string &)> reject)
|
|
19
|
-
: resolve_(std::move(resolve)), reject_(std::move(reject)) {}
|
|
16
|
+
Promise(std::function<void(const std::function<jsi::Value(jsi::Runtime&)>)> resolve, std::function<void(const std::string &)> reject) : resolve_(std::move(resolve)), reject_(std::move(reject)) {}
|
|
20
17
|
|
|
21
|
-
void resolve(jsi::Value
|
|
22
|
-
resolve_(std::forward<jsi::Value
|
|
18
|
+
void resolve(const std::function<jsi::Value(jsi::Runtime&)> &resolver) {
|
|
19
|
+
resolve_(std::forward<const std::function<jsi::Value(jsi::Runtime&)>>(resolver));
|
|
23
20
|
}
|
|
21
|
+
|
|
24
22
|
void reject(const std::string &errorMessage) {
|
|
25
23
|
reject_(errorMessage);
|
|
26
24
|
}
|
|
27
25
|
|
|
28
26
|
private:
|
|
29
|
-
std::function<void(jsi::Value)> resolve_;
|
|
27
|
+
std::function<void(const std::function<jsi::Value(jsi::Runtime&)>)> resolve_;
|
|
30
28
|
std::function<void(const std::string &)> reject_;
|
|
31
29
|
};
|
|
32
30
|
|
|
33
31
|
class PromiseVendor {
|
|
34
32
|
public:
|
|
35
|
-
PromiseVendor(
|
|
36
|
-
jsi::Runtime *runtime,
|
|
37
|
-
const std::shared_ptr<react::CallInvoker> &callInvoker)
|
|
38
|
-
: runtime_(runtime), callInvoker_(callInvoker) {}
|
|
33
|
+
PromiseVendor(jsi::Runtime *runtime, const std::shared_ptr<react::CallInvoker> &callInvoker): runtime_(runtime), callInvoker_(callInvoker) {}
|
|
39
34
|
|
|
40
|
-
|
|
41
|
-
jsi::Value createPromise(
|
|
42
|
-
const std::function<void(std::shared_ptr<Promise>)> &function);
|
|
35
|
+
jsi::Value createPromise(const std::function<void(std::shared_ptr<Promise>)> &function);
|
|
43
36
|
|
|
44
37
|
private:
|
|
45
38
|
jsi::Runtime *runtime_;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-audio-api",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.5",
|
|
4
4
|
"description": "react-native-audio-api provides system for controlling audio in React Native environment compatible with Web Audio API specification",
|
|
5
5
|
"main": "lib/commonjs/index",
|
|
6
6
|
"module": "lib/module/index",
|