react-native-audio-api 0.4.0 → 0.4.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.
- package/android/src/main/cpp/core/AudioPlayer.cpp +38 -11
- package/android/src/main/cpp/core/AudioPlayer.h +6 -2
- package/common/cpp/HostObjects/AnalyserNodeHostObject.h +19 -6
- package/common/cpp/HostObjects/AudioAPIInstallerHostObject.h +11 -3
- package/common/cpp/HostObjects/AudioBufferHostObject.h +6 -5
- package/common/cpp/HostObjects/AudioNodeHostObject.h +5 -0
- package/common/cpp/HostObjects/AudioParamHostObject.h +2 -1
- package/common/cpp/HostObjects/BaseAudioContextHostObject.h +4 -3
- package/common/cpp/core/AnalyserNode.cpp +56 -34
- package/common/cpp/core/AnalyserNode.h +51 -19
- package/common/cpp/core/AudioArray.cpp +14 -14
- package/common/cpp/core/AudioArray.h +16 -15
- package/common/cpp/core/AudioBuffer.cpp +12 -9
- package/common/cpp/core/AudioBuffer.h +9 -8
- package/common/cpp/core/AudioBufferSourceNode.cpp +25 -20
- package/common/cpp/core/AudioBufferSourceNode.h +1 -0
- package/common/cpp/core/AudioBus.cpp +22 -26
- package/common/cpp/core/AudioBus.h +24 -24
- package/common/cpp/core/AudioContext.cpp +41 -1
- package/common/cpp/core/AudioContext.h +17 -0
- package/common/cpp/core/AudioDecoder.h +2 -2
- package/common/cpp/core/AudioDestinationNode.cpp +1 -1
- package/common/cpp/core/AudioDestinationNode.h +2 -1
- package/common/cpp/core/AudioNode.cpp +22 -8
- package/common/cpp/core/AudioNode.h +10 -10
- package/common/cpp/core/AudioNodeManager.cpp +1 -3
- package/common/cpp/core/AudioNodeManager.h +1 -1
- package/common/cpp/core/AudioParam.cpp +6 -3
- package/common/cpp/core/AudioParam.h +2 -1
- package/common/cpp/core/AudioScheduledSourceNode.cpp +1 -1
- package/common/cpp/core/AudioScheduledSourceNode.h +1 -0
- package/common/cpp/core/BaseAudioContext.cpp +7 -43
- package/common/cpp/core/BaseAudioContext.h +10 -21
- package/common/cpp/core/BiquadFilterNode.cpp +13 -14
- package/common/cpp/core/Constants.h +26 -12
- package/common/cpp/core/GainNode.cpp +1 -1
- package/common/cpp/core/OscillatorNode.cpp +4 -3
- package/common/cpp/core/PeriodicWave.cpp +7 -6
- package/common/cpp/core/PeriodicWave.h +4 -4
- package/common/cpp/core/StereoPannerNode.cpp +4 -4
- package/common/cpp/jsi/JsiHostObject.h +1 -1
- package/common/cpp/jsi/JsiPromise.h +1 -0
- package/common/cpp/utils/AudioUtils.cpp +2 -2
- package/common/cpp/utils/AudioUtils.h +2 -2
- package/common/cpp/utils/Locker.h +2 -2
- package/common/cpp/utils/VectorMath.cpp +1 -1
- package/ios/core/AudioPlayer.h +3 -2
- package/ios/core/AudioPlayer.m +49 -15
- package/ios/core/IOSAudioPlayer.h +4 -2
- package/ios/core/IOSAudioPlayer.mm +47 -11
- package/lib/module/core/AnalyserNode.js +6 -0
- package/lib/module/core/AnalyserNode.js.map +1 -1
- package/lib/module/core/AudioContext.js +2 -2
- package/lib/module/core/AudioContext.js.map +1 -1
- package/lib/module/core/AudioNode.js +5 -5
- package/lib/module/core/AudioNode.js.map +1 -1
- package/lib/module/index.js +16 -6
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.native.js +1 -1
- package/lib/module/index.native.js.map +1 -1
- package/lib/typescript/core/AnalyserNode.d.ts +3 -0
- package/lib/typescript/core/AnalyserNode.d.ts.map +1 -1
- package/lib/typescript/core/AudioContext.d.ts +1 -1
- package/lib/typescript/core/AudioContext.d.ts.map +1 -1
- package/lib/typescript/core/AudioNode.d.ts +2 -2
- package/lib/typescript/core/AudioNode.d.ts.map +1 -1
- package/lib/typescript/core/types.d.ts +1 -0
- package/lib/typescript/core/types.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +6 -4
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/index.native.d.ts +1 -1
- package/lib/typescript/index.native.d.ts.map +1 -1
- package/lib/typescript/interfaces.d.ts +3 -2
- package/lib/typescript/interfaces.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/core/AnalyserNode.ts +9 -0
- package/src/core/AudioContext.ts +2 -2
- package/src/core/AudioNode.ts +5 -5
- package/src/core/types.ts +2 -0
- package/src/index.native.ts +1 -0
- package/src/index.ts +26 -7
- package/src/interfaces.ts +3 -1
- package/src/specs/global.d.ts +1 -1
|
@@ -9,9 +9,7 @@ namespace audioapi {
|
|
|
9
9
|
|
|
10
10
|
AudioNode::AudioNode(BaseAudioContext *context) : context_(context) {
|
|
11
11
|
audioBus_ = std::make_shared<AudioBus>(
|
|
12
|
-
context->getSampleRate(),
|
|
13
|
-
context->getBufferSizeInFrames(),
|
|
14
|
-
channelCount_);
|
|
12
|
+
context->getSampleRate(), RENDER_QUANTUM_SIZE, channelCount_);
|
|
15
13
|
}
|
|
16
14
|
|
|
17
15
|
AudioNode::~AudioNode() {
|
|
@@ -49,6 +47,12 @@ void AudioNode::connectNode(const std::shared_ptr<AudioNode> &node) {
|
|
|
49
47
|
node->onInputConnected(this);
|
|
50
48
|
}
|
|
51
49
|
|
|
50
|
+
void AudioNode::disconnect() {
|
|
51
|
+
for (auto &outputNode : outputNodes_) {
|
|
52
|
+
disconnectNode(outputNode);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
52
56
|
void AudioNode::disconnect(const std::shared_ptr<AudioNode> &node) {
|
|
53
57
|
context_->getNodeManager()->addPendingConnection(
|
|
54
58
|
shared_from_this(), node, AudioNodeManager::ConnectionType::DISCONNECT);
|
|
@@ -71,16 +75,16 @@ bool AudioNode::isEnabled() const {
|
|
|
71
75
|
void AudioNode::enable() {
|
|
72
76
|
isEnabled_ = true;
|
|
73
77
|
|
|
74
|
-
for (auto
|
|
75
|
-
|
|
78
|
+
for (auto &outputNode : outputNodes_) {
|
|
79
|
+
outputNode->onInputEnabled();
|
|
76
80
|
}
|
|
77
81
|
}
|
|
78
82
|
|
|
79
83
|
void AudioNode::disable() {
|
|
80
84
|
isEnabled_ = false;
|
|
81
85
|
|
|
82
|
-
for (auto
|
|
83
|
-
|
|
86
|
+
for (auto &outputNode : outputNodes_) {
|
|
87
|
+
outputNode->onInputDisabled();
|
|
84
88
|
}
|
|
85
89
|
}
|
|
86
90
|
|
|
@@ -162,12 +166,14 @@ AudioBus *AudioNode::processAudio(AudioBus *outputBus, int framesToProcess) {
|
|
|
162
166
|
AudioBus *inputBus = (*it)->processAudio(processingBus, framesToProcess);
|
|
163
167
|
|
|
164
168
|
if (inputBus != processingBus) {
|
|
169
|
+
// add assert
|
|
165
170
|
processingBus->sum(inputBus);
|
|
166
171
|
}
|
|
167
172
|
} else {
|
|
168
173
|
// Enforce the summing to be done using the internal bus.
|
|
169
|
-
AudioBus *inputBus = (*it)->processAudio(
|
|
174
|
+
AudioBus *inputBus = (*it)->processAudio(nullptr, framesToProcess);
|
|
170
175
|
if (inputBus) {
|
|
176
|
+
// add assert
|
|
171
177
|
processingBus->sum(inputBus);
|
|
172
178
|
}
|
|
173
179
|
}
|
|
@@ -201,6 +207,10 @@ void AudioNode::onInputDisabled() {
|
|
|
201
207
|
}
|
|
202
208
|
|
|
203
209
|
void AudioNode::onInputConnected(AudioNode *node) {
|
|
210
|
+
if (!isInitialized_) {
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
|
|
204
214
|
inputNodes_.push_back(node);
|
|
205
215
|
|
|
206
216
|
if (node->isEnabled()) {
|
|
@@ -209,6 +219,10 @@ void AudioNode::onInputConnected(AudioNode *node) {
|
|
|
209
219
|
}
|
|
210
220
|
|
|
211
221
|
void AudioNode::onInputDisconnected(AudioNode *node) {
|
|
222
|
+
if (!isInitialized_) {
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
|
|
212
226
|
auto position = std::find(inputNodes_.begin(), inputNodes_.end(), node);
|
|
213
227
|
|
|
214
228
|
if (position != inputNodes_.end()) {
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
#include <memory>
|
|
4
4
|
#include <string>
|
|
5
5
|
#include <vector>
|
|
6
|
+
#include <cstddef>
|
|
6
7
|
|
|
7
8
|
#include "ChannelCountMode.h"
|
|
8
9
|
#include "ChannelInterpretation.h"
|
|
@@ -23,6 +24,7 @@ class AudioNode : public std::enable_shared_from_this<AudioNode> {
|
|
|
23
24
|
std::string getChannelCountMode() const;
|
|
24
25
|
std::string getChannelInterpretation() const;
|
|
25
26
|
void connect(const std::shared_ptr<AudioNode> &node);
|
|
27
|
+
void disconnect();
|
|
26
28
|
void disconnect(const std::shared_ptr<AudioNode> &node);
|
|
27
29
|
|
|
28
30
|
bool isEnabled() const;
|
|
@@ -36,24 +38,22 @@ class AudioNode : public std::enable_shared_from_this<AudioNode> {
|
|
|
36
38
|
BaseAudioContext *context_;
|
|
37
39
|
std::shared_ptr<AudioBus> audioBus_;
|
|
38
40
|
|
|
39
|
-
int channelCount_ = CHANNEL_COUNT;
|
|
40
|
-
|
|
41
41
|
int numberOfInputs_ = 1;
|
|
42
42
|
int numberOfOutputs_ = 1;
|
|
43
|
-
int
|
|
43
|
+
int channelCount_ = 2;
|
|
44
|
+
ChannelCountMode channelCountMode_ = ChannelCountMode::MAX;
|
|
45
|
+
ChannelInterpretation channelInterpretation_ =
|
|
46
|
+
ChannelInterpretation::SPEAKERS;
|
|
47
|
+
|
|
48
|
+
std::vector<AudioNode *> inputNodes_ = {};
|
|
49
|
+
std::vector<std::shared_ptr<AudioNode>> outputNodes_ = {};
|
|
44
50
|
|
|
51
|
+
int numberOfEnabledInputNodes_ = 0;
|
|
45
52
|
bool isInitialized_ = false;
|
|
46
53
|
bool isEnabled_ = true;
|
|
47
54
|
|
|
48
55
|
std::size_t lastRenderedFrame_{SIZE_MAX};
|
|
49
56
|
|
|
50
|
-
ChannelCountMode channelCountMode_ = ChannelCountMode::MAX;
|
|
51
|
-
ChannelInterpretation channelInterpretation_ =
|
|
52
|
-
ChannelInterpretation::SPEAKERS;
|
|
53
|
-
|
|
54
|
-
std::vector<AudioNode *> inputNodes_ = {};
|
|
55
|
-
std::vector<std::shared_ptr<AudioNode>> outputNodes_ = {};
|
|
56
|
-
|
|
57
57
|
private:
|
|
58
58
|
static std::string toString(ChannelCountMode mode);
|
|
59
59
|
static std::string toString(ChannelInterpretation interpretation);
|
|
@@ -5,8 +5,6 @@
|
|
|
5
5
|
|
|
6
6
|
namespace audioapi {
|
|
7
7
|
|
|
8
|
-
AudioNodeManager::AudioNodeManager() {}
|
|
9
|
-
|
|
10
8
|
AudioNodeManager::~AudioNodeManager() {
|
|
11
9
|
audioNodesToConnect_.clear();
|
|
12
10
|
sourceNodes_.clear();
|
|
@@ -18,7 +16,7 @@ void AudioNodeManager::addPendingConnection(
|
|
|
18
16
|
ConnectionType type) {
|
|
19
17
|
Locker lock(getGraphLock());
|
|
20
18
|
|
|
21
|
-
audioNodesToConnect_.
|
|
19
|
+
audioNodesToConnect_.emplace_back(from, to, type);
|
|
22
20
|
}
|
|
23
21
|
|
|
24
22
|
void AudioNodeManager::addSourceNode(const std::shared_ptr<AudioNode> &node) {
|
|
@@ -181,7 +181,7 @@ void AudioParam::setTargetAtTime(
|
|
|
181
181
|
|
|
182
182
|
void AudioParam::setValueCurveAtTime(
|
|
183
183
|
const float *values,
|
|
184
|
-
|
|
184
|
+
size_t length,
|
|
185
185
|
double startTime,
|
|
186
186
|
double duration) {
|
|
187
187
|
if (startTime <= getQueueEndTime()) {
|
|
@@ -200,9 +200,12 @@ void AudioParam::setValueCurveAtTime(
|
|
|
200
200
|
|
|
201
201
|
if (time < endTime) {
|
|
202
202
|
auto k = static_cast<int>(std::floor(
|
|
203
|
-
(length - 1) / (endTime - startTime) *
|
|
203
|
+
static_cast<double>(length - 1) / (endTime - startTime) *
|
|
204
|
+
(time - startTime)));
|
|
204
205
|
auto factor = static_cast<float>(
|
|
205
|
-
k -
|
|
206
|
+
k -
|
|
207
|
+
(time - startTime) * static_cast<double>(length - 1) /
|
|
208
|
+
(endTime - startTime));
|
|
206
209
|
|
|
207
210
|
return AudioUtils::linearInterpolate(values, k, k + 1, factor);
|
|
208
211
|
}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
#include <deque>
|
|
4
4
|
#include <memory>
|
|
5
5
|
#include <vector>
|
|
6
|
+
#include <cstddef>
|
|
6
7
|
|
|
7
8
|
#include "ParamChangeEvent.h"
|
|
8
9
|
#include "ParamChangeEventType.h"
|
|
@@ -27,7 +28,7 @@ class AudioParam {
|
|
|
27
28
|
void setTargetAtTime(float target, double startTime, double timeConstant);
|
|
28
29
|
void setValueCurveAtTime(
|
|
29
30
|
const float *values,
|
|
30
|
-
|
|
31
|
+
size_t length,
|
|
31
32
|
double startTime,
|
|
32
33
|
double duration);
|
|
33
34
|
void cancelScheduledValues(double cancelTime);
|
|
@@ -53,7 +53,7 @@ void AudioScheduledSourceNode::updatePlaybackInfo(
|
|
|
53
53
|
return;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
|
|
56
|
+
auto sampleRate = context_->getSampleRate();
|
|
57
57
|
|
|
58
58
|
size_t firstFrame = context_->getCurrentSampleFrame();
|
|
59
59
|
size_t lastFrame = firstFrame + framesToProcess;
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
#ifdef ANDROID
|
|
2
|
-
#include "AudioPlayer.h"
|
|
3
|
-
#else
|
|
4
|
-
#include "IOSAudioPlayer.h"
|
|
5
|
-
#endif
|
|
6
|
-
|
|
7
1
|
#include "BaseAudioContext.h"
|
|
8
2
|
|
|
9
3
|
#include "AnalyserNode.h"
|
|
@@ -23,42 +17,18 @@
|
|
|
23
17
|
namespace audioapi {
|
|
24
18
|
|
|
25
19
|
BaseAudioContext::BaseAudioContext() {
|
|
26
|
-
#ifdef ANDROID
|
|
27
|
-
audioPlayer_ = std::make_shared<AudioPlayer>(this->renderAudio());
|
|
28
|
-
#else
|
|
29
|
-
audioPlayer_ = std::make_shared<IOSAudioPlayer>(this->renderAudio());
|
|
30
|
-
#endif
|
|
31
|
-
|
|
32
|
-
audioDecoder_ = std::make_shared<AudioDecoder>(audioPlayer_->getSampleRate());
|
|
33
|
-
|
|
34
|
-
sampleRate_ = audioPlayer_->getSampleRate();
|
|
35
|
-
bufferSizeInFrames_ = audioPlayer_->getBufferSizeInFrames();
|
|
36
|
-
|
|
37
20
|
nodeManager_ = std::make_shared<AudioNodeManager>();
|
|
38
21
|
destination_ = std::make_shared<AudioDestinationNode>(this);
|
|
39
22
|
}
|
|
40
23
|
|
|
41
|
-
BaseAudioContext::~BaseAudioContext() {
|
|
42
|
-
if (isRunning()) {
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
state_ = ContextState::CLOSED;
|
|
47
|
-
audioPlayer_->stop();
|
|
48
|
-
}
|
|
49
|
-
|
|
50
24
|
std::string BaseAudioContext::getState() {
|
|
51
25
|
return BaseAudioContext::toString(state_);
|
|
52
26
|
}
|
|
53
27
|
|
|
54
|
-
|
|
28
|
+
float BaseAudioContext::getSampleRate() const {
|
|
55
29
|
return sampleRate_;
|
|
56
30
|
}
|
|
57
31
|
|
|
58
|
-
int BaseAudioContext::getBufferSizeInFrames() const {
|
|
59
|
-
return bufferSizeInFrames_;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
32
|
std::size_t BaseAudioContext::getCurrentSampleFrame() const {
|
|
63
33
|
return destination_->getCurrentSampleFrame();
|
|
64
34
|
}
|
|
@@ -93,8 +63,8 @@ std::shared_ptr<AudioBufferSourceNode> BaseAudioContext::createBufferSource() {
|
|
|
93
63
|
|
|
94
64
|
std::shared_ptr<AudioBuffer> BaseAudioContext::createBuffer(
|
|
95
65
|
int numberOfChannels,
|
|
96
|
-
|
|
97
|
-
|
|
66
|
+
size_t length,
|
|
67
|
+
float sampleRate) {
|
|
98
68
|
return std::make_shared<AudioBuffer>(numberOfChannels, length, sampleRate);
|
|
99
69
|
}
|
|
100
70
|
|
|
@@ -117,16 +87,6 @@ std::shared_ptr<AudioBuffer> BaseAudioContext::decodeAudioDataSource(
|
|
|
117
87
|
return std::make_shared<AudioBuffer>(audioBus);
|
|
118
88
|
}
|
|
119
89
|
|
|
120
|
-
std::function<void(AudioBus *, int)> BaseAudioContext::renderAudio() {
|
|
121
|
-
if (!isRunning()) {
|
|
122
|
-
return [](AudioBus *, int) {};
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
return [this](AudioBus *data, int frames) {
|
|
126
|
-
destination_->renderAudio(data, frames);
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
|
|
130
90
|
AudioNodeManager *BaseAudioContext::getNodeManager() {
|
|
131
91
|
return nodeManager_.get();
|
|
132
92
|
}
|
|
@@ -139,6 +99,10 @@ bool BaseAudioContext::isClosed() const {
|
|
|
139
99
|
return state_ == ContextState::CLOSED;
|
|
140
100
|
}
|
|
141
101
|
|
|
102
|
+
float BaseAudioContext::getNyquistFrequency() const {
|
|
103
|
+
return sampleRate_ / 2.0f;
|
|
104
|
+
}
|
|
105
|
+
|
|
142
106
|
std::string BaseAudioContext::toString(ContextState state) {
|
|
143
107
|
switch (state) {
|
|
144
108
|
case ContextState::SUSPENDED:
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
#include <string>
|
|
6
6
|
#include <utility>
|
|
7
7
|
#include <vector>
|
|
8
|
+
#include <cstddef>
|
|
8
9
|
|
|
9
10
|
#include "ContextState.h"
|
|
10
11
|
#include "OscillatorType.h"
|
|
@@ -24,21 +25,14 @@ class AudioBufferSourceNode;
|
|
|
24
25
|
class AudioDecoder;
|
|
25
26
|
class AnalyserNode;
|
|
26
27
|
|
|
27
|
-
#ifdef ANDROID
|
|
28
|
-
class AudioPlayer;
|
|
29
|
-
#else
|
|
30
|
-
class IOSAudioPlayer;
|
|
31
|
-
#endif
|
|
32
|
-
|
|
33
28
|
class BaseAudioContext {
|
|
34
29
|
public:
|
|
35
30
|
BaseAudioContext();
|
|
36
|
-
~BaseAudioContext();
|
|
31
|
+
virtual ~BaseAudioContext() = default;
|
|
37
32
|
|
|
38
33
|
std::string getState();
|
|
39
|
-
[[nodiscard]]
|
|
34
|
+
[[nodiscard]] float getSampleRate() const;
|
|
40
35
|
[[nodiscard]] double getCurrentTime() const;
|
|
41
|
-
[[nodiscard]] int getBufferSizeInFrames() const;
|
|
42
36
|
[[nodiscard]] std::size_t getCurrentSampleFrame() const;
|
|
43
37
|
std::shared_ptr<AudioDestinationNode> getDestination();
|
|
44
38
|
|
|
@@ -48,34 +42,29 @@ class BaseAudioContext {
|
|
|
48
42
|
std::shared_ptr<BiquadFilterNode> createBiquadFilter();
|
|
49
43
|
std::shared_ptr<AudioBufferSourceNode> createBufferSource();
|
|
50
44
|
static std::shared_ptr<AudioBuffer>
|
|
51
|
-
createBuffer(int numberOfChannels,
|
|
45
|
+
createBuffer(int numberOfChannels, size_t length, float sampleRate);
|
|
52
46
|
std::shared_ptr<PeriodicWave> createPeriodicWave(
|
|
53
47
|
float *real,
|
|
54
48
|
float *imag,
|
|
55
49
|
bool disableNormalization,
|
|
56
50
|
int length);
|
|
57
51
|
std::shared_ptr<AnalyserNode> createAnalyser();
|
|
58
|
-
|
|
59
52
|
std::shared_ptr<AudioBuffer> decodeAudioDataSource(const std::string &path);
|
|
53
|
+
|
|
60
54
|
std::shared_ptr<PeriodicWave> getBasicWaveForm(OscillatorType type);
|
|
61
|
-
std::function<void(AudioBus *, int)> renderAudio();
|
|
62
55
|
AudioNodeManager *getNodeManager();
|
|
63
56
|
[[nodiscard]] bool isRunning() const;
|
|
64
57
|
[[nodiscard]] bool isClosed() const;
|
|
58
|
+
[[nodiscard]] float getNyquistFrequency() const;
|
|
65
59
|
|
|
66
60
|
protected:
|
|
67
61
|
static std::string toString(ContextState state);
|
|
68
62
|
std::shared_ptr<AudioDestinationNode> destination_;
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
#ifdef ANDROID
|
|
72
|
-
std::shared_ptr<AudioPlayer> audioPlayer_;
|
|
73
|
-
#else
|
|
74
|
-
std::shared_ptr<IOSAudioPlayer> audioPlayer_;
|
|
75
|
-
#endif
|
|
63
|
+
// init in AudioContext or OfflineContext constructor
|
|
64
|
+
std::shared_ptr<AudioDecoder> audioDecoder_ {};
|
|
76
65
|
|
|
77
|
-
|
|
78
|
-
|
|
66
|
+
// init in AudioContext or OfflineContext constructor
|
|
67
|
+
float sampleRate_ {};
|
|
79
68
|
ContextState state_ = ContextState::RUNNING;
|
|
80
69
|
std::shared_ptr<AudioNodeManager> nodeManager_;
|
|
81
70
|
|
|
@@ -11,9 +11,9 @@ namespace audioapi {
|
|
|
11
11
|
BiquadFilterNode::BiquadFilterNode(BaseAudioContext *context)
|
|
12
12
|
: AudioNode(context) {
|
|
13
13
|
frequencyParam_ = std::make_shared<AudioParam>(
|
|
14
|
-
350.0, MIN_FILTER_FREQUENCY,
|
|
14
|
+
350.0, MIN_FILTER_FREQUENCY, context->getNyquistFrequency());
|
|
15
15
|
detuneParam_ = std::make_shared<AudioParam>(0.0, -MAX_DETUNE, MAX_DETUNE);
|
|
16
|
-
QParam_ = std::make_shared<AudioParam>(1.0,
|
|
16
|
+
QParam_ = std::make_shared<AudioParam>(1.0, MIN_FILTER_Q, MAX_FILTER_Q);
|
|
17
17
|
gainParam_ =
|
|
18
18
|
std::make_shared<AudioParam>(0.0, MIN_FILTER_GAIN, MAX_FILTER_GAIN);
|
|
19
19
|
type_ = BiquadFilterType::LOWPASS;
|
|
@@ -67,8 +67,7 @@ void BiquadFilterNode::getFrequencyResponse(
|
|
|
67
67
|
float a2 = a2_;
|
|
68
68
|
|
|
69
69
|
for (size_t i = 0; i < frequencyArraySize; i++) {
|
|
70
|
-
auto omega =
|
|
71
|
-
static_cast<float>(M_PI) * frequencyArray[i] / NYQUIST_FREQUENCY;
|
|
70
|
+
auto omega = PI * frequencyArray[i] / context_->getNyquistFrequency();
|
|
72
71
|
auto z = std::complex<float>(cos(omega), sin(omega));
|
|
73
72
|
auto response = ((b0 * z + b1) * z + b2) / ((z + a1) * z + a2);
|
|
74
73
|
magResponseOutput[i] = static_cast<float>(abs(response));
|
|
@@ -113,7 +112,7 @@ void BiquadFilterNode::setLowpassCoefficients(float frequency, float Q) {
|
|
|
113
112
|
Q = std::max(0.0f, Q);
|
|
114
113
|
float g = std::pow(10.0f, 0.05f * Q);
|
|
115
114
|
|
|
116
|
-
float theta =
|
|
115
|
+
float theta = PI * frequency;
|
|
117
116
|
float alpha = std::sin(theta) / (2 * g);
|
|
118
117
|
float cosW = std::cos(theta);
|
|
119
118
|
float beta = (1 - cosW) / 2;
|
|
@@ -136,7 +135,7 @@ void BiquadFilterNode::setHighpassCoefficients(float frequency, float Q) {
|
|
|
136
135
|
Q = std::max(0.0f, Q);
|
|
137
136
|
float g = std::pow(10.0f, 0.05f * Q);
|
|
138
137
|
|
|
139
|
-
float theta =
|
|
138
|
+
float theta = PI * frequency;
|
|
140
139
|
float alpha = std::sin(theta) / (2 * g);
|
|
141
140
|
float cosW = std::cos(theta);
|
|
142
141
|
float beta = (1 - cosW) / 2;
|
|
@@ -159,7 +158,7 @@ void BiquadFilterNode::setBandpassCoefficients(float frequency, float Q) {
|
|
|
159
158
|
return;
|
|
160
159
|
}
|
|
161
160
|
|
|
162
|
-
float w0 =
|
|
161
|
+
float w0 = PI * frequency;
|
|
163
162
|
float alpha = std::sin(w0) / (2 * Q);
|
|
164
163
|
float k = std::cos(w0);
|
|
165
164
|
|
|
@@ -181,7 +180,7 @@ void BiquadFilterNode::setLowshelfCoefficients(float frequency, float gain) {
|
|
|
181
180
|
return;
|
|
182
181
|
}
|
|
183
182
|
|
|
184
|
-
float w0 =
|
|
183
|
+
float w0 = PI * frequency;
|
|
185
184
|
float alpha =
|
|
186
185
|
0.5f * std::sin(w0) * std::sqrt((A + 1 / A) * (1 / 1.0f - 1) + 2);
|
|
187
186
|
float k = std::cos(w0);
|
|
@@ -210,7 +209,7 @@ void BiquadFilterNode::setHighshelfCoefficients(float frequency, float gain) {
|
|
|
210
209
|
return;
|
|
211
210
|
}
|
|
212
211
|
|
|
213
|
-
float w0 =
|
|
212
|
+
float w0 = PI * frequency;
|
|
214
213
|
float alpha =
|
|
215
214
|
0.5f * std::sin(w0) * std::sqrt((A + 1 / A) * (1 / 1.0f - 1) + 2);
|
|
216
215
|
float k = std::cos(w0);
|
|
@@ -243,7 +242,7 @@ void BiquadFilterNode::setPeakingCoefficients(
|
|
|
243
242
|
return;
|
|
244
243
|
}
|
|
245
244
|
|
|
246
|
-
float w0 =
|
|
245
|
+
float w0 = PI * frequency;
|
|
247
246
|
float alpha = std::sin(w0) / (2 * Q);
|
|
248
247
|
float k = std::cos(w0);
|
|
249
248
|
|
|
@@ -270,7 +269,7 @@ void BiquadFilterNode::setNotchCoefficients(float frequency, float Q) {
|
|
|
270
269
|
return;
|
|
271
270
|
}
|
|
272
271
|
|
|
273
|
-
float w0 =
|
|
272
|
+
float w0 = PI * frequency;
|
|
274
273
|
float alpha = std::sin(w0) / (2 * Q);
|
|
275
274
|
float k = std::cos(w0);
|
|
276
275
|
|
|
@@ -291,7 +290,7 @@ void BiquadFilterNode::setAllpassCoefficients(float frequency, float Q) {
|
|
|
291
290
|
return;
|
|
292
291
|
}
|
|
293
292
|
|
|
294
|
-
float w0 =
|
|
293
|
+
float w0 = PI * frequency;
|
|
295
294
|
float alpha = std::sin(w0) / (2 * Q);
|
|
296
295
|
float k = std::cos(w0);
|
|
297
296
|
|
|
@@ -302,8 +301,8 @@ void BiquadFilterNode::setAllpassCoefficients(float frequency, float Q) {
|
|
|
302
301
|
void BiquadFilterNode::applyFilter() {
|
|
303
302
|
double currentTime = context_->getCurrentTime();
|
|
304
303
|
|
|
305
|
-
float normalizedFrequency =
|
|
306
|
-
|
|
304
|
+
float normalizedFrequency = frequencyParam_->getValueAtTime(currentTime) /
|
|
305
|
+
context_->getNyquistFrequency();
|
|
307
306
|
float detuneValue = detuneParam_->getValueAtTime(currentTime);
|
|
308
307
|
|
|
309
308
|
if (detuneValue != 0.0) {
|
|
@@ -6,25 +6,39 @@
|
|
|
6
6
|
// https://webaudio.github.io/web-audio-api/
|
|
7
7
|
|
|
8
8
|
namespace audioapi {
|
|
9
|
-
|
|
9
|
+
// context
|
|
10
|
+
constexpr int RENDER_QUANTUM_SIZE = 128;
|
|
10
11
|
constexpr int CHANNEL_COUNT = 2;
|
|
11
12
|
|
|
13
|
+
// general
|
|
12
14
|
constexpr float MOST_POSITIVE_SINGLE_FLOAT = static_cast<float>(std::numeric_limits<float>::max());
|
|
13
15
|
constexpr float MOST_NEGATIVE_SINGLE_FLOAT = static_cast<float>(std::numeric_limits<float>::lowest());
|
|
16
|
+
constexpr float PI = static_cast<float>(M_PI);
|
|
14
17
|
|
|
15
|
-
|
|
16
|
-
static float MAX_DETUNE = 1200 * std::log2(MOST_POSITIVE_SINGLE_FLOAT);
|
|
17
|
-
constexpr float MAX_GAIN = MOST_POSITIVE_SINGLE_FLOAT;
|
|
18
|
+
// pan
|
|
18
19
|
constexpr float MAX_PAN = 1.0;
|
|
19
|
-
constexpr float
|
|
20
|
-
|
|
20
|
+
constexpr float MIN_PAN = -1.0;
|
|
21
|
+
|
|
22
|
+
// gain
|
|
23
|
+
constexpr float MAX_GAIN = MOST_POSITIVE_SINGLE_FLOAT;
|
|
24
|
+
constexpr float MIN_GAIN = -MAX_GAIN;
|
|
25
|
+
|
|
26
|
+
// biquad filter
|
|
21
27
|
constexpr float MIN_FILTER_FREQUENCY = 0.0;
|
|
22
28
|
static float MAX_FILTER_GAIN = 40 * std::log10(MOST_POSITIVE_SINGLE_FLOAT);
|
|
23
|
-
|
|
29
|
+
static float MIN_FILTER_GAIN = -MAX_GAIN;
|
|
30
|
+
constexpr float MAX_FILTER_Q = MOST_POSITIVE_SINGLE_FLOAT;
|
|
31
|
+
constexpr float MIN_FILTER_Q = -MAX_FILTER_Q;
|
|
32
|
+
|
|
33
|
+
//detune
|
|
34
|
+
static float MAX_DETUNE = 1200 * std::log2(MOST_POSITIVE_SINGLE_FLOAT);
|
|
35
|
+
static float MIN_DETUNE = -MAX_DETUNE;
|
|
24
36
|
|
|
25
|
-
|
|
26
|
-
constexpr
|
|
27
|
-
constexpr
|
|
28
|
-
constexpr
|
|
29
|
-
|
|
37
|
+
// analyser node
|
|
38
|
+
constexpr size_t MAX_FFT_SIZE = 32768;
|
|
39
|
+
constexpr size_t MIN_FFT_SIZE = 32;
|
|
40
|
+
constexpr size_t DEFAULT_FFT_SIZE = 2048;
|
|
41
|
+
constexpr float DEFAULT_MAX_DECIBELS = -30;
|
|
42
|
+
constexpr float DEFAULT_MIN_DECIBELS = -100;
|
|
43
|
+
const float DEFAULT_SMOOTHING_TIME_CONSTANT = 0.8;
|
|
30
44
|
} // namespace audioapi
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
namespace audioapi {
|
|
7
7
|
|
|
8
8
|
GainNode::GainNode(BaseAudioContext *context) : AudioNode(context) {
|
|
9
|
-
gainParam_ = std::make_shared<AudioParam>(1.0,
|
|
9
|
+
gainParam_ = std::make_shared<AudioParam>(1.0, MIN_GAIN, MAX_GAIN);
|
|
10
10
|
isInitialized_ = true;
|
|
11
11
|
}
|
|
12
12
|
|
|
@@ -8,7 +8,7 @@ namespace audioapi {
|
|
|
8
8
|
OscillatorNode::OscillatorNode(BaseAudioContext *context)
|
|
9
9
|
: AudioScheduledSourceNode(context) {
|
|
10
10
|
frequencyParam_ = std::make_shared<AudioParam>(
|
|
11
|
-
444.0, -
|
|
11
|
+
444.0, -context_->getNyquistFrequency(), context_->getNyquistFrequency());
|
|
12
12
|
detuneParam_ = std::make_shared<AudioParam>(0.0, -MAX_DETUNE, MAX_DETUNE);
|
|
13
13
|
type_ = OscillatorType::SINE;
|
|
14
14
|
periodicWave_ = context_->getBasicWaveForm(type_);
|
|
@@ -49,8 +49,9 @@ void OscillatorNode::processNode(AudioBus *processingBus, int framesToProcess) {
|
|
|
49
49
|
return;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
auto deltaTime = 1.0 / context_->getSampleRate();
|
|
53
|
+
auto time =
|
|
54
|
+
context_->getCurrentTime() + static_cast<double>(startOffset) * deltaTime;
|
|
54
55
|
|
|
55
56
|
for (size_t i = startOffset; i < offsetLength; i += 1) {
|
|
56
57
|
auto detuneRatio =
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
*/
|
|
28
28
|
|
|
29
29
|
#include "PeriodicWave.h"
|
|
30
|
+
#include "Constants.h"
|
|
30
31
|
|
|
31
32
|
constexpr unsigned NumberOfOctaveBands = 3;
|
|
32
33
|
constexpr float CentsPerRange = 1200.0f / NumberOfOctaveBands;
|
|
@@ -34,10 +35,10 @@ constexpr float interpolate2Point = 0.3;
|
|
|
34
35
|
constexpr float interpolate3Point = 0.16;
|
|
35
36
|
|
|
36
37
|
namespace audioapi {
|
|
37
|
-
PeriodicWave::PeriodicWave(
|
|
38
|
+
PeriodicWave::PeriodicWave(float sampleRate, bool disableNormalization)
|
|
38
39
|
: sampleRate_(sampleRate), disableNormalization_(disableNormalization) {
|
|
39
|
-
numberOfRanges_ =
|
|
40
|
-
NumberOfOctaveBands * log2f(static_cast<float>(getPeriodicWaveSize())));
|
|
40
|
+
numberOfRanges_ = static_cast<int>(round(
|
|
41
|
+
NumberOfOctaveBands * log2f(static_cast<float>(getPeriodicWaveSize()))));
|
|
41
42
|
auto nyquistFrequency = sampleRate_ / 2;
|
|
42
43
|
lowestFundamentalFrequency_ = static_cast<float>(nyquistFrequency) /
|
|
43
44
|
static_cast<float>(getMaxNumberOfPartials());
|
|
@@ -47,7 +48,7 @@ PeriodicWave::PeriodicWave(int sampleRate, bool disableNormalization)
|
|
|
47
48
|
}
|
|
48
49
|
|
|
49
50
|
PeriodicWave::PeriodicWave(
|
|
50
|
-
|
|
51
|
+
float sampleRate,
|
|
51
52
|
audioapi::OscillatorType type,
|
|
52
53
|
bool disableNormalization)
|
|
53
54
|
: PeriodicWave(sampleRate, disableNormalization) {
|
|
@@ -55,7 +56,7 @@ PeriodicWave::PeriodicWave(
|
|
|
55
56
|
}
|
|
56
57
|
|
|
57
58
|
PeriodicWave::PeriodicWave(
|
|
58
|
-
|
|
59
|
+
float sampleRate,
|
|
59
60
|
float *real,
|
|
60
61
|
float *imaginary,
|
|
61
62
|
int length,
|
|
@@ -147,7 +148,7 @@ void PeriodicWave::generateBasicWaveForm(OscillatorType type) {
|
|
|
147
148
|
// Coefficient for sin()
|
|
148
149
|
float b;
|
|
149
150
|
|
|
150
|
-
auto piFactor =
|
|
151
|
+
auto piFactor = 1.0f / (PI * static_cast<float>(i));
|
|
151
152
|
|
|
152
153
|
switch (type) {
|
|
153
154
|
case OscillatorType::SINE:
|
|
@@ -40,11 +40,11 @@ namespace audioapi {
|
|
|
40
40
|
class PeriodicWave {
|
|
41
41
|
public:
|
|
42
42
|
explicit PeriodicWave(
|
|
43
|
-
|
|
43
|
+
float sampleRate,
|
|
44
44
|
OscillatorType type,
|
|
45
45
|
bool disableNormalization);
|
|
46
46
|
explicit PeriodicWave(
|
|
47
|
-
|
|
47
|
+
float sampleRate,
|
|
48
48
|
float *real,
|
|
49
49
|
float *imaginary,
|
|
50
50
|
int length,
|
|
@@ -57,7 +57,7 @@ class PeriodicWave {
|
|
|
57
57
|
getSample(float fundamentalFrequency, float phase, float phaseIncrement);
|
|
58
58
|
|
|
59
59
|
private:
|
|
60
|
-
explicit PeriodicWave(
|
|
60
|
+
explicit PeriodicWave(float sampleRate, bool disableNormalization);
|
|
61
61
|
|
|
62
62
|
// Partial is any frequency component of a sound.
|
|
63
63
|
// Both harmonics(fundamentalFrequency * k) and overtones are partials.
|
|
@@ -102,7 +102,7 @@ class PeriodicWave {
|
|
|
102
102
|
const float *higherWaveData) const;
|
|
103
103
|
|
|
104
104
|
// determines the time resolution of the waveform.
|
|
105
|
-
|
|
105
|
+
float sampleRate_;
|
|
106
106
|
// determines number of frequency segments (or bands) the signal is divided.
|
|
107
107
|
int numberOfRanges_;
|
|
108
108
|
// the lowest frequency (in hertz) where playback will include all of the
|
|
@@ -11,7 +11,7 @@ namespace audioapi {
|
|
|
11
11
|
StereoPannerNode::StereoPannerNode(BaseAudioContext *context)
|
|
12
12
|
: AudioNode(context) {
|
|
13
13
|
channelCountMode_ = ChannelCountMode::CLAMPED_MAX;
|
|
14
|
-
panParam_ = std::make_shared<AudioParam>(0.0,
|
|
14
|
+
panParam_ = std::make_shared<AudioParam>(0.0, MIN_PAN, MAX_PAN);
|
|
15
15
|
isInitialized_ = true;
|
|
16
16
|
}
|
|
17
17
|
|
|
@@ -36,10 +36,10 @@ void StereoPannerNode::processNode(
|
|
|
36
36
|
|
|
37
37
|
for (int i = 0; i < framesToProcess; i += 1) {
|
|
38
38
|
float pan = panParam_->getValueAtTime(time);
|
|
39
|
-
float x = (pan <= 0 ? pan + 1 : pan) *
|
|
39
|
+
float x = (pan <= 0 ? pan + 1 : pan) * PI / 2;
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
auto gainL = static_cast<float>(cos(x));
|
|
42
|
+
auto gainR = static_cast<float>(sin(x));
|
|
43
43
|
|
|
44
44
|
float inputL = (*left)[i];
|
|
45
45
|
float inputR = (*right)[i];
|