react-native-audio-api 0.4.12-beta.4 → 0.4.12
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/audioapi/CMakeLists.txt +2 -3
- package/android/src/main/cpp/audioapi/android/core/AudioDecoder.cpp +3 -3
- package/android/src/main/cpp/audioapi/android/core/AudioPlayer.cpp +10 -11
- package/android/src/main/cpp/audioapi/android/core/AudioPlayer.h +1 -0
- package/android/src/main/java/com/swmansion/audioapi/AudioAPIPackage.kt +0 -1
- package/common/cpp/audioapi/AudioAPIModuleInstaller.h +1 -3
- package/common/cpp/audioapi/HostObjects/AnalyserNodeHostObject.h +24 -16
- package/common/cpp/audioapi/HostObjects/AudioBufferHostObject.h +4 -0
- package/common/cpp/audioapi/HostObjects/AudioBufferSourceNodeHostObject.h +20 -4
- package/common/cpp/audioapi/HostObjects/AudioContextHostObject.h +3 -2
- package/common/cpp/audioapi/HostObjects/AudioScheduledSourceNodeHostObject.h +32 -2
- package/common/cpp/audioapi/HostObjects/BaseAudioContextHostObject.h +14 -21
- package/common/cpp/audioapi/HostObjects/OscillatorNodeHostObject.h +4 -2
- package/common/cpp/audioapi/core/AudioNode.cpp +2 -2
- package/common/cpp/audioapi/core/AudioParam.cpp +1 -1
- package/common/cpp/audioapi/core/BaseAudioContext.cpp +4 -12
- package/common/cpp/audioapi/core/BaseAudioContext.h +2 -4
- package/common/cpp/audioapi/core/Constants.h +8 -33
- package/common/cpp/audioapi/core/analysis/AnalyserNode.cpp +42 -45
- package/common/cpp/audioapi/core/analysis/AnalyserNode.h +8 -6
- package/common/cpp/audioapi/core/destinations/AudioDestinationNode.cpp +1 -1
- package/common/cpp/audioapi/core/effects/BiquadFilterNode.cpp +12 -8
- package/common/cpp/audioapi/core/effects/GainNode.cpp +4 -3
- package/common/cpp/audioapi/core/effects/PeriodicWave.cpp +32 -49
- package/common/cpp/audioapi/core/effects/PeriodicWave.h +8 -3
- package/common/cpp/audioapi/core/effects/StereoPannerNode.cpp +3 -3
- package/common/cpp/audioapi/core/sources/AudioBuffer.cpp +9 -2
- package/common/cpp/audioapi/core/sources/AudioBuffer.h +5 -2
- package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp +72 -35
- package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.h +41 -8
- package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.cpp +18 -6
- package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.h +7 -0
- package/common/cpp/audioapi/core/sources/OscillatorNode.cpp +12 -3
- package/common/cpp/audioapi/core/sources/OscillatorNode.h +1 -0
- package/common/cpp/audioapi/core/types/TimeStretchType.h +7 -0
- package/common/cpp/audioapi/dsp/AudioUtils.cpp +2 -2
- package/common/cpp/audioapi/dsp/AudioUtils.h +2 -2
- package/common/cpp/audioapi/dsp/FFT.cpp +41 -0
- package/common/cpp/audioapi/dsp/FFT.h +29 -0
- package/common/cpp/audioapi/dsp/VectorMath.cpp +3 -3
- package/common/cpp/audioapi/dsp/VectorMath.h +2 -2
- package/common/cpp/audioapi/dsp/Windows.cpp +80 -0
- package/common/cpp/audioapi/dsp/Windows.h +95 -0
- package/{android/src/main/cpp/audioapi/android/libs → common/cpp/audioapi/libs/pffft}/pffft.c +1 -1
- package/common/cpp/audioapi/libs/{dsp → signalsmith-stretch}/delay.h +9 -11
- package/common/cpp/audioapi/libs/{dsp → signalsmith-stretch}/fft.h +6 -7
- package/common/cpp/audioapi/libs/{dsp → signalsmith-stretch}/perf.h +0 -2
- package/common/cpp/audioapi/libs/{signalsmith-stretch.h → signalsmith-stretch/signalsmith-stretch.h} +3 -4
- package/common/cpp/audioapi/libs/{dsp → signalsmith-stretch}/spectral.h +10 -13
- package/common/cpp/audioapi/{core/utils → utils}/AudioArray.cpp +5 -5
- package/common/cpp/audioapi/{core/utils → utils}/AudioBus.cpp +29 -29
- package/ios/audioapi/ios/core/AudioDecoder.mm +3 -3
- package/ios/audioapi/ios/core/AudioPlayer.h +5 -2
- package/ios/audioapi/ios/core/AudioPlayer.m +9 -5
- package/ios/audioapi/ios/core/IOSAudioPlayer.h +1 -0
- package/ios/audioapi/ios/core/IOSAudioPlayer.mm +12 -10
- package/lib/module/api.js +30 -0
- package/lib/module/api.js.map +1 -0
- package/lib/module/{index.web.js → api.web.js} +4 -2
- package/lib/module/api.web.js.map +1 -0
- package/lib/module/core/AudioBufferSourceNode.js +6 -0
- package/lib/module/core/AudioBufferSourceNode.js.map +1 -1
- package/lib/module/core/AudioScheduledSourceNode.js +5 -0
- package/lib/module/core/AudioScheduledSourceNode.js.map +1 -1
- package/lib/module/core/BaseAudioContext.js +0 -4
- package/lib/module/core/BaseAudioContext.js.map +1 -1
- package/lib/module/index.js +1 -28
- package/lib/module/index.js.map +1 -1
- package/lib/module/web-core/AudioBuffer.js +1 -1
- package/lib/module/web-core/AudioBuffer.js.map +1 -1
- package/lib/module/web-core/AudioBufferSourceNode.js +6 -0
- package/lib/module/web-core/AudioBufferSourceNode.js.map +1 -1
- package/lib/module/web-core/AudioContext.js +7 -0
- package/lib/module/web-core/AudioContext.js.map +1 -1
- package/lib/module/web-core/AudioScheduledSourceNode.js +8 -0
- package/lib/module/web-core/AudioScheduledSourceNode.js.map +1 -1
- package/lib/module/web-core/StretcherNode.js +64 -0
- package/lib/module/web-core/StretcherNode.js.map +1 -0
- package/lib/module/web-core/custom/LoadCustomWasm.js +33 -0
- package/lib/module/web-core/custom/LoadCustomWasm.js.map +1 -0
- package/lib/module/web-core/custom/index.js +4 -0
- package/lib/module/web-core/custom/index.js.map +1 -0
- package/lib/module/web-core/custom/signalsmithStretch/LICENSE.txt +21 -0
- package/lib/module/web-core/custom/signalsmithStretch/README.md +46 -0
- package/lib/module/web-core/custom/signalsmithStretch/SignalsmithStretch.js +822 -0
- package/lib/module/web-core/custom/signalsmithStretch/SignalsmithStretch.js.map +1 -0
- package/lib/module/web-core/custom/signalsmithStretch/SignalsmithStretch.mjs +826 -0
- package/lib/module/web-core/custom/signalsmithStretch/SignalsmithStretch.mjs.map +1 -0
- package/lib/typescript/api.d.ts +20 -0
- package/lib/typescript/api.d.ts.map +1 -0
- package/lib/typescript/{index.web.d.ts → api.web.d.ts} +4 -2
- package/lib/typescript/api.web.d.ts.map +1 -0
- package/lib/typescript/core/AudioBufferSourceNode.d.ts +3 -0
- package/lib/typescript/core/AudioBufferSourceNode.d.ts.map +1 -1
- package/lib/typescript/core/AudioScheduledSourceNode.d.ts +1 -0
- package/lib/typescript/core/AudioScheduledSourceNode.d.ts.map +1 -1
- package/lib/typescript/core/BaseAudioContext.d.ts +0 -2
- package/lib/typescript/core/BaseAudioContext.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +1 -20
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/interfaces.d.ts +3 -6
- package/lib/typescript/interfaces.d.ts.map +1 -1
- package/lib/typescript/types.d.ts +1 -0
- package/lib/typescript/types.d.ts.map +1 -1
- package/lib/typescript/web-core/AudioBuffer.d.ts +1 -1
- package/lib/typescript/web-core/AudioBuffer.d.ts.map +1 -1
- package/lib/typescript/web-core/AudioBufferSourceNode.d.ts +3 -0
- package/lib/typescript/web-core/AudioBufferSourceNode.d.ts.map +1 -1
- package/lib/typescript/web-core/AudioContext.d.ts +2 -0
- package/lib/typescript/web-core/AudioContext.d.ts.map +1 -1
- package/lib/typescript/web-core/AudioScheduledSourceNode.d.ts +1 -0
- package/lib/typescript/web-core/AudioScheduledSourceNode.d.ts.map +1 -1
- package/lib/typescript/web-core/StretcherNode.d.ts +45 -0
- package/lib/typescript/web-core/StretcherNode.d.ts.map +1 -0
- package/lib/typescript/web-core/custom/LoadCustomWasm.d.ts +5 -0
- package/lib/typescript/web-core/custom/LoadCustomWasm.d.ts.map +1 -0
- package/lib/typescript/web-core/custom/index.d.ts +2 -0
- package/lib/typescript/web-core/custom/index.d.ts.map +1 -0
- package/package.json +8 -5
- package/scripts/setup-custom-wasm.js +104 -0
- package/src/api.ts +51 -0
- package/src/{index.web.ts → api.web.ts} +4 -0
- package/src/core/AudioBufferSourceNode.ts +9 -0
- package/src/core/AudioScheduledSourceNode.ts +5 -0
- package/src/core/BaseAudioContext.ts +0 -5
- package/src/index.ts +1 -51
- package/src/interfaces.ts +3 -6
- package/src/types.ts +2 -0
- package/src/web-core/AudioBuffer.tsx +2 -2
- package/src/web-core/AudioBufferSourceNode.tsx +11 -0
- package/src/web-core/AudioContext.tsx +11 -0
- package/src/web-core/AudioScheduledSourceNode.tsx +9 -0
- package/src/web-core/StretcherNode.tsx +125 -0
- package/src/web-core/custom/LoadCustomWasm.ts +39 -0
- package/src/web-core/custom/index.ts +1 -0
- package/src/web-core/custom/signalsmithStretch/LICENSE.txt +21 -0
- package/src/web-core/custom/signalsmithStretch/README.md +46 -0
- package/src/web-core/custom/signalsmithStretch/SignalsmithStretch.js +945 -0
- package/src/web-core/custom/signalsmithStretch/SignalsmithStretch.mjs +949 -0
- package/common/cpp/audioapi/HostObjects/StretcherNodeHostObject.h +0 -35
- package/common/cpp/audioapi/core/effects/StretcherNode.cpp +0 -94
- package/common/cpp/audioapi/core/effects/StretcherNode.h +0 -35
- package/common/cpp/audioapi/dsp/FFTFrame.cpp +0 -100
- package/common/cpp/audioapi/dsp/FFTFrame.h +0 -74
- package/common/cpp/audioapi/libs/dsp/common.h +0 -47
- package/common/cpp/audioapi/libs/dsp/windows.h +0 -219
- package/lib/module/core/StretcherNode.js +0 -12
- package/lib/module/core/StretcherNode.js.map +0 -1
- package/lib/module/index.web.js.map +0 -1
- package/lib/typescript/core/StretcherNode.d.ts +0 -10
- package/lib/typescript/core/StretcherNode.d.ts.map +0 -1
- package/lib/typescript/index.web.d.ts.map +0 -1
- package/src/core/StretcherNode.ts +0 -15
- /package/common/cpp/audioapi/libs/{miniaudio.h → miniaudio/miniaudio.h} +0 -0
- /package/{android/src/main/cpp/audioapi/android/libs → common/cpp/audioapi/libs/pffft}/pffft.h +0 -0
- /package/common/cpp/audioapi/{core/utils → utils}/AudioArray.h +0 -0
- /package/common/cpp/audioapi/{core/utils → utils}/AudioBus.h +0 -0
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
#include <audioapi/core/BaseAudioContext.h>
|
|
3
3
|
#include <audioapi/core/Constants.h>
|
|
4
4
|
#include <audioapi/core/sources/AudioBufferSourceNode.h>
|
|
5
|
-
#include <audioapi/core/utils/AudioArray.h>
|
|
6
|
-
#include <audioapi/core/utils/AudioBus.h>
|
|
7
5
|
#include <audioapi/core/utils/Locker.h>
|
|
8
6
|
#include <audioapi/dsp/AudioUtils.h>
|
|
7
|
+
#include <audioapi/utils/AudioArray.h>
|
|
8
|
+
#include <audioapi/utils/AudioBus.h>
|
|
9
9
|
|
|
10
10
|
namespace audioapi {
|
|
11
11
|
|
|
@@ -14,15 +14,18 @@ AudioBufferSourceNode::AudioBufferSourceNode(BaseAudioContext *context)
|
|
|
14
14
|
loop_(false),
|
|
15
15
|
loopStart_(0),
|
|
16
16
|
loopEnd_(0),
|
|
17
|
+
timeStretchType_(TimeStretchType::LINEAR),
|
|
17
18
|
vReadIndex_(0.0) {
|
|
18
19
|
buffer_ = std::shared_ptr<AudioBuffer>(nullptr);
|
|
19
|
-
alignedBus_ = std::make_shared<AudioBus>(
|
|
20
|
-
RENDER_QUANTUM_SIZE, 1, context_->getSampleRate());
|
|
21
20
|
|
|
22
|
-
detuneParam_ = std::make_shared<AudioParam>(
|
|
21
|
+
detuneParam_ = std::make_shared<AudioParam>(
|
|
22
|
+
0.0, MOST_NEGATIVE_SINGLE_FLOAT, MOST_POSITIVE_SINGLE_FLOAT);
|
|
23
23
|
playbackRateParam_ = std::make_shared<AudioParam>(
|
|
24
24
|
1.0, MOST_NEGATIVE_SINGLE_FLOAT, MOST_POSITIVE_SINGLE_FLOAT);
|
|
25
25
|
|
|
26
|
+
playbackRateBus_ = std::make_shared<AudioBus>(
|
|
27
|
+
RENDER_QUANTUM_SIZE * 3, channelCount_, context_->getSampleRate());
|
|
28
|
+
|
|
26
29
|
isInitialized_ = true;
|
|
27
30
|
}
|
|
28
31
|
|
|
@@ -51,6 +54,10 @@ std::shared_ptr<AudioBuffer> AudioBufferSourceNode::getBuffer() const {
|
|
|
51
54
|
return buffer_;
|
|
52
55
|
}
|
|
53
56
|
|
|
57
|
+
std::string AudioBufferSourceNode::getTimeStretchType() const {
|
|
58
|
+
return toString(timeStretchType_);
|
|
59
|
+
}
|
|
60
|
+
|
|
54
61
|
void AudioBufferSourceNode::setLoop(bool loop) {
|
|
55
62
|
loop_ = loop;
|
|
56
63
|
}
|
|
@@ -69,8 +76,6 @@ void AudioBufferSourceNode::setBuffer(
|
|
|
69
76
|
|
|
70
77
|
if (!buffer) {
|
|
71
78
|
buffer_ = std::shared_ptr<AudioBuffer>(nullptr);
|
|
72
|
-
alignedBus_ = std::make_shared<AudioBus>(
|
|
73
|
-
RENDER_QUANTUM_SIZE, 1, context_->getSampleRate());
|
|
74
79
|
loopEnd_ = 0;
|
|
75
80
|
return;
|
|
76
81
|
}
|
|
@@ -78,17 +83,18 @@ void AudioBufferSourceNode::setBuffer(
|
|
|
78
83
|
buffer_ = buffer;
|
|
79
84
|
channelCount_ = buffer_->getNumberOfChannels();
|
|
80
85
|
|
|
81
|
-
alignedBus_ = std::make_shared<AudioBus>(
|
|
82
|
-
buffer_->getLength(), channelCount_, context_->getSampleRate());
|
|
83
|
-
alignedBus_->zero();
|
|
84
|
-
alignedBus_->sum(buffer_->bus_.get());
|
|
85
|
-
|
|
86
86
|
audioBus_ = std::make_shared<AudioBus>(
|
|
87
87
|
RENDER_QUANTUM_SIZE, channelCount_, context_->getSampleRate());
|
|
88
|
+
playbackRateBus_ = std::make_shared<AudioBus>(
|
|
89
|
+
RENDER_QUANTUM_SIZE * 3, channelCount_, context_->getSampleRate());
|
|
88
90
|
|
|
89
91
|
loopEnd_ = buffer_->getDuration();
|
|
90
92
|
}
|
|
91
93
|
|
|
94
|
+
void AudioBufferSourceNode::setTimeStretchType(const std::string &type) {
|
|
95
|
+
timeStretchType_ = fromString(type);
|
|
96
|
+
}
|
|
97
|
+
|
|
92
98
|
void AudioBufferSourceNode::start(double when, double offset, double duration) {
|
|
93
99
|
AudioScheduledSourceNode::start(when);
|
|
94
100
|
|
|
@@ -117,7 +123,7 @@ void AudioBufferSourceNode::processNode(
|
|
|
117
123
|
const std::shared_ptr<AudioBus> &processingBus,
|
|
118
124
|
int framesToProcess) {
|
|
119
125
|
// No audio data to fill, zero the output and return.
|
|
120
|
-
if (!buffer_) {
|
|
126
|
+
if (!buffer_ || !buffer_->bus_) {
|
|
121
127
|
processingBus->zero();
|
|
122
128
|
return;
|
|
123
129
|
}
|
|
@@ -130,26 +136,58 @@ void AudioBufferSourceNode::processNode(
|
|
|
130
136
|
size_t startOffset = 0;
|
|
131
137
|
size_t offsetLength = 0;
|
|
132
138
|
|
|
133
|
-
|
|
134
|
-
|
|
139
|
+
if (timeStretchType_ == TimeStretchType::LINEAR) {
|
|
140
|
+
auto computedPlaybackRate = getComputedPlaybackRateValue();
|
|
141
|
+
updatePlaybackInfo(
|
|
142
|
+
processingBus, framesToProcess, startOffset, offsetLength);
|
|
143
|
+
|
|
144
|
+
if (computedPlaybackRate == 0.0f || !isPlaying()) {
|
|
145
|
+
processingBus->zero();
|
|
146
|
+
return;
|
|
147
|
+
} else if (std::fabs(computedPlaybackRate) == 1.0) {
|
|
148
|
+
processWithoutInterpolation(
|
|
149
|
+
processingBus, startOffset, offsetLength, computedPlaybackRate);
|
|
150
|
+
} else {
|
|
151
|
+
processWithInterpolation(
|
|
152
|
+
processingBus, startOffset, offsetLength, computedPlaybackRate);
|
|
153
|
+
}
|
|
154
|
+
} else {
|
|
155
|
+
auto time = context_->getCurrentTime();
|
|
156
|
+
auto playbackRate =
|
|
157
|
+
std::clamp(playbackRateParam_->getValueAtTime(time), 0.0f, 3.0f);
|
|
158
|
+
auto detune =
|
|
159
|
+
std::clamp(detuneParam_->getValueAtTime(time) / 100.0f, -12.0f, 12.0f);
|
|
135
160
|
|
|
136
|
-
|
|
137
|
-
|
|
161
|
+
playbackRateBus_->zero();
|
|
162
|
+
|
|
163
|
+
auto framesNeededToStretch =
|
|
164
|
+
static_cast<int>(playbackRate * static_cast<float>(framesToProcess));
|
|
165
|
+
|
|
166
|
+
updatePlaybackInfo(
|
|
167
|
+
playbackRateBus_, framesNeededToStretch, startOffset, offsetLength);
|
|
138
168
|
|
|
139
|
-
if (playbackRate == 0.0f || !isPlaying()) {
|
|
140
|
-
processingBus->zero();
|
|
141
|
-
return;
|
|
142
|
-
} else if (std::fabs(playbackRate) == 1.0) {
|
|
143
169
|
processWithoutInterpolation(
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
170
|
+
playbackRateBus_, startOffset, offsetLength, playbackRate);
|
|
171
|
+
|
|
172
|
+
auto stretch = buffer_->stretch_;
|
|
173
|
+
|
|
174
|
+
stretch->process(
|
|
175
|
+
playbackRateBus_.get()[0],
|
|
176
|
+
framesNeededToStretch,
|
|
177
|
+
processingBus.get()[0],
|
|
178
|
+
framesToProcess);
|
|
179
|
+
|
|
180
|
+
stretch->setTransposeSemitones(detune);
|
|
148
181
|
}
|
|
149
182
|
|
|
150
183
|
handleStopScheduled();
|
|
151
184
|
}
|
|
152
185
|
|
|
186
|
+
double AudioBufferSourceNode::getStopTime() const {
|
|
187
|
+
return dsp::sampleFrameToTime(
|
|
188
|
+
static_cast<int>(vReadIndex_), buffer_->getSampleRate());
|
|
189
|
+
}
|
|
190
|
+
|
|
153
191
|
/**
|
|
154
192
|
* Helper functions
|
|
155
193
|
*/
|
|
@@ -182,12 +220,12 @@ void AudioBufferSourceNode::processWithoutInterpolation(
|
|
|
182
220
|
// Direction is forward, we can normally copy the data
|
|
183
221
|
if (direction == 1) {
|
|
184
222
|
processingBus->copy(
|
|
185
|
-
|
|
223
|
+
buffer_->bus_.get(), readIndex, writeIndex, framesToCopy);
|
|
186
224
|
} else {
|
|
187
225
|
for (int i = 0; i < framesToCopy; i += 1) {
|
|
188
226
|
for (int j = 0; j < processingBus->getNumberOfChannels(); j += 1) {
|
|
189
227
|
(*processingBus->getChannel(j))[writeIndex + i] =
|
|
190
|
-
(*
|
|
228
|
+
(*buffer_->bus_->getChannel(j))[readIndex - i];
|
|
191
229
|
}
|
|
192
230
|
}
|
|
193
231
|
}
|
|
@@ -248,10 +286,10 @@ void AudioBufferSourceNode::processWithInterpolation(
|
|
|
248
286
|
|
|
249
287
|
for (int i = 0; i < processingBus->getNumberOfChannels(); i += 1) {
|
|
250
288
|
float *destination = processingBus->getChannel(i)->getData();
|
|
251
|
-
const float *source =
|
|
289
|
+
const float *source = buffer_->bus_->getChannel(i)->getData();
|
|
252
290
|
|
|
253
|
-
destination[writeIndex] =
|
|
254
|
-
source, readIndex, nextReadIndex, factor);
|
|
291
|
+
destination[writeIndex] =
|
|
292
|
+
dsp::linearInterpolate(source, readIndex, nextReadIndex, factor);
|
|
255
293
|
}
|
|
256
294
|
|
|
257
295
|
writeIndex += 1;
|
|
@@ -271,13 +309,12 @@ void AudioBufferSourceNode::processWithInterpolation(
|
|
|
271
309
|
}
|
|
272
310
|
}
|
|
273
311
|
|
|
274
|
-
float AudioBufferSourceNode::
|
|
275
|
-
auto time = context_->getCurrentTime()
|
|
276
|
-
static_cast<double>(startOffset) / context_->getSampleRate();
|
|
312
|
+
float AudioBufferSourceNode::getComputedPlaybackRateValue() {
|
|
313
|
+
auto time = context_->getCurrentTime();
|
|
277
314
|
|
|
278
315
|
auto sampleRateFactor = buffer_->getSampleRate() / context_->getSampleRate();
|
|
279
|
-
auto detune = std::pow(2.0f, detuneParam_->getValueAtTime(time) / 1200.0f);
|
|
280
316
|
auto playbackRate = playbackRateParam_->getValueAtTime(time);
|
|
317
|
+
auto detune = std::pow(2.0f, detuneParam_->getValueAtTime(time) / 1200.0f);
|
|
281
318
|
|
|
282
319
|
return playbackRate * sampleRateFactor * detune;
|
|
283
320
|
}
|
|
@@ -290,7 +327,7 @@ double AudioBufferSourceNode::getVirtualStartFrame() {
|
|
|
290
327
|
}
|
|
291
328
|
|
|
292
329
|
double AudioBufferSourceNode::getVirtualEndFrame() {
|
|
293
|
-
auto inputBufferLength = static_cast<double>(
|
|
330
|
+
auto inputBufferLength = static_cast<double>(buffer_->bus_->getSize());
|
|
294
331
|
auto loopEndFrame = loopEnd_ * context_->getSampleRate();
|
|
295
332
|
|
|
296
333
|
return loop_ && loopEndFrame > 0 && loopStart_ < loopEnd_
|
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
#include <audioapi/core/sources/AudioBuffer.h>
|
|
4
4
|
#include <audioapi/core/sources/AudioScheduledSourceNode.h>
|
|
5
|
+
#include <audioapi/core/types/TimeStretchType.h>
|
|
5
6
|
|
|
6
7
|
#include <memory>
|
|
7
8
|
#include <cstddef>
|
|
8
9
|
#include <algorithm>
|
|
9
|
-
#include <
|
|
10
|
+
#include <string>
|
|
10
11
|
|
|
11
12
|
namespace audioapi {
|
|
12
13
|
|
|
@@ -22,41 +23,68 @@ class AudioBufferSourceNode : public AudioScheduledSourceNode {
|
|
|
22
23
|
[[nodiscard]] double getLoopEnd() const;
|
|
23
24
|
[[nodiscard]] std::shared_ptr<AudioParam> getDetuneParam() const;
|
|
24
25
|
[[nodiscard]] std::shared_ptr<AudioParam> getPlaybackRateParam() const;
|
|
26
|
+
[[nodiscard]] std::shared_ptr<AudioParam> getSemitonesParam() const;
|
|
25
27
|
[[nodiscard]] std::shared_ptr<AudioBuffer> getBuffer() const;
|
|
28
|
+
[[nodiscard]] std::string getTimeStretchType() const;
|
|
26
29
|
|
|
27
30
|
void setLoop(bool loop);
|
|
28
31
|
void setLoopStart(double loopStart);
|
|
29
32
|
void setLoopEnd(double loopEnd);
|
|
30
33
|
void setBuffer(const std::shared_ptr<AudioBuffer> &buffer);
|
|
34
|
+
void setTimeStretchType(const std::string &type);
|
|
31
35
|
|
|
32
36
|
void start(double when, double offset, double duration = -1);
|
|
33
37
|
|
|
34
38
|
protected:
|
|
35
39
|
std::mutex &getBufferLock();
|
|
36
40
|
void processNode(const std::shared_ptr<AudioBus>& processingBus, int framesToProcess) override;
|
|
41
|
+
double getStopTime() const override;
|
|
37
42
|
|
|
38
43
|
private:
|
|
44
|
+
static TimeStretchType fromString(const std::string &type) {
|
|
45
|
+
std::string lowerType = type;
|
|
46
|
+
std::transform(
|
|
47
|
+
lowerType.begin(), lowerType.end(), lowerType.begin(), ::tolower);
|
|
48
|
+
|
|
49
|
+
if (lowerType == "linear")
|
|
50
|
+
return TimeStretchType::LINEAR;
|
|
51
|
+
if (lowerType == "speech-music")
|
|
52
|
+
return TimeStretchType::SPEECH_MUSIC;
|
|
53
|
+
|
|
54
|
+
throw std::invalid_argument("Unknown time stretch type: " + type);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
static std::string toString(TimeStretchType type) {
|
|
58
|
+
switch (type) {
|
|
59
|
+
case TimeStretchType::LINEAR:
|
|
60
|
+
return "linear";
|
|
61
|
+
case TimeStretchType::SPEECH_MUSIC:
|
|
62
|
+
return "speech-music";
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
throw std::invalid_argument("Unknown time stretch type");
|
|
66
|
+
}
|
|
67
|
+
|
|
39
68
|
// Looping related properties
|
|
40
69
|
bool loop_;
|
|
41
70
|
double loopStart_;
|
|
42
71
|
double loopEnd_;
|
|
43
72
|
std::mutex bufferLock_;
|
|
44
73
|
|
|
45
|
-
//
|
|
74
|
+
// time-stretching and pitch-shifting
|
|
75
|
+
TimeStretchType timeStretchType_;
|
|
76
|
+
|
|
77
|
+
// k-rate params
|
|
46
78
|
std::shared_ptr<AudioParam> detuneParam_;
|
|
47
79
|
std::shared_ptr<AudioParam> playbackRateParam_;
|
|
48
80
|
|
|
81
|
+
std::shared_ptr<AudioBus> playbackRateBus_;
|
|
82
|
+
|
|
49
83
|
// internal helper
|
|
50
84
|
double vReadIndex_;
|
|
51
85
|
|
|
52
86
|
// User provided buffer
|
|
53
87
|
std::shared_ptr<AudioBuffer> buffer_;
|
|
54
|
-
std::shared_ptr<AudioBus> alignedBus_;
|
|
55
|
-
|
|
56
|
-
float getPlaybackRateValue(size_t &startOffset);
|
|
57
|
-
|
|
58
|
-
double getVirtualStartFrame();
|
|
59
|
-
double getVirtualEndFrame();
|
|
60
88
|
|
|
61
89
|
void processWithoutInterpolation(
|
|
62
90
|
const std::shared_ptr<AudioBus>& processingBus,
|
|
@@ -69,6 +97,11 @@ class AudioBufferSourceNode : public AudioScheduledSourceNode {
|
|
|
69
97
|
size_t startOffset,
|
|
70
98
|
size_t offsetLength,
|
|
71
99
|
float playbackRate);
|
|
100
|
+
|
|
101
|
+
float getComputedPlaybackRateValue();
|
|
102
|
+
|
|
103
|
+
double getVirtualStartFrame();
|
|
104
|
+
double getVirtualEndFrame();
|
|
72
105
|
};
|
|
73
106
|
|
|
74
107
|
} // namespace audioapi
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#include <audioapi/core/BaseAudioContext.h>
|
|
2
2
|
#include <audioapi/core/sources/AudioScheduledSourceNode.h>
|
|
3
|
-
#include <audioapi/core/utils/AudioArray.h>
|
|
4
|
-
#include <audioapi/core/utils/AudioBus.h>
|
|
5
3
|
#include <audioapi/core/utils/AudioNodeManager.h>
|
|
6
4
|
#include <audioapi/dsp/AudioUtils.h>
|
|
5
|
+
#include <audioapi/utils/AudioArray.h>
|
|
6
|
+
#include <audioapi/utils/AudioBus.h>
|
|
7
7
|
|
|
8
8
|
namespace audioapi {
|
|
9
9
|
|
|
@@ -40,6 +40,11 @@ bool AudioScheduledSourceNode::isFinished() {
|
|
|
40
40
|
return playbackState_ == PlaybackState::FINISHED;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
void AudioScheduledSourceNode::setOnendedCallback(
|
|
44
|
+
const std::function<void(double)> &onendedCallback) {
|
|
45
|
+
onendedCallback_ = onendedCallback;
|
|
46
|
+
}
|
|
47
|
+
|
|
43
48
|
void AudioScheduledSourceNode::updatePlaybackInfo(
|
|
44
49
|
const std::shared_ptr<AudioBus> &processingBus,
|
|
45
50
|
int framesToProcess,
|
|
@@ -58,12 +63,11 @@ void AudioScheduledSourceNode::updatePlaybackInfo(
|
|
|
58
63
|
size_t firstFrame = context_->getCurrentSampleFrame();
|
|
59
64
|
size_t lastFrame = firstFrame + framesToProcess;
|
|
60
65
|
|
|
61
|
-
size_t startFrame =
|
|
62
|
-
|
|
66
|
+
size_t startFrame =
|
|
67
|
+
std::max(dsp::timeToSampleFrame(startTime_, sampleRate), firstFrame);
|
|
63
68
|
size_t stopFrame = stopTime_ == -1.0
|
|
64
69
|
? std::numeric_limits<size_t>::max()
|
|
65
|
-
: std::max(
|
|
66
|
-
AudioUtils::timeToSampleFrame(stopTime_, sampleRate), firstFrame);
|
|
70
|
+
: std::max(dsp::timeToSampleFrame(stopTime_, sampleRate), firstFrame);
|
|
67
71
|
|
|
68
72
|
if (isUnscheduled() || isFinished()) {
|
|
69
73
|
startOffset = 0;
|
|
@@ -105,6 +109,11 @@ void AudioScheduledSourceNode::updatePlaybackInfo(
|
|
|
105
109
|
if (stopFrame < firstFrame) {
|
|
106
110
|
startOffset = 0;
|
|
107
111
|
nonSilentFramesToProcess = 0;
|
|
112
|
+
|
|
113
|
+
if (onendedCallback_) {
|
|
114
|
+
onendedCallback_(getStopTime());
|
|
115
|
+
}
|
|
116
|
+
|
|
108
117
|
playbackState_ = PlaybackState::FINISHED;
|
|
109
118
|
disable();
|
|
110
119
|
return;
|
|
@@ -117,6 +126,9 @@ void AudioScheduledSourceNode::updatePlaybackInfo(
|
|
|
117
126
|
|
|
118
127
|
void AudioScheduledSourceNode::handleStopScheduled() {
|
|
119
128
|
if (isPlaying() && stopTime_ > 0 && context_->getCurrentTime() >= stopTime_) {
|
|
129
|
+
if (onendedCallback_) {
|
|
130
|
+
onendedCallback_(getStopTime());
|
|
131
|
+
}
|
|
120
132
|
playbackState_ = PlaybackState::FINISHED;
|
|
121
133
|
disable();
|
|
122
134
|
}
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
#include <thread>
|
|
13
13
|
#include <cstddef>
|
|
14
14
|
#include <cassert>
|
|
15
|
+
#include <utility>
|
|
15
16
|
|
|
16
17
|
namespace audioapi {
|
|
17
18
|
|
|
@@ -28,6 +29,10 @@ class AudioScheduledSourceNode : public AudioNode {
|
|
|
28
29
|
bool isPlaying();
|
|
29
30
|
bool isFinished();
|
|
30
31
|
|
|
32
|
+
void setOnendedCallback(const std::function<void(double)> &onendedCallback);
|
|
33
|
+
|
|
34
|
+
virtual double getStopTime() const = 0;
|
|
35
|
+
|
|
31
36
|
protected:
|
|
32
37
|
PlaybackState playbackState_;
|
|
33
38
|
|
|
@@ -42,6 +47,8 @@ class AudioScheduledSourceNode : public AudioNode {
|
|
|
42
47
|
private:
|
|
43
48
|
double startTime_;
|
|
44
49
|
double stopTime_;
|
|
50
|
+
|
|
51
|
+
std::function<void(double)> onendedCallback_;
|
|
45
52
|
};
|
|
46
53
|
|
|
47
54
|
} // namespace audioapi
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
#include <audioapi/core/BaseAudioContext.h>
|
|
2
2
|
#include <audioapi/core/sources/OscillatorNode.h>
|
|
3
|
-
#include <audioapi/
|
|
4
|
-
#include <audioapi/
|
|
3
|
+
#include <audioapi/dsp/AudioUtils.h>
|
|
4
|
+
#include <audioapi/utils/AudioArray.h>
|
|
5
|
+
#include <audioapi/utils/AudioBus.h>
|
|
5
6
|
|
|
6
7
|
namespace audioapi {
|
|
7
8
|
|
|
@@ -9,7 +10,10 @@ OscillatorNode::OscillatorNode(BaseAudioContext *context)
|
|
|
9
10
|
: AudioScheduledSourceNode(context) {
|
|
10
11
|
frequencyParam_ = std::make_shared<AudioParam>(
|
|
11
12
|
444.0, -context_->getNyquistFrequency(), context_->getNyquistFrequency());
|
|
12
|
-
detuneParam_ = std::make_shared<AudioParam>(
|
|
13
|
+
detuneParam_ = std::make_shared<AudioParam>(
|
|
14
|
+
0.0,
|
|
15
|
+
-1200 * LOG2_MOST_POSITIVE_SINGLE_FLOAT,
|
|
16
|
+
1200 * LOG2_MOST_POSITIVE_SINGLE_FLOAT);
|
|
13
17
|
type_ = OscillatorType::SINE;
|
|
14
18
|
periodicWave_ = context_->getBasicWaveForm(type_);
|
|
15
19
|
isInitialized_ = true;
|
|
@@ -81,4 +85,9 @@ void OscillatorNode::processNode(
|
|
|
81
85
|
handleStopScheduled();
|
|
82
86
|
}
|
|
83
87
|
|
|
88
|
+
double OscillatorNode::getStopTime() const {
|
|
89
|
+
return dsp::sampleFrameToTime(
|
|
90
|
+
static_cast<int>(phase_), context_->getSampleRate());
|
|
91
|
+
}
|
|
92
|
+
|
|
84
93
|
} // namespace audioapi
|
|
@@ -25,6 +25,7 @@ class OscillatorNode : public AudioScheduledSourceNode {
|
|
|
25
25
|
|
|
26
26
|
protected:
|
|
27
27
|
void processNode(const std::shared_ptr<AudioBus>& processingBus, int framesToProcess) override;
|
|
28
|
+
double getStopTime() const override;
|
|
28
29
|
|
|
29
30
|
private:
|
|
30
31
|
std::shared_ptr<AudioParam> frequencyParam_;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#include <audioapi/dsp/AudioUtils.h>
|
|
2
2
|
|
|
3
|
-
namespace audioapi::
|
|
3
|
+
namespace audioapi::dsp {
|
|
4
4
|
size_t timeToSampleFrame(double time, float sampleRate) {
|
|
5
5
|
return static_cast<size_t>(time * sampleRate);
|
|
6
6
|
}
|
|
@@ -30,4 +30,4 @@ float linearToDecibels(float value) {
|
|
|
30
30
|
float decibelsToLinear(float value) {
|
|
31
31
|
return powf(10, value / 20);
|
|
32
32
|
}
|
|
33
|
-
} // namespace audioapi::
|
|
33
|
+
} // namespace audioapi::dsp
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
#include <cstdint>
|
|
5
5
|
#include <cmath>
|
|
6
6
|
|
|
7
|
-
namespace audioapi::
|
|
7
|
+
namespace audioapi::dsp {
|
|
8
8
|
|
|
9
9
|
size_t timeToSampleFrame(double time, float sampleRate);
|
|
10
10
|
double sampleFrameToTime(int sampleFrame, float sampleRate);
|
|
@@ -13,4 +13,4 @@ float linearInterpolate(const float *source, size_t firstIndex, size_t secondInd
|
|
|
13
13
|
|
|
14
14
|
float linearToDecibels(float value);
|
|
15
15
|
float decibelsToLinear(float value);
|
|
16
|
-
} // namespace audioapi::
|
|
16
|
+
} // namespace audioapi::dsp
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#include <audioapi/dsp/FFT.h>
|
|
2
|
+
|
|
3
|
+
namespace audioapi::dsp {
|
|
4
|
+
|
|
5
|
+
FFT::FFT(int size) : size_(size) {
|
|
6
|
+
pffftSetup_ = pffft_new_setup(size_, PFFFT_REAL);
|
|
7
|
+
work_ = (float *)pffft_aligned_malloc(size_ * sizeof(float));
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
FFT::~FFT() {
|
|
11
|
+
pffft_destroy_setup(pffftSetup_);
|
|
12
|
+
pffft_aligned_free(work_);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
void FFT::doFFT(float *in, std::vector<std::complex<float>> &out) {
|
|
16
|
+
pffft_transform_ordered(
|
|
17
|
+
pffftSetup_,
|
|
18
|
+
in,
|
|
19
|
+
reinterpret_cast<float *>(&out[0]),
|
|
20
|
+
work_,
|
|
21
|
+
PFFFT_FORWARD);
|
|
22
|
+
|
|
23
|
+
dsp::multiplyByScalar(
|
|
24
|
+
reinterpret_cast<float *>(&out[0]),
|
|
25
|
+
0.5f,
|
|
26
|
+
reinterpret_cast<float *>(&out[0]),
|
|
27
|
+
size_ * 2);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
void FFT::doInverseFFT(std::vector<std::complex<float>> &in, float *out) {
|
|
31
|
+
pffft_transform_ordered(
|
|
32
|
+
pffftSetup_,
|
|
33
|
+
reinterpret_cast<float *>(&in[0]),
|
|
34
|
+
out,
|
|
35
|
+
work_,
|
|
36
|
+
PFFFT_BACKWARD);
|
|
37
|
+
|
|
38
|
+
dsp::multiplyByScalar(out, 1.0f / static_cast<float>(size_), out, size_);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
} // namespace audioapi::dsp
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <audioapi/dsp/VectorMath.h>
|
|
4
|
+
#include <audioapi/libs/pffft/pffft.h>
|
|
5
|
+
|
|
6
|
+
#include <algorithm>
|
|
7
|
+
#include <cmath>
|
|
8
|
+
#include <utility>
|
|
9
|
+
#include <complex>
|
|
10
|
+
#include <vector>
|
|
11
|
+
|
|
12
|
+
namespace audioapi::dsp {
|
|
13
|
+
|
|
14
|
+
class FFT {
|
|
15
|
+
public:
|
|
16
|
+
explicit FFT(int size);
|
|
17
|
+
~FFT();
|
|
18
|
+
|
|
19
|
+
void doFFT(float *in, std::vector<std::complex<float>> &out);
|
|
20
|
+
void doInverseFFT(std::vector<std::complex<float>> &in, float *out);
|
|
21
|
+
|
|
22
|
+
private:
|
|
23
|
+
int size_;
|
|
24
|
+
|
|
25
|
+
PFFFT_Setup *pffftSetup_;
|
|
26
|
+
float *work_;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
} // namespace audioapi::dsp
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
#include <arm_neon.h>
|
|
39
39
|
#endif
|
|
40
40
|
|
|
41
|
-
namespace audioapi::
|
|
41
|
+
namespace audioapi::dsp {
|
|
42
42
|
|
|
43
43
|
#if defined(HAVE_ACCELERATE)
|
|
44
44
|
|
|
@@ -695,7 +695,7 @@ void linearToDecibels(
|
|
|
695
695
|
float *outputVector,
|
|
696
696
|
size_t numberOfElementsToProcess) {
|
|
697
697
|
for (int i = 0; i < numberOfElementsToProcess; i++) {
|
|
698
|
-
outputVector[i] =
|
|
698
|
+
outputVector[i] = dsp::linearToDecibels(inputVector[i]);
|
|
699
699
|
}
|
|
700
700
|
}
|
|
701
|
-
} // namespace audioapi::
|
|
701
|
+
} // namespace audioapi::dsp
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
#include <algorithm>
|
|
33
33
|
#include <cmath>
|
|
34
34
|
|
|
35
|
-
namespace audioapi::
|
|
35
|
+
namespace audioapi::dsp {
|
|
36
36
|
|
|
37
37
|
void multiplyByScalarThenAddToOutput(const float *inputVector, float scalar, float *outputVector, size_t numberOfElementsToProcess);
|
|
38
38
|
|
|
@@ -46,4 +46,4 @@ void multiply(const float *inputVector1, const float *inputVector2, float *outpu
|
|
|
46
46
|
float maximumMagnitude(const float *inputVector, size_t numberOfElementsToProcess);
|
|
47
47
|
|
|
48
48
|
void linearToDecibels(const float *inputVector, float *outputVector, size_t numberOfElementsToProcess);
|
|
49
|
-
} // namespace audioapi::
|
|
49
|
+
} // namespace audioapi::dsp
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#include <audioapi/core/Constants.h>
|
|
2
|
+
#include <audioapi/dsp/Windows.h>
|
|
3
|
+
|
|
4
|
+
namespace audioapi::dsp {
|
|
5
|
+
|
|
6
|
+
void WindowFunction::forcePerfectReconstruction(
|
|
7
|
+
float *data,
|
|
8
|
+
int windowLength,
|
|
9
|
+
int interval) {
|
|
10
|
+
for (int i = 0; i < interval; ++i) {
|
|
11
|
+
float sum2 = 0;
|
|
12
|
+
|
|
13
|
+
for (int index = i; index < windowLength; index += interval) {
|
|
14
|
+
sum2 += data[index] * data[index];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
float factor = 1 / std::sqrt(sum2);
|
|
18
|
+
|
|
19
|
+
for (int index = i; index < windowLength; index += interval) {
|
|
20
|
+
data[index] *= factor;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
void Hann::apply(float *data, int size) const {
|
|
26
|
+
for (int i = 0; i < size; ++i) {
|
|
27
|
+
auto x = static_cast<float>(i) / static_cast<float>(size - 1);
|
|
28
|
+
auto window = 0.5f - 0.5f * cos(2 * PI * x);
|
|
29
|
+
data[i] = window * amplitude_;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
void Blackman::apply(float *data, int size) const {
|
|
34
|
+
for (int i = 0; i < size; ++i) {
|
|
35
|
+
auto x = static_cast<float>(i) / static_cast<float>(size - 1);
|
|
36
|
+
auto window = 0.42f - 0.5f * cos(2 * PI * x) + 0.08f * cos(4 * PI * x);
|
|
37
|
+
data[i] = window * amplitude_;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
void Kaiser::apply(float *data, int size) const {
|
|
42
|
+
for (int i = 0; i < size; ++i) {
|
|
43
|
+
auto r = static_cast<float>(2 * i + 1) / static_cast<float>(size) - 1.0f;
|
|
44
|
+
auto arg = std::sqrt(1 - r * r);
|
|
45
|
+
data[i] = bessel0(beta_ * arg) * invB0_ * amplitude_;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
float Kaiser::bandwidthToBeta(float bandwidth, bool heuristicOptimal) {
|
|
50
|
+
if (heuristicOptimal) { // Heuristic based on numerical search
|
|
51
|
+
return bandwidth + 8.0f / (bandwidth + 3.0f) * (bandwidth + 3.0f) +
|
|
52
|
+
0.25f * std::max(3.0f - bandwidth, 0.0f);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
bandwidth = std::max(bandwidth, 2.0f);
|
|
56
|
+
auto alpha = std::sqrt(bandwidth * bandwidth * 0.25f - 1.0f);
|
|
57
|
+
return alpha * PI;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
void ApproximateConfinedGaussian::apply(float *data, int size) const {
|
|
61
|
+
auto offsetScale =
|
|
62
|
+
getGaussian(1.0f) / (getGaussian(3.0f) + getGaussian(-1.0f));
|
|
63
|
+
auto norm = 1 / (getGaussian(1.0f) - 2 * offsetScale * getGaussian(2.0f));
|
|
64
|
+
for (int i = 0; i < size; ++i) {
|
|
65
|
+
auto r = static_cast<float>(2 * i + 1) / static_cast<float>(size) - 1.0f;
|
|
66
|
+
data[i] = norm *
|
|
67
|
+
(getGaussian(r) -
|
|
68
|
+
offsetScale * (getGaussian(r - 2) + getGaussian(r + 2)));
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
float ApproximateConfinedGaussian::bandwidthToSigma(float bandwidth) {
|
|
73
|
+
return 0.3f / std::sqrt(bandwidth);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
float ApproximateConfinedGaussian::getGaussian(float x) const {
|
|
77
|
+
return std::exp(-x * x * gaussianFactor_);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
} // namespace audioapi::dsp
|