react-native-audio-api 0.0.1 → 0.2.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 (242) hide show
  1. package/README.md +60 -1
  2. package/RNAudioAPI.podspec +46 -0
  3. package/android/CMakeLists.txt +74 -0
  4. package/android/build.gradle +194 -0
  5. package/android/gradle.properties +5 -0
  6. package/android/libs/fftw3/arm64-v8a/libfftw3.a +0 -0
  7. package/android/libs/fftw3/armeabi-v7a/libfftw3.a +0 -0
  8. package/android/libs/fftw3/x86/libfftw3.a +0 -0
  9. package/android/libs/fftw3/x86_64/libfftw3.a +0 -0
  10. package/android/libs/include/fftw3/fftw3.h +413 -0
  11. package/android/src/main/AndroidManifest.xml +3 -0
  12. package/android/src/main/AndroidManifestNew.xml +2 -0
  13. package/android/src/main/cpp/AudioAPIInstaller/AudioAPIInstaller.cpp +22 -0
  14. package/android/src/main/cpp/AudioAPIInstaller/AudioAPIInstaller.h +48 -0
  15. package/android/src/main/cpp/AudioPlayer/AudioPlayer.cpp +66 -0
  16. package/android/src/main/cpp/AudioPlayer/AudioPlayer.h +33 -0
  17. package/android/src/main/cpp/OnLoad.cpp +9 -0
  18. package/android/src/main/java/com/swmansion/audioapi/AudioAPIPackage.kt +14 -0
  19. package/android/src/main/java/com/swmansion/audioapi/module/AudioAPIInstaller.kt +21 -0
  20. package/android/src/main/java/com/swmansion/audioapi/nativemodules/AudioAPIModule.kt +25 -0
  21. package/common/cpp/AudioAPIInstaller/AudioAPIInstallerHostObject.cpp +52 -0
  22. package/common/cpp/AudioAPIInstaller/AudioAPIInstallerHostObject.h +45 -0
  23. package/common/cpp/AudioAPIInstaller/AudioAPIInstallerWrapper.h +38 -0
  24. package/common/cpp/AudioAPIInstaller/android/AudioAPIInstallerWrapper.cpp +16 -0
  25. package/common/cpp/AudioAPIInstaller/ios/AudioAPIInstallerWrapper.cpp +12 -0
  26. package/common/cpp/HostObjects/AudioBufferHostObject.cpp +143 -0
  27. package/common/cpp/HostObjects/AudioBufferHostObject.h +33 -0
  28. package/common/cpp/HostObjects/AudioBufferSourceNodeHostObject.cpp +79 -0
  29. package/common/cpp/HostObjects/AudioBufferSourceNodeHostObject.h +37 -0
  30. package/common/cpp/HostObjects/AudioContextHostObject.cpp +54 -0
  31. package/common/cpp/HostObjects/AudioContextHostObject.h +36 -0
  32. package/common/cpp/HostObjects/AudioDestinationNodeHostObject.cpp +33 -0
  33. package/common/cpp/HostObjects/AudioDestinationNodeHostObject.h +31 -0
  34. package/common/cpp/HostObjects/AudioNodeHostObject.cpp +102 -0
  35. package/common/cpp/HostObjects/AudioNodeHostObject.h +29 -0
  36. package/common/cpp/HostObjects/AudioParamHostObject.cpp +115 -0
  37. package/common/cpp/HostObjects/AudioParamHostObject.h +34 -0
  38. package/common/cpp/HostObjects/AudioScheduledSourceNodeHostObject.cpp +73 -0
  39. package/common/cpp/HostObjects/AudioScheduledSourceNodeHostObject.h +31 -0
  40. package/common/cpp/HostObjects/BaseAudioContextHostObject.cpp +214 -0
  41. package/common/cpp/HostObjects/BaseAudioContextHostObject.h +39 -0
  42. package/common/cpp/HostObjects/BiquadFilterNodeHostObject.cpp +125 -0
  43. package/common/cpp/HostObjects/BiquadFilterNodeHostObject.h +42 -0
  44. package/common/cpp/HostObjects/Constants.h +22 -0
  45. package/common/cpp/HostObjects/GainNodeHostObject.cpp +41 -0
  46. package/common/cpp/HostObjects/GainNodeHostObject.h +32 -0
  47. package/common/cpp/HostObjects/OscillatorNodeHostObject.cpp +88 -0
  48. package/common/cpp/HostObjects/OscillatorNodeHostObject.h +41 -0
  49. package/common/cpp/HostObjects/PeriodicWaveHostObject.cpp +33 -0
  50. package/common/cpp/HostObjects/PeriodicWaveHostObject.h +33 -0
  51. package/common/cpp/HostObjects/StereoPannerNodeHostObject.cpp +41 -0
  52. package/common/cpp/HostObjects/StereoPannerNodeHostObject.h +36 -0
  53. package/common/cpp/core/AudioArray.cpp +103 -0
  54. package/common/cpp/core/AudioArray.h +42 -0
  55. package/common/cpp/core/AudioBuffer.cpp +55 -0
  56. package/common/cpp/core/AudioBuffer.h +40 -0
  57. package/common/cpp/core/AudioBufferSourceNode.cpp +135 -0
  58. package/common/cpp/core/AudioBufferSourceNode.h +30 -0
  59. package/common/cpp/core/AudioBus.cpp +357 -0
  60. package/common/cpp/core/AudioBus.h +63 -0
  61. package/common/cpp/core/AudioContext.cpp +24 -0
  62. package/common/cpp/core/AudioContext.h +16 -0
  63. package/common/cpp/core/AudioDestinationNode.cpp +45 -0
  64. package/common/cpp/core/AudioDestinationNode.h +32 -0
  65. package/common/cpp/core/AudioNode.cpp +222 -0
  66. package/common/cpp/core/AudioNode.h +74 -0
  67. package/common/cpp/core/AudioNodeManager.cpp +72 -0
  68. package/common/cpp/core/AudioNodeManager.h +35 -0
  69. package/common/cpp/core/AudioParam.cpp +133 -0
  70. package/common/cpp/core/AudioParam.h +50 -0
  71. package/common/cpp/core/AudioScheduledSourceNode.cpp +53 -0
  72. package/common/cpp/core/AudioScheduledSourceNode.h +34 -0
  73. package/common/cpp/core/BaseAudioContext.cpp +157 -0
  74. package/common/cpp/core/BaseAudioContext.h +80 -0
  75. package/common/cpp/core/BiquadFilterNode.cpp +385 -0
  76. package/common/cpp/core/BiquadFilterNode.h +124 -0
  77. package/common/cpp/core/GainNode.cpp +30 -0
  78. package/common/cpp/core/GainNode.h +25 -0
  79. package/common/cpp/core/OscillatorNode.cpp +75 -0
  80. package/common/cpp/core/OscillatorNode.h +72 -0
  81. package/common/cpp/core/ParamChange.cpp +46 -0
  82. package/common/cpp/core/ParamChange.h +34 -0
  83. package/common/cpp/core/PeriodicWave.cpp +362 -0
  84. package/common/cpp/core/PeriodicWave.h +119 -0
  85. package/common/cpp/core/StereoPannerNode.cpp +56 -0
  86. package/common/cpp/core/StereoPannerNode.h +26 -0
  87. package/common/cpp/types/BiquadFilterType.h +19 -0
  88. package/common/cpp/types/ChannelCountMode.h +10 -0
  89. package/common/cpp/types/ChannelInterpretation.h +10 -0
  90. package/common/cpp/types/ContextState.h +10 -0
  91. package/common/cpp/types/OscillatorType.h +11 -0
  92. package/common/cpp/utils/FFTFrame.h +63 -0
  93. package/common/cpp/utils/Locker.h +47 -0
  94. package/common/cpp/utils/VectorMath.cpp +678 -0
  95. package/common/cpp/utils/VectorMath.h +71 -0
  96. package/common/cpp/utils/android/FFTFrame.cpp +22 -0
  97. package/common/cpp/utils/ios/FFTFrame.cpp +24 -0
  98. package/common/cpp/wrappers/AudioBufferSourceNodeWrapper.cpp +45 -0
  99. package/common/cpp/wrappers/AudioBufferSourceNodeWrapper.h +26 -0
  100. package/common/cpp/wrappers/AudioBufferWrapper.cpp +46 -0
  101. package/common/cpp/wrappers/AudioBufferWrapper.h +30 -0
  102. package/common/cpp/wrappers/AudioContextWrapper.cpp +17 -0
  103. package/common/cpp/wrappers/AudioContextWrapper.h +19 -0
  104. package/common/cpp/wrappers/AudioDestinationNodeWrapper.h +16 -0
  105. package/common/cpp/wrappers/AudioNodeWrapper.cpp +37 -0
  106. package/common/cpp/wrappers/AudioNodeWrapper.h +25 -0
  107. package/common/cpp/wrappers/AudioParamWrapper.cpp +42 -0
  108. package/common/cpp/wrappers/AudioParamWrapper.h +25 -0
  109. package/common/cpp/wrappers/AudioScheduledSourceNodeWrapper.cpp +23 -0
  110. package/common/cpp/wrappers/AudioScheduledSourceNodeWrapper.h +23 -0
  111. package/common/cpp/wrappers/BaseAudioContextWrapper.cpp +76 -0
  112. package/common/cpp/wrappers/BaseAudioContextWrapper.h +49 -0
  113. package/common/cpp/wrappers/BiquadFilterNodeWrapper.cpp +60 -0
  114. package/common/cpp/wrappers/BiquadFilterNodeWrapper.h +37 -0
  115. package/common/cpp/wrappers/GainNodeWrapper.cpp +14 -0
  116. package/common/cpp/wrappers/GainNodeWrapper.h +20 -0
  117. package/common/cpp/wrappers/OscillatorNodeWrapper.cpp +44 -0
  118. package/common/cpp/wrappers/OscillatorNodeWrapper.h +31 -0
  119. package/common/cpp/wrappers/PeriodicWaveWrapper.h +17 -0
  120. package/common/cpp/wrappers/StereoPannerNodeWrapper.cpp +16 -0
  121. package/common/cpp/wrappers/StereoPannerNodeWrapper.h +21 -0
  122. package/ios/AudioAPIModule.h +24 -0
  123. package/ios/AudioAPIModule.mm +44 -0
  124. package/ios/AudioPlayer/AudioPlayer.h +28 -0
  125. package/ios/AudioPlayer/AudioPlayer.m +119 -0
  126. package/ios/AudioPlayer/IOSAudioPlayer.h +33 -0
  127. package/ios/AudioPlayer/IOSAudioPlayer.mm +57 -0
  128. package/lib/module/core/AudioBuffer.js +37 -0
  129. package/lib/module/core/AudioBuffer.js.map +1 -0
  130. package/lib/module/core/AudioBufferSourceNode.js +28 -0
  131. package/lib/module/core/AudioBufferSourceNode.js.map +1 -0
  132. package/lib/module/core/AudioContext.js +10 -0
  133. package/lib/module/core/AudioContext.js.map +1 -0
  134. package/lib/module/core/AudioDestinationNode.js +7 -0
  135. package/lib/module/core/AudioDestinationNode.js.map +1 -0
  136. package/lib/module/core/AudioNode.js +22 -0
  137. package/lib/module/core/AudioNode.js.map +1 -0
  138. package/lib/module/core/AudioParam.js +35 -0
  139. package/lib/module/core/AudioParam.js.map +1 -0
  140. package/lib/module/core/AudioScheduledSourceNode.js +28 -0
  141. package/lib/module/core/AudioScheduledSourceNode.js.map +1 -0
  142. package/lib/module/core/BaseAudioContext.js +57 -0
  143. package/lib/module/core/BaseAudioContext.js.map +1 -0
  144. package/lib/module/core/BiquadFilterNode.js +25 -0
  145. package/lib/module/core/BiquadFilterNode.js.map +1 -0
  146. package/lib/module/core/GainNode.js +9 -0
  147. package/lib/module/core/GainNode.js.map +1 -0
  148. package/lib/module/core/OscillatorNode.js +24 -0
  149. package/lib/module/core/OscillatorNode.js.map +1 -0
  150. package/lib/module/core/PeriodicWave.js +8 -0
  151. package/lib/module/core/PeriodicWave.js.map +1 -0
  152. package/lib/module/core/StereoPannerNode.js +9 -0
  153. package/lib/module/core/StereoPannerNode.js.map +1 -0
  154. package/lib/module/core/types.js +2 -0
  155. package/lib/module/core/types.js.map +1 -0
  156. package/lib/module/errors/IndexSizeError.js +8 -0
  157. package/lib/module/errors/IndexSizeError.js.map +1 -0
  158. package/lib/module/errors/InvalidAccessError.js +8 -0
  159. package/lib/module/errors/InvalidAccessError.js.map +1 -0
  160. package/lib/module/errors/InvalidStateError.js +8 -0
  161. package/lib/module/errors/InvalidStateError.js.map +1 -0
  162. package/lib/module/errors/RangeError.js +8 -0
  163. package/lib/module/errors/RangeError.js.map +1 -0
  164. package/lib/module/errors/index.js +5 -0
  165. package/lib/module/errors/index.js.map +1 -0
  166. package/lib/module/index.js +18 -0
  167. package/lib/module/index.js.map +1 -0
  168. package/lib/module/interfaces.js +2 -0
  169. package/lib/module/interfaces.js.map +1 -0
  170. package/lib/module/modules/global.d.js +2 -0
  171. package/lib/module/modules/global.d.js.map +1 -0
  172. package/lib/module/utils/install.js +22 -0
  173. package/lib/module/utils/install.js.map +1 -0
  174. package/lib/typescript/core/AudioBuffer.d.ts +12 -0
  175. package/lib/typescript/core/AudioBuffer.d.ts.map +1 -0
  176. package/lib/typescript/core/AudioBufferSourceNode.d.ts +12 -0
  177. package/lib/typescript/core/AudioBufferSourceNode.d.ts.map +1 -0
  178. package/lib/typescript/core/AudioContext.d.ts +6 -0
  179. package/lib/typescript/core/AudioContext.d.ts.map +1 -0
  180. package/lib/typescript/core/AudioDestinationNode.d.ts +7 -0
  181. package/lib/typescript/core/AudioDestinationNode.d.ts.map +1 -0
  182. package/lib/typescript/core/AudioNode.d.ts +16 -0
  183. package/lib/typescript/core/AudioNode.d.ts.map +1 -0
  184. package/lib/typescript/core/AudioParam.d.ts +14 -0
  185. package/lib/typescript/core/AudioParam.d.ts.map +1 -0
  186. package/lib/typescript/core/AudioScheduledSourceNode.d.ts +10 -0
  187. package/lib/typescript/core/AudioScheduledSourceNode.d.ts.map +1 -0
  188. package/lib/typescript/core/BaseAudioContext.d.ts +26 -0
  189. package/lib/typescript/core/BaseAudioContext.d.ts.map +1 -0
  190. package/lib/typescript/core/BiquadFilterNode.d.ts +16 -0
  191. package/lib/typescript/core/BiquadFilterNode.d.ts.map +1 -0
  192. package/lib/typescript/core/GainNode.d.ts +9 -0
  193. package/lib/typescript/core/GainNode.d.ts.map +1 -0
  194. package/lib/typescript/core/OscillatorNode.d.ts +15 -0
  195. package/lib/typescript/core/OscillatorNode.d.ts.map +1 -0
  196. package/lib/typescript/core/PeriodicWave.d.ts +5 -0
  197. package/lib/typescript/core/PeriodicWave.d.ts.map +1 -0
  198. package/lib/typescript/core/StereoPannerNode.d.ts +9 -0
  199. package/lib/typescript/core/StereoPannerNode.d.ts.map +1 -0
  200. package/lib/typescript/core/types.d.ts +9 -0
  201. package/lib/typescript/core/types.d.ts.map +1 -0
  202. package/lib/typescript/errors/IndexSizeError.d.ts +5 -0
  203. package/lib/typescript/errors/IndexSizeError.d.ts.map +1 -0
  204. package/lib/typescript/errors/InvalidAccessError.d.ts +5 -0
  205. package/lib/typescript/errors/InvalidAccessError.d.ts.map +1 -0
  206. package/lib/typescript/errors/InvalidStateError.d.ts +5 -0
  207. package/lib/typescript/errors/InvalidStateError.d.ts.map +1 -0
  208. package/lib/typescript/errors/RangeError.d.ts +5 -0
  209. package/lib/typescript/errors/RangeError.d.ts.map +1 -0
  210. package/lib/typescript/errors/index.d.ts +5 -0
  211. package/lib/typescript/errors/index.d.ts.map +1 -0
  212. package/lib/typescript/index.d.ts +14 -0
  213. package/lib/typescript/index.d.ts.map +1 -0
  214. package/lib/typescript/interfaces.d.ts +78 -0
  215. package/lib/typescript/interfaces.d.ts.map +1 -0
  216. package/lib/typescript/utils/install.d.ts +7 -0
  217. package/lib/typescript/utils/install.d.ts.map +1 -0
  218. package/package.json +104 -5
  219. package/src/core/AudioBuffer.ts +68 -0
  220. package/src/core/AudioBufferSourceNode.ts +35 -0
  221. package/src/core/AudioContext.ts +12 -0
  222. package/src/core/AudioDestinationNode.ts +9 -0
  223. package/src/core/AudioNode.ts +38 -0
  224. package/src/core/AudioParam.ts +55 -0
  225. package/src/core/AudioScheduledSourceNode.ts +43 -0
  226. package/src/core/BaseAudioContext.ts +97 -0
  227. package/src/core/BiquadFilterNode.ts +49 -0
  228. package/src/core/GainNode.ts +13 -0
  229. package/src/core/OscillatorNode.ts +37 -0
  230. package/src/core/PeriodicWave.ts +10 -0
  231. package/src/core/StereoPannerNode.ts +13 -0
  232. package/src/core/types.ts +26 -0
  233. package/src/errors/IndexSizeError.ts +8 -0
  234. package/src/errors/InvalidAccessError.ts +8 -0
  235. package/src/errors/InvalidStateError.ts +8 -0
  236. package/src/errors/RangeError.ts +8 -0
  237. package/src/errors/index.ts +4 -0
  238. package/src/index.ts +25 -0
  239. package/src/interfaces.ts +120 -0
  240. package/src/modules/global.d.ts +10 -0
  241. package/src/utils/install.ts +39 -0
  242. package/index.ts +0 -1
