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

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 (197) hide show
  1. package/RNAudioAPI.podspec +40 -29
  2. package/android/CMakeLists.txt +17 -21
  3. package/android/build.gradle +26 -9
  4. package/android/src/main/cpp/OnLoad.cpp +1 -1
  5. package/android/src/main/cpp/core/AudioAPIInstaller.cpp +37 -0
  6. package/android/src/main/cpp/{AudioAPIInstaller → core}/AudioAPIInstaller.h +5 -16
  7. package/android/src/main/cpp/{AudioDecoder → core}/AudioDecoder.cpp +0 -8
  8. package/android/src/main/java/com/swmansion/audioapi/AudioAPIPackage.kt +2 -0
  9. package/android/src/main/java/com/swmansion/audioapi/nativemodules/AudioAPIModule.kt +6 -4
  10. package/common/cpp/HostObjects/AudioAPIInstallerHostObject.h +48 -0
  11. package/common/cpp/HostObjects/AudioBufferHostObject.h +79 -13
  12. package/common/cpp/HostObjects/AudioBufferSourceNodeHostObject.h +93 -14
  13. package/common/cpp/HostObjects/AudioContextHostObject.h +10 -21
  14. package/common/cpp/HostObjects/AudioDestinationNodeHostObject.h +3 -16
  15. package/common/cpp/HostObjects/AudioNodeHostObject.h +48 -11
  16. package/common/cpp/HostObjects/AudioParamHostObject.h +93 -14
  17. package/common/cpp/HostObjects/AudioScheduledSourceNodeHostObject.h +23 -16
  18. package/common/cpp/HostObjects/BaseAudioContextHostObject.h +131 -14
  19. package/common/cpp/HostObjects/BiquadFilterNodeHostObject.h +76 -18
  20. package/common/cpp/HostObjects/GainNodeHostObject.h +10 -15
  21. package/common/cpp/HostObjects/OscillatorNodeHostObject.h +40 -17
  22. package/common/cpp/HostObjects/PeriodicWaveHostObject.h +4 -17
  23. package/common/cpp/HostObjects/StereoPannerNodeHostObject.h +10 -17
  24. package/common/cpp/core/AudioBufferSourceNode.cpp +181 -73
  25. package/common/cpp/core/AudioBufferSourceNode.h +41 -1
  26. package/{android/src/main/cpp/AudioDecoder → common/cpp/core}/AudioDecoder.h +1 -3
  27. package/common/cpp/core/AudioDestinationNode.h +1 -1
  28. package/common/cpp/core/AudioParam.cpp +218 -58
  29. package/common/cpp/core/AudioParam.h +19 -15
  30. package/common/cpp/core/AudioScheduledSourceNode.cpp +94 -21
  31. package/common/cpp/core/AudioScheduledSourceNode.h +16 -5
  32. package/common/cpp/core/BaseAudioContext.cpp +3 -13
  33. package/common/cpp/core/BaseAudioContext.h +2 -4
  34. package/common/cpp/core/BiquadFilterNode.cpp +5 -7
  35. package/common/cpp/{HostObjects → core}/Constants.h +2 -2
  36. package/common/cpp/core/GainNode.cpp +1 -1
  37. package/common/cpp/core/OscillatorNode.cpp +11 -5
  38. package/common/cpp/core/ParamChangeEvent.cpp +58 -0
  39. package/common/cpp/core/{ParamChange.h → ParamChangeEvent.h} +11 -5
  40. package/common/cpp/core/StereoPannerNode.cpp +1 -1
  41. package/common/cpp/jsi/JsiHostObject.cpp +90 -0
  42. package/common/cpp/jsi/JsiHostObject.h +100 -0
  43. package/common/cpp/{utils → jsi}/JsiPromise.cpp +10 -9
  44. package/common/cpp/jsi/JsiPromise.h +48 -0
  45. package/common/cpp/jsi/RuntimeAwareCache.h +57 -0
  46. package/common/cpp/jsi/RuntimeLifecycleMonitor.cpp +61 -0
  47. package/common/cpp/jsi/RuntimeLifecycleMonitor.h +32 -0
  48. package/common/cpp/types/BiquadFilterType.h +0 -4
  49. package/common/cpp/types/ChannelCountMode.h +0 -3
  50. package/common/cpp/types/ChannelInterpretation.h +0 -3
  51. package/common/cpp/types/ContextState.h +0 -3
  52. package/common/cpp/types/OscillatorType.h +0 -4
  53. package/common/cpp/types/ParamChangeEventType.h +13 -0
  54. package/common/cpp/utils/AudioUtils.cpp +26 -0
  55. package/common/cpp/utils/AudioUtils.h +12 -0
  56. package/common/cpp/utils/{ios/FFTFrame.cpp → FFTFrame.cpp} +30 -3
  57. package/common/cpp/utils/VectorMath.h +7 -33
  58. package/ios/AudioAPIModule.h +4 -12
  59. package/ios/AudioAPIModule.mm +26 -25
  60. package/ios/core/AudioDecoder.mm +45 -0
  61. package/ios/{AudioPlayer → core}/AudioPlayer.m +2 -1
  62. package/lib/module/core/AudioBuffer.js +3 -1
  63. package/lib/module/core/AudioBuffer.js.map +1 -1
  64. package/lib/module/core/AudioBufferSourceNode.js +19 -2
  65. package/lib/module/core/AudioBufferSourceNode.js.map +1 -1
  66. package/lib/module/core/AudioContext.js +3 -1
  67. package/lib/module/core/AudioContext.js.map +1 -1
  68. package/lib/module/core/AudioDestinationNode.js +4 -6
  69. package/lib/module/core/AudioDestinationNode.js.map +1 -1
  70. package/lib/module/core/AudioNode.js +3 -1
  71. package/lib/module/core/AudioNode.js.map +1 -1
  72. package/lib/module/core/AudioParam.js +27 -1
  73. package/lib/module/core/AudioParam.js.map +1 -1
  74. package/lib/module/core/AudioScheduledSourceNode.js +4 -5
  75. package/lib/module/core/AudioScheduledSourceNode.js.map +1 -1
  76. package/lib/module/core/BaseAudioContext.js +11 -9
  77. package/lib/module/core/BaseAudioContext.js.map +1 -1
  78. package/lib/module/core/BiquadFilterNode.js +5 -3
  79. package/lib/module/core/BiquadFilterNode.js.map +1 -1
  80. package/lib/module/core/GainNode.js +4 -2
  81. package/lib/module/core/GainNode.js.map +1 -1
  82. package/lib/module/core/OscillatorNode.js +5 -3
  83. package/lib/module/core/OscillatorNode.js.map +1 -1
  84. package/lib/module/core/PeriodicWave.js +2 -0
  85. package/lib/module/core/PeriodicWave.js.map +1 -1
  86. package/lib/module/core/StereoPannerNode.js +4 -2
  87. package/lib/module/core/StereoPannerNode.js.map +1 -1
  88. package/lib/module/core/types.js +1 -1
  89. package/lib/module/errors/IndexSizeError.js +2 -0
  90. package/lib/module/errors/IndexSizeError.js.map +1 -1
  91. package/lib/module/errors/InvalidAccessError.js +2 -0
  92. package/lib/module/errors/InvalidAccessError.js.map +1 -1
  93. package/lib/module/errors/InvalidStateError.js +2 -0
  94. package/lib/module/errors/InvalidStateError.js.map +1 -1
  95. package/lib/module/errors/RangeError.js +2 -0
  96. package/lib/module/errors/RangeError.js.map +1 -1
  97. package/lib/module/errors/index.js +6 -4
  98. package/lib/module/errors/index.js.map +1 -1
  99. package/lib/module/index.js +35 -10
  100. package/lib/module/index.js.map +1 -1
  101. package/lib/module/index.native.js +16 -14
  102. package/lib/module/index.native.js.map +1 -1
  103. package/lib/module/interfaces.js +2 -0
  104. package/lib/module/specs/global.d.js +4 -0
  105. package/lib/module/{modules → specs}/global.d.js.map +1 -1
  106. package/lib/module/{utils → specs}/install.js +5 -9
  107. package/lib/module/specs/install.js.map +1 -0
  108. package/lib/typescript/core/AudioBuffer.d.ts +2 -0
  109. package/lib/typescript/core/AudioBuffer.d.ts.map +1 -1
  110. package/lib/typescript/core/AudioBufferSourceNode.d.ts +7 -0
  111. package/lib/typescript/core/AudioBufferSourceNode.d.ts.map +1 -1
  112. package/lib/typescript/core/AudioDestinationNode.d.ts +0 -3
  113. package/lib/typescript/core/AudioDestinationNode.d.ts.map +1 -1
  114. package/lib/typescript/core/AudioParam.d.ts +4 -0
  115. package/lib/typescript/core/AudioParam.d.ts.map +1 -1
  116. package/lib/typescript/core/AudioScheduledSourceNode.d.ts +0 -3
  117. package/lib/typescript/core/AudioScheduledSourceNode.d.ts.map +1 -1
  118. package/lib/typescript/core/PeriodicWave.d.ts +2 -0
  119. package/lib/typescript/core/PeriodicWave.d.ts.map +1 -1
  120. package/lib/typescript/index.d.ts +13 -3
  121. package/lib/typescript/index.d.ts.map +1 -1
  122. package/lib/typescript/interfaces.d.ts +8 -0
  123. package/lib/typescript/interfaces.d.ts.map +1 -1
  124. package/lib/typescript/{utils → specs}/install.d.ts.map +1 -1
  125. package/metro-config/index.d.ts +5 -0
  126. package/metro-config/index.js +41 -0
  127. package/metro-config/tsconfig.json +3 -0
  128. package/package.json +50 -16
  129. package/scripts/audioapi_utils.rb +56 -0
  130. package/src/core/AudioBufferSourceNode.ts +23 -0
  131. package/src/core/AudioDestinationNode.ts +1 -7
  132. package/src/core/AudioParam.ts +48 -0
  133. package/src/core/AudioScheduledSourceNode.ts +0 -5
  134. package/src/index.native.ts +1 -1
  135. package/src/index.ts +54 -13
  136. package/src/interfaces.ts +17 -0
  137. package/src/{modules → specs}/global.d.ts +2 -0
  138. package/src/{utils → specs}/install.ts +4 -11
  139. package/android/src/main/cpp/AudioAPIInstaller/AudioAPIInstaller.cpp +0 -26
  140. package/common/cpp/AudioAPIInstaller/AudioAPIInstallerHostObject.cpp +0 -58
  141. package/common/cpp/AudioAPIInstaller/AudioAPIInstallerHostObject.h +0 -51
  142. package/common/cpp/AudioAPIInstaller/AudioAPIInstallerWrapper.h +0 -38
  143. package/common/cpp/AudioAPIInstaller/android/AudioAPIInstallerWrapper.cpp +0 -16
  144. package/common/cpp/AudioAPIInstaller/ios/AudioAPIInstallerWrapper.cpp +0 -12
  145. package/common/cpp/HostObjects/AudioBufferHostObject.cpp +0 -150
  146. package/common/cpp/HostObjects/AudioBufferSourceNodeHostObject.cpp +0 -79
  147. package/common/cpp/HostObjects/AudioContextHostObject.cpp +0 -55
  148. package/common/cpp/HostObjects/AudioDestinationNodeHostObject.cpp +0 -33
  149. package/common/cpp/HostObjects/AudioNodeHostObject.cpp +0 -102
  150. package/common/cpp/HostObjects/AudioParamHostObject.cpp +0 -115
  151. package/common/cpp/HostObjects/AudioScheduledSourceNodeHostObject.cpp +0 -73
  152. package/common/cpp/HostObjects/BaseAudioContextHostObject.cpp +0 -250
  153. package/common/cpp/HostObjects/BiquadFilterNodeHostObject.cpp +0 -125
  154. package/common/cpp/HostObjects/GainNodeHostObject.cpp +0 -41
  155. package/common/cpp/HostObjects/OscillatorNodeHostObject.cpp +0 -88
  156. package/common/cpp/HostObjects/PeriodicWaveHostObject.cpp +0 -33
  157. package/common/cpp/HostObjects/StereoPannerNodeHostObject.cpp +0 -41
  158. package/common/cpp/core/ParamChange.cpp +0 -46
  159. package/common/cpp/utils/JsiPromise.h +0 -48
  160. package/common/cpp/utils/android/FFTFrame.cpp +0 -23
  161. package/common/cpp/wrappers/AudioBufferSourceNodeWrapper.cpp +0 -45
  162. package/common/cpp/wrappers/AudioBufferSourceNodeWrapper.h +0 -26
  163. package/common/cpp/wrappers/AudioBufferWrapper.cpp +0 -46
  164. package/common/cpp/wrappers/AudioBufferWrapper.h +0 -30
  165. package/common/cpp/wrappers/AudioContextWrapper.cpp +0 -17
  166. package/common/cpp/wrappers/AudioContextWrapper.h +0 -19
  167. package/common/cpp/wrappers/AudioDestinationNodeWrapper.h +0 -16
  168. package/common/cpp/wrappers/AudioNodeWrapper.cpp +0 -37
  169. package/common/cpp/wrappers/AudioNodeWrapper.h +0 -25
  170. package/common/cpp/wrappers/AudioParamWrapper.cpp +0 -42
  171. package/common/cpp/wrappers/AudioParamWrapper.h +0 -25
  172. package/common/cpp/wrappers/AudioScheduledSourceNodeWrapper.cpp +0 -23
  173. package/common/cpp/wrappers/AudioScheduledSourceNodeWrapper.h +0 -23
  174. package/common/cpp/wrappers/BaseAudioContextWrapper.cpp +0 -83
  175. package/common/cpp/wrappers/BaseAudioContextWrapper.h +0 -51
  176. package/common/cpp/wrappers/BiquadFilterNodeWrapper.cpp +0 -60
  177. package/common/cpp/wrappers/BiquadFilterNodeWrapper.h +0 -37
  178. package/common/cpp/wrappers/GainNodeWrapper.cpp +0 -14
  179. package/common/cpp/wrappers/GainNodeWrapper.h +0 -20
  180. package/common/cpp/wrappers/OscillatorNodeWrapper.cpp +0 -44
  181. package/common/cpp/wrappers/OscillatorNodeWrapper.h +0 -31
  182. package/common/cpp/wrappers/PeriodicWaveWrapper.h +0 -17
  183. package/common/cpp/wrappers/StereoPannerNodeWrapper.cpp +0 -16
  184. package/common/cpp/wrappers/StereoPannerNodeWrapper.h +0 -21
  185. package/ios/AudioDecoder/AudioDecoder.h +0 -17
  186. package/ios/AudioDecoder/AudioDecoder.m +0 -80
  187. package/ios/AudioDecoder/IOSAudioDecoder.h +0 -28
  188. package/ios/AudioDecoder/IOSAudioDecoder.mm +0 -46
  189. package/lib/module/modules/global.d.js +0 -2
  190. package/lib/module/utils/install.js.map +0 -1
  191. /package/android/src/main/cpp/{AudioPlayer → core}/AudioPlayer.cpp +0 -0
  192. /package/android/src/main/cpp/{AudioPlayer → core}/AudioPlayer.h +0 -0
  193. /package/{android/libs/include → common/cpp/libs}/miniaudio.h +0 -0
  194. /package/ios/{AudioPlayer → core}/AudioPlayer.h +0 -0
  195. /package/ios/{AudioPlayer → core}/IOSAudioPlayer.h +0 -0
  196. /package/ios/{AudioPlayer → core}/IOSAudioPlayer.mm +0 -0
  197. /package/lib/typescript/{utils → specs}/install.d.ts +0 -0
