react-native-audio-api 0.1.0 → 0.3.0-rc1

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 (217) hide show
  1. package/README.md +10 -8
  2. package/RNAudioAPI.podspec +5 -0
  3. package/android/CMakeLists.txt +21 -10
  4. package/android/libs/fftw3/arm64-v8a/libfftw3.a +0 -0
  5. package/android/libs/fftw3/armeabi-v7a/libfftw3.a +0 -0
  6. package/android/libs/fftw3/x86/libfftw3.a +0 -0
  7. package/android/libs/fftw3/x86_64/libfftw3.a +0 -0
  8. package/android/libs/include/fftw3/fftw3.h +413 -0
  9. package/android/src/main/cpp/AudioPlayer/AudioPlayer.cpp +32 -2
  10. package/android/src/main/cpp/AudioPlayer/AudioPlayer.h +6 -2
  11. package/common/cpp/AudioAPIInstaller/AudioAPIInstallerHostObject.cpp +5 -3
  12. package/common/cpp/AudioAPIInstaller/AudioAPIInstallerHostObject.h +5 -1
  13. package/common/cpp/HostObjects/AudioBufferHostObject.cpp +6 -0
  14. package/common/cpp/HostObjects/AudioBufferSourceNodeHostObject.cpp +13 -1
  15. package/common/cpp/HostObjects/AudioContextHostObject.cpp +12 -149
  16. package/common/cpp/HostObjects/AudioContextHostObject.h +8 -14
  17. package/common/cpp/HostObjects/AudioNodeHostObject.cpp +0 -6
  18. package/common/cpp/HostObjects/BaseAudioContextHostObject.cpp +240 -0
  19. package/common/cpp/HostObjects/BaseAudioContextHostObject.h +41 -0
  20. package/common/cpp/HostObjects/BiquadFilterNodeHostObject.cpp +44 -0
  21. package/common/cpp/HostObjects/OscillatorNodeHostObject.cpp +21 -0
  22. package/common/cpp/HostObjects/OscillatorNodeHostObject.h +1 -0
  23. package/common/cpp/HostObjects/PeriodicWaveHostObject.cpp +33 -0
  24. package/common/cpp/HostObjects/PeriodicWaveHostObject.h +33 -0
  25. package/common/cpp/core/AudioArray.cpp +117 -0
  26. package/common/cpp/core/AudioArray.h +48 -0
  27. package/common/cpp/core/AudioBuffer.cpp +23 -80
  28. package/common/cpp/core/AudioBuffer.h +12 -13
  29. package/common/cpp/core/AudioBufferSourceNode.cpp +112 -25
  30. package/common/cpp/core/AudioBufferSourceNode.h +10 -6
  31. package/common/cpp/core/AudioBus.cpp +518 -0
  32. package/common/cpp/core/AudioBus.h +83 -0
  33. package/common/cpp/core/AudioContext.cpp +7 -77
  34. package/common/cpp/core/AudioContext.h +3 -60
  35. package/common/cpp/core/AudioDestinationNode.cpp +27 -15
  36. package/common/cpp/core/AudioDestinationNode.h +13 -5
  37. package/common/cpp/core/AudioNode.cpp +184 -22
  38. package/common/cpp/core/AudioNode.h +37 -37
  39. package/common/cpp/core/AudioNodeManager.cpp +75 -0
  40. package/common/cpp/core/AudioNodeManager.h +42 -0
  41. package/common/cpp/core/AudioParam.cpp +8 -11
  42. package/common/cpp/core/AudioParam.h +8 -8
  43. package/common/cpp/core/AudioScheduledSourceNode.cpp +19 -5
  44. package/common/cpp/core/AudioScheduledSourceNode.h +6 -2
  45. package/common/cpp/core/BaseAudioContext.cpp +191 -0
  46. package/common/cpp/core/BaseAudioContext.h +87 -0
  47. package/common/cpp/core/BiquadFilterNode.cpp +92 -69
  48. package/common/cpp/core/BiquadFilterNode.h +53 -57
  49. package/common/cpp/core/GainNode.cpp +12 -12
  50. package/common/cpp/core/GainNode.h +5 -3
  51. package/common/cpp/core/OscillatorNode.cpp +38 -29
  52. package/common/cpp/core/OscillatorNode.h +29 -69
  53. package/common/cpp/core/ParamChange.h +6 -6
  54. package/common/cpp/core/PeriodicWave.cpp +362 -0
  55. package/common/cpp/core/PeriodicWave.h +119 -0
  56. package/common/cpp/core/StereoPannerNode.cpp +31 -30
  57. package/common/cpp/core/StereoPannerNode.h +6 -6
  58. package/common/cpp/types/BiquadFilterType.h +19 -0
  59. package/common/cpp/types/ChannelCountMode.h +10 -0
  60. package/common/cpp/types/ChannelInterpretation.h +10 -0
  61. package/common/cpp/types/ContextState.h +10 -0
  62. package/common/cpp/types/OscillatorType.h +11 -0
  63. package/common/cpp/utils/FFTFrame.h +67 -0
  64. package/common/cpp/utils/JsiPromise.cpp +59 -0
  65. package/common/cpp/utils/JsiPromise.h +42 -0
  66. package/common/cpp/utils/Locker.h +49 -0
  67. package/common/cpp/utils/VectorMath.cpp +88 -3
  68. package/common/cpp/utils/VectorMath.h +7 -1
  69. package/common/cpp/utils/android/FFTFrame.cpp +23 -0
  70. package/common/cpp/utils/ios/FFTFrame.cpp +29 -0
  71. package/common/cpp/wrappers/AudioBufferSourceNodeWrapper.cpp +10 -0
  72. package/common/cpp/wrappers/AudioBufferSourceNodeWrapper.h +3 -2
  73. package/common/cpp/wrappers/AudioBufferWrapper.h +5 -5
  74. package/common/cpp/wrappers/AudioContextWrapper.cpp +7 -60
  75. package/common/cpp/wrappers/AudioContextWrapper.h +5 -26
  76. package/common/cpp/wrappers/AudioNodeWrapper.h +5 -5
  77. package/common/cpp/wrappers/AudioParamWrapper.h +4 -4
  78. package/common/cpp/wrappers/BaseAudioContextWrapper.cpp +83 -0
  79. package/common/cpp/wrappers/BaseAudioContextWrapper.h +50 -0
  80. package/common/cpp/wrappers/BiquadFilterNodeWrapper.cpp +9 -0
  81. package/common/cpp/wrappers/BiquadFilterNodeWrapper.h +9 -4
  82. package/common/cpp/wrappers/GainNodeWrapper.h +1 -1
  83. package/common/cpp/wrappers/OscillatorNodeWrapper.cpp +6 -0
  84. package/common/cpp/wrappers/OscillatorNodeWrapper.h +5 -2
  85. package/common/cpp/wrappers/PeriodicWaveWrapper.h +17 -0
  86. package/common/cpp/wrappers/StereoPannerNodeWrapper.h +1 -1
  87. package/ios/AudioAPIModule.h +20 -1
  88. package/ios/AudioAPIModule.mm +6 -4
  89. package/ios/AudioDecoder/AudioDecoder.h +17 -0
  90. package/ios/AudioDecoder/AudioDecoder.m +167 -0
  91. package/ios/AudioDecoder/IOSAudioDecoder.h +26 -0
  92. package/ios/AudioDecoder/IOSAudioDecoder.mm +40 -0
  93. package/ios/AudioPlayer/AudioPlayer.h +3 -2
  94. package/ios/AudioPlayer/AudioPlayer.m +14 -17
  95. package/ios/AudioPlayer/IOSAudioPlayer.h +7 -3
  96. package/ios/AudioPlayer/IOSAudioPlayer.mm +31 -7
  97. package/lib/module/core/AudioBuffer.js +37 -0
  98. package/lib/module/core/AudioBuffer.js.map +1 -0
  99. package/lib/module/core/AudioBufferSourceNode.js +28 -0
  100. package/lib/module/core/AudioBufferSourceNode.js.map +1 -0
  101. package/lib/module/core/AudioContext.js +10 -0
  102. package/lib/module/core/AudioContext.js.map +1 -0
  103. package/lib/module/core/AudioDestinationNode.js +7 -0
  104. package/lib/module/core/AudioDestinationNode.js.map +1 -0
  105. package/lib/module/core/AudioNode.js +22 -0
  106. package/lib/module/core/AudioNode.js.map +1 -0
  107. package/lib/module/core/AudioParam.js +35 -0
  108. package/lib/module/core/AudioParam.js.map +1 -0
  109. package/lib/module/core/AudioScheduledSourceNode.js +28 -0
  110. package/lib/module/core/AudioScheduledSourceNode.js.map +1 -0
  111. package/lib/module/core/BaseAudioContext.js +62 -0
  112. package/lib/module/core/BaseAudioContext.js.map +1 -0
  113. package/lib/module/core/BiquadFilterNode.js +25 -0
  114. package/lib/module/core/BiquadFilterNode.js.map +1 -0
  115. package/lib/module/core/GainNode.js +9 -0
  116. package/lib/module/core/GainNode.js.map +1 -0
  117. package/lib/module/core/OscillatorNode.js +24 -0
  118. package/lib/module/core/OscillatorNode.js.map +1 -0
  119. package/lib/module/core/PeriodicWave.js +8 -0
  120. package/lib/module/core/PeriodicWave.js.map +1 -0
  121. package/lib/module/core/StereoPannerNode.js +9 -0
  122. package/lib/module/core/StereoPannerNode.js.map +1 -0
  123. package/lib/module/core/types.js.map +1 -0
  124. package/lib/module/errors/IndexSizeError.js +8 -0
  125. package/lib/module/errors/IndexSizeError.js.map +1 -0
  126. package/lib/module/errors/InvalidAccessError.js +8 -0
  127. package/lib/module/errors/InvalidAccessError.js.map +1 -0
  128. package/lib/module/errors/InvalidStateError.js +8 -0
  129. package/lib/module/errors/InvalidStateError.js.map +1 -0
  130. package/lib/module/errors/RangeError.js +8 -0
  131. package/lib/module/errors/RangeError.js.map +1 -0
  132. package/lib/module/errors/index.js +5 -0
  133. package/lib/module/errors/index.js.map +1 -0
  134. package/lib/module/index.js +212 -15
  135. package/lib/module/index.js.map +1 -1
  136. package/lib/module/index.native.js +18 -0
  137. package/lib/module/index.native.js.map +1 -0
  138. package/lib/module/interfaces.js +2 -0
  139. package/lib/module/interfaces.js.map +1 -0
  140. package/lib/module/utils/resolveAudioSource.js +10 -0
  141. package/lib/module/utils/resolveAudioSource.js.map +1 -0
  142. package/lib/typescript/core/AudioBuffer.d.ts +12 -0
  143. package/lib/typescript/core/AudioBuffer.d.ts.map +1 -0
  144. package/lib/typescript/core/AudioBufferSourceNode.d.ts +12 -0
  145. package/lib/typescript/core/AudioBufferSourceNode.d.ts.map +1 -0
  146. package/lib/typescript/core/AudioContext.d.ts +6 -0
  147. package/lib/typescript/core/AudioContext.d.ts.map +1 -0
  148. package/lib/typescript/core/AudioDestinationNode.d.ts +7 -0
  149. package/lib/typescript/core/AudioDestinationNode.d.ts.map +1 -0
  150. package/lib/typescript/core/AudioNode.d.ts +16 -0
  151. package/lib/typescript/core/AudioNode.d.ts.map +1 -0
  152. package/lib/typescript/core/AudioParam.d.ts +14 -0
  153. package/lib/typescript/core/AudioParam.d.ts.map +1 -0
  154. package/lib/typescript/core/AudioScheduledSourceNode.d.ts +10 -0
  155. package/lib/typescript/core/AudioScheduledSourceNode.d.ts.map +1 -0
  156. package/lib/typescript/core/BaseAudioContext.d.ts +27 -0
  157. package/lib/typescript/core/BaseAudioContext.d.ts.map +1 -0
  158. package/lib/typescript/core/BiquadFilterNode.d.ts +16 -0
  159. package/lib/typescript/core/BiquadFilterNode.d.ts.map +1 -0
  160. package/lib/typescript/core/GainNode.d.ts +9 -0
  161. package/lib/typescript/core/GainNode.d.ts.map +1 -0
  162. package/lib/typescript/core/OscillatorNode.d.ts +15 -0
  163. package/lib/typescript/core/OscillatorNode.d.ts.map +1 -0
  164. package/lib/typescript/core/PeriodicWave.d.ts +5 -0
  165. package/lib/typescript/core/PeriodicWave.d.ts.map +1 -0
  166. package/lib/typescript/core/StereoPannerNode.d.ts +9 -0
  167. package/lib/typescript/core/StereoPannerNode.d.ts.map +1 -0
  168. package/lib/typescript/core/types.d.ts +15 -0
  169. package/lib/typescript/core/types.d.ts.map +1 -0
  170. package/lib/typescript/errors/IndexSizeError.d.ts +5 -0
  171. package/lib/typescript/errors/IndexSizeError.d.ts.map +1 -0
  172. package/lib/typescript/errors/InvalidAccessError.d.ts +5 -0
  173. package/lib/typescript/errors/InvalidAccessError.d.ts.map +1 -0
  174. package/lib/typescript/errors/InvalidStateError.d.ts +5 -0
  175. package/lib/typescript/errors/InvalidStateError.d.ts.map +1 -0
  176. package/lib/typescript/errors/RangeError.d.ts +5 -0
  177. package/lib/typescript/errors/RangeError.d.ts.map +1 -0
  178. package/lib/typescript/errors/index.d.ts +5 -0
  179. package/lib/typescript/errors/index.d.ts.map +1 -0
  180. package/lib/typescript/index.d.ts +88 -5
  181. package/lib/typescript/index.d.ts.map +1 -1
  182. package/lib/typescript/index.native.d.ts +14 -0
  183. package/lib/typescript/index.native.d.ts.map +1 -0
  184. package/lib/typescript/interfaces.d.ts +79 -0
  185. package/lib/typescript/interfaces.d.ts.map +1 -0
  186. package/lib/typescript/utils/resolveAudioSource.d.ts +3 -0
  187. package/lib/typescript/utils/resolveAudioSource.d.ts.map +1 -0
  188. package/package.json +4 -2
  189. package/src/core/AudioBuffer.ts +68 -0
  190. package/src/core/AudioBufferSourceNode.ts +35 -0
  191. package/src/core/AudioContext.ts +12 -0
  192. package/src/core/AudioDestinationNode.ts +9 -0
  193. package/src/core/AudioNode.ts +38 -0
  194. package/src/core/AudioParam.ts +55 -0
  195. package/src/core/AudioScheduledSourceNode.ts +43 -0
  196. package/src/core/BaseAudioContext.ts +108 -0
  197. package/src/core/BiquadFilterNode.ts +49 -0
  198. package/src/core/GainNode.ts +13 -0
  199. package/src/core/OscillatorNode.ts +37 -0
  200. package/src/core/PeriodicWave.ts +10 -0
  201. package/src/core/StereoPannerNode.ts +13 -0
  202. package/src/core/types.ts +33 -0
  203. package/src/errors/IndexSizeError.ts +8 -0
  204. package/src/errors/InvalidAccessError.ts +8 -0
  205. package/src/errors/InvalidStateError.ts +8 -0
  206. package/src/errors/RangeError.ts +8 -0
  207. package/src/errors/index.ts +4 -0
  208. package/src/index.native.ts +25 -0
  209. package/src/index.ts +380 -40
  210. package/src/interfaces.ts +121 -0
  211. package/src/modules/global.d.ts +3 -3
  212. package/src/utils/resolveAudioSource.ts +14 -0
  213. package/lib/module/types.js.map +0 -1
  214. package/lib/typescript/types.d.ts +0 -76
  215. package/lib/typescript/types.d.ts.map +0 -1
  216. package/src/types.ts +0 -108
  217. /package/lib/module/{types.js → core/types.js} +0 -0
