react-native-audio-api 0.9.0 → 0.10.0-nightly-971a6b4-20251010
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/src/main/cpp/audioapi/android/core/{AudioDecoder.cpp → utils/AudioDecoder.cpp} +79 -75
- package/common/cpp/audioapi/AudioAPIModuleInstaller.h +124 -43
- package/common/cpp/audioapi/HostObjects/BaseAudioContextHostObject.cpp +1 -101
- package/common/cpp/audioapi/HostObjects/BaseAudioContextHostObject.h +0 -3
- package/common/cpp/audioapi/HostObjects/utils/AudioDecoderHostObject.cpp +133 -0
- package/common/cpp/audioapi/HostObjects/utils/AudioDecoderHostObject.h +28 -0
- package/common/cpp/audioapi/HostObjects/utils/AudioStretcherHostObject.cpp +58 -0
- package/common/cpp/audioapi/HostObjects/utils/AudioStretcherHostObject.h +26 -0
- package/common/cpp/audioapi/core/AudioContext.cpp +0 -2
- package/common/cpp/audioapi/core/BaseAudioContext.cpp +0 -35
- package/common/cpp/audioapi/core/BaseAudioContext.h +4 -12
- package/common/cpp/audioapi/core/OfflineAudioContext.cpp +0 -2
- package/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.cpp +0 -4
- package/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.h +0 -1
- package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp +0 -2
- package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.cpp +0 -4
- package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.h +0 -1
- package/common/cpp/audioapi/core/types/AudioFormat.h +16 -0
- package/common/cpp/audioapi/core/utils/AudioDecoder.h +36 -91
- package/common/cpp/audioapi/core/utils/AudioStretcher.cpp +75 -0
- package/common/cpp/audioapi/core/utils/AudioStretcher.h +30 -0
- package/common/cpp/audioapi/core/utils/Constants.h +4 -0
- package/common/cpp/audioapi/events/AudioEventHandlerRegistry.cpp +5 -1
- package/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.cpp +241 -282
- package/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.h +57 -19
- package/common/cpp/test/CMakeLists.txt +1 -1
- package/ios/audioapi/ios/core/utils/AudioDecoder.mm +160 -0
- package/lib/commonjs/api.js +21 -1
- package/lib/commonjs/api.js.map +1 -1
- package/lib/commonjs/core/AudioDecoder.js +48 -0
- package/lib/commonjs/core/AudioDecoder.js.map +1 -0
- package/lib/commonjs/core/AudioStretcher.js +31 -0
- package/lib/commonjs/core/AudioStretcher.js.map +1 -0
- package/lib/commonjs/core/BaseAudioContext.js +11 -18
- package/lib/commonjs/core/BaseAudioContext.js.map +1 -1
- package/lib/module/api.js +3 -1
- package/lib/module/api.js.map +1 -1
- package/lib/module/core/AudioDecoder.js +42 -0
- package/lib/module/core/AudioDecoder.js.map +1 -0
- package/lib/module/core/AudioStretcher.js +26 -0
- package/lib/module/core/AudioStretcher.js.map +1 -0
- package/lib/module/core/BaseAudioContext.js +11 -18
- package/lib/module/core/BaseAudioContext.js.map +1 -1
- package/lib/typescript/api.d.ts +5 -1
- package/lib/typescript/api.d.ts.map +1 -1
- package/lib/typescript/core/AudioDecoder.d.ts +4 -0
- package/lib/typescript/core/AudioDecoder.d.ts.map +1 -0
- package/lib/typescript/core/AudioStretcher.d.ts +3 -0
- package/lib/typescript/core/AudioStretcher.d.ts.map +1 -0
- package/lib/typescript/core/BaseAudioContext.d.ts +3 -6
- package/lib/typescript/core/BaseAudioContext.d.ts.map +1 -1
- package/lib/typescript/interfaces.d.ts +10 -3
- package/lib/typescript/interfaces.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/api.ts +10 -0
- package/src/core/AudioDecoder.ts +78 -0
- package/src/core/AudioStretcher.ts +43 -0
- package/src/core/BaseAudioContext.ts +26 -29
- package/src/interfaces.ts +26 -6
- package/ios/audioapi/ios/core/AudioDecoder.mm +0 -156
package/android/src/main/cpp/audioapi/android/core/{AudioDecoder.cpp → utils/AudioDecoder.cpp}
RENAMED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
#include <audioapi/core/sources/AudioBuffer.h>
|
|
1
2
|
#include <audioapi/core/utils/AudioDecoder.h>
|
|
2
3
|
#include <audioapi/dsp/VectorMath.h>
|
|
3
4
|
#include <audioapi/libs/base64/base64.h>
|
|
@@ -5,28 +6,28 @@
|
|
|
5
6
|
#include <audioapi/utils/AudioBus.h>
|
|
6
7
|
|
|
7
8
|
#define MINIAUDIO_IMPLEMENTATION
|
|
9
|
+
#include <audioapi/libs/miniaudio/decoders/libopus/miniaudio_libopus.h>
|
|
10
|
+
#include <audioapi/libs/miniaudio/decoders/libvorbis/miniaudio_libvorbis.h>
|
|
8
11
|
#include <audioapi/libs/miniaudio/miniaudio.h>
|
|
9
12
|
|
|
10
13
|
#ifndef AUDIO_API_TEST_SUITE
|
|
11
14
|
#include <android/log.h>
|
|
12
15
|
#include <audioapi/libs/ffmpeg/FFmpegDecoding.h>
|
|
13
16
|
#endif
|
|
14
|
-
#include <audioapi/libs/miniaudio/decoders/libopus/miniaudio_libopus.h>
|
|
15
|
-
#include <audioapi/libs/miniaudio/decoders/libvorbis/miniaudio_libvorbis.h>
|
|
16
17
|
|
|
17
18
|
namespace audioapi {
|
|
18
19
|
|
|
19
20
|
// Decoding audio in fixed-size chunks because total frame count can't be
|
|
20
21
|
// determined in advance. Note: ma_decoder_get_length_in_pcm_frames() always
|
|
21
22
|
// returns 0 for Vorbis decoders.
|
|
22
|
-
std::vector<
|
|
23
|
+
std::vector<float> AudioDecoder::readAllPcmFrames(
|
|
23
24
|
ma_decoder &decoder,
|
|
24
|
-
int
|
|
25
|
-
|
|
26
|
-
std::vector<
|
|
27
|
-
|
|
28
|
-
outFramesRead = 0;
|
|
25
|
+
int outputChannels) {
|
|
26
|
+
std::vector<float> buffer;
|
|
27
|
+
std::vector<float> temp(CHUNK_SIZE * outputChannels);
|
|
28
|
+
ma_uint64 outFramesRead = 0;
|
|
29
29
|
|
|
30
|
+
#ifndef AUDIO_API_TEST_SUITE
|
|
30
31
|
while (true) {
|
|
31
32
|
ma_uint64 tempFramesDecoded = 0;
|
|
32
33
|
ma_decoder_read_pcm_frames(
|
|
@@ -38,38 +39,46 @@ std::vector<int16_t> AudioDecoder::readAllPcmFrames(
|
|
|
38
39
|
buffer.insert(
|
|
39
40
|
buffer.end(),
|
|
40
41
|
temp.data(),
|
|
41
|
-
temp.data() + tempFramesDecoded *
|
|
42
|
+
temp.data() + tempFramesDecoded * outputChannels);
|
|
42
43
|
outFramesRead += tempFramesDecoded;
|
|
43
44
|
}
|
|
44
45
|
|
|
46
|
+
if (outFramesRead == 0) {
|
|
47
|
+
__android_log_print(ANDROID_LOG_ERROR, "AudioDecoder", "Failed to decode");
|
|
48
|
+
}
|
|
49
|
+
#endif
|
|
45
50
|
return buffer;
|
|
46
51
|
}
|
|
47
52
|
|
|
48
|
-
std::shared_ptr<
|
|
49
|
-
const std::vector<
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
53
|
+
std::shared_ptr<AudioBuffer> AudioDecoder::makeAudioBufferFromFloatBuffer(
|
|
54
|
+
const std::vector<float> &buffer,
|
|
55
|
+
float outputSampleRate,
|
|
56
|
+
int outputChannels) {
|
|
57
|
+
if (buffer.empty()) {
|
|
58
|
+
return nullptr;
|
|
59
|
+
}
|
|
55
60
|
|
|
56
|
-
|
|
61
|
+
auto outputFrames = buffer.size() / outputChannels;
|
|
62
|
+
auto audioBus = std::make_shared<AudioBus>(
|
|
63
|
+
outputFrames, outputChannels, outputSampleRate);
|
|
64
|
+
|
|
65
|
+
for (int ch = 0; ch < outputChannels; ++ch) {
|
|
57
66
|
auto channelData = audioBus->getChannel(ch)->getData();
|
|
58
67
|
for (int i = 0; i < outputFrames; ++i) {
|
|
59
|
-
channelData[i] =
|
|
68
|
+
channelData[i] = buffer[i * outputChannels + ch];
|
|
60
69
|
}
|
|
61
70
|
}
|
|
62
|
-
return audioBus;
|
|
71
|
+
return std::make_shared<AudioBuffer>(audioBus);
|
|
63
72
|
}
|
|
64
73
|
|
|
65
|
-
std::shared_ptr<
|
|
66
|
-
const std::string &path
|
|
74
|
+
std::shared_ptr<AudioBuffer> AudioDecoder::decodeWithFilePath(
|
|
75
|
+
const std::string &path,
|
|
76
|
+
float sampleRate) {
|
|
67
77
|
#ifndef AUDIO_API_TEST_SUITE
|
|
68
|
-
std::vector<int16_t> buffer;
|
|
69
78
|
if (AudioDecoder::pathHasExtension(path, {".mp4", ".m4a", ".aac"})) {
|
|
70
|
-
buffer =
|
|
71
|
-
path,
|
|
72
|
-
if (buffer
|
|
79
|
+
auto buffer =
|
|
80
|
+
ffmpegdecoder::decodeWithFilePath(path, static_cast<int>(sampleRate));
|
|
81
|
+
if (buffer == nullptr) {
|
|
73
82
|
__android_log_print(
|
|
74
83
|
ANDROID_LOG_ERROR,
|
|
75
84
|
"AudioDecoder",
|
|
@@ -77,11 +86,11 @@ std::shared_ptr<AudioBus> AudioDecoder::decodeWithFilePath(
|
|
|
77
86
|
path.c_str());
|
|
78
87
|
return nullptr;
|
|
79
88
|
}
|
|
80
|
-
return
|
|
89
|
+
return buffer;
|
|
81
90
|
}
|
|
82
91
|
ma_decoder decoder;
|
|
83
|
-
ma_decoder_config config =
|
|
84
|
-
|
|
92
|
+
ma_decoder_config config =
|
|
93
|
+
ma_decoder_config_init(ma_format_f32, 0, static_cast<int>(sampleRate));
|
|
85
94
|
ma_decoding_backend_vtable *customBackends[] = {
|
|
86
95
|
ma_decoding_backend_libvorbis, ma_decoding_backend_libopus};
|
|
87
96
|
|
|
@@ -99,41 +108,38 @@ std::shared_ptr<AudioBus> AudioDecoder::decodeWithFilePath(
|
|
|
99
108
|
return nullptr;
|
|
100
109
|
}
|
|
101
110
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
if (framesRead == 0) {
|
|
105
|
-
__android_log_print(ANDROID_LOG_ERROR, "AudioDecoder", "Failed to decode");
|
|
106
|
-
ma_decoder_uninit(&decoder);
|
|
107
|
-
return nullptr;
|
|
108
|
-
}
|
|
111
|
+
auto outputSampleRate = static_cast<float>(decoder.outputSampleRate);
|
|
112
|
+
auto outputChannels = static_cast<int>(decoder.outputChannels);
|
|
109
113
|
|
|
114
|
+
std::vector<float> buffer = readAllPcmFrames(decoder, outputChannels);
|
|
110
115
|
ma_decoder_uninit(&decoder);
|
|
111
|
-
return
|
|
116
|
+
return makeAudioBufferFromFloatBuffer(
|
|
117
|
+
buffer, outputSampleRate, outputChannels);
|
|
112
118
|
#else
|
|
113
119
|
return nullptr;
|
|
114
120
|
#endif
|
|
115
121
|
}
|
|
116
122
|
|
|
117
|
-
std::shared_ptr<
|
|
123
|
+
std::shared_ptr<AudioBuffer> AudioDecoder::decodeWithMemoryBlock(
|
|
118
124
|
const void *data,
|
|
119
|
-
size_t size
|
|
125
|
+
size_t size,
|
|
126
|
+
float sampleRate) {
|
|
120
127
|
#ifndef AUDIO_API_TEST_SUITE
|
|
121
|
-
std::vector<int16_t> buffer;
|
|
122
128
|
const AudioFormat format = AudioDecoder::detectAudioFormat(data, size);
|
|
123
129
|
if (format == AudioFormat::MP4 || format == AudioFormat::M4A ||
|
|
124
130
|
format == AudioFormat::AAC) {
|
|
125
|
-
buffer =
|
|
126
|
-
data, size,
|
|
127
|
-
if (buffer
|
|
131
|
+
auto buffer = ffmpegdecoder::decodeWithMemoryBlock(
|
|
132
|
+
data, size, static_cast<int>(sampleRate));
|
|
133
|
+
if (buffer == nullptr) {
|
|
128
134
|
__android_log_print(
|
|
129
135
|
ANDROID_LOG_ERROR, "AudioDecoder", "Failed to decode with FFmpeg");
|
|
130
136
|
return nullptr;
|
|
131
137
|
}
|
|
132
|
-
return
|
|
138
|
+
return buffer;
|
|
133
139
|
}
|
|
134
140
|
ma_decoder decoder;
|
|
135
|
-
ma_decoder_config config =
|
|
136
|
-
|
|
141
|
+
ma_decoder_config config =
|
|
142
|
+
ma_decoder_config_init(ma_format_f32, 0, static_cast<int>(sampleRate));
|
|
137
143
|
|
|
138
144
|
ma_decoding_backend_vtable *customBackends[] = {
|
|
139
145
|
ma_decoding_backend_libvorbis, ma_decoding_backend_libopus};
|
|
@@ -151,50 +157,48 @@ std::shared_ptr<AudioBus> AudioDecoder::decodeWithMemoryBlock(
|
|
|
151
157
|
return nullptr;
|
|
152
158
|
}
|
|
153
159
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
if (framesRead == 0) {
|
|
157
|
-
__android_log_print(ANDROID_LOG_ERROR, "AudioDecoder", "Failed to decode");
|
|
158
|
-
ma_decoder_uninit(&decoder);
|
|
159
|
-
return nullptr;
|
|
160
|
-
}
|
|
160
|
+
auto outputSampleRate = static_cast<float>(decoder.outputSampleRate);
|
|
161
|
+
auto outputChannels = static_cast<int>(decoder.outputChannels);
|
|
161
162
|
|
|
163
|
+
std::vector<float> buffer = readAllPcmFrames(decoder, outputChannels);
|
|
162
164
|
ma_decoder_uninit(&decoder);
|
|
163
|
-
return
|
|
165
|
+
return makeAudioBufferFromFloatBuffer(
|
|
166
|
+
buffer, outputSampleRate, outputChannels);
|
|
164
167
|
#else
|
|
165
168
|
return nullptr;
|
|
166
169
|
#endif
|
|
167
170
|
}
|
|
168
171
|
|
|
169
|
-
std::shared_ptr<
|
|
172
|
+
std::shared_ptr<AudioBuffer> AudioDecoder::decodeWithPCMInBase64(
|
|
170
173
|
const std::string &data,
|
|
171
|
-
float
|
|
174
|
+
float inputSampleRate,
|
|
175
|
+
int inputChannelCount,
|
|
176
|
+
bool interleaved) {
|
|
172
177
|
auto decodedData = base64_decode(data, false);
|
|
173
|
-
|
|
174
178
|
const auto uint8Data = reinterpret_cast<uint8_t *>(decodedData.data());
|
|
175
|
-
size_t
|
|
176
|
-
|
|
177
|
-
std::vector<int16_t> buffer(framesDecoded);
|
|
178
|
-
for (size_t i = 0; i < framesDecoded; ++i) {
|
|
179
|
-
buffer[i] =
|
|
180
|
-
static_cast<int16_t>((uint8Data[i * 2 + 1] << 8) | uint8Data[i * 2]);
|
|
181
|
-
}
|
|
179
|
+
size_t numFramesDecoded =
|
|
180
|
+
decodedData.size() / (inputChannelCount * sizeof(int16_t));
|
|
182
181
|
|
|
183
|
-
|
|
184
|
-
|
|
182
|
+
auto audioBus = std::make_shared<AudioBus>(
|
|
183
|
+
numFramesDecoded, inputChannelCount, inputSampleRate);
|
|
185
184
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
auto leftChannelData = audioBus->getChannel(0)->getData();
|
|
189
|
-
auto rightChannelData = audioBus->getChannel(1)->getData();
|
|
185
|
+
for (int ch = 0; ch < inputChannelCount; ++ch) {
|
|
186
|
+
auto channelData = audioBus->getChannel(ch)->getData();
|
|
190
187
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
188
|
+
for (size_t i = 0; i < numFramesDecoded; ++i) {
|
|
189
|
+
size_t offset;
|
|
190
|
+
if (interleaved) {
|
|
191
|
+
// Ch1, Ch2, Ch1, Ch2, ...
|
|
192
|
+
offset = (i * inputChannelCount + ch) * sizeof(int16_t);
|
|
193
|
+
} else {
|
|
194
|
+
// Ch1, Ch1, Ch1, ..., Ch2, Ch2, Ch2, ...
|
|
195
|
+
offset = (ch * numFramesDecoded + i) * sizeof(int16_t);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
channelData[i] = uint8ToFloat(uint8Data[offset], uint8Data[offset + 1]);
|
|
199
|
+
}
|
|
195
200
|
}
|
|
196
|
-
|
|
197
|
-
return audioBus;
|
|
201
|
+
return std::make_shared<AudioBuffer>(audioBus);
|
|
198
202
|
}
|
|
199
203
|
|
|
200
204
|
} // namespace audioapi
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
|
|
3
|
-
#include <audioapi/jsi/JsiPromise.h>
|
|
4
|
-
#include <audioapi/core/AudioContext.h>
|
|
5
|
-
#include <audioapi/core/OfflineAudioContext.h>
|
|
6
|
-
#include <audioapi/core/inputs/AudioRecorder.h>
|
|
7
3
|
#include <audioapi/HostObjects/AudioContextHostObject.h>
|
|
8
4
|
#include <audioapi/HostObjects/OfflineAudioContextHostObject.h>
|
|
9
5
|
#include <audioapi/HostObjects/inputs/AudioRecorderHostObject.h>
|
|
6
|
+
#include <audioapi/HostObjects/utils/AudioDecoderHostObject.h>
|
|
7
|
+
#include <audioapi/HostObjects/utils/AudioStretcherHostObject.h>
|
|
8
|
+
#include <audioapi/core/AudioContext.h>
|
|
9
|
+
#include <audioapi/core/OfflineAudioContext.h>
|
|
10
|
+
#include <audioapi/core/inputs/AudioRecorder.h>
|
|
11
|
+
#include <audioapi/jsi/JsiPromise.h>
|
|
10
12
|
|
|
11
|
-
#include <audioapi/events/AudioEventHandlerRegistry.h>
|
|
12
13
|
#include <audioapi/HostObjects/events/AudioEventHandlerRegistryHostObject.h>
|
|
14
|
+
#include <audioapi/events/AudioEventHandlerRegistry.h>
|
|
13
15
|
|
|
14
16
|
#include <audioapi/core/utils/worklets/SafeIncludes.h>
|
|
15
17
|
|
|
@@ -22,29 +24,50 @@ using namespace facebook;
|
|
|
22
24
|
class AudioAPIModuleInstaller {
|
|
23
25
|
public:
|
|
24
26
|
static void injectJSIBindings(
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
auto createAudioContext = getCreateAudioContextFunction(
|
|
31
|
-
|
|
32
|
-
auto
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
auto
|
|
39
|
-
|
|
27
|
+
jsi::Runtime *jsiRuntime,
|
|
28
|
+
const std::shared_ptr<react::CallInvoker> &jsCallInvoker,
|
|
29
|
+
const std::shared_ptr<AudioEventHandlerRegistry>
|
|
30
|
+
&audioEventHandlerRegistry,
|
|
31
|
+
std::shared_ptr<worklets::WorkletRuntime> uiRuntime = nullptr) {
|
|
32
|
+
auto createAudioContext = getCreateAudioContextFunction(
|
|
33
|
+
jsiRuntime, jsCallInvoker, audioEventHandlerRegistry, uiRuntime);
|
|
34
|
+
auto createAudioRecorder =
|
|
35
|
+
getCreateAudioRecorderFunction(jsiRuntime, audioEventHandlerRegistry);
|
|
36
|
+
auto createOfflineAudioContext = getCreateOfflineAudioContextFunction(
|
|
37
|
+
jsiRuntime, jsCallInvoker, audioEventHandlerRegistry, uiRuntime);
|
|
38
|
+
auto createAudioDecoder =
|
|
39
|
+
getCreateAudioDecoderFunction(jsiRuntime, jsCallInvoker);
|
|
40
|
+
auto createAudioStretcher =
|
|
41
|
+
getCreateAudioStretcherFunction(jsiRuntime, jsCallInvoker);
|
|
42
|
+
|
|
43
|
+
jsiRuntime->global().setProperty(
|
|
44
|
+
*jsiRuntime, "createAudioContext", createAudioContext);
|
|
45
|
+
jsiRuntime->global().setProperty(
|
|
46
|
+
*jsiRuntime, "createAudioRecorder", createAudioRecorder);
|
|
47
|
+
jsiRuntime->global().setProperty(
|
|
48
|
+
*jsiRuntime, "createOfflineAudioContext", createOfflineAudioContext);
|
|
49
|
+
jsiRuntime->global().setProperty(
|
|
50
|
+
*jsiRuntime, "createAudioDecoder", createAudioDecoder);
|
|
51
|
+
jsiRuntime->global().setProperty(
|
|
52
|
+
*jsiRuntime, "createAudioStretcher", createAudioStretcher);
|
|
53
|
+
|
|
54
|
+
auto audioEventHandlerRegistryHostObject =
|
|
55
|
+
std::make_shared<AudioEventHandlerRegistryHostObject>(
|
|
56
|
+
audioEventHandlerRegistry);
|
|
57
|
+
jsiRuntime->global().setProperty(
|
|
58
|
+
*jsiRuntime,
|
|
59
|
+
"AudioEventEmitter",
|
|
60
|
+
jsi::Object::createFromHostObject(
|
|
61
|
+
*jsiRuntime, audioEventHandlerRegistryHostObject));
|
|
40
62
|
}
|
|
41
63
|
|
|
42
64
|
private:
|
|
43
65
|
static jsi::Function getCreateAudioContextFunction(
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
66
|
+
jsi::Runtime *jsiRuntime,
|
|
67
|
+
const std::shared_ptr<react::CallInvoker> &jsCallInvoker,
|
|
68
|
+
const std::shared_ptr<AudioEventHandlerRegistry>
|
|
69
|
+
&audioEventHandlerRegistry,
|
|
70
|
+
const std::weak_ptr<worklets::WorkletRuntime> &uiRuntime) {
|
|
48
71
|
return jsi::Function::createFromHostFunction(
|
|
49
72
|
*jsiRuntime,
|
|
50
73
|
jsi::PropNameID::forAscii(*jsiRuntime, "createAudioContext"),
|
|
@@ -67,9 +90,14 @@ class AudioAPIModuleInstaller {
|
|
|
67
90
|
auto runtimeRegistry = RuntimeRegistry{};
|
|
68
91
|
#endif
|
|
69
92
|
|
|
70
|
-
audioContext = std::make_shared<AudioContext>(
|
|
71
|
-
|
|
72
|
-
|
|
93
|
+
audioContext = std::make_shared<AudioContext>(
|
|
94
|
+
sampleRate,
|
|
95
|
+
initSuspended,
|
|
96
|
+
audioEventHandlerRegistry,
|
|
97
|
+
runtimeRegistry);
|
|
98
|
+
auto audioContextHostObject =
|
|
99
|
+
std::make_shared<AudioContextHostObject>(
|
|
100
|
+
audioContext, &runtime, jsCallInvoker);
|
|
73
101
|
|
|
74
102
|
return jsi::Object::createFromHostObject(
|
|
75
103
|
runtime, audioContextHostObject);
|
|
@@ -77,10 +105,11 @@ class AudioAPIModuleInstaller {
|
|
|
77
105
|
}
|
|
78
106
|
|
|
79
107
|
static jsi::Function getCreateOfflineAudioContextFunction(
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
108
|
+
jsi::Runtime *jsiRuntime,
|
|
109
|
+
const std::shared_ptr<react::CallInvoker> &jsCallInvoker,
|
|
110
|
+
const std::shared_ptr<AudioEventHandlerRegistry>
|
|
111
|
+
&audioEventHandlerRegistry,
|
|
112
|
+
const std::weak_ptr<worklets::WorkletRuntime> &uiRuntime) {
|
|
84
113
|
return jsi::Function::createFromHostFunction(
|
|
85
114
|
*jsiRuntime,
|
|
86
115
|
jsi::PropNameID::forAscii(*jsiRuntime, "createOfflineAudioContext"),
|
|
@@ -90,9 +119,9 @@ class AudioAPIModuleInstaller {
|
|
|
90
119
|
const jsi::Value &thisValue,
|
|
91
120
|
const jsi::Value *args,
|
|
92
121
|
size_t count) -> jsi::Value {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
122
|
+
auto numberOfChannels = static_cast<int>(args[0].getNumber());
|
|
123
|
+
auto length = static_cast<size_t>(args[1].getNumber());
|
|
124
|
+
auto sampleRate = static_cast<float>(args[2].getNumber());
|
|
96
125
|
|
|
97
126
|
#if RN_AUDIO_API_ENABLE_WORKLETS
|
|
98
127
|
auto runtimeRegistry = RuntimeRegistry{
|
|
@@ -103,9 +132,15 @@ class AudioAPIModuleInstaller {
|
|
|
103
132
|
auto runtimeRegistry = RuntimeRegistry{};
|
|
104
133
|
#endif
|
|
105
134
|
|
|
106
|
-
auto offlineAudioContext = std::make_shared<OfflineAudioContext>(
|
|
107
|
-
|
|
108
|
-
|
|
135
|
+
auto offlineAudioContext = std::make_shared<OfflineAudioContext>(
|
|
136
|
+
numberOfChannels,
|
|
137
|
+
length,
|
|
138
|
+
sampleRate,
|
|
139
|
+
audioEventHandlerRegistry,
|
|
140
|
+
runtimeRegistry);
|
|
141
|
+
auto audioContextHostObject =
|
|
142
|
+
std::make_shared<OfflineAudioContextHostObject>(
|
|
143
|
+
offlineAudioContext, &runtime, jsCallInvoker);
|
|
109
144
|
|
|
110
145
|
return jsi::Object::createFromHostObject(
|
|
111
146
|
runtime, audioContextHostObject);
|
|
@@ -113,8 +148,9 @@ class AudioAPIModuleInstaller {
|
|
|
113
148
|
}
|
|
114
149
|
|
|
115
150
|
static jsi::Function getCreateAudioRecorderFunction(
|
|
116
|
-
|
|
117
|
-
|
|
151
|
+
jsi::Runtime *jsiRuntime,
|
|
152
|
+
const std::shared_ptr<AudioEventHandlerRegistry>
|
|
153
|
+
&audioEventHandlerRegistry) {
|
|
118
154
|
return jsi::Function::createFromHostFunction(
|
|
119
155
|
*jsiRuntime,
|
|
120
156
|
jsi::PropNameID::forAscii(*jsiRuntime, "createAudioRecorder"),
|
|
@@ -126,12 +162,57 @@ class AudioAPIModuleInstaller {
|
|
|
126
162
|
size_t count) -> jsi::Value {
|
|
127
163
|
auto options = args[0].getObject(runtime);
|
|
128
164
|
|
|
129
|
-
auto sampleRate = static_cast<float>(
|
|
130
|
-
|
|
165
|
+
auto sampleRate = static_cast<float>(
|
|
166
|
+
options.getProperty(runtime, "sampleRate").getNumber());
|
|
167
|
+
auto bufferLength = static_cast<int>(
|
|
168
|
+
options.getProperty(runtime, "bufferLengthInSamples")
|
|
169
|
+
.getNumber());
|
|
131
170
|
|
|
132
|
-
auto audioRecorderHostObject =
|
|
171
|
+
auto audioRecorderHostObject =
|
|
172
|
+
std::make_shared<AudioRecorderHostObject>(
|
|
173
|
+
audioEventHandlerRegistry, sampleRate, bufferLength);
|
|
133
174
|
|
|
134
|
-
return jsi::Object::createFromHostObject(
|
|
175
|
+
return jsi::Object::createFromHostObject(
|
|
176
|
+
runtime, audioRecorderHostObject);
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
static jsi::Function getCreateAudioDecoderFunction(
|
|
181
|
+
jsi::Runtime *jsiRuntime,
|
|
182
|
+
const std::shared_ptr<react::CallInvoker> &jsCallInvoker) {
|
|
183
|
+
return jsi::Function::createFromHostFunction(
|
|
184
|
+
*jsiRuntime,
|
|
185
|
+
jsi::PropNameID::forAscii(*jsiRuntime, "createAudioDecoder"),
|
|
186
|
+
0,
|
|
187
|
+
[jsCallInvoker](
|
|
188
|
+
jsi::Runtime &runtime,
|
|
189
|
+
const jsi::Value &thisValue,
|
|
190
|
+
const jsi::Value *args,
|
|
191
|
+
size_t count) -> jsi::Value {
|
|
192
|
+
auto audioDecoderHostObject =
|
|
193
|
+
std::make_shared<AudioDecoderHostObject>(&runtime, jsCallInvoker);
|
|
194
|
+
return jsi::Object::createFromHostObject(
|
|
195
|
+
runtime, audioDecoderHostObject);
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
static jsi::Function getCreateAudioStretcherFunction(
|
|
200
|
+
jsi::Runtime *jsiRuntime,
|
|
201
|
+
const std::shared_ptr<react::CallInvoker> &jsCallInvoker) {
|
|
202
|
+
return jsi::Function::createFromHostFunction(
|
|
203
|
+
*jsiRuntime,
|
|
204
|
+
jsi::PropNameID::forAscii(*jsiRuntime, "createAudioStretcher"),
|
|
205
|
+
0,
|
|
206
|
+
[jsCallInvoker](
|
|
207
|
+
jsi::Runtime &runtime,
|
|
208
|
+
const jsi::Value &thisValue,
|
|
209
|
+
const jsi::Value *args,
|
|
210
|
+
size_t count) -> jsi::Value {
|
|
211
|
+
auto audioStretcherHostObject =
|
|
212
|
+
std::make_shared<AudioStretcherHostObject>(
|
|
213
|
+
&runtime, jsCallInvoker);
|
|
214
|
+
return jsi::Object::createFromHostObject(
|
|
215
|
+
runtime, audioStretcherHostObject);
|
|
135
216
|
});
|
|
136
217
|
}
|
|
137
218
|
};
|
|
@@ -49,11 +49,7 @@ BaseAudioContextHostObject::BaseAudioContextHostObject(
|
|
|
49
49
|
JSI_EXPORT_FUNCTION(BaseAudioContextHostObject, createBufferQueueSource),
|
|
50
50
|
JSI_EXPORT_FUNCTION(BaseAudioContextHostObject, createBuffer),
|
|
51
51
|
JSI_EXPORT_FUNCTION(BaseAudioContextHostObject, createPeriodicWave),
|
|
52
|
-
JSI_EXPORT_FUNCTION(BaseAudioContextHostObject, createAnalyser)
|
|
53
|
-
JSI_EXPORT_FUNCTION(BaseAudioContextHostObject, decodeAudioData),
|
|
54
|
-
JSI_EXPORT_FUNCTION(BaseAudioContextHostObject, decodeAudioDataSource),
|
|
55
|
-
JSI_EXPORT_FUNCTION(
|
|
56
|
-
BaseAudioContextHostObject, decodePCMAudioDataInBase64));
|
|
52
|
+
JSI_EXPORT_FUNCTION(BaseAudioContextHostObject, createAnalyser));
|
|
57
53
|
}
|
|
58
54
|
|
|
59
55
|
JSI_PROPERTY_GETTER_IMPL(BaseAudioContextHostObject, destination) {
|
|
@@ -266,100 +262,4 @@ JSI_HOST_FUNCTION_IMPL(BaseAudioContextHostObject, createAnalyser) {
|
|
|
266
262
|
auto analyserHostObject = std::make_shared<AnalyserNodeHostObject>(analyser);
|
|
267
263
|
return jsi::Object::createFromHostObject(runtime, analyserHostObject);
|
|
268
264
|
}
|
|
269
|
-
|
|
270
|
-
JSI_HOST_FUNCTION_IMPL(BaseAudioContextHostObject, decodeAudioDataSource) {
|
|
271
|
-
auto sourcePath = args[0].getString(runtime).utf8(runtime);
|
|
272
|
-
|
|
273
|
-
auto promise = promiseVendor_->createPromise(
|
|
274
|
-
[this, sourcePath](std::shared_ptr<Promise> promise) {
|
|
275
|
-
std::thread([this, sourcePath, promise = std::move(promise)]() {
|
|
276
|
-
auto results = context_->decodeAudioDataSource(sourcePath);
|
|
277
|
-
|
|
278
|
-
if (!results) {
|
|
279
|
-
promise->reject("Failed to decode audio data source.");
|
|
280
|
-
return;
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
auto audioBufferHostObject =
|
|
284
|
-
std::make_shared<AudioBufferHostObject>(results);
|
|
285
|
-
|
|
286
|
-
promise->resolve([audioBufferHostObject = std::move(
|
|
287
|
-
audioBufferHostObject)](jsi::Runtime &runtime) {
|
|
288
|
-
auto jsiObject = jsi::Object::createFromHostObject(
|
|
289
|
-
runtime, audioBufferHostObject);
|
|
290
|
-
jsiObject.setExternalMemoryPressure(
|
|
291
|
-
runtime, audioBufferHostObject->getSizeInBytes());
|
|
292
|
-
return jsiObject;
|
|
293
|
-
});
|
|
294
|
-
}).detach();
|
|
295
|
-
});
|
|
296
|
-
|
|
297
|
-
return promise;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
JSI_HOST_FUNCTION_IMPL(BaseAudioContextHostObject, decodeAudioData) {
|
|
301
|
-
auto arrayBuffer = args[0]
|
|
302
|
-
.getObject(runtime)
|
|
303
|
-
.getPropertyAsObject(runtime, "buffer")
|
|
304
|
-
.getArrayBuffer(runtime);
|
|
305
|
-
auto data = arrayBuffer.data(runtime);
|
|
306
|
-
auto size = static_cast<int>(arrayBuffer.size(runtime));
|
|
307
|
-
|
|
308
|
-
auto promise = promiseVendor_->createPromise(
|
|
309
|
-
[this, data, size](std::shared_ptr<Promise> promise) {
|
|
310
|
-
std::thread([this, data, size, promise = std::move(promise)]() {
|
|
311
|
-
auto results = context_->decodeAudioData(data, size);
|
|
312
|
-
|
|
313
|
-
if (!results) {
|
|
314
|
-
promise->reject("Failed to decode audio data source.");
|
|
315
|
-
return;
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
auto audioBufferHostObject =
|
|
319
|
-
std::make_shared<AudioBufferHostObject>(results);
|
|
320
|
-
|
|
321
|
-
promise->resolve([audioBufferHostObject = std::move(
|
|
322
|
-
audioBufferHostObject)](jsi::Runtime &runtime) {
|
|
323
|
-
auto jsiObject = jsi::Object::createFromHostObject(
|
|
324
|
-
runtime, audioBufferHostObject);
|
|
325
|
-
jsiObject.setExternalMemoryPressure(
|
|
326
|
-
runtime, audioBufferHostObject->getSizeInBytes());
|
|
327
|
-
return jsiObject;
|
|
328
|
-
});
|
|
329
|
-
}).detach();
|
|
330
|
-
});
|
|
331
|
-
|
|
332
|
-
return promise;
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
JSI_HOST_FUNCTION_IMPL(BaseAudioContextHostObject, decodePCMAudioDataInBase64) {
|
|
336
|
-
auto b64 = args[0].getString(runtime).utf8(runtime);
|
|
337
|
-
auto playbackSpeed = static_cast<float>(args[1].getNumber());
|
|
338
|
-
|
|
339
|
-
auto promise = promiseVendor_->createPromise(
|
|
340
|
-
[this, b64, playbackSpeed](std::shared_ptr<Promise> promise) {
|
|
341
|
-
std::thread([this, b64, playbackSpeed, promise = std::move(promise)]() {
|
|
342
|
-
auto results = context_->decodeWithPCMInBase64(b64, playbackSpeed);
|
|
343
|
-
|
|
344
|
-
if (!results) {
|
|
345
|
-
promise->reject("Failed to decode audio data source.");
|
|
346
|
-
return;
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
auto audioBufferHostObject =
|
|
350
|
-
std::make_shared<AudioBufferHostObject>(results);
|
|
351
|
-
|
|
352
|
-
promise->resolve([audioBufferHostObject = std::move(
|
|
353
|
-
audioBufferHostObject)](jsi::Runtime &runtime) {
|
|
354
|
-
auto jsiObject = jsi::Object::createFromHostObject(
|
|
355
|
-
runtime, audioBufferHostObject);
|
|
356
|
-
jsiObject.setExternalMemoryPressure(
|
|
357
|
-
runtime, audioBufferHostObject->getSizeInBytes());
|
|
358
|
-
return jsiObject;
|
|
359
|
-
});
|
|
360
|
-
}).detach();
|
|
361
|
-
});
|
|
362
|
-
|
|
363
|
-
return promise;
|
|
364
|
-
}
|
|
365
265
|
} // namespace audioapi
|
|
@@ -41,9 +41,6 @@ class BaseAudioContextHostObject : public JsiHostObject {
|
|
|
41
41
|
JSI_HOST_FUNCTION_DECL(createBuffer);
|
|
42
42
|
JSI_HOST_FUNCTION_DECL(createPeriodicWave);
|
|
43
43
|
JSI_HOST_FUNCTION_DECL(createAnalyser);
|
|
44
|
-
JSI_HOST_FUNCTION_DECL(decodeAudioDataSource);
|
|
45
|
-
JSI_HOST_FUNCTION_DECL(decodeAudioData);
|
|
46
|
-
JSI_HOST_FUNCTION_DECL(decodePCMAudioDataInBase64);
|
|
47
44
|
|
|
48
45
|
std::shared_ptr<BaseAudioContext> context_;
|
|
49
46
|
|