react-native-audio-api 0.2.0 → 0.3.0-rc2

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 (84) hide show
  1. package/android/CMakeLists.txt +2 -2
  2. package/android/build.gradle +1 -3
  3. package/android/libs/include/miniaudio.h +92621 -0
  4. package/android/src/main/cpp/AudioAPIInstaller/AudioAPIInstaller.cpp +8 -4
  5. package/android/src/main/cpp/AudioAPIInstaller/AudioAPIInstaller.h +16 -7
  6. package/android/src/main/cpp/AudioDecoder/AudioDecoder.cpp +64 -0
  7. package/android/src/main/cpp/AudioDecoder/AudioDecoder.h +21 -0
  8. package/android/src/main/cpp/AudioPlayer/AudioPlayer.cpp +16 -7
  9. package/android/src/main/cpp/AudioPlayer/AudioPlayer.h +5 -4
  10. package/android/src/main/java/com/swmansion/audioapi/module/AudioAPIInstaller.kt +14 -4
  11. package/android/src/main/java/com/swmansion/audioapi/nativemodules/AudioAPIModule.kt +2 -3
  12. package/common/cpp/AudioAPIInstaller/AudioAPIInstallerHostObject.cpp +9 -3
  13. package/common/cpp/AudioAPIInstaller/AudioAPIInstallerHostObject.h +13 -7
  14. package/common/cpp/HostObjects/AudioBufferHostObject.cpp +7 -0
  15. package/common/cpp/HostObjects/AudioContextHostObject.cpp +3 -2
  16. package/common/cpp/HostObjects/AudioContextHostObject.h +6 -3
  17. package/common/cpp/HostObjects/BaseAudioContextHostObject.cpp +38 -2
  18. package/common/cpp/HostObjects/BaseAudioContextHostObject.h +4 -1
  19. package/common/cpp/core/AudioArray.cpp +28 -14
  20. package/common/cpp/core/AudioArray.h +20 -14
  21. package/common/cpp/core/AudioBuffer.cpp +14 -11
  22. package/common/cpp/core/AudioBuffer.h +1 -0
  23. package/common/cpp/core/AudioBufferSourceNode.cpp +29 -19
  24. package/common/cpp/core/AudioBufferSourceNode.h +1 -1
  25. package/common/cpp/core/AudioBus.cpp +276 -115
  26. package/common/cpp/core/AudioBus.h +29 -9
  27. package/common/cpp/core/AudioContext.cpp +5 -9
  28. package/common/cpp/core/AudioDestinationNode.cpp +11 -8
  29. package/common/cpp/core/AudioDestinationNode.h +4 -4
  30. package/common/cpp/core/AudioNode.cpp +25 -17
  31. package/common/cpp/core/AudioNode.h +5 -5
  32. package/common/cpp/core/AudioNodeManager.cpp +10 -7
  33. package/common/cpp/core/AudioNodeManager.h +11 -4
  34. package/common/cpp/core/AudioScheduledSourceNode.cpp +2 -2
  35. package/common/cpp/core/BaseAudioContext.cpp +49 -12
  36. package/common/cpp/core/BaseAudioContext.h +16 -7
  37. package/common/cpp/core/BiquadFilterNode.cpp +5 -3
  38. package/common/cpp/core/GainNode.cpp +1 -1
  39. package/common/cpp/core/OscillatorNode.cpp +4 -4
  40. package/common/cpp/core/OscillatorNode.h +2 -2
  41. package/common/cpp/core/StereoPannerNode.cpp +10 -7
  42. package/common/cpp/core/StereoPannerNode.h +1 -1
  43. package/common/cpp/utils/FFTFrame.h +5 -1
  44. package/common/cpp/utils/JsiPromise.cpp +64 -0
  45. package/common/cpp/utils/JsiPromise.h +48 -0
  46. package/common/cpp/utils/Locker.h +8 -6
  47. package/common/cpp/utils/VectorMath.cpp +71 -55
  48. package/common/cpp/utils/android/FFTFrame.cpp +12 -11
  49. package/common/cpp/utils/ios/FFTFrame.cpp +6 -1
  50. package/common/cpp/wrappers/BaseAudioContextWrapper.cpp +7 -0
  51. package/common/cpp/wrappers/BaseAudioContextWrapper.h +2 -0
  52. package/ios/AudioAPIModule.mm +4 -1
  53. package/ios/AudioDecoder/AudioDecoder.h +17 -0
  54. package/ios/AudioDecoder/AudioDecoder.m +80 -0
  55. package/ios/AudioDecoder/IOSAudioDecoder.h +28 -0
  56. package/ios/AudioDecoder/IOSAudioDecoder.mm +46 -0
  57. package/ios/AudioPlayer/AudioPlayer.h +1 -1
  58. package/ios/AudioPlayer/AudioPlayer.m +2 -2
  59. package/ios/AudioPlayer/IOSAudioPlayer.h +5 -5
  60. package/ios/AudioPlayer/IOSAudioPlayer.mm +4 -3
  61. package/lib/module/core/BaseAudioContext.js +4 -0
  62. package/lib/module/core/BaseAudioContext.js.map +1 -1
  63. package/lib/module/index.js +232 -17
  64. package/lib/module/index.js.map +1 -1
  65. package/lib/module/index.native.js +18 -0
  66. package/lib/module/index.native.js.map +1 -0
  67. package/lib/typescript/core/BaseAudioContext.d.ts +1 -0
  68. package/lib/typescript/core/BaseAudioContext.d.ts.map +1 -1
  69. package/lib/typescript/index.d.ts +100 -13
  70. package/lib/typescript/index.d.ts.map +1 -1
  71. package/lib/typescript/index.native.d.ts +14 -0
  72. package/lib/typescript/index.native.d.ts.map +1 -0
  73. package/lib/typescript/interfaces.d.ts +1 -0
  74. package/lib/typescript/interfaces.d.ts.map +1 -1
  75. package/package.json +4 -2
  76. package/src/core/BaseAudioContext.ts +6 -0
  77. package/src/index.native.ts +25 -0
  78. package/src/index.ts +403 -19
  79. package/src/interfaces.ts +1 -0
  80. package/android/libs/fftw3/x86/libfftw3.a +0 -0
  81. package/android/libs/fftw3/x86_64/libfftw3.a +0 -0
  82. /package/android/libs/{fftw3/arm64-v8a → arm64-v8a}/libfftw3.a +0 -0
  83. /package/android/libs/{fftw3/armeabi-v7a → armeabi-v7a}/libfftw3.a +0 -0
  84. /package/android/libs/include/{fftw3/fftw3.h → fftw3.h} +0 -0
