react-native-audio-api 0.8.3-nightly-e918179-20251003 → 0.8.3-nightly-ea268f4-20251005
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 +31 -14
- package/common/cpp/audioapi/HostObjects/BaseAudioContextHostObject.cpp +74 -4
- package/common/cpp/audioapi/HostObjects/BaseAudioContextHostObject.h +3 -0
- package/common/cpp/audioapi/HostObjects/WorkletProcessingNodeHostObject.h +18 -0
- package/common/cpp/audioapi/HostObjects/sources/AudioBufferSourceNodeHostObject.cpp +20 -1
- package/common/cpp/audioapi/HostObjects/sources/AudioBufferSourceNodeHostObject.h +3 -0
- package/common/cpp/audioapi/HostObjects/sources/ConstantSourceNodeHostObject.cpp +19 -0
- package/common/cpp/audioapi/HostObjects/sources/ConstantSourceNodeHostObject.h +21 -0
- package/common/cpp/audioapi/HostObjects/sources/WorkletSourceNodeHostObject.h +18 -0
- package/common/cpp/audioapi/core/AudioContext.cpp +2 -2
- package/common/cpp/audioapi/core/AudioContext.h +2 -2
- package/common/cpp/audioapi/core/AudioParam.cpp +2 -2
- package/common/cpp/audioapi/core/BaseAudioContext.cpp +32 -3
- package/common/cpp/audioapi/core/BaseAudioContext.h +9 -4
- package/common/cpp/audioapi/core/OfflineAudioContext.cpp +2 -2
- package/common/cpp/audioapi/core/OfflineAudioContext.h +2 -2
- package/common/cpp/audioapi/core/effects/WorkletNode.cpp +4 -3
- package/common/cpp/audioapi/core/effects/WorkletNode.h +4 -3
- package/common/cpp/audioapi/core/effects/WorkletProcessingNode.cpp +89 -0
- package/common/cpp/audioapi/core/effects/WorkletProcessingNode.h +52 -0
- package/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.cpp +1 -6
- package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp +30 -0
- package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.h +6 -0
- package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.cpp +1 -6
- package/common/cpp/audioapi/core/sources/ConstantSourceNode.cpp +51 -0
- package/common/cpp/audioapi/core/sources/ConstantSourceNode.h +26 -0
- package/common/cpp/audioapi/core/sources/WorkletSourceNode.cpp +82 -0
- package/common/cpp/audioapi/core/sources/WorkletSourceNode.h +47 -0
- package/common/cpp/audioapi/core/utils/AudioParamEventQueue.cpp +12 -6
- package/common/cpp/audioapi/core/utils/Constants.h +5 -0
- package/common/cpp/audioapi/core/utils/worklets/SafeIncludes.h +7 -0
- package/common/cpp/audioapi/core/utils/worklets/{UiWorkletsRunner.cpp → WorkletsRunner.cpp} +2 -2
- package/common/cpp/audioapi/core/utils/worklets/{UiWorkletsRunner.h → WorkletsRunner.h} +2 -2
- package/common/cpp/audioapi/events/AudioEventHandlerRegistry.h +2 -1
- package/common/cpp/audioapi/jsi/JsiPromise.cpp +23 -27
- package/common/cpp/audioapi/jsi/JsiPromise.h +10 -1
- package/common/cpp/audioapi/utils/ThreadPool.hpp +104 -0
- package/common/cpp/test/AudioParamTest.cpp +204 -0
- package/common/cpp/test/CMakeLists.txt +3 -0
- package/common/cpp/test/GainTest.cpp +2 -1
- package/common/cpp/test/OscillatorTest.cpp +2 -1
- package/ios/audioapi/ios/core/IOSAudioRecorder.h +2 -1
- package/lib/commonjs/api.js +27 -0
- package/lib/commonjs/api.js.map +1 -1
- package/lib/commonjs/api.web.js +8 -0
- package/lib/commonjs/api.web.js.map +1 -1
- package/lib/commonjs/core/AudioBufferBaseSourceNode.js +7 -7
- package/lib/commonjs/core/AudioBufferBaseSourceNode.js.map +1 -1
- package/lib/commonjs/core/AudioBufferQueueSourceNode.js +1 -6
- package/lib/commonjs/core/AudioBufferQueueSourceNode.js.map +1 -1
- package/lib/commonjs/core/AudioBufferSourceNode.js +15 -0
- package/lib/commonjs/core/AudioBufferSourceNode.js.map +1 -1
- package/lib/commonjs/core/AudioContext.js +10 -1
- package/lib/commonjs/core/AudioContext.js.map +1 -1
- package/lib/commonjs/core/BaseAudioContext.js +35 -2
- package/lib/commonjs/core/BaseAudioContext.js.map +1 -1
- package/lib/commonjs/core/ConstantSourceNode.js +17 -0
- package/lib/commonjs/core/ConstantSourceNode.js.map +1 -0
- package/lib/commonjs/core/OfflineAudioContext.js +11 -2
- package/lib/commonjs/core/OfflineAudioContext.js.map +1 -1
- package/lib/commonjs/core/WorkletProcessingNode.js +11 -0
- package/lib/commonjs/core/WorkletProcessingNode.js.map +1 -0
- package/lib/commonjs/core/WorkletSourceNode.js +11 -0
- package/lib/commonjs/core/WorkletSourceNode.js.map +1 -0
- package/lib/commonjs/utils/index.js.map +1 -1
- package/lib/commonjs/web-core/AudioContext.js +4 -0
- package/lib/commonjs/web-core/AudioContext.js.map +1 -1
- package/lib/commonjs/web-core/ConstantSourceNode.js +17 -0
- package/lib/commonjs/web-core/ConstantSourceNode.js.map +1 -0
- package/lib/commonjs/web-core/OfflineAudioContext.js +4 -0
- package/lib/commonjs/web-core/OfflineAudioContext.js.map +1 -1
- package/lib/module/api.js +4 -1
- package/lib/module/api.js.map +1 -1
- package/lib/module/api.web.js +1 -0
- package/lib/module/api.web.js.map +1 -1
- package/lib/module/core/AudioBufferBaseSourceNode.js +7 -7
- package/lib/module/core/AudioBufferBaseSourceNode.js.map +1 -1
- package/lib/module/core/AudioBufferQueueSourceNode.js +1 -6
- package/lib/module/core/AudioBufferQueueSourceNode.js.map +1 -1
- package/lib/module/core/AudioBufferSourceNode.js +15 -0
- package/lib/module/core/AudioBufferSourceNode.js.map +1 -1
- package/lib/module/core/AudioContext.js +10 -1
- package/lib/module/core/AudioContext.js.map +1 -1
- package/lib/module/core/BaseAudioContext.js +35 -2
- package/lib/module/core/BaseAudioContext.js.map +1 -1
- package/lib/module/core/ConstantSourceNode.js +11 -0
- package/lib/module/core/ConstantSourceNode.js.map +1 -0
- package/lib/module/core/OfflineAudioContext.js +11 -2
- package/lib/module/core/OfflineAudioContext.js.map +1 -1
- package/lib/module/core/WorkletProcessingNode.js +5 -0
- package/lib/module/core/WorkletProcessingNode.js.map +1 -0
- package/lib/module/core/WorkletSourceNode.js +5 -0
- package/lib/module/core/WorkletSourceNode.js.map +1 -0
- package/lib/module/utils/index.js.map +1 -1
- package/lib/module/web-core/AudioContext.js +4 -0
- package/lib/module/web-core/AudioContext.js.map +1 -1
- package/lib/module/web-core/ConstantSourceNode.js +11 -0
- package/lib/module/web-core/ConstantSourceNode.js.map +1 -0
- package/lib/module/web-core/OfflineAudioContext.js +4 -0
- package/lib/module/web-core/OfflineAudioContext.js.map +1 -1
- package/lib/typescript/api.d.ts +6 -3
- package/lib/typescript/api.d.ts.map +1 -1
- package/lib/typescript/api.web.d.ts +1 -0
- package/lib/typescript/api.web.d.ts.map +1 -1
- package/lib/typescript/core/AudioBufferBaseSourceNode.d.ts +2 -2
- package/lib/typescript/core/AudioBufferBaseSourceNode.d.ts.map +1 -1
- package/lib/typescript/core/AudioBufferQueueSourceNode.d.ts +1 -1
- package/lib/typescript/core/AudioBufferQueueSourceNode.d.ts.map +1 -1
- package/lib/typescript/core/AudioBufferSourceNode.d.ts +4 -0
- package/lib/typescript/core/AudioBufferSourceNode.d.ts.map +1 -1
- package/lib/typescript/core/AudioContext.d.ts +1 -0
- package/lib/typescript/core/AudioContext.d.ts.map +1 -1
- package/lib/typescript/core/BaseAudioContext.d.ts +8 -2
- package/lib/typescript/core/BaseAudioContext.d.ts.map +1 -1
- package/lib/typescript/core/ConstantSourceNode.d.ts +9 -0
- package/lib/typescript/core/ConstantSourceNode.d.ts.map +1 -0
- package/lib/typescript/core/OfflineAudioContext.d.ts +1 -0
- package/lib/typescript/core/OfflineAudioContext.d.ts.map +1 -1
- package/lib/typescript/core/WorkletProcessingNode.d.ts +4 -0
- package/lib/typescript/core/WorkletProcessingNode.d.ts.map +1 -0
- package/lib/typescript/core/WorkletSourceNode.d.ts +4 -0
- package/lib/typescript/core/WorkletSourceNode.d.ts.map +1 -0
- package/lib/typescript/events/types.d.ts +1 -0
- package/lib/typescript/events/types.d.ts.map +1 -1
- package/lib/typescript/interfaces.d.ts +16 -2
- package/lib/typescript/interfaces.d.ts.map +1 -1
- package/lib/typescript/types.d.ts +1 -0
- package/lib/typescript/types.d.ts.map +1 -1
- package/lib/typescript/utils/index.d.ts +1 -0
- package/lib/typescript/utils/index.d.ts.map +1 -1
- package/lib/typescript/web-core/AudioContext.d.ts +2 -0
- package/lib/typescript/web-core/AudioContext.d.ts.map +1 -1
- package/lib/typescript/web-core/BaseAudioContext.d.ts +2 -0
- package/lib/typescript/web-core/BaseAudioContext.d.ts.map +1 -1
- package/lib/typescript/web-core/ConstantSourceNode.d.ts +8 -0
- package/lib/typescript/web-core/ConstantSourceNode.d.ts.map +1 -0
- package/lib/typescript/web-core/OfflineAudioContext.d.ts +2 -0
- package/lib/typescript/web-core/OfflineAudioContext.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/api.ts +10 -2
- package/src/api.web.ts +1 -0
- package/src/core/AudioBufferBaseSourceNode.ts +9 -9
- package/src/core/AudioBufferQueueSourceNode.ts +1 -9
- package/src/core/AudioBufferSourceNode.ts +28 -0
- package/src/core/AudioContext.ts +12 -1
- package/src/core/BaseAudioContext.ts +90 -1
- package/src/core/ConstantSourceNode.ts +13 -0
- package/src/core/OfflineAudioContext.ts +18 -2
- package/src/core/WorkletProcessingNode.ts +3 -0
- package/src/core/WorkletSourceNode.ts +3 -0
- package/src/events/types.ts +1 -0
- package/src/interfaces.ts +42 -2
- package/src/types.ts +2 -0
- package/src/utils/index.ts +3 -0
- package/src/web-core/AudioContext.tsx +5 -0
- package/src/web-core/BaseAudioContext.tsx +2 -0
- package/src/web-core/ConstantSourceNode.tsx +12 -0
- package/src/web-core/OfflineAudioContext.tsx +5 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
#include <audioapi/core/effects/WorkletProcessingNode.h>
|
|
2
|
+
#include <audioapi/core/utils/Constants.h>
|
|
3
|
+
|
|
4
|
+
namespace audioapi {
|
|
5
|
+
|
|
6
|
+
WorkletProcessingNode::WorkletProcessingNode(
|
|
7
|
+
BaseAudioContext *context,
|
|
8
|
+
std::shared_ptr<worklets::SerializableWorklet> &worklet,
|
|
9
|
+
std::weak_ptr<worklets::WorkletRuntime> runtime)
|
|
10
|
+
: AudioNode(context), workletRunner_(runtime), shareableWorklet_(worklet) {
|
|
11
|
+
isInitialized_ = true;
|
|
12
|
+
|
|
13
|
+
// Pre-allocate buffers for max 128 frames and 2 channels (stereo)
|
|
14
|
+
size_t maxChannelCount = 2;
|
|
15
|
+
inputBuffsHandles_.resize(maxChannelCount);
|
|
16
|
+
outputBuffsHandles_.resize(maxChannelCount);
|
|
17
|
+
|
|
18
|
+
for (size_t i = 0; i < maxChannelCount; ++i) {
|
|
19
|
+
auto inputBuff = new uint8_t[RENDER_QUANTUM_SIZE * sizeof(float)];
|
|
20
|
+
inputBuffsHandles_[i] = std::make_shared<AudioArrayBuffer>(
|
|
21
|
+
inputBuff, RENDER_QUANTUM_SIZE * sizeof(float));
|
|
22
|
+
|
|
23
|
+
auto outputBuff = new uint8_t[RENDER_QUANTUM_SIZE * sizeof(float)];
|
|
24
|
+
outputBuffsHandles_[i] = std::make_shared<AudioArrayBuffer>(
|
|
25
|
+
outputBuff, RENDER_QUANTUM_SIZE * sizeof(float));
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
void WorkletProcessingNode::processNode(
|
|
30
|
+
const std::shared_ptr<AudioBus> &processingBus,
|
|
31
|
+
int framesToProcess) {
|
|
32
|
+
size_t channelCount = std::min(
|
|
33
|
+
static_cast<size_t>(2), // Fixed to stereo for now
|
|
34
|
+
static_cast<size_t>(processingBus->getNumberOfChannels()));
|
|
35
|
+
|
|
36
|
+
// Copy input data to pre-allocated input buffers
|
|
37
|
+
for (size_t ch = 0; ch < channelCount; ch++) {
|
|
38
|
+
auto channelData = processingBus->getChannel(ch)->getData();
|
|
39
|
+
std::memcpy(
|
|
40
|
+
/* dest */ inputBuffsHandles_[ch]->data(),
|
|
41
|
+
/* src */ reinterpret_cast<const uint8_t *>(channelData),
|
|
42
|
+
/* size */ framesToProcess * sizeof(float));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Execute the worklet
|
|
46
|
+
auto result = workletRunner_.executeOnRuntimeGuardedSync(
|
|
47
|
+
[this, channelCount, framesToProcess](jsi::Runtime &rt) {
|
|
48
|
+
auto inputJsArray = jsi::Array(rt, channelCount);
|
|
49
|
+
auto outputJsArray = jsi::Array(rt, channelCount);
|
|
50
|
+
|
|
51
|
+
for (size_t ch = 0; ch < channelCount; ch++) {
|
|
52
|
+
// Create input array buffer
|
|
53
|
+
auto inputArrayBuffer = jsi::ArrayBuffer(rt, inputBuffsHandles_[ch]);
|
|
54
|
+
inputJsArray.setValueAtIndex(rt, ch, inputArrayBuffer);
|
|
55
|
+
|
|
56
|
+
// Create output array buffer
|
|
57
|
+
auto outputArrayBuffer =
|
|
58
|
+
jsi::ArrayBuffer(rt, outputBuffsHandles_[ch]);
|
|
59
|
+
outputJsArray.setValueAtIndex(rt, ch, outputArrayBuffer);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return workletRunner_
|
|
63
|
+
.executeWorklet(
|
|
64
|
+
shareableWorklet_,
|
|
65
|
+
inputJsArray,
|
|
66
|
+
outputJsArray,
|
|
67
|
+
jsi::Value(rt, static_cast<int>(framesToProcess)),
|
|
68
|
+
jsi::Value(rt, this->context_->getCurrentTime()))
|
|
69
|
+
.value_or(jsi::Value::undefined());
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// Copy processed output data back to the processing bus or zero on failure
|
|
73
|
+
for (size_t ch = 0; ch < channelCount; ch++) {
|
|
74
|
+
auto channelData = processingBus->getChannel(ch)->getData();
|
|
75
|
+
|
|
76
|
+
if (result.has_value()) {
|
|
77
|
+
// Copy processed output data
|
|
78
|
+
std::memcpy(
|
|
79
|
+
/* dest */ reinterpret_cast<uint8_t *>(channelData),
|
|
80
|
+
/* src */ outputBuffsHandles_[ch]->data(),
|
|
81
|
+
/* size */ framesToProcess * sizeof(float));
|
|
82
|
+
} else {
|
|
83
|
+
// Zero the output on worklet execution failure
|
|
84
|
+
std::memset(channelData, 0, framesToProcess * sizeof(float));
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
} // namespace audioapi
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <jsi/jsi.h>
|
|
4
|
+
#include <audioapi/core/utils/worklets/WorkletsRunner.h>
|
|
5
|
+
#include <audioapi/core/AudioNode.h>
|
|
6
|
+
#include <audioapi/core/BaseAudioContext.h>
|
|
7
|
+
#include <audioapi/utils/AudioBus.h>
|
|
8
|
+
#include <audioapi/utils/AudioArray.h>
|
|
9
|
+
#include <audioapi/jsi/AudioArrayBuffer.h>
|
|
10
|
+
|
|
11
|
+
#include <memory>
|
|
12
|
+
#include <vector>
|
|
13
|
+
|
|
14
|
+
namespace audioapi {
|
|
15
|
+
|
|
16
|
+
#if RN_AUDIO_API_TEST
|
|
17
|
+
class WorkletProcessingNode : public AudioNode {
|
|
18
|
+
public:
|
|
19
|
+
explicit WorkletProcessingNode(
|
|
20
|
+
BaseAudioContext *context,
|
|
21
|
+
std::shared_ptr<worklets::SerializableWorklet> &worklet,
|
|
22
|
+
std::weak_ptr<worklets::WorkletRuntime> runtime
|
|
23
|
+
) : AudioNode(context) {}
|
|
24
|
+
|
|
25
|
+
protected:
|
|
26
|
+
void processNode(const std::shared_ptr<AudioBus>& processingBus, int framesToProcess) override {}
|
|
27
|
+
};
|
|
28
|
+
#else
|
|
29
|
+
|
|
30
|
+
using namespace facebook;
|
|
31
|
+
|
|
32
|
+
class WorkletProcessingNode : public AudioNode {
|
|
33
|
+
public:
|
|
34
|
+
explicit WorkletProcessingNode(
|
|
35
|
+
BaseAudioContext *context,
|
|
36
|
+
std::shared_ptr<worklets::SerializableWorklet> &worklet,
|
|
37
|
+
std::weak_ptr<worklets::WorkletRuntime> runtime
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
protected:
|
|
41
|
+
void processNode(const std::shared_ptr<AudioBus>& processingBus, int framesToProcess) override;
|
|
42
|
+
|
|
43
|
+
private:
|
|
44
|
+
WorkletsRunner workletRunner_;
|
|
45
|
+
std::shared_ptr<worklets::SerializableWorklet> shareableWorklet_;
|
|
46
|
+
std::vector<std::shared_ptr<AudioArrayBuffer>> inputBuffsHandles_;
|
|
47
|
+
std::vector<std::shared_ptr<AudioArrayBuffer>> outputBuffsHandles_;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
#endif // RN_AUDIO_API_TEST
|
|
51
|
+
|
|
52
|
+
} // namespace audioapi
|
|
@@ -28,12 +28,7 @@ AudioBufferBaseSourceNode::AudioBufferBaseSourceNode(
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
AudioBufferBaseSourceNode::~AudioBufferBaseSourceNode() {
|
|
31
|
-
|
|
32
|
-
context_->audioEventHandlerRegistry_ != nullptr) {
|
|
33
|
-
context_->audioEventHandlerRegistry_->unregisterHandler(
|
|
34
|
-
"positionChanged", onPositionChangedCallbackId_);
|
|
35
|
-
onPositionChangedCallbackId_ = 0;
|
|
36
|
-
}
|
|
31
|
+
clearOnPositionChangedCallback();
|
|
37
32
|
}
|
|
38
33
|
|
|
39
34
|
std::shared_ptr<AudioParam> AudioBufferBaseSourceNode::getDetuneParam() const {
|
|
@@ -29,6 +29,8 @@ AudioBufferSourceNode::~AudioBufferSourceNode() {
|
|
|
29
29
|
|
|
30
30
|
buffer_.reset();
|
|
31
31
|
alignedBus_.reset();
|
|
32
|
+
|
|
33
|
+
clearOnLoopEndedCallback();
|
|
32
34
|
}
|
|
33
35
|
|
|
34
36
|
bool AudioBufferSourceNode::getLoop() const {
|
|
@@ -123,6 +125,21 @@ void AudioBufferSourceNode::disable() {
|
|
|
123
125
|
alignedBus_.reset();
|
|
124
126
|
}
|
|
125
127
|
|
|
128
|
+
void AudioBufferSourceNode::clearOnLoopEndedCallback() {
|
|
129
|
+
if (onLoopEndedCallbackId_ == 0 || context_ == nullptr ||
|
|
130
|
+
context_->audioEventHandlerRegistry_ == nullptr) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
context_->audioEventHandlerRegistry_->unregisterHandler(
|
|
135
|
+
"loopEnded", onLoopEndedCallbackId_);
|
|
136
|
+
onLoopEndedCallbackId_ = 0;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
void AudioBufferSourceNode::setOnLoopEndedCallbackId(uint64_t callbackId) {
|
|
140
|
+
onLoopEndedCallbackId_ = callbackId;
|
|
141
|
+
}
|
|
142
|
+
|
|
126
143
|
void AudioBufferSourceNode::processNode(
|
|
127
144
|
const std::shared_ptr<AudioBus> &processingBus,
|
|
128
145
|
int framesToProcess) {
|
|
@@ -150,6 +167,15 @@ double AudioBufferSourceNode::getCurrentPosition() const {
|
|
|
150
167
|
static_cast<int>(vReadIndex_), buffer_->getSampleRate());
|
|
151
168
|
}
|
|
152
169
|
|
|
170
|
+
void AudioBufferSourceNode::sendOnLoopEndedEvent() {
|
|
171
|
+
auto onLoopEndedCallbackId =
|
|
172
|
+
onLoopEndedCallbackId_.load(std::memory_order_acquire);
|
|
173
|
+
if (onLoopEndedCallbackId != 0) {
|
|
174
|
+
context_->audioEventHandlerRegistry_->invokeHandlerWithEventBody(
|
|
175
|
+
"loopEnded", onLoopEndedCallbackId_, {});
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
153
179
|
/**
|
|
154
180
|
* Helper functions
|
|
155
181
|
*/
|
|
@@ -217,6 +243,8 @@ void AudioBufferSourceNode::processWithoutInterpolation(
|
|
|
217
243
|
playbackState_ = PlaybackState::STOP_SCHEDULED;
|
|
218
244
|
break;
|
|
219
245
|
}
|
|
246
|
+
|
|
247
|
+
sendOnLoopEndedEvent();
|
|
220
248
|
}
|
|
221
249
|
}
|
|
222
250
|
|
|
@@ -278,6 +306,8 @@ void AudioBufferSourceNode::processWithInterpolation(
|
|
|
278
306
|
playbackState_ = PlaybackState::STOP_SCHEDULED;
|
|
279
307
|
break;
|
|
280
308
|
}
|
|
309
|
+
|
|
310
|
+
sendOnLoopEndedEvent();
|
|
281
311
|
}
|
|
282
312
|
}
|
|
283
313
|
}
|
|
@@ -34,6 +34,9 @@ class AudioBufferSourceNode : public AudioBufferBaseSourceNode {
|
|
|
34
34
|
void start(double when, double offset, double duration = -1);
|
|
35
35
|
void disable() override;
|
|
36
36
|
|
|
37
|
+
void clearOnLoopEndedCallback();
|
|
38
|
+
void setOnLoopEndedCallbackId(uint64_t callbackId);
|
|
39
|
+
|
|
37
40
|
protected:
|
|
38
41
|
void processNode(const std::shared_ptr<AudioBus>& processingBus, int framesToProcess) override;
|
|
39
42
|
double getCurrentPosition() const override;
|
|
@@ -49,6 +52,9 @@ class AudioBufferSourceNode : public AudioBufferBaseSourceNode {
|
|
|
49
52
|
std::shared_ptr<AudioBuffer> buffer_;
|
|
50
53
|
std::shared_ptr<AudioBus> alignedBus_;
|
|
51
54
|
|
|
55
|
+
std::atomic<uint64_t> onLoopEndedCallbackId_ = 0; // 0 means no callback
|
|
56
|
+
void sendOnLoopEndedEvent();
|
|
57
|
+
|
|
52
58
|
void processWithoutInterpolation(
|
|
53
59
|
const std::shared_ptr<AudioBus>& processingBus,
|
|
54
60
|
size_t startOffset,
|
|
@@ -17,12 +17,7 @@ AudioScheduledSourceNode::AudioScheduledSourceNode(BaseAudioContext *context)
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
AudioScheduledSourceNode::~AudioScheduledSourceNode() {
|
|
20
|
-
|
|
21
|
-
context_->audioEventHandlerRegistry_ != nullptr) {
|
|
22
|
-
context_->audioEventHandlerRegistry_->unregisterHandler(
|
|
23
|
-
"ended", onEndedCallbackId_);
|
|
24
|
-
onEndedCallbackId_ = 0;
|
|
25
|
-
}
|
|
20
|
+
clearOnEndedCallback();
|
|
26
21
|
}
|
|
27
22
|
|
|
28
23
|
void AudioScheduledSourceNode::start(double when) {
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#include <audioapi/core/BaseAudioContext.h>
|
|
2
|
+
#include <audioapi/core/sources/ConstantSourceNode.h>
|
|
3
|
+
#include <audioapi/dsp/AudioUtils.h>
|
|
4
|
+
#include <audioapi/utils/AudioArray.h>
|
|
5
|
+
#include <audioapi/utils/AudioBus.h>
|
|
6
|
+
|
|
7
|
+
namespace audioapi {
|
|
8
|
+
ConstantSourceNode::ConstantSourceNode(BaseAudioContext *context)
|
|
9
|
+
: AudioScheduledSourceNode(context) {
|
|
10
|
+
offsetParam_ = std::make_shared<AudioParam>(
|
|
11
|
+
1.0, MOST_NEGATIVE_SINGLE_FLOAT, MOST_POSITIVE_SINGLE_FLOAT, context);
|
|
12
|
+
isInitialized_ = true;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
std::shared_ptr<AudioParam> ConstantSourceNode::getOffsetParam() const {
|
|
16
|
+
return offsetParam_;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
void ConstantSourceNode::processNode(
|
|
20
|
+
const std::shared_ptr<AudioBus> &processingBus,
|
|
21
|
+
int framesToProcess) {
|
|
22
|
+
size_t startOffset = 0;
|
|
23
|
+
size_t offsetLength = 0;
|
|
24
|
+
|
|
25
|
+
updatePlaybackInfo(processingBus, framesToProcess, startOffset, offsetLength);
|
|
26
|
+
|
|
27
|
+
if (!isPlaying() && !isStopScheduled()) {
|
|
28
|
+
processingBus->zero();
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
auto offsetBus = offsetParam_->processARateParam(
|
|
33
|
+
framesToProcess, context_->getCurrentTime());
|
|
34
|
+
|
|
35
|
+
auto offsetChannelData = offsetBus->getChannel(0)->getData();
|
|
36
|
+
|
|
37
|
+
for (int channel = 0; channel < processingBus->getNumberOfChannels();
|
|
38
|
+
++channel) {
|
|
39
|
+
auto outputChannelData = processingBus->getChannel(channel)->getData();
|
|
40
|
+
|
|
41
|
+
std::copy(
|
|
42
|
+
offsetChannelData + startOffset,
|
|
43
|
+
offsetChannelData + startOffset + offsetLength,
|
|
44
|
+
outputChannelData + startOffset);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (isStopScheduled()) {
|
|
48
|
+
handleStopScheduled();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
} // namespace audioapi
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <audioapi/core/AudioParam.h>
|
|
4
|
+
#include <audioapi/core/sources/AudioScheduledSourceNode.h>
|
|
5
|
+
|
|
6
|
+
#include <cmath>
|
|
7
|
+
#include <memory>
|
|
8
|
+
#include <string>
|
|
9
|
+
|
|
10
|
+
namespace audioapi {
|
|
11
|
+
|
|
12
|
+
class AudioBus;
|
|
13
|
+
|
|
14
|
+
class ConstantSourceNode : public AudioScheduledSourceNode {
|
|
15
|
+
public:
|
|
16
|
+
explicit ConstantSourceNode(BaseAudioContext *context);
|
|
17
|
+
|
|
18
|
+
[[nodiscard]] std::shared_ptr<AudioParam> getOffsetParam() const;
|
|
19
|
+
|
|
20
|
+
protected:
|
|
21
|
+
void processNode(const std::shared_ptr<AudioBus>& processingBus, int framesToProcess) override;
|
|
22
|
+
|
|
23
|
+
private:
|
|
24
|
+
std::shared_ptr<AudioParam> offsetParam_;
|
|
25
|
+
};
|
|
26
|
+
} // namespace audioapi
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
#include <audioapi/core/sources/WorkletSourceNode.h>
|
|
2
|
+
#include <audioapi/core/utils/Constants.h>
|
|
3
|
+
|
|
4
|
+
namespace audioapi {
|
|
5
|
+
|
|
6
|
+
WorkletSourceNode::WorkletSourceNode(
|
|
7
|
+
BaseAudioContext *context,
|
|
8
|
+
std::shared_ptr<worklets::SerializableWorklet> &worklet,
|
|
9
|
+
std::weak_ptr<worklets::WorkletRuntime> runtime)
|
|
10
|
+
: AudioScheduledSourceNode(context),
|
|
11
|
+
workletRunner_(runtime),
|
|
12
|
+
shareableWorklet_(worklet) {
|
|
13
|
+
isInitialized_ = true;
|
|
14
|
+
|
|
15
|
+
// Prepare buffers for audio processing
|
|
16
|
+
size_t outputChannelCount = this->getChannelCount();
|
|
17
|
+
outputBuffsHandles_.resize(outputChannelCount);
|
|
18
|
+
for (size_t i = 0; i < outputChannelCount; ++i) {
|
|
19
|
+
auto buff = new uint8_t[RENDER_QUANTUM_SIZE * sizeof(float)];
|
|
20
|
+
outputBuffsHandles_[i] = std::make_shared<AudioArrayBuffer>(
|
|
21
|
+
buff, RENDER_QUANTUM_SIZE * sizeof(float));
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
void WorkletSourceNode::processNode(
|
|
26
|
+
const std::shared_ptr<AudioBus> &processingBus,
|
|
27
|
+
int framesToProcess) {
|
|
28
|
+
if (isUnscheduled() || isFinished() || !isEnabled()) {
|
|
29
|
+
processingBus->zero();
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
size_t startOffset = 0;
|
|
34
|
+
size_t nonSilentFramesToProcess = framesToProcess;
|
|
35
|
+
|
|
36
|
+
updatePlaybackInfo(
|
|
37
|
+
processingBus, framesToProcess, startOffset, nonSilentFramesToProcess);
|
|
38
|
+
|
|
39
|
+
if (nonSilentFramesToProcess == 0) {
|
|
40
|
+
processingBus->zero();
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
size_t outputChannelCount = processingBus->getNumberOfChannels();
|
|
45
|
+
|
|
46
|
+
auto result = workletRunner_.executeOnRuntimeGuardedSync(
|
|
47
|
+
[this, nonSilentFramesToProcess, startOffset](jsi::Runtime &rt) {
|
|
48
|
+
auto jsiArray = jsi::Array(rt, this->outputBuffsHandles_.size());
|
|
49
|
+
for (size_t i = 0; i < this->outputBuffsHandles_.size(); ++i) {
|
|
50
|
+
auto arrayBuffer = jsi::ArrayBuffer(rt, this->outputBuffsHandles_[i]);
|
|
51
|
+
jsiArray.setValueAtIndex(rt, i, arrayBuffer);
|
|
52
|
+
}
|
|
53
|
+
return workletRunner_
|
|
54
|
+
.executeWorklet(
|
|
55
|
+
shareableWorklet_,
|
|
56
|
+
jsiArray,
|
|
57
|
+
jsi::Value(rt, static_cast<int>(nonSilentFramesToProcess)),
|
|
58
|
+
jsi::Value(rt, this->context_->getCurrentTime()),
|
|
59
|
+
jsi::Value(rt, static_cast<int>(startOffset)))
|
|
60
|
+
.value_or(jsi::Value::undefined());
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// If the worklet execution failed, zero the output
|
|
64
|
+
// It might happen if the runtime is not available
|
|
65
|
+
if (!result.has_value()) {
|
|
66
|
+
processingBus->zero();
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Copy the processed data back to the AudioBus
|
|
71
|
+
for (size_t i = 0; i < outputChannelCount; ++i) {
|
|
72
|
+
float *channelData = processingBus->getChannel(i)->getData();
|
|
73
|
+
memcpy(
|
|
74
|
+
channelData + startOffset,
|
|
75
|
+
outputBuffsHandles_[i]->data(),
|
|
76
|
+
nonSilentFramesToProcess * sizeof(float));
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
handleStopScheduled();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
} // namespace audioapi
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
#include <jsi/jsi.h>
|
|
3
|
+
#include <audioapi/core/BaseAudioContext.h>
|
|
4
|
+
#include <audioapi/utils/AudioBus.h>
|
|
5
|
+
#include <audioapi/core/sources/AudioScheduledSourceNode.h>
|
|
6
|
+
#include <audioapi/core/utils/worklets/SafeIncludes.h>
|
|
7
|
+
#include <audioapi/core/utils/worklets/WorkletsRunner.h>
|
|
8
|
+
#include <audioapi/jsi/AudioArrayBuffer.h>
|
|
9
|
+
#include <audioapi/utils/AudioArray.h>
|
|
10
|
+
|
|
11
|
+
#include <vector>
|
|
12
|
+
#include <memory>
|
|
13
|
+
|
|
14
|
+
namespace audioapi {
|
|
15
|
+
|
|
16
|
+
#if RN_AUDIO_API_TEST
|
|
17
|
+
class WorkletSourceNode : public AudioScheduledSourceNode {
|
|
18
|
+
public:
|
|
19
|
+
explicit WorkletSourceNode(
|
|
20
|
+
BaseAudioContext *context,
|
|
21
|
+
std::shared_ptr<worklets::SerializableWorklet> &worklet,
|
|
22
|
+
std::weak_ptr<worklets::WorkletRuntime> runtime
|
|
23
|
+
) : AudioScheduledSourceNode(context) {}
|
|
24
|
+
|
|
25
|
+
protected:
|
|
26
|
+
void processNode(const std::shared_ptr<AudioBus>& processingBus, int framesToProcess) override {}
|
|
27
|
+
};
|
|
28
|
+
#else
|
|
29
|
+
|
|
30
|
+
class WorkletSourceNode : public AudioScheduledSourceNode {
|
|
31
|
+
public:
|
|
32
|
+
explicit WorkletSourceNode(
|
|
33
|
+
BaseAudioContext *context,
|
|
34
|
+
std::shared_ptr<worklets::SerializableWorklet> &worklet,
|
|
35
|
+
std::weak_ptr<worklets::WorkletRuntime> runtime
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
protected:
|
|
39
|
+
void processNode(const std::shared_ptr<AudioBus>& processingBus, int framesToProcess) override;
|
|
40
|
+
private:
|
|
41
|
+
WorkletsRunner workletRunner_;
|
|
42
|
+
std::shared_ptr<worklets::SerializableWorklet> shareableWorklet_;
|
|
43
|
+
std::vector<std::shared_ptr<AudioArrayBuffer>> outputBuffsHandles_;
|
|
44
|
+
};
|
|
45
|
+
#endif // RN_AUDIO_API_TEST
|
|
46
|
+
|
|
47
|
+
} // namespace audioapi
|
|
@@ -31,12 +31,12 @@ bool AudioParamEventQueue::popFront(ParamChangeEvent &event) {
|
|
|
31
31
|
|
|
32
32
|
void AudioParamEventQueue::cancelScheduledValues(double cancelTime) {
|
|
33
33
|
while (!eventQueue_.isEmpty()) {
|
|
34
|
-
auto &
|
|
35
|
-
if (
|
|
34
|
+
auto &back = eventQueue_.peekBack();
|
|
35
|
+
if (back.getEndTime() < cancelTime) {
|
|
36
36
|
break;
|
|
37
37
|
}
|
|
38
|
-
if (
|
|
39
|
-
|
|
38
|
+
if (back.getStartTime() >= cancelTime ||
|
|
39
|
+
back.getType() == ParamChangeEventType::SET_VALUE_CURVE) {
|
|
40
40
|
eventQueue_.popBack();
|
|
41
41
|
}
|
|
42
42
|
}
|
|
@@ -46,8 +46,8 @@ void AudioParamEventQueue::cancelAndHoldAtTime(
|
|
|
46
46
|
double cancelTime,
|
|
47
47
|
double &endTimeCache) {
|
|
48
48
|
while (!eventQueue_.isEmpty()) {
|
|
49
|
-
auto &
|
|
50
|
-
if (
|
|
49
|
+
auto &back = eventQueue_.peekBack();
|
|
50
|
+
if (back.getEndTime() < cancelTime || back.getStartTime() <= cancelTime) {
|
|
51
51
|
break;
|
|
52
52
|
}
|
|
53
53
|
eventQueue_.popBack();
|
|
@@ -59,6 +59,12 @@ void AudioParamEventQueue::cancelAndHoldAtTime(
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
auto &back = eventQueue_.peekBackMut();
|
|
62
|
+
back.setEndValue(back.getCalculateValue()(
|
|
63
|
+
back.getStartTime(),
|
|
64
|
+
back.getEndTime(),
|
|
65
|
+
back.getStartValue(),
|
|
66
|
+
back.getEndValue(),
|
|
67
|
+
cancelTime));
|
|
62
68
|
back.setEndTime(std::min(cancelTime, back.getEndTime()));
|
|
63
69
|
}
|
|
64
70
|
|
|
@@ -16,4 +16,9 @@ static constexpr float MOST_NEGATIVE_SINGLE_FLOAT = static_cast<float>(std::nume
|
|
|
16
16
|
static float LOG2_MOST_POSITIVE_SINGLE_FLOAT = std::log2(MOST_POSITIVE_SINGLE_FLOAT);
|
|
17
17
|
static float LOG10_MOST_POSITIVE_SINGLE_FLOAT = std::log10(MOST_POSITIVE_SINGLE_FLOAT);
|
|
18
18
|
static constexpr float PI = static_cast<float>(M_PI);
|
|
19
|
+
|
|
20
|
+
// buffer sizes
|
|
21
|
+
static constexpr size_t PROMISE_VENDOR_THREAD_POOL_WORKER_COUNT = 4;
|
|
22
|
+
static constexpr size_t PROMISE_VENDOR_THREAD_POOL_LOAD_BALANCER_QUEUE_SIZE = 32;
|
|
23
|
+
static constexpr size_t PROMISE_VENDOR_THREAD_POOL_WORKER_QUEUE_SIZE = 32;
|
|
19
24
|
} // namespace audioapi
|
|
@@ -43,3 +43,10 @@ class SerializableWorklet {
|
|
|
43
43
|
};
|
|
44
44
|
} // namespace worklets
|
|
45
45
|
#endif
|
|
46
|
+
|
|
47
|
+
/// @brief Struct to hold references to different runtimes used in the AudioAPI
|
|
48
|
+
/// @note it is used to pass them around and avoid creating multiple instances of the same runtime
|
|
49
|
+
struct RuntimeRegistry {
|
|
50
|
+
std::weak_ptr<worklets::WorkletRuntime> uiRuntime;
|
|
51
|
+
std::weak_ptr<worklets::WorkletRuntime> audioRuntime;
|
|
52
|
+
};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
#include <audioapi/core/utils/worklets/
|
|
1
|
+
#include <audioapi/core/utils/worklets/WorkletsRunner.h>
|
|
2
2
|
|
|
3
3
|
namespace audioapi {
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
WorkletsRunner::WorkletsRunner(
|
|
6
6
|
std::weak_ptr<worklets::WorkletRuntime> weakUiRuntime) noexcept
|
|
7
7
|
: weakUiRuntime_(std::move(weakUiRuntime)) {}
|
|
8
8
|
|
|
@@ -24,9 +24,9 @@ using namespace facebook;
|
|
|
24
24
|
* This will return a shared pointer to the extracted worklet, or throw an error if the argument is invalid.
|
|
25
25
|
*/
|
|
26
26
|
|
|
27
|
-
class
|
|
27
|
+
class WorkletsRunner {
|
|
28
28
|
public:
|
|
29
|
-
explicit
|
|
29
|
+
explicit WorkletsRunner(std::weak_ptr<worklets::WorkletRuntime> weakUiRuntime) noexcept;
|
|
30
30
|
|
|
31
31
|
/// @brief Execute a job on the UI runtime safely.
|
|
32
32
|
/// @param job
|
|
@@ -53,8 +53,9 @@ class AudioEventHandlerRegistry : public IAudioEventHandlerRegistry {
|
|
|
53
53
|
"volumeChange",
|
|
54
54
|
};
|
|
55
55
|
|
|
56
|
-
static constexpr std::array<std::string_view,
|
|
56
|
+
static constexpr std::array<std::string_view, 6> AUDIO_API_EVENT_NAMES = {
|
|
57
57
|
"ended",
|
|
58
|
+
"loopEnded",
|
|
58
59
|
"audioReady",
|
|
59
60
|
"positionChanged",
|
|
60
61
|
"audioError",
|
|
@@ -66,8 +66,10 @@ jsi::Value PromiseVendor::createAsyncPromise(
|
|
|
66
66
|
&&function) {
|
|
67
67
|
auto &runtime = *runtime_;
|
|
68
68
|
auto callInvoker = callInvoker_;
|
|
69
|
+
auto threadPool = threadPool_;
|
|
69
70
|
auto promiseCtor = runtime.global().getPropertyAsFunction(runtime, "Promise");
|
|
70
|
-
auto promiseLambda = [
|
|
71
|
+
auto promiseLambda = [threadPool = std::move(threadPool),
|
|
72
|
+
callInvoker = std::move(callInvoker),
|
|
71
73
|
function = std::move(function)](
|
|
72
74
|
jsi::Runtime &runtime,
|
|
73
75
|
const jsi::Value &thisValue,
|
|
@@ -78,32 +80,26 @@ jsi::Value PromiseVendor::createAsyncPromise(
|
|
|
78
80
|
auto rejectLocal = arguments[1].asObject(runtime).asFunction(runtime);
|
|
79
81
|
auto reject = std::make_shared<jsi::Function>(std::move(rejectLocal));
|
|
80
82
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
reject->call(runtime, error.value());
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
},
|
|
105
|
-
std::ref(runtime))
|
|
106
|
-
.detach();
|
|
83
|
+
threadPool->schedule([callInvoker = std::move(callInvoker),
|
|
84
|
+
function = std::move(function),
|
|
85
|
+
resolve = std::move(resolve),
|
|
86
|
+
reject = std::move(reject),
|
|
87
|
+
&runtime]() {
|
|
88
|
+
auto result = function(runtime);
|
|
89
|
+
if (std::holds_alternative<jsi::Value>(result)) {
|
|
90
|
+
auto valueShared = std::make_shared<jsi::Value>(
|
|
91
|
+
std::move(std::get<jsi::Value>(result)));
|
|
92
|
+
callInvoker->invokeAsync([resolve, &runtime, valueShared]() -> void {
|
|
93
|
+
resolve->call(runtime, *valueShared);
|
|
94
|
+
});
|
|
95
|
+
} else {
|
|
96
|
+
auto errorMessage = std::get<std::string>(result);
|
|
97
|
+
callInvoker->invokeAsync([reject, &runtime, errorMessage]() -> void {
|
|
98
|
+
auto error = jsi::JSError(runtime, errorMessage);
|
|
99
|
+
reject->call(runtime, error.value());
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
});
|
|
107
103
|
return jsi::Value::undefined();
|
|
108
104
|
};
|
|
109
105
|
auto promiseFunction = jsi::Function::createFromHostFunction(
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
|
|
3
|
+
|
|
4
|
+
#include <audioapi/core/utils/Constants.h>
|
|
3
5
|
#include <ReactCommon/CallInvoker.h>
|
|
4
6
|
#include <jsi/jsi.h>
|
|
5
7
|
#include <variant>
|
|
@@ -8,6 +10,7 @@
|
|
|
8
10
|
#include <string>
|
|
9
11
|
#include <utility>
|
|
10
12
|
#include <functional>
|
|
13
|
+
#include <audioapi/utils/ThreadPool.hpp>
|
|
11
14
|
|
|
12
15
|
namespace audioapi {
|
|
13
16
|
|
|
@@ -32,7 +35,11 @@ class Promise {
|
|
|
32
35
|
|
|
33
36
|
class PromiseVendor {
|
|
34
37
|
public:
|
|
35
|
-
PromiseVendor(jsi::Runtime *runtime, const std::shared_ptr<react::CallInvoker> &callInvoker):
|
|
38
|
+
PromiseVendor(jsi::Runtime *runtime, const std::shared_ptr<react::CallInvoker> &callInvoker):
|
|
39
|
+
runtime_(runtime), callInvoker_(callInvoker), threadPool_(std::make_shared<ThreadPool>(
|
|
40
|
+
audioapi::PROMISE_VENDOR_THREAD_POOL_WORKER_COUNT,
|
|
41
|
+
audioapi::PROMISE_VENDOR_THREAD_POOL_LOAD_BALANCER_QUEUE_SIZE,
|
|
42
|
+
audioapi::PROMISE_VENDOR_THREAD_POOL_WORKER_QUEUE_SIZE)) {}
|
|
36
43
|
|
|
37
44
|
jsi::Value createPromise(const std::function<void(std::shared_ptr<Promise>)> &function);
|
|
38
45
|
|
|
@@ -40,6 +47,7 @@ class PromiseVendor {
|
|
|
40
47
|
/// @param function The function to execute asynchronously. It should return either a jsi::Value on success or a std::string error message on failure.
|
|
41
48
|
/// @return The created promise.
|
|
42
49
|
/// @note The function is executed on a different thread, and the promise is resolved or rejected based on the function's outcome.
|
|
50
|
+
/// @note IMPORTANT: This function is not thread-safe and should be called from a single thread only. (comes from underlying ThreadPool implementation)
|
|
43
51
|
/// @example
|
|
44
52
|
/// ```cpp
|
|
45
53
|
/// auto promise = promiseVendor_->createAsyncPromise(
|
|
@@ -56,6 +64,7 @@ class PromiseVendor {
|
|
|
56
64
|
private:
|
|
57
65
|
jsi::Runtime *runtime_;
|
|
58
66
|
std::shared_ptr<react::CallInvoker> callInvoker_;
|
|
67
|
+
std::shared_ptr<ThreadPool> threadPool_;
|
|
59
68
|
};
|
|
60
69
|
|
|
61
70
|
} // namespace audioapi
|