@@ -0,0 +1,55 @@
1
+ #include "AudioBus.h"
2
+ #include "AudioArray.h"
3
+ #include "AudioBuffer.h"
4
+
5
+ namespace audioapi {
6
+
7
+ AudioBuffer::AudioBuffer(int numberOfChannels, int length, int sampleRate) {
8
+ bus_ = std::make_shared<AudioBus>(sampleRate, length, numberOfChannels);
9
+ }
10
+
11
+ int AudioBuffer::getLength() const {
12
+ return bus_->getSize();
13
+ }
14
+
15
+ int AudioBuffer::getNumberOfChannels() const {
16
+ return bus_->getNumberOfChannels();
17
+ }
18
+
19
+ int AudioBuffer::getSampleRate() const {
20
+ return bus_->getSampleRate();
21
+ }
22
+
23
+ double AudioBuffer::getDuration() const {
24
+ return static_cast<double>(getLength()) / getSampleRate();
25
+ }
26
+
27
+ float* AudioBuffer::getChannelData(int channel) const {
28
+ return bus_->getChannel(channel)->getData();
29
+ }
30
+
31
+ void AudioBuffer::copyFromChannel(
32
+ float *destination,
33
+ int destinationLength,
34
+ int channelNumber,
35
+ int startInChannel) const {
36
+ memcpy(
37
+ destination,
38
+ bus_->getChannel(channelNumber)->getData() + startInChannel,
39
+ std::min(destinationLength, getLength() - startInChannel) * sizeof(float)
40
+ );
41
+ }
42
+
43
+ void AudioBuffer::copyToChannel(
44
+ const float *source,
45
+ int sourceLength,
46
+ int channelNumber,
47
+ int startInChannel) {
48
+ memcpy(
49
+ bus_->getChannel(channelNumber)->getData() + startInChannel,
50
+ source,
51
+ std::min(sourceLength, getLength() - startInChannel) * sizeof(float)
52
+ );
53
+ }
54
+
55
+ } // namespace audioapi
@@ -0,0 +1,40 @@
1
+ #pragma once
2
+
3
+ #include <algorithm>
4
+ #include <memory>
5
+ #include <string>
6
+ #include <vector>
7
+
8
+ namespace audioapi {
9
+
10
+ class AudioBus;
11
+
12
+ class AudioBuffer : public std::enable_shared_from_this<AudioBuffer> {
13
+ public:
14
+ explicit AudioBuffer(int numberOfChannels, int length, int sampleRate);
15
+
16
+ [[nodiscard]] int getLength() const;
17
+ [[nodiscard]] int getSampleRate() const;
18
+ [[nodiscard]] double getDuration() const;
19
+
20
+ [[nodiscard]] int getNumberOfChannels() const;
21
+ [[nodiscard]] float *getChannelData(int channel) const;
22
+
23
+ void copyFromChannel(
24
+ float *destination,
25
+ int destinationLength,
26
+ int channelNumber,
27
+ int startInChannel) const;
28
+ void copyToChannel(
29
+ const float *source,
30
+ int sourceLength,
31
+ int channelNumber,
32
+ int startInChannel);
33
+
34
+ private:
35
+ std::shared_ptr<AudioBus> bus_;
36
+
37
+ friend class AudioBufferSourceNode;
38
+ };
39
+
40
+ } // namespace audioapi
@@ -0,0 +1,135 @@
1
+ #include <algorithm>
2
+
3
+ #include "AudioBus.h"
4
+ #include "AudioArray.h"
5
+ #include "BaseAudioContext.h"
6
+ #include "AudioBufferSourceNode.h"
7
+
8
+ namespace audioapi {
9
+
10
+ AudioBufferSourceNode::AudioBufferSourceNode(BaseAudioContext *context)
11
+ : AudioScheduledSourceNode(context), loop_(false), bufferIndex_(0) {
12
+ numberOfInputs_ = 0;
13
+ buffer_ = std::shared_ptr<AudioBuffer>(nullptr);
14
+ isInitialized_ = true;
15
+ }
16
+
17
+ bool AudioBufferSourceNode::getLoop() const {
18
+ return loop_;
19
+ }
20
+
21
+ std::shared_ptr<AudioBuffer> AudioBufferSourceNode::getBuffer() const {
22
+ return buffer_;
23
+ }
24
+
25
+ void AudioBufferSourceNode::setLoop(bool loop) {
26
+ loop_ = loop;
27
+ }
28
+
29
+ void AudioBufferSourceNode::setBuffer(
30
+ const std::shared_ptr<AudioBuffer> &buffer) {
31
+
32
+ if (!buffer) {
33
+ buffer_ = std::shared_ptr<AudioBuffer>(nullptr);
34
+ return;
35
+ }
36
+
37
+ buffer_ = buffer;
38
+ }
39
+
40
+ // Note: AudioBus copy method will use memcpy if the source buffer and system processing bus have same channel count,
41
+ // otherwise it will use the summing function taking care of up/down mixing.
42
+ void AudioBufferSourceNode::processNode(AudioBus* processingBus, int framesToProcess) {
43
+ // No audio data to fill, zero the output and return.
44
+ if (!isPlaying() || !buffer_ || buffer_->getLength() == 0) {
45
+ processingBus->zero();
46
+ return;
47
+ }
48
+
49
+ // Easiest case, the buffer is the same length as the number of frames to process, just copy the data.
50
+ if (framesToProcess == buffer_->getLength()) {
51
+ processingBus->copy(buffer_->bus_.get());
52
+
53
+ if (!loop_) {
54
+ playbackState_ = PlaybackState::FINISHED;
55
+ disable();
56
+ }
57
+
58
+ return;
59
+ }
60
+
61
+ // The buffer is longer than the number of frames to process.
62
+ // We have to keep track of where we are in the buffer.
63
+ if (framesToProcess < buffer_->getLength()) {
64
+ int outputBusIndex = 0;
65
+ int framesToCopy = 0;
66
+
67
+ while (framesToProcess - outputBusIndex > 0) {
68
+ framesToCopy = std::min(framesToProcess - outputBusIndex, buffer_->getLength() - bufferIndex_);
69
+
70
+ processingBus->copy(buffer_->bus_.get(), bufferIndex_, outputBusIndex, framesToCopy);
71
+
72
+ bufferIndex_ += framesToCopy;
73
+ outputBusIndex += framesToCopy;
74
+
75
+ if (bufferIndex_ < buffer_->getLength()) {
76
+ continue;
77
+ }
78
+
79
+
80
+ bufferIndex_ %= buffer_->getLength();
81
+
82
+ if (!loop_) {
83
+ playbackState_ = PlaybackState::FINISHED;
84
+ disable();
85
+
86
+ if (framesToProcess - outputBusIndex > 0) {
87
+ processingBus->zero(outputBusIndex, framesToProcess - outputBusIndex);
88
+ }
89
+ }
90
+ }
91
+
92
+ return;
93
+ }
94
+
95
+ // processing bus is longer than the source buffer
96
+ if (!loop_) {
97
+ // If we don't loop the buffer, copy it once and zero the remaining processing bus frames.
98
+ processingBus->copy(buffer_->bus_.get());
99
+ processingBus->zero(buffer_->getLength(), framesToProcess - buffer_->getLength());
100
+
101
+ playbackState_ = PlaybackState::FINISHED;
102
+ disable();
103
+
104
+ return;
105
+ }
106
+
107
+ // If we loop the buffer, we need to loop the buffer framesToProcess / bufferSize times
108
+ // There might also be a remainder of frames to copy after the loop,
109
+ // which will also carry over some buffer frames to the next render quantum.
110
+ int processingBusPosition = 0;
111
+ int bufferSize = buffer_->getLength();
112
+ int remainingFrames = framesToProcess - framesToProcess / bufferSize;
113
+
114
+ // Do we have some frames left in the buffer from the previous render quantum,
115
+ // if yes copy them over and reset the buffer position.
116
+ if (bufferIndex_ > 0) {
117
+ processingBus->copy(buffer_->bus_.get(), 0, bufferIndex_);
118
+ processingBusPosition += bufferIndex_;
119
+ bufferIndex_ = 0;
120
+ }
121
+
122
+ // Copy the entire buffer n times to the processing bus.
123
+ while (processingBusPosition + bufferSize <= framesToProcess) {
124
+ processingBus->copy(buffer_->bus_.get());
125
+ processingBusPosition += bufferSize;
126
+ }
127
+
128
+ // Fill in the remaining frames from the processing buffer and update buffer index for next render quantum.
129
+ if (remainingFrames > 0) {
130
+ processingBus->copy(buffer_->bus_.get(), 0, processingBusPosition, remainingFrames);
131
+ bufferIndex_ = remainingFrames;
132
+ }
133
+ }
134
+
135
+ } // namespace audioapi
@@ -0,0 +1,30 @@
1
+ #pragma once
2
+
3
+ #include <memory>
4
+
5
+ #include "AudioBuffer.h"
6
+ #include "AudioScheduledSourceNode.h"
7
+
8
+ namespace audioapi {
9
+
10
+ class AudioBus;
11
+
12
+ class AudioBufferSourceNode : public AudioScheduledSourceNode {
13
+ public:
14
+ explicit AudioBufferSourceNode(BaseAudioContext *context);
15
+
16
+ [[nodiscard]] bool getLoop() const;
17
+ [[nodiscard]] std::shared_ptr<AudioBuffer> getBuffer() const;
18
+ void setLoop(bool loop);
19
+ void setBuffer(const std::shared_ptr<AudioBuffer> &buffer);
20
+
21
+ protected:
22
+ void processNode(AudioBus* processingBus, int framesToProcess) override;
23
+
24
+ private:
25
+ bool loop_;
26
+ std::shared_ptr<AudioBuffer> buffer_;
27
+ int bufferIndex_;
28
+ };
29
+
30
+ } // namespace audioapi
@@ -0,0 +1,357 @@
1
+ #include <algorithm>
2
+
3
+ #include "AudioBus.h"
4
+ #include "Constants.h"
5
+ #include "AudioArray.h"
6
+ #include "VectorMath.h"
7
+ #include "BaseAudioContext.h"
8
+
9
+ // Implementation of channel summing/mixing is based on the WebKit approach, source:
10
+ // https://github.com/WebKit/WebKit/blob/main/Source/WebCore/platform/audio/AudioBus.cpp
11
+
12
+ const float SQRT_HALF = sqrtf(0.5f);
13
+
14
+ namespace audioapi {
15
+
16
+ /**
17
+ * Public interfaces - memory management
18
+ */
19
+ AudioBus::AudioBus(int sampleRate, int size)
20
+ : sampleRate_(sampleRate), size_(size), numberOfChannels_(CHANNEL_COUNT) {
21
+ createChannels();
22
+ }
23
+
24
+ AudioBus::AudioBus(int sampleRate, int size, int numberOfChannels)
25
+ : sampleRate_(sampleRate), size_(size), numberOfChannels_(numberOfChannels) {
26
+ createChannels();
27
+ }
28
+
29
+ AudioBus::~AudioBus() {
30
+ channels_.clear();
31
+ }
32
+
33
+ /**
34
+ * Public interfaces - getters
35
+ */
36
+
37
+ int AudioBus::getNumberOfChannels() const {
38
+ return numberOfChannels_;
39
+ }
40
+
41
+ int AudioBus::getSampleRate() const {
42
+ return sampleRate_;
43
+ }
44
+
45
+ int AudioBus::getSize() const {
46
+ return size_;
47
+ }
48
+
49
+ AudioArray* AudioBus::getChannel(int index) const {
50
+ return channels_[index].get();
51
+ }
52
+
53
+ AudioArray* AudioBus::getChannelByType(int channelType) const {
54
+ switch (getNumberOfChannels()) {
55
+ case 1: // mono
56
+ if (channelType == ChannelMono || channelType == ChannelLeft) {
57
+ return getChannel(0);
58
+ }
59
+ return 0;
60
+
61
+ case 2: // stereo
62
+ switch (channelType) {
63
+ case ChannelLeft: return getChannel(0);
64
+ case ChannelRight: return getChannel(1);
65
+ default: return 0;
66
+ }
67
+
68
+ case 4: // quad
69
+ switch (channelType) {
70
+ case ChannelLeft: return getChannel(0);
71
+ case ChannelRight: return getChannel(1);
72
+ case ChannelSurroundLeft: return getChannel(2);
73
+ case ChannelSurroundRight: return getChannel(3);
74
+ default: return 0;
75
+ }
76
+
77
+ case 5: // 5.0
78
+ switch (channelType) {
79
+ case ChannelLeft: return getChannel(0);
80
+ case ChannelRight: return getChannel(1);
81
+ case ChannelCenter: return getChannel(2);
82
+ case ChannelSurroundLeft: return getChannel(3);
83
+ case ChannelSurroundRight: return getChannel(4);
84
+ default: return 0;
85
+ }
86
+
87
+ case 6: // 5.1
88
+ switch (channelType) {
89
+ case ChannelLeft: return getChannel(0);
90
+ case ChannelRight: return getChannel(1);
91
+ case ChannelCenter: return getChannel(2);
92
+ case ChannelLFE: return getChannel(3);
93
+ case ChannelSurroundLeft: return getChannel(4);
94
+ case ChannelSurroundRight: return getChannel(5);
95
+ default: return 0;
96
+ }
97
+ default:
98
+ return 0;
99
+ }
100
+ }
101
+
102
+ /**
103
+ * Public interfaces - audio processing and setters
104
+ */
105
+
106
+ void AudioBus::zero() {
107
+ zero(0, getSize());
108
+ }
109
+
110
+ void AudioBus::zero(int start, int length) {
111
+ for (auto it = channels_.begin(); it != channels_.end(); it += 1) {
112
+ it->get()->zero(start, length);
113
+ }
114
+ }
115
+
116
+ void AudioBus::normalize() {
117
+ float maxAbsValue = this->maxAbsValue();
118
+
119
+ if (maxAbsValue == 0.0f || maxAbsValue == 1.0f) {
120
+ return;
121
+ }
122
+
123
+ float scale = 1.0f / maxAbsValue;
124
+ this->scale(scale);
125
+ }
126
+
127
+ void AudioBus::scale(float value) {
128
+ for (auto it = channels_.begin(); it != channels_.end(); ++it) {
129
+ it->get()->scale(value);
130
+ }
131
+ }
132
+
133
+ float AudioBus::maxAbsValue() const {
134
+ float maxAbsValue = 1.0f;
135
+
136
+ for (auto it = channels_.begin(); it != channels_.end(); ++it) {
137
+ float channelMaxAbsValue = it->get()->getMaxAbsValue();
138
+ maxAbsValue = std::max(maxAbsValue, channelMaxAbsValue);
139
+ }
140
+
141
+ return maxAbsValue;
142
+ }
143
+
144
+ void AudioBus::sum(const AudioBus *source) {
145
+ sum(source, 0, 0, getSize());
146
+ }
147
+
148
+ void AudioBus::sum(const AudioBus *source, int start, int length) {
149
+ sum(source, start, start, length);
150
+ }
151
+
152
+ void AudioBus::sum(const AudioBus *source, int sourceStart, int destinationStart, int length) {
153
+ if (source == this) {
154
+ return;
155
+ }
156
+
157
+ int numberOfSourceChannels = source->getNumberOfChannels();
158
+ int numberOfChannels = getNumberOfChannels();
159
+
160
+ // TODO: consider adding ability to enforce discrete summing (if/when it will be useful).
161
+ // Source channel count is smaller than current bus, we need to up-mix.
162
+ if (numberOfSourceChannels < numberOfChannels) {
163
+ sumByUpMixing(source, sourceStart, destinationStart, length);
164
+ return;
165
+ }
166
+
167
+ // Source channel count is larger than current bus, we need to down-mix.
168
+ if (numberOfSourceChannels > numberOfChannels) {
169
+ sumByDownMixing(source, sourceStart, destinationStart, length);
170
+ return;
171
+ }
172
+
173
+ // Source and destination channel counts are the same. Just sum the channels.
174
+ for (int i = 0; i < numberOfChannels_; i += 1) {
175
+ getChannel(i)->sum(source->getChannel(i), sourceStart, destinationStart, length);
176
+ }
177
+ }
178
+
179
+ void AudioBus::copy(const AudioBus *source) {
180
+ copy(source, 0, 0, getSize());
181
+ }
182
+
183
+ void AudioBus::copy(const AudioBus *source, int start, int length) {
184
+ copy(source, start, start, length);
185
+ }
186
+
187
+ void AudioBus::copy(const AudioBus *source, int sourceStart, int destinationStart, int length) {
188
+ if (source == this) {
189
+ return;
190
+ }
191
+
192
+ if (source->getNumberOfChannels() == getNumberOfChannels()) {
193
+ for (int i = 0; i < getNumberOfChannels(); i += 1) {
194
+ getChannel(i)->copy(source->getChannel(i), sourceStart, destinationStart, length);
195
+ }
196
+
197
+ return;
198
+ }
199
+
200
+ // zero + sum is equivalent to copy, but takes care of up/down-mixing.
201
+ zero(destinationStart, length);
202
+ sum(source, sourceStart, destinationStart, length);
203
+ }
204
+
205
+ /**
206
+ * Internal tooling - channel initialization
207
+ */
208
+
209
+ void AudioBus::createChannels() {
210
+ channels_ = std::vector<std::shared_ptr<AudioArray>>(numberOfChannels_);
211
+
212
+ for (int i = 0; i < numberOfChannels_; i += 1) {
213
+ channels_[i] = std::make_shared<AudioArray>(size_);
214
+ }
215
+ }
216
+
217
+ /**
218
+ * Internal tooling - channel summing
219
+ */
220
+
221
+ void AudioBus::discreteSum(const AudioBus *source, int sourceStart, int destinationStart, int length) {
222
+ int numberOfChannels = std::min(getNumberOfChannels(), source->getNumberOfChannels());
223
+
224
+ // In case of source > destination, we "down-mix" and drop the extra channels.
225
+ // In case of source < destination, we "up-mix" as many channels as we have, leaving the remaining channels untouched.
226
+ for (int i = 0; i < numberOfChannels; i++) {
227
+ getChannel(i)->sum(source->getChannel(i), sourceStart, destinationStart, length);
228
+ }
229
+ }
230
+
231
+ void AudioBus::sumByUpMixing(const AudioBus *source, int sourceStart, int destinationStart, int length) {
232
+ int numberOfSourceChannels = source->getNumberOfChannels();
233
+ int numberOfChannels = getNumberOfChannels();
234
+
235
+ // Mono to stereo (1 -> 2, 4)
236
+ if (numberOfSourceChannels == 1 && (numberOfChannels == 2 || numberOfChannels == 4)) {
237
+ AudioArray* sourceChannel = source->getChannelByType(ChannelMono);
238
+
239
+ getChannelByType(ChannelLeft)->sum(sourceChannel, sourceStart, destinationStart, length);
240
+ getChannelByType(ChannelRight)->sum(sourceChannel, sourceStart, destinationStart, length);
241
+ return;
242
+ }
243
+
244
+ // Mono to 5.1 (1 -> 6)
245
+ if (numberOfSourceChannels == 1 && numberOfChannels == 6) {
246
+ AudioArray* sourceChannel = source->getChannel(0);
247
+
248
+ getChannelByType(ChannelCenter)->sum(sourceChannel, sourceStart, destinationStart, length);
249
+ return;
250
+ }
251
+
252
+ // Stereo 2 to stereo 4 or 5.1 (2 -> 4, 6)
253
+ if (numberOfSourceChannels == 2 && (numberOfChannels == 4 || numberOfChannels == 6)) {
254
+ getChannelByType(ChannelLeft)->sum(source->getChannelByType(ChannelLeft), sourceStart, destinationStart, length);
255
+ getChannelByType(ChannelRight)->sum(source->getChannelByType(ChannelRight), sourceStart, destinationStart, length);
256
+ return;
257
+ }
258
+
259
+ // Stereo 4 to 5.1 (4 -> 6)
260
+ if (numberOfSourceChannels == 4 && numberOfChannels == 6) {
261
+ getChannelByType(ChannelLeft)->sum(source->getChannelByType(ChannelLeft), sourceStart, destinationStart, length);
262
+ getChannelByType(ChannelRight)->sum(source->getChannelByType(ChannelRight), sourceStart, destinationStart, length);
263
+ getChannelByType(ChannelSurroundLeft)->sum(source->getChannelByType(ChannelSurroundLeft), sourceStart, destinationStart, length);
264
+ getChannelByType(ChannelSurroundRight)->sum(source->getChannelByType(ChannelSurroundRight), sourceStart, destinationStart, length);
265
+ return;
266
+ }
267
+
268
+ discreteSum(source, sourceStart, destinationStart, length);
269
+ }
270
+
271
+ void AudioBus::sumByDownMixing(const AudioBus *source, int sourceStart, int destinationStart, int length) {
272
+ int numberOfSourceChannels = source->getNumberOfChannels();
273
+ int numberOfChannels = getNumberOfChannels();
274
+
275
+ // Stereo to mono (2 -> 1): output += 0.5 * (input.left + input.right).
276
+ if (numberOfSourceChannels == 2 && numberOfChannels == 1) {
277
+ float* sourceLeft = source->getChannelByType(ChannelLeft)->getData();
278
+ float* sourceRight = source->getChannelByType(ChannelRight)->getData();
279
+
280
+ float* destinationData = getChannelByType(ChannelMono)->getData();
281
+
282
+ VectorMath::multiplyByScalarThenAddToOutput(sourceLeft + sourceStart, 0.5f, destinationData + destinationStart, length);
283
+ VectorMath::multiplyByScalarThenAddToOutput(sourceRight + sourceStart, 0.5f, destinationData + destinationStart, length);
284
+ return;
285
+ }
286
+
287
+ // Stereo 4 to mono: output += 0.25 * (input.left + input.right + input.surroundLeft + input.surroundRight)
288
+ if (numberOfSourceChannels == 4 && numberOfChannels == 1) {
289
+ float* sourceLeft = source->getChannelByType(ChannelLeft)->getData();
290
+ float* sourceRight = source->getChannelByType(ChannelRight)->getData();
291
+ float* sourceSurroundLeft = source->getChannelByType(ChannelSurroundLeft)->getData();
292
+ float* sourceSurroundRight = source->getChannelByType(ChannelSurroundRight)->getData();
293
+
294
+ float* destinationData = getChannelByType(ChannelMono)->getData();
295
+
296
+ VectorMath::multiplyByScalarThenAddToOutput(sourceLeft + sourceStart, 0.25f, destinationData + destinationStart, length);
297
+ VectorMath::multiplyByScalarThenAddToOutput(sourceRight + sourceStart, 0.25f, destinationData + destinationStart, length);
298
+ VectorMath::multiplyByScalarThenAddToOutput(sourceSurroundLeft + sourceStart, 0.25f, destinationData + destinationStart, length);
299
+ VectorMath::multiplyByScalarThenAddToOutput(sourceSurroundRight + sourceStart, 0.25f, destinationData + destinationStart, length);
300
+ return;
301
+ }
302
+
303
+ // 5.1 to stereo:
304
+ // output.left += input.left + sqrt(1/2) * (input.center + input.surroundLeft)
305
+ // output.right += input.right + sqrt(1/2) * (input.center + input.surroundRight)
306
+ if (numberOfSourceChannels == 6 && numberOfChannels == 2) {
307
+ float* sourceLeft = source->getChannelByType(ChannelLeft)->getData();
308
+ float* sourceRight = source->getChannelByType(ChannelRight)->getData();
309
+ float* sourceCenter = source->getChannelByType(ChannelCenter)->getData();
310
+ float* sourceSurroundLeft = source->getChannelByType(ChannelSurroundLeft)->getData();
311
+ float* sourceSurroundRight = source->getChannelByType(ChannelSurroundRight)->getData();
312
+
313
+ float* destinationLeft = getChannelByType(ChannelLeft)->getData();
314
+ float* destinationRight = getChannelByType(ChannelRight)->getData();
315
+
316
+ VectorMath::add(sourceLeft + sourceStart, destinationLeft + destinationStart, destinationLeft + destinationStart, length);
317
+ VectorMath::multiplyByScalarThenAddToOutput(sourceCenter + sourceStart, SQRT_HALF, destinationLeft + destinationStart, length);
318
+ VectorMath::multiplyByScalarThenAddToOutput(sourceSurroundLeft + sourceStart, SQRT_HALF, destinationLeft + destinationStart, length);
319
+
320
+ VectorMath::add(sourceRight + sourceStart, destinationRight + destinationStart, destinationRight + destinationStart, length);
321
+ VectorMath::multiplyByScalarThenAddToOutput(sourceCenter + sourceStart, SQRT_HALF, destinationRight + destinationStart, length);
322
+ VectorMath::multiplyByScalarThenAddToOutput(sourceSurroundRight + sourceStart, SQRT_HALF, destinationRight + destinationStart, length);
323
+ return;
324
+ }
325
+
326
+ // 5.1 to stereo 4:
327
+ // output.left += input.left + sqrt(1/2) * input.center
328
+ // output.right += input.right + sqrt(1/2) * input.center
329
+ // output.surroundLeft += input.surroundLeft
330
+ // output.surroundRight += input.surroundRight
331
+ if (numberOfSourceChannels == 6 && numberOfChannels == 4) {
332
+ float* sourceLeft = source->getChannelByType(ChannelLeft)->getData();
333
+ float* sourceRight = source->getChannelByType(ChannelRight)->getData();
334
+ float* sourceCenter = source->getChannelByType(ChannelCenter)->getData();
335
+ float* sourceSurroundLeft = source->getChannelByType(ChannelSurroundLeft)->getData();
336
+ float* sourceSurroundRight = source->getChannelByType(ChannelSurroundRight)->getData();
337
+
338
+ float* destinationLeft = getChannelByType(ChannelLeft)->getData();
339
+ float* destinationRight = getChannelByType(ChannelRight)->getData();
340
+ float* destinationSurroundLeft = getChannelByType(ChannelSurroundLeft)->getData();
341
+ float* destinationSurroundRight = getChannelByType(ChannelSurroundRight)->getData();
342
+
343
+ VectorMath::add(sourceLeft + sourceStart, destinationLeft + destinationStart, destinationLeft + destinationStart, length);
344
+ VectorMath::multiplyByScalarThenAddToOutput(sourceCenter, SQRT_HALF, destinationLeft + destinationStart, length);
345
+
346
+ VectorMath::add(sourceRight + sourceStart, destinationRight + destinationStart, destinationRight + destinationStart, length);
347
+ VectorMath::multiplyByScalarThenAddToOutput(sourceCenter, SQRT_HALF, destinationRight + destinationStart, length);
348
+
349
+ VectorMath::add(sourceSurroundLeft + sourceStart, destinationSurroundLeft + destinationStart, destinationSurroundLeft + destinationStart, length);
350
+ VectorMath::add(sourceSurroundRight + sourceStart, destinationSurroundRight + destinationStart, destinationSurroundRight + destinationStart, length);
351
+ return;
352
+ }
353
+
354
+ discreteSum(source, sourceStart, destinationStart, length);
355
+ }
356
+
357
+ } // namespace audioapi
@@ -0,0 +1,63 @@
1
+ #pragma once
2
+
3
+ #include <memory>
4
+ #include <vector>
5
+ #include <algorithm>
6
+
7
+ namespace audioapi {
8
+
9
+ class BaseAudioContext;
10
+ class AudioArray;
11
+
12
+ class AudioBus {
13
+ public:
14
+ enum {
15
+ ChannelMono = 0,
16
+ ChannelLeft = 0,
17
+ ChannelRight = 1,
18
+ ChannelCenter = 2,
19
+ ChannelLFE = 3,
20
+ ChannelSurroundLeft = 4,
21
+ ChannelSurroundRight = 5,
22
+ };
23
+
24
+ explicit AudioBus(int sampleRate, int size);
25
+ explicit AudioBus(int sampleRate, int size, int numberOfChannels);
26
+
27
+ ~AudioBus();
28
+
29
+ [[nodiscard]] int getNumberOfChannels() const;
30
+ [[nodiscard]] int getSampleRate() const;
31
+ [[nodiscard]] int getSize() const;
32
+ AudioArray* getChannel(int index) const;
33
+ AudioArray* getChannelByType(int channelType) const;
34
+
35
+ void normalize();
36
+ void scale(float value);
37
+ float maxAbsValue() const;
38
+
39
+ void zero();
40
+ void zero(int start, int length);
41
+
42
+ void sum(const AudioBus *source);
43
+ void sum(const AudioBus *source, int start, int length);
44
+ void sum(const AudioBus *source, int sourceStart, int destinationStart, int length);
45
+
46
+ void copy(const AudioBus *source);
47
+ void copy(const AudioBus *source, int start, int length);
48
+ void copy(const AudioBus *source, int sourceStart, int destinationStart, int length);
49
+
50
+ private:
51
+ std::vector<std::shared_ptr<AudioArray>> channels_;
52
+
53
+ int numberOfChannels_;
54
+ int sampleRate_;
55
+ int size_;
56
+
57
+ void createChannels();
58
+ void discreteSum(const AudioBus *source, int sourceStart, int destinationStart, int length);
59
+ void sumByUpMixing(const AudioBus *source, int sourceStart, int destinationStart, int length);
60
+ void sumByDownMixing(const AudioBus *source, int sourceStart, int destinationStart, int length);
61
+ };
62
+
63
+ } // namespace audioapi