react-native-audio-api 0.6.5-rc.1 → 0.7.0-nightly-fba4835-20250717
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/README.md +4 -1
- package/android/src/main/cpp/audioapi/android/core/AudioDecoder.cpp +56 -47
- package/android/src/main/cpp/audioapi/android/core/AudioPlayer.cpp +38 -8
- package/android/src/main/cpp/audioapi/android/core/AudioPlayer.h +9 -3
- package/android/src/main/java/com/swmansion/audioapi/AudioAPIModule.kt +4 -0
- package/android/src/main/java/com/swmansion/audioapi/system/LockScreenManager.kt +2 -2
- package/android/src/main/java/com/swmansion/audioapi/system/MediaNotificationManager.kt +2 -2
- package/android/src/main/java/com/swmansion/audioapi/system/MediaSessionCallback.kt +2 -2
- package/android/src/main/java/com/swmansion/audioapi/system/MediaSessionManager.kt +46 -0
- package/android/src/main/res/drawable/skip_backward_15.xml +16 -0
- package/android/src/main/res/drawable/skip_forward_15.xml +16 -0
- package/android/src/oldarch/NativeAudioAPIModuleSpec.java +4 -0
- package/common/cpp/audioapi/HostObjects/AudioBufferBaseSourceNodeHostObject.h +9 -0
- package/common/cpp/audioapi/HostObjects/AudioBufferSourceNodeHostObject.h +3 -5
- package/common/cpp/audioapi/HostObjects/AudioScheduledSourceNodeHostObject.h +11 -2
- package/common/cpp/audioapi/HostObjects/BaseAudioContextHostObject.h +24 -23
- package/common/cpp/audioapi/core/AudioContext.cpp +6 -4
- package/common/cpp/audioapi/core/AudioContext.h +1 -1
- package/common/cpp/audioapi/core/AudioParam.cpp +18 -4
- package/common/cpp/audioapi/core/AudioParam.h +3 -0
- package/common/cpp/audioapi/core/BaseAudioContext.cpp +3 -3
- package/common/cpp/audioapi/core/BaseAudioContext.h +4 -3
- package/common/cpp/audioapi/core/OfflineAudioContext.cpp +2 -1
- package/common/cpp/audioapi/core/OfflineAudioContext.h +1 -1
- package/common/cpp/audioapi/core/effects/PeriodicWave.cpp +1 -1
- package/common/cpp/audioapi/core/inputs/AudioRecorder.h +1 -0
- package/common/cpp/audioapi/core/sources/AudioBuffer.h +1 -0
- package/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.cpp +11 -0
- package/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.h +4 -1
- package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.cpp +11 -0
- package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.h +2 -1
- package/common/cpp/audioapi/core/utils/AudioDecoder.h +38 -1
- package/common/cpp/audioapi/core/utils/AudioNodeDestructor.h +1 -0
- package/common/cpp/audioapi/core/utils/AudioNodeManager.h +1 -2
- package/common/cpp/audioapi/dsp/AudioUtils.cpp +1 -1
- package/common/cpp/audioapi/events/AudioEventHandlerRegistry.cpp +47 -17
- package/common/cpp/audioapi/events/AudioEventHandlerRegistry.h +6 -5
- package/common/cpp/audioapi/events/IAudioEventHandlerRegistry.h +25 -0
- package/common/cpp/audioapi/jsi/JsiPromise.cpp +1 -0
- package/common/cpp/audioapi/libs/audio-stretch/stretch.c +610 -0
- package/common/cpp/audioapi/libs/audio-stretch/stretch.h +49 -0
- package/common/cpp/audioapi/utils/AudioArray.h +1 -0
- package/common/cpp/audioapi/utils/CircularAudioArray.h +1 -0
- package/common/cpp/test/CMakeLists.txt +63 -0
- package/common/cpp/test/GainTest.cpp +78 -0
- package/common/cpp/test/MockAudioEventHandlerRegistry.h +22 -0
- package/common/cpp/test/OscillatorTest.cpp +22 -0
- package/common/cpp/test/RunTests.sh +26 -0
- package/ios/audioapi/ios/AudioAPIModule.mm +17 -8
- package/ios/audioapi/ios/core/AudioDecoder.mm +37 -31
- package/ios/audioapi/ios/core/IOSAudioPlayer.h +2 -1
- package/ios/audioapi/ios/core/IOSAudioPlayer.mm +5 -2
- package/ios/audioapi/ios/system/AudioSessionManager.h +4 -0
- package/ios/audioapi/ios/system/AudioSessionManager.mm +26 -0
- package/ios/audioapi/ios/system/LockScreenManager.mm +2 -0
- package/lib/commonjs/core/AudioBufferSourceNode.js +2 -2
- package/lib/commonjs/core/AudioBufferSourceNode.js.map +1 -1
- package/lib/commonjs/core/AudioScheduledSourceNode.js +4 -4
- package/lib/commonjs/core/AudioScheduledSourceNode.js.map +1 -1
- package/lib/commonjs/core/BaseAudioContext.js +7 -6
- package/lib/commonjs/core/BaseAudioContext.js.map +1 -1
- package/lib/commonjs/plugin/withAudioAPI.js +1 -1
- package/lib/commonjs/plugin/withAudioAPI.js.map +1 -1
- package/lib/commonjs/specs/NativeAudioAPIModule.js.map +1 -1
- package/lib/commonjs/system/AudioManager.js +3 -0
- package/lib/commonjs/system/AudioManager.js.map +1 -1
- package/lib/module/core/AudioBufferSourceNode.js +2 -2
- package/lib/module/core/AudioBufferSourceNode.js.map +1 -1
- package/lib/module/core/AudioScheduledSourceNode.js +4 -4
- package/lib/module/core/AudioScheduledSourceNode.js.map +1 -1
- package/lib/module/core/BaseAudioContext.js +7 -6
- package/lib/module/core/BaseAudioContext.js.map +1 -1
- package/lib/module/plugin/withAudioAPI.js +1 -1
- package/lib/module/plugin/withAudioAPI.js.map +1 -1
- package/lib/module/specs/NativeAudioAPIModule.js.map +1 -1
- package/lib/module/system/AudioManager.js +3 -0
- package/lib/module/system/AudioManager.js.map +1 -1
- package/lib/typescript/core/AudioBufferSourceNode.d.ts.map +1 -1
- package/lib/typescript/core/AudioScheduledSourceNode.d.ts +2 -2
- package/lib/typescript/core/BaseAudioContext.d.ts +4 -1
- package/lib/typescript/core/BaseAudioContext.d.ts.map +1 -1
- package/lib/typescript/interfaces.d.ts +3 -3
- package/lib/typescript/interfaces.d.ts.map +1 -1
- package/lib/typescript/specs/NativeAudioAPIModule.d.ts +2 -1
- package/lib/typescript/specs/NativeAudioAPIModule.d.ts.map +1 -1
- package/lib/typescript/system/AudioManager.d.ts +2 -1
- package/lib/typescript/system/AudioManager.d.ts.map +1 -1
- package/lib/typescript/system/types.d.ts +11 -0
- package/lib/typescript/system/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/core/AudioBufferSourceNode.ts +2 -8
- package/src/core/AudioScheduledSourceNode.ts +4 -4
- package/src/core/BaseAudioContext.ts +12 -9
- package/src/interfaces.ts +6 -6
- package/src/plugin/withAudioAPI.ts +1 -1
- package/src/specs/NativeAudioAPIModule.ts +4 -1
- package/src/system/AudioManager.ts +10 -1
- package/src/system/types.ts +14 -0
- package/android/src/main/res/drawable/skip_backward_10.xml +0 -9
- package/android/src/main/res/drawable/skip_forward_10.xml +0 -9
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#include <audioapi/core/AudioParam.h>
|
|
2
2
|
#include <audioapi/core/BaseAudioContext.h>
|
|
3
|
+
#include <audioapi/core/utils/Locker.h>
|
|
3
4
|
#include <audioapi/dsp/AudioUtils.h>
|
|
4
5
|
#include <audioapi/dsp/VectorMath.h>
|
|
5
6
|
#include <audioapi/utils/AudioArray.h>
|
|
@@ -17,10 +18,11 @@ AudioParam::AudioParam(
|
|
|
17
18
|
minValue_(minValue),
|
|
18
19
|
maxValue_(maxValue),
|
|
19
20
|
context_(context),
|
|
20
|
-
audioBus_(
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
audioBus_(
|
|
22
|
+
std::make_shared<AudioBus>(
|
|
23
|
+
RENDER_QUANTUM_SIZE,
|
|
24
|
+
1,
|
|
25
|
+
context->getSampleRate())) {
|
|
24
26
|
startTime_ = 0;
|
|
25
27
|
endTime_ = 0;
|
|
26
28
|
startValue_ = value_;
|
|
@@ -46,11 +48,16 @@ float AudioParam::getMaxValue() const {
|
|
|
46
48
|
return maxValue_;
|
|
47
49
|
}
|
|
48
50
|
|
|
51
|
+
std::mutex &AudioParam::getQueueLock() {
|
|
52
|
+
return queueLock_;
|
|
53
|
+
}
|
|
54
|
+
|
|
49
55
|
void AudioParam::setValue(float value) {
|
|
50
56
|
value_ = std::clamp(value, minValue_, maxValue_);
|
|
51
57
|
}
|
|
52
58
|
|
|
53
59
|
float AudioParam::getValueAtTime(double time) {
|
|
60
|
+
Locker lock(getQueueLock());
|
|
54
61
|
if (endTime_ < time && !eventsQueue_.empty()) {
|
|
55
62
|
auto event = eventsQueue_.front();
|
|
56
63
|
startTime_ = event.getStartTime();
|
|
@@ -83,6 +90,7 @@ void AudioParam::setValueAtTime(float value, double startTime) {
|
|
|
83
90
|
return endValue;
|
|
84
91
|
};
|
|
85
92
|
|
|
93
|
+
Locker lock(getQueueLock());
|
|
86
94
|
auto event = ParamChangeEvent(
|
|
87
95
|
startTime,
|
|
88
96
|
startTime,
|
|
@@ -116,6 +124,7 @@ void AudioParam::linearRampToValueAtTime(float value, double endTime) {
|
|
|
116
124
|
return endValue;
|
|
117
125
|
};
|
|
118
126
|
|
|
127
|
+
Locker lock(getQueueLock());
|
|
119
128
|
auto event = ParamChangeEvent(
|
|
120
129
|
getQueueEndTime(),
|
|
121
130
|
endTime,
|
|
@@ -150,6 +159,7 @@ void AudioParam::exponentialRampToValueAtTime(float value, double endTime) {
|
|
|
150
159
|
return endValue;
|
|
151
160
|
};
|
|
152
161
|
|
|
162
|
+
Locker lock(getQueueLock());
|
|
153
163
|
auto event = ParamChangeEvent(
|
|
154
164
|
getQueueEndTime(),
|
|
155
165
|
endTime,
|
|
@@ -180,6 +190,7 @@ void AudioParam::setTargetAtTime(
|
|
|
180
190
|
(startValue - target) * exp(-(time - startTime) / timeConstant));
|
|
181
191
|
};
|
|
182
192
|
|
|
193
|
+
Locker lock(getQueueLock());
|
|
183
194
|
auto event = ParamChangeEvent(
|
|
184
195
|
startTime,
|
|
185
196
|
startTime,
|
|
@@ -224,6 +235,7 @@ void AudioParam::setValueCurveAtTime(
|
|
|
224
235
|
return endValue;
|
|
225
236
|
};
|
|
226
237
|
|
|
238
|
+
Locker lock(getQueueLock());
|
|
227
239
|
auto event = ParamChangeEvent(
|
|
228
240
|
startTime,
|
|
229
241
|
startTime + duration,
|
|
@@ -235,6 +247,7 @@ void AudioParam::setValueCurveAtTime(
|
|
|
235
247
|
}
|
|
236
248
|
|
|
237
249
|
void AudioParam::cancelScheduledValues(double cancelTime) {
|
|
250
|
+
Locker lock(getQueueLock());
|
|
238
251
|
auto it = eventsQueue_.rbegin();
|
|
239
252
|
while (it->getEndTime() >= cancelTime) {
|
|
240
253
|
if (it->getStartTime() >= cancelTime ||
|
|
@@ -247,6 +260,7 @@ void AudioParam::cancelScheduledValues(double cancelTime) {
|
|
|
247
260
|
}
|
|
248
261
|
|
|
249
262
|
void AudioParam::cancelAndHoldAtTime(double cancelTime) {
|
|
263
|
+
Locker lock(getQueueLock());
|
|
250
264
|
auto it = eventsQueue_.rbegin();
|
|
251
265
|
while (it->getEndTime() >= cancelTime) {
|
|
252
266
|
if (it->getStartTime() >= cancelTime) {
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
#include <vector>
|
|
11
11
|
#include <unordered_set>
|
|
12
12
|
#include <cstddef>
|
|
13
|
+
#include <mutex>
|
|
13
14
|
|
|
14
15
|
namespace audioapi {
|
|
15
16
|
|
|
@@ -50,6 +51,7 @@ class AudioParam {
|
|
|
50
51
|
std::deque<ParamChangeEvent> eventsQueue_;
|
|
51
52
|
std::unordered_set<AudioNode *> inputNodes_;
|
|
52
53
|
std::shared_ptr<AudioBus> audioBus_;
|
|
54
|
+
std::mutex queueLock_;
|
|
53
55
|
|
|
54
56
|
double startTime_;
|
|
55
57
|
double endTime_;
|
|
@@ -58,6 +60,7 @@ class AudioParam {
|
|
|
58
60
|
std::function<float(double, double, float, float, double)> calculateValue_;
|
|
59
61
|
std::vector<std::shared_ptr<AudioBus>> inputBuses_ = {};
|
|
60
62
|
|
|
63
|
+
std::mutex &getQueueLock();
|
|
61
64
|
double getQueueEndTime();
|
|
62
65
|
float getQueueEndValue();
|
|
63
66
|
void updateQueue(ParamChangeEvent &event);
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
namespace audioapi {
|
|
20
20
|
|
|
21
21
|
BaseAudioContext::BaseAudioContext(
|
|
22
|
-
const std::shared_ptr<
|
|
22
|
+
const std::shared_ptr<IAudioEventHandlerRegistry>
|
|
23
23
|
&audioEventHandlerRegistry) {
|
|
24
24
|
nodeManager_ = std::make_shared<AudioNodeManager>();
|
|
25
25
|
destination_ = std::make_shared<AudioDestinationNode>(this);
|
|
@@ -141,8 +141,8 @@ std::shared_ptr<AudioBuffer> BaseAudioContext::decodeAudioData(
|
|
|
141
141
|
}
|
|
142
142
|
|
|
143
143
|
std::shared_ptr<AudioBuffer> BaseAudioContext::decodeWithPCMInBase64(
|
|
144
|
-
const std::string &data) {
|
|
145
|
-
auto audioBus = audioDecoder_->decodeWithPCMInBase64(data);
|
|
144
|
+
const std::string &data, float playbackSpeed) {
|
|
145
|
+
auto audioBus = audioDecoder_->decodeWithPCMInBase64(data, playbackSpeed);
|
|
146
146
|
|
|
147
147
|
if (!audioBus) {
|
|
148
148
|
return nullptr;
|
|
@@ -29,10 +29,11 @@ class AudioBufferQueueSourceNode;
|
|
|
29
29
|
class AudioDecoder;
|
|
30
30
|
class AnalyserNode;
|
|
31
31
|
class AudioEventHandlerRegistry;
|
|
32
|
+
class IAudioEventHandlerRegistry;
|
|
32
33
|
|
|
33
34
|
class BaseAudioContext {
|
|
34
35
|
public:
|
|
35
|
-
explicit BaseAudioContext(const std::shared_ptr<
|
|
36
|
+
explicit BaseAudioContext(const std::shared_ptr<IAudioEventHandlerRegistry> &audioEventHandlerRegistry);
|
|
36
37
|
virtual ~BaseAudioContext() = default;
|
|
37
38
|
|
|
38
39
|
std::string getState();
|
|
@@ -58,7 +59,7 @@ class BaseAudioContext {
|
|
|
58
59
|
|
|
59
60
|
std::shared_ptr<AudioBuffer> decodeAudioDataSource(const std::string &path);
|
|
60
61
|
std::shared_ptr<AudioBuffer> decodeAudioData(const void *data, size_t size);
|
|
61
|
-
std::shared_ptr<AudioBuffer> decodeWithPCMInBase64(const std::string &data);
|
|
62
|
+
std::shared_ptr<AudioBuffer> decodeWithPCMInBase64(const std::string &data, float playbackSpeed);
|
|
62
63
|
|
|
63
64
|
std::shared_ptr<PeriodicWave> getBasicWaveForm(OscillatorType type);
|
|
64
65
|
[[nodiscard]] float getNyquistFrequency() const;
|
|
@@ -86,7 +87,7 @@ class BaseAudioContext {
|
|
|
86
87
|
std::shared_ptr<PeriodicWave> cachedTriangleWave_ = nullptr;
|
|
87
88
|
|
|
88
89
|
public:
|
|
89
|
-
std::shared_ptr<
|
|
90
|
+
std::shared_ptr<IAudioEventHandlerRegistry> audioEventHandlerRegistry_;
|
|
90
91
|
};
|
|
91
92
|
|
|
92
93
|
} // namespace audioapi
|
|
@@ -22,7 +22,8 @@ OfflineAudioContext::OfflineAudioContext(
|
|
|
22
22
|
int numberOfChannels,
|
|
23
23
|
size_t length,
|
|
24
24
|
float sampleRate,
|
|
25
|
-
const std::shared_ptr<
|
|
25
|
+
const std::shared_ptr<IAudioEventHandlerRegistry>
|
|
26
|
+
&audioEventHandlerRegistry)
|
|
26
27
|
: BaseAudioContext(audioEventHandlerRegistry),
|
|
27
28
|
length_(length),
|
|
28
29
|
numberOfChannels_(numberOfChannels),
|
|
@@ -14,7 +14,7 @@ using OfflineAudioContextResultCallback = std::function<void(std::shared_ptr<Aud
|
|
|
14
14
|
|
|
15
15
|
class OfflineAudioContext : public BaseAudioContext {
|
|
16
16
|
public:
|
|
17
|
-
explicit OfflineAudioContext(int numberOfChannels, size_t length, float sampleRate, const std::shared_ptr<
|
|
17
|
+
explicit OfflineAudioContext(int numberOfChannels, size_t length, float sampleRate, const std::shared_ptr<IAudioEventHandlerRegistry> &audioEventHandlerRegistry);
|
|
18
18
|
~OfflineAudioContext() override;
|
|
19
19
|
|
|
20
20
|
void resume();
|
|
@@ -118,7 +118,7 @@ int PeriodicWave::getNumberOfPartialsPerRange(int rangeIndex) const {
|
|
|
118
118
|
auto centsToCull = static_cast<float>(rangeIndex) * CentsPerRange;
|
|
119
119
|
|
|
120
120
|
// A value from 0 -> 1 representing what fraction of the partials to keep.
|
|
121
|
-
auto cullingScale = std::
|
|
121
|
+
auto cullingScale = std::pow(2, -centsToCull / 1200);
|
|
122
122
|
|
|
123
123
|
// The very top range will have all the partials culled.
|
|
124
124
|
int numberOfPartials =
|
|
@@ -41,6 +41,17 @@ std::shared_ptr<AudioParam> AudioBufferBaseSourceNode::getPlaybackRateParam()
|
|
|
41
41
|
return playbackRateParam_;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
void AudioBufferBaseSourceNode::clearOnPositionChangedCallback() {
|
|
45
|
+
if (onPositionChangedCallbackId_ == 0 || context_ == nullptr ||
|
|
46
|
+
context_->audioEventHandlerRegistry_ == nullptr) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
context_->audioEventHandlerRegistry_->unregisterHandler(
|
|
51
|
+
"positionChanged", onPositionChangedCallbackId_);
|
|
52
|
+
onPositionChangedCallbackId_ = 0;
|
|
53
|
+
}
|
|
54
|
+
|
|
44
55
|
void AudioBufferBaseSourceNode::setOnPositionChangedCallbackId(
|
|
45
56
|
uint64_t callbackId) {
|
|
46
57
|
onPositionChangedCallbackId_ = callbackId;
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
#include <audioapi/libs/signalsmith-stretch/signalsmith-stretch.h>
|
|
5
5
|
|
|
6
6
|
#include <memory>
|
|
7
|
+
#include <mutex>
|
|
8
|
+
#include <atomic>
|
|
7
9
|
|
|
8
10
|
namespace audioapi {
|
|
9
11
|
|
|
@@ -18,6 +20,7 @@ class AudioBufferBaseSourceNode : public AudioScheduledSourceNode {
|
|
|
18
20
|
[[nodiscard]] std::shared_ptr<AudioParam> getDetuneParam() const;
|
|
19
21
|
[[nodiscard]] std::shared_ptr<AudioParam> getPlaybackRateParam() const;
|
|
20
22
|
|
|
23
|
+
void clearOnPositionChangedCallback();
|
|
21
24
|
void setOnPositionChangedCallbackId(uint64_t callbackId);
|
|
22
25
|
void setOnPositionChangedInterval(int interval);
|
|
23
26
|
[[nodiscard]] int getOnPositionChangedInterval();
|
|
@@ -36,7 +39,7 @@ class AudioBufferBaseSourceNode : public AudioScheduledSourceNode {
|
|
|
36
39
|
// internal helper
|
|
37
40
|
double vReadIndex_;
|
|
38
41
|
|
|
39
|
-
uint64_t onPositionChangedCallbackId_ = 0; // 0 means no callback
|
|
42
|
+
std::atomic<uint64_t> onPositionChangedCallbackId_ = 0; // 0 means no callback
|
|
40
43
|
int onPositionChangedInterval_;
|
|
41
44
|
int onPositionChangedTime_ = 0;
|
|
42
45
|
|
|
@@ -54,6 +54,17 @@ bool AudioScheduledSourceNode::isStopScheduled() {
|
|
|
54
54
|
return playbackState_ == PlaybackState::STOP_SCHEDULED;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
void AudioScheduledSourceNode::clearOnEndedCallback() {
|
|
58
|
+
if (onEndedCallbackId_ == 0 || context_ == nullptr ||
|
|
59
|
+
context_->audioEventHandlerRegistry_ == nullptr) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
context_->audioEventHandlerRegistry_->unregisterHandler(
|
|
64
|
+
"ended", onEndedCallbackId_);
|
|
65
|
+
onEndedCallbackId_ = 0;
|
|
66
|
+
}
|
|
67
|
+
|
|
57
68
|
void AudioScheduledSourceNode::setOnEndedCallbackId(const uint64_t callbackId) {
|
|
58
69
|
onEndedCallbackId_ = callbackId;
|
|
59
70
|
}
|
|
@@ -38,6 +38,7 @@ class AudioScheduledSourceNode : public AudioNode {
|
|
|
38
38
|
bool isFinished();
|
|
39
39
|
bool isStopScheduled();
|
|
40
40
|
|
|
41
|
+
void clearOnEndedCallback();
|
|
41
42
|
void setOnEndedCallbackId(uint64_t callbackId);
|
|
42
43
|
|
|
43
44
|
void disable() override;
|
|
@@ -48,7 +49,7 @@ class AudioScheduledSourceNode : public AudioNode {
|
|
|
48
49
|
|
|
49
50
|
PlaybackState playbackState_;
|
|
50
51
|
|
|
51
|
-
uint64_t onEndedCallbackId_ = 0;
|
|
52
|
+
std::atomic<uint64_t> onEndedCallbackId_ = 0;
|
|
52
53
|
|
|
53
54
|
void updatePlaybackInfo(
|
|
54
55
|
const std::shared_ptr<AudioBus>& processingBus,
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
|
|
3
|
+
#include <audioapi/libs/audio-stretch/stretch.h>
|
|
3
4
|
#include <memory>
|
|
4
5
|
#include <string>
|
|
6
|
+
#include <vector>
|
|
5
7
|
|
|
6
8
|
namespace audioapi {
|
|
7
9
|
|
|
@@ -13,10 +15,45 @@ class AudioDecoder {
|
|
|
13
15
|
|
|
14
16
|
[[nodiscard]] std::shared_ptr<AudioBus> decodeWithFilePath(const std::string &path) const;
|
|
15
17
|
[[nodiscard]] std::shared_ptr<AudioBus> decodeWithMemoryBlock(const void *data, size_t size) const;
|
|
16
|
-
[[nodiscard]] std::shared_ptr<AudioBus> decodeWithPCMInBase64(const std::string &data) const;
|
|
18
|
+
[[nodiscard]] std::shared_ptr<AudioBus> decodeWithPCMInBase64(const std::string &data, float playbackSpeed) const;
|
|
17
19
|
|
|
18
20
|
private:
|
|
19
21
|
float sampleRate_;
|
|
22
|
+
int numChannels_ = 2;
|
|
23
|
+
|
|
24
|
+
void changePlaybackSpeedIfNeeded(std::vector<int16_t> &buffer, size_t framesDecoded, int numChannels, float playbackSpeed) const {
|
|
25
|
+
if (playbackSpeed == 1.0f) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
auto stretcher = stretch_init(static_cast<int>(sampleRate_ / 333.0f), static_cast<int>(sampleRate_ / 55.0f), numChannels, 0x1);
|
|
30
|
+
|
|
31
|
+
int maxOutputFrames = stretch_output_capacity(stretcher, static_cast<int>(framesDecoded), 1 / playbackSpeed);
|
|
32
|
+
std::vector<int16_t> stretchedBuffer(maxOutputFrames);
|
|
33
|
+
|
|
34
|
+
int outputFrames = stretch_samples(
|
|
35
|
+
stretcher,
|
|
36
|
+
buffer.data(),
|
|
37
|
+
static_cast<int>(framesDecoded),
|
|
38
|
+
stretchedBuffer.data(),
|
|
39
|
+
1 / playbackSpeed
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
outputFrames += stretch_flush(stretcher, stretchedBuffer.data() + (outputFrames));
|
|
43
|
+
stretchedBuffer.resize(outputFrames);
|
|
44
|
+
|
|
45
|
+
buffer = stretchedBuffer;
|
|
46
|
+
|
|
47
|
+
stretch_deinit(stretcher);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
[[nodiscard]] static inline int16_t floatToInt16(float sample) {
|
|
51
|
+
return static_cast<int16_t>(sample * 32768.0f);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
[[nodiscard]] static inline float int16ToFloat(int16_t sample) {
|
|
55
|
+
return static_cast<float>(sample) / 32768.0f;
|
|
56
|
+
}
|
|
20
57
|
};
|
|
21
58
|
|
|
22
59
|
} // namespace audioapi
|
|
@@ -20,8 +20,6 @@ class AudioNodeManager {
|
|
|
20
20
|
AudioNodeManager() = default;
|
|
21
21
|
~AudioNodeManager();
|
|
22
22
|
|
|
23
|
-
std::mutex &getGraphLock();
|
|
24
|
-
|
|
25
23
|
void preProcessGraph();
|
|
26
24
|
|
|
27
25
|
void addPendingNodeConnection(
|
|
@@ -62,6 +60,7 @@ class AudioNodeManager {
|
|
|
62
60
|
ConnectionType>>
|
|
63
61
|
audioParamToConnect_;
|
|
64
62
|
|
|
63
|
+
std::mutex &getGraphLock();
|
|
65
64
|
void settlePendingConnections();
|
|
66
65
|
void cleanupNode(const std::shared_ptr<AudioNode> &node);
|
|
67
66
|
void prepareNodesForDestruction();
|
|
@@ -4,7 +4,8 @@ namespace audioapi {
|
|
|
4
4
|
|
|
5
5
|
AudioEventHandlerRegistry::AudioEventHandlerRegistry(
|
|
6
6
|
jsi::Runtime *runtime,
|
|
7
|
-
const std::shared_ptr<react::CallInvoker> &callInvoker)
|
|
7
|
+
const std::shared_ptr<react::CallInvoker> &callInvoker)
|
|
8
|
+
: IAudioEventHandlerRegistry() {
|
|
8
9
|
runtime_ = runtime;
|
|
9
10
|
callInvoker_ = callInvoker;
|
|
10
11
|
|
|
@@ -91,8 +92,18 @@ void AudioEventHandlerRegistry::invokeHandlerWithEventBody(
|
|
|
91
92
|
continue;
|
|
92
93
|
}
|
|
93
94
|
|
|
94
|
-
|
|
95
|
-
|
|
95
|
+
try {
|
|
96
|
+
auto eventObject = createEventObject(body);
|
|
97
|
+
handler->call(*runtime_, eventObject);
|
|
98
|
+
} catch (const std::exception &e) {
|
|
99
|
+
// re-throw the exception to be handled by the caller
|
|
100
|
+
// std::exception is safe to parse by the rn bridge
|
|
101
|
+
throw;
|
|
102
|
+
} catch (...) {
|
|
103
|
+
printf(
|
|
104
|
+
"Unknown exception occurred while invoking handler for event: %s\n",
|
|
105
|
+
eventName.c_str());
|
|
106
|
+
}
|
|
96
107
|
}
|
|
97
108
|
});
|
|
98
109
|
}
|
|
@@ -122,8 +133,26 @@ void AudioEventHandlerRegistry::invokeHandlerWithEventBody(
|
|
|
122
133
|
return;
|
|
123
134
|
}
|
|
124
135
|
|
|
125
|
-
|
|
126
|
-
|
|
136
|
+
// Depending on how the AudioBufferSourceNode is handled on the JS side,
|
|
137
|
+
// it sometimes might enter race condition where the ABSN is deleted on JS
|
|
138
|
+
// side, but it is still processed on the audio thread, leading to a crash
|
|
139
|
+
// when f.e. `positionChanged` event is triggered.
|
|
140
|
+
|
|
141
|
+
// In case of debugging this, please increment the hours spent counter
|
|
142
|
+
|
|
143
|
+
// Hours spent on this: 5
|
|
144
|
+
try {
|
|
145
|
+
auto eventObject = createEventObject(body);
|
|
146
|
+
handlerIt->second->call(*runtime_, eventObject);
|
|
147
|
+
} catch (const std::exception &e) {
|
|
148
|
+
// re-throw the exception to be handled by the caller
|
|
149
|
+
// std::exception is safe to parse by the rn bridge
|
|
150
|
+
throw;
|
|
151
|
+
} catch (...) {
|
|
152
|
+
printf(
|
|
153
|
+
"Unknown exception occurred while invoking handler for event: %s\n",
|
|
154
|
+
eventName.c_str());
|
|
155
|
+
}
|
|
127
156
|
});
|
|
128
157
|
}
|
|
129
158
|
|
|
@@ -135,19 +164,20 @@ jsi::Object AudioEventHandlerRegistry::createEventObject(
|
|
|
135
164
|
const auto name = pair.first.data();
|
|
136
165
|
const auto &value = pair.second;
|
|
137
166
|
|
|
138
|
-
if (holds_alternative<int>(value)) {
|
|
139
|
-
eventObject.setProperty(*runtime_, name, get<int>(value));
|
|
140
|
-
} else if (holds_alternative<double>(value)) {
|
|
141
|
-
eventObject.setProperty(*runtime_, name, get<double>(value));
|
|
142
|
-
} else if (holds_alternative<float>(value)) {
|
|
143
|
-
eventObject.setProperty(*runtime_, name, get<float>(value));
|
|
144
|
-
} else if (holds_alternative<bool>(value)) {
|
|
145
|
-
eventObject.setProperty(*runtime_, name, get<bool>(value));
|
|
146
|
-
} else if (holds_alternative<std::string>(value)) {
|
|
147
|
-
eventObject.setProperty(*runtime_, name, get<std::string>(value));
|
|
148
|
-
} else if (holds_alternative<std::shared_ptr<jsi::HostObject>>(
|
|
167
|
+
if (std::holds_alternative<int>(value)) {
|
|
168
|
+
eventObject.setProperty(*runtime_, name, std::get<int>(value));
|
|
169
|
+
} else if (std::holds_alternative<double>(value)) {
|
|
170
|
+
eventObject.setProperty(*runtime_, name, std::get<double>(value));
|
|
171
|
+
} else if (std::holds_alternative<float>(value)) {
|
|
172
|
+
eventObject.setProperty(*runtime_, name, std::get<float>(value));
|
|
173
|
+
} else if (std::holds_alternative<bool>(value)) {
|
|
174
|
+
eventObject.setProperty(*runtime_, name, std::get<bool>(value));
|
|
175
|
+
} else if (std::holds_alternative<std::string>(value)) {
|
|
176
|
+
eventObject.setProperty(*runtime_, name, std::get<std::string>(value));
|
|
177
|
+
} else if (std::holds_alternative<std::shared_ptr<jsi::HostObject>>(
|
|
178
|
+
value)) {
|
|
149
179
|
auto hostObject = jsi::Object::createFromHostObject(
|
|
150
|
-
*runtime_, get<std::shared_ptr<jsi::HostObject>>(value));
|
|
180
|
+
*runtime_, std::get<std::shared_ptr<jsi::HostObject>>(value));
|
|
151
181
|
eventObject.setProperty(*runtime_, name, hostObject);
|
|
152
182
|
}
|
|
153
183
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
#include <jsi/jsi.h>
|
|
4
4
|
#include <ReactCommon/CallInvoker.h>
|
|
5
|
+
#include <audioapi/events/IAudioEventHandlerRegistry.h>
|
|
5
6
|
#include <memory>
|
|
6
7
|
#include <unordered_map>
|
|
7
8
|
#include <array>
|
|
@@ -14,18 +15,18 @@ using namespace facebook;
|
|
|
14
15
|
|
|
15
16
|
using EventValue = std::variant<int, float, double, std::string, bool, std::shared_ptr<jsi::HostObject>>;
|
|
16
17
|
|
|
17
|
-
class AudioEventHandlerRegistry {
|
|
18
|
+
class AudioEventHandlerRegistry : public IAudioEventHandlerRegistry {
|
|
18
19
|
public:
|
|
19
20
|
explicit AudioEventHandlerRegistry(
|
|
20
21
|
jsi::Runtime *runtime,
|
|
21
22
|
const std::shared_ptr<react::CallInvoker> &callInvoker);
|
|
22
23
|
~AudioEventHandlerRegistry();
|
|
23
24
|
|
|
24
|
-
uint64_t registerHandler(const std::string &eventName, const std::shared_ptr<jsi::Function> &handler);
|
|
25
|
-
void unregisterHandler(const std::string &eventName, uint64_t listenerId);
|
|
25
|
+
uint64_t registerHandler(const std::string &eventName, const std::shared_ptr<jsi::Function> &handler) override;
|
|
26
|
+
void unregisterHandler(const std::string &eventName, uint64_t listenerId) override;
|
|
26
27
|
|
|
27
|
-
void invokeHandlerWithEventBody(const std::string &eventName, const std::unordered_map<std::string, EventValue> &body);
|
|
28
|
-
void invokeHandlerWithEventBody(const std::string &eventName, uint64_t listenerId, const std::unordered_map<std::string, EventValue> &body);
|
|
28
|
+
void invokeHandlerWithEventBody(const std::string &eventName, const std::unordered_map<std::string, EventValue> &body) override;
|
|
29
|
+
void invokeHandlerWithEventBody(const std::string &eventName, uint64_t listenerId, const std::unordered_map<std::string, EventValue> &body) override;
|
|
29
30
|
|
|
30
31
|
private:
|
|
31
32
|
std::atomic<uint64_t> listenerIdCounter_{1}; // Atomic counter for listener IDs
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <jsi/jsi.h>
|
|
4
|
+
#include <ReactCommon/CallInvoker.h>
|
|
5
|
+
#include <unordered_map>
|
|
6
|
+
#include <variant>
|
|
7
|
+
#include <string>
|
|
8
|
+
#include <memory>
|
|
9
|
+
|
|
10
|
+
namespace audioapi {
|
|
11
|
+
|
|
12
|
+
using EventValue = std::variant<int, float, double, std::string, bool, std::shared_ptr<facebook::jsi::HostObject>>;
|
|
13
|
+
|
|
14
|
+
class IAudioEventHandlerRegistry {
|
|
15
|
+
public:
|
|
16
|
+
virtual ~IAudioEventHandlerRegistry() = default;
|
|
17
|
+
|
|
18
|
+
virtual uint64_t registerHandler(const std::string &eventName, const std::shared_ptr<facebook::jsi::Function> &handler) = 0;
|
|
19
|
+
virtual void unregisterHandler(const std::string &eventName, uint64_t listenerId) = 0;
|
|
20
|
+
|
|
21
|
+
virtual void invokeHandlerWithEventBody(const std::string &eventName, const std::unordered_map<std::string, EventValue> &body) = 0;
|
|
22
|
+
virtual void invokeHandlerWithEventBody(const std::string &eventName, uint64_t listenerId, const std::unordered_map<std::string, EventValue> &body) = 0;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
} // namespace audioapi
|