@@ -1,9 +1,9 @@
1
+ #include "AudioDestinationNode.h"
1
2
  #include "AudioBus.h"
2
3
  #include "AudioNode.h"
3
- #include "VectorMath.h"
4
4
  #include "AudioNodeManager.h"
5
5
  #include "BaseAudioContext.h"
6
- #include "AudioDestinationNode.h"
6
+ #include "VectorMath.h"
7
7
 
8
8
  namespace audioapi {
9
9
 
@@ -23,15 +23,18 @@ double AudioDestinationNode::getCurrentTime() const {
23
23
  return static_cast<double>(currentSampleFrame_) / context_->getSampleRate();
24
24
  }
25
25
 
26
- void AudioDestinationNode::renderAudio(AudioBus *destinationBus, int32_t numFrames) {
27
- context_->getNodeManager()->preProcessGraph();
28
- destinationBus->zero();
29
-
30
- if (!numFrames) {
26
+ void AudioDestinationNode::renderAudio(
27
+ AudioBus *destinationBus,
28
+ int32_t numFrames) {
29
+ if (!numFrames || !destinationBus || !isInitialized_) {
31
30
  return;
32
31
  }
33
32
 
34
- AudioBus* processedBus = processAudio(destinationBus, numFrames);
33
+ context_->getNodeManager()->preProcessGraph();
34
+
35
+ destinationBus->zero();
36
+
37
+ AudioBus *processedBus = processAudio(destinationBus, numFrames);
35
38
 
36
39
  if (processedBus && processedBus != destinationBus) {
37
40
  destinationBus->copy(processedBus);
@@ -1,8 +1,8 @@
1
1
  #pragma once
2
2
 
3
- #include <vector>
4
- #include <memory>
5
3
  #include <algorithm>
4
+ #include <memory>
5
+ #include <vector>
6
6
 
7
7
  #include "AudioNode.h"
8
8
 
@@ -15,7 +15,7 @@ class AudioDestinationNode : public AudioNode {
15
15
  public:
16
16
  explicit AudioDestinationNode(BaseAudioContext *context);
17
17
 
18
- void renderAudio(AudioBus* audioData, int32_t numFrames);
18
+ void renderAudio(AudioBus *audioData, int32_t numFrames);
19
19
 
20
20
  std::size_t getCurrentSampleFrame() const;
21
21
  double getCurrentTime() const;
@@ -23,7 +23,7 @@ class AudioDestinationNode : public AudioNode {
23
23
  protected:
24
24
  // DestinationNode is triggered by AudioContext using renderAudio
25
25
  // processNode function is not necessary and is never called.
26
- void processNode(AudioBus*, int) final { };
26
+ void processNode(AudioBus *, int) final{};
27
27
 
28
28
  private:
29
29
  std::size_t currentSampleFrame_;
@@ -2,13 +2,16 @@
2
2
 
3
3
  #include "AudioBus.h"
4
4
  #include "AudioNode.h"
5
- #include "BaseAudioContext.h"
6
5
  #include "AudioNodeManager.h"
6
+ #include "BaseAudioContext.h"
7
7
 
8
8
  namespace audioapi {
9
9
 
10
10
  AudioNode::AudioNode(BaseAudioContext *context) : context_(context) {
11
- audioBus_ = std::make_shared<AudioBus>(context->getSampleRate(), context->getBufferSizeInFrames(), channelCount_);
11
+ audioBus_ = std::make_shared<AudioBus>(
12
+ context->getSampleRate(),
13
+ context->getBufferSizeInFrames(),
14
+ channelCount_);
12
15
  }
13
16
 
14
17
  AudioNode::~AudioNode() {
@@ -37,7 +40,8 @@ std::string AudioNode::getChannelInterpretation() const {
37
40
  }
38
41
 
39
42
  void AudioNode::connect(const std::shared_ptr<AudioNode> &node) {
40
- context_->getNodeManager()->addPendingConnection(shared_from_this(), node, AudioNodeManager::ConnectionType::CONNECT);
43
+ context_->getNodeManager()->addPendingConnection(
44
+ shared_from_this(), node, AudioNodeManager::ConnectionType::CONNECT);
41
45
  }
42
46
 
43
47
  void AudioNode::connectNode(const std::shared_ptr<AudioNode> &node) {
@@ -46,7 +50,8 @@ void AudioNode::connectNode(const std::shared_ptr<AudioNode> &node) {
46
50
  }
47
51
 
48
52
  void AudioNode::disconnect(const std::shared_ptr<AudioNode> &node) {
49
- context_->getNodeManager()->addPendingConnection(shared_from_this(), node, AudioNodeManager::ConnectionType::DISCONNECT);
53
+ context_->getNodeManager()->addPendingConnection(
54
+ shared_from_this(), node, AudioNodeManager::ConnectionType::DISCONNECT);
50
55
  }
51
56
 
52
57
  void AudioNode::disconnectNode(const std::shared_ptr<AudioNode> &node) {
@@ -103,7 +108,7 @@ std::string AudioNode::toString(ChannelInterpretation interpretation) {
103
108
  }
104
109
  }
105
110
 
106
- AudioBus* AudioNode::processAudio(AudioBus* outputBus, int framesToProcess) {
111
+ AudioBus *AudioNode::processAudio(AudioBus *outputBus, int framesToProcess) {
107
112
  if (!isInitialized_) {
108
113
  return outputBus;
109
114
  }
@@ -114,10 +119,14 @@ AudioBus* AudioNode::processAudio(AudioBus* outputBus, int framesToProcess) {
114
119
  bool isAlreadyProcessed = currentSampleFrame == lastRenderedFrame_;
115
120
 
116
121
  // Node can't use output bus if:
117
- // - outputBus is not provided, which means that next node is doing a multi-node summing.
118
- // - it has more than one input, which means that it has to sum all inputs using internal bus.
119
- // - it has more than one output, so each output node can get the processed data without re-calculating the node.
120
- bool canUseOutputBus = outputBus != 0 && inputNodes_.size() < 2 && outputNodes_.size() < 2;
122
+ // - outputBus is not provided, which means that next node is doing a
123
+ // multi-node summing.
124
+ // - it has more than one input, which means that it has to sum all inputs
125
+ // using internal bus.
126
+ // - it has more than one output, so each output node can get the processed
127
+ // data without re-calculating the node.
128
+ bool canUseOutputBus =
129
+ outputBus != 0 && inputNodes_.size() < 2 && outputNodes_.size() < 2;
121
130
 
122
131
  if (isAlreadyProcessed) {
123
132
  // If it was already processed in the rendering quantum, return it.
@@ -127,7 +136,7 @@ AudioBus* AudioNode::processAudio(AudioBus* outputBus, int framesToProcess) {
127
136
  // Update the last rendered frame before processing node and its inputs.
128
137
  lastRenderedFrame_ = currentSampleFrame;
129
138
 
130
- AudioBus* processingBus = canUseOutputBus ? outputBus : audioBus_.get();
139
+ AudioBus *processingBus = canUseOutputBus ? outputBus : audioBus_.get();
131
140
 
132
141
  if (!canUseOutputBus) {
133
142
  // Clear the bus before summing all connected nodes.
@@ -135,8 +144,8 @@ AudioBus* AudioNode::processAudio(AudioBus* outputBus, int framesToProcess) {
135
144
  }
136
145
 
137
146
  if (inputNodes_.empty()) {
138
- // If there are no connected inputs, process the node just to advance the audio params.
139
- // The node will output silence anyway.
147
+ // If there are no connected inputs, process the node just to advance the
148
+ // audio params. The node will output silence anyway.
140
149
  processNode(processingBus, framesToProcess);
141
150
  return processingBus;
142
151
  }
@@ -146,17 +155,17 @@ AudioBus* AudioNode::processAudio(AudioBus* outputBus, int framesToProcess) {
146
155
  continue;
147
156
  }
148
157
 
149
- // Process first connected node, it can be directly connected to the processingBus,
150
- // resulting in one less summing operation.
158
+ // Process first connected node, it can be directly connected to the
159
+ // processingBus, resulting in one less summing operation.
151
160
  if (it == inputNodes_.begin()) {
152
- AudioBus* inputBus = (*it)->processAudio(processingBus, framesToProcess);
161
+ AudioBus *inputBus = (*it)->processAudio(processingBus, framesToProcess);
153
162
 
154
163
  if (inputBus != processingBus) {
155
164
  processingBus->sum(inputBus);
156
165
  }
157
166
  } else {
158
167
  // Enforce the summing to be done using the internal bus.
159
- AudioBus* inputBus = (*it)->processAudio(0, framesToProcess);
168
+ AudioBus *inputBus = (*it)->processAudio(0, framesToProcess);
160
169
  if (inputBus) {
161
170
  processingBus->sum(inputBus);
162
171
  }
@@ -205,7 +214,6 @@ void AudioNode::onInputDisconnected(AudioNode *node) {
205
214
  inputNodes_.erase(position);
206
215
  }
207
216
 
208
-
209
217
  if (inputNodes_.size() > 0) {
210
218
  return;
211
219
  }
@@ -4,9 +4,9 @@
4
4
  #include <string>
5
5
  #include <vector>
6
6
 
7
- #include "Constants.h"
8
7
  #include "ChannelCountMode.h"
9
8
  #include "ChannelInterpretation.h"
9
+ #include "Constants.h"
10
10
 
11
11
  namespace audioapi {
12
12
 
@@ -45,13 +45,13 @@ class AudioNode : public std::enable_shared_from_this<AudioNode> {
45
45
  bool isInitialized_ = false;
46
46
  bool isEnabled_ = true;
47
47
 
48
- std::size_t lastRenderedFrame_ { SIZE_MAX };
48
+ std::size_t lastRenderedFrame_{SIZE_MAX};
49
49
 
50
50
  ChannelCountMode channelCountMode_ = ChannelCountMode::MAX;
51
51
  ChannelInterpretation channelInterpretation_ =
52
52
  ChannelInterpretation::SPEAKERS;
53
53
 
54
- std::vector<AudioNode*> inputNodes_ = {};
54
+ std::vector<AudioNode *> inputNodes_ = {};
55
55
  std::vector<std::shared_ptr<AudioNode>> outputNodes_ = {};
56
56
 
57
57
  private:
@@ -59,8 +59,8 @@ class AudioNode : public std::enable_shared_from_this<AudioNode> {
59
59
  static std::string toString(ChannelInterpretation interpretation);
60
60
 
61
61
  void cleanup();
62
- AudioBus* processAudio(AudioBus* outputBus, int framesToProcess);
63
- virtual void processNode(AudioBus* processingBus, int framesToProcess) = 0;
62
+ AudioBus *processAudio(AudioBus *outputBus, int framesToProcess);
63
+ virtual void processNode(AudioBus *processingBus, int framesToProcess) = 0;
64
64
 
65
65
  void connectNode(const std::shared_ptr<AudioNode> &node);
66
66
  void disconnectNode(const std::shared_ptr<AudioNode> &node);
@@ -1,7 +1,7 @@
1
1
 
2
- #include "Locker.h"
3
- #include "AudioNode.h"
4
2
  #include "AudioNodeManager.h"
3
+ #include "AudioNode.h"
4
+ #include "Locker.h"
5
5
 
6
6
  namespace audioapi {
7
7
 
@@ -12,7 +12,10 @@ AudioNodeManager::~AudioNodeManager() {
12
12
  sourceNodes_.clear();
13
13
  }
14
14
 
15
- void AudioNodeManager::addPendingConnection(const std::shared_ptr<AudioNode> &from, const std::shared_ptr<AudioNode> &to, ConnectionType type) {
15
+ void AudioNodeManager::addPendingConnection(
16
+ const std::shared_ptr<AudioNode> &from,
17
+ const std::shared_ptr<AudioNode> &to,
18
+ ConnectionType type) {
16
19
  Locker lock(getGraphLock());
17
20
 
18
21
  audioNodesToConnect_.push_back(std::make_tuple(from, to, type));
@@ -25,7 +28,7 @@ void AudioNodeManager::addSourceNode(const std::shared_ptr<AudioNode> &node) {
25
28
  }
26
29
 
27
30
  void AudioNodeManager::preProcessGraph() {
28
- if (!Locker::tryLock(getGraphLock())) {
31
+ if (!Locker::tryLock(getGraphLock())) {
29
32
  return;
30
33
  }
31
34
 
@@ -33,12 +36,12 @@ void AudioNodeManager::preProcessGraph() {
33
36
  removeFinishedSourceNodes();
34
37
  }
35
38
 
36
- std::mutex& AudioNodeManager::getGraphLock() {
39
+ std::mutex &AudioNodeManager::getGraphLock() {
37
40
  return graphLock_;
38
41
  }
39
42
 
40
43
  void AudioNodeManager::settlePendingConnections() {
41
- for (auto& connection : audioNodesToConnect_) {
44
+ for (auto &connection : audioNodesToConnect_) {
42
45
  std::shared_ptr<AudioNode> from = std::get<0>(connection);
43
46
  std::shared_ptr<AudioNode> to = std::get<1>(connection);
44
47
  ConnectionType type = std::get<2>(connection);
@@ -58,7 +61,7 @@ void AudioNodeManager::removeFinishedSourceNodes() {
58
61
  auto currentNode = it->get();
59
62
  // Release the source node if use count is equal to 1 (this vector)
60
63
  if (!currentNode->isEnabled() && it->use_count() == 1) {
61
- for (auto& outputNode : currentNode->outputNodes_) {
64
+ for (auto &outputNode : currentNode->outputNodes_) {
62
65
  currentNode->disconnectNode(outputNode);
63
66
  }
64
67
 
@@ -1,8 +1,8 @@
1
1
  #pragma once
2
2
 
3
+ #include <memory>
3
4
  #include <mutex>
4
5
  #include <tuple>
5
- #include <memory>
6
6
  #include <vector>
7
7
 
8
8
  namespace audioapi {
@@ -16,17 +16,24 @@ class AudioNodeManager {
16
16
  ~AudioNodeManager();
17
17
 
18
18
  void preProcessGraph();
19
- void addPendingConnection(const std::shared_ptr<AudioNode> &from, const std::shared_ptr<AudioNode> &to, ConnectionType type);
19
+ void addPendingConnection(
20
+ const std::shared_ptr<AudioNode> &from,
21
+ const std::shared_ptr<AudioNode> &to,
22
+ ConnectionType type);
20
23
 
21
24
  void addSourceNode(const std::shared_ptr<AudioNode> &node);
22
25
 
23
- std::mutex& getGraphLock();
26
+ std::mutex &getGraphLock();
24
27
 
25
28
  private:
26
29
  std::mutex graphLock_;
27
30
 
28
31
  std::vector<std::shared_ptr<AudioNode>> sourceNodes_;
29
- std::vector<std::tuple<std::shared_ptr<AudioNode>, std::shared_ptr<AudioNode>, ConnectionType>> audioNodesToConnect_;
32
+ std::vector<std::tuple<
33
+ std::shared_ptr<AudioNode>,
34
+ std::shared_ptr<AudioNode>,
35
+ ConnectionType>>
36
+ audioNodesToConnect_;
30
37
 
31
38
  void settlePendingConnections();
32
39
  void removeFinishedSourceNodes();
@@ -1,6 +1,6 @@
1
- #include "BaseAudioContext.h"
2
- #include "AudioNodeManager.h"
3
1
  #include "AudioScheduledSourceNode.h"
2
+ #include "AudioNodeManager.h"
3
+ #include "BaseAudioContext.h"
4
4
 
5
5
  namespace audioapi {
6
6
 
@@ -1,40 +1,53 @@
1
1
  #ifdef ANDROID
2
+ #include "AudioDecoder.h"
2
3
  #include "AudioPlayer.h"
3
4
  #else
5
+ #include "IOSAudioDecoder.h"
4
6
  #include "IOSAudioPlayer.h"
5
7
  #endif
6
8
 
7
9
  #include "BaseAudioContext.h"
8
10
 
9
- #include "GainNode.h"
10
- #include "AudioBus.h"
11
11
  #include "AudioArray.h"
12
12
  #include "AudioBuffer.h"
13
+ #include "AudioBufferSourceNode.h"
14
+ #include "AudioBus.h"
15
+ #include "AudioDestinationNode.h"
16
+ #include "AudioNodeManager.h"
17
+ #include "BiquadFilterNode.h"
13
18
  #include "ContextState.h"
19
+ #include "GainNode.h"
14
20
  #include "OscillatorNode.h"
15
21
  #include "StereoPannerNode.h"
16
- #include "BiquadFilterNode.h"
17
- #include "AudioNodeManager.h"
18
- #include "AudioDestinationNode.h"
19
- #include "AudioBufferSourceNode.h"
20
22
 
21
23
  namespace audioapi {
22
24
 
23
25
  BaseAudioContext::BaseAudioContext() {
24
26
  #ifdef ANDROID
25
27
  audioPlayer_ = std::make_shared<AudioPlayer>(this->renderAudio());
28
+ audioDecoder_ = std::make_shared<AudioDecoder>(audioPlayer_->getSampleRate());
26
29
  #else
27
30
  audioPlayer_ = std::make_shared<IOSAudioPlayer>(this->renderAudio());
31
+ audioDecoder_ =
32
+ std::make_shared<IOSAudioDecoder>(audioPlayer_->getSampleRate());
28
33
  #endif
29
34
 
30
35
  sampleRate_ = audioPlayer_->getSampleRate();
31
36
  bufferSizeInFrames_ = audioPlayer_->getBufferSizeInFrames();
32
37
 
33
- audioPlayer_->start();
34
38
  nodeManager_ = std::make_shared<AudioNodeManager>();
35
39
  destination_ = std::make_shared<AudioDestinationNode>(this);
36
40
  }
37
41
 
42
+ BaseAudioContext::~BaseAudioContext() {
43
+ if (isRunning()) {
44
+ return;
45
+ }
46
+
47
+ state_ = ContextState::CLOSED;
48
+ audioPlayer_->stop();
49
+ }
50
+
38
51
  std::string BaseAudioContext::getState() {
39
52
  return BaseAudioContext::toString(state_);
40
53
  }
@@ -95,20 +108,42 @@ std::shared_ptr<PeriodicWave> BaseAudioContext::createPeriodicWave(
95
108
  sampleRate_, real, imag, length, disableNormalization);
96
109
  }
97
110
 
111
+ #ifdef ANDROID
112
+ std::shared_ptr<AudioBuffer> BaseAudioContext::decodeAudioDataSource(
113
+ const std::string &path) {
114
+ auto audioBus = audioDecoder_->decodeWithFilePath(path);
115
+ return std::make_shared<AudioBuffer>(audioBus);
116
+ }
117
+ #else
118
+ std::shared_ptr<AudioBuffer> BaseAudioContext::decodeAudioDataSource(
119
+ const std::string &path) {
120
+ auto audioBus = audioDecoder_->decodeWithFilePath(path);
121
+ return std::make_shared<AudioBuffer>(audioBus);
122
+ }
123
+ #endif
124
+
98
125
  std::function<void(AudioBus *, int)> BaseAudioContext::renderAudio() {
99
- if (state_ == ContextState::CLOSED) {
126
+ if (!isRunning()) {
100
127
  return [](AudioBus *, int) {};
101
128
  }
102
129
 
103
- return [this](AudioBus* data, int frames) {
130
+ return [this](AudioBus *data, int frames) {
104
131
  destination_->renderAudio(data, frames);
105
132
  };
106
133
  }
107
134
 
108
- AudioNodeManager* BaseAudioContext::getNodeManager() {
135
+ AudioNodeManager *BaseAudioContext::getNodeManager() {
109
136
  return nodeManager_.get();
110
137
  }
111
138
 
139
+ bool BaseAudioContext::isRunning() const {
140
+ return state_ == ContextState::RUNNING;
141
+ }
142
+
143
+ bool BaseAudioContext::isClosed() const {
144
+ return state_ == ContextState::CLOSED;
145
+ }
146
+
112
147
  std::string BaseAudioContext::toString(ContextState state) {
113
148
  switch (state) {
114
149
  case ContextState::SUSPENDED:
@@ -122,7 +157,8 @@ std::string BaseAudioContext::toString(ContextState state) {
122
157
  }
123
158
  }
124
159
 
125
- std::shared_ptr<PeriodicWave> BaseAudioContext::getBasicWaveForm(OscillatorType type) {
160
+ std::shared_ptr<PeriodicWave> BaseAudioContext::getBasicWaveForm(
161
+ OscillatorType type) {
126
162
  switch (type) {
127
163
  case OscillatorType::SINE:
128
164
  if (cachedSineWave_ == nullptr) {
@@ -149,7 +185,8 @@ std::shared_ptr<PeriodicWave> BaseAudioContext::getBasicWaveForm(OscillatorType
149
185
  }
150
186
  return cachedTriangleWave_;
151
187
  case OscillatorType::CUSTOM:
152
- throw std::invalid_argument("You can't get a custom wave form. You need to create it.");
188
+ throw std::invalid_argument(
189
+ "You can't get a custom wave form. You need to create it.");
153
190
  break;
154
191
  }
155
192
  }
@@ -1,10 +1,10 @@
1
1
  #pragma once
2
2
 
3
+ #include <functional>
3
4
  #include <memory>
4
5
  #include <string>
5
- #include <vector>
6
6
  #include <utility>
7
- #include <functional>
7
+ #include <vector>
8
8
 
9
9
  #include "ContextState.h"
10
10
  #include "OscillatorType.h"
@@ -24,36 +24,43 @@ class AudioBufferSourceNode;
24
24
 
25
25
  #ifdef ANDROID
26
26
  class AudioPlayer;
27
+ class AudioDecoder;
27
28
  #else
28
29
  class IOSAudioPlayer;
30
+ class IOSAudioDecoder;
29
31
  #endif
30
32
 
31
33
  class BaseAudioContext {
32
34
  public:
33
35
  BaseAudioContext();
36
+ ~BaseAudioContext();
37
+
34
38
  std::string getState();
35
39
  [[nodiscard]] int getSampleRate() const;
36
40
  [[nodiscard]] double getCurrentTime() const;
37
41
  [[nodiscard]] int getBufferSizeInFrames() const;
38
42
  [[nodiscard]] std::size_t getCurrentSampleFrame() const;
39
-
40
43
  std::shared_ptr<AudioDestinationNode> getDestination();
44
+
41
45
  std::shared_ptr<OscillatorNode> createOscillator();
42
46
  std::shared_ptr<GainNode> createGain();
43
47
  std::shared_ptr<StereoPannerNode> createStereoPanner();
44
48
  std::shared_ptr<BiquadFilterNode> createBiquadFilter();
45
49
  std::shared_ptr<AudioBufferSourceNode> createBufferSource();
46
- static std::shared_ptr<AudioBuffer> createBuffer(int numberOfChannels, int length, int sampleRate);
50
+ static std::shared_ptr<AudioBuffer>
51
+ createBuffer(int numberOfChannels, int length, int sampleRate);
47
52
  std::shared_ptr<PeriodicWave> createPeriodicWave(
48
53
  float *real,
49
54
  float *imag,
50
55
  bool disableNormalization,
51
56
  int length);
52
- std::shared_ptr<PeriodicWave> getBasicWaveForm(OscillatorType type);
53
57
 
58
+ std::shared_ptr<AudioBuffer> decodeAudioDataSource(const std::string &path);
59
+ std::shared_ptr<PeriodicWave> getBasicWaveForm(OscillatorType type);
54
60
  std::function<void(AudioBus *, int)> renderAudio();
55
-
56
- AudioNodeManager* getNodeManager();
61
+ AudioNodeManager *getNodeManager();
62
+ [[nodiscard]] bool isRunning() const;
63
+ [[nodiscard]] bool isClosed() const;
57
64
 
58
65
  protected:
59
66
  static std::string toString(ContextState state);
@@ -61,8 +68,10 @@ class BaseAudioContext {
61
68
 
62
69
  #ifdef ANDROID
63
70
  std::shared_ptr<AudioPlayer> audioPlayer_;
71
+ std::shared_ptr<AudioDecoder> audioDecoder_;
64
72
  #else
65
73
  std::shared_ptr<IOSAudioPlayer> audioPlayer_;
74
+ std::shared_ptr<IOSAudioDecoder> audioDecoder_;
66
75
  #endif
67
76
 
68
77
  int sampleRate_;
@@ -1,6 +1,6 @@
1
- #include "AudioBus.h"
2
- #include "AudioArray.h"
3
1
  #include "BiquadFilterNode.h"
2
+ #include "AudioArray.h"
3
+ #include "AudioBus.h"
4
4
  #include "BaseAudioContext.h"
5
5
 
6
6
  // https://webaudio.github.io/Audio-EQ-Cookbook/audio-eq-cookbook.html - math
@@ -352,7 +352,9 @@ void BiquadFilterNode::applyFilter() {
352
352
  }
353
353
  }
354
354
 
355
- void BiquadFilterNode::processNode(AudioBus* processingBus, int framesToProcess) {
355
+ void BiquadFilterNode::processNode(
356
+ AudioBus *processingBus,
357
+ int framesToProcess) {
356
358
  resetCoefficients();
357
359
  applyFilter();
358
360
 
@@ -1,6 +1,6 @@
1
1
  #include "GainNode.h"
2
- #include "AudioBus.h"
3
2
  #include "AudioArray.h"
3
+ #include "AudioBus.h"
4
4
  #include "BaseAudioContext.h"
5
5
 
6
6
  namespace audioapi {
@@ -1,6 +1,6 @@
1
- #include "AudioBus.h"
2
- #include "AudioArray.h"
3
1
  #include "OscillatorNode.h"
2
+ #include "AudioArray.h"
3
+ #include "AudioBus.h"
4
4
  #include "BaseAudioContext.h"
5
5
 
6
6
  namespace audioapi {
@@ -39,7 +39,7 @@ void OscillatorNode::setPeriodicWave(
39
39
  type_ = OscillatorType::CUSTOM;
40
40
  }
41
41
 
42
- void OscillatorNode::processNode(AudioBus* processingBus, int framesToProcess) {
42
+ void OscillatorNode::processNode(AudioBus *processingBus, int framesToProcess) {
43
43
  if (!isPlaying()) {
44
44
  processingBus->zero();
45
45
  return;
@@ -50,7 +50,7 @@ void OscillatorNode::processNode(AudioBus* processingBus, int framesToProcess) {
50
50
 
51
51
  for (int i = 0; i < framesToProcess; i += 1) {
52
52
  auto detuneRatio =
53
- std::pow(2.0f, detuneParam_->getValueAtTime(time) / 1200.0f);
53
+ std::pow(2.0f, detuneParam_->getValueAtTime(time) / 1200.0f);
54
54
  auto detunedFrequency =
55
55
  round(frequencyParam_->getValueAtTime(time) * detuneRatio);
56
56
  auto phaseIncrement = detunedFrequency * periodicWave_->getScale();
@@ -5,9 +5,9 @@
5
5
  #include <string>
6
6
 
7
7
  #include "AudioParam.h"
8
- #include "PeriodicWave.h"
9
- #include "OscillatorType.h"
10
8
  #include "AudioScheduledSourceNode.h"
9
+ #include "OscillatorType.h"
10
+ #include "PeriodicWave.h"
11
11
 
12
12
  namespace audioapi {
13
13
 
@@ -1,8 +1,8 @@
1
- #include "AudioBus.h"
2
- #include "Constants.h"
3
- #include "AudioArray.h"
4
1
  #include "StereoPannerNode.h"
2
+ #include "AudioArray.h"
3
+ #include "AudioBus.h"
5
4
  #include "BaseAudioContext.h"
5
+ #include "Constants.h"
6
6
 
7
7
  // https://webaudio.github.io/web-audio-api/#stereopanner-algorithm
8
8
 
@@ -19,17 +19,20 @@ std::shared_ptr<AudioParam> StereoPannerNode::getPanParam() const {
19
19
  return panParam_;
20
20
  }
21
21
 
22
- void StereoPannerNode::processNode(AudioBus* processingBus, int framesToProcess) {
22
+ void StereoPannerNode::processNode(
23
+ AudioBus *processingBus,
24
+ int framesToProcess) {
23
25
  // TODO: Currently assumed channelCount is 2
24
26
  // it should:
25
27
  // - support mono-channel buses
26
- // - throw errors when trying to setup stereo panner with more than 2 channels
28
+ // - throw errors when trying to setup stereo panner with more than 2
29
+ // channels
27
30
 
28
31
  double time = context_->getCurrentTime();
29
32
  double deltaTime = 1.0 / context_->getSampleRate();
30
33
 
31
- AudioArray* left = processingBus->getChannelByType(AudioBus::ChannelLeft);
32
- AudioArray* right = processingBus->getChannelByType(AudioBus::ChannelRight);
34
+ AudioArray *left = processingBus->getChannelByType(AudioBus::ChannelLeft);
35
+ AudioArray *right = processingBus->getChannelByType(AudioBus::ChannelRight);
33
36
 
34
37
  for (int i = 0; i < framesToProcess; i += 1) {
35
38
  float pan = panParam_->getValueAtTime(time);
@@ -17,7 +17,7 @@ class StereoPannerNode : public AudioNode {
17
17
  [[nodiscard]] std::shared_ptr<AudioParam> getPanParam() const;
18
18
 
19
19
  protected:
20
- void processNode(AudioBus* processingBus, int framesToProcess) override;
20
+ void processNode(AudioBus *processingBus, int framesToProcess) override;
21
21
 
22
22
  private:
23
23
  std::shared_ptr<AudioParam> panParam_;
@@ -38,7 +38,11 @@ namespace audioapi {
38
38
 
39
39
  class FFTFrame {
40
40
  public:
41
- explicit FFTFrame(int size): size_(size), log2Size_(static_cast<int>(log2(size))), realData_(new float[size]), imaginaryData_(new float[size]) {}
41
+ explicit FFTFrame(int size)
42
+ : size_(size),
43
+ log2Size_(static_cast<int>(log2(size))),
44
+ realData_(new float[size]),
45
+ imaginaryData_(new float[size]) {}
42
46
  ~FFTFrame() {
43
47
  delete[] realData_;
44
48
  delete[] imaginaryData_;