react-native-audio-api 0.9.0 → 0.10.0-nightly-971a6b4-20251009

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 (60) hide show
  1. package/android/src/main/cpp/audioapi/android/core/{AudioDecoder.cpp → utils/AudioDecoder.cpp} +79 -75
  2. package/common/cpp/audioapi/AudioAPIModuleInstaller.h +124 -43
  3. package/common/cpp/audioapi/HostObjects/BaseAudioContextHostObject.cpp +1 -101
  4. package/common/cpp/audioapi/HostObjects/BaseAudioContextHostObject.h +0 -3
  5. package/common/cpp/audioapi/HostObjects/utils/AudioDecoderHostObject.cpp +133 -0
  6. package/common/cpp/audioapi/HostObjects/utils/AudioDecoderHostObject.h +28 -0
  7. package/common/cpp/audioapi/HostObjects/utils/AudioStretcherHostObject.cpp +58 -0
  8. package/common/cpp/audioapi/HostObjects/utils/AudioStretcherHostObject.h +26 -0
  9. package/common/cpp/audioapi/core/AudioContext.cpp +0 -2
  10. package/common/cpp/audioapi/core/BaseAudioContext.cpp +0 -35
  11. package/common/cpp/audioapi/core/BaseAudioContext.h +4 -12
  12. package/common/cpp/audioapi/core/OfflineAudioContext.cpp +0 -2
  13. package/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.cpp +0 -4
  14. package/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.h +0 -1
  15. package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp +0 -2
  16. package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.cpp +0 -4
  17. package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.h +0 -1
  18. package/common/cpp/audioapi/core/types/AudioFormat.h +16 -0
  19. package/common/cpp/audioapi/core/utils/AudioDecoder.h +36 -91
  20. package/common/cpp/audioapi/core/utils/AudioStretcher.cpp +75 -0
  21. package/common/cpp/audioapi/core/utils/AudioStretcher.h +30 -0
  22. package/common/cpp/audioapi/core/utils/Constants.h +4 -0
  23. package/common/cpp/audioapi/events/AudioEventHandlerRegistry.cpp +5 -1
  24. package/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.cpp +241 -282
  25. package/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.h +57 -19
  26. package/common/cpp/test/CMakeLists.txt +1 -1
  27. package/ios/audioapi/ios/core/utils/AudioDecoder.mm +160 -0
  28. package/lib/commonjs/api.js +21 -1
  29. package/lib/commonjs/api.js.map +1 -1
  30. package/lib/commonjs/core/AudioDecoder.js +48 -0
  31. package/lib/commonjs/core/AudioDecoder.js.map +1 -0
  32. package/lib/commonjs/core/AudioStretcher.js +31 -0
  33. package/lib/commonjs/core/AudioStretcher.js.map +1 -0
  34. package/lib/commonjs/core/BaseAudioContext.js +11 -18
  35. package/lib/commonjs/core/BaseAudioContext.js.map +1 -1
  36. package/lib/module/api.js +3 -1
  37. package/lib/module/api.js.map +1 -1
  38. package/lib/module/core/AudioDecoder.js +42 -0
  39. package/lib/module/core/AudioDecoder.js.map +1 -0
  40. package/lib/module/core/AudioStretcher.js +26 -0
  41. package/lib/module/core/AudioStretcher.js.map +1 -0
  42. package/lib/module/core/BaseAudioContext.js +11 -18
  43. package/lib/module/core/BaseAudioContext.js.map +1 -1
  44. package/lib/typescript/api.d.ts +5 -1
  45. package/lib/typescript/api.d.ts.map +1 -1
  46. package/lib/typescript/core/AudioDecoder.d.ts +4 -0
  47. package/lib/typescript/core/AudioDecoder.d.ts.map +1 -0
  48. package/lib/typescript/core/AudioStretcher.d.ts +3 -0
  49. package/lib/typescript/core/AudioStretcher.d.ts.map +1 -0
  50. package/lib/typescript/core/BaseAudioContext.d.ts +3 -6
  51. package/lib/typescript/core/BaseAudioContext.d.ts.map +1 -1
  52. package/lib/typescript/interfaces.d.ts +10 -3
  53. package/lib/typescript/interfaces.d.ts.map +1 -1
  54. package/package.json +1 -1
  55. package/src/api.ts +10 -0
  56. package/src/core/AudioDecoder.ts +78 -0
  57. package/src/core/AudioStretcher.ts +43 -0
  58. package/src/core/BaseAudioContext.ts +26 -29
  59. package/src/interfaces.ts +26 -6
  60. package/ios/audioapi/ios/core/AudioDecoder.mm +0 -156