@@ -6,7 +6,7 @@
6
6
 
7
7
  #include "AudioParamHostObject.h"
8
8
  #include "AudioScheduledSourceNodeHostObject.h"
9
- #include "OscillatorNodeWrapper.h"
9
+ #include "OscillatorNode.h"
10
10
  #include "PeriodicWaveHostObject.h"
11
11
 
12
12
  namespace audioapi {
@@ -14,28 +14,51 @@ using namespace facebook;
14
14
 
15
15
  class OscillatorNodeHostObject : public AudioScheduledSourceNodeHostObject {
16
16
  public:
17
- explicit OscillatorNodeHostObject(
18
- const std::shared_ptr<OscillatorNodeWrapper> &wrapper);
17
+ explicit OscillatorNodeHostObject(const std::shared_ptr<OscillatorNode> &node)
18
+ : AudioScheduledSourceNodeHostObject(node) {
19
+ addGetters(
20
+ JSI_EXPORT_PROPERTY_GETTER(OscillatorNodeHostObject, frequency),
21
+ JSI_EXPORT_PROPERTY_GETTER(OscillatorNodeHostObject, detune),
22
+ JSI_EXPORT_PROPERTY_GETTER(OscillatorNodeHostObject, type));
19
23
 
20
- jsi::Value get(jsi::Runtime &runtime, const jsi::PropNameID &name) override;
24
+ addFunctions(
25
+ JSI_EXPORT_FUNCTION(OscillatorNodeHostObject, setPeriodicWave));
21
26
 
22
- void set(
23
- jsi::Runtime &runtime,
24
- const jsi::PropNameID &name,
25
- const jsi::Value &value) override;
27
+ addSetters(JSI_EXPORT_PROPERTY_SETTER(OscillatorNodeHostObject, type));
28
+ }
29
+
30
+ JSI_PROPERTY_GETTER(frequency) {
31
+ auto oscillatorNode = std::static_pointer_cast<OscillatorNode>(node_);
32
+ auto frequencyParam_ = std::make_shared<AudioParamHostObject>(
33
+ oscillatorNode->getFrequencyParam());
34
+ return jsi::Object::createFromHostObject(runtime, frequencyParam_);
35
+ }
26
36
 
27
- std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime &rt) override;
37
+ JSI_PROPERTY_GETTER(detune) {
38
+ auto oscillatorNode = std::static_pointer_cast<OscillatorNode>(node_);
39
+ auto detuneParam_ = std::make_shared<AudioParamHostObject>(
40
+ oscillatorNode->getDetuneParam());
41
+ return jsi::Object::createFromHostObject(runtime, detuneParam_);
42
+ }
28
43
 
29
- static std::shared_ptr<OscillatorNodeHostObject> createFromWrapper(
30
- const std::shared_ptr<OscillatorNodeWrapper> &wrapper) {
31
- return std::make_shared<OscillatorNodeHostObject>(wrapper);
44
+ JSI_PROPERTY_GETTER(type) {
45
+ auto oscillatorNode = std::static_pointer_cast<OscillatorNode>(node_);
46
+ auto waveType = oscillatorNode->getType();
47
+ return jsi::String::createFromUtf8(runtime, waveType);
32
48
  }
33
49
 
34
- private:
35
- std::shared_ptr<AudioParamHostObject> frequencyParam_;
36
- std::shared_ptr<AudioParamHostObject> detuneParam_;
50
+ JSI_HOST_FUNCTION(setPeriodicWave) {
51
+ auto oscillatorNode = std::static_pointer_cast<OscillatorNode>(node_);
52
+ auto periodicWave =
53
+ args[0].getObject(runtime).getHostObject<PeriodicWaveHostObject>(
54
+ runtime);
55
+ oscillatorNode->setPeriodicWave(periodicWave->periodicWave_);
56
+ return jsi::Value::undefined();
57
+ }
37
58
 
38
- std::shared_ptr<OscillatorNodeWrapper>
39
- getOscillatorNodeWrapperFromAudioNodeWrapper();
59
+ JSI_PROPERTY_SETTER(type) {
60
+ auto oscillatorNode = std::static_pointer_cast<OscillatorNode>(node_);
61
+ oscillatorNode->setType(value.getString(runtime).utf8(runtime));
62
+ }
40
63
  };
41
64
  } // namespace audioapi
