react-native-audio-api 0.0.1 → 0.1.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 (116) hide show
  1. package/README.md +58 -1
  2. package/RNAudioAPI.podspec +41 -0
  3. package/android/CMakeLists.txt +63 -0
  4. package/android/build.gradle +194 -0
  5. package/android/gradle.properties +5 -0
  6. package/android/src/main/AndroidManifest.xml +3 -0
  7. package/android/src/main/AndroidManifestNew.xml +2 -0
  8. package/android/src/main/cpp/AudioAPIInstaller/AudioAPIInstaller.cpp +22 -0
  9. package/android/src/main/cpp/AudioAPIInstaller/AudioAPIInstaller.h +48 -0
  10. package/android/src/main/cpp/AudioPlayer/AudioPlayer.cpp +45 -0
  11. package/android/src/main/cpp/AudioPlayer/AudioPlayer.h +30 -0
  12. package/android/src/main/cpp/OnLoad.cpp +9 -0
  13. package/android/src/main/java/com/swmansion/audioapi/AudioAPIPackage.kt +14 -0
  14. package/android/src/main/java/com/swmansion/audioapi/module/AudioAPIInstaller.kt +21 -0
  15. package/android/src/main/java/com/swmansion/audioapi/nativemodules/AudioAPIModule.kt +25 -0
  16. package/common/cpp/AudioAPIInstaller/AudioAPIInstallerHostObject.cpp +52 -0
  17. package/common/cpp/AudioAPIInstaller/AudioAPIInstallerHostObject.h +45 -0
  18. package/common/cpp/AudioAPIInstaller/AudioAPIInstallerWrapper.h +38 -0
  19. package/common/cpp/AudioAPIInstaller/android/AudioAPIInstallerWrapper.cpp +16 -0
  20. package/common/cpp/AudioAPIInstaller/ios/AudioAPIInstallerWrapper.cpp +12 -0
  21. package/common/cpp/HostObjects/AudioBufferHostObject.cpp +143 -0
  22. package/common/cpp/HostObjects/AudioBufferHostObject.h +33 -0
  23. package/common/cpp/HostObjects/AudioBufferSourceNodeHostObject.cpp +67 -0
  24. package/common/cpp/HostObjects/AudioBufferSourceNodeHostObject.h +37 -0
  25. package/common/cpp/HostObjects/AudioContextHostObject.cpp +191 -0
  26. package/common/cpp/HostObjects/AudioContextHostObject.h +43 -0
  27. package/common/cpp/HostObjects/AudioDestinationNodeHostObject.cpp +33 -0
  28. package/common/cpp/HostObjects/AudioDestinationNodeHostObject.h +31 -0
  29. package/common/cpp/HostObjects/AudioNodeHostObject.cpp +108 -0
  30. package/common/cpp/HostObjects/AudioNodeHostObject.h +29 -0
  31. package/common/cpp/HostObjects/AudioParamHostObject.cpp +115 -0
  32. package/common/cpp/HostObjects/AudioParamHostObject.h +34 -0
  33. package/common/cpp/HostObjects/AudioScheduledSourceNodeHostObject.cpp +73 -0
  34. package/common/cpp/HostObjects/AudioScheduledSourceNodeHostObject.h +31 -0
  35. package/common/cpp/HostObjects/BiquadFilterNodeHostObject.cpp +81 -0
  36. package/common/cpp/HostObjects/BiquadFilterNodeHostObject.h +42 -0
  37. package/common/cpp/HostObjects/Constants.h +22 -0
  38. package/common/cpp/HostObjects/GainNodeHostObject.cpp +41 -0
  39. package/common/cpp/HostObjects/GainNodeHostObject.h +32 -0
  40. package/common/cpp/HostObjects/OscillatorNodeHostObject.cpp +67 -0
  41. package/common/cpp/HostObjects/OscillatorNodeHostObject.h +40 -0
  42. package/common/cpp/HostObjects/StereoPannerNodeHostObject.cpp +41 -0
  43. package/common/cpp/HostObjects/StereoPannerNodeHostObject.h +36 -0
  44. package/common/cpp/core/AudioBuffer.cpp +115 -0
  45. package/common/cpp/core/AudioBuffer.h +42 -0
  46. package/common/cpp/core/AudioBufferSourceNode.cpp +58 -0
  47. package/common/cpp/core/AudioBufferSourceNode.h +26 -0
  48. package/common/cpp/core/AudioContext.cpp +90 -0
  49. package/common/cpp/core/AudioContext.h +73 -0
  50. package/common/cpp/core/AudioDestinationNode.cpp +35 -0
  51. package/common/cpp/core/AudioDestinationNode.h +24 -0
  52. package/common/cpp/core/AudioNode.cpp +68 -0
  53. package/common/cpp/core/AudioNode.h +74 -0
  54. package/common/cpp/core/AudioParam.cpp +136 -0
  55. package/common/cpp/core/AudioParam.h +50 -0
  56. package/common/cpp/core/AudioScheduledSourceNode.cpp +39 -0
  57. package/common/cpp/core/AudioScheduledSourceNode.h +30 -0
  58. package/common/cpp/core/BiquadFilterNode.cpp +364 -0
  59. package/common/cpp/core/BiquadFilterNode.h +128 -0
  60. package/common/cpp/core/GainNode.cpp +30 -0
  61. package/common/cpp/core/GainNode.h +23 -0
  62. package/common/cpp/core/OscillatorNode.cpp +66 -0
  63. package/common/cpp/core/OscillatorNode.h +112 -0
  64. package/common/cpp/core/ParamChange.cpp +46 -0
  65. package/common/cpp/core/ParamChange.h +34 -0
  66. package/common/cpp/core/StereoPannerNode.cpp +58 -0
  67. package/common/cpp/core/StereoPannerNode.h +26 -0
  68. package/common/cpp/utils/VectorMath.cpp +609 -0
  69. package/common/cpp/utils/VectorMath.h +65 -0
  70. package/common/cpp/wrappers/AudioBufferSourceNodeWrapper.cpp +35 -0
  71. package/common/cpp/wrappers/AudioBufferSourceNodeWrapper.h +25 -0
  72. package/common/cpp/wrappers/AudioBufferWrapper.cpp +46 -0
  73. package/common/cpp/wrappers/AudioBufferWrapper.h +30 -0
  74. package/common/cpp/wrappers/AudioContextWrapper.cpp +70 -0
  75. package/common/cpp/wrappers/AudioContextWrapper.h +40 -0
  76. package/common/cpp/wrappers/AudioDestinationNodeWrapper.h +16 -0
  77. package/common/cpp/wrappers/AudioNodeWrapper.cpp +37 -0
  78. package/common/cpp/wrappers/AudioNodeWrapper.h +25 -0
  79. package/common/cpp/wrappers/AudioParamWrapper.cpp +42 -0
  80. package/common/cpp/wrappers/AudioParamWrapper.h +25 -0
  81. package/common/cpp/wrappers/AudioScheduledSourceNodeWrapper.cpp +23 -0
  82. package/common/cpp/wrappers/AudioScheduledSourceNodeWrapper.h +23 -0
  83. package/common/cpp/wrappers/BiquadFilterNodeWrapper.cpp +51 -0
  84. package/common/cpp/wrappers/BiquadFilterNodeWrapper.h +32 -0
  85. package/common/cpp/wrappers/GainNodeWrapper.cpp +14 -0
  86. package/common/cpp/wrappers/GainNodeWrapper.h +20 -0
  87. package/common/cpp/wrappers/OscillatorNodeWrapper.cpp +38 -0
  88. package/common/cpp/wrappers/OscillatorNodeWrapper.h +28 -0
  89. package/common/cpp/wrappers/StereoPannerNodeWrapper.cpp +16 -0
  90. package/common/cpp/wrappers/StereoPannerNodeWrapper.h +21 -0
  91. package/ios/AudioAPIModule.h +5 -0
  92. package/ios/AudioAPIModule.mm +44 -0
  93. package/ios/AudioPlayer/AudioPlayer.h +27 -0
  94. package/ios/AudioPlayer/AudioPlayer.m +121 -0
  95. package/ios/AudioPlayer/IOSAudioPlayer.h +29 -0
  96. package/ios/AudioPlayer/IOSAudioPlayer.mm +34 -0
  97. package/lib/module/index.js +39 -0
  98. package/lib/module/index.js.map +1 -0
  99. package/lib/module/modules/global.d.js +2 -0
  100. package/lib/module/modules/global.d.js.map +1 -0
  101. package/lib/module/types.js +2 -0
  102. package/lib/module/types.js.map +1 -0
  103. package/lib/module/utils/install.js +22 -0
  104. package/lib/module/utils/install.js.map +1 -0
  105. package/lib/typescript/index.d.ts +18 -0
  106. package/lib/typescript/index.d.ts.map +1 -0
  107. package/lib/typescript/types.d.ts +76 -0
  108. package/lib/typescript/types.d.ts.map +1 -0
  109. package/lib/typescript/utils/install.d.ts +7 -0
  110. package/lib/typescript/utils/install.d.ts.map +1 -0
  111. package/package.json +104 -5
  112. package/src/index.ts +79 -0
  113. package/src/modules/global.d.ts +10 -0
  114. package/src/types.ts +108 -0
  115. package/src/utils/install.ts +39 -0
  116. package/index.ts +0 -1