@@ -0,0 +1,133 @@
1
+ #pragma once
2
+
3
+ #include <audioapi/HostObjects/sources/AudioBufferHostObject.h>
4
+ #include <audioapi/HostObjects/utils/AudioDecoderHostObject.h>
5
+ #include <audioapi/core/utils/AudioDecoder.h>
6
+ #include <audioapi/jsi/JsiPromise.h>
7
+
8
+ #include <jsi/jsi.h>
9
+ #include <memory>
10
+ #include <string>
11
+ #include <thread>
12
+ #include <utility>
13
+
14
+ namespace audioapi {
15
+ AudioDecoderHostObject::AudioDecoderHostObject(
16
+ jsi::Runtime *runtime,
17
+ const std::shared_ptr<react::CallInvoker> &callInvoker) {
18
+ promiseVendor_ = std::make_shared<PromiseVendor>(runtime, callInvoker);
19
+ addFunctions(
20
+ JSI_EXPORT_FUNCTION(AudioDecoderHostObject, decodeWithPCMInBase64),
21
+ JSI_EXPORT_FUNCTION(AudioDecoderHostObject, decodeWithFilePath),
22
+ JSI_EXPORT_FUNCTION(AudioDecoderHostObject, decodeWithMemoryBlock));
23
+ }
24
+
25
+ JSI_HOST_FUNCTION_IMPL(AudioDecoderHostObject, decodeWithMemoryBlock) {
26
+ auto arrayBuffer = args[0]
27
+ .getObject(runtime)
28
+ .getPropertyAsObject(runtime, "buffer")
29
+ .getArrayBuffer(runtime);
30
+ auto data = arrayBuffer.data(runtime);
31
+ auto size = static_cast<int>(arrayBuffer.size(runtime));
32
+
33
+ auto sampleRate = args[1].getNumber();
34
+
35
+ auto promise = promiseVendor_->createPromise(
36
+ [data, size, sampleRate](std::shared_ptr<Promise> promise) {
37
+ std::thread([data, size, sampleRate, promise = std::move(promise)]() {
38
+ auto result =
39
+ AudioDecoder::decodeWithMemoryBlock(data, size, sampleRate);
40
+
41
+ if (!result) {
42
+ promise->reject("Failed to decode audio data.");
43
+ return;
44
+ }
45
+
46
+ auto audioBufferHostObject =
47
+ std::make_shared<AudioBufferHostObject>(result);
48
+
49
+ promise->resolve([audioBufferHostObject = std::move(
50
+ audioBufferHostObject)](jsi::Runtime &runtime) {
51
+ auto jsiObject = jsi::Object::createFromHostObject(
52
+ runtime, audioBufferHostObject);
53
+ jsiObject.setExternalMemoryPressure(
54
+ runtime, audioBufferHostObject->getSizeInBytes());
55
+ return jsiObject;
56
+ });
57
+ }).detach();
58
+ });
59
+ return promise;
60
+ }
61
+
62
+ JSI_HOST_FUNCTION_IMPL(AudioDecoderHostObject, decodeWithFilePath) {
63
+ auto sourcePath = args[0].getString(runtime).utf8(runtime);
64
+ auto sampleRate = args[1].getNumber();
65
+
66
+ auto promise = promiseVendor_->createPromise(
67
+ [sourcePath, sampleRate](std::shared_ptr<Promise> promise) {
68
+ std::thread([sourcePath, sampleRate, promise = std::move(promise)]() {
69
+ auto result =
70
+ AudioDecoder::decodeWithFilePath(sourcePath, sampleRate);
71
+
72
+ if (!result) {
73
+ promise->reject("Failed to decode audio data source.");
74
+ return;
75
+ }
76
+
77
+ auto audioBufferHostObject =
78
+ std::make_shared<AudioBufferHostObject>(result);
79
+
80
+ promise->resolve([audioBufferHostObject = std::move(
81
+ audioBufferHostObject)](jsi::Runtime &runtime) {
82
+ auto jsiObject = jsi::Object::createFromHostObject(
83
+ runtime, audioBufferHostObject);
84
+ jsiObject.setExternalMemoryPressure(
85
+ runtime, audioBufferHostObject->getSizeInBytes());
86
+ return jsiObject;
87
+ });
88
+ }).detach();
89
+ });
90
+
91
+ return promise;
92
+ }
93
+
94
+ JSI_HOST_FUNCTION_IMPL(AudioDecoderHostObject, decodeWithPCMInBase64) {
95
+ auto b64 = args[0].getString(runtime).utf8(runtime);
96
+ auto inputSampleRate = args[1].getNumber();
97
+ auto inputChannelCount = args[2].getNumber();
98
+ auto interleaved = args[3].getBool();
99
+
100
+ auto promise = promiseVendor_->createPromise(
101
+ [b64, inputSampleRate, inputChannelCount, interleaved](
102
+ std::shared_ptr<Promise> promise) {
103
+ std::thread([b64,
104
+ inputSampleRate,
105
+ inputChannelCount,
106
+ interleaved,
107
+ promise = std::move(promise)]() {
108
+ auto result = AudioDecoder::decodeWithPCMInBase64(
109
+ b64, inputSampleRate, inputChannelCount, interleaved);
110
+
111
+ if (!result) {
112
+ promise->reject("Failed to decode audio data source.");
113
+ return;
114
+ }
115
+
116
+ auto audioBufferHostObject =
117
+ std::make_shared<AudioBufferHostObject>(result);
118
+
119
+ promise->resolve([audioBufferHostObject = std::move(
120
+ audioBufferHostObject)](jsi::Runtime &runtime) {
121
+ auto jsiObject = jsi::Object::createFromHostObject(
122
+ runtime, audioBufferHostObject);
123
+ jsiObject.setExternalMemoryPressure(
124
+ runtime, audioBufferHostObject->getSizeInBytes());
125
+ return jsiObject;
126
+ });
127
+ }).detach();
128
+ });
129
+
130
+ return promise;
131
+ }
132
+
133
+ } // namespace audioapi
@@ -0,0 +1,28 @@
1
+ #pragma once
2
+
3
+ #include <audioapi/HostObjects/sources/AudioBufferHostObject.h>
4
+ #include <audioapi/core/utils/AudioDecoder.h>
5
+ #include <audioapi/jsi/JsiPromise.h>
6
+
7
+ #include <jsi/jsi.h>
8
+ #include <memory>
9
+ #include <string>
10
+ #include <thread>
11
+ #include <utility>
12
+
13
+ namespace audioapi {
14
+ using namespace facebook;
15
+
16
+ class AudioDecoderHostObject : public JsiHostObject {
17
+ public:
18
+ explicit AudioDecoderHostObject(
19
+ jsi::Runtime *runtime,
20
+ const std::shared_ptr<react::CallInvoker> &callInvoker);
21
+ JSI_HOST_FUNCTION_DECL(decodeWithMemoryBlock);
22
+ JSI_HOST_FUNCTION_DECL(decodeWithFilePath);
23
+ JSI_HOST_FUNCTION_DECL(decodeWithPCMInBase64);
24
+
25
+ private:
26
+ std::shared_ptr<PromiseVendor> promiseVendor_;
27
+ };
28
+ } // namespace audioapi
@@ -0,0 +1,58 @@
1
+ #pragma once
2
+
3
+ #include <audioapi/HostObjects/sources/AudioBufferHostObject.h>
4
+ #include <audioapi/HostObjects/utils/AudioStretcherHostObject.h>
5
+ #include <audioapi/core/utils/AudioStretcher.h>
6
+ #include <audioapi/jsi/JsiPromise.h>
7
+
8
+ #include <jsi/jsi.h>
9
+ #include <memory>
10
+ #include <string>
11
+ #include <thread>
12
+ #include <utility>
13
+
14
+ namespace audioapi {
15
+
16
+ AudioStretcherHostObject::AudioStretcherHostObject(
17
+ jsi::Runtime *runtime,
18
+ const std::shared_ptr<react::CallInvoker> &callInvoker) {
19
+ promiseVendor_ = std::make_shared<PromiseVendor>(runtime, callInvoker);
20
+ addFunctions(
21
+ JSI_EXPORT_FUNCTION(AudioStretcherHostObject, changePlaybackSpeed));
22
+ }
23
+
24
+ JSI_HOST_FUNCTION_IMPL(AudioStretcherHostObject, changePlaybackSpeed) {
25
+ auto audioBuffer =
26
+ args[0].getObject(runtime).asHostObject<AudioBufferHostObject>(runtime);
27
+ auto playbackSpeed = static_cast<float>(args[1].asNumber());
28
+
29
+ auto promise = promiseVendor_->createPromise(
30
+ [audioBuffer, playbackSpeed](std::shared_ptr<Promise> promise) {
31
+ std::thread([audioBuffer,
32
+ playbackSpeed,
33
+ promise = std::move(promise)]() {
34
+ auto result = AudioStretcher::changePlaybackSpeed(
35
+ *audioBuffer->audioBuffer_, playbackSpeed);
36
+
37
+ if (!result) {
38
+ promise->reject("Failed to change audio playback speed.");
39
+ return;
40
+ }
41
+
42
+ auto audioBufferHostObject =
43
+ std::make_shared<AudioBufferHostObject>(result);
44
+
45
+ promise->resolve([audioBufferHostObject = std::move(
46
+ audioBufferHostObject)](jsi::Runtime &runtime) {
47
+ auto jsiObject = jsi::Object::createFromHostObject(
48
+ runtime, audioBufferHostObject);
49
+ jsiObject.setExternalMemoryPressure(
50
+ runtime, audioBufferHostObject->getSizeInBytes());
51
+ return jsiObject;
52
+ });
53
+ }).detach();
54
+ });
55
+ return promise;
56
+ }
57
+
58
+ } // namespace audioapi
@@ -0,0 +1,26 @@
1
+ #pragma once
2
+
3
+ #include <audioapi/HostObjects/sources/AudioBufferHostObject.h>
4
+ #include <audioapi/core/utils/AudioStretcher.h>
5
+ #include <audioapi/jsi/JsiPromise.h>
6
+
7
+ #include <jsi/jsi.h>
8
+ #include <memory>
9
+ #include <string>
10
+ #include <thread>
11
+ #include <utility>
12
+
13
+ namespace audioapi {
14
+ using namespace facebook;
15
+
16
+ class AudioStretcherHostObject : public JsiHostObject {
17
+ public:
18
+ explicit AudioStretcherHostObject(
19
+ jsi::Runtime *runtime,
20
+ const std::shared_ptr<react::CallInvoker> &callInvoker);
21
+ JSI_HOST_FUNCTION_DECL(changePlaybackSpeed);
22
+
23
+ private:
24
+ std::shared_ptr<PromiseVendor> promiseVendor_;
25
+ };
26
+ } // namespace audioapi
@@ -6,7 +6,6 @@
6
6
 