@@ -4,30 +4,17 @@
4
4
  #include <memory>
5
5
  #include <vector>
6
6
 
7
- #include "PeriodicWaveWrapper.h"
7
+ #include "PeriodicWave.h"
8
8
 
9
9
  namespace audioapi {
10
10
  using namespace facebook;
11
11
 
12
12
  class PeriodicWaveHostObject : public jsi::HostObject {
13
13
  public:
14
- std::shared_ptr<PeriodicWaveWrapper> wrapper_;
14
+ std::shared_ptr<PeriodicWave> periodicWave_;
15
15
 
16
16
  explicit PeriodicWaveHostObject(
17
- const std::shared_ptr<PeriodicWaveWrapper> &wrapper);
18
-
19
- jsi::Value get(jsi::Runtime &runtime, const jsi::PropNameID &name) override;
20
-
21
- void set(
22
- jsi::Runtime &runtime,
23
- const jsi::PropNameID &name,
24
- const jsi::Value &value) override;
25
-
26
- std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime &rt) override;
27
-
28
- static std::shared_ptr<PeriodicWaveHostObject> createFromWrapper(
29
- const std::shared_ptr<PeriodicWaveWrapper> &wrapper) {
30
- return std::make_shared<PeriodicWaveHostObject>(wrapper);
31
- }
17
+ const std::shared_ptr<PeriodicWave> &periodicWave)
18
+ : periodicWave_(periodicWave) {}
32
19
  };
