react-native-audio-api 0.7.1-nightly-968a0e5-20250812 → 0.7.1-nightly-b6583fe-20250813
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/HostObjects/AudioBufferHostObject.h +35 -12
- package/common/cpp/audioapi/jsi/JsiHostObject.cpp +35 -7
- package/common/cpp/audioapi/jsi/JsiHostObject.h +8 -4
- package/ios/audioapi/ios/core/NativeAudioPlayer.m +9 -1
- package/ios/audioapi/ios/core/NativeAudioRecorder.m +10 -1
- package/package.json +1 -1
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
|
|
3
|
-
#include <audioapi/jsi/JsiHostObject.h>
|
|
4
|
-
#include <audioapi/jsi/AudioArrayBuffer.h>
|
|
5
3
|
#include <audioapi/core/sources/AudioBuffer.h>
|
|
4
|
+
#include <audioapi/jsi/AudioArrayBuffer.h>
|
|
5
|
+
#include <audioapi/jsi/JsiHostObject.h>
|
|
6
6
|
|
|
7
7
|
#include <jsi/jsi.h>
|
|
8
|
+
#include <cstddef>
|
|
8
9
|
#include <memory>
|
|
10
|
+
#include <utility>
|
|
9
11
|
#include <vector>
|
|
10
|
-
#include <cstddef>
|
|
11
12
|
|
|
12
13
|
namespace audioapi {
|
|
13
14
|
using namespace facebook;
|
|
@@ -30,9 +31,22 @@ class AudioBufferHostObject : public JsiHostObject {
|
|
|
30
31
|
JSI_EXPORT_FUNCTION(AudioBufferHostObject, copyFromChannel),
|
|
31
32
|
JSI_EXPORT_FUNCTION(AudioBufferHostObject, copyToChannel));
|
|
32
33
|
}
|
|
34
|
+
AudioBufferHostObject(const AudioBufferHostObject &) = delete;
|
|
35
|
+
AudioBufferHostObject &operator=(const AudioBufferHostObject &) = delete;
|
|
36
|
+
AudioBufferHostObject(AudioBufferHostObject &&other) noexcept
|
|
37
|
+
: JsiHostObject(std::move(other)),
|
|
38
|
+
audioBuffer_(std::move(other.audioBuffer_)) {}
|
|
39
|
+
AudioBufferHostObject &operator=(AudioBufferHostObject &&other) noexcept {
|
|
40
|
+
if (this != &other) {
|
|
41
|
+
JsiHostObject::operator=(std::move(other));
|
|
42
|
+
audioBuffer_ = std::move(other.audioBuffer_);
|
|
43
|
+
}
|
|
44
|
+
return *this;
|
|
45
|
+
}
|
|
33
46
|
|
|
34
47
|
[[nodiscard]] size_t getSizeInBytes() const {
|
|
35
|
-
return audioBuffer_->getLength() * audioBuffer_->getNumberOfChannels() *
|
|
48
|
+
return audioBuffer_->getLength() * audioBuffer_->getNumberOfChannels() *
|
|
49
|
+
sizeof(float);
|
|
36
50
|
}
|
|
37
51
|
|
|
38
52
|
JSI_PROPERTY_GETTER(sampleRate) {
|
|
@@ -53,23 +67,30 @@ class AudioBufferHostObject : public JsiHostObject {
|
|
|
53
67
|
|
|
54
68
|
JSI_HOST_FUNCTION(getChannelData) {
|
|
55
69
|
auto channel = static_cast<int>(args[0].getNumber());
|
|
56
|
-
auto channelData =
|
|
70
|
+
auto channelData =
|
|
71
|
+
reinterpret_cast<uint8_t *>(audioBuffer_->getChannelData(channel));
|
|
57
72
|
auto length = static_cast<int>(audioBuffer_->getLength());
|
|
58
73
|
auto size = static_cast<int>(length * sizeof(float));
|
|
59
74
|
|
|
60
75
|
// reading or writing from this ArrayBuffer could cause a crash
|
|
61
76
|
// if underlying channelData is deallocated
|
|
62
|
-
auto audioArrayBuffer =
|
|
77
|
+
auto audioArrayBuffer =
|
|
78
|
+
std::make_shared<AudioArrayBuffer>(channelData, size);
|
|
63
79
|
auto arrayBuffer = jsi::ArrayBuffer(runtime, audioArrayBuffer);
|
|
64
80
|
|
|
65
|
-
auto float32ArrayCtor =
|
|
66
|
-
|
|
81
|
+
auto float32ArrayCtor =
|
|
82
|
+
runtime.global().getPropertyAsFunction(runtime, "Float32Array");
|
|
83
|
+
auto float32Array = float32ArrayCtor.callAsConstructor(runtime, arrayBuffer)
|
|
84
|
+
.getObject(runtime);
|
|
67
85
|
|
|
68
86
|
return float32Array;
|
|
69
87
|
}
|
|
70
88
|
|
|
71
89
|
JSI_HOST_FUNCTION(copyFromChannel) {
|
|
72
|
-
auto arrayBuffer = args[0]
|
|
90
|
+
auto arrayBuffer = args[0]
|
|
91
|
+
.getObject(runtime)
|
|
92
|
+
.getPropertyAsObject(runtime, "buffer")
|
|
93
|
+
.getArrayBuffer(runtime);
|
|
73
94
|
auto destination = reinterpret_cast<float *>(arrayBuffer.data(runtime));
|
|
74
95
|
auto length = static_cast<int>(arrayBuffer.size(runtime));
|
|
75
96
|
auto channelNumber = static_cast<int>(args[1].getNumber());
|
|
@@ -82,14 +103,16 @@ class AudioBufferHostObject : public JsiHostObject {
|
|
|
82
103
|
}
|
|
83
104
|
|
|
84
105
|
JSI_HOST_FUNCTION(copyToChannel) {
|
|
85
|
-
auto arrayBuffer = args[0]
|
|
106
|
+
auto arrayBuffer = args[0]
|
|
107
|
+
.getObject(runtime)
|
|
108
|
+
.getPropertyAsObject(runtime, "buffer")
|
|
109
|
+
.getArrayBuffer(runtime);
|
|
86
110
|
auto source = reinterpret_cast<float *>(arrayBuffer.data(runtime));
|
|
87
111
|
auto length = static_cast<int>(arrayBuffer.size(runtime));
|
|
88
112
|
auto channelNumber = static_cast<int>(args[1].getNumber());
|
|
89
113
|
auto startInChannel = static_cast<size_t>(args[2].getNumber());
|
|
90
114
|
|
|
91
|
-
audioBuffer_->copyToChannel(
|
|
92
|
-
source, length, channelNumber, startInChannel);
|
|
115
|
+
audioBuffer_->copyToChannel(source, length, channelNumber, startInChannel);
|
|
93
116
|
|
|
94
117
|
return jsi::Value::undefined();
|
|
95
118
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#include <audioapi/jsi/JsiHostObject.h>
|
|
2
2
|
|
|
3
3
|
// set this value to 1 in order to debug the construction/destruction
|
|
4
|
-
#define JSI_DEBUG_ALLOCATIONS
|
|
4
|
+
#define JSI_DEBUG_ALLOCATIONS 0
|
|
5
5
|
|
|
6
6
|
namespace audioapi {
|
|
7
7
|
|
|
@@ -28,15 +28,43 @@ JsiHostObject::JsiHostObject() {
|
|
|
28
28
|
#endif
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
JsiHostObject
|
|
31
|
+
JsiHostObject::JsiHostObject(JsiHostObject &&other) noexcept
|
|
32
|
+
: getters_(std::move(other.getters_)),
|
|
33
|
+
functions_(std::move(other.functions_)),
|
|
34
|
+
setters_(std::move(other.setters_)) {
|
|
35
|
+
#if JSI_DEBUG_ALLOCATIONS
|
|
36
|
+
auto it = std::find(objects.begin(), objects.end(), &other);
|
|
37
|
+
if (it != objects.end()) {
|
|
38
|
+
objects.erase(it);
|
|
39
|
+
}
|
|
40
|
+
objects.push_back(this);
|
|
41
|
+
#endif
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
JsiHostObject &JsiHostObject::operator=(JsiHostObject &&other) noexcept {
|
|
45
|
+
if (this != &other) {
|
|
46
|
+
getters_ = std::move(other.getters_);
|
|
47
|
+
functions_ = std::move(other.functions_);
|
|
48
|
+
setters_ = std::move(other.setters_);
|
|
49
|
+
|
|
32
50
|
#if JSI_DEBUG_ALLOCATIONS
|
|
33
|
-
|
|
34
|
-
if (objects.
|
|
35
|
-
objects.erase(
|
|
36
|
-
break;
|
|
51
|
+
auto it = std::find(objects.begin(), objects.end(), &other);
|
|
52
|
+
if (it != objects.end()) {
|
|
53
|
+
objects.erase(it);
|
|
37
54
|
}
|
|
55
|
+
objects.push_back(this);
|
|
56
|
+
#endif
|
|
57
|
+
}
|
|
58
|
+
return *this;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
JsiHostObject::~JsiHostObject() {
|
|
62
|
+
#if JSI_DEBUG_ALLOCATIONS
|
|
63
|
+
auto it = std::find(objects.begin(), objects.end(), this);
|
|
64
|
+
if (it != objects.end()) {
|
|
65
|
+
objects.erase(it);
|
|
66
|
+
objCounter--;
|
|
38
67
|
}
|
|
39
|
-
objCounter--;
|
|
40
68
|
#endif
|
|
41
69
|
}
|
|
42
70
|
|
|
@@ -10,11 +10,11 @@
|
|
|
10
10
|
#include <utility>
|
|
11
11
|
#include <vector>
|
|
12
12
|
|
|
13
|
-
#define JSI_HOST_FUNCTION(NAME)
|
|
14
|
-
jsi::Value NAME(
|
|
15
|
-
jsi::Runtime &runtime,
|
|
13
|
+
#define JSI_HOST_FUNCTION(NAME) \
|
|
14
|
+
jsi::Value NAME( \
|
|
15
|
+
jsi::Runtime &runtime, \
|
|
16
16
|
const jsi::Value &thisValue, \
|
|
17
|
-
const jsi::Value *args,
|
|
17
|
+
const jsi::Value *args, \
|
|
18
18
|
size_t count)
|
|
19
19
|
|
|
20
20
|
#define JSI_EXPORT_FUNCTION(CLASS, FUNCTION) \
|
|
@@ -48,6 +48,10 @@ using namespace facebook;
|
|
|
48
48
|
class JsiHostObject : public jsi::HostObject {
|
|
49
49
|
public:
|
|
50
50
|
JsiHostObject();
|
|
51
|
+
JsiHostObject(const JsiHostObject &) = delete;
|
|
52
|
+
JsiHostObject &operator=(const JsiHostObject &) = delete;
|
|
53
|
+
JsiHostObject(JsiHostObject &&) noexcept;
|
|
54
|
+
JsiHostObject &operator=(JsiHostObject &&other) noexcept;
|
|
51
55
|
~JsiHostObject() override;
|
|
52
56
|
|
|
53
57
|
std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime &rt) override;
|
|
@@ -40,7 +40,14 @@
|
|
|
40
40
|
assert(audioEngine != nil);
|
|
41
41
|
self.sourceNodeId = [audioEngine attachSourceNode:self.sourceNode format:self.format];
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
// AudioEngine allows us to attach and connect nodes at runtime but with few limitations
|
|
44
|
+
// in this case if it is the first player and recorder started the engine we need to restart.
|
|
45
|
+
// It can be optimized by tracking if we haven't break rules of at runtime modifications from docs
|
|
46
|
+
// https://developer.apple.com/documentation/avfaudio/avaudioengine?language=objc
|
|
47
|
+
//
|
|
48
|
+
// Currently we are restarting because we do not see any significant performance issue and case when
|
|
49
|
+
// you will need to start and stop player very frequently
|
|
50
|
+
return [audioEngine restartAudioEngine];
|
|
44
51
|
}
|
|
45
52
|
|
|
46
53
|
- (void)stop
|
|
@@ -50,6 +57,7 @@
|
|
|
50
57
|
AudioEngine *audioEngine = [AudioEngine sharedInstance];
|
|
51
58
|
assert(audioEngine != nil);
|
|
52
59
|
[audioEngine detachSourceNodeWithId:self.sourceNodeId];
|
|
60
|
+
[audioEngine restartAudioEngine];
|
|
53
61
|
[audioEngine stopIfNecessary];
|
|
54
62
|
self.sourceNodeId = nil;
|
|
55
63
|
}
|
|
@@ -101,7 +101,15 @@
|
|
|
101
101
|
AudioEngine *audioEngine = [AudioEngine sharedInstance];
|
|
102
102
|
assert(audioEngine != nil);
|
|
103
103
|
[audioEngine attachInputNode:self.sinkNode];
|
|
104
|
-
|
|
104
|
+
|
|
105
|
+
// AudioEngine allows us to attach and connect nodes at runtime but with few limitations
|
|
106
|
+
// in this case if it is the first recorder node and player started the engine we need to restart.
|
|
107
|
+
// It can be optimized by tracking if we haven't break rules of at runtime modifications from docs
|
|
108
|
+
// https://developer.apple.com/documentation/avfaudio/avaudioengine?language=objc
|
|
109
|
+
//
|
|
110
|
+
// Currently we are restarting because we do not see any significant performance issue and case when
|
|
111
|
+
// you will need to start and stop recorder very frequently
|
|
112
|
+
[audioEngine restartAudioEngine];
|
|
105
113
|
}
|
|
106
114
|
|
|
107
115
|
- (void)stop
|
|
@@ -109,6 +117,7 @@
|
|
|
109
117
|
AudioEngine *audioEngine = [AudioEngine sharedInstance];
|
|
110
118
|
assert(audioEngine != nil);
|
|
111
119
|
[audioEngine detachInputNode];
|
|
120
|
+
[audioEngine restartAudioEngine];
|
|
112
121
|
[audioEngine stopIfNecessary];
|
|
113
122
|
}
|
|
114
123
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-audio-api",
|
|
3
|
-
"version": "0.7.1-nightly-
|
|
3
|
+
"version": "0.7.1-nightly-b6583fe-20250813",
|
|
4
4
|
"description": "react-native-audio-api provides system for controlling audio in React Native environment compatible with Web Audio API specification",
|
|
5
5
|
"bin": {
|
|
6
6
|
"setup-rn-audio-api-web": "./scripts/setup-rn-audio-api-web.js"
|