react-native-audio-api 0.9.0-nightly-96a5bcd-20251007 → 0.9.0

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.
Files changed (42) hide show
  1. package/android/src/main/cpp/audioapi/android/core/{utils/AudioDecoder.cpp → AudioDecoder.cpp} +75 -79
  2. package/common/cpp/audioapi/AudioAPIModuleInstaller.h +43 -99
  3. package/common/cpp/audioapi/HostObjects/BaseAudioContextHostObject.cpp +101 -1
  4. package/common/cpp/audioapi/HostObjects/BaseAudioContextHostObject.h +3 -0
  5. package/common/cpp/audioapi/core/AudioContext.cpp +2 -0
  6. package/common/cpp/audioapi/core/BaseAudioContext.cpp +35 -0
  7. package/common/cpp/audioapi/core/BaseAudioContext.h +12 -4
  8. package/common/cpp/audioapi/core/OfflineAudioContext.cpp +2 -0
  9. package/common/cpp/audioapi/core/utils/AudioDecoder.h +90 -36
  10. package/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.cpp +282 -241
  11. package/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.h +19 -57
  12. package/common/cpp/test/CMakeLists.txt +1 -1
  13. package/ios/audioapi/ios/core/AudioDecoder.mm +156 -0
  14. package/lib/commonjs/api.js +1 -14
  15. package/lib/commonjs/api.js.map +1 -1
  16. package/lib/commonjs/core/BaseAudioContext.js +18 -11
  17. package/lib/commonjs/core/BaseAudioContext.js.map +1 -1
  18. package/lib/module/api.js +1 -2
  19. package/lib/module/api.js.map +1 -1
  20. package/lib/module/core/BaseAudioContext.js +18 -11
  21. package/lib/module/core/BaseAudioContext.js.map +1 -1
  22. package/lib/typescript/api.d.ts +1 -3
  23. package/lib/typescript/api.d.ts.map +1 -1
  24. package/lib/typescript/core/BaseAudioContext.d.ts +6 -3
  25. package/lib/typescript/core/BaseAudioContext.d.ts.map +1 -1
  26. package/lib/typescript/interfaces.d.ts +3 -6
  27. package/lib/typescript/interfaces.d.ts.map +1 -1
  28. package/package.json +1 -1
  29. package/src/api.ts +0 -5
  30. package/src/core/BaseAudioContext.ts +29 -26
  31. package/src/interfaces.ts +6 -18
  32. package/common/cpp/audioapi/HostObjects/utils/AudioDecoderHostObject.cpp +0 -107
  33. package/common/cpp/audioapi/HostObjects/utils/AudioDecoderHostObject.h +0 -28
  34. package/common/cpp/audioapi/core/types/AudioFormat.h +0 -16
  35. package/ios/audioapi/ios/core/utils/AudioDecoder.mm +0 -160
  36. package/lib/commonjs/core/AudioDecoder.js +0 -48
  37. package/lib/commonjs/core/AudioDecoder.js.map +0 -1
  38. package/lib/module/core/AudioDecoder.js +0 -42
  39. package/lib/module/core/AudioDecoder.js.map +0 -1
  40. package/lib/typescript/core/AudioDecoder.d.ts +0 -4
  41. package/lib/typescript/core/AudioDecoder.d.ts.map +0 -1
  42. package/src/core/AudioDecoder.ts +0 -78
@@ -1,4 +1,3 @@
1
- #include <audioapi/core/sources/AudioBuffer.h>
2
1
  #include <audioapi/core/utils/AudioDecoder.h>
3
2
  #include <audioapi/dsp/VectorMath.h>
4
3
  #include <audioapi/libs/base64/base64.h>
@@ -6,28 +5,28 @@
6
5
  #include <audioapi/utils/AudioBus.h>
7
6
 
8
7
  #define MINIAUDIO_IMPLEMENTATION