33
20
  } // namespace audioapi
@@ -6,7 +6,7 @@
6
6
 
7
7
  #include "AudioNodeHostObject.h"
8
8
  #include "AudioParamHostObject.h"
9
- #include "StereoPannerNodeWrapper.h"
9
+ #include "StereoPannerNode.h"
10
10
 
11
11
  namespace audioapi {
12
12
  using namespace facebook;
@@ -14,23 +14,16 @@ using namespace facebook;
14
14
  class StereoPannerNodeHostObject : public AudioNodeHostObject {
15
15
  public:
16
16
  explicit StereoPannerNodeHostObject(
17
- const std::shared_ptr<StereoPannerNodeWrapper> &wrapper);
18
-
19
- jsi::Value get(jsi::Runtime &runtime, const jsi::PropNameID &name) override;
20
-
21
- void set(
22
- jsi::Runtime &runtime,
23
- const jsi::PropNameID &name,
24
- const jsi::Value &value) override;
25
-
26
- std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime &rt) override;
27
-
28
- static std::shared_ptr<StereoPannerNodeHostObject> createFromWrapper(
29
- const std::shared_ptr<StereoPannerNodeWrapper> &wrapper) {
30
- return std::make_shared<StereoPannerNodeHostObject>(wrapper);
17
+ const std::shared_ptr<StereoPannerNode> &node)
18
+ : AudioNodeHostObject(node) {
19
+ addGetters(JSI_EXPORT_PROPERTY_GETTER(StereoPannerNodeHostObject, pan));
31
20
  }
32
21
 
33
- private:
34
- std::shared_ptr<AudioParamHostObject> panParam_;
22
+ JSI_PROPERTY_GETTER(pan) {
23
+ auto stereoPannerNode = std::static_pointer_cast<StereoPannerNode>(node_);
24
+ auto panParam_ =
25
+ std::make_shared<AudioParamHostObject>(stereoPannerNode->getPanParam());
26
+ return jsi::Object::createFromHostObject(runtime, panParam_);
27
+ }
35
28
  };