@@ -0,0 +1,40 @@
1
+ #pragma once
2
+
3
+ #include <memory>
4
+ #include <string>
5
+ #include <vector>
6
+
7
+ #include "AudioParamHostObject.h"
8
+ #include "AudioScheduledSourceNodeHostObject.h"
9
+ #include "OscillatorNodeWrapper.h"
10
+
11
+ namespace audioapi {
12
+ using namespace facebook;
13
+
14
+ class OscillatorNodeHostObject : public AudioScheduledSourceNodeHostObject {
15
+ public:
16
+ explicit OscillatorNodeHostObject(
17
+ const std::shared_ptr<OscillatorNodeWrapper> &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<OscillatorNodeHostObject> createFromWrapper(
29
+ const std::shared_ptr<OscillatorNodeWrapper> &wrapper) {
30
+ return std::make_shared<OscillatorNodeHostObject>(wrapper);
31
+ }
32
+
33
+ private:
34
+ std::shared_ptr<AudioParamHostObject> frequencyParam_;
35
+ std::shared_ptr<AudioParamHostObject> detuneParam_;
36
+
37
+ std::shared_ptr<OscillatorNodeWrapper>
38
+ getOscillatorNodeWrapperFromAudioNodeWrapper();
39
+ };
40
+ } // namespace audioapi
@@ -0,0 +1,41 @@
1
+ #include "StereoPannerNodeHostObject.h"
2
+
3
+ namespace audioapi {
4
+ using namespace facebook;
5
+
6
+ StereoPannerNodeHostObject::StereoPannerNodeHostObject(
7
+ const std::shared_ptr<StereoPannerNodeWrapper> &wrapper)
8
+ : AudioNodeHostObject(wrapper) {
9
+ auto panParam = wrapper->getPanParam();
10
+ panParam_ = AudioParamHostObject::createFromWrapper(panParam);
11
+ }
12
+
13
+ std::vector<jsi::PropNameID> StereoPannerNodeHostObject::getPropertyNames(
14
+ jsi::Runtime &runtime) {
15
+ std::vector<jsi::PropNameID> propertyNames =
16
+ AudioNodeHostObject::getPropertyNames(runtime);
17
+ propertyNames.push_back(jsi::PropNameID::forAscii(runtime, "pan"));
18
+ return propertyNames;
19
+ }
20
+
21
+ jsi::Value StereoPannerNodeHostObject::get(
22
+ jsi::Runtime &runtime,
23
+ const jsi::PropNameID &propNameId) {
24
+ auto propName = propNameId.utf8(runtime);
25
+
26
+ if (propName == "pan") {
27
+ return jsi::Object::createFromHostObject(runtime, panParam_);
28
+ }
29
+
30
+ return AudioNodeHostObject::get(runtime, propNameId);
31
+ }
32
+
33
+ void StereoPannerNodeHostObject::set(
34
+ jsi::Runtime &runtime,
35
+ const jsi::PropNameID &propNameId,
36
+ const jsi::Value &value) {
37
+ auto propName = propNameId.utf8(runtime);
38
+
39
+ return AudioNodeHostObject::set(runtime, propNameId, value);
40
+ }
41
+ } // namespace audioapi
@@ -0,0 +1,36 @@
1
+ #pragma once
2
+
3
+ #include <memory>
4
+ #include <string>
5
+ #include <vector>
6
+
7
+ #include "AudioNodeHostObject.h"
8
+ #include "AudioParamHostObject.h"
9
+ #include "StereoPannerNodeWrapper.h"
10
+
11
+ namespace audioapi {
12
+ using namespace facebook;
13
+
14
+ class StereoPannerNodeHostObject : public AudioNodeHostObject {
15
+ public:
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);
31
+ }
32
+
33
+ private:
34
+ std::shared_ptr<AudioParamHostObject> panParam_;
35
+ };
36
+ } // namespace audioapi
@@ -0,0 +1,115 @@
1
+ #include "AudioBuffer.h"
2
+
3
+ namespace audioapi {
4
+
5
+ AudioBuffer::AudioBuffer(int numberOfChannels, int length, int sampleRate)
6
+ : numberOfChannels_(numberOfChannels),
7
+ length_(length),
8
+ sampleRate_(sampleRate),
9
+ duration_(static_cast<double>(length) / sampleRate) {
10
+ if (numberOfChannels != 1 && numberOfChannels != 2) {
11
+ throw std::invalid_argument("Invalid number of channels");
12
+ }
13
+
14
+ channels_ = new float *[numberOfChannels];
15
+
16
+ for (int i = 0; i < numberOfChannels; i++) {
17
+ channels_[i] = new float[length];
18
+
19
+ for (int j = 0; j < length; j++) {
20
+ channels_[i][j] = 0.0f;
21
+ }
22
+ }
23
+ }
24
+
25
+ int AudioBuffer::getNumberOfChannels() const {
26
+ return numberOfChannels_;
27
+ }
28
+
29
+ int AudioBuffer::getLength() const {
30
+ return length_;
31
+ }
32
+
33
+ int AudioBuffer::getSampleRate() const {
34
+ return sampleRate_;
35
+ }
36
+
37
+ double AudioBuffer::getDuration() const {
38
+ return duration_;
39
+ }
40
+
41
+ float *AudioBuffer::getChannelData(int channel) const {
42
+ if (channel < 0 || channel >= numberOfChannels_) {
43
+ throw std::invalid_argument("Invalid channel number");
44
+ }
45
+
46
+ return channels_[channel];
47
+ }
48
+
49
+ std::shared_ptr<AudioBuffer> AudioBuffer::mix(int outputNumberOfChannels) {
50
+ if (outputNumberOfChannels != 1 && outputNumberOfChannels != 2) {
51
+ throw std::invalid_argument("Invalid number of channels");
52
+ }
53
+
54
+ if (outputNumberOfChannels == numberOfChannels_) {
55
+ return shared_from_this();
56
+ }
57
+
58
+ auto mixedBuffer = std::make_shared<AudioBuffer>(
59
+ outputNumberOfChannels, length_, sampleRate_);
60
+
61
+ switch (this->numberOfChannels_) {
62
+ case 1:
63
+ mixedBuffer->copyToChannel(this->channels_[0], length_, 0, 0);
64
+ mixedBuffer->copyToChannel(this->channels_[0], length_, 1, 0);
65
+ break;
66
+ case 2:
67
+ for (int i = 0; i < length_; i++) {
68
+ mixedBuffer->channels_[0][i] =
69
+ (this->channels_[0][i] + this->channels_[1][i]) / 2;
70
+ }
71
+ break;
72
+ }
73
+
74
+ return mixedBuffer;
75
+ }
76
+
77
+ void AudioBuffer::copyFromChannel(
78
+ float *destination,
79
+ int destinationLength,
80
+ int channelNumber,
81
+ int startInChannel) const {
82
+ if (channelNumber < 0 || channelNumber >= numberOfChannels_) {
83
+ throw std::invalid_argument("Invalid channel number");
84
+ }
85
+
86
+ if (startInChannel < 0 || startInChannel >= length_) {
87
+ throw std::invalid_argument("Invalid start in channel");
88
+ }
89
+
90
+ std::copy(
91
+ channels_[channelNumber] + startInChannel,
92
+ channels_[channelNumber] + startInChannel +
93
+ std::min(destinationLength, length_ - startInChannel),
94
+ destination);
95
+ }
96
+
97
+ void AudioBuffer::copyToChannel(
98
+ const float *source,
99
+ int sourceLength,
100
+ int channelNumber,
101
+ int startInChannel) {
102
+ if (channelNumber < 0 || channelNumber >= numberOfChannels_) {
103
+ throw std::invalid_argument("Invalid channel number");
104
+ }
105
+
106
+ if (startInChannel < 0 || startInChannel >= length_) {
107
+ throw std::invalid_argument("Invalid start in channel");
108
+ }
109
+
110
+ std::copy(
111
+ source,
112
+ source + std::min(sourceLength, length_ - startInChannel),
113
+ channels_[channelNumber] + startInChannel);
114
+ }
115
+ } // namespace audioapi
@@ -0,0 +1,42 @@
1
+ #pragma once
2
+
3
+ #include <algorithm>
4
+ #include <memory>
5
+ #include <string>
6
+ #include <vector>
7
+
8
+ namespace audioapi {
9
+
10
+ class AudioBuffer : public std::enable_shared_from_this<AudioBuffer> {
11
+ public:
12
+ explicit AudioBuffer(int numberOfChannels, int length, int sampleRate);
13
+
14
+ int getNumberOfChannels() const;
15
+ int getLength() const;
16
+ int getSampleRate() const;
17
+ double getDuration() const;
18
+ float *getChannelData(int channel) const;
19
+ void copyFromChannel(
20
+ float *destination,
21
+ int destinationLength,
22
+ int channelNumber,
23
+ int startInChannel) const;
24
+ void copyToChannel(
25
+ const float *source,
26
+ int sourceLength,
27
+ int channelNumber,
28
+ int startInChannel);
29
+
30
+ private:
31
+ friend class AudioBufferSourceNode;
32
+
33
+ int numberOfChannels_;
34
+ int length_;
35
+ int sampleRate_;
36
+ double duration_;
37
+ float **channels_;
38
+
39
+ std::shared_ptr<AudioBuffer> mix(int outputNumberOfChannels);
40
+ };
41
+
42
+ } // namespace audioapi
@@ -0,0 +1,58 @@
1
+ #include "AudioBufferSourceNode.h"
2
+ #include "AudioContext.h"
3
+
4
+ namespace audioapi {
5
+
6
+ AudioBufferSourceNode::AudioBufferSourceNode(AudioContext *context)
7
+ : AudioScheduledSourceNode(context), loop_(false), bufferIndex_(0) {
8
+ numberOfInputs_ = 0;
9
+ buffer_ = std::nullopt;
10
+ }
11
+
12
+ bool AudioBufferSourceNode::getLoop() const {
13
+ return loop_;
14
+ }
15
+
16
+ std::shared_ptr<AudioBuffer> AudioBufferSourceNode::getBuffer() const {
17
+ if (!buffer_.has_value()) {
18
+ throw std::runtime_error("Buffer is not set");
19
+ }
20
+
21
+ return buffer_.value();
22
+ }
23
+
24
+ void AudioBufferSourceNode::setLoop(bool loop) {
25
+ loop_ = loop;
26
+ }
27
+
28
+ void AudioBufferSourceNode::setBuffer(
29
+ const std::shared_ptr<AudioBuffer> &buffer) {
30
+ buffer_ = buffer->mix(channelCount_);
31
+ }
32
+
33
+ bool AudioBufferSourceNode::processAudio(float *audioData, int32_t numFrames) {
34
+ if (!isPlaying_ || !buffer_.has_value()) {
35
+ return false;
36
+ } else {
37
+ for (int i = 0; i < numFrames; ++i) {
38
+ for (int j = 0; j < channelCount_; j++) {
39
+ audioData[i * channelCount_ + j] =
40
+ buffer_.value()->getChannelData(j)[bufferIndex_];
41
+ }
42
+
43
+ bufferIndex_++;
44
+
45
+ if (bufferIndex_ >= buffer_.value()->getLength()) {
46
+ if (loop_) {
47
+ bufferIndex_ = 0;
48
+ } else {
49
+ isPlaying_ = false;
50
+ break;
51
+ }
52
+ }
53
+ }
54
+
55
+ return true;
56
+ }
57
+ }
58
+ } // namespace audioapi
@@ -0,0 +1,26 @@
1
+ #pragma once
2
+
3
+ #include <memory>
4
+ #include <optional>
5
+
6
+ #include "AudioBuffer.h"
7
+ #include "AudioScheduledSourceNode.h"
8
+
9
+ namespace audioapi {
10
+
11
+ class AudioBufferSourceNode : public AudioScheduledSourceNode {
12
+ public:
13
+ explicit AudioBufferSourceNode(AudioContext *context);
14
+
15
+ bool getLoop() const;
16
+ std::shared_ptr<AudioBuffer> getBuffer() const;
17
+ void setLoop(bool loop);
18
+ void setBuffer(const std::shared_ptr<AudioBuffer> &buffer);
19
+ bool processAudio(float *audioData, int32_t numFrames) override;
20
+
21
+ private:
22
+ bool loop_;
23
+ std::optional<std::shared_ptr<AudioBuffer>> buffer_;
24
+ int bufferIndex_;
25
+ };
26
+ } // namespace audioapi
@@ -0,0 +1,90 @@
1
+ #include "AudioContext.h"
2
+
3
+ namespace audioapi {
4
+
5
+ AudioContext::AudioContext() {
6
+ #ifdef ANDROID
7
+ audioPlayer_ = std::make_shared<AudioPlayer>(this->renderAudio());
8
+ #else
9
+ audioPlayer_ = std::make_shared<IOSAudioPlayer>(this->renderAudio());
10
+ #endif
11
+ destination_ = std::make_shared<AudioDestinationNode>(this);
12
+
13
+ sampleRate_ = audioPlayer_->getSampleRate();
14
+
15
+ auto now = std::chrono::high_resolution_clock ::now();
16
+ contextStartTime_ =
17
+ static_cast<double>(std::chrono::duration_cast<std::chrono::nanoseconds>(
18
+ now.time_since_epoch())
19
+ .count());
20
+
21
+ audioPlayer_->start();
22
+ }
23
+
24
+ std::string AudioContext::getState() {
25
+ return AudioContext::toString(state_);
26
+ }
27
+
28
+ int AudioContext::getSampleRate() const {
29
+ return sampleRate_;
30
+ }
31
+
32
+ double AudioContext::getCurrentTime() const {
33
+ auto now = std::chrono::high_resolution_clock ::now();
34
+ auto currentTime =
35
+ static_cast<double>(std::chrono::duration_cast<std::chrono::nanoseconds>(
36
+ now.time_since_epoch())
37
+ .count());
38
+ return (currentTime - contextStartTime_) / 1e9;
39
+ }
40
+
41
+ void AudioContext::close() {
42
+ state_ = State::CLOSED;
43
+
44
+ if (audioPlayer_) {
45
+ audioPlayer_->stop();
46
+ }
47
+
48
+ audioPlayer_.reset();
49
+ destination_.reset();
50
+ }
51
+
52
+ std::shared_ptr<AudioDestinationNode> AudioContext::getDestination() {
53
+ return destination_;
54
+ }
55
+
56
+ std::shared_ptr<OscillatorNode> AudioContext::createOscillator() {
57
+ return std::make_shared<OscillatorNode>(this);
58
+ }
59
+
60
+ std::shared_ptr<GainNode> AudioContext::createGain() {
61
+ return std::make_shared<GainNode>(this);
62
+ }
63
+
64
+ std::shared_ptr<StereoPannerNode> AudioContext::createStereoPanner() {
65
+ return std::make_shared<StereoPannerNode>(this);
66
+ }
67
+
68
+ std::shared_ptr<BiquadFilterNode> AudioContext::createBiquadFilter() {
69
+ return std::make_shared<BiquadFilterNode>(this);
70
+ }
71
+
72
+ std::shared_ptr<AudioBufferSourceNode> AudioContext::createBufferSource() {
73
+ return std::make_shared<AudioBufferSourceNode>(this);
74
+ }
75
+
76
+ std::shared_ptr<AudioBuffer>
77
+ AudioContext::createBuffer(int numberOfChannels, int length, int sampleRate) {
78
+ return std::make_shared<AudioBuffer>(numberOfChannels, length, sampleRate);
79
+ }
80
+
81
+ std::function<void(float *, int)> AudioContext::renderAudio() {
82
+ if (state_ == State::CLOSED) {
83
+ return [](float *, int) {};
84
+ }
85
+
86
+ return [this](float *data, int frames) {
87
+ destination_->renderAudio(data, frames);
88
+ };
89
+ }
90
+ } // namespace audioapi
@@ -0,0 +1,73 @@
1
+ #pragma once
2
+
3
+ #include <functional>
4
+ #include <memory>
5
+ #include <string>
6
+ #include <utility>
7
+ #include <vector>
8
+
9
+ #include "AudioBuffer.h"
10
+ #include "AudioBufferSourceNode.h"
11
+ #include "AudioDestinationNode.h"
12
+ #include "AudioScheduledSourceNode.h"
13
+ #include "BiquadFilterNode.h"
14
+ #include "Constants.h"
15
+ #include "GainNode.h"
16
+ #include "OscillatorNode.h"
17
+ #include "StereoPannerNode.h"
18
+
19
+ #ifdef ANDROID
20
+ #include "AudioPlayer.h"
21
+ #else
22
+ #include "IOSAudioPlayer.h"
23
+ #endif
24
+
25
+ namespace audioapi {
26
+
27
+ class AudioContext {
28
+ public:
29
+ AudioContext();
30
+ std::string getState();
31
+ int getSampleRate() const;
32
+ double getCurrentTime() const;
33
+ void close();
34
+
35
+ std::shared_ptr<AudioDestinationNode> getDestination();
36
+ std::shared_ptr<OscillatorNode> createOscillator();
37
+ std::shared_ptr<GainNode> createGain();
38
+ std::shared_ptr<StereoPannerNode> createStereoPanner();
39
+ std::shared_ptr<BiquadFilterNode> createBiquadFilter();
40
+ std::shared_ptr<AudioBufferSourceNode> createBufferSource();
41
+ static std::shared_ptr<AudioBuffer>
42
+ createBuffer(int numberOfChannels, int length, int sampleRate);
43
+ std::function<void(float *, int)> renderAudio();
44
+
45
+ private:
46
+ enum class State { SUSPENDED, RUNNING, CLOSED };
47
+
48
+ static std::string toString(State state) {
49
+ switch (state) {
50
+ case State::SUSPENDED:
51
+ return "suspended";
52
+ case State::RUNNING:
53
+ return "running";
54
+ case State::CLOSED:
55
+ return "closed";
56
+ default:
57
+ throw std::invalid_argument("Unknown context state");
58
+ }
59
+ }
60
+
61
+ private:
62
+ std::shared_ptr<AudioDestinationNode> destination_;
63
+ #ifdef ANDROID
64
+ std::shared_ptr<AudioPlayer> audioPlayer_;
65
+ #else
66
+ std::shared_ptr<IOSAudioPlayer> audioPlayer_;
67
+ #endif
68
+ State state_ = State::RUNNING;
69
+ int sampleRate_;
70
+ double contextStartTime_;
71
+ };
72
+
73
+ } // namespace audioapi
@@ -0,0 +1,35 @@
1
+ #include "AudioDestinationNode.h"
2
+ #include "AudioContext.h"
3
+
4
+ namespace audioapi {
5
+
6
+ AudioDestinationNode::AudioDestinationNode(AudioContext *context)
7
+ : AudioNode(context) {
8
+ numberOfOutputs_ = 0;
9
+ numberOfInputs_ = INT_MAX;
10
+ channelCountMode_ = ChannelCountMode::EXPLICIT;
11
+ }
12
+
13
+ void AudioDestinationNode::renderAudio(float *audioData, int32_t numFrames) {
14
+ processAudio(audioData, numFrames);
15
+ }
16
+
17
+ bool AudioDestinationNode::processAudio(float *audioData, int32_t numFrames) {
18
+ int numSamples = numFrames * CHANNEL_COUNT;
19
+
20
+ if (mixingBuffer == nullptr) {
21
+ mixingBuffer = std::make_unique<float[]>(numSamples);
22
+ }
23
+
24
+ memset(audioData, 0.0f, sizeof(float) * numSamples);
25
+
26
+ for (auto &node : inputNodes_) {
27
+ if (node && node->processAudio(mixingBuffer.get(), numFrames)) {
28
+ VectorMath::add(audioData, mixingBuffer.get(), audioData, numSamples);
29
+ }
30
+ }
31
+
32
+ return true;
33
+ }
34
+
35
+ } // namespace audioapi
@@ -0,0 +1,24 @@
1
+ #pragma once
2
+
3
+ #include <algorithm>
4
+ #include <memory>
5
+ #include <vector>
6
+
7
+ #include "AudioNode.h"
8
+ #include "VectorMath.h"
9
+
10
+ namespace audioapi {
11
+
12
+ class AudioDestinationNode : public AudioNode {
13
+ public:
14
+ explicit AudioDestinationNode(AudioContext *context);
15
+
16
+ void renderAudio(float *audioData, int32_t numFrames);
17
+
18
+ protected:
19
+ bool processAudio(float *audioData, int32_t numFrames) override;
20
+
21
+ private:
22
+ std::unique_ptr<float[]> mixingBuffer;
23
+ };
24
+ } // namespace audioapi
@@ -0,0 +1,68 @@
1
+ #include "AudioNode.h"
2
+ #include "AudioContext.h"
3
+
4
+ namespace audioapi {
5
+
6
+ AudioNode::AudioNode(AudioContext *context) : context_(context) {}
7
+
8
+ AudioNode::~AudioNode() {
9
+ cleanup();
10
+ }
11
+
12
+ int AudioNode::getNumberOfInputs() const {
13
+ return numberOfInputs_;
14
+ }
15
+
16
+ int AudioNode::getNumberOfOutputs() const {
17
+ return numberOfOutputs_;
18
+ }
19
+
20
+ int AudioNode::getChannelCount() const {
21
+ return channelCount_;
22
+ }
23
+
24
+ std::string AudioNode::getChannelCountMode() const {
25
+ return AudioNode::toString(channelCountMode_);
26
+ }
27
+
28
+ std::string AudioNode::getChannelInterpretation() const {
29
+ return AudioNode::toString(channelInterpretation_);
30
+ }
31
+
32
+ void AudioNode::connect(const std::shared_ptr<AudioNode> &node) {
33
+ if (numberOfOutputs_ > outputNodes_.size() &&
34
+ node->getNumberOfInputs() > node->inputNodes_.size()) {
35
+ outputNodes_.push_back(node);
36
+ node->inputNodes_.push_back(shared_from_this());
37
+ }
38
+ }
39
+
40
+ void AudioNode::disconnect(const std::shared_ptr<AudioNode> &node) {
41
+ outputNodes_.erase(
42
+ std::remove(outputNodes_.begin(), outputNodes_.end(), node),
43
+ outputNodes_.end());
44
+ if (auto sharedThis = shared_from_this()) {
45
+ node->inputNodes_.erase(
46
+ std::remove(
47
+ node->inputNodes_.begin(), node->inputNodes_.end(), sharedThis),
48
+ node->inputNodes_.end());
49
+ }
50
+ }
51
+
52
+ void AudioNode::cleanup() {
53
+ outputNodes_.clear();
54
+ inputNodes_.clear();
55
+ }
56
+
57
+ bool AudioNode::processAudio(float *audioData, int32_t numFrames) {
58
+ bool isPlaying = false;
59
+ for (auto &node : inputNodes_) {
60
+ if (node->processAudio(audioData, numFrames)) {
61
+ isPlaying = true;
62
+ }
63
+ }
64
+
65
+ return isPlaying;
66
+ }
67
+
68
+ } // namespace audioapi