react-native-audio-api 0.11.0-nightly-141c86f-20251118 → 0.11.0-nightly-4e6f25c-20251119
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/android/AudioAPIModule.cpp +10 -16
- package/android/src/main/cpp/audioapi/android/OnLoad.cpp +1 -2
- package/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.cpp +4 -4
- package/android/src/main/cpp/audioapi/android/core/AudioPlayer.cpp +11 -20
- package/android/src/main/cpp/audioapi/android/core/utils/AudioDecoder.cpp +24 -46
- package/common/cpp/audioapi/AudioAPIModuleInstaller.h +48 -78
- package/common/cpp/audioapi/HostObjects/AudioContextHostObject.cpp +20 -21
- package/common/cpp/audioapi/HostObjects/AudioNodeHostObject.cpp +3 -4
- package/common/cpp/audioapi/HostObjects/AudioParamHostObject.cpp +6 -8
- package/common/cpp/audioapi/HostObjects/AudioParamHostObject.h +2 -2
- package/common/cpp/audioapi/HostObjects/BaseAudioContextHostObject.cpp +42 -78
- package/common/cpp/audioapi/HostObjects/BaseAudioContextHostObject.h +1 -1
- package/common/cpp/audioapi/HostObjects/OfflineAudioContextHostObject.cpp +14 -18
- package/common/cpp/audioapi/HostObjects/OfflineAudioContextHostObject.h +3 -3
- package/common/cpp/audioapi/HostObjects/WorkletNodeHostObject.h +1 -2
- package/common/cpp/audioapi/HostObjects/WorkletProcessingNodeHostObject.h +1 -2
- package/common/cpp/audioapi/HostObjects/analysis/AnalyserNodeHostObject.cpp +10 -18
- package/common/cpp/audioapi/HostObjects/destinations/AudioDestinationNodeHostObject.h +2 -3
- package/common/cpp/audioapi/HostObjects/effects/BiquadFilterNodeHostObject.cpp +16 -28
- package/common/cpp/audioapi/HostObjects/effects/BiquadFilterNodeHostObject.h +1 -2
- package/common/cpp/audioapi/HostObjects/effects/ConvolverNodeHostObject.cpp +4 -6
- package/common/cpp/audioapi/HostObjects/effects/GainNodeHostObject.cpp +2 -2
- package/common/cpp/audioapi/HostObjects/effects/PeriodicWaveHostObject.h +1 -2
- package/common/cpp/audioapi/HostObjects/effects/StereoPannerNodeHostObject.cpp +2 -2
- package/common/cpp/audioapi/HostObjects/effects/StereoPannerNodeHostObject.h +1 -2
- package/common/cpp/audioapi/HostObjects/events/AudioEventHandlerRegistryHostObject.cpp +6 -12
- package/common/cpp/audioapi/HostObjects/events/AudioEventHandlerRegistryHostObject.h +7 -7
- package/common/cpp/audioapi/HostObjects/inputs/AudioRecorderHostObject.cpp +8 -10
- package/common/cpp/audioapi/HostObjects/inputs/AudioRecorderHostObject.h +1 -1
- package/common/cpp/audioapi/HostObjects/sources/AudioBufferBaseSourceNodeHostObject.cpp +13 -27
- package/common/cpp/audioapi/HostObjects/sources/AudioBufferBaseSourceNodeHostObject.h +11 -12
- package/common/cpp/audioapi/HostObjects/sources/AudioBufferHostObject.cpp +15 -22
- package/common/cpp/audioapi/HostObjects/sources/AudioBufferHostObject.h +5 -7
- package/common/cpp/audioapi/HostObjects/sources/AudioBufferQueueSourceNodeHostObject.cpp +7 -12
- package/common/cpp/audioapi/HostObjects/sources/AudioBufferQueueSourceNodeHostObject.h +8 -9
- package/common/cpp/audioapi/HostObjects/sources/AudioBufferSourceNodeHostObject.cpp +16 -30
- package/common/cpp/audioapi/HostObjects/sources/AudioBufferSourceNodeHostObject.h +2 -4
- package/common/cpp/audioapi/HostObjects/sources/AudioScheduledSourceNodeHostObject.cpp +6 -10
- package/common/cpp/audioapi/HostObjects/sources/ConstantSourceNodeHostObject.cpp +2 -2
- package/common/cpp/audioapi/HostObjects/sources/ConstantSourceNodeHostObject.h +1 -2
- package/common/cpp/audioapi/HostObjects/sources/OscillatorNodeHostObject.cpp +6 -8
- package/common/cpp/audioapi/HostObjects/sources/OscillatorNodeHostObject.h +1 -2
- package/common/cpp/audioapi/HostObjects/sources/RecorderAdapterNodeHostObject.h +4 -5
- package/common/cpp/audioapi/HostObjects/sources/StreamerNodeHostObject.cpp +2 -2
- package/common/cpp/audioapi/HostObjects/sources/StreamerNodeHostObject.h +5 -6
- package/common/cpp/audioapi/HostObjects/sources/WorkletSourceNodeHostObject.h +1 -2
- package/common/cpp/audioapi/HostObjects/utils/AudioDecoderHostObject.cpp +39 -60
- package/common/cpp/audioapi/HostObjects/utils/AudioStretcherHostObject.cpp +4 -8
- package/common/cpp/audioapi/core/AudioContext.cpp +4 -4
- package/common/cpp/audioapi/core/AudioContext.h +5 -2
- package/common/cpp/audioapi/core/AudioNode.cpp +13 -19
- package/common/cpp/audioapi/core/AudioNode.h +14 -7
- package/common/cpp/audioapi/core/AudioParam.cpp +66 -98
- package/common/cpp/audioapi/core/AudioParam.h +20 -12
- package/common/cpp/audioapi/core/BaseAudioContext.cpp +22 -34
- package/common/cpp/audioapi/core/BaseAudioContext.h +19 -15
- package/common/cpp/audioapi/core/OfflineAudioContext.cpp +12 -17
- package/common/cpp/audioapi/core/OfflineAudioContext.h +10 -5
- package/common/cpp/audioapi/core/analysis/AnalyserNode.cpp +13 -21
- package/common/cpp/audioapi/core/analysis/AnalyserNode.h +8 -6
- package/common/cpp/audioapi/core/destinations/AudioDestinationNode.cpp +1 -0
- package/common/cpp/audioapi/core/destinations/AudioDestinationNode.h +5 -3
- package/common/cpp/audioapi/core/effects/BiquadFilterNode.cpp +17 -36
- package/common/cpp/audioapi/core/effects/BiquadFilterNode.h +2 -9
- package/common/cpp/audioapi/core/effects/ConvolverNode.cpp +18 -28
- package/common/cpp/audioapi/core/effects/ConvolverNode.h +19 -10
- package/common/cpp/audioapi/core/effects/GainNode.cpp +1 -0
- package/common/cpp/audioapi/core/effects/GainNode.h +3 -1
- package/common/cpp/audioapi/core/effects/PeriodicWave.cpp +22 -35
- package/common/cpp/audioapi/core/effects/PeriodicWave.h +4 -9
- package/common/cpp/audioapi/core/effects/StereoPannerNode.cpp +4 -5
- package/common/cpp/audioapi/core/effects/StereoPannerNode.h +4 -2
- package/common/cpp/audioapi/core/effects/WorkletNode.cpp +11 -13
- package/common/cpp/audioapi/core/effects/WorkletNode.h +15 -12
- package/common/cpp/audioapi/core/effects/WorkletProcessingNode.cpp +4 -4
- package/common/cpp/audioapi/core/effects/WorkletProcessingNode.h +15 -14
- package/common/cpp/audioapi/core/inputs/AudioRecorder.cpp +9 -8
- package/common/cpp/audioapi/core/inputs/AudioRecorder.h +4 -5
- package/common/cpp/audioapi/core/sources/AudioBuffer.cpp +4 -6
- package/common/cpp/audioapi/core/sources/AudioBuffer.h +4 -7
- package/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.cpp +31 -53
- package/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.h +35 -33
- package/common/cpp/audioapi/core/sources/AudioBufferQueueSourceNode.cpp +19 -20
- package/common/cpp/audioapi/core/sources/AudioBufferQueueSourceNode.h +38 -36
- package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp +25 -40
- package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.h +3 -1
- package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.cpp +9 -9
- package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.h +3 -3
- package/common/cpp/audioapi/core/sources/ConstantSourceNode.cpp +3 -4
- package/common/cpp/audioapi/core/sources/ConstantSourceNode.h +3 -1
- package/common/cpp/audioapi/core/sources/OscillatorNode.cpp +12 -23
- package/common/cpp/audioapi/core/sources/OscillatorNode.h +6 -4
- package/common/cpp/audioapi/core/sources/RecorderAdapterNode.cpp +3 -4
- package/common/cpp/audioapi/core/sources/RecorderAdapterNode.h +18 -16
- package/common/cpp/audioapi/core/sources/StreamerNode.cpp +7 -4
- package/common/cpp/audioapi/core/sources/StreamerNode.h +38 -30
- package/common/cpp/audioapi/core/sources/WorkletSourceNode.cpp +5 -7
- package/common/cpp/audioapi/core/sources/WorkletSourceNode.h +15 -13
- package/common/cpp/audioapi/core/types/AudioFormat.h +1 -11
- package/common/cpp/audioapi/core/utils/AudioDecoder.h +15 -6
- package/common/cpp/audioapi/core/utils/AudioNodeDestructor.cpp +5 -6
- package/common/cpp/audioapi/core/utils/AudioNodeDestructor.h +7 -10
- package/common/cpp/audioapi/core/utils/AudioNodeManager.cpp +13 -22
- package/common/cpp/audioapi/core/utils/AudioNodeManager.h +8 -11
- package/common/cpp/audioapi/core/utils/AudioParamEventQueue.cpp +3 -3
- package/common/cpp/audioapi/core/utils/AudioParamEventQueue.h +5 -5
- package/common/cpp/audioapi/core/utils/AudioStretcher.cpp +6 -6
- package/common/cpp/audioapi/core/utils/Constants.h +5 -3
- package/common/cpp/audioapi/core/utils/ParamChangeEvent.cpp +1 -0
- package/common/cpp/audioapi/core/utils/ParamChangeEvent.h +9 -9
- package/common/cpp/audioapi/core/utils/worklets/SafeIncludes.h +29 -34
- package/common/cpp/audioapi/core/utils/worklets/WorkletsRunner.cpp +14 -16
- package/common/cpp/audioapi/core/utils/worklets/WorkletsRunner.h +23 -19
- package/common/cpp/audioapi/dsp/AudioUtils.cpp +3 -9
- package/common/cpp/audioapi/dsp/AudioUtils.h +1 -1
- package/common/cpp/audioapi/dsp/Convolver.cpp +13 -25
- package/common/cpp/audioapi/dsp/Convolver.h +26 -24
- package/common/cpp/audioapi/dsp/FFT.cpp +1 -1
- package/common/cpp/audioapi/dsp/FFT.h +5 -13
- package/common/cpp/audioapi/dsp/VectorMath.cpp +9 -43
- package/common/cpp/audioapi/dsp/VectorMath.h +35 -8
- package/common/cpp/audioapi/dsp/Windows.cpp +4 -9
- package/common/cpp/audioapi/dsp/Windows.h +24 -23
- package/common/cpp/audioapi/events/AudioEventHandlerRegistry.cpp +12 -17
- package/common/cpp/audioapi/events/AudioEventHandlerRegistry.h +44 -39
- package/common/cpp/audioapi/events/IAudioEventHandlerRegistry.h +15 -7
- package/common/cpp/audioapi/jsi/AudioArrayBuffer.h +4 -5
- package/common/cpp/audioapi/jsi/JsiHostObject.cpp +11 -13
- package/common/cpp/audioapi/jsi/JsiHostObject.h +26 -33
- package/common/cpp/audioapi/jsi/JsiPromise.cpp +11 -21
- package/common/cpp/audioapi/jsi/JsiPromise.h +55 -46
- package/common/cpp/audioapi/jsi/RuntimeLifecycleMonitor.cpp +7 -10
- package/common/cpp/audioapi/jsi/RuntimeLifecycleMonitor.h +1 -3
- package/common/cpp/audioapi/utils/AudioArray.cpp +3 -8
- package/common/cpp/audioapi/utils/AudioArray.h +3 -11
- package/common/cpp/audioapi/utils/AudioBus.cpp +51 -149
- package/common/cpp/audioapi/utils/AudioBus.h +15 -15
- package/common/cpp/audioapi/utils/CircularAudioArray.cpp +6 -18
- package/common/cpp/audioapi/utils/CircularOverflowableAudioArray.cpp +6 -10
- package/common/cpp/audioapi/utils/CircularOverflowableAudioArray.h +2 -2
- package/common/cpp/test/src/AudioParamTest.cpp +3 -2
- package/common/cpp/test/src/AudioScheduledSourceTest.cpp +14 -35
- package/common/cpp/test/src/ConstantSourceTest.cpp +4 -6
- package/common/cpp/test/src/GainTest.cpp +3 -4
- package/common/cpp/test/src/MockAudioEventHandlerRegistry.h +19 -11
- package/common/cpp/test/src/OscillatorTest.cpp +1 -0
- package/common/cpp/test/src/StereoPannerTest.cpp +5 -8
- package/common/cpp/test/src/biquad/BiquadFilterChromium.cpp +10 -27
- package/common/cpp/test/src/biquad/BiquadFilterChromium.h +7 -6
- package/common/cpp/test/src/biquad/BiquadFilterTest.cpp +16 -28
- package/common/cpp/test/src/biquad/BiquadFilterTest.h +13 -6
- package/ios/audioapi/ios/AudioAPIModule.h +4 -6
- package/ios/audioapi/ios/AudioAPIModule.mm +31 -46
- package/ios/audioapi/ios/core/IOSAudioPlayer.mm +24 -33
- package/ios/audioapi/ios/core/IOSAudioRecorder.h +1 -2
- package/ios/audioapi/ios/core/IOSAudioRecorder.mm +4 -6
- package/ios/audioapi/ios/core/NativeAudioPlayer.m +3 -5
- package/ios/audioapi/ios/core/NativeAudioRecorder.h +1 -2
- package/ios/audioapi/ios/core/NativeAudioRecorder.m +21 -33
- package/ios/audioapi/ios/core/utils/AudioDecoder.mm +17 -37
- package/ios/audioapi/ios/system/AudioEngine.h +2 -4
- package/ios/audioapi/ios/system/AudioEngine.mm +7 -19
- package/ios/audioapi/ios/system/AudioSessionManager.h +2 -4
- package/ios/audioapi/ios/system/AudioSessionManager.mm +17 -32
- package/ios/audioapi/ios/system/LockScreenManager.mm +73 -105
- package/ios/audioapi/ios/system/NotificationManager.mm +43 -68
- package/package.json +2 -2
|
@@ -6,6 +6,10 @@
|
|
|
6
6
|
#include <audioapi/utils/AudioArray.h>
|
|
7
7
|
#include <audioapi/utils/AudioBus.h>
|
|
8
8
|
#include <audioapi/utils/CircularAudioArray.h>
|
|
9
|
+
#include <algorithm>
|
|
10
|
+
#include <memory>
|
|
11
|
+
#include <string>
|
|
12
|
+
#include <vector>
|
|
9
13
|
|
|
10
14
|
namespace audioapi {
|
|
11
15
|
AnalyserNode::AnalyserNode(audioapi::BaseAudioContext *context)
|
|
@@ -18,8 +22,7 @@ AnalyserNode::AnalyserNode(audioapi::BaseAudioContext *context)
|
|
|
18
22
|
inputBuffer_ = std::make_unique<CircularAudioArray>(MAX_FFT_SIZE * 2);
|
|
19
23
|
tempBuffer_ = std::make_unique<AudioArray>(fftSize_);
|
|
20
24
|
magnitudeBuffer_ = std::make_unique<AudioArray>(fftSize_ / 2);
|
|
21
|
-
downMixBus_ = std::make_unique<AudioBus>(
|
|
22
|
-
RENDER_QUANTUM_SIZE, 1, context_->getSampleRate());
|
|
25
|
+
downMixBus_ = std::make_unique<AudioBus>(RENDER_QUANTUM_SIZE, 1, context_->getSampleRate());
|
|
23
26
|
|
|
24
27
|
fft_ = std::make_unique<dsp::FFT>(fftSize_);
|
|
25
28
|
complexData_ = std::vector<std::complex<float>>(fftSize_);
|
|
@@ -100,9 +103,8 @@ void AnalyserNode::getByteFrequencyData(uint8_t *data, int length) {
|
|
|
100
103
|
maxDecibels_ == minDecibels_ ? 1 : 1 / (maxDecibels_ - minDecibels_);
|
|
101
104
|
|
|
102
105
|
for (int i = 0; i < length; i++) {
|
|
103
|
-
auto dbMag =
|
|
104
|
-
? minDecibels_
|
|
105
|
-
: dsp::linearToDecibels(magnitudeBufferData[i]);
|
|
106
|
+
auto dbMag =
|
|
107
|
+
magnitudeBufferData[i] == 0 ? minDecibels_ : dsp::linearToDecibels(magnitudeBufferData[i]);
|
|
106
108
|
auto scaledValue = UINT8_MAX * (dbMag - minDecibels_) * rangeScaleFactor;
|
|
107
109
|
|
|
108
110
|
if (scaledValue < 0) {
|
|
@@ -124,8 +126,7 @@ void AnalyserNode::getFloatTimeDomainData(float *data, int length) {
|
|
|
124
126
|
void AnalyserNode::getByteTimeDomainData(uint8_t *data, int length) {
|
|
125
127
|
auto size = std::min(fftSize_, length);
|
|
126
128
|
|
|
127
|
-
inputBuffer_->pop_back(
|
|
128
|
-
tempBuffer_->getData(), fftSize_, std::max(0, fftSize_ - size), true);
|
|
129
|
+
inputBuffer_->pop_back(tempBuffer_->getData(), fftSize_, std::max(0, fftSize_ - size), true);
|
|
129
130
|
|
|
130
131
|
for (int i = 0; i < size; i++) {
|
|
131
132
|
auto value = tempBuffer_->getData()[i];
|
|
@@ -152,8 +153,7 @@ std::shared_ptr<AudioBus> AnalyserNode::processNode(
|
|
|
152
153
|
// Down mix the input bus to mono
|
|
153
154
|
downMixBus_->copy(processingBus.get());
|
|
154
155
|
// Copy the down mixed bus to the input buffer (circular buffer)
|
|
155
|
-
inputBuffer_->push_back(
|
|
156
|
-
downMixBus_->getChannel(0)->getData(), framesToProcess, true);
|
|
156
|
+
inputBuffer_->push_back(downMixBus_->getChannel(0)->getData(), framesToProcess, true);
|
|
157
157
|
|
|
158
158
|
shouldDoFFTAnalysis_ = true;
|
|
159
159
|
|
|
@@ -171,11 +171,7 @@ void AnalyserNode::doFFTAnalysis() {
|
|
|
171
171
|
// the window.
|
|
172
172
|
inputBuffer_->pop_back(tempBuffer_->getData(), fftSize_, 0, true);
|
|
173
173
|
|
|
174
|
-
dsp::multiply(
|
|
175
|
-
tempBuffer_->getData(),
|
|
176
|
-
windowData_->getData(),
|
|
177
|
-
tempBuffer_->getData(),
|
|
178
|
-
fftSize_);
|
|
174
|
+
dsp::multiply(tempBuffer_->getData(), windowData_->getData(), tempBuffer_->getData(), fftSize_);
|
|
179
175
|
|
|
180
176
|
// do fft analysis - get frequency domain data
|
|
181
177
|
fft_->doFFT(tempBuffer_->getData(), complexData_);
|
|
@@ -194,9 +190,7 @@ void AnalyserNode::doFFTAnalysis() {
|
|
|
194
190
|
}
|
|
195
191
|
}
|
|
196
192
|
|
|
197
|
-
void AnalyserNode::setWindowData(
|
|
198
|
-
audioapi::AnalyserNode::WindowType type,
|
|
199
|
-
int size) {
|
|
193
|
+
void AnalyserNode::setWindowData(audioapi::AnalyserNode::WindowType type, int size) {
|
|
200
194
|
if (windowType_ == type && windowData_ && windowData_->getSize() == size) {
|
|
201
195
|
return;
|
|
202
196
|
}
|
|
@@ -207,12 +201,10 @@ void AnalyserNode::setWindowData(
|
|
|
207
201
|
|
|
208
202
|
switch (windowType_) {
|
|
209
203
|
case WindowType::BLACKMAN:
|
|
210
|
-
dsp::Blackman().apply(
|
|
211
|
-
windowData_->getData(), static_cast<int>(windowData_->getSize()));
|
|
204
|
+
dsp::Blackman().apply(windowData_->getData(), static_cast<int>(windowData_->getSize()));
|
|
212
205
|
break;
|
|
213
206
|
case WindowType::HANN:
|
|
214
|
-
dsp::Hann().apply(
|
|
215
|
-
windowData_->getData(), static_cast<int>(windowData_->getSize()));
|
|
207
|
+
dsp::Hann().apply(windowData_->getData(), static_cast<int>(windowData_->getSize()));
|
|
216
208
|
break;
|
|
217
209
|
}
|
|
218
210
|
}
|
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
#include <audioapi/core/AudioNode.h>
|
|
4
4
|
#include <audioapi/dsp/FFT.h>
|
|
5
5
|
|
|
6
|
-
#include <
|
|
6
|
+
#include <algorithm>
|
|
7
|
+
#include <complex>
|
|
7
8
|
#include <cstddef>
|
|
9
|
+
#include <memory>
|
|
8
10
|
#include <string>
|
|
9
|
-
#include <complex>
|
|
10
11
|
#include <vector>
|
|
11
12
|
|
|
12
13
|
namespace audioapi {
|
|
@@ -39,7 +40,9 @@ class AnalyserNode : public AudioNode {
|
|
|
39
40
|
void getByteTimeDomainData(uint8_t *data, int length);
|
|
40
41
|
|
|
41
42
|
protected:
|
|
42
|
-
std::shared_ptr<AudioBus> processNode(
|
|
43
|
+
std::shared_ptr<AudioBus> processNode(
|
|
44
|
+
const std::shared_ptr<AudioBus> &processingBus,
|
|
45
|
+
int framesToProcess) override;
|
|
43
46
|
|
|
44
47
|
private:
|
|
45
48
|
int fftSize_;
|
|
@@ -57,12 +60,11 @@ class AnalyserNode : public AudioNode {
|
|
|
57
60
|
std::unique_ptr<dsp::FFT> fft_;
|
|
58
61
|
std::vector<std::complex<float>> complexData_;
|
|
59
62
|
std::unique_ptr<AudioArray> magnitudeBuffer_;
|
|
60
|
-
bool shouldDoFFTAnalysis_
|
|
63
|
+
bool shouldDoFFTAnalysis_{true};
|
|
61
64
|
|
|
62
65
|
static WindowType fromString(const std::string &type) {
|
|
63
66
|
std::string lowerType = type;
|
|
64
|
-
std::transform(
|
|
65
|
-
lowerType.begin(), lowerType.end(), lowerType.begin(), ::tolower);
|
|
67
|
+
std::transform(lowerType.begin(), lowerType.end(), lowerType.begin(), ::tolower);
|
|
66
68
|
if (lowerType == "blackman") {
|
|
67
69
|
return WindowType::BLACKMAN;
|
|
68
70
|
}
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
#include <audioapi/core/AudioNode.h>
|
|
4
4
|
|
|
5
5
|
#include <algorithm>
|
|
6
|
+
#include <cstddef>
|
|
6
7
|
#include <memory>
|
|
7
8
|
#include <vector>
|
|
8
|
-
#include <cstddef>
|
|
9
9
|
|
|
10
10
|
namespace audioapi {
|
|
11
11
|
|
|
@@ -19,12 +19,14 @@ class AudioDestinationNode : public AudioNode {
|
|
|
19
19
|
std::size_t getCurrentSampleFrame() const;
|
|
20
20
|
double getCurrentTime() const;
|
|
21
21
|
|
|
22
|
-
void renderAudio(const std::shared_ptr<AudioBus
|
|
22
|
+
void renderAudio(const std::shared_ptr<AudioBus> &audioData, int numFrames);
|
|
23
23
|
|
|
24
24
|
protected:
|
|
25
25
|
// DestinationNode is triggered by AudioContext using renderAudio
|
|
26
26
|
// processNode function is not necessary and is never called.
|
|
27
|
-
std::shared_ptr<AudioBus> processNode(const std::shared_ptr<AudioBus
|
|
27
|
+
std::shared_ptr<AudioBus> processNode(const std::shared_ptr<AudioBus> &processingBus, int) final {
|
|
28
|
+
return processingBus;
|
|
29
|
+
};
|
|
28
30
|
|
|
29
31
|
private:
|
|
30
32
|
std::size_t currentSampleFrame_;
|
|
@@ -30,16 +30,17 @@
|
|
|
30
30
|
#include <audioapi/core/effects/BiquadFilterNode.h>
|
|
31
31
|
#include <audioapi/utils/AudioArray.h>
|
|
32
32
|
#include <audioapi/utils/AudioBus.h>
|
|
33
|
+
#include <memory>
|
|
34
|
+
#include <string>
|
|
33
35
|
|
|
34
36
|
// https://webaudio.github.io/Audio-EQ-Cookbook/audio-eq-cookbook.html - math
|
|
35
37
|
// formulas for filters
|
|
36
38
|
|
|
37
39
|
namespace audioapi {
|
|
38
40
|
|
|
39
|
-
BiquadFilterNode::BiquadFilterNode(BaseAudioContext *context)
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
350.0, 0.0f, context->getNyquistFrequency(), context);
|
|
41
|
+
BiquadFilterNode::BiquadFilterNode(BaseAudioContext *context) : AudioNode(context) {
|
|
42
|
+
frequencyParam_ =
|
|
43
|
+
std::make_shared<AudioParam>(350.0, 0.0f, context->getNyquistFrequency(), context);
|
|
43
44
|
detuneParam_ = std::make_shared<AudioParam>(
|
|
44
45
|
0.0f,
|
|
45
46
|
-1200 * LOG2_MOST_POSITIVE_SINGLE_FLOAT,
|
|
@@ -48,10 +49,7 @@ BiquadFilterNode::BiquadFilterNode(BaseAudioContext *context)
|
|
|
48
49
|
QParam_ = std::make_shared<AudioParam>(
|
|
49
50
|
1.0f, MOST_NEGATIVE_SINGLE_FLOAT, MOST_POSITIVE_SINGLE_FLOAT, context);
|
|
50
51
|
gainParam_ = std::make_shared<AudioParam>(
|
|
51
|
-
0.0f,
|
|
52
|
-
MOST_NEGATIVE_SINGLE_FLOAT,
|
|
53
|
-
40 * LOG10_MOST_POSITIVE_SINGLE_FLOAT,
|
|
54
|
-
context);
|
|
52
|
+
0.0f, MOST_NEGATIVE_SINGLE_FLOAT, 40 * LOG10_MOST_POSITIVE_SINGLE_FLOAT, context);
|
|
55
53
|
type_ = BiquadFilterType::LOWPASS;
|
|
56
54
|
isInitialized_ = true;
|
|
57
55
|
channelCountMode_ = ChannelCountMode::MAX;
|
|
@@ -131,11 +129,9 @@ void BiquadFilterNode::getFrequencyResponse(
|
|
|
131
129
|
|
|
132
130
|
double omega = -PI * normalizedFreq;
|
|
133
131
|
auto z = std::complex<double>(std::cos(omega), std::sin(omega));
|
|
134
|
-
auto response = (b0 + (b1 + b2 * z) * z) /
|
|
135
|
-
(std::complex<double>(1, 0) + (a1 + a2 * z) * z);
|
|
132
|
+
auto response = (b0 + (b1 + b2 * z) * z) / (std::complex<double>(1, 0) + (a1 + a2 * z) * z);
|
|
136
133
|
magResponseOutput[i] = static_cast<float>(std::abs(response));
|
|
137
|
-
phaseResponseOutput[i] =
|
|
138
|
-
static_cast<float>(atan2(imag(response), real(response)));
|
|
134
|
+
phaseResponseOutput[i] = static_cast<float>(atan2(imag(response), real(response)));
|
|
139
135
|
}
|
|
140
136
|
}
|
|
141
137
|
|
|
@@ -173,8 +169,7 @@ void BiquadFilterNode::setLowpassCoefficients(float frequency, float Q) {
|
|
|
173
169
|
float cosW = std::cos(theta);
|
|
174
170
|
float beta = (1 - cosW) / 2;
|
|
175
171
|
|
|
176
|
-
setNormalizedCoefficients(
|
|
177
|
-
beta, 2 * beta, beta, 1 + alpha, -2 * cosW, 1 - alpha);
|
|
172
|
+
setNormalizedCoefficients(beta, 2 * beta, beta, 1 + alpha, -2 * cosW, 1 - alpha);
|
|
178
173
|
}
|
|
179
174
|
|
|
180
175
|
void BiquadFilterNode::setHighpassCoefficients(float frequency, float Q) {
|
|
@@ -194,8 +189,7 @@ void BiquadFilterNode::setHighpassCoefficients(float frequency, float Q) {
|
|
|
194
189
|
float cosW = std::cos(theta);
|
|
195
190
|
float beta = (1 + cosW) / 2;
|
|
196
191
|
|
|
197
|
-
setNormalizedCoefficients(
|
|
198
|
-
beta, -2 * beta, beta, 1 + alpha, -2 * cosW, 1 - alpha);
|
|
192
|
+
setNormalizedCoefficients(beta, -2 * beta, beta, 1 + alpha, -2 * cosW, 1 - alpha);
|
|
199
193
|
}
|
|
200
194
|
|
|
201
195
|
void BiquadFilterNode::setBandpassCoefficients(float frequency, float Q) {
|
|
@@ -215,8 +209,7 @@ void BiquadFilterNode::setBandpassCoefficients(float frequency, float Q) {
|
|
|
215
209
|
float alpha = std::sin(w0) / (2 * Q);
|
|
216
210
|
float cosW = std::cos(w0);
|
|
217
211
|
|
|
218
|
-
setNormalizedCoefficients(
|
|
219
|
-
alpha, 0.0f, -alpha, 1.0f + alpha, -2 * cosW, 1.0f - alpha);
|
|
212
|
+
setNormalizedCoefficients(alpha, 0.0f, -alpha, 1.0f + alpha, -2 * cosW, 1.0f - alpha);
|
|
220
213
|
}
|
|
221
214
|
|
|
222
215
|
void BiquadFilterNode::setLowshelfCoefficients(float frequency, float gain) {
|
|
@@ -275,10 +268,7 @@ void BiquadFilterNode::setHighshelfCoefficients(float frequency, float gain) {
|
|
|
275
268
|
A + 1 - (A - 1) * cosW - gamma);
|
|
276
269
|
}
|
|
277
270
|
|
|
278
|
-
void BiquadFilterNode::setPeakingCoefficients(
|
|
279
|
-
float frequency,
|
|
280
|
-
float Q,
|
|
281
|
-
float gain) {
|
|
271
|
+
void BiquadFilterNode::setPeakingCoefficients(float frequency, float Q, float gain) {
|
|
282
272
|
float A = std::pow(10.0f, gain / 40.0f);
|
|
283
273
|
|
|
284
274
|
if (frequency <= 0.0f || frequency >= 1.0f) {
|
|
@@ -296,12 +286,7 @@ void BiquadFilterNode::setPeakingCoefficients(
|
|
|
296
286
|
float cosW = std::cos(w0);
|
|
297
287
|
|
|
298
288
|
setNormalizedCoefficients(
|
|
299
|
-
1 + alpha * A,
|
|
300
|
-
-2 * cosW,
|
|
301
|
-
1 - alpha * A,
|
|
302
|
-
1 + alpha / A,
|
|
303
|
-
-2 * cosW,
|
|
304
|
-
1 - alpha / A);
|
|
289
|
+
1 + alpha * A, -2 * cosW, 1 - alpha * A, 1 + alpha / A, -2 * cosW, 1 - alpha / A);
|
|
305
290
|
}
|
|
306
291
|
|
|
307
292
|
void BiquadFilterNode::setNotchCoefficients(float frequency, float Q) {
|
|
@@ -319,8 +304,7 @@ void BiquadFilterNode::setNotchCoefficients(float frequency, float Q) {
|
|
|
319
304
|
float alpha = std::sin(w0) / (2 * Q);
|
|
320
305
|
float cosW = std::cos(w0);
|
|
321
306
|
|
|
322
|
-
setNormalizedCoefficients(
|
|
323
|
-
1.0f, -2 * cosW, 1.0f, 1 + alpha, -2 * cosW, 1 - alpha);
|
|
307
|
+
setNormalizedCoefficients(1.0f, -2 * cosW, 1.0f, 1 + alpha, -2 * cosW, 1 - alpha);
|
|
324
308
|
}
|
|
325
309
|
|
|
326
310
|
void BiquadFilterNode::setAllpassCoefficients(float frequency, float Q) {
|
|
@@ -338,17 +322,14 @@ void BiquadFilterNode::setAllpassCoefficients(float frequency, float Q) {
|
|
|
338
322
|
float alpha = std::sin(w0) / (2 * Q);
|
|
339
323
|
float cosW = std::cos(w0);
|
|
340
324
|
|
|
341
|
-
setNormalizedCoefficients(
|
|
342
|
-
1 - alpha, -2 * cosW, 1 + alpha, 1 + alpha, -2 * cosW, 1 - alpha);
|
|
325
|
+
setNormalizedCoefficients(1 - alpha, -2 * cosW, 1 + alpha, 1 + alpha, -2 * cosW, 1 - alpha);
|
|
343
326
|
}
|
|
344
327
|
|
|
345
328
|
void BiquadFilterNode::applyFilter() {
|
|
346
329
|
double currentTime = context_->getCurrentTime();
|
|
347
330
|
|
|
348
|
-
float frequency =
|
|
349
|
-
|
|
350
|
-
float detune =
|
|
351
|
-
detuneParam_->processKRateParam(RENDER_QUANTUM_SIZE, currentTime);
|
|
331
|
+
float frequency = frequencyParam_->processKRateParam(RENDER_QUANTUM_SIZE, currentTime);
|
|
332
|
+
float detune = detuneParam_->processKRateParam(RENDER_QUANTUM_SIZE, currentTime);
|
|
352
333
|
auto Q = QParam_->processKRateParam(RENDER_QUANTUM_SIZE, currentTime);
|
|
353
334
|
auto gain = gainParam_->processKRateParam(RENDER_QUANTUM_SIZE, currentTime);
|
|
354
335
|
|
|
@@ -95,8 +95,7 @@ class BiquadFilterNode : public AudioNode {
|
|
|
95
95
|
|
|
96
96
|
static BiquadFilterType fromString(const std::string &type) {
|
|
97
97
|
std::string lowerType = type;
|
|
98
|
-
std::transform(
|
|
99
|
-
lowerType.begin(), lowerType.end(), lowerType.begin(), ::tolower);
|
|
98
|
+
std::transform(lowerType.begin(), lowerType.end(), lowerType.begin(), ::tolower);
|
|
100
99
|
|
|
101
100
|
if (lowerType == "lowpass")
|
|
102
101
|
return BiquadFilterType::LOWPASS;
|
|
@@ -141,13 +140,7 @@ class BiquadFilterNode : public AudioNode {
|
|
|
141
140
|
}
|
|
142
141
|
}
|
|
143
142
|
|
|
144
|
-
void setNormalizedCoefficients(
|
|
145
|
-
float b0,
|
|
146
|
-
float b1,
|
|
147
|
-
float b2,
|
|
148
|
-
float a0,
|
|
149
|
-
float a1,
|
|
150
|
-
float a2);
|
|
143
|
+
void setNormalizedCoefficients(float b0, float b1, float b2, float a0, float a1, float a2);
|
|
151
144
|
void setLowpassCoefficients(float frequency, float Q);
|
|
152
145
|
void setHighpassCoefficients(float frequency, float Q);
|
|
153
146
|
void setBandpassCoefficients(float frequency, float Q);
|
|
@@ -6,7 +6,9 @@
|
|
|
6
6
|
#include <audioapi/dsp/FFT.h>
|
|
7
7
|
#include <audioapi/utils/AudioArray.h>
|
|
8
8
|
#include <iostream>
|
|
9
|
+
#include <memory>
|
|
9
10
|
#include <thread>
|
|
11
|
+
#include <vector>
|
|
10
12
|
|
|
11
13
|
namespace audioapi {
|
|
12
14
|
ConvolverNode::ConvolverNode(
|
|
@@ -26,8 +28,8 @@ ConvolverNode::ConvolverNode(
|
|
|
26
28
|
normalize_ = !disableNormalization;
|
|
27
29
|
gainCalibrationSampleRate_ = context->getSampleRate();
|
|
28
30
|
setBuffer(buffer);
|
|
29
|
-
audioBus_ =
|
|
30
|
-
RENDER_QUANTUM_SIZE, channelCount_, context->getSampleRate());
|
|
31
|
+
audioBus_ =
|
|
32
|
+
std::make_shared<AudioBus>(RENDER_QUANTUM_SIZE, channelCount_, context->getSampleRate());
|
|
31
33
|
isInitialized_ = true;
|
|
32
34
|
}
|
|
33
35
|
|
|
@@ -60,26 +62,18 @@ void ConvolverNode::setBuffer(const std::shared_ptr<AudioBuffer> &buffer) {
|
|
|
60
62
|
for (int i = 0; i < buffer->getNumberOfChannels(); ++i) {
|
|
61
63
|
convolvers_.emplace_back();
|
|
62
64
|
AudioArray channelData(buffer->getLength());
|
|
63
|
-
memcpy(
|
|
64
|
-
|
|
65
|
-
buffer->getChannelData(i),
|
|
66
|
-
buffer->getLength() * sizeof(float));
|
|
67
|
-
convolvers_.back().init(
|
|
68
|
-
RENDER_QUANTUM_SIZE, channelData, buffer->getLength());
|
|
65
|
+
memcpy(channelData.getData(), buffer->getChannelData(i), buffer->getLength() * sizeof(float));
|
|
66
|
+
convolvers_.back().init(RENDER_QUANTUM_SIZE, channelData, buffer->getLength());
|
|
69
67
|
}
|
|
70
68
|
if (buffer->getNumberOfChannels() == 1) {
|
|
71
69
|
// add one more convolver, because right now input is always stereo
|
|
72
70
|
convolvers_.emplace_back();
|
|
73
71
|
AudioArray channelData(buffer->getLength());
|
|
74
|
-
memcpy(
|
|
75
|
-
|
|
76
|
-
buffer->getChannelData(0),
|
|
77
|
-
buffer->getLength() * sizeof(float));
|
|
78
|
-
convolvers_.back().init(
|
|
79
|
-
RENDER_QUANTUM_SIZE, channelData, buffer->getLength());
|
|
72
|
+
memcpy(channelData.getData(), buffer->getChannelData(0), buffer->getLength() * sizeof(float));
|
|
73
|
+
convolvers_.back().init(RENDER_QUANTUM_SIZE, channelData, buffer->getLength());
|
|
80
74
|
}
|
|
81
|
-
internalBuffer_ =
|
|
82
|
-
RENDER_QUANTUM_SIZE * 2, channelCount_, buffer->getSampleRate());
|
|
75
|
+
internalBuffer_ =
|
|
76
|
+
std::make_shared<AudioBus>(RENDER_QUANTUM_SIZE * 2, channelCount_, buffer->getSampleRate());
|
|
83
77
|
intermediateBus_ = std::make_shared<AudioBus>(
|
|
84
78
|
RENDER_QUANTUM_SIZE, convolvers_.size(), buffer->getSampleRate());
|
|
85
79
|
internalBufferIndex_ = 0;
|
|
@@ -123,8 +117,7 @@ std::shared_ptr<AudioBus> ConvolverNode::processNode(
|
|
|
123
117
|
performConvolution(processingBus); // result returned to intermediateBus_
|
|
124
118
|
audioBus_->sum(intermediateBus_.get());
|
|
125
119
|
|
|
126
|
-
internalBuffer_->copy(
|
|
127
|
-
audioBus_.get(), 0, internalBufferIndex_, RENDER_QUANTUM_SIZE);
|
|
120
|
+
internalBuffer_->copy(audioBus_.get(), 0, internalBufferIndex_, RENDER_QUANTUM_SIZE);
|
|
128
121
|
internalBufferIndex_ += RENDER_QUANTUM_SIZE;
|
|
129
122
|
}
|
|
130
123
|
audioBus_->zero();
|
|
@@ -176,14 +169,12 @@ void ConvolverNode::calculateNormalizationScale() {
|
|
|
176
169
|
scaleFactor_ *= gainCalibrationSampleRate_ / buffer_->getSampleRate();
|
|
177
170
|
}
|
|
178
171
|
|
|
179
|
-
void ConvolverNode::performConvolution(
|
|
180
|
-
const std::shared_ptr<AudioBus> &processingBus) {
|
|
172
|
+
void ConvolverNode::performConvolution(const std::shared_ptr<AudioBus> &processingBus) {
|
|
181
173
|
if (processingBus->getNumberOfChannels() == 1) {
|
|
182
174
|
for (int i = 0; i < convolvers_.size(); ++i) {
|
|
183
175
|
threadPool_->schedule([&, i] {
|
|
184
176
|
convolvers_[i].process(
|
|
185
|
-
processingBus->getChannel(0)->getData(),
|
|
186
|
-
intermediateBus_->getChannel(i)->getData());
|
|
177
|
+
processingBus->getChannel(0)->getData(), intermediateBus_->getChannel(i)->getData());
|
|
187
178
|
});
|
|
188
179
|
}
|
|
189
180
|
} else if (processingBus->getNumberOfChannels() == 2) {
|
|
@@ -197,12 +188,11 @@ void ConvolverNode::performConvolution(
|
|
|
197
188
|
outputChannelMap = {0, 3, 2, 1};
|
|
198
189
|
}
|
|
199
190
|
for (int i = 0; i < convolvers_.size(); ++i) {
|
|
200
|
-
threadPool_->schedule(
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
});
|
|
191
|
+
threadPool_->schedule([this, i, inputChannelMap, outputChannelMap, &processingBus] {
|
|
192
|
+
convolvers_[i].process(
|
|
193
|
+
processingBus->getChannel(inputChannelMap[i])->getData(),
|
|
194
|
+
intermediateBus_->getChannel(outputChannelMap[i])->getData());
|
|
195
|
+
});
|
|
206
196
|
}
|
|
207
197
|
}
|
|
208
198
|
threadPool_->wait();
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
|
|
10
10
|
#include <audioapi/utils/ThreadPool.hpp>
|
|
11
11
|
|
|
12
|
-
static constexpr int GAIN_CALIBRATION =
|
|
12
|
+
static constexpr int GAIN_CALIBRATION =
|
|
13
|
+
-58; // magic number so that processed signal and dry signal have roughly the same volume
|
|
13
14
|
static constexpr double MIN_IR_POWER = 0.000125;
|
|
14
15
|
|
|
15
16
|
namespace audioapi {
|
|
@@ -19,18 +20,26 @@ class AudioBuffer;
|
|
|
19
20
|
|
|
20
21
|
class ConvolverNode : public AudioNode {
|
|
21
22
|
public:
|
|
22
|
-
|
|
23
|
+
explicit ConvolverNode(
|
|
24
|
+
BaseAudioContext *context,
|
|
25
|
+
const std::shared_ptr<AudioBuffer> &buffer,
|
|
26
|
+
bool disableNormalization);
|
|
23
27
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
[[nodiscard]] bool getNormalize_() const;
|
|
29
|
+
[[nodiscard]] const std::shared_ptr<AudioBuffer> &getBuffer() const;
|
|
30
|
+
void setNormalize(bool normalize);
|
|
31
|
+
void setBuffer(const std::shared_ptr<AudioBuffer> &buffer);
|
|
28
32
|
|
|
29
33
|
protected:
|
|
30
|
-
std::shared_ptr<AudioBus> processNode(
|
|
34
|
+
std::shared_ptr<AudioBus> processNode(
|
|
35
|
+
const std::shared_ptr<AudioBus> &processingBus,
|
|
36
|
+
int framesToProcess) override;
|
|
31
37
|
|
|
32
38
|
private:
|
|
33
|
-
std::shared_ptr<AudioBus> processInputs(
|
|
39
|
+
std::shared_ptr<AudioBus> processInputs(
|
|
40
|
+
const std::shared_ptr<AudioBus> &outputBus,
|
|
41
|
+
int framesToProcess,
|
|
42
|
+
bool checkIsAlreadyProcessed) override;
|
|
34
43
|
void onInputDisabled() override;
|
|
35
44
|
float gainCalibrationSampleRate_;
|
|
36
45
|
size_t remainingSegments_;
|
|
@@ -38,7 +47,7 @@ class ConvolverNode : public AudioNode {
|
|
|
38
47
|
bool normalize_;
|
|
39
48
|
bool signalledToStop_;
|
|
40
49
|
float scaleFactor_;
|
|
41
|
-
std::shared_ptr<AudioBus>intermediateBus_;
|
|
50
|
+
std::shared_ptr<AudioBus> intermediateBus_;
|
|
42
51
|
|
|
43
52
|
// impulse response buffer
|
|
44
53
|
std::shared_ptr<AudioBuffer> buffer_;
|
|
@@ -49,7 +58,7 @@ class ConvolverNode : public AudioNode {
|
|
|
49
58
|
std::shared_ptr<ThreadPool> threadPool_;
|
|
50
59
|
|
|
51
60
|
void calculateNormalizationScale();
|
|
52
|
-
void performConvolution(const std::shared_ptr<AudioBus
|
|
61
|
+
void performConvolution(const std::shared_ptr<AudioBus> &processingBus);
|
|
53
62
|
};
|
|
54
63
|
|
|
55
64
|
} // namespace audioapi
|
|
@@ -16,7 +16,9 @@ class GainNode : public AudioNode {
|
|
|
16
16
|
[[nodiscard]] std::shared_ptr<AudioParam> getGainParam() const;
|
|
17
17
|
|
|
18
18
|
protected:
|
|
19
|
-
std::shared_ptr<AudioBus> processNode(
|
|
19
|
+
std::shared_ptr<AudioBus> processNode(
|
|
20
|
+
const std::shared_ptr<AudioBus> &processingBus,
|
|
21
|
+
int framesToProcess) override;
|
|
20
22
|
|
|
21
23
|
private:
|
|
22
24
|
std::shared_ptr<AudioParam> gainParam_;
|
|
@@ -29,6 +29,9 @@
|
|
|
29
29
|
#include <audioapi/core/effects/PeriodicWave.h>
|
|
30
30
|
#include <audioapi/core/utils/Constants.h>
|
|
31
31
|
#include <audioapi/dsp/VectorMath.h>
|
|
32
|
+
#include <algorithm>
|
|
33
|
+
#include <memory>
|
|
34
|
+
#include <vector>
|
|
32
35
|
|
|
33
36
|
constexpr unsigned NumberOfOctaveBands = 3;
|
|
34
37
|
constexpr float CentsPerRange = 1200.0f / NumberOfOctaveBands;
|
|
@@ -38,13 +41,12 @@ constexpr float interpolate3Point = 0.16;
|
|
|
38
41
|
namespace audioapi {
|
|
39
42
|
PeriodicWave::PeriodicWave(float sampleRate, bool disableNormalization)
|
|
40
43
|
: sampleRate_(sampleRate), disableNormalization_(disableNormalization) {
|
|
41
|
-
numberOfRanges_ = static_cast<int>(
|
|
42
|
-
NumberOfOctaveBands * log2f(static_cast<float>(getPeriodicWaveSize()))));
|
|
44
|
+
numberOfRanges_ = static_cast<int>(
|
|
45
|
+
round(NumberOfOctaveBands * log2f(static_cast<float>(getPeriodicWaveSize()))));
|
|
43
46
|
auto nyquistFrequency = sampleRate_ / 2;
|
|
44
|
-
lowestFundamentalFrequency_ =
|
|
45
|
-
static_cast<float>(getMaxNumberOfPartials());
|
|
46
|
-
scale_ = static_cast<float>(getPeriodicWaveSize()) /
|
|
47
|
-
static_cast<float>(sampleRate_);
|
|
47
|
+
lowestFundamentalFrequency_ =
|
|
48
|
+
static_cast<float>(nyquistFrequency) / static_cast<float>(getMaxNumberOfPartials());
|
|
49
|
+
scale_ = static_cast<float>(getPeriodicWaveSize()) / static_cast<float>(sampleRate_);
|
|
48
50
|
bandLimitedTables_ = new float *[numberOfRanges_];
|
|
49
51
|
|
|
50
52
|
fft_ = std::make_unique<dsp::FFT>(getPeriodicWaveSize());
|
|
@@ -91,22 +93,14 @@ float PeriodicWave::getScale() const {
|
|
|
91
93
|
return scale_;
|
|
92
94
|
}
|
|
93
95
|
|
|
94
|
-
float PeriodicWave::getSample(
|
|
95
|
-
float fundamentalFrequency,
|
|
96
|
-
float phase,
|
|
97
|
-
float phaseIncrement) {
|
|
96
|
+
float PeriodicWave::getSample(float fundamentalFrequency, float phase, float phaseIncrement) {
|
|
98
97
|
float *lowerWaveData = nullptr;
|
|
99
98
|
float *higherWaveData = nullptr;
|
|
100
99
|
|
|
101
|
-
auto interpolationFactor =
|
|
102
|
-
fundamentalFrequency, lowerWaveData, higherWaveData);
|
|
100
|
+
auto interpolationFactor =
|
|
101
|
+
getWaveDataForFundamentalFrequency(fundamentalFrequency, lowerWaveData, higherWaveData);
|
|
103
102
|
|
|
104
|
-
return doInterpolation(
|
|
105
|
-
phase,
|
|
106
|
-
phaseIncrement,
|
|
107
|
-
interpolationFactor,
|
|
108
|
-
lowerWaveData,
|
|
109
|
-
higherWaveData);
|
|
103
|
+
return doInterpolation(phase, phaseIncrement, interpolationFactor, lowerWaveData, higherWaveData);
|
|
110
104
|
}
|
|
111
105
|
|
|
112
106
|
int PeriodicWave::getMaxNumberOfPartials() const {
|
|
@@ -122,7 +116,7 @@ int PeriodicWave::getNumberOfPartialsPerRange(int rangeIndex) const {
|
|
|
122
116
|
|
|
123
117
|
// The very top range will have all the partials culled.
|
|
124
118
|
int numberOfPartials =
|
|
125
|
-
int(static_cast<float>(getMaxNumberOfPartials()) * cullingScale);
|
|
119
|
+
static_cast<int>(static_cast<float>(getMaxNumberOfPartials()) * cullingScale);
|
|
126
120
|
|
|
127
121
|
return numberOfPartials;
|
|
128
122
|
}
|
|
@@ -230,8 +224,7 @@ void PeriodicWave::createBandLimitedTables(
|
|
|
230
224
|
fft_->doInverseFFT(complexFFTData, bandLimitedTables_[rangeIndex]);
|
|
231
225
|
|
|
232
226
|
if (!disableNormalization_ && rangeIndex == 0) {
|
|
233
|
-
float maxValue =
|
|
234
|
-
dsp::maximumMagnitude(bandLimitedTables_[rangeIndex], fftSize);
|
|
227
|
+
float maxValue = dsp::maximumMagnitude(bandLimitedTables_[rangeIndex], fftSize);
|
|
235
228
|
if (maxValue != 0) {
|
|
236
229
|
normalizationFactor = 1.0f / maxValue;
|
|
237
230
|
}
|
|
@@ -254,20 +247,17 @@ float PeriodicWave::getWaveDataForFundamentalFrequency(
|
|
|
254
247
|
|
|
255
248
|
// calculating lower and higher range index for the given fundamental
|
|
256
249
|
// frequency.
|
|
257
|
-
float ratio =
|
|
258
|
-
? fundamentalFrequency / lowestFundamentalFrequency_
|
|
259
|
-
: 0.5f;
|
|
250
|
+
float ratio =
|
|
251
|
+
fundamentalFrequency > 0 ? fundamentalFrequency / lowestFundamentalFrequency_ : 0.5f;
|
|
260
252
|
float centsAboveLowestFrequency = log2f(ratio) * 1200;
|
|
261
253
|
|
|
262
254
|
float pitchRange = 1 + centsAboveLowestFrequency / CentsPerRange;
|
|
263
255
|
|
|
264
|
-
pitchRange =
|
|
265
|
-
std::clamp(pitchRange, 0.0f, static_cast<float>(numberOfRanges_ - 1));
|
|
256
|
+
pitchRange = std::clamp(pitchRange, 0.0f, static_cast<float>(numberOfRanges_ - 1));
|
|
266
257
|
|
|
267
258
|
int lowerRangeIndex = static_cast<int>(pitchRange);
|
|
268
|
-
int higherRangeIndex =
|
|
269
|
-
? lowerRangeIndex + 1
|
|
270
|
-
: lowerRangeIndex;
|
|
259
|
+
int higherRangeIndex =
|
|
260
|
+
lowerRangeIndex < numberOfRanges_ - 1 ? lowerRangeIndex + 1 : lowerRangeIndex;
|
|
271
261
|
|
|
272
262
|
// get the wave data for the lower and higher range index.
|
|
273
263
|
lowerWaveData = bandLimitedTables_[lowerRangeIndex];
|
|
@@ -297,8 +287,7 @@ float PeriodicWave::doInterpolation(
|
|
|
297
287
|
|
|
298
288
|
for (int i = 0; i < 2; i++) {
|
|
299
289
|
indices[i] = (index + i) &
|
|
300
|
-
(getPeriodicWaveSize() -
|
|
301
|
-
1); // more efficient alternative to % getPeriodicWaveSize()
|
|
290
|
+
(getPeriodicWaveSize() - 1); // more efficient alternative to % getPeriodicWaveSize()
|
|
302
291
|
}
|
|
303
292
|
|
|
304
293
|
auto lowerWaveDataSample1 = lowerWaveData[indices[0]];
|
|
@@ -306,10 +295,8 @@ float PeriodicWave::doInterpolation(
|
|
|
306
295
|
auto higherWaveDataSample1 = higherWaveData[indices[0]];
|
|
307
296
|
auto higherWaveDataSample2 = higherWaveData[indices[1]];
|
|
308
297
|
|
|
309
|
-
lowerWaveDataSample =
|
|
310
|
-
|
|
311
|
-
higherWaveDataSample =
|
|
312
|
-
(1 - factor) * higherWaveDataSample1 + factor * higherWaveDataSample2;
|
|
298
|
+
lowerWaveDataSample = (1 - factor) * lowerWaveDataSample1 + factor * lowerWaveDataSample2;
|
|
299
|
+
higherWaveDataSample = (1 - factor) * higherWaveDataSample1 + factor * higherWaveDataSample2;
|
|
313
300
|
} else if (phaseIncrement >= interpolate3Point) { // 3-point Lagrange
|
|
314
301
|
// interpolation
|
|
315
302
|
int indices[3];
|
|
@@ -33,17 +33,14 @@
|
|
|
33
33
|
|
|
34
34
|
#include <algorithm>
|
|
35
35
|
#include <cmath>
|
|
36
|
+
#include <complex>
|
|
36
37
|
#include <memory>
|
|
37
38
|
#include <vector>
|
|
38
|
-
#include <complex>
|
|
39
39
|
|
|
40
40
|
namespace audioapi {
|
|
41
41
|
class PeriodicWave {
|
|
42
42
|
public:
|
|
43
|
-
explicit PeriodicWave(
|
|
44
|
-
float sampleRate,
|
|
45
|
-
OscillatorType type,
|
|
46
|
-
bool disableNormalization);
|
|
43
|
+
explicit PeriodicWave(float sampleRate, OscillatorType type, bool disableNormalization);
|
|
47
44
|
explicit PeriodicWave(
|
|
48
45
|
float sampleRate,
|
|
49
46
|
const std::vector<std::complex<float>> &complexData,
|
|
@@ -54,8 +51,7 @@ class PeriodicWave {
|
|
|
54
51
|
[[nodiscard]] int getPeriodicWaveSize() const;
|
|
55
52
|
[[nodiscard]] float getScale() const;
|
|
56
53
|
|
|
57
|
-
float
|
|
58
|
-
getSample(float fundamentalFrequency, float phase, float phaseIncrement);
|
|
54
|
+
float getSample(float fundamentalFrequency, float phase, float phaseIncrement);
|
|
59
55
|
|
|
60
56
|
private:
|
|
61
57
|
explicit PeriodicWave(float sampleRate, bool disableNormalization);
|
|
@@ -80,8 +76,7 @@ class PeriodicWave {
|
|
|
80
76
|
// The higher frequencies are culled to band-limit the waveform.
|
|
81
77
|
// For each range, the inverse FFT is performed to get the time domain
|
|
82
78
|
// representation of the band-limited waveform.
|
|
83
|
-
void
|
|
84
|
-
createBandLimitedTables(const std::vector<std::complex<float>> &complexData, int size);
|
|
79
|
+
void createBandLimitedTables(const std::vector<std::complex<float>> &complexData, int size);
|
|
85
80
|
|
|
86
81
|
// This function returns the interpolation factor between the lower and higher
|
|
87
82
|
// range data and sets the lower and higher wave data for the given
|