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,74 @@
1
+ #pragma once
2
+
3
+ #include <memory>
4
+ #include <string>
5
+ #include <vector>
6
+ #include "Constants.h"
7
+
8
+ // channelCount always equal to 2
9
+
10
+ namespace audioapi {
11
+
12
+ class AudioContext;
13
+
14
+ class AudioNode : public std::enable_shared_from_this<AudioNode> {
15
+ public:
16
+ explicit AudioNode(AudioContext *context);
17
+ virtual ~AudioNode();
18
+ int getNumberOfInputs() const;
19
+ int getNumberOfOutputs() const;
20
+ int getChannelCount() const;
21
+ std::string getChannelCountMode() const;
22
+ std::string getChannelInterpretation() const;
23
+ void connect(const std::shared_ptr<AudioNode> &node);
24
+ void disconnect(const std::shared_ptr<AudioNode> &node);
25
+
26
+ // Change public to protected
27
+ virtual bool processAudio(float *audioData, int32_t numFrames);
28
+
29
+ protected:
30
+ enum class ChannelCountMode { MAX, CLAMPED_MAX, EXPLICIT };
31
+
32
+ static std::string toString(ChannelCountMode mode) {
33
+ switch (mode) {
34
+ case ChannelCountMode::MAX:
35
+ return "max";
36
+ case ChannelCountMode::CLAMPED_MAX:
37
+ return "clamped-max";
38
+ case ChannelCountMode::EXPLICIT:
39
+ return "explicit";
40
+ default:
41
+ throw std::invalid_argument("Unknown channel count mode");
42
+ }
43
+ }
44
+
45
+ enum class ChannelInterpretation { SPEAKERS, DISCRETE };
46
+
47
+ static std::string toString(ChannelInterpretation interpretation) {
48
+ switch (interpretation) {
49
+ case ChannelInterpretation::SPEAKERS:
50
+ return "speakers";
51
+ case ChannelInterpretation::DISCRETE:
52
+ return "discrete";
53
+ default:
54
+ throw std::invalid_argument("Unknown channel interpretation");
55
+ }
56
+ }
57
+
58
+ protected:
59
+ AudioContext *context_;
60
+ int numberOfInputs_ = 1;
61
+ int numberOfOutputs_ = 1;
62
+ int channelCount_ = CHANNEL_COUNT;
63
+ ChannelCountMode channelCountMode_ = ChannelCountMode::MAX;
64
+ ChannelInterpretation channelInterpretation_ =
65
+ ChannelInterpretation::SPEAKERS;
66
+
67
+ std::vector<std::shared_ptr<AudioNode>> inputNodes_ = {};
68
+ std::vector<std::shared_ptr<AudioNode>> outputNodes_ = {};
69
+
70
+ private:
71
+ void cleanup();
72
+ };
73
+
74
+ } // namespace audioapi
@@ -0,0 +1,136 @@
1
+ #include "AudioParam.h"
2
+ #include "AudioContext.h"
3
+
4
+ namespace audioapi {
5
+
6
+ AudioParam::AudioParam(
7
+ AudioContext *context,
8
+ float defaultValue,
9
+ float minValue,
10
+ float maxValue)
11
+ : value_(defaultValue),
12
+ defaultValue_(defaultValue),
13
+ minValue_(minValue),
14
+ maxValue_(maxValue),
15
+ context_(context),
16
+ changesQueue_() {
17
+ startTime_ = 0;
18
+ endTime_ = 0;
19
+ startValue_ = 0;
20
+ endValue_ = 0;
21
+ calculateValue_ = [this](double, double, float, float, double) {
22
+ return value_;
23
+ };
24
+ }
25
+
26
+ float AudioParam::getValue() const {
27
+ return value_;
28
+ }
29
+
30
+ float AudioParam::getDefaultValue() const {
31
+ return defaultValue_;
32
+ }
33
+
34
+ float AudioParam::getMinValue() const {
35
+ return minValue_;
36
+ }
37
+
38
+ float AudioParam::getMaxValue() const {
39
+ return maxValue_;
40
+ }
41
+
42
+ void AudioParam::setValue(float value) {
43
+ checkValue(value);
44
+ value_ = value;
45
+ }
46
+
47
+ float AudioParam::getValueAtTime(double time) {
48
+ if (!changesQueue_.empty()) {
49
+ if (endTime_ < time) {
50
+ auto change = *changesQueue_.begin();
51
+ startTime_ = change.getStartTime();
52
+ endTime_ = change.getEndTime();
53
+ startValue_ = change.getStartValue();
54
+ endValue_ = change.getEndValue();
55
+ calculateValue_ = change.getCalculateValue();
56
+ changesQueue_.erase(changesQueue_.begin());
57
+ }
58
+ }
59
+
60
+ if (startTime_ <= time) {
61
+ value_ =
62
+ calculateValue_(startTime_, endTime_, startValue_, endValue_, time);
63
+ }
64
+
65
+ return value_;
66
+ }
67
+
68
+ void AudioParam::setValueAtTime(float value, double time) {
69
+ checkValue(value);
70
+ auto calculateValue = [](double, double, float, float endValue, double) {
71
+ return endValue;
72
+ };
73
+
74
+ auto paramChange = ParamChange(time, time, value, value, calculateValue);
75
+ changesQueue_.insert(paramChange);
76
+ }
77
+
78
+ void AudioParam::linearRampToValueAtTime(float value, double time) {
79
+ checkValue(value);
80
+ auto calculateValue = [](double startTime,
81
+ double endTime,
82
+ float startValue,
83
+ float endValue,
84
+ double time) {
85
+ return time >= endTime ? endValue
86
+ : startValue +
87
+ (endValue - startValue) * (time - startTime) /
88
+ (endTime - startTime);
89
+ };
90
+
91
+ auto paramChange =
92
+ ParamChange(getStartTime(), time, getStartValue(), value, calculateValue);
93
+ changesQueue_.emplace(paramChange);
94
+ }
95
+
96
+ void AudioParam::exponentialRampToValueAtTime(float value, double time) {
97
+ checkValue(value);
98
+ auto calculateValue = [](double startTime,
99
+ double endTime,
100
+ float startValue,
101
+ float endValue,
102
+ double time) {
103
+ return time >= endTime ? endValue
104
+ : startValue *
105
+ pow(endValue / startValue,
106
+ (time - startTime) / (endTime - startTime));
107
+ };
108
+
109
+ auto paramChange =
110
+ ParamChange(getStartTime(), time, getStartValue(), value, calculateValue);
111
+ changesQueue_.emplace(paramChange);
112
+ }
113
+
114
+ void AudioParam::checkValue(float value) const {
115
+ if (value < minValue_ || value > maxValue_) {
116
+ throw std::invalid_argument("Value out of range");
117
+ }
118
+ }
119
+
120
+ double AudioParam::getStartTime() {
121
+ if (changesQueue_.empty()) {
122
+ return context_->getCurrentTime();
123
+ }
124
+
125
+ return changesQueue_.rbegin()->getEndTime();
126
+ }
127
+
128
+ float AudioParam::getStartValue() {
129
+ if (changesQueue_.empty()) {
130
+ return this->value_;
131
+ }
132
+
133
+ return changesQueue_.rbegin()->getEndValue();
134
+ }
135
+
136
+ } // namespace audioapi
@@ -0,0 +1,50 @@
1
+ #pragma once
2
+
3
+ #include <memory>
4
+ #include <set>
5
+ #include <vector>
6
+
7
+ #include "ParamChange.h"
8
+
9
+ namespace audioapi {
10
+
11
+ class AudioContext;
12
+
13
+ class AudioParam {
14
+ public:
15
+ explicit AudioParam(
16
+ AudioContext *context,
17
+ float defaultValue,
18
+ float minValue,
19
+ float maxValue);
20
+
21
+ float getValue() const;
22
+ float getValueAtTime(double time);
23
+ void setValue(float value);
24
+ float getDefaultValue() const;
25
+ float getMinValue() const;
26
+ float getMaxValue() const;
27
+ void setValueAtTime(float value, double startTime);
28
+ void linearRampToValueAtTime(float value, double endTime);
29
+ void exponentialRampToValueAtTime(float value, double endTime);
30
+
31
+ private:
32
+ float value_;
33
+ float defaultValue_;
34
+ float minValue_;
35
+ float maxValue_;
36
+ AudioContext *context_;
37
+ std::set<ParamChange> changesQueue_;
38
+
39
+ double startTime_;
40
+ double endTime_;
41
+ float startValue_;
42
+ float endValue_;
43
+ std::function<float(double, double, float, float, double)> calculateValue_;
44
+
45
+ void checkValue(float value) const;
46
+ double getStartTime();
47
+ float getStartValue();
48
+ };
49
+
50
+ } // namespace audioapi
@@ -0,0 +1,39 @@
1
+ #include "AudioScheduledSourceNode.h"
2
+ #include "AudioContext.h"
3
+
4
+ namespace audioapi {
5
+
6
+ AudioScheduledSourceNode::AudioScheduledSourceNode(AudioContext *context)
7
+ : AudioNode(context), isPlaying_(false) {
8
+ numberOfInputs_ = 0;
9
+ }
10
+
11
+ void AudioScheduledSourceNode::start(double time) {
12
+ waitAndExecute(time, [this](double time) { startPlayback(); });
13
+ }
14
+
15
+ void AudioScheduledSourceNode::stop(double time) {
16
+ waitAndExecute(time, [this](double time) { stopPlayback(); });
17
+ }
18
+
19
+ void AudioScheduledSourceNode::startPlayback() {
20
+ isPlaying_ = true;
21
+ }
22
+
23
+ void AudioScheduledSourceNode::stopPlayback() {
24
+ isPlaying_ = false;
25
+ }
26
+
27
+ void AudioScheduledSourceNode::waitAndExecute(
28
+ double time,
29
+ const std::function<void(double)> &fun) {
30
+ std::thread([this, time, fun]() {
31
+ while (context_->getCurrentTime() < time) {
32
+ std::this_thread::sleep_for(std::chrono::milliseconds(1));
33
+ }
34
+
35
+ fun(time);
36
+ }).detach();
37
+ }
38
+
39
+ } // namespace audioapi
@@ -0,0 +1,30 @@
1
+ #pragma once
2
+
3
+ #include <atomic>
4
+ #include <chrono>
5
+ #include <functional>
6
+ #include <iostream>
7
+ #include <memory>
8
+ #include <thread>
9
+
10
+ #include "AudioNode.h"
11
+
12
+ namespace audioapi {
13
+
14
+ class AudioScheduledSourceNode : public AudioNode {
15
+ public:
16
+ explicit AudioScheduledSourceNode(AudioContext *context);
17
+
18
+ void start(double time);
19
+ void stop(double time);
20
+
21
+ protected:
22
+ std::atomic<bool> isPlaying_;
23
+
24
+ private:
25
+ void startPlayback();
26
+ void stopPlayback();
27
+ void waitAndExecute(double time, const std::function<void(double)> &fun);
28
+ };
29
+
30
+ } // namespace audioapi
@@ -0,0 +1,364 @@
1
+ #include "BiquadFilterNode.h"
2
+ #include "AudioContext.h"
3
+
4
+ // https://webaudio.github.io/Audio-EQ-Cookbook/audio-eq-cookbook.html - math
5
+ // 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
+
9
+ namespace audioapi {
10
+
11
+ BiquadFilterNode::BiquadFilterNode(AudioContext *context) : AudioNode(context) {
12
+ frequencyParam_ = std::make_shared<AudioParam>(
13
+ context, 350.0, MIN_FILTER_FREQUENCY, MAX_FILTER_FREQUENCY);
14
+ detuneParam_ =
15
+ std::make_shared<AudioParam>(context, 0.0, -MAX_DETUNE, MAX_DETUNE);
16
+ QParam_ =
17
+ std::make_shared<AudioParam>(context, 1.0, -MAX_FILTER_Q, MAX_FILTER_Q);
18
+ gainParam_ = std::make_shared<AudioParam>(
19
+ context, 0.0, MIN_FILTER_GAIN, MAX_FILTER_GAIN);
20
+ type_ = FilterType::LOWPASS;
21
+ }
22
+
23
+ std::string BiquadFilterNode::getType() const {
24
+ return BiquadFilterNode::toString(type_);
25
+ }
26
+
27
+ void BiquadFilterNode::setType(const std::string &type) {
28
+ type_ = BiquadFilterNode::fromString(type);
29
+ }
30
+
31
+ std::shared_ptr<AudioParam> BiquadFilterNode::getFrequencyParam() const {
32
+ return frequencyParam_;
33
+ }
34
+
35
+ std::shared_ptr<AudioParam> BiquadFilterNode::getDetuneParam() const {
36
+ return detuneParam_;
37
+ }
38
+
39
+ std::shared_ptr<AudioParam> BiquadFilterNode::getQParam() const {
40
+ return QParam_;
41
+ }
42
+
43
+ std::shared_ptr<AudioParam> BiquadFilterNode::getGainParam() const {
44
+ return gainParam_;
45
+ }
46
+
47
+ float BiquadFilterNode::clamp(float value, float min, float max) {
48
+ return std::min(std::max(value, min), max);
49
+ }
50
+
51
+ void BiquadFilterNode::resetCoefficients() {
52
+ x1_ = 0.0;
53
+ x2_ = 0.0;
54
+ y1_ = 0.0;
55
+ y2_ = 0.0;
56
+ }
57
+
58
+ void BiquadFilterNode::setNormalizedCoefficients(
59
+ float b0,
60
+ float b1,
61
+ float b2,
62
+ float a0,
63
+ float a1,
64
+ 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;
71
+ }
72
+
73
+ void BiquadFilterNode::setLowpassCoefficients(float frequency, float Q) {
74
+ frequency = clamp(frequency, 0.0, 1.0);
75
+ if (frequency == 1.0) {
76
+ setNormalizedCoefficients(1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f);
77
+ return;
78
+ }
79
+ if (frequency <= 0.0) {
80
+ setNormalizedCoefficients(0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f);
81
+ return;
82
+ }
83
+
84
+ Q = std::max(0.0f, Q);
85
+ float g = std::pow(10.0f, 0.05f * Q);
86
+ float d = std::sqrt((4 - std::sqrt(16 - 16 / (g * g))) / 2);
87
+
88
+ 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);
93
+
94
+ setNormalizedCoefficients(
95
+ 2 * alpha, 4 * alpha, 2 * alpha, 1.0f, -2 * gamma, 2 * beta);
96
+ }
97
+
98
+ void BiquadFilterNode::setHighpassCoefficients(float frequency, float Q) {
99
+ frequency = clamp(frequency, 0.0, 1.0);
100
+ if (frequency == 1.0) {
101
+ setNormalizedCoefficients(0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f);
102
+ return;
103
+ }
104
+ if (frequency <= 0.0) {
105
+ setNormalizedCoefficients(1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f);
106
+ return;
107
+ }
108
+
109
+ Q = std::max(0.0f, Q);
110
+ float g = std::pow(10.0f, 0.05f * Q);
111
+ float d = std::sqrt((4 - std::sqrt(16 - 16 / (g * g))) / 2);
112
+
113
+ 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);
118
+
119
+ setNormalizedCoefficients(
120
+ 2 * alpha, -4 * alpha, 2 * alpha, 1.0f, -2 * gamma, 2 * beta);
121
+ }
122
+
123
+ void BiquadFilterNode::setBandpassCoefficients(float frequency, float Q) {
124
+ frequency = clamp(frequency, 0.0, 1.0);
125
+ Q = std::max(0.0f, Q);
126
+
127
+ if (frequency <= 0.0 || frequency >= 1.0) {
128
+ setNormalizedCoefficients(0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f);
129
+ return;
130
+ }
131
+
132
+ if (Q <= 0.0) {
133
+ setNormalizedCoefficients(1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f);
134
+ return;
135
+ }
136
+
137
+ float w0 = M_PI * frequency;
138
+ float alpha = std::sin(w0) / (2 * Q);
139
+ float k = std::cos(w0);
140
+
141
+ setNormalizedCoefficients(
142
+ alpha, 0.0f, -alpha, 1.0f + alpha, -2 * k, 1.0f - alpha);
143
+ }
144
+
145
+ void BiquadFilterNode::setLowshelfCoefficients(float frequency, float gain) {
146
+ frequency = clamp(frequency, 0.0, 1.0);
147
+ float A = std::pow(10.0f, gain / 40.0f);
148
+
149
+ if (frequency == 1.0) {
150
+ setNormalizedCoefficients(A * A, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f);
151
+ return;
152
+ }
153
+
154
+ if (frequency <= 0.0) {
155
+ setNormalizedCoefficients(1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f);
156
+ return;
157
+ }
158
+
159
+ float w0 = M_PI * frequency;
160
+ float alpha =
161
+ 0.5f * std::sin(w0) * std::sqrt((A + 1 / A) * (1 / 1.0f - 1) + 2);
162
+ float k = std::cos(w0);
163
+ float k2 = 2.0f * std::sqrt(A) * alpha;
164
+
165
+ setNormalizedCoefficients(
166
+ A * (A + 1 - (A - 1) * k + k2),
167
+ 2.0f * A * (A - 1 - (A + 1) * k),
168
+ A * (A + 1 - (A - 1) * k - k2),
169
+ A + 1 + (A - 1) * k + k2,
170
+ -2.0f * (A - 1 + (A + 1) * k),
171
+ A + 1 + (A - 1) * k - k2);
172
+ }
173
+
174
+ void BiquadFilterNode::setHighshelfCoefficients(float frequency, float gain) {
175
+ frequency = clamp(frequency, 0.0, 1.0);
176
+ float A = std::pow(10.0f, gain / 40.0f);
177
+
178
+ if (frequency == 1.0) {
179
+ setNormalizedCoefficients(1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f);
180
+ return;
181
+ }
182
+
183
+ if (frequency <= 0.0) {
184
+ setNormalizedCoefficients(A * A, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f);
185
+ return;
186
+ }
187
+
188
+ float w0 = M_PI * frequency;
189
+ float alpha =
190
+ 0.5f * std::sin(w0) * std::sqrt((A + 1 / A) * (1 / 1.0f - 1) + 2);
191
+ float k = std::cos(w0);
192
+ float k2 = 2.0f * std::sqrt(A) * alpha;
193
+
194
+ setNormalizedCoefficients(
195
+ A * (A + 1 + (A - 1) * k + k2),
196
+ -2.0f * A * (A - 1 + (A + 1) * k),
197
+ A * (A + 1 + (A - 1) * k - k2),
198
+ A + 1 - (A - 1) * k + k2,
199
+ 2.0f * (A - 1 - (A + 1) * k),
200
+ A + 1 - (A - 1) * k - k2);
201
+ }
202
+
203
+ void BiquadFilterNode::setPeakingCoefficients(
204
+ float frequency,
205
+ float Q,
206
+ float gain) {
207
+ frequency = clamp(frequency, 0.0, 1.0);
208
+ Q = std::max(0.0f, Q);
209
+ float A = std::pow(10.0f, gain / 40.0f);
210
+
211
+ if (frequency <= 0.0 || frequency >= 1.0) {
212
+ setNormalizedCoefficients(1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f);
213
+ return;
214
+ }
215
+
216
+ if (Q <= 0.0) {
217
+ setNormalizedCoefficients(A * A, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f);
218
+ return;
219
+ }
220
+
221
+ float w0 = M_PI * frequency;
222
+ float alpha = std::sin(w0) / (2 * Q);
223
+ float k = std::cos(w0);
224
+
225
+ setNormalizedCoefficients(
226
+ 1 + alpha * A,
227
+ -2 * k,
228
+ 1 - alpha * A,
229
+ 1 + alpha / A,
230
+ -2 * k,
231
+ 1 - alpha / A);
232
+ }
233
+
234
+ void BiquadFilterNode::setNotchCoefficients(float frequency, float Q) {
235
+ frequency = clamp(frequency, 0.0, 1.0);
236
+ Q = std::max(0.0f, Q);
237
+
238
+ if (frequency <= 0.0 || frequency >= 1.0) {
239
+ setNormalizedCoefficients(1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f);
240
+ return;
241
+ }
242
+
243
+ if (Q <= 0.0) {
244
+ setNormalizedCoefficients(0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f);
245
+ return;
246
+ }
247
+
248
+ float w0 = M_PI * frequency;
249
+ float alpha = std::sin(w0) / (2 * Q);
250
+ float k = std::cos(w0);
251
+
252
+ setNormalizedCoefficients(1.0f, -2 * k, 1.0f, 1 + alpha, -2 * k, 1 - alpha);
253
+ }
254
+
255
+ void BiquadFilterNode::setAllpassCoefficients(float frequency, float Q) {
256
+ frequency = clamp(frequency, 0.0, 1.0);
257
+ Q = std::max(0.0f, Q);
258
+
259
+ if (frequency <= 0.0 || frequency >= 1.0) {
260
+ setNormalizedCoefficients(1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f);
261
+ return;
262
+ }
263
+
264
+ if (Q <= 0.0) {
265
+ setNormalizedCoefficients(-1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f);
266
+ return;
267
+ }
268
+
269
+ float w0 = M_PI * frequency;
270
+ float alpha = std::sin(w0) / (2 * Q);
271
+ float k = std::cos(w0);
272
+
273
+ setNormalizedCoefficients(
274
+ 1 - alpha, -2 * k, 1 + alpha, 1 + alpha, -2 * k, 1 - alpha);
275
+ }
276
+
277
+ void BiquadFilterNode::applyFilter() {
278
+ double currentTime = context_->getCurrentTime();
279
+
280
+ float normalizedFrequency =
281
+ frequencyParam_->getValueAtTime(currentTime) / NYQUIST_FREQUENCY;
282
+ float detuneValue = detuneParam_->getValueAtTime(currentTime);
283
+
284
+ if (detuneValue != 0.0) {
285
+ normalizedFrequency *= std::pow(2.0f, detuneValue / 1200.0f);
286
+ }
287
+
288
+ switch (type_) {
289
+ case FilterType::LOWPASS:
290
+ setLowpassCoefficients(
291
+ normalizedFrequency, QParam_->getValueAtTime(currentTime));
292
+ break;
293
+ case FilterType::HIGHPASS:
294
+ setHighpassCoefficients(
295
+ normalizedFrequency, QParam_->getValueAtTime(currentTime));
296
+ break;
297
+ case FilterType::BANDPASS:
298
+ setBandpassCoefficients(
299
+ normalizedFrequency, QParam_->getValueAtTime(currentTime));
300
+ break;
301
+ case FilterType::LOWSHELF:
302
+ setLowshelfCoefficients(
303
+ normalizedFrequency, gainParam_->getValueAtTime(currentTime));
304
+ break;
305
+ case FilterType::HIGHSHELF:
306
+ setHighshelfCoefficients(
307
+ normalizedFrequency, gainParam_->getValueAtTime(currentTime));
308
+ break;
309
+ case FilterType::PEAKING:
310
+ setPeakingCoefficients(
311
+ normalizedFrequency,
312
+ QParam_->getValueAtTime(currentTime),
313
+ gainParam_->getValueAtTime(currentTime));
314
+ break;
315
+ case FilterType::NOTCH:
316
+ setNotchCoefficients(
317
+ normalizedFrequency, QParam_->getValueAtTime(currentTime));
318
+ break;
319
+ case FilterType::ALLPASS:
320
+ setAllpassCoefficients(
321
+ normalizedFrequency, QParam_->getValueAtTime(currentTime));
322
+ break;
323
+ default:
324
+ break;
325
+ }
326
+ }
327
+
328
+ bool BiquadFilterNode::processAudio(float *audioData, int32_t numFrames) {
329
+ if (!AudioNode::processAudio(audioData, numFrames)) {
330
+ return false;
331
+ }
332
+
333
+ resetCoefficients();
334
+ applyFilter();
335
+
336
+ float x1 = x1_;
337
+ float x2 = x2_;
338
+ float y1 = y1_;
339
+ float y2 = y2_;
340
+
341
+ float b0 = b0_;
342
+ float b1 = b1_;
343
+ float b2 = b2_;
344
+ float a1 = a1_;
345
+ float a2 = a2_;
346
+
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);
351
+
352
+ for (int j = 0; j < channelCount_; j++) {
353
+ audioData[i * channelCount_ + j] = output;
354
+ }
355
+
356
+ x2 = x1;
357
+ x1 = input;
358
+ y2 = y1;
359
+ y1 = output;
360
+ }
361
+
362
+ return true;
363
+ }
364
+ } // namespace audioapi