react-native-audio-api 0.4.8-rc1 → 0.4.8
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/build.gradle +25 -2
- package/android/src/main/cpp/core/AudioDecoder.cpp +10 -1
- package/android/src/main/cpp/core/AudioPlayer.cpp +6 -3
- package/common/cpp/core/AnalyserNode.cpp +2 -6
- package/common/cpp/core/AudioBuffer.cpp +1 -1
- package/common/cpp/core/AudioBufferSourceNode.cpp +26 -16
- package/common/cpp/core/AudioBus.cpp +105 -13
- package/common/cpp/core/AudioBus.h +6 -4
- package/common/cpp/core/AudioContext.cpp +4 -3
- package/common/cpp/core/AudioContext.h +4 -4
- package/common/cpp/core/AudioDestinationNode.cpp +2 -3
- package/common/cpp/core/AudioNode.cpp +78 -58
- package/common/cpp/core/AudioNode.h +10 -1
- package/common/cpp/core/AudioNodeManager.cpp +13 -1
- package/common/cpp/core/AudioNodeManager.h +2 -0
- package/common/cpp/core/AudioScheduledSourceNode.cpp +5 -1
- package/common/cpp/core/BaseAudioContext.cpp +4 -1
- package/common/cpp/core/BaseAudioContext.h +4 -2
- package/common/cpp/core/StereoPannerNode.cpp +9 -12
- package/ios/core/AudioDecoder.mm +10 -1
- package/ios/core/AudioPlayer.m +4 -24
- package/ios/core/IOSAudioPlayer.mm +3 -3
- package/lib/module/core/AudioBufferSourceNode.js +2 -2
- package/lib/module/core/AudioBufferSourceNode.js.map +1 -1
- package/lib/module/index.js +19 -335
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.web.js +18 -0
- package/lib/module/index.web.js.map +1 -0
- package/lib/module/types.js.map +1 -0
- package/lib/module/web-core/AnalyserNode.js +48 -0
- package/lib/module/web-core/AnalyserNode.js.map +1 -0
- package/lib/module/web-core/AudioBuffer.js +43 -0
- package/lib/module/web-core/AudioBuffer.js.map +1 -0
- package/lib/module/web-core/AudioBufferSourceNode.js +62 -0
- package/lib/module/web-core/AudioBufferSourceNode.js.map +1 -0
- package/lib/module/web-core/AudioContext.js +69 -0
- package/lib/module/web-core/AudioContext.js.map +1 -0
- package/lib/module/web-core/AudioDestinationNode.js +5 -0
- package/lib/module/web-core/AudioDestinationNode.js.map +1 -0
- package/lib/module/web-core/AudioNode.js +27 -0
- package/lib/module/web-core/AudioNode.js.map +1 -0
- package/lib/module/web-core/AudioParam.js +60 -0
- package/lib/module/web-core/AudioParam.js.map +1 -0
- package/lib/module/web-core/AudioScheduledSourceNode.js +27 -0
- package/lib/module/web-core/AudioScheduledSourceNode.js.map +1 -0
- package/lib/module/web-core/BaseAudioContext.js +2 -0
- package/lib/module/{core/types.js.map → web-core/BaseAudioContext.js.map} +1 -1
- package/lib/module/web-core/BiquadFilterNode.js +35 -0
- package/lib/module/web-core/BiquadFilterNode.js.map +1 -0
- package/lib/module/web-core/GainNode.js +11 -0
- package/lib/module/web-core/GainNode.js.map +1 -0
- package/lib/module/web-core/OscillatorNode.js +25 -0
- package/lib/module/web-core/OscillatorNode.js.map +1 -0
- package/lib/module/web-core/PeriodicWave.js +10 -0
- package/lib/module/web-core/PeriodicWave.js.map +1 -0
- package/lib/module/web-core/StereoPannerNode.js +11 -0
- package/lib/module/web-core/StereoPannerNode.js.map +1 -0
- package/lib/typescript/core/AnalyserNode.d.ts +1 -1
- package/lib/typescript/core/AnalyserNode.d.ts.map +1 -1
- package/lib/typescript/core/AudioNode.d.ts +1 -1
- package/lib/typescript/core/AudioNode.d.ts.map +1 -1
- package/lib/typescript/core/BaseAudioContext.d.ts +1 -1
- package/lib/typescript/core/BaseAudioContext.d.ts.map +1 -1
- package/lib/typescript/core/BiquadFilterNode.d.ts +1 -1
- package/lib/typescript/core/BiquadFilterNode.d.ts.map +1 -1
- package/lib/typescript/core/OscillatorNode.d.ts +1 -1
- package/lib/typescript/core/OscillatorNode.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +15 -126
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/index.web.d.ts +16 -0
- package/lib/typescript/index.web.d.ts.map +1 -0
- package/lib/typescript/interfaces.d.ts +1 -1
- package/lib/typescript/interfaces.d.ts.map +1 -1
- package/lib/typescript/types.d.ts.map +1 -0
- package/lib/typescript/web-core/AnalyserNode.d.ts +18 -0
- package/lib/typescript/web-core/AnalyserNode.d.ts.map +1 -0
- package/lib/typescript/web-core/AudioBuffer.d.ts +13 -0
- package/lib/typescript/web-core/AudioBuffer.d.ts.map +1 -0
- package/lib/typescript/web-core/AudioBufferSourceNode.d.ts +19 -0
- package/lib/typescript/web-core/AudioBufferSourceNode.d.ts.map +1 -0
- package/lib/typescript/web-core/AudioContext.d.ts +30 -0
- package/lib/typescript/web-core/AudioContext.d.ts.map +1 -0
- package/lib/typescript/web-core/AudioDestinationNode.d.ts +4 -0
- package/lib/typescript/web-core/AudioDestinationNode.d.ts.map +1 -0
- package/lib/typescript/web-core/AudioNode.d.ts +15 -0
- package/lib/typescript/web-core/AudioNode.d.ts.map +1 -0
- package/lib/typescript/web-core/AudioParam.d.ts +17 -0
- package/lib/typescript/web-core/AudioParam.d.ts.map +1 -0
- package/lib/typescript/web-core/AudioScheduledSourceNode.d.ts +7 -0
- package/lib/typescript/web-core/AudioScheduledSourceNode.d.ts.map +1 -0
- package/lib/typescript/web-core/BaseAudioContext.d.ts +27 -0
- package/lib/typescript/web-core/BaseAudioContext.d.ts.map +1 -0
- package/lib/typescript/web-core/BiquadFilterNode.d.ts +15 -0
- package/lib/typescript/web-core/BiquadFilterNode.d.ts.map +1 -0
- package/lib/typescript/web-core/GainNode.d.ts +8 -0
- package/lib/typescript/web-core/GainNode.d.ts.map +1 -0
- package/lib/typescript/web-core/OscillatorNode.d.ts +14 -0
- package/lib/typescript/web-core/OscillatorNode.d.ts.map +1 -0
- package/lib/typescript/web-core/PeriodicWave.d.ts +6 -0
- package/lib/typescript/web-core/PeriodicWave.d.ts.map +1 -0
- package/lib/typescript/web-core/StereoPannerNode.d.ts +8 -0
- package/lib/typescript/web-core/StereoPannerNode.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/core/AnalyserNode.ts +1 -1
- package/src/core/AudioBufferSourceNode.ts +2 -2
- package/src/core/AudioNode.ts +1 -1
- package/src/core/BaseAudioContext.ts +1 -1
- package/src/core/BiquadFilterNode.ts +1 -1
- package/src/core/OscillatorNode.ts +1 -1
- package/src/index.ts +30 -568
- package/src/index.web.ts +30 -0
- package/src/interfaces.ts +1 -1
- package/src/web-core/AnalyserNode.tsx +69 -0
- package/src/web-core/AudioBuffer.tsx +79 -0
- package/src/web-core/AudioBufferSourceNode.tsx +94 -0
- package/src/web-core/AudioContext.tsx +114 -0
- package/src/web-core/AudioDestinationNode.tsx +3 -0
- package/src/web-core/AudioNode.tsx +40 -0
- package/src/web-core/AudioParam.tsx +106 -0
- package/src/web-core/AudioScheduledSourceNode.tsx +37 -0
- package/src/web-core/BaseAudioContext.tsx +37 -0
- package/src/web-core/BiquadFilterNode.tsx +62 -0
- package/src/web-core/GainNode.tsx +12 -0
- package/src/web-core/OscillatorNode.tsx +36 -0
- package/src/web-core/PeriodicWave.tsx +8 -0
- package/src/web-core/StereoPannerNode.tsx +12 -0
- package/lib/module/index.native.js +0 -21
- package/lib/module/index.native.js.map +0 -1
- package/lib/typescript/core/types.d.ts.map +0 -1
- package/lib/typescript/index.native.d.ts +0 -15
- package/lib/typescript/index.native.d.ts.map +0 -1
- package/src/index.native.ts +0 -27
- /package/lib/module/{core/types.js → types.js} +0 -0
- /package/lib/typescript/{core/types.d.ts → types.d.ts} +0 -0
- /package/src/{core/types.ts → types.ts} +0 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
#include <cassert>
|
|
1
2
|
#include <memory>
|
|
2
3
|
|
|
3
4
|
#include "AudioBus.h"
|
|
@@ -9,11 +10,11 @@ namespace audioapi {
|
|
|
9
10
|
|
|
10
11
|
AudioNode::AudioNode(BaseAudioContext *context) : context_(context) {
|
|
11
12
|
audioBus_ = std::make_shared<AudioBus>(
|
|
12
|
-
context->getSampleRate()
|
|
13
|
+
RENDER_QUANTUM_SIZE, channelCount_, context->getSampleRate());
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
AudioNode::~AudioNode() {
|
|
16
|
-
|
|
17
|
+
isInitialized_ = false;
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
int AudioNode::getNumberOfInputs() const {
|
|
@@ -101,87 +102,91 @@ AudioBus *AudioNode::processAudio(AudioBus *outputBus, int framesToProcess) {
|
|
|
101
102
|
return outputBus;
|
|
102
103
|
}
|
|
103
104
|
|
|
105
|
+
if (isAlreadyProcessed()) {
|
|
106
|
+
return audioBus_.get();
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Process inputs and return the bus with the most channels.
|
|
110
|
+
AudioBus *processingBus = processInputs(outputBus, framesToProcess);
|
|
111
|
+
|
|
112
|
+
// Apply channel count mode.
|
|
113
|
+
processingBus = applyChannelCountMode(processingBus);
|
|
114
|
+
|
|
115
|
+
// Mix all input buses into the processing bus.
|
|
116
|
+
mixInputsBuses(processingBus);
|
|
117
|
+
|
|
118
|
+
assert(processingBus != nullptr);
|
|
119
|
+
// Finally, process the node itself.
|
|
120
|
+
processNode(processingBus, framesToProcess);
|
|
121
|
+
|
|
122
|
+
return processingBus;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
bool AudioNode::isAlreadyProcessed() {
|
|
126
|
+
assert(context_ != nullptr);
|
|
127
|
+
|
|
104
128
|
std::size_t currentSampleFrame = context_->getCurrentSampleFrame();
|
|
105
129
|
|
|
106
130
|
// check if the node has already been processed for this rendering quantum
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
// Node can't use output bus if:
|
|
110
|
-
// - outputBus is not provided, which means that next node is doing a
|
|
111
|
-
// multi-node summing.
|
|
112
|
-
// - it has more than one input, which means that it has to sum all inputs
|
|
113
|
-
// using internal bus.
|
|
114
|
-
// - it has more than one output, so each output node can get the processed
|
|
115
|
-
// data without re-calculating the node.
|
|
116
|
-
bool canUseOutputBus =
|
|
117
|
-
outputBus != nullptr && inputNodes_.size() < 2 && outputNodes_.size() < 2;
|
|
118
|
-
|
|
119
|
-
if (isAlreadyProcessed) {
|
|
120
|
-
// If it was already processed in the rendering quantum, return it.
|
|
121
|
-
return audioBus_.get();
|
|
131
|
+
if (currentSampleFrame == lastRenderedFrame_) {
|
|
132
|
+
return true;
|
|
122
133
|
}
|
|
123
134
|
|
|
124
135
|
// Update the last rendered frame before processing node and its inputs.
|
|
125
136
|
lastRenderedFrame_ = currentSampleFrame;
|
|
126
137
|
|
|
127
|
-
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
128
140
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
}
|
|
141
|
+
AudioBus *AudioNode::processInputs(AudioBus *outputBus, int framesToProcess) {
|
|
142
|
+
AudioBus *processingBus = audioBus_.get();
|
|
143
|
+
processingBus->zero();
|
|
133
144
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
// silence.
|
|
138
|
-
processNode(processingBus, framesToProcess);
|
|
139
|
-
return processingBus;
|
|
140
|
-
}
|
|
145
|
+
int maxNumberOfChannels = 0;
|
|
146
|
+
for (auto inputNode : inputNodes_) {
|
|
147
|
+
assert(inputNode != nullptr);
|
|
141
148
|
|
|
142
|
-
|
|
143
|
-
if (!(*it)->isEnabled()) {
|
|
149
|
+
if (!inputNode->isEnabled()) {
|
|
144
150
|
continue;
|
|
145
151
|
}
|
|
146
152
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
// add assert
|
|
154
|
-
processingBus->sum(inputBus);
|
|
155
|
-
}
|
|
156
|
-
} else {
|
|
157
|
-
// Enforce the summing to be done using the internal bus.
|
|
158
|
-
AudioBus *inputBus = (*it)->processAudio(nullptr, framesToProcess);
|
|
159
|
-
if (inputBus) {
|
|
160
|
-
// add assert
|
|
161
|
-
processingBus->sum(inputBus);
|
|
162
|
-
}
|
|
153
|
+
auto inputBus = inputNode->processAudio(outputBus, framesToProcess);
|
|
154
|
+
inputBuses_.push_back(inputBus);
|
|
155
|
+
|
|
156
|
+
if (maxNumberOfChannels < inputBus->getNumberOfChannels()) {
|
|
157
|
+
maxNumberOfChannels = inputBus->getNumberOfChannels();
|
|
158
|
+
processingBus = inputBus;
|
|
163
159
|
}
|
|
164
160
|
}
|
|
165
161
|
|
|
166
|
-
// Finally, process the node itself.
|
|
167
|
-
processNode(processingBus, framesToProcess);
|
|
168
|
-
|
|
169
162
|
return processingBus;
|
|
170
163
|
}
|
|
171
164
|
|
|
172
|
-
|
|
173
|
-
|
|
165
|
+
AudioBus *AudioNode::applyChannelCountMode(AudioBus *processingBus) {
|
|
166
|
+
// If the channelCountMode is EXPLICIT, the node should output the number of
|
|
167
|
+
// channels specified by the channelCount.
|
|
168
|
+
if (channelCountMode_ == ChannelCountMode::EXPLICIT) {
|
|
169
|
+
return audioBus_.get();
|
|
170
|
+
}
|
|
174
171
|
|
|
175
|
-
|
|
176
|
-
|
|
172
|
+
// If the channelCountMode is CLAMPED_MAX, the node should output the maximum
|
|
173
|
+
// number of channels clamped to channelCount.
|
|
174
|
+
if (channelCountMode_ == ChannelCountMode::CLAMPED_MAX &&
|
|
175
|
+
processingBus->getNumberOfChannels() >= channelCount_) {
|
|
176
|
+
return audioBus_.get();
|
|
177
177
|
}
|
|
178
178
|
|
|
179
|
-
|
|
180
|
-
|
|
179
|
+
return processingBus;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
void AudioNode::mixInputsBuses(AudioBus *processingBus) {
|
|
183
|
+
assert(processingBus != nullptr);
|
|
184
|
+
|
|
185
|
+
for (auto inputBus : inputBuses_) {
|
|
186
|
+
processingBus->sum(inputBus, channelInterpretation_);
|
|
181
187
|
}
|
|
182
188
|
|
|
183
|
-
|
|
184
|
-
inputNodes_.clear();
|
|
189
|
+
inputBuses_.clear();
|
|
185
190
|
}
|
|
186
191
|
|
|
187
192
|
void AudioNode::connectNode(const std::shared_ptr<AudioNode> &node) {
|
|
@@ -234,4 +239,19 @@ void AudioNode::onInputDisconnected(AudioNode *node) {
|
|
|
234
239
|
}
|
|
235
240
|
}
|
|
236
241
|
|
|
242
|
+
void AudioNode::cleanup() {
|
|
243
|
+
isInitialized_ = false;
|
|
244
|
+
|
|
245
|
+
for (const auto &outputNode : outputNodes_) {
|
|
246
|
+
outputNode->onInputDisconnected(this);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
for (const auto &inputNode : inputNodes_) {
|
|
250
|
+
inputNode->disconnectNode(shared_from_this());
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
outputNodes_.clear();
|
|
254
|
+
inputNodes_.clear();
|
|
255
|
+
}
|
|
256
|
+
|
|
237
257
|
} // namespace audioapi
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
#include <string>
|
|
5
5
|
#include <unordered_set>
|
|
6
6
|
#include <cstddef>
|
|
7
|
+
#include <vector>
|
|
7
8
|
|
|
8
9
|
#include "ChannelCountMode.h"
|
|
9
10
|
#include "ChannelInterpretation.h"
|
|
@@ -56,13 +57,19 @@ class AudioNode : public std::enable_shared_from_this<AudioNode> {
|
|
|
56
57
|
std::size_t lastRenderedFrame_{SIZE_MAX};
|
|
57
58
|
|
|
58
59
|
private:
|
|
60
|
+
std::vector<AudioBus*> inputBuses_;
|
|
61
|
+
|
|
59
62
|
static std::string toString(ChannelCountMode mode);
|
|
60
63
|
static std::string toString(ChannelInterpretation interpretation);
|
|
61
64
|
|
|
62
|
-
void cleanup();
|
|
63
65
|
AudioBus *processAudio(AudioBus *outputBus, int framesToProcess);
|
|
64
66
|
virtual void processNode(AudioBus *processingBus, int framesToProcess) = 0;
|
|
65
67
|
|
|
68
|
+
bool isAlreadyProcessed();
|
|
69
|
+
AudioBus *processInputs(AudioBus *outputBus, int framesToProcess);
|
|
70
|
+
AudioBus *applyChannelCountMode(AudioBus *processingBus);
|
|
71
|
+
void mixInputsBuses(AudioBus *processingBus);
|
|
72
|
+
|
|
66
73
|
void connectNode(const std::shared_ptr<AudioNode> &node);
|
|
67
74
|
void disconnectNode(const std::shared_ptr<AudioNode> &node);
|
|
68
75
|
|
|
@@ -70,6 +77,8 @@ class AudioNode : public std::enable_shared_from_this<AudioNode> {
|
|
|
70
77
|
void onInputDisabled();
|
|
71
78
|
void onInputConnected(AudioNode *node);
|
|
72
79
|
void onInputDisconnected(AudioNode *node);
|
|
80
|
+
|
|
81
|
+
void cleanup();
|
|
73
82
|
};
|
|
74
83
|
|
|
75
84
|
} // namespace audioapi
|
|
@@ -43,7 +43,9 @@ void AudioNodeManager::settlePendingConnections() {
|
|
|
43
43
|
std::shared_ptr<AudioNode> to = std::get<1>(connection);
|
|
44
44
|
ConnectionType type = std::get<2>(connection);
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
if (!to || !from) {
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
47
49
|
|
|
48
50
|
if (type == ConnectionType::CONNECT) {
|
|
49
51
|
from->connectNode(to);
|
|
@@ -66,4 +68,14 @@ void AudioNodeManager::prepareNodesForDestruction() {
|
|
|
66
68
|
}
|
|
67
69
|
}
|
|
68
70
|
|
|
71
|
+
void AudioNodeManager::cleanup() {
|
|
72
|
+
Locker lock(getGraphLock());
|
|
73
|
+
|
|
74
|
+
for (auto &node : nodes_) {
|
|
75
|
+
node->cleanup();
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
nodes_.clear();
|
|
79
|
+
}
|
|
80
|
+
|
|
69
81
|
} // namespace audioapi
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
#include
|
|
1
|
+
#include <cassert>
|
|
2
|
+
|
|
2
3
|
#include "AudioArray.h"
|
|
3
4
|
#include "AudioBus.h"
|
|
4
5
|
#include "AudioNodeManager.h"
|
|
6
|
+
#include "AudioScheduledSourceNode.h"
|
|
5
7
|
#include "AudioUtils.h"
|
|
6
8
|
#include "BaseAudioContext.h"
|
|
7
9
|
|
|
@@ -51,6 +53,8 @@ void AudioScheduledSourceNode::updatePlaybackInfo(
|
|
|
51
53
|
return;
|
|
52
54
|
}
|
|
53
55
|
|
|
56
|
+
assert(context_ != nullptr);
|
|
57
|
+
|
|
54
58
|
auto sampleRate = context_->getSampleRate();
|
|
55
59
|
|
|
56
60
|
size_t firstFrame = context_->getCurrentSampleFrame();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#include
|
|
1
|
+
#include <cassert>
|
|
2
2
|
|
|
3
3
|
#include "AnalyserNode.h"
|
|
4
4
|
#include "AudioArray.h"
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
#include "AudioDecoder.h"
|
|
9
9
|
#include "AudioDestinationNode.h"
|
|
10
10
|
#include "AudioNodeManager.h"
|
|
11
|
+
#include "BaseAudioContext.h"
|
|
11
12
|
#include "BiquadFilterNode.h"
|
|
12
13
|
#include "ContextState.h"
|
|
13
14
|
#include "GainNode.h"
|
|
@@ -30,10 +31,12 @@ float BaseAudioContext::getSampleRate() const {
|
|
|
30
31
|
}
|
|
31
32
|
|
|
32
33
|
std::size_t BaseAudioContext::getCurrentSampleFrame() const {
|
|
34
|
+
assert(destination_ != nullptr);
|
|
33
35
|
return destination_->getCurrentSampleFrame();
|
|
34
36
|
}
|
|
35
37
|
|
|
36
38
|
double BaseAudioContext::getCurrentTime() const {
|
|
39
|
+
assert(destination_ != nullptr);
|
|
37
40
|
return destination_->getCurrentTime();
|
|
38
41
|
}
|
|
39
42
|
|
|
@@ -49,20 +49,22 @@ class BaseAudioContext {
|
|
|
49
49
|
bool disableNormalization,
|
|
50
50
|
int length);
|
|
51
51
|
std::shared_ptr<AnalyserNode> createAnalyser();
|
|
52
|
+
|
|
52
53
|
std::shared_ptr<AudioBuffer> decodeAudioDataSource(const std::string &path);
|
|
53
54
|
|
|
54
55
|
std::shared_ptr<PeriodicWave> getBasicWaveForm(OscillatorType type);
|
|
56
|
+
[[nodiscard]] float getNyquistFrequency() const;
|
|
55
57
|
AudioNodeManager *getNodeManager();
|
|
58
|
+
|
|
56
59
|
[[nodiscard]] bool isRunning() const;
|
|
57
60
|
[[nodiscard]] bool isClosed() const;
|
|
58
|
-
[[nodiscard]] float getNyquistFrequency() const;
|
|
59
61
|
|
|
60
62
|
protected:
|
|
61
63
|
static std::string toString(ContextState state);
|
|
64
|
+
|
|
62
65
|
std::shared_ptr<AudioDestinationNode> destination_;
|
|
63
66
|
// init in AudioContext or OfflineContext constructor
|
|
64
67
|
std::shared_ptr<AudioDecoder> audioDecoder_ {};
|
|
65
|
-
|
|
66
68
|
// init in AudioContext or OfflineContext constructor
|
|
67
69
|
float sampleRate_ {};
|
|
68
70
|
ContextState state_ = ContextState::RUNNING;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
#include
|
|
1
|
+
#include <cassert>
|
|
2
|
+
|
|
2
3
|
#include "AudioArray.h"
|
|
3
4
|
#include "AudioBus.h"
|
|
4
5
|
#include "BaseAudioContext.h"
|
|
5
6
|
#include "Constants.h"
|
|
7
|
+
#include "StereoPannerNode.h"
|
|
6
8
|
|
|
7
9
|
// https://webaudio.github.io/web-audio-api/#stereopanner-algorithm
|
|
8
10
|
|
|
@@ -10,7 +12,7 @@ namespace audioapi {
|
|
|
10
12
|
|
|
11
13
|
StereoPannerNode::StereoPannerNode(BaseAudioContext *context)
|
|
12
14
|
: AudioNode(context) {
|
|
13
|
-
channelCountMode_ = ChannelCountMode::
|
|
15
|
+
channelCountMode_ = ChannelCountMode::EXPLICIT;
|
|
14
16
|
panParam_ = std::make_shared<AudioParam>(0.0, MIN_PAN, MAX_PAN);
|
|
15
17
|
isInitialized_ = true;
|
|
16
18
|
}
|
|
@@ -22,12 +24,6 @@ std::shared_ptr<AudioParam> StereoPannerNode::getPanParam() const {
|
|
|
22
24
|
void StereoPannerNode::processNode(
|
|
23
25
|
AudioBus *processingBus,
|
|
24
26
|
int framesToProcess) {
|
|
25
|
-
// TODO: Currently assumed channelCount is 2
|
|
26
|
-
// it should:
|
|
27
|
-
// - support mono-channel buses
|
|
28
|
-
// - throw errors when trying to setup stereo panner with more than 2
|
|
29
|
-
// channels
|
|
30
|
-
|
|
31
27
|
double time = context_->getCurrentTime();
|
|
32
28
|
double deltaTime = 1.0 / context_->getSampleRate();
|
|
33
29
|
|
|
@@ -35,11 +31,12 @@ void StereoPannerNode::processNode(
|
|
|
35
31
|
AudioArray *right = processingBus->getChannelByType(AudioBus::ChannelRight);
|
|
36
32
|
|
|
37
33
|
for (int i = 0; i < framesToProcess; i += 1) {
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
auto pan = panParam_->getValueAtTime(time);
|
|
35
|
+
|
|
36
|
+
auto x = (pan <= 0 ? pan + 1 : pan);
|
|
40
37
|
|
|
41
|
-
auto gainL = static_cast<float>(cos(x));
|
|
42
|
-
auto gainR = static_cast<float>(sin(x));
|
|
38
|
+
auto gainL = static_cast<float>(cos(x * PI / 2));
|
|
39
|
+
auto gainR = static_cast<float>(sin(x * PI / 2));
|
|
43
40
|
|
|
44
41
|
float inputL = (*left)[i];
|
|
45
42
|
float inputR = (*right)[i];
|
package/ios/core/AudioDecoder.mm
CHANGED
|
@@ -14,19 +14,28 @@ AudioBus *AudioDecoder::decodeWithFilePath(const std::string &path) const
|
|
|
14
14
|
ma_result result = ma_decoder_init_file(path.c_str(), &config, &decoder);
|
|
15
15
|
if (result != MA_SUCCESS) {
|
|
16
16
|
NSLog(@"Failed to initialize decoder for file: %s", path.c_str());
|
|
17
|
+
|
|
18
|
+
ma_decoder_uninit(&decoder);
|
|
19
|
+
|
|
17
20
|
return nullptr;
|
|
18
21
|
}
|
|
19
22
|
|
|
20
23
|
ma_uint64 totalFrameCount;
|
|
21
24
|
ma_decoder_get_length_in_pcm_frames(&decoder, &totalFrameCount);
|
|
22
25
|
|
|
23
|
-
auto *audioBus = new AudioBus(
|
|
26
|
+
auto *audioBus = new AudioBus(static_cast<int>(totalFrameCount), 2, sampleRate_);
|
|
24
27
|
auto *buffer = new float[totalFrameCount * 2];
|
|
25
28
|
|
|
26
29
|
ma_uint64 framesDecoded;
|
|
27
30
|
ma_decoder_read_pcm_frames(&decoder, buffer, totalFrameCount, &framesDecoded);
|
|
28
31
|
if (framesDecoded == 0) {
|
|
29
32
|
NSLog(@"Failed to decode audio file: %s", path.c_str());
|
|
33
|
+
|
|
34
|
+
delete[] buffer;
|
|
35
|
+
delete audioBus;
|
|
36
|
+
ma_decoder_uninit(&decoder);
|
|
37
|
+
|
|
38
|
+
return nullptr;
|
|
30
39
|
}
|
|
31
40
|
|
|
32
41
|
for (int i = 0; i < decoder.outputChannels; ++i) {
|
package/ios/core/AudioPlayer.m
CHANGED
|
@@ -10,23 +10,13 @@
|
|
|
10
10
|
self.audioEngine.mainMixerNode.outputVolume = 1;
|
|
11
11
|
|
|
12
12
|
self.audioSession = AVAudioSession.sharedInstance;
|
|
13
|
-
NSError *error = nil;
|
|
14
13
|
|
|
15
14
|
// TODO:
|
|
16
15
|
// We will probably want to change it to AVAudioSessionCategoryPlayAndRecord in the future.
|
|
17
16
|
// Eventually we to make this a dynamic setting, if user of the lib wants to use recording features.
|
|
18
17
|
// But setting a recording category might require some setup first, so lets skip it for now :)
|
|
19
|
-
[self.audioSession setCategory:AVAudioSessionCategoryPlayback error:&error];
|
|
20
|
-
|
|
21
|
-
if (error != nil) {
|
|
22
|
-
@throw error;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
[self.audioSession setActive:true error:&error];
|
|
26
|
-
|
|
27
|
-
if (error != nil) {
|
|
28
|
-
@throw error;
|
|
29
|
-
}
|
|
18
|
+
// [self.audioSession setCategory:AVAudioSessionCategoryPlayback error:&error];
|
|
19
|
+
// [self.audioSession setActive:true error:&error];
|
|
30
20
|
|
|
31
21
|
self.sampleRate = [self.audioSession sampleRate];
|
|
32
22
|
|
|
@@ -57,23 +47,13 @@
|
|
|
57
47
|
self.audioEngine.mainMixerNode.outputVolume = 1;
|
|
58
48
|
|
|
59
49
|
self.audioSession = AVAudioSession.sharedInstance;
|
|
60
|
-
NSError *error = nil;
|
|
61
50
|
|
|
62
51
|
// TODO:
|
|
63
52
|
// We will probably want to change it to AVAudioSessionCategoryPlayAndRecord in the future.
|
|
64
53
|
// Eventually we to make this a dynamic setting, if user of the lib wants to use recording features.
|
|
65
54
|
// But setting a recording category might require some setup first, so lets skip it for now :)
|
|
66
|
-
[self.audioSession setCategory:AVAudioSessionCategoryPlayback error:&error];
|
|
67
|
-
|
|
68
|
-
if (error != nil) {
|
|
69
|
-
@throw error;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
[self.audioSession setActive:true error:&error];
|
|
73
|
-
|
|
74
|
-
if (error != nil) {
|
|
75
|
-
@throw error;
|
|
76
|
-
}
|
|
55
|
+
// [self.audioSession setCategory:AVAudioSessionCategoryPlayback error:&error];
|
|
56
|
+
// [self.audioSession setActive:true error:&error];
|
|
77
57
|
|
|
78
58
|
self.sampleRate = sampleRate;
|
|
79
59
|
|
|
@@ -10,7 +10,7 @@ namespace audioapi {
|
|
|
10
10
|
IOSAudioPlayer::IOSAudioPlayer(const std::function<void(AudioBus *, int)> &renderAudio)
|
|
11
11
|
: renderAudio_(renderAudio), audioBus_(0)
|
|
12
12
|
{
|
|
13
|
-
audioBus_ = new AudioBus(
|
|
13
|
+
audioBus_ = new AudioBus(RENDER_QUANTUM_SIZE, CHANNEL_COUNT, getSampleRate());
|
|
14
14
|
|
|
15
15
|
RenderAudioBlock renderAudioBlock = ^(AudioBufferList *outputData, int numFrames) {
|
|
16
16
|
int processedFrames = 0;
|
|
@@ -34,7 +34,7 @@ IOSAudioPlayer::IOSAudioPlayer(const std::function<void(AudioBus *, int)> &rende
|
|
|
34
34
|
};
|
|
35
35
|
|
|
36
36
|
audioPlayer_ = [[AudioPlayer alloc] initWithRenderAudioBlock:renderAudioBlock];
|
|
37
|
-
audioBus_ = new AudioBus([audioPlayer_ getSampleRate]
|
|
37
|
+
audioBus_ = new AudioBus(RENDER_QUANTUM_SIZE, CHANNEL_COUNT, [audioPlayer_ getSampleRate]);
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
IOSAudioPlayer::IOSAudioPlayer(const std::function<void(AudioBus *, int)> &renderAudio, float sampleRate)
|
|
@@ -62,7 +62,7 @@ IOSAudioPlayer::IOSAudioPlayer(const std::function<void(AudioBus *, int)> &rende
|
|
|
62
62
|
};
|
|
63
63
|
|
|
64
64
|
audioPlayer_ = [[AudioPlayer alloc] initWithRenderAudioBlock:renderAudioBlock sampleRate:sampleRate];
|
|
65
|
-
audioBus_ = new AudioBus([audioPlayer_ getSampleRate]
|
|
65
|
+
audioBus_ = new AudioBus(RENDER_QUANTUM_SIZE, CHANNEL_COUNT, [audioPlayer_ getSampleRate]);
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
IOSAudioPlayer::~IOSAudioPlayer()
|
|
@@ -47,10 +47,10 @@ export default class AudioBufferSourceNode extends AudioScheduledSourceNode {
|
|
|
47
47
|
throw new RangeError(`when must be a finite non-negative number: ${when}`);
|
|
48
48
|
}
|
|
49
49
|
if (offset < 0) {
|
|
50
|
-
throw new RangeError(`offset must be a finite non-negative number: ${
|
|
50
|
+
throw new RangeError(`offset must be a finite non-negative number: ${offset}`);
|
|
51
51
|
}
|
|
52
52
|
if (duration && duration < 0) {
|
|
53
|
-
throw new RangeError(`duration must be a finite non-negative number: ${
|
|
53
|
+
throw new RangeError(`duration must be a finite non-negative number: ${duration}`);
|
|
54
54
|
}
|
|
55
55
|
if (this.hasBeenStarted) {
|
|
56
56
|
throw new InvalidStateError('Cannot call start more than once');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["AudioScheduledSourceNode","AudioBuffer","AudioParam","InvalidStateError","RangeError","AudioBufferSourceNode","constructor","context","node","detune","playbackRate","buffer","loop","value","loopStart","loopEnd","start","when","offset","duration","hasBeenStarted"],"sourceRoot":"../../../src","sources":["core/AudioBufferSourceNode.ts"],"mappings":";;AACA,OAAOA,wBAAwB,MAAM,+BAA4B;AAEjE,OAAOC,WAAW,MAAM,kBAAe;AACvC,OAAOC,UAAU,MAAM,iBAAc;AACrC,SAASC,iBAAiB,EAAEC,UAAU,QAAQ,oBAAW;AAEzD,eAAe,MAAMC,qBAAqB,SAASL,wBAAwB,CAAC;EAI1EM,WAAWA,CAACC,OAAyB,EAAEC,IAA4B,EAAE;IACnE,KAAK,CAACD,OAAO,EAAEC,IAAI,CAAC;IAEpB,IAAI,CAACC,MAAM,GAAG,IAAIP,UAAU,CAACM,IAAI,CAACC,MAAM,CAAC;IACzC,IAAI,CAACC,YAAY,GAAG,IAAIR,UAAU,CAACM,IAAI,CAACE,YAAY,CAAC;EACvD;EAEA,IAAWC,MAAMA,CAAA,EAAuB;IACtC,MAAMA,MAAM,GAAI,IAAI,CAACH,IAAI,CAA4BG,MAAM;IAC3D,IAAI,CAACA,MAAM,EAAE;MACX,OAAO,IAAI;IACb;IACA,OAAO,IAAIV,WAAW,CAACU,MAAM,CAAC;EAChC;EAEA,IAAWA,MAAMA,CAACA,MAA0B,EAAE;IAC5C,IAAI,CAACA,MAAM,EAAE;MACV,IAAI,CAACH,IAAI,CAA4BG,MAAM,GAAG,IAAI;MACnD;IACF;IAEC,IAAI,CAACH,IAAI,CAA4BG,MAAM,GAAGA,MAAM,CAACA,MAAM;EAC9D;EAEA,IAAWC,IAAIA,CAAA,EAAY;IACzB,OAAQ,IAAI,CAACJ,IAAI,CAA4BI,IAAI;EACnD;EAEA,IAAWA,IAAIA,CAACC,KAAc,EAAE;IAC7B,IAAI,CAACL,IAAI,CAA4BI,IAAI,GAAGC,KAAK;EACpD;EAEA,IAAWC,SAASA,CAAA,EAAW;IAC7B,OAAQ,IAAI,CAACN,IAAI,CAA4BM,SAAS;EACxD;EAEA,IAAWA,SAASA,CAACD,KAAa,EAAE;IACjC,IAAI,CAACL,IAAI,CAA4BM,SAAS,GAAGD,KAAK;EACzD;EAEA,IAAWE,OAAOA,CAAA,EAAW;IAC3B,OAAQ,IAAI,CAACP,IAAI,CAA4BO,OAAO;EACtD;EAEA,IAAWA,OAAOA,CAACF,KAAa,EAAE;IAC/B,IAAI,CAACL,IAAI,CAA4BO,OAAO,GAAGF,KAAK;EACvD;EAEOG,KAAKA,CAACC,IAAY,GAAG,CAAC,EAAEC,MAAc,GAAG,CAAC,EAAEC,QAAiB,EAAQ;IAC1E,IAAIF,IAAI,GAAG,CAAC,EAAE;MACZ,MAAM,IAAIb,UAAU,CAClB,8CAA8Ca,IAAI,EACpD,CAAC;IACH;IAEA,IAAIC,MAAM,GAAG,CAAC,EAAE;MACd,MAAM,IAAId,UAAU,CAClB,
|
|
1
|
+
{"version":3,"names":["AudioScheduledSourceNode","AudioBuffer","AudioParam","InvalidStateError","RangeError","AudioBufferSourceNode","constructor","context","node","detune","playbackRate","buffer","loop","value","loopStart","loopEnd","start","when","offset","duration","hasBeenStarted"],"sourceRoot":"../../../src","sources":["core/AudioBufferSourceNode.ts"],"mappings":";;AACA,OAAOA,wBAAwB,MAAM,+BAA4B;AAEjE,OAAOC,WAAW,MAAM,kBAAe;AACvC,OAAOC,UAAU,MAAM,iBAAc;AACrC,SAASC,iBAAiB,EAAEC,UAAU,QAAQ,oBAAW;AAEzD,eAAe,MAAMC,qBAAqB,SAASL,wBAAwB,CAAC;EAI1EM,WAAWA,CAACC,OAAyB,EAAEC,IAA4B,EAAE;IACnE,KAAK,CAACD,OAAO,EAAEC,IAAI,CAAC;IAEpB,IAAI,CAACC,MAAM,GAAG,IAAIP,UAAU,CAACM,IAAI,CAACC,MAAM,CAAC;IACzC,IAAI,CAACC,YAAY,GAAG,IAAIR,UAAU,CAACM,IAAI,CAACE,YAAY,CAAC;EACvD;EAEA,IAAWC,MAAMA,CAAA,EAAuB;IACtC,MAAMA,MAAM,GAAI,IAAI,CAACH,IAAI,CAA4BG,MAAM;IAC3D,IAAI,CAACA,MAAM,EAAE;MACX,OAAO,IAAI;IACb;IACA,OAAO,IAAIV,WAAW,CAACU,MAAM,CAAC;EAChC;EAEA,IAAWA,MAAMA,CAACA,MAA0B,EAAE;IAC5C,IAAI,CAACA,MAAM,EAAE;MACV,IAAI,CAACH,IAAI,CAA4BG,MAAM,GAAG,IAAI;MACnD;IACF;IAEC,IAAI,CAACH,IAAI,CAA4BG,MAAM,GAAGA,MAAM,CAACA,MAAM;EAC9D;EAEA,IAAWC,IAAIA,CAAA,EAAY;IACzB,OAAQ,IAAI,CAACJ,IAAI,CAA4BI,IAAI;EACnD;EAEA,IAAWA,IAAIA,CAACC,KAAc,EAAE;IAC7B,IAAI,CAACL,IAAI,CAA4BI,IAAI,GAAGC,KAAK;EACpD;EAEA,IAAWC,SAASA,CAAA,EAAW;IAC7B,OAAQ,IAAI,CAACN,IAAI,CAA4BM,SAAS;EACxD;EAEA,IAAWA,SAASA,CAACD,KAAa,EAAE;IACjC,IAAI,CAACL,IAAI,CAA4BM,SAAS,GAAGD,KAAK;EACzD;EAEA,IAAWE,OAAOA,CAAA,EAAW;IAC3B,OAAQ,IAAI,CAACP,IAAI,CAA4BO,OAAO;EACtD;EAEA,IAAWA,OAAOA,CAACF,KAAa,EAAE;IAC/B,IAAI,CAACL,IAAI,CAA4BO,OAAO,GAAGF,KAAK;EACvD;EAEOG,KAAKA,CAACC,IAAY,GAAG,CAAC,EAAEC,MAAc,GAAG,CAAC,EAAEC,QAAiB,EAAQ;IAC1E,IAAIF,IAAI,GAAG,CAAC,EAAE;MACZ,MAAM,IAAIb,UAAU,CAClB,8CAA8Ca,IAAI,EACpD,CAAC;IACH;IAEA,IAAIC,MAAM,GAAG,CAAC,EAAE;MACd,MAAM,IAAId,UAAU,CAClB,gDAAgDc,MAAM,EACxD,CAAC;IACH;IAEA,IAAIC,QAAQ,IAAIA,QAAQ,GAAG,CAAC,EAAE;MAC5B,MAAM,IAAIf,UAAU,CAClB,kDAAkDe,QAAQ,EAC5D,CAAC;IACH;IAEA,IAAI,IAAI,CAACC,cAAc,EAAE;MACvB,MAAM,IAAIjB,iBAAiB,CAAC,kCAAkC,CAAC;IACjE;IAEA,IAAI,CAACiB,cAAc,GAAG,IAAI;IACzB,IAAI,CAACZ,IAAI,CAA4BQ,KAAK,CAACC,IAAI,EAAEC,MAAM,EAAEC,QAAQ,CAAC;EACrE;AACF","ignoreList":[]}
|