7
7
  #include <audioapi/core/AudioContext.h>
8
8
  #include <audioapi/core/destinations/AudioDestinationNode.h>
9
- #include <audioapi/core/utils/AudioDecoder.h>
10
9
  #include <audioapi/core/utils/AudioNodeManager.h>
11
10
 
12
11
  namespace audioapi {
@@ -26,7 +25,6 @@ AudioContext::AudioContext(
26
25
  #endif
27
26
 
28
27
  sampleRate_ = sampleRate;
29
- audioDecoder_ = std::make_shared<AudioDecoder>(sampleRate);
30
28
 
31
29
  if (initSuspended) {
32
30
  playerHasBeenStarted_ = false;
@@ -176,41 +176,6 @@ 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
-
214
179
  AudioNodeManager *BaseAudioContext::getNodeManager() {
215
180
  return nodeManager_.get();
216
181
  }
@@ -3,15 +3,14 @@
3
3
  #include <audioapi/core/types/ContextState.h>
4
4
  #include <audioapi/core/types/OscillatorType.h>
5
5
  #include <audioapi/core/utils/worklets/SafeIncludes.h>
6
-
6
+ #include <cassert>
7
+ #include <complex>
8
+ #include <cstddef>
7
9
  #include <functional>
8
10
  #include <memory>
9
11
  #include <string>
10
12
  #include <utility>
11
13
  #include <vector>
12
- #include <complex>
13
- #include <cstddef>
14
- #include <cassert>
15
14
 
16
15
  namespace audioapi {
17
16
 
@@ -27,7 +26,6 @@ class BiquadFilterNode;
27
26
  class AudioDestinationNode;
28
27
  class AudioBufferSourceNode;
29
28
  class AudioBufferQueueSourceNode;
30
- class AudioDecoder;
31
29
  class AnalyserNode;
32
30
  class AudioEventHandlerRegistry;
33
31
  class IAudioEventHandlerRegistry;
@@ -68,10 +66,6 @@ class BaseAudioContext {
68
66
  int length);
69
67
  std::shared_ptr<AnalyserNode> createAnalyser();
70
68
 
71
- std::shared_ptr<AudioBuffer> decodeAudioDataSource(const std::string &path);
72
- std::shared_ptr<AudioBuffer> decodeAudioData(const void *data, size_t size);
73
- std::shared_ptr<AudioBuffer> decodeWithPCMInBase64(const std::string &data, float playbackSpeed);
74
-
75
69
  std::shared_ptr<PeriodicWave> getBasicWaveForm(OscillatorType type);
76
70
  [[nodiscard]] float getNyquistFrequency() const;
77
71
  AudioNodeManager *getNodeManager();
@@ -85,9 +79,7 @@ class BaseAudioContext {
85
79
 
86
80
  std::shared_ptr<AudioDestinationNode> destination_;
87
81
  // init in AudioContext or OfflineContext constructor
88
- std::shared_ptr<AudioDecoder> audioDecoder_ {};
89
- // init in AudioContext or OfflineContext constructor
90
- float sampleRate_ {};
82
+ float sampleRate_{};
91
83
  ContextState state_ = ContextState::RUNNING;
92
84
  std::shared_ptr<AudioNodeManager> nodeManager_;
93
85
 
@@ -3,7 +3,6 @@
3
3
  #include <audioapi/core/AudioContext.h>
4
4
  #include <audioapi/core/destinations/AudioDestinationNode.h>
5
5
  #include <audioapi/core/sources/AudioBuffer.h>
6
- #include <audioapi/core/utils/AudioDecoder.h>
7
6
  #include <audioapi/core/utils/AudioNodeManager.h>
8
7
  #include <audioapi/core/utils/Constants.h>
9
8
  #include <audioapi/core/utils/Locker.h>
@@ -30,7 +29,6 @@ OfflineAudioContext::OfflineAudioContext(
30
29
  numberOfChannels_(numberOfChannels),
31
30
  currentSampleFrame_(0) {
32
31
  sampleRate_ = sampleRate;
33
- audioDecoder_ = std::make_shared<AudioDecoder>(sampleRate_);
34
32
  resultBus_ = std::make_shared<AudioBus>(
35
33
  static_cast<int>(length_), numberOfChannels_, sampleRate_);
36
34
  }
@@ -27,10 +27,6 @@ AudioBufferBaseSourceNode::AudioBufferBaseSourceNode(
27
27
  std::make_shared<signalsmith::stretch::SignalsmithStretch<float>>();
28
28
  }
29
29
 
30
- AudioBufferBaseSourceNode::~AudioBufferBaseSourceNode() {
31
- clearOnPositionChangedCallback();
32
- }
33
-
34
30
  std::shared_ptr<AudioParam> AudioBufferBaseSourceNode::getDetuneParam() const {
35
31
  return detuneParam_;
36
32
  }
@@ -15,7 +15,6 @@ class AudioParam;
15
15
  class AudioBufferBaseSourceNode : public AudioScheduledSourceNode {
16
16
  public:
17
17
  explicit AudioBufferBaseSourceNode(BaseAudioContext *context, bool pitchCorrection);
18
- ~AudioBufferBaseSourceNode() override;
19
18
 
20
19
  [[nodiscard]] std::shared_ptr<AudioParam> getDetuneParam() const;
21
20
  [[nodiscard]] std::shared_ptr<AudioParam> getPlaybackRateParam() const;
@@ -29,8 +29,6 @@ AudioBufferSourceNode::~AudioBufferSourceNode() {
29
29
 
30
30
  buffer_.reset();
31
31
  alignedBus_.reset();
32
-
33
- clearOnLoopEndedCallback();
34
32
  }
35
33
 
36
34
  bool AudioBufferSourceNode::getLoop() const {
@@ -16,10 +16,6 @@ AudioScheduledSourceNode::AudioScheduledSourceNode(BaseAudioContext *context)
16
16
  numberOfInputs_ = 0;
17
17
  }
18
18
 
19
- AudioScheduledSourceNode::~AudioScheduledSourceNode() {
20
- clearOnEndedCallback();
21
- }
22
-
23
19
  void AudioScheduledSourceNode::start(double when) {
24
20
  playbackState_ = PlaybackState::SCHEDULED;
25
21
  startTime_ = when;
@@ -27,7 +27,6 @@ class AudioScheduledSourceNode : public AudioNode {
27
27
  // FINISHED: The node has finished playing.
28
28
  enum class PlaybackState { UNSCHEDULED, SCHEDULED, PLAYING, STOP_SCHEDULED, FINISHED };
29
29
  explicit AudioScheduledSourceNode(BaseAudioContext *context);
30
- ~AudioScheduledSourceNode() override;
31
30
 
32
31
  void start(double when);
33
32
  virtual void stop(double when);
@@ -0,0 +1,16 @@
1
+ #pragma once
2
+
3
+ namespace audioapi {
4
+
5
+ enum class AudioFormat {
6
+ UNKNOWN,
7
+ WAV,
8
+ OGG,
9
+ FLAC,
10
+ AAC,
11
+ MP3,
12
+ M4A,
13
+ MP4,
14
+ MOV
15
+ };
16
+ } // namespace audioapi
@@ -1,124 +1,67 @@
1
1
  #pragma once
2
2
 
3
- #include <audioapi/libs/audio-stretch/stretch.h>
3
+ #include <audioapi/core/types/AudioFormat.h>
4
4
  #include <audioapi/libs/miniaudio/miniaudio.h>
5
+ #include <algorithm>
6
+ #include <cstring>
5
7
  #include <memory>
6
8
  #include <string>
7
9
  #include <vector>
8
- #include <cstring>
9
- #include <algorithm>
10
10
 
11
11
  namespace audioapi {
12
12
 
13
- enum class AudioFormat {
14
- UNKNOWN,
15
- WAV,
16
- OGG,
17
- FLAC,
18
- AAC,
19
- MP3,
20
- M4A,
21
- MP4,
22
- MOV
23
- };
24
-
25
- class AudioBus;
13
+ class AudioBuffer;
26
14
 
27
15
  static constexpr int CHUNK_SIZE = 4096;
28
16
 
29
17
  class AudioDecoder {
30
18
  public:
31
- explicit AudioDecoder(float sampleRate) : sampleRate_(sampleRate) {}
19
+ AudioDecoder() = delete;
32
20
 
33
- [[nodiscard]] std::shared_ptr<AudioBus> decodeWithFilePath(
34
- const std::string &path) const;
35
- [[nodiscard]] std::shared_ptr<AudioBus> decodeWithMemoryBlock(
36
- const void *data,
37
- size_t size) const;
38
- [[nodiscard]] std::shared_ptr<AudioBus> decodeWithPCMInBase64(
39
- const std::string &data,
40
- float playbackSpeed) const;
21
+ [[nodiscard]] static std::shared_ptr<AudioBuffer> decodeWithFilePath(const std::string &path, float sampleRate);
22
+ [[nodiscard]] static std::shared_ptr<AudioBuffer>
23
+ decodeWithMemoryBlock(const void *data, size_t size, float sampleRate);
24
+ [[nodiscard]] static std::shared_ptr<AudioBuffer>
25
+ decodeWithPCMInBase64(const std::string &data, float inputSampleRate, int inputChannelCount, bool interleaved);
41
26
 
42
27
  private:
43
- float sampleRate_;
44
- int numChannels_ = 2;
45
-
46
- static std::vector<int16_t> readAllPcmFrames(
47
- ma_decoder &decoder,
48
- int numChannels,
49
- ma_uint64 &outFramesRead);
50
- static std::shared_ptr<AudioBus> makeAudioBusFromInt16Buffer(
51
- const std::vector<int16_t> &buffer,
52
- int numChannels,
53
- float sampleRate);
54
-
55
- void changePlaybackSpeedIfNeeded(
56
- std::vector<int16_t> &buffer,
57
- size_t framesDecoded,
58
- int numChannels,
59
- float playbackSpeed) const {
60
- if (playbackSpeed == 1.0f) {
61
- return;
62
- }
63
-
64
- auto stretcher = stretch_init(
65
- static_cast<int>(sampleRate_ / 333.0f),
66
- static_cast<int>(sampleRate_ / 55.0f),
67
- numChannels,
68
- 0x1);
28
+ static std::vector<float> readAllPcmFrames(ma_decoder &decoder, int outputChannels);
29
+ static std::shared_ptr<AudioBuffer>
30
+ makeAudioBufferFromFloatBuffer(const std::vector<float> &buffer, float outputSampleRate, int outputChannels);
69
31
 
70
- int maxOutputFrames = stretch_output_capacity(
71
- stretcher, static_cast<int>(framesDecoded), 1 / playbackSpeed);
72
- std::vector<int16_t> stretchedBuffer(maxOutputFrames);
73
-
74
- int outputFrames = stretch_samples(
75
- stretcher,
76
- buffer.data(),
77
- static_cast<int>(framesDecoded),
78
- stretchedBuffer.data(),
79
- 1 / playbackSpeed);
80
-
81
- outputFrames +=
82
- stretch_flush(stretcher, stretchedBuffer.data() + (outputFrames));
83
- stretchedBuffer.resize(outputFrames);
84
-
85
- buffer = stretchedBuffer;
86
-
87
- stretch_deinit(stretcher);
88
- }
89
-
90
- static AudioFormat detectAudioFormat(const void* data, size_t size) {
91
- if (size < 12) return AudioFormat::UNKNOWN;
92
- const auto* bytes = static_cast<const unsigned char*>(data);
32
+ static AudioFormat detectAudioFormat(const void *data, size_t size) {
33
+ if (size < 12)
34
+ return AudioFormat::UNKNOWN;
35
+ const auto *bytes = static_cast<const unsigned char *>(data);
93
36
 
94
37
  // WAV/RIFF
95
38
  if (std::memcmp(bytes, "RIFF", 4) == 0 && std::memcmp(bytes + 8, "WAVE", 4) == 0)
96
- return AudioFormat::WAV;
39
+ return AudioFormat::WAV;
97
40
 
98
41
  // OGG
99
42
  if (std::memcmp(bytes, "OggS", 4) == 0)
100
- return AudioFormat::OGG;
43
+ return AudioFormat::OGG;
101
44
 
102
45
  // FLAC
103
46
  if (std::memcmp(bytes, "fLaC", 4) == 0)
104
- return AudioFormat::FLAC;
47
+ return AudioFormat::FLAC;
105
48
 
106
49
  // AAC starts with 0xFF 0xF1 or 0xFF 0xF9
107
50
  if (bytes[0] == 0xFF && (bytes[1] & 0xF6) == 0xF0)
108
- return AudioFormat::AAC;
51
+ return AudioFormat::AAC;
109
52
 
110
53
  // MP3: "ID3" or 11-bit frame sync (0xFF 0xE0)
111
54
  if (std::memcmp(bytes, "ID3", 3) == 0)
112
- return AudioFormat::MP3;
55
+ return AudioFormat::MP3;
113
56
  if (bytes[0] == 0xFF && (bytes[1] & 0xE0) == 0xE0)
114
- return AudioFormat::MP3;
57
+ return AudioFormat::MP3;
115
58
 
116
59
  if (std::memcmp(bytes + 4, "ftyp", 4) == 0) {
117
- if (std::memcmp(bytes + 8, "M4A ", 4) == 0)
118
- return AudioFormat::M4A;
119
- else if (std::memcmp(bytes + 8, "qt ", 4) == 0)
120
- return AudioFormat::MOV;
121
- return AudioFormat::MP4;
60
+ if (std::memcmp(bytes + 8, "M4A ", 4) == 0)
61
+ return AudioFormat::M4A;
62
+ else if (std::memcmp(bytes + 8, "qt ", 4) == 0)
63
+ return AudioFormat::MOV;
64
+ return AudioFormat::MP4;
122
65
  }
123
66
  return AudioFormat::UNKNOWN;
124
67
  }
@@ -126,19 +69,21 @@ class AudioDecoder {
126
69
  static inline bool pathHasExtension(const std::string &path, const std::vector<std::string> &extensions) {
127
70
  std::string pathLower = path;
128
71
  std::transform(pathLower.begin(), pathLower.end(), pathLower.begin(), ::tolower);
129
- for (const auto& ext : extensions) {
130
- if (pathLower.ends_with(ext))
131
- return true;
72
+ for (const auto &ext : extensions) {
73
+ if (pathLower.ends_with(ext))
74
+ return true;
132
75
  }
133
76
  return false;
134
77
  }
135
78
 
136
-
137
79
  [[nodiscard]] static inline int16_t floatToInt16(float sample) {
138
- return static_cast<int16_t>(sample * 32768.0f);
80
+ return static_cast<int16_t>(sample * INT16_MAX);
139
81
  }
140
82
  [[nodiscard]] static inline float int16ToFloat(int16_t sample) {
141
- return static_cast<float>(sample) / 32768.0f;
83
+ return static_cast<float>(sample) / INT16_MAX;
84
+ }
85
+ [[nodiscard]] static inline float uint8ToFloat(uint8_t byte1, uint8_t byte2) {
86
+ return static_cast<float>(static_cast<int16_t>((byte2 << 8) | byte1)) / INT16_MAX;
142
87
  }
143
88
  };
144
89