@@ -8,22 +8,22 @@
8
8
 
9
9
  namespace audioapi {
10
10
 
11
- class AudioContext;
11
+ class BaseAudioContext;
12
12
 
13
13
  class AudioParam {
14
14
  public:
15
15
  explicit AudioParam(
16
- AudioContext *context,
16
+ BaseAudioContext *context,
17
17
  float defaultValue,
18
18
  float minValue,
19
19
  float maxValue);
20
20
 
21
- float getValue() const;
21
+ [[nodiscard]] float getValue() const;
22
22
  float getValueAtTime(double time);
23
23
  void setValue(float value);
24
- float getDefaultValue() const;
25
- float getMinValue() const;
26
- float getMaxValue() const;
24
+ [[nodiscard]] float getDefaultValue() const;
25
+ [[nodiscard]] float getMinValue() const;
26
+ [[nodiscard]] float getMaxValue() const;
27
27
  void setValueAtTime(float value, double startTime);
28
28
  void linearRampToValueAtTime(float value, double endTime);
29
29
  void exponentialRampToValueAtTime(float value, double endTime);
@@ -33,7 +33,7 @@ class AudioParam {
33
33
  float defaultValue_;
34
34
  float minValue_;
35
35
  float maxValue_;
36
- AudioContext *context_;
36
+ BaseAudioContext *context_;
37
37
  std::set<ParamChange> changesQueue_;
38
38
 
39
39
  double startTime_;
@@ -42,7 +42,7 @@ class AudioParam {
42
42
  float endValue_;
43
43
  std::function<float(double, double, float, float, double)> calculateValue_;
44
44
 
45
- void checkValue(float value) const;
45
+ float checkValue(float value) const;
46
46
  double getStartTime();
47
47
  float getStartValue();
48
48
  };
@@ -1,14 +1,19 @@
1
1
  #include "AudioScheduledSourceNode.h"
2
- #include "AudioContext.h"
2
+ #include "AudioNodeManager.h"
3
+ #include "BaseAudioContext.h"
3
4
 
4
5
  namespace audioapi {
5
6
 
6
- AudioScheduledSourceNode::AudioScheduledSourceNode(AudioContext *context)
7
- : AudioNode(context), isPlaying_(false) {
7
+ AudioScheduledSourceNode::AudioScheduledSourceNode(BaseAudioContext *context)
8
+ : AudioNode(context), playbackState_(PlaybackState::UNSCHEDULED) {
8
9
  numberOfInputs_ = 0;
10
+ isInitialized_ = true;
9
11
  }
10
12
 
11
13
  void AudioScheduledSourceNode::start(double time) {
14
+ context_->getNodeManager()->addSourceNode(shared_from_this());
15
+
16
+ playbackState_ = PlaybackState::SCHEDULED;
12
17
  waitAndExecute(time, [this](double time) { startPlayback(); });
13
18
  }
14
19
 
@@ -16,12 +21,21 @@ void AudioScheduledSourceNode::stop(double time) {
16
21
  waitAndExecute(time, [this](double time) { stopPlayback(); });
17
22
  }
18
23
 
24
+ bool AudioScheduledSourceNode::isPlaying() {
25
+ return playbackState_ == PlaybackState::PLAYING;
26
+ }
27
+
28
+ bool AudioScheduledSourceNode::isFinished() {
29
+ return playbackState_ == PlaybackState::FINISHED;
30
+ }
31
+
19
32
  void AudioScheduledSourceNode::startPlayback() {
20
- isPlaying_ = true;
33
+ playbackState_ = PlaybackState::PLAYING;
21
34
  }
22
35
 
23
36
  void AudioScheduledSourceNode::stopPlayback() {
24
- isPlaying_ = false;
37
+ playbackState_ = PlaybackState::FINISHED;
38
+ disable();
25
39
  }
26
40
 
27
41
  void AudioScheduledSourceNode::waitAndExecute(
@@ -13,13 +13,17 @@ namespace audioapi {
13
13
 
14
14
  class AudioScheduledSourceNode : public AudioNode {
15
15
  public:
16
- explicit AudioScheduledSourceNode(AudioContext *context);
16
+ enum class PlaybackState { UNSCHEDULED, SCHEDULED, PLAYING, FINISHED };
17
+ explicit AudioScheduledSourceNode(BaseAudioContext *context);
17
18
 
18
19
  void start(double time);
19
20
  void stop(double time);
20
21
 
22
+ bool isFinished();
23
+ bool isPlaying();
24
+
21
25
  protected:
22
- std::atomic<bool> isPlaying_;
26
+ std::atomic<PlaybackState> playbackState_;
23
27
 
24
28
  private:
25
29
  void startPlayback();
@@ -0,0 +1,191 @@
1
+ #ifdef ANDROID
2
+ #include "AudioPlayer.h"
3
+ #else
4
+ #include "IOSAudioDecoder.h"
5
+ #include "IOSAudioPlayer.h"
6
+ #endif
7
+
8
+ #include "BaseAudioContext.h"
9
+
10
+ #include "AudioArray.h"
11
+ #include "AudioBuffer.h"
12
+ #include "AudioBufferSourceNode.h"
13
+ #include "AudioBus.h"
14
+ #include "AudioDestinationNode.h"
15
+ #include "AudioNodeManager.h"
16
+ #include "BiquadFilterNode.h"
17
+ #include "ContextState.h"
18
+ #include "GainNode.h"
19
+ #include "OscillatorNode.h"
20
+ #include "StereoPannerNode.h"
21
+
22
+ namespace audioapi {
23
+
24
+ BaseAudioContext::BaseAudioContext() {
25
+ #ifdef ANDROID
26
+ audioPlayer_ = std::make_shared<AudioPlayer>(this->renderAudio());
27
+ #else
28
+ audioPlayer_ = std::make_shared<IOSAudioPlayer>(this->renderAudio());
29
+ audioDecoder_ =
30
+ std::make_shared<IOSAudioDecoder>(audioPlayer_->getSampleRate());
31
+ #endif
32
+
33
+ sampleRate_ = audioPlayer_->getSampleRate();
34
+ bufferSizeInFrames_ = audioPlayer_->getBufferSizeInFrames();
35
+
36
+ nodeManager_ = std::make_shared<AudioNodeManager>();
37
+ destination_ = std::make_shared<AudioDestinationNode>(this);
38
+ }
39
+
40
+ BaseAudioContext::~BaseAudioContext() {
41
+ if (isRunning()) {
42
+ return;
43
+ }
44
+
45
+ state_ = ContextState::CLOSED;
46
+ audioPlayer_->stop();
47
+ }
48
+
49
+ std::string BaseAudioContext::getState() {
50
+ return BaseAudioContext::toString(state_);
51
+ }
52
+
53
+ int BaseAudioContext::getSampleRate() const {
54
+ return sampleRate_;
55
+ }
56
+
57
+ int BaseAudioContext::getBufferSizeInFrames() const {
58
+ return bufferSizeInFrames_;
59
+ }
60
+
61
+ std::size_t BaseAudioContext::getCurrentSampleFrame() const {
62
+ return destination_->getCurrentSampleFrame();
63
+ }
64
+
65
+ double BaseAudioContext::getCurrentTime() const {
66
+ return destination_->getCurrentTime();
67
+ }
68
+
69
+ std::shared_ptr<AudioDestinationNode> BaseAudioContext::getDestination() {
70
+ return destination_;
71
+ }
72
+
73
+ std::shared_ptr<OscillatorNode> BaseAudioContext::createOscillator() {
74
+ return std::make_shared<OscillatorNode>(this);
75
+ }
76
+
77
+ std::shared_ptr<GainNode> BaseAudioContext::createGain() {
78
+ return std::make_shared<GainNode>(this);
79
+ }
80
+
81
+ std::shared_ptr<StereoPannerNode> BaseAudioContext::createStereoPanner() {
82
+ return std::make_shared<StereoPannerNode>(this);
83
+ }
84
+
85
+ std::shared_ptr<BiquadFilterNode> BaseAudioContext::createBiquadFilter() {
86
+ return std::make_shared<BiquadFilterNode>(this);
87
+ }
88
+
89
+ std::shared_ptr<AudioBufferSourceNode> BaseAudioContext::createBufferSource() {
90
+ return std::make_shared<AudioBufferSourceNode>(this);
91
+ }
92
+
93
+ std::shared_ptr<AudioBuffer> BaseAudioContext::createBuffer(
94
+ int numberOfChannels,
95
+ int length,
96
+ int sampleRate) {
97
+ return std::make_shared<AudioBuffer>(numberOfChannels, length, sampleRate);
98
+ }
99
+
100
+ std::shared_ptr<PeriodicWave> BaseAudioContext::createPeriodicWave(
101
+ float *real,
102
+ float *imag,
103
+ bool disableNormalization,
104
+ int length) {
105
+ return std::make_shared<PeriodicWave>(
106
+ sampleRate_, real, imag, length, disableNormalization);
107
+ }
108
+
109
+ #ifdef ANDROID
110
+ std::shared_ptr<AudioBuffer> BaseAudioContext::decodeAudioDataSource(
111
+ const std::string &source) {
112
+ return {nullptr};
113
+ }
114
+ #else
115
+ std::shared_ptr<AudioBuffer> BaseAudioContext::decodeAudioDataSource(
116
+ const std::string &source) {
117
+ auto audioBus = audioDecoder_->decodeWithFilePath(source);
118
+ return std::make_shared<AudioBuffer>(audioBus);
119
+ }
120
+ #endif
121
+
122
+ std::function<void(AudioBus *, int)> BaseAudioContext::renderAudio() {
123
+ if (isClosed()) {
124
+ return [](AudioBus *, int) {};
125
+ }
126
+
127
+ return [this](AudioBus *data, int frames) {
128
+ destination_->renderAudio(data, frames);
129
+ };
130
+ }
131
+
132
+ AudioNodeManager *BaseAudioContext::getNodeManager() {
133
+ return nodeManager_.get();
134
+ }
135
+
136
+ bool BaseAudioContext::isRunning() const {
137
+ return state_ == ContextState::RUNNING;
138
+ }
139
+
140
+ bool BaseAudioContext::isClosed() const {
141
+ return state_ == ContextState::CLOSED;
142
+ }
143
+
144
+ std::string BaseAudioContext::toString(ContextState state) {
145
+ switch (state) {
146
+ case ContextState::SUSPENDED:
147
+ return "suspended";
148
+ case ContextState::RUNNING:
149
+ return "running";
150
+ case ContextState::CLOSED:
151
+ return "closed";
152
+ default:
153
+ throw std::invalid_argument("Unknown context state");
154
+ }
155
+ }
156
+
157
+ std::shared_ptr<PeriodicWave> BaseAudioContext::getBasicWaveForm(
158
+ OscillatorType type) {
159
+ switch (type) {
160
+ case OscillatorType::SINE:
161
+ if (cachedSineWave_ == nullptr) {
162
+ cachedSineWave_ =
163
+ std::make_shared<PeriodicWave>(sampleRate_, type, false);
164
+ }
165
+ return cachedSineWave_;
166
+ case OscillatorType::SQUARE:
167
+ if (cachedSquareWave_ == nullptr) {
168
+ cachedSquareWave_ =
169
+ std::make_shared<PeriodicWave>(sampleRate_, type, false);
170
+ }
171
+ return cachedSquareWave_;
172
+ case OscillatorType::SAWTOOTH:
173
+ if (cachedSawtoothWave_ == nullptr) {
174
+ cachedSawtoothWave_ =
175
+ std::make_shared<PeriodicWave>(sampleRate_, type, false);
176
+ }
177
+ return cachedSawtoothWave_;
178
+ case OscillatorType::TRIANGLE:
179
+ if (cachedTriangleWave_ == nullptr) {
180
+ cachedTriangleWave_ =
181
+ std::make_shared<PeriodicWave>(sampleRate_, type, false);
182
+ }
183
+ return cachedTriangleWave_;
184
+ case OscillatorType::CUSTOM:
185
+ throw std::invalid_argument(
186
+ "You can't get a custom wave form. You need to create it.");
187
+ break;
188
+ }
189
+ }
190
+
191
+ } // namespace audioapi
@@ -0,0 +1,87 @@
1
+ #pragma once
2
+
3
+ #include <functional>
4
+ #include <memory>
5
+ #include <string>
6
+ #include <utility>
7
+ #include <vector>
8
+
9
+ #include "ContextState.h"
10
+ #include "OscillatorType.h"
11
+
12
+ namespace audioapi {
13
+
14
+ class AudioBus;
15
+ class GainNode;
16
+ class AudioBuffer;
17
+ class PeriodicWave;
18
+ class OscillatorNode;
19
+ class StereoPannerNode;
20
+ class AudioNodeManager;
21
+ class BiquadFilterNode;
22
+ class AudioDestinationNode;
23
+ class AudioBufferSourceNode;
24
+
25
+ #ifdef ANDROID
26
+ class AudioPlayer;
27
+ #else
28
+ class IOSAudioPlayer;
29
+ class IOSAudioDecoder;
30
+ #endif
31
+
32
+ class BaseAudioContext {
33
+ public:
34
+ BaseAudioContext();
35
+ ~BaseAudioContext();
36
+ std::string getState();
37
+ [[nodiscard]] int getSampleRate() const;
38
+ [[nodiscard]] double getCurrentTime() const;
39
+ [[nodiscard]] int getBufferSizeInFrames() const;
40
+ [[nodiscard]] std::size_t getCurrentSampleFrame() const;
41
+
42
+ std::shared_ptr<AudioDestinationNode> getDestination();
43
+ std::shared_ptr<OscillatorNode> createOscillator();
44
+ std::shared_ptr<GainNode> createGain();
45
+ std::shared_ptr<StereoPannerNode> createStereoPanner();
46
+ std::shared_ptr<BiquadFilterNode> createBiquadFilter();
47
+ std::shared_ptr<AudioBufferSourceNode> createBufferSource();
48
+ static std::shared_ptr<AudioBuffer>
49
+ createBuffer(int numberOfChannels, int length, int sampleRate);
50
+ std::shared_ptr<PeriodicWave> createPeriodicWave(
51
+ float *real,
52
+ float *imag,
53
+ bool disableNormalization,
54
+ int length);
55
+ std::shared_ptr<AudioBuffer> decodeAudioDataSource(const std::string &source);
56
+
57
+ std::shared_ptr<PeriodicWave> getBasicWaveForm(OscillatorType type);
58
+ std::function<void(AudioBus *, int)> renderAudio();
59
+
60
+ AudioNodeManager *getNodeManager();
61
+ [[nodiscard]] bool isRunning() const;
62
+ [[nodiscard]] bool isClosed() const;
63
+
64
+ protected:
65
+ static std::string toString(ContextState state);
66
+ std::shared_ptr<AudioDestinationNode> destination_;
67
+
68
+ #ifdef ANDROID
69
+ std::shared_ptr<AudioPlayer> audioPlayer_;
70
+ #else
71
+ std::shared_ptr<IOSAudioPlayer> audioPlayer_;
72
+ std::shared_ptr<IOSAudioDecoder> audioDecoder_;
73
+ #endif
74
+
75
+ int sampleRate_;
76
+ int bufferSizeInFrames_;
77
+ ContextState state_ = ContextState::RUNNING;
78
+ std::shared_ptr<AudioNodeManager> nodeManager_;
79
+
80
+ private:
81
+ std::shared_ptr<PeriodicWave> cachedSineWave_ = nullptr;
82
+ std::shared_ptr<PeriodicWave> cachedSquareWave_ = nullptr;
83
+ std::shared_ptr<PeriodicWave> cachedSawtoothWave_ = nullptr;
84
+ std::shared_ptr<PeriodicWave> cachedTriangleWave_ = nullptr;
85
+ };
86
+
87
+ } // namespace audioapi
@@ -1,14 +1,15 @@
1
1
  #include "BiquadFilterNode.h"
2
- #include "AudioContext.h"
2
+ #include "AudioArray.h"
3
+ #include "AudioBus.h"
4
+ #include "BaseAudioContext.h"
3
5
 
4
6
  // https://webaudio.github.io/Audio-EQ-Cookbook/audio-eq-cookbook.html - math
5
7
  // formulas for filters
6
- // https://github.com/LabSound/LabSound/blob/main/src/internal/src/Biquad.cpp -
7
- // implementation of filters on which I based mine
8
8
 
9
9
  namespace audioapi {
10
10
 
11
- BiquadFilterNode::BiquadFilterNode(AudioContext *context) : AudioNode(context) {
11
+ BiquadFilterNode::BiquadFilterNode(BaseAudioContext *context)
12
+ : AudioNode(context) {
12
13
  frequencyParam_ = std::make_shared<AudioParam>(
13
14
  context, 350.0, MIN_FILTER_FREQUENCY, MAX_FILTER_FREQUENCY);
14
15
  detuneParam_ =
@@ -17,10 +18,11 @@ BiquadFilterNode::BiquadFilterNode(AudioContext *context) : AudioNode(context) {
17
18
  std::make_shared<AudioParam>(context, 1.0, -MAX_FILTER_Q, MAX_FILTER_Q);
18
19
  gainParam_ = std::make_shared<AudioParam>(
19
20
  context, 0.0, MIN_FILTER_GAIN, MAX_FILTER_GAIN);
20
- type_ = FilterType::LOWPASS;
21
+ type_ = BiquadFilterType::LOWPASS;
22
+ isInitialized_ = true;
21
23
  }
22
24
 
23
- std::string BiquadFilterNode::getType() const {
25
+ std::string BiquadFilterNode::getType() {
24
26
  return BiquadFilterNode::toString(type_);
25
27
  }
26
28
 
@@ -44,8 +46,37 @@ std::shared_ptr<AudioParam> BiquadFilterNode::getGainParam() const {
44
46
  return gainParam_;
45
47
  }
46
48
 
47
- float BiquadFilterNode::clamp(float value, float min, float max) {
48
- return std::min(std::max(value, min), max);
49
+ // Compute Z-transform of the filter
50
+ // https://www.dsprelated.com/freebooks/filters/Frequency_Response_Analysis.html
51
+ // https://www.dsprelated.com/freebooks/filters/Transfer_Function_Analysis.html
52
+ //
53
+ // frequency response - H(z) = (b0 + b1*z^(-1) + b2*z^(-2))/(1 + a1*z^(-1) +
54
+ // a2*z^(-2)) = ((b0 * z + b1) * z + b2) / ((z + a1) * z + a2) phase response -
55
+ // angle of the frequency response
56
+
57
+ void BiquadFilterNode::getFrequencyResponse(
58
+ const std::vector<float> &frequencyArray,
59
+ std::vector<float> &magResponseOutput,
60
+ std::vector<float> &phaseResponseOutput) {
61
+ applyFilter();
62
+
63
+ auto frequencyArraySize = frequencyArray.size();
64
+
65
+ float b0 = b0_;
66
+ float b1 = b1_;
67
+ float b2 = b2_;
68
+ float a1 = a1_;
69
+ float a2 = a2_;
70
+
71
+ for (size_t i = 0; i < frequencyArraySize; i++) {
72
+ auto omega =
73
+ static_cast<float>(M_PI) * frequencyArray[i] / NYQUIST_FREQUENCY;
74
+ auto z = std::complex<float>(cos(omega), sin(omega));
75
+ auto response = ((b0 * z + b1) * z + b2) / ((z + a1) * z + a2);
76
+ magResponseOutput[i] = static_cast<float>(abs(response));
77
+ phaseResponseOutput[i] =
78
+ static_cast<float>(atan2(imag(response), real(response)));
79
+ }
49
80
  }
50
81
 
51
82
  void BiquadFilterNode::resetCoefficients() {
@@ -62,16 +93,16 @@ void BiquadFilterNode::setNormalizedCoefficients(
62
93
  float a0,
63
94
  float a1,
64
95
  float a2) {
65
- auto a0Inversed = 1.0f / a0;
66
- b0_ = b0 * a0Inversed;
67
- b1_ = b1 * a0Inversed;
68
- b2_ = b2 * a0Inversed;
69
- a1_ = a1 * a0Inversed;
70
- a2_ = a2 * a0Inversed;
96
+ auto a0Inverted = 1.0f / a0;
97
+ b0_ = b0 * a0Inverted;
98
+ b1_ = b1 * a0Inverted;
99
+ b2_ = b2 * a0Inverted;
100
+ a1_ = a1 * a0Inverted;
101
+ a2_ = a2 * a0Inverted;
71
102
  }
72
103
 
73
104
  void BiquadFilterNode::setLowpassCoefficients(float frequency, float Q) {
74
- frequency = clamp(frequency, 0.0, 1.0);
105
+ frequency = std::clamp(frequency, 0.0f, 1.0f);
75
106
  if (frequency == 1.0) {
76
107
  setNormalizedCoefficients(1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f);
77
108
  return;
@@ -83,20 +114,18 @@ void BiquadFilterNode::setLowpassCoefficients(float frequency, float Q) {
83
114
 
84
115
  Q = std::max(0.0f, Q);
85
116
  float g = std::pow(10.0f, 0.05f * Q);
86
- float d = std::sqrt((4 - std::sqrt(16 - 16 / (g * g))) / 2);
87
117
 
88
118
  float theta = M_PI * frequency;
89
- float sn = 0.5f * d * std::sin(theta);
90
- float beta = 0.5f * (1 - sn) / (1 + sn);
91
- float gamma = (0.5f + beta) * std::cos(theta);
92
- float alpha = 0.25f * (0.5f + beta - gamma);
119
+ float alpha = std::sin(theta) / (2 * g);
120
+ float cosW = std::cos(theta);
121
+ float beta = (1 - cosW) / 2;
93
122
 
94
123
  setNormalizedCoefficients(
95
- 2 * alpha, 4 * alpha, 2 * alpha, 1.0f, -2 * gamma, 2 * beta);
124
+ beta, 2 * beta, beta, 1 + alpha, -2 * cosW, 1 - alpha);
96
125
  }
97
126
 
98
127
  void BiquadFilterNode::setHighpassCoefficients(float frequency, float Q) {
99
- frequency = clamp(frequency, 0.0, 1.0);
128
+ frequency = std::clamp(frequency, 0.0f, 1.0f);
100
129
  if (frequency == 1.0) {
101
130
  setNormalizedCoefficients(0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f);
102
131
  return;
@@ -108,20 +137,18 @@ void BiquadFilterNode::setHighpassCoefficients(float frequency, float Q) {
108
137
 
109
138
  Q = std::max(0.0f, Q);
110
139
  float g = std::pow(10.0f, 0.05f * Q);
111
- float d = std::sqrt((4 - std::sqrt(16 - 16 / (g * g))) / 2);
112
140
 
113
141
  float theta = M_PI * frequency;
114
- float sn = 0.5f * d * std::sin(theta);
115
- float beta = 0.5f * (1 - sn) / (1 + sn);
116
- float gamma = (0.5f + beta) * std::cos(theta);
117
- float alpha = 0.25f * (0.5f + beta - gamma);
142
+ float alpha = std::sin(theta) / (2 * g);
143
+ float cosW = std::cos(theta);
144
+ float beta = (1 - cosW) / 2;
118
145
 
119
146
  setNormalizedCoefficients(
120
- 2 * alpha, -4 * alpha, 2 * alpha, 1.0f, -2 * gamma, 2 * beta);
147
+ beta, -2 * beta, beta, 1 + alpha, -2 * cosW, 1 - alpha);
121
148
  }
122
149
 
123
150
  void BiquadFilterNode::setBandpassCoefficients(float frequency, float Q) {
124
- frequency = clamp(frequency, 0.0, 1.0);
151
+ frequency = std::clamp(frequency, 0.0f, 1.0f);
125
152
  Q = std::max(0.0f, Q);
126
153
 
127
154
  if (frequency <= 0.0 || frequency >= 1.0) {
@@ -143,7 +170,7 @@ void BiquadFilterNode::setBandpassCoefficients(float frequency, float Q) {
143
170
  }
144
171
 
145
172
  void BiquadFilterNode::setLowshelfCoefficients(float frequency, float gain) {
146
- frequency = clamp(frequency, 0.0, 1.0);
173
+ frequency = std::clamp(frequency, 0.0f, 1.0f);
147
174
  float A = std::pow(10.0f, gain / 40.0f);
148
175
 
149
176
  if (frequency == 1.0) {
@@ -172,7 +199,7 @@ void BiquadFilterNode::setLowshelfCoefficients(float frequency, float gain) {
172
199
  }
173
200
 
174
201
  void BiquadFilterNode::setHighshelfCoefficients(float frequency, float gain) {
175
- frequency = clamp(frequency, 0.0, 1.0);
202
+ frequency = std::clamp(frequency, 0.0f, 1.0f);
176
203
  float A = std::pow(10.0f, gain / 40.0f);
177
204
 
178
205
  if (frequency == 1.0) {
@@ -204,7 +231,7 @@ void BiquadFilterNode::setPeakingCoefficients(
204
231
  float frequency,
205
232
  float Q,
206
233
  float gain) {
207
- frequency = clamp(frequency, 0.0, 1.0);
234
+ frequency = std::clamp(frequency, 0.0f, 1.0f);
208
235
  Q = std::max(0.0f, Q);
209
236
  float A = std::pow(10.0f, gain / 40.0f);
210
237
 
@@ -232,7 +259,7 @@ void BiquadFilterNode::setPeakingCoefficients(
232
259
  }
233
260
 
234
261
  void BiquadFilterNode::setNotchCoefficients(float frequency, float Q) {
235
- frequency = clamp(frequency, 0.0, 1.0);
262
+ frequency = std::clamp(frequency, 0.0f, 1.0f);
236
263
  Q = std::max(0.0f, Q);
237
264
 
238
265
  if (frequency <= 0.0 || frequency >= 1.0) {
@@ -253,7 +280,7 @@ void BiquadFilterNode::setNotchCoefficients(float frequency, float Q) {
253
280
  }
254
281
 
255
282
  void BiquadFilterNode::setAllpassCoefficients(float frequency, float Q) {
256
- frequency = clamp(frequency, 0.0, 1.0);
283
+ frequency = std::clamp(frequency, 0.0f, 1.0f);
257
284
  Q = std::max(0.0f, Q);
258
285
 
259
286
  if (frequency <= 0.0 || frequency >= 1.0) {
@@ -286,37 +313,37 @@ void BiquadFilterNode::applyFilter() {
286
313
  }
287
314
 
288
315
  switch (type_) {
289
- case FilterType::LOWPASS:
316
+ case BiquadFilterType::LOWPASS:
290
317
  setLowpassCoefficients(
291
318
  normalizedFrequency, QParam_->getValueAtTime(currentTime));
292
319
  break;
293
- case FilterType::HIGHPASS:
320
+ case BiquadFilterType::HIGHPASS:
294
321
  setHighpassCoefficients(
295
322
  normalizedFrequency, QParam_->getValueAtTime(currentTime));
296
323
  break;
297
- case FilterType::BANDPASS:
324
+ case BiquadFilterType::BANDPASS:
298
325
  setBandpassCoefficients(
299
326
  normalizedFrequency, QParam_->getValueAtTime(currentTime));
300
327
  break;
301
- case FilterType::LOWSHELF:
328
+ case BiquadFilterType::LOWSHELF:
302
329
  setLowshelfCoefficients(
303
330
  normalizedFrequency, gainParam_->getValueAtTime(currentTime));
304
331
  break;
305
- case FilterType::HIGHSHELF:
332
+ case BiquadFilterType::HIGHSHELF:
306
333
  setHighshelfCoefficients(
307
334
  normalizedFrequency, gainParam_->getValueAtTime(currentTime));
308
335
  break;
309
- case FilterType::PEAKING:
336
+ case BiquadFilterType::PEAKING:
310
337
  setPeakingCoefficients(
311
338
  normalizedFrequency,
312
339
  QParam_->getValueAtTime(currentTime),
313
340
  gainParam_->getValueAtTime(currentTime));
314
341
  break;
315
- case FilterType::NOTCH:
342
+ case BiquadFilterType::NOTCH:
316
343
  setNotchCoefficients(
317
344
  normalizedFrequency, QParam_->getValueAtTime(currentTime));
318
345
  break;
319
- case FilterType::ALLPASS:
346
+ case BiquadFilterType::ALLPASS:
320
347
  setAllpassCoefficients(
321
348
  normalizedFrequency, QParam_->getValueAtTime(currentTime));
322
349
  break;
@@ -325,40 +352,36 @@ void BiquadFilterNode::applyFilter() {
325
352
  }
326
353
  }
327
354
 
328
- bool BiquadFilterNode::processAudio(float *audioData, int32_t numFrames) {
329
- if (!AudioNode::processAudio(audioData, numFrames)) {
330
- return false;
331
- }
332
-
355
+ void BiquadFilterNode::processNode(
356
+ AudioBus *processingBus,
357
+ int framesToProcess) {
333
358
  resetCoefficients();
334
359
  applyFilter();
335
360
 
336
- float x1 = x1_;
337
- float x2 = x2_;
338
- float y1 = y1_;
339
- float y2 = y2_;
361
+ for (int c = 0; c < processingBus->getNumberOfChannels(); c += 1) {
362
+ float x1 = x1_;
363
+ float x2 = x2_;
364
+ float y1 = y1_;
365
+ float y2 = y2_;
340
366
 
341
- float b0 = b0_;
342
- float b1 = b1_;
343
- float b2 = b2_;
344
- float a1 = a1_;
345
- float a2 = a2_;
367
+ float b0 = b0_;
368
+ float b1 = b1_;
369
+ float b2 = b2_;
370
+ float a1 = a1_;
371
+ float a2 = a2_;
346
372
 
347
- for (int i = 0; i < numFrames; i++) {
348
- auto input = audioData[i * channelCount_];
349
- auto output =
350
- static_cast<float>(b0 * input + b1 * x1 + b2 * x2 - a1 * y1 - a2 * y2);
373
+ for (int i = 0; i < framesToProcess; i += 1) {
374
+ float input = (*processingBus->getChannel(c))[i];
375
+ float output = b0 * input + b1 * x1 + b2 * x2 - a1 * y1 - a2 * y2;
351
376
 
352
- for (int j = 0; j < channelCount_; j++) {
353
- audioData[i * channelCount_ + j] = output;
354
- }
377
+ (*processingBus->getChannel(c))[i] = output;
355
378
 
356
- x2 = x1;
357
- x1 = input;
358
- y2 = y1;
359
- y1 = output;
379
+ x2 = x1;
380
+ x1 = input;
381
+ y2 = y1;
382
+ y1 = output;
383
+ }
360
384
  }
361
-
362
- return true;
363
385
  }
386
+
364
387
  } // namespace audioapi