9
- #include <audioapi/libs/miniaudio/decoders/libopus/miniaudio_libopus.h>
10
- #include <audioapi/libs/miniaudio/decoders/libvorbis/miniaudio_libvorbis.h>
11
8
  #include <audioapi/libs/miniaudio/miniaudio.h>
12
9
 
13
10
  #ifndef AUDIO_API_TEST_SUITE
14
11
  #include <android/log.h>
15
12
  #include <audioapi/libs/ffmpeg/FFmpegDecoding.h>
16
13
  #endif
14
+ #include <audioapi/libs/miniaudio/decoders/libopus/miniaudio_libopus.h>
15
+ #include <audioapi/libs/miniaudio/decoders/libvorbis/miniaudio_libvorbis.h>
17
16
 
18
17
  namespace audioapi {
19
18
 
20
19
  // Decoding audio in fixed-size chunks because total frame count can't be
21
20
  // determined in advance. Note: ma_decoder_get_length_in_pcm_frames() always
22
21
  // returns 0 for Vorbis decoders.
23
- std::vector<float> AudioDecoder::readAllPcmFrames(
22
+ std::vector<int16_t> AudioDecoder::readAllPcmFrames(
24
23
  ma_decoder &decoder,
25
- int outputChannels) {
26
- std::vector<float> buffer;
27
- std::vector<float> temp(CHUNK_SIZE * outputChannels);
28
- ma_uint64 outFramesRead = 0;
24
+ int numChannels,
25
+ ma_uint64 &outFramesRead) {
26
+ std::vector<int16_t> buffer;
27
+ std::vector<int16_t> temp(CHUNK_SIZE * numChannels);
28
+ outFramesRead = 0;
29
29
 
30
- #ifndef AUDIO_API_TEST_SUITE
31
30
  while (true) {
32
31
  ma_uint64 tempFramesDecoded = 0;
33
32
  ma_decoder_read_pcm_frames(
@@ -39,46 +38,38 @@ std::vector<float> AudioDecoder::readAllPcmFrames(
39
38
  buffer.insert(
40
39
  buffer.end(),
41
40
  temp.data(),
42
- temp.data() + tempFramesDecoded * outputChannels);
41
+ temp.data() + tempFramesDecoded * numChannels);
43
42
  outFramesRead += tempFramesDecoded;
44
43
  }
45
44
 
46
- if (outFramesRead == 0) {
47
- __android_log_print(ANDROID_LOG_ERROR, "AudioDecoder", "Failed to decode");
48
- }
49
- #endif
50
45
  return buffer;
51
46
  }
52
47
 
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
- }
60
-
61
- auto outputFrames = buffer.size() / outputChannels;
62
- auto audioBus = std::make_shared<AudioBus>(
63
- outputFrames, outputChannels, outputSampleRate);
48
+ std::shared_ptr<AudioBus> AudioDecoder::makeAudioBusFromInt16Buffer(
49
+ const std::vector<int16_t> &buffer,
50
+ int numChannels,
51
+ float sampleRate) {
52
+ auto outputFrames = buffer.size() / numChannels;
53
+ auto audioBus =
54
+ std::make_shared<AudioBus>(outputFrames, numChannels, sampleRate);
64
55
 
65
- for (int ch = 0; ch < outputChannels; ++ch) {
56
+ for (int ch = 0; ch < numChannels; ++ch) {
66
57
  auto channelData = audioBus->getChannel(ch)->getData();
67
58
  for (int i = 0; i < outputFrames; ++i) {
68
- channelData[i] = buffer[i * outputChannels + ch];
59
+ channelData[i] = int16ToFloat(buffer[i * numChannels + ch]);
69
60
  }
70
61
  }
71
- return std::make_shared<AudioBuffer>(audioBus);
62
+ return audioBus;
72
63
  }
73
64
 
74
- std::shared_ptr<AudioBuffer> AudioDecoder::decodeWithFilePath(
75
- const std::string &path,
76
- float sampleRate) {
65
+ std::shared_ptr<AudioBus> AudioDecoder::decodeWithFilePath(
66
+ const std::string &path) const {
77
67
  #ifndef AUDIO_API_TEST_SUITE
68
+ std::vector<int16_t> buffer;
78
69
  if (AudioDecoder::pathHasExtension(path, {".mp4", ".m4a", ".aac"})) {
79
- auto buffer =
80
- ffmpegdecoder::decodeWithFilePath(path, static_cast<int>(sampleRate));
81
- if (buffer == nullptr) {
70
+ buffer = ffmpegdecoding::decodeWithFilePath(
71
+ path, numChannels_, static_cast<int>(sampleRate_));
72
+ if (buffer.empty()) {
82
73
  __android_log_print(
83
74
  ANDROID_LOG_ERROR,
84
75
  "AudioDecoder",
@@ -86,11 +77,11 @@ std::shared_ptr<AudioBuffer> AudioDecoder::decodeWithFilePath(
86
77
  path.c_str());
87
78
  return nullptr;
88
79
  }
89
- return buffer;
80
+ return makeAudioBusFromInt16Buffer(buffer, numChannels_, sampleRate_);
90
81
  }
91
82
  ma_decoder decoder;
92
- ma_decoder_config config =
93
- ma_decoder_config_init(ma_format_f32, 0, static_cast<int>(sampleRate));
83
+ ma_decoder_config config = ma_decoder_config_init(
84
+ ma_format_s16, numChannels_, static_cast<int>(sampleRate_));
94
85
  ma_decoding_backend_vtable *customBackends[] = {
95
86
  ma_decoding_backend_libvorbis, ma_decoding_backend_libopus};
96
87
 
@@ -108,38 +99,41 @@ std::shared_ptr<AudioBuffer> AudioDecoder::decodeWithFilePath(
108
99
  return nullptr;
109
100
  }
110
101
 
111
- auto outputSampleRate = static_cast<float>(decoder.outputSampleRate);
112
- auto outputChannels = static_cast<int>(decoder.outputChannels);
102
+ ma_uint64 framesRead = 0;
103
+ buffer = readAllPcmFrames(decoder, numChannels_, framesRead);
104
+ if (framesRead == 0) {
105
+ __android_log_print(ANDROID_LOG_ERROR, "AudioDecoder", "Failed to decode");
106
+ ma_decoder_uninit(&decoder);
107
+ return nullptr;
108
+ }
113
109
 
114
- std::vector<float> buffer = readAllPcmFrames(decoder, outputChannels);
115
110
  ma_decoder_uninit(&decoder);
116
- return makeAudioBufferFromFloatBuffer(
117
- buffer, outputSampleRate, outputChannels);
111
+ return makeAudioBusFromInt16Buffer(buffer, numChannels_, sampleRate_);
118
112
  #else
119
113
  return nullptr;
120
114
  #endif
121
115
  }
122
116
 
123
- std::shared_ptr<AudioBuffer> AudioDecoder::decodeWithMemoryBlock(
117
+ std::shared_ptr<AudioBus> AudioDecoder::decodeWithMemoryBlock(
124
118
  const void *data,
125
- size_t size,
126
- float sampleRate) {
119
+ size_t size) const {
127
120
  #ifndef AUDIO_API_TEST_SUITE
121
+ std::vector<int16_t> buffer;
128
122
  const AudioFormat format = AudioDecoder::detectAudioFormat(data, size);
129
123
  if (format == AudioFormat::MP4 || format == AudioFormat::M4A ||
130
124
  format == AudioFormat::AAC) {
131
- auto buffer = ffmpegdecoder::decodeWithMemoryBlock(
132
- data, size, static_cast<int>(sampleRate));
133
- if (buffer == nullptr) {
125
+ buffer = ffmpegdecoding::decodeWithMemoryBlock(
126
+ data, size, numChannels_, sampleRate_);
127
+ if (buffer.empty()) {
134
128
  __android_log_print(
135
129
  ANDROID_LOG_ERROR, "AudioDecoder", "Failed to decode with FFmpeg");
136
130
  return nullptr;
137
131
  }
138
- return buffer;
132
+ return makeAudioBusFromInt16Buffer(buffer, numChannels_, sampleRate_);
139
133
  }
140
134
  ma_decoder decoder;
141
- ma_decoder_config config =
142
- ma_decoder_config_init(ma_format_f32, 0, static_cast<int>(sampleRate));
135
+ ma_decoder_config config = ma_decoder_config_init(
136
+ ma_format_s16, numChannels_, static_cast<int>(sampleRate_));
143
137
 
144
138
  ma_decoding_backend_vtable *customBackends[] = {
145
139
  ma_decoding_backend_libvorbis, ma_decoding_backend_libopus};
@@ -157,48 +151,50 @@ std::shared_ptr<AudioBuffer> AudioDecoder::decodeWithMemoryBlock(
157
151
  return nullptr;
158
152
  }
159
153
 
160
- auto outputSampleRate = static_cast<float>(decoder.outputSampleRate);
161
- auto outputChannels = static_cast<int>(decoder.outputChannels);
154
+ ma_uint64 framesRead = 0;
155
+ buffer = readAllPcmFrames(decoder, numChannels_, framesRead);
156
+ if (framesRead == 0) {
157
+ __android_log_print(ANDROID_LOG_ERROR, "AudioDecoder", "Failed to decode");
158
+ ma_decoder_uninit(&decoder);
159
+ return nullptr;
160
+ }
162
161
 
163
- std::vector<float> buffer = readAllPcmFrames(decoder, outputChannels);
164
162
  ma_decoder_uninit(&decoder);
165
- return makeAudioBufferFromFloatBuffer(
166
- buffer, outputSampleRate, outputChannels);
163
+ return makeAudioBusFromInt16Buffer(buffer, numChannels_, sampleRate_);
167
164
  #else
168
165
  return nullptr;
169
166
  #endif
170
167
  }
171
168
 
172
- std::shared_ptr<AudioBuffer> AudioDecoder::decodeWithPCMInBase64(
169
+ std::shared_ptr<AudioBus> AudioDecoder::decodeWithPCMInBase64(
173
170
  const std::string &data,
174
- float inputSampleRate,
175
- int inputChannelCount,
176
- bool interleaved) {
171
+ float playbackSpeed) const {
177
172
  auto decodedData = base64_decode(data, false);
173
+
178
174
  const auto uint8Data = reinterpret_cast<uint8_t *>(decodedData.data());
179
- size_t numFramesDecoded =
180
- decodedData.size() / (inputChannelCount * sizeof(int16_t));
175
+ size_t framesDecoded = decodedData.size() / 2;
181
176
 
182
- auto audioBus = std::make_shared<AudioBus>(
183
- numFramesDecoded, inputChannelCount, inputSampleRate);
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
+ }
184
182
 
185
- for (int ch = 0; ch < inputChannelCount; ++ch) {
186
- auto channelData = audioBus->getChannel(ch)->getData();
183
+ changePlaybackSpeedIfNeeded(buffer, framesDecoded, 1, playbackSpeed);
184
+ auto outputFrames = buffer.size();
187
185
 
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
- }
186
+ auto audioBus =
187
+ std::make_shared<AudioBus>(outputFrames, numChannels_, sampleRate_);
188
+ auto leftChannelData = audioBus->getChannel(0)->getData();
189
+ auto rightChannelData = audioBus->getChannel(1)->getData();
190
+
191
+ for (size_t i = 0; i < outputFrames; ++i) {
192
+ auto sample = int16ToFloat(buffer[i]);
193
+ leftChannelData[i] = sample;
194
+ rightChannelData[i] = sample;
200
195
  }
201
- return std::make_shared<AudioBuffer>(audioBus);
196
+
197
+ return audioBus;
202
198
  }
203
199
 
204
200
  } // namespace audioapi
@@ -1,16 +1,15 @@
1
1
  #pragma once
2
2
 
3
- #include <audioapi/HostObjects/AudioContextHostObject.h>
4
- #include <audioapi/HostObjects/OfflineAudioContextHostObject.h>
5
- #include <audioapi/HostObjects/inputs/AudioRecorderHostObject.h>
6
- #include <audioapi/HostObjects/utils/AudioDecoderHostObject.h>
3
+ #include <audioapi/jsi/JsiPromise.h>
7
4
  #include <audioapi/core/AudioContext.h>
8
5
  #include <audioapi/core/OfflineAudioContext.h>
9
6
  #include <audioapi/core/inputs/AudioRecorder.h>
10
- #include <audioapi/jsi/JsiPromise.h>
7
+ #include <audioapi/HostObjects/AudioContextHostObject.h>
8
+ #include <audioapi/HostObjects/OfflineAudioContextHostObject.h>
9
+ #include <audioapi/HostObjects/inputs/AudioRecorderHostObject.h>
11
10
 
12
- #include <audioapi/HostObjects/events/AudioEventHandlerRegistryHostObject.h>
13
11
  #include <audioapi/events/AudioEventHandlerRegistry.h>
12
+ #include <audioapi/HostObjects/events/AudioEventHandlerRegistryHostObject.h>
14
13
 
15
14
  #include <audioapi/core/utils/worklets/SafeIncludes.h>
16
15
 
@@ -23,46 +22,29 @@ using namespace facebook;
23
22
  class AudioAPIModuleInstaller {
24
23
  public:
25
24
  static void injectJSIBindings(
26
- jsi::Runtime *jsiRuntime,
27
- const std::shared_ptr<react::CallInvoker> &jsCallInvoker,
28
- const std::shared_ptr<AudioEventHandlerRegistry>
29
- &audioEventHandlerRegistry,
30
- std::shared_ptr<worklets::WorkletRuntime> uiRuntime = nullptr) {
31
- auto createAudioContext = getCreateAudioContextFunction(
32
- jsiRuntime, jsCallInvoker, audioEventHandlerRegistry, uiRuntime);
33
- auto createAudioRecorder =
34
- getCreateAudioRecorderFunction(jsiRuntime, audioEventHandlerRegistry);
35
- auto createOfflineAudioContext = getCreateOfflineAudioContextFunction(
36
- jsiRuntime, jsCallInvoker, audioEventHandlerRegistry, uiRuntime);
37
- auto createAudioDecoder =
38
- getCreateAudioDecoderFunction(jsiRuntime, jsCallInvoker);
39
-
40
- jsiRuntime->global().setProperty(
41
- *jsiRuntime, "createAudioContext", createAudioContext);
42
- jsiRuntime->global().setProperty(
43
- *jsiRuntime, "createAudioRecorder", createAudioRecorder);
44
- jsiRuntime->global().setProperty(
45
- *jsiRuntime, "createOfflineAudioContext", createOfflineAudioContext);
46
- jsiRuntime->global().setProperty(
47
- *jsiRuntime, "createAudioDecoder", createAudioDecoder);
48
-
49
- auto audioEventHandlerRegistryHostObject =
50
- std::make_shared<AudioEventHandlerRegistryHostObject>(
51
- audioEventHandlerRegistry);
52
- jsiRuntime->global().setProperty(
53
- *jsiRuntime,
54
- "AudioEventEmitter",
55
- jsi::Object::createFromHostObject(
56
- *jsiRuntime, audioEventHandlerRegistryHostObject));
25
+ jsi::Runtime *jsiRuntime,
26
+ const std::shared_ptr<react::CallInvoker> &jsCallInvoker,
27
+ const std::shared_ptr<AudioEventHandlerRegistry> &audioEventHandlerRegistry,
28
+ std::shared_ptr<worklets::WorkletRuntime> uiRuntime = nullptr) {
29
+
30
+ auto createAudioContext = getCreateAudioContextFunction(jsiRuntime, jsCallInvoker, audioEventHandlerRegistry, uiRuntime);
31
+ auto createAudioRecorder = getCreateAudioRecorderFunction(jsiRuntime, audioEventHandlerRegistry);
32
+ auto createOfflineAudioContext = getCreateOfflineAudioContextFunction(jsiRuntime, jsCallInvoker, audioEventHandlerRegistry, uiRuntime);
33
+
34
+ jsiRuntime->global().setProperty(*jsiRuntime, "createAudioContext", createAudioContext);
35
+ jsiRuntime->global().setProperty(*jsiRuntime, "createAudioRecorder", createAudioRecorder);
36
+ jsiRuntime->global().setProperty(*jsiRuntime, "createOfflineAudioContext", createOfflineAudioContext);
37
+
38
+ auto audioEventHandlerRegistryHostObject = std::make_shared<AudioEventHandlerRegistryHostObject>(audioEventHandlerRegistry);
39
+ jsiRuntime->global().setProperty(*jsiRuntime, "AudioEventEmitter", jsi::Object::createFromHostObject(*jsiRuntime, audioEventHandlerRegistryHostObject));
57
40
  }
58
41
 
59
42
  private:
60
43
  static jsi::Function getCreateAudioContextFunction(
61
- jsi::Runtime *jsiRuntime,
62
- const std::shared_ptr<react::CallInvoker> &jsCallInvoker,
63
- const std::shared_ptr<AudioEventHandlerRegistry>
64
- &audioEventHandlerRegistry,
65
- const std::weak_ptr<worklets::WorkletRuntime> &uiRuntime) {
44
+ jsi::Runtime *jsiRuntime,
45
+ const std::shared_ptr<react::CallInvoker> &jsCallInvoker,
46
+ const std::shared_ptr<AudioEventHandlerRegistry> &audioEventHandlerRegistry,
47
+ const std::weak_ptr<worklets::WorkletRuntime> &uiRuntime) {
66
48
  return jsi::Function::createFromHostFunction(
67
49
  *jsiRuntime,
68
50
  jsi::PropNameID::forAscii(*jsiRuntime, "createAudioContext"),
@@ -85,14 +67,9 @@ class AudioAPIModuleInstaller {
85
67
  auto runtimeRegistry = RuntimeRegistry{};
86
68
  #endif
87
69
 
88
- audioContext = std::make_shared<AudioContext>(
89
- sampleRate,
90
- initSuspended,
91
- audioEventHandlerRegistry,
92
- runtimeRegistry);
93
- auto audioContextHostObject =
94
- std::make_shared<AudioContextHostObject>(
95
- audioContext, &runtime, jsCallInvoker);
70
+ audioContext = std::make_shared<AudioContext>(sampleRate, initSuspended, audioEventHandlerRegistry, runtimeRegistry);
71
+ auto audioContextHostObject = std::make_shared<AudioContextHostObject>(
72
+ audioContext, &runtime, jsCallInvoker);
96
73
 
97
74
  return jsi::Object::createFromHostObject(
98
75
  runtime, audioContextHostObject);
@@ -100,11 +77,10 @@ class AudioAPIModuleInstaller {
100
77
  }
101
78
 
102
79
  static jsi::Function getCreateOfflineAudioContextFunction(
103
- jsi::Runtime *jsiRuntime,
104
- const std::shared_ptr<react::CallInvoker> &jsCallInvoker,
105
- const std::shared_ptr<AudioEventHandlerRegistry>
106
- &audioEventHandlerRegistry,
107
- const std::weak_ptr<worklets::WorkletRuntime> &uiRuntime) {
80
+ jsi::Runtime *jsiRuntime,
81
+ const std::shared_ptr<react::CallInvoker> &jsCallInvoker,
82
+ const std::shared_ptr<AudioEventHandlerRegistry> &audioEventHandlerRegistry,
83
+ const std::weak_ptr<worklets::WorkletRuntime> &uiRuntime) {
108
84
  return jsi::Function::createFromHostFunction(
109
85
  *jsiRuntime,
110
86
  jsi::PropNameID::forAscii(*jsiRuntime, "createOfflineAudioContext"),
@@ -114,9 +90,9 @@ class AudioAPIModuleInstaller {
114
90
  const jsi::Value &thisValue,
115
91
  const jsi::Value *args,
116
92
  size_t count) -> jsi::Value {
117
- auto numberOfChannels = static_cast<int>(args[0].getNumber());
118
- auto length = static_cast<size_t>(args[1].getNumber());
119
- auto sampleRate = static_cast<float>(args[2].getNumber());
93
+ auto numberOfChannels = static_cast<int>(args[0].getNumber());
94
+ auto length = static_cast<size_t>(args[1].getNumber());
95
+ auto sampleRate = static_cast<float>(args[2].getNumber());
120
96
 
121
97
  #if RN_AUDIO_API_ENABLE_WORKLETS
122
98
  auto runtimeRegistry = RuntimeRegistry{
@@ -127,15 +103,9 @@ class AudioAPIModuleInstaller {
127
103
  auto runtimeRegistry = RuntimeRegistry{};
128
104
  #endif
129
105
 
130
- auto offlineAudioContext = std::make_shared<OfflineAudioContext>(
131
- numberOfChannels,
132
- length,
133
- sampleRate,
134
- audioEventHandlerRegistry,
135
- runtimeRegistry);
136
- auto audioContextHostObject =
137
- std::make_shared<OfflineAudioContextHostObject>(
138
- offlineAudioContext, &runtime, jsCallInvoker);
106
+ auto offlineAudioContext = std::make_shared<OfflineAudioContext>(numberOfChannels, length, sampleRate, audioEventHandlerRegistry, runtimeRegistry);
107
+ auto audioContextHostObject = std::make_shared<OfflineAudioContextHostObject>(
108
+ offlineAudioContext, &runtime, jsCallInvoker);
139
109
 
140
110
  return jsi::Object::createFromHostObject(
141
111
  runtime, audioContextHostObject);
@@ -143,9 +113,8 @@ class AudioAPIModuleInstaller {
143
113
  }
144
114
 
145
115
  static jsi::Function getCreateAudioRecorderFunction(
146
- jsi::Runtime *jsiRuntime,
147
- const std::shared_ptr<AudioEventHandlerRegistry>
148
- &audioEventHandlerRegistry) {
116
+ jsi::Runtime *jsiRuntime,
117
+ const std::shared_ptr<AudioEventHandlerRegistry> &audioEventHandlerRegistry) {
149
118
  return jsi::Function::createFromHostFunction(
150
119
  *jsiRuntime,
151
120
  jsi::PropNameID::forAscii(*jsiRuntime, "createAudioRecorder"),
@@ -157,37 +126,12 @@ class AudioAPIModuleInstaller {
157
126
  size_t count) -> jsi::Value {
158
127
  auto options = args[0].getObject(runtime);
159
128
 
160
- auto sampleRate = static_cast<float>(
161
- options.getProperty(runtime, "sampleRate").getNumber());
162
- auto bufferLength = static_cast<int>(
163
- options.getProperty(runtime, "bufferLengthInSamples")
164
- .getNumber());
129
+ auto sampleRate = static_cast<float>(options.getProperty(runtime, "sampleRate").getNumber());
130
+ auto bufferLength = static_cast<int>(options.getProperty(runtime, "bufferLengthInSamples").getNumber());
165
131
 
166
- auto audioRecorderHostObject =
167
- std::make_shared<AudioRecorderHostObject>(
168
- audioEventHandlerRegistry, sampleRate, bufferLength);
132
+ auto audioRecorderHostObject = std::make_shared<AudioRecorderHostObject>(audioEventHandlerRegistry, sampleRate, bufferLength);
169
133
 
170
- return jsi::Object::createFromHostObject(
171
- runtime, audioRecorderHostObject);
172
- });
173
- }
174
-
175
- static jsi::Function getCreateAudioDecoderFunction(
176
- jsi::Runtime *jsiRuntime,
177
- const std::shared_ptr<react::CallInvoker> &jsCallInvoker) {
178
- return jsi::Function::createFromHostFunction(
179
- *jsiRuntime,
180
- jsi::PropNameID::forAscii(*jsiRuntime, "createAudioDecoder"),
181
- 0,
182
- [jsCallInvoker](
183
- jsi::Runtime &runtime,
184
- const jsi::Value &thisValue,
185
- const jsi::Value *args,
186
- size_t count) -> jsi::Value {
187
- auto audioDecoderHostObject =
188
- std::make_shared<AudioDecoderHostObject>(&runtime, jsCallInvoker);
189
- return jsi::Object::createFromHostObject(
190
- runtime, audioDecoderHostObject);
134
+ return jsi::Object::createFromHostObject(runtime, audioRecorderHostObject);
191
135
  });
192
136
  }
193
137
  };
@@ -49,7 +49,11 @@ 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));
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));
53
57
  }
54
58
 
55
59
  JSI_PROPERTY_GETTER_IMPL(BaseAudioContextHostObject, destination) {
@@ -262,4 +266,100 @@ JSI_HOST_FUNCTION_IMPL(BaseAudioContextHostObject, createAnalyser) {
262
266
  auto analyserHostObject = std::make_shared<AnalyserNodeHostObject>(analyser);
263
267
  return jsi::Object::createFromHostObject(runtime, analyserHostObject);
264
268
  }
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
+ }
265
365
  } // namespace audioapi
@@ -41,6 +41,9 @@ 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);
44
47
 
45
48
  std::shared_ptr<BaseAudioContext> context_;
46
49
 
@@ -6,6 +6,7 @@
6
6
 
7
7
  #include <audioapi/core/AudioContext.h>
8
8
  #include <audioapi/core/destinations/AudioDestinationNode.h>
9
+ #include <audioapi/core/utils/AudioDecoder.h>
9
10
  #include <audioapi/core/utils/AudioNodeManager.h>
10
11
 
11
12
  namespace audioapi {
@@ -25,6 +26,7 @@ AudioContext::AudioContext(
25
26
  #endif
26
27
 
27
28
  sampleRate_ = sampleRate;
29
+ audioDecoder_ = std::make_shared<AudioDecoder>(sampleRate);
28
30
 
29
31
  if (initSuspended) {
30
32
  playerHasBeenStarted_ = false;
@@ -176,6 +176,41 @@ std::shared_ptr<AnalyserNode> BaseAudioContext::createAnalyser() {
176
176
  return analyser;
177
177
  }
178
178
 
179
+ std::shared_ptr<AudioBuffer> BaseAudioContext::decodeAudioDataSource(
180
+ const std::string &path) {
181
+ auto audioBus = audioDecoder_->decodeWithFilePath(path);
182
+
183
+ if (!audioBus) {
184
+ return nullptr;
185
+ }
186
+
187
+ return std::make_shared<AudioBuffer>(audioBus);
188
+ }
189
+
190
+ std::shared_ptr<AudioBuffer> BaseAudioContext::decodeAudioData(
191
+ const void *data,
192
+ size_t size) {
193
+ auto audioBus = audioDecoder_->decodeWithMemoryBlock(data, size);
194
+
195
+ if (!audioBus) {
196
+ return nullptr;
197
+ }
198
+
199
+ return std::make_shared<AudioBuffer>(audioBus);
200
+ }
201
+
202
+ std::shared_ptr<AudioBuffer> BaseAudioContext::decodeWithPCMInBase64(
203
+ const std::string &data,
204
+ float playbackSpeed) {
205
+ auto audioBus = audioDecoder_->decodeWithPCMInBase64(data, playbackSpeed);
206
+
207
+ if (!audioBus) {
208
+ return nullptr;
209
+ }
210
+
211
+ return std::make_shared<AudioBuffer>(audioBus);
212
+ }
213
+
179
214
  AudioNodeManager *BaseAudioContext::getNodeManager() {
180
215
  return nodeManager_.get();
181
216
  }