36
29
  } // namespace audioapi
@@ -3,14 +3,26 @@
3
3
  #include "AudioArray.h"
4
4
  #include "AudioBufferSourceNode.h"
5
5
  #include "AudioBus.h"
6
+ #include "AudioParam.h"
7
+ #include "AudioUtils.h"
6
8
  #include "BaseAudioContext.h"
9
+ #include "Constants.h"
7
10
 
8
11
  namespace audioapi {
9
12
 
10
13
  AudioBufferSourceNode::AudioBufferSourceNode(BaseAudioContext *context)
11
- : AudioScheduledSourceNode(context), loop_(false), bufferIndex_(0) {
14
+ : AudioScheduledSourceNode(context),
15
+ loop_(false),
16
+ loopStart_(0),
17
+ loopEnd_(0),
18
+ vReadIndex_(0.0) {
12
19
  numberOfInputs_ = 0;
13
20
  buffer_ = std::shared_ptr<AudioBuffer>(nullptr);
21
+
22
+ detuneParam_ = std::make_shared<AudioParam>(0.0, -MAX_DETUNE, MAX_DETUNE);
23
+ playbackRateParam_ = std::make_shared<AudioParam>(
24
+ 1.0, MOST_NEGATIVE_SINGLE_FLOAT, MOST_POSITIVE_SINGLE_FLOAT);
25
+
14
26
  isInitialized_ = true;
15
27
  }
16
28
 
@@ -18,6 +30,23 @@ bool AudioBufferSourceNode::getLoop() const {
18
30
  return loop_;
19
31
  }
20
32
 
33
+ double AudioBufferSourceNode::getLoopStart() const {
34
+ return loopStart_;
35
+ }
36
+
37
+ double AudioBufferSourceNode::getLoopEnd() const {
38
+ return loopEnd_;
39
+ }
40
+
41
+ std::shared_ptr<AudioParam> AudioBufferSourceNode::getDetuneParam() const {
42
+ return detuneParam_;
43
+ }
44
+
45
+ std::shared_ptr<AudioParam> AudioBufferSourceNode::getPlaybackRateParam()
46
+ const {
47
+ return playbackRateParam_;
48
+ }
49
+
21
50
  std::shared_ptr<AudioBuffer> AudioBufferSourceNode::getBuffer() const {
22
51
  return buffer_;
23
52
  }
@@ -26,120 +55,199 @@ void AudioBufferSourceNode::setLoop(bool loop) {
26
55
  loop_ = loop;
27
56
  }
28
57
 
58
+ void AudioBufferSourceNode::setLoopStart(double loopStart) {
59
+ loopStart_ = loopStart;
60
+ }
61
+
62
+ void AudioBufferSourceNode::setLoopEnd(double loopEnd) {
63
+ loopEnd_ = loopEnd;
64
+ }
65
+
29
66
  void AudioBufferSourceNode::setBuffer(
30
67
  const std::shared_ptr<AudioBuffer> &buffer) {
31
68
  if (!buffer) {
32
69
  buffer_ = std::shared_ptr<AudioBuffer>(nullptr);
70
+ alignedBus_ = std::shared_ptr<AudioBus>(nullptr);
33
71
  return;
34
72
  }
35
73
 
36
74
  buffer_ = buffer;
75
+ alignedBus_ = std::make_shared<AudioBus>(
76
+ context_->getSampleRate(), buffer_->getLength());
77
+
78
+ alignedBus_->zero();
79
+ alignedBus_->sum(buffer_->bus_.get());
37
80
  }
38
81
 
39
- // Note: AudioBus copy method will use memcpy if the source buffer and system
40
- // processing bus have same channel count, otherwise it will use the summing
41
- // function taking care of up/down mixing.
42
82
  void AudioBufferSourceNode::processNode(
43
83
  AudioBus *processingBus,
44
84
  int framesToProcess) {
85
+ size_t startOffset = 0;
86
+ size_t offsetLength = 0;
87
+
88
+ updatePlaybackInfo(processingBus, framesToProcess, startOffset, offsetLength);
89
+ float playbackRate = getPlaybackRateValue(startOffset);
90
+
45
91
  // No audio data to fill, zero the output and return.
46
- if (!isPlaying() || !buffer_ || buffer_->getLength() == 0) {
92
+ if (!isPlaying() || !alignedBus_ || alignedBus_->getSize() == 0 ||
93
+ !playbackRate) {
47
94
  processingBus->zero();
48
95
  return;
49
96
  }
50
97
 
51
- // Easiest case, the buffer is the same length as the number of frames to
52
- // process, just copy the data.
53
- if (framesToProcess == buffer_->getLength()) {
54
- processingBus->copy(buffer_->bus_.get());
98
+ if (std::fabs(playbackRate) == 1.0) {
99
+ processWithoutInterpolation(
100
+ processingBus, startOffset, offsetLength, playbackRate);
101
+ } else {
102
+ processWithInterpolation(
103
+ processingBus, startOffset, offsetLength, playbackRate);
104
+ }
55
105
 
56
- if (!loop_) {
57
- playbackState_ = PlaybackState::FINISHED;
58
- disable();
59
- }
106
+ handleStopScheduled();
107
+ }
60
108
 
61
- return;
62
- }
109
+ /**
110
+ * Helper functions
111
+ */
63
112
 
64
- // The buffer is longer than the number of frames to process.
65
- // We have to keep track of where we are in the buffer.
66
- if (framesToProcess < buffer_->getLength()) {
67
- int outputBusIndex = 0;
68
- int framesToCopy = 0;
113
+ void AudioBufferSourceNode::processWithoutInterpolation(
114
+ AudioBus *processingBus,
115
+ size_t startOffset,
116
+ size_t offsetLength,
117
+ float playbackRate) {
118
+ size_t direction = playbackRate < 0 ? -1 : 1;
69
119
 
70
- while (framesToProcess - outputBusIndex > 0) {
71
- framesToCopy = std::min(
72
- framesToProcess - outputBusIndex,
73
- buffer_->getLength() - bufferIndex_);
120
+ auto readIndex = static_cast<size_t>(vReadIndex_);
121
+ size_t writeIndex = startOffset;
74
122
 
75
- processingBus->copy(
76
- buffer_->bus_.get(), bufferIndex_, outputBusIndex, framesToCopy);
123
+ auto frameStart = static_cast<size_t>(getVirtualStartFrame());
124
+ auto frameEnd = static_cast<size_t>(getVirtualEndFrame());
125
+ size_t frameDelta = frameEnd - frameStart;
77
126
 
78
- bufferIndex_ += framesToCopy;
79
- outputBusIndex += framesToCopy;
127
+ size_t framesLeft = offsetLength;
80
128
 
81
- if (bufferIndex_ < buffer_->getLength()) {
82
- continue;
129
+ if (loop_ && (readIndex >= frameEnd || readIndex < frameStart)) {
130
+ readIndex = frameStart + (readIndex - frameStart) % frameDelta;
131
+ }
132
+
133
+ while (framesLeft > 0) {
134
+ size_t framesToEnd = frameEnd - readIndex;
135
+ size_t framesToCopy = std::min(framesToEnd, framesLeft);
136
+ framesToCopy = framesToCopy > 0 ? framesToCopy : 0;
137
+
138
+ // Direction is forward, we can normally copy the data
139
+ if (direction == 1) {
140
+ processingBus->copy(
141
+ alignedBus_.get(), readIndex, writeIndex, framesToCopy);
142
+ } else {
143
+ for (int i = 0; i < framesToCopy; i += 1) {
144
+ for (int j = 0; j < processingBus->getNumberOfChannels(); j += 1) {
145
+ (*processingBus->getChannel(j))[writeIndex + i] =
146
+ (*alignedBus_->getChannel(j))[readIndex - i];
147
+ }
83
148
  }
149
+ }
84
150
 
85
- bufferIndex_ %= buffer_->getLength();
151
+ writeIndex += framesToCopy;
152
+ readIndex += framesToCopy * direction;
153
+ framesLeft -= framesToCopy;
154
+
155
+ if (readIndex >= frameEnd || readIndex < frameStart) {
156
+ readIndex -= direction * frameDelta;
86
157
 
87
158
  if (!loop_) {
159
+ processingBus->zero(writeIndex, framesLeft);
88
160
  playbackState_ = PlaybackState::FINISHED;
89
161
  disable();
90
-
91
- if (framesToProcess - outputBusIndex > 0) {
92
- processingBus->zero(outputBusIndex, framesToProcess - outputBusIndex);
93
- }
162
+ break;
94
163
  }
95
164
  }
96
-
97
- return;
98
165
  }
99
166
 
100
- // processing bus is longer than the source buffer
101
- if (!loop_) {
102
- // If we don't loop the buffer, copy it once and zero the remaining
103
- // processing bus frames.
104
- processingBus->copy(buffer_->bus_.get());
105
- processingBus->zero(
106
- buffer_->getLength(), framesToProcess - buffer_->getLength());
167
+ // update reading index for next render quantum
168
+ vReadIndex_ = readIndex;
169
+ }
107
170
 
108
- playbackState_ = PlaybackState::FINISHED;
109
- disable();
171
+ void AudioBufferSourceNode::processWithInterpolation(
172
+ AudioBus *processingBus,
173
+ size_t startOffset,
174
+ size_t offsetLength,
175
+ float playbackRate) {
176
+ size_t direction = playbackRate < 0 ? -1 : 1;
110
177
 
111
- return;
112
- }
178
+ size_t writeIndex = startOffset;
113
179
 
114
- // If we loop the buffer, we need to loop the buffer framesToProcess /
115
- // bufferSize times There might also be a remainder of frames to copy after
116
- // the loop, which will also carry over some buffer frames to the next render
117
- // quantum.
118
- int processingBusPosition = 0;
119
- int bufferSize = buffer_->getLength();
120
- int remainingFrames = framesToProcess - framesToProcess / bufferSize;
121
-
122
- // Do we have some frames left in the buffer from the previous render quantum,
123
- // if yes copy them over and reset the buffer position.
124
- if (bufferIndex_ > 0) {
125
- processingBus->copy(buffer_->bus_.get(), 0, bufferIndex_);
126
- processingBusPosition += bufferIndex_;
127
- bufferIndex_ = 0;
128
- }
180
+ double vFrameStart = getVirtualStartFrame();
181
+ double vFrameEnd = getVirtualEndFrame();
182
+ double vFrameDelta = vFrameEnd - vFrameStart;
129
183
 
130
- // Copy the entire buffer n times to the processing bus.
131
- while (processingBusPosition + bufferSize <= framesToProcess) {
132
- processingBus->copy(buffer_->bus_.get());
133
- processingBusPosition += bufferSize;
184
+ auto frameStart = static_cast<size_t>(vFrameStart);
185
+ auto frameEnd = static_cast<size_t>(vFrameEnd);
186
+
187
+ size_t framesLeft = offsetLength;
188
+
189
+ // Wrap to the start of the loop if necessary
190
+ if (loop_ && (vReadIndex_ >= vFrameEnd || vReadIndex_ < vFrameStart)) {
191
+ vReadIndex_ =
192
+ vFrameStart + std::fmod(vReadIndex_ - vFrameStart, vFrameDelta);
134
193
  }
135
194
 
136
- // Fill in the remaining frames from the processing buffer and update buffer
137
- // index for next render quantum.
138
- if (remainingFrames > 0) {
139
- processingBus->copy(
140
- buffer_->bus_.get(), 0, processingBusPosition, remainingFrames);
141
- bufferIndex_ = remainingFrames;
195
+ while (framesLeft > 0) {
196
+ auto readIndex = static_cast<size_t>(vReadIndex_);
197
+ size_t nextReadIndex = readIndex + 1;
198
+ float factor = vReadIndex_ - readIndex;
199
+
200
+ if (nextReadIndex >= frameEnd) {
201
+ nextReadIndex = loop_ ? frameStart : readIndex;
202
+ }
203
+
204
+ for (int i = 0; i < processingBus->getNumberOfChannels(); i += 1) {
205
+ float *destination = processingBus->getChannel(i)->getData();
206
+ const float *source = alignedBus_->getChannel(i)->getData();
207
+
208
+ destination[writeIndex] = AudioUtils::linearInterpolate(
209
+ source, readIndex, nextReadIndex, factor);
210
+ }
211
+
212
+ writeIndex += 1;
213
+ vReadIndex_ += playbackRate * direction;
214
+ framesLeft -= 1;
215
+
216
+ if (vReadIndex_ < vFrameStart || vReadIndex_ >= vFrameEnd) {
217
+ vReadIndex_ -= direction * vFrameDelta;
218
+
219
+ if (!loop_) {
220
+ processingBus->zero(writeIndex, framesLeft);
221
+ playbackState_ = PlaybackState::FINISHED;
222
+ disable();
223
+ break;
224
+ }
225
+ }
142
226
  }
143
227
  }
144
228
 
229
+ float AudioBufferSourceNode::getPlaybackRateValue(size_t &startOffset) {
230
+ double time =
231
+ context_->getCurrentTime() + startOffset / context_->getSampleRate();
232
+
233
+ return playbackRateParam_->getValueAtTime(time) *
234
+ std::pow(2.0f, detuneParam_->getValueAtTime(time) / 1200.0f);
235
+ }
236
+
237
+ double AudioBufferSourceNode::getVirtualStartFrame() {
238
+ double loopStartFrame = loopStart_ * context_->getSampleRate();
239
+
240
+ return loop_ && loopStartFrame >= 0 && loopStart_ < loopEnd_ ? loopStartFrame
241
+ : 0.0;
242
+ }
243
+
244
+ double AudioBufferSourceNode::getVirtualEndFrame() {
245
+ double inputBufferLength = alignedBus_->getSize();
246
+ double loopEndFrame = loopEnd_ * context_->getSampleRate();
247
+
248
+ return loop_ && loopEndFrame > 0 && loopStart_ < loopEnd_
249
+ ? std::min(loopEndFrame, inputBufferLength)
250
+ : inputBufferLength;
251
+ }
252
+
145
253
  } // namespace audioapi
@@ -8,23 +8,63 @@
8
8
  namespace audioapi {
9
9
 
10
10
  class AudioBus;
11
+ class AudioParam;
11
12
 
12
13
  class AudioBufferSourceNode : public AudioScheduledSourceNode {
13
14
  public:
14
15
  explicit AudioBufferSourceNode(BaseAudioContext *context);
15
16
 
16
17
  [[nodiscard]] bool getLoop() const;
18
+ [[nodiscard]] double getLoopStart() const;
19
+ [[nodiscard]] double getLoopEnd() const;
20
+
21
+ [[nodiscard]] std::shared_ptr<AudioParam> getDetuneParam() const;
22
+ [[nodiscard]] std::shared_ptr<AudioParam> getPlaybackRateParam() const;
23
+
17
24
  [[nodiscard]] std::shared_ptr<AudioBuffer> getBuffer() const;
25
+
18
26
  void setLoop(bool loop);
27
+ void setLoopStart(double loopStart);
28
+ void setLoopEnd(double loopEnd);
29
+
19
30
  void setBuffer(const std::shared_ptr<AudioBuffer> &buffer);
20
31
 
21
32
  protected:
22
33
  void processNode(AudioBus *processingBus, int framesToProcess) override;
23
34
 
24
35
  private:
36
+ // Looping related properties
25
37
  bool loop_;
38
+ double loopStart_;
39
+ double loopEnd_;
40
+
41
+ // playback rate aka pitch change params
42
+ std::shared_ptr<AudioParam> detuneParam_;
43
+ std::shared_ptr<AudioParam> playbackRateParam_;
44
+
45
+ // internal helper
46
+ double vReadIndex_;
47
+
48
+ // User provided buffer
26
49
  std::shared_ptr<AudioBuffer> buffer_;
27
- int bufferIndex_;
50
+ std::shared_ptr<AudioBus> alignedBus_;
51
+
52
+ float getPlaybackRateValue(size_t &startOffset);
53
+
54
+ double getVirtualStartFrame();
55
+ double getVirtualEndFrame();
56
+
57
+ void processWithoutInterpolation(
58
+ AudioBus *processingBus,
59
+ size_t startOffset,
60
+ size_t offsetLength,
61
+ float playbackRate);
62
+
63
+ void processWithInterpolation(
64
+ AudioBus *processingBus,
65
+ size_t startOffset,
66
+ size_t offsetLength,
67
+ float playbackRate);
28
68
  };
29
69
 
30
70
  } // namespace audioapi
@@ -8,11 +8,9 @@ class AudioBus;
8
8
 
9
9
  class AudioDecoder {
10
10
  public:
11
- explicit AudioDecoder(int sampleRate);
11
+ explicit AudioDecoder(int sampleRate) : sampleRate_(sampleRate) {}
12
12
 
13
13
  [[nodiscard]] AudioBus *decodeWithFilePath(const std::string &path) const;
14
- // TODO: implement this
15
- [[nodiscard]] AudioBus *decodeWithArrayBuffer() const;
16
14
 
17
15
  private:
18
16
  int sampleRate_;
@@ -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_;