react-native-audio-api 0.4.12-beta.1 → 0.4.12-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/RNAudioAPI.podspec +11 -1
- package/android/CMakeLists.txt +9 -48
- package/android/src/main/cpp/audioapi/CMakeLists.txt +44 -0
- package/android/src/main/cpp/{AudioAPIModule.cpp → audioapi/android/AudioAPIModule.cpp} +1 -4
- package/android/src/main/cpp/{AudioAPIModule.h → audioapi/android/AudioAPIModule.h} +2 -1
- package/android/src/main/cpp/{OnLoad.cpp → audioapi/android/OnLoad.cpp} +2 -1
- package/android/src/main/cpp/{core → audioapi/android/core}/AudioDecoder.cpp +5 -5
- package/android/src/main/cpp/{core → audioapi/android/core}/AudioPlayer.cpp +5 -7
- package/android/src/main/cpp/{core → audioapi/android/core}/AudioPlayer.h +1 -0
- package/android/src/main/cpp/{libs → audioapi/android/libs}/pffft.c +2 -2
- package/android/src/main/java/com/swmansion/audioapi/AudioAPIPackage.kt +1 -0
- package/common/cpp/{installer → audioapi}/AudioAPIModuleInstaller.h +5 -3
- package/common/cpp/{HostObjects → audioapi/HostObjects}/AnalyserNodeHostObject.h +3 -3
- package/common/cpp/{HostObjects → audioapi/HostObjects}/AudioBufferHostObject.h +3 -3
- package/common/cpp/{HostObjects → audioapi/HostObjects}/AudioBufferSourceNodeHostObject.h +5 -5
- package/common/cpp/{HostObjects → audioapi/HostObjects}/AudioContextHostObject.h +3 -3
- package/common/cpp/{HostObjects → audioapi/HostObjects}/AudioDestinationNodeHostObject.h +3 -3
- package/common/cpp/{HostObjects → audioapi/HostObjects}/AudioNodeHostObject.h +3 -3
- package/common/cpp/{HostObjects → audioapi/HostObjects}/AudioParamHostObject.h +3 -3
- package/common/cpp/{HostObjects → audioapi/HostObjects}/AudioScheduledSourceNodeHostObject.h +3 -3
- package/common/cpp/{HostObjects → audioapi/HostObjects}/BaseAudioContextHostObject.h +14 -15
- package/common/cpp/{HostObjects → audioapi/HostObjects}/BiquadFilterNodeHostObject.h +4 -4
- package/common/cpp/{HostObjects → audioapi/HostObjects}/GainNodeHostObject.h +4 -4
- package/common/cpp/{HostObjects → audioapi/HostObjects}/OscillatorNodeHostObject.h +5 -5
- package/common/cpp/{HostObjects → audioapi/HostObjects}/PeriodicWaveHostObject.h +2 -2
- package/common/cpp/{HostObjects → audioapi/HostObjects}/StereoPannerNodeHostObject.h +4 -4
- package/common/cpp/audioapi/HostObjects/StretcherNodeHostObject.h +35 -0
- package/common/cpp/{core → audioapi/core}/AudioContext.cpp +6 -6
- package/common/cpp/{core → audioapi/core}/AudioContext.h +2 -2
- package/common/cpp/{core → audioapi/core}/AudioNode.cpp +5 -7
- package/common/cpp/{core → audioapi/core}/AudioNode.h +5 -4
- package/common/cpp/{core → audioapi/core}/AudioParam.cpp +3 -4
- package/common/cpp/{core → audioapi/core}/AudioParam.h +3 -3
- package/common/cpp/{core → audioapi/core}/BaseAudioContext.cpp +14 -17
- package/common/cpp/{core → audioapi/core}/BaseAudioContext.h +4 -3
- package/common/cpp/{core → audioapi/core/analysis}/AnalyserNode.cpp +6 -10
- package/common/cpp/{core → audioapi/core/analysis}/AnalyserNode.h +4 -3
- package/common/cpp/{core → audioapi/core/destinations}/AudioDestinationNode.cpp +5 -5
- package/common/cpp/{core → audioapi/core/destinations}/AudioDestinationNode.h +2 -2
- package/common/cpp/{core → audioapi/core/effects}/BiquadFilterNode.cpp +4 -4
- package/common/cpp/{core → audioapi/core/effects}/BiquadFilterNode.h +4 -4
- package/common/cpp/{core → audioapi/core/effects}/GainNode.cpp +4 -4
- package/common/cpp/{core → audioapi/core/effects}/GainNode.h +3 -3
- package/common/cpp/{core → audioapi/core/effects}/PeriodicWave.cpp +4 -2
- package/common/cpp/{core → audioapi/core/effects}/PeriodicWave.h +2 -4
- package/common/cpp/{core → audioapi/core/effects}/StereoPannerNode.cpp +5 -7
- package/common/cpp/{core → audioapi/core/effects}/StereoPannerNode.h +4 -3
- package/common/cpp/{core → audioapi/core/effects}/StretcherNode.cpp +4 -6
- package/common/cpp/audioapi/core/effects/StretcherNode.h +35 -0
- package/common/cpp/{core → audioapi/core/sources}/AudioBuffer.cpp +3 -3
- package/common/cpp/{core → audioapi/core/sources}/AudioBufferSourceNode.cpp +8 -11
- package/common/cpp/{core → audioapi/core/sources}/AudioBufferSourceNode.h +5 -3
- package/common/cpp/{core → audioapi/core/sources}/AudioScheduledSourceNode.cpp +6 -8
- package/common/cpp/{core → audioapi/core/sources}/AudioScheduledSourceNode.h +3 -2
- package/common/cpp/{core → audioapi/core/sources}/OscillatorNode.cpp +4 -4
- package/common/cpp/{core → audioapi/core/sources}/OscillatorNode.h +5 -5
- package/common/cpp/{core → audioapi/core/utils}/AudioArray.cpp +2 -4
- package/common/cpp/{core → audioapi/core/utils}/AudioBus.cpp +4 -7
- package/common/cpp/{core → audioapi/core/utils}/AudioBus.h +2 -2
- package/common/cpp/{core → audioapi/core/utils}/AudioNodeManager.cpp +3 -4
- package/common/cpp/{core → audioapi/core/utils}/ParamChangeEvent.cpp +1 -3
- package/common/cpp/{core → audioapi/core/utils}/ParamChangeEvent.h +3 -1
- package/common/cpp/{utils → audioapi/dsp}/AudioUtils.cpp +1 -1
- package/common/cpp/{utils → audioapi/dsp}/FFTFrame.cpp +1 -10
- package/common/cpp/{utils → audioapi/dsp}/FFTFrame.h +4 -3
- package/common/cpp/{utils → audioapi/dsp}/VectorMath.cpp +2 -5
- package/common/cpp/{utils → audioapi/dsp}/VectorMath.h +2 -0
- package/common/cpp/{jsi → audioapi/jsi}/JsiHostObject.cpp +1 -1
- package/common/cpp/{jsi → audioapi/jsi}/JsiHostObject.h +2 -2
- package/common/cpp/{jsi → audioapi/jsi}/JsiPromise.cpp +2 -6
- package/common/cpp/{jsi → audioapi/jsi}/RuntimeAwareCache.h +2 -3
- package/common/cpp/{jsi → audioapi/jsi}/RuntimeLifecycleMonitor.cpp +1 -5
- package/common/cpp/{jsi → audioapi/jsi}/RuntimeLifecycleMonitor.h +3 -0
- package/common/cpp/{libs → audioapi/libs}/dsp/delay.h +35 -35
- package/common/cpp/{libs → audioapi/libs}/dsp/fft.h +21 -21
- package/common/cpp/{libs → audioapi/libs}/dsp/perf.h +3 -3
- package/common/cpp/{libs → audioapi/libs}/dsp/spectral.h +39 -39
- package/common/cpp/{libs → audioapi/libs}/dsp/windows.h +11 -11
- package/common/cpp/{libs → audioapi/libs}/signalsmith-stretch.h +30 -30
- package/ios/{AudioAPIModule.mm → audioapi/ios/AudioAPIModule.mm} +1 -1
- package/ios/{core → audioapi/ios/core}/AudioDecoder.mm +4 -4
- package/ios/{core → audioapi/ios/core}/AudioPlayer.m +1 -1
- package/ios/{core → audioapi/ios/core}/IOSAudioPlayer.mm +4 -4
- package/package.json +6 -6
- package/common/cpp/HostObjects/StretcherNodeHostObject.h +0 -35
- package/common/cpp/core/StretcherNode.h +0 -63
- package/common/cpp/libs/dsp/LICENSE.txt +0 -21
- package/common/cpp/libs/dsp/README.md +0 -40
- package/common/cpp/libs/dsp/curves.h +0 -371
- package/common/cpp/libs/dsp/envelopes.h +0 -523
- package/common/cpp/libs/dsp/filters.h +0 -436
- package/common/cpp/libs/dsp/mix.h +0 -218
- package/common/cpp/libs/dsp/rates.h +0 -184
- package/common/cpp/types/TimeStretchType.h +0 -6
- /package/android/src/main/cpp/{libs → audioapi/android/libs}/pffft.h +0 -0
- /package/common/cpp/{core → audioapi/core}/Constants.h +0 -0
- /package/common/cpp/{core → audioapi/core/sources}/AudioBuffer.h +0 -0
- /package/common/cpp/{types → audioapi/core/types}/BiquadFilterType.h +0 -0
- /package/common/cpp/{types → audioapi/core/types}/ChannelCountMode.h +0 -0
- /package/common/cpp/{types → audioapi/core/types}/ChannelInterpretation.h +0 -0
- /package/common/cpp/{types → audioapi/core/types}/ContextState.h +0 -0
- /package/common/cpp/{types → audioapi/core/types}/OscillatorType.h +0 -0
- /package/common/cpp/{types → audioapi/core/types}/ParamChangeEventType.h +0 -0
- /package/common/cpp/{core → audioapi/core/utils}/AudioArray.h +0 -0
- /package/common/cpp/{core → audioapi/core/utils}/AudioDecoder.h +0 -0
- /package/common/cpp/{core → audioapi/core/utils}/AudioNodeManager.h +0 -0
- /package/common/cpp/{utils → audioapi/core/utils}/Locker.h +0 -0
- /package/common/cpp/{utils → audioapi/dsp}/AudioUtils.h +0 -0
- /package/common/cpp/{jsi → audioapi/jsi}/JsiPromise.h +0 -0
- /package/common/cpp/{libs → audioapi/libs}/dsp/common.h +0 -0
- /package/common/cpp/{libs → audioapi/libs}/miniaudio.h +0 -0
- /package/ios/{AudioAPIModule.h → audioapi/ios/AudioAPIModule.h} +0 -0
- /package/ios/{core → audioapi/ios/core}/AudioPlayer.h +0 -0
- /package/ios/{core → audioapi/ios/core}/IOSAudioPlayer.h +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#include
|
|
1
|
+
#include <audioapi/libs/dsp/common.h>
|
|
2
2
|
|
|
3
3
|
#ifndef SIGNALSMITH_DSP_DELAY_H
|
|
4
4
|
#define SIGNALSMITH_DSP_DELAY_H
|
|
@@ -9,14 +9,14 @@
|
|
|
9
9
|
#include <type_traits>
|
|
10
10
|
|
|
11
11
|
#include <complex>
|
|
12
|
-
#include
|
|
13
|
-
#include
|
|
12
|
+
#include <audioapi/libs/dsp/fft.h>
|
|
13
|
+
#include <audioapi/libs/dsp/windows.h>
|
|
14
14
|
|
|
15
15
|
namespace signalsmith {
|
|
16
16
|
namespace delay {
|
|
17
17
|
/** @defgroup Delay Delay utilities
|
|
18
18
|
@brief Standalone templated classes for delays
|
|
19
|
-
|
|
19
|
+
|
|
20
20
|
You can set up a `Buffer` or `MultiBuffer`, and get interpolated samples using a `Reader` (separately on each channel in the multi-channel case) - or you can use `Delay`/`MultiDelay` which include their own buffers.
|
|
21
21
|
|
|
22
22
|
Interpolation quality is chosen using a template class, from @ref Interpolators.
|
|
@@ -26,13 +26,13 @@ namespace delay {
|
|
|
26
26
|
*/
|
|
27
27
|
|
|
28
28
|
/** @brief Single-channel delay buffer
|
|
29
|
-
|
|
29
|
+
|
|
30
30
|
Access is used with `buffer[]`, relative to the internal read/write position ("head"). This head is moved using `++buffer` (or `buffer += n`), such that `buffer[1] == (buffer + 1)[0]` in a similar way iterators/pointers.
|
|
31
|
-
|
|
31
|
+
|
|
32
32
|
Operations like `buffer - 10` or `buffer++` return a View, which holds a fixed position in the buffer (based on the read/write position at the time).
|
|
33
|
-
|
|
33
|
+
|
|
34
34
|
The capacity includes both positive and negative indices. For example, a capacity of 100 would support using any of the ranges:
|
|
35
|
-
|
|
35
|
+
|
|
36
36
|
* `buffer[-99]` to buffer[0]`
|
|
37
37
|
* `buffer[-50]` to buffer[49]`
|
|
38
38
|
* `buffer[0]` to buffer[99]`
|
|
@@ -81,7 +81,7 @@ namespace delay {
|
|
|
81
81
|
bufferIndex = other.bufferIndex;
|
|
82
82
|
return *this;
|
|
83
83
|
}
|
|
84
|
-
|
|
84
|
+
|
|
85
85
|
CSample & operator[](int offset) {
|
|
86
86
|
return buffer->buffer[(bufferIndex + (unsigned)offset)&buffer->bufferMask];
|
|
87
87
|
}
|
|
@@ -113,7 +113,7 @@ namespace delay {
|
|
|
113
113
|
};
|
|
114
114
|
using MutableView = View<false>;
|
|
115
115
|
using ConstView = View<true>;
|
|
116
|
-
|
|
116
|
+
|
|
117
117
|
MutableView view(int offset=0) {
|
|
118
118
|
return MutableView(*this, offset);
|
|
119
119
|
}
|
|
@@ -145,7 +145,7 @@ namespace delay {
|
|
|
145
145
|
data[i] = (*this)[i];
|
|
146
146
|
}
|
|
147
147
|
}
|
|
148
|
-
|
|
148
|
+
|
|
149
149
|
Buffer & operator ++() {
|
|
150
150
|
++bufferIndex;
|
|
151
151
|
return *this;
|
|
@@ -190,7 +190,7 @@ namespace delay {
|
|
|
190
190
|
/** @brief Multi-channel delay buffer
|
|
191
191
|
|
|
192
192
|
This behaves similarly to the single-channel `Buffer`, with the following differences:
|
|
193
|
-
|
|
193
|
+
|
|
194
194
|
* `buffer[c]` returns a view for a single channel, which behaves like the single-channel `Buffer::View`.
|
|
195
195
|
* The constructor and `.resize()` take an additional first `channel` argument.
|
|
196
196
|
*/
|
|
@@ -223,7 +223,7 @@ namespace delay {
|
|
|
223
223
|
public:
|
|
224
224
|
Stride(CChannel view, int channels, int stride) : view(view), channels(channels), stride(stride) {}
|
|
225
225
|
Stride(const Stride &other) : view(other.view), channels(other.channels), stride(other.stride) {}
|
|
226
|
-
|
|
226
|
+
|
|
227
227
|
CSample & operator[](int channel) {
|
|
228
228
|
return view[channel*stride];
|
|
229
229
|
}
|
|
@@ -255,7 +255,7 @@ namespace delay {
|
|
|
255
255
|
return *this;
|
|
256
256
|
}
|
|
257
257
|
};
|
|
258
|
-
|
|
258
|
+
|
|
259
259
|
Stride<false> at(int offset) {
|
|
260
260
|
return {buffer.view(offset), channels, stride};
|
|
261
261
|
}
|
|
@@ -271,7 +271,7 @@ namespace delay {
|
|
|
271
271
|
int channels, stride;
|
|
272
272
|
public:
|
|
273
273
|
View(CChannel view, int channels, int stride) : view(view), channels(channels), stride(stride) {}
|
|
274
|
-
|
|
274
|
+
|
|
275
275
|
CChannel operator[](int channel) {
|
|
276
276
|
return view + channel*stride;
|
|
277
277
|
}
|
|
@@ -305,7 +305,7 @@ namespace delay {
|
|
|
305
305
|
ConstChannel operator[](int channel) const {
|
|
306
306
|
return buffer + channel*stride;
|
|
307
307
|
}
|
|
308
|
-
|
|
308
|
+
|
|
309
309
|
MultiBuffer & operator ++() {
|
|
310
310
|
++buffer;
|
|
311
311
|
return *this;
|
|
@@ -341,7 +341,7 @@ namespace delay {
|
|
|
341
341
|
return ConstView(buffer - i, channels, stride);
|
|
342
342
|
}
|
|
343
343
|
};
|
|
344
|
-
|
|
344
|
+
|
|
345
345
|
/** \defgroup Interpolators Interpolators
|
|
346
346
|
\ingroup Delay
|
|
347
347
|
@{ */
|
|
@@ -351,7 +351,7 @@ namespace delay {
|
|
|
351
351
|
struct InterpolatorNearest {
|
|
352
352
|
static constexpr int inputLength = 1;
|
|
353
353
|
static constexpr Sample latency = -0.5; // Because we're truncating, which rounds down too often
|
|
354
|
-
|
|
354
|
+
|
|
355
355
|
template<class Data>
|
|
356
356
|
static Sample fractional(const Data &data, Sample) {
|
|
357
357
|
return data[0];
|
|
@@ -363,7 +363,7 @@ namespace delay {
|
|
|
363
363
|
struct InterpolatorLinear {
|
|
364
364
|
static constexpr int inputLength = 2;
|
|
365
365
|
static constexpr int latency = 0;
|
|
366
|
-
|
|
366
|
+
|
|
367
367
|
template<class Data>
|
|
368
368
|
static Sample fractional(const Data &data, Sample fractional) {
|
|
369
369
|
Sample a = data[0], b = data[1];
|
|
@@ -376,7 +376,7 @@ namespace delay {
|
|
|
376
376
|
struct InterpolatorCubic {
|
|
377
377
|
static constexpr int inputLength = 4;
|
|
378
378
|
static constexpr int latency = 1;
|
|
379
|
-
|
|
379
|
+
|
|
380
380
|
template<class Data>
|
|
381
381
|
static Sample fractional(const Data &data, Sample fractional) {
|
|
382
382
|
// Cubic interpolation
|
|
@@ -477,7 +477,7 @@ namespace delay {
|
|
|
477
477
|
|
|
478
478
|
int subSampleSteps;
|
|
479
479
|
std::vector<Sample> coefficients;
|
|
480
|
-
|
|
480
|
+
|
|
481
481
|
InterpolatorKaiserSincN() : InterpolatorKaiserSincN(0.5 - 0.45/std::sqrt(n)) {}
|
|
482
482
|
InterpolatorKaiserSincN(double passFreq) : InterpolatorKaiserSincN(passFreq, 1 - passFreq) {}
|
|
483
483
|
InterpolatorKaiserSincN(double passFreq, double stopFreq) {
|
|
@@ -488,7 +488,7 @@ namespace delay {
|
|
|
488
488
|
|
|
489
489
|
double centreIndex = n*subSampleSteps*0.5, scaleFactor = 1.0/subSampleSteps;
|
|
490
490
|
std::vector<Sample> windowedSinc(subSampleSteps*n + 1);
|
|
491
|
-
|
|
491
|
+
|
|
492
492
|
::signalsmith::windows::Kaiser::withBandwidth(kaiserBandwidth, false).fill(windowedSinc, windowedSinc.size());
|
|
493
493
|
|
|
494
494
|
for (size_t i = 0; i < windowedSinc.size(); ++i) {
|
|
@@ -502,7 +502,7 @@ namespace delay {
|
|
|
502
502
|
windowedSinc[i] *= std::sin(p)/p;
|
|
503
503
|
}
|
|
504
504
|
}
|
|
505
|
-
|
|
505
|
+
|
|
506
506
|
if (minimumPhase) {
|
|
507
507
|
signalsmith::fft::FFT<Sample> fft(windowedSinc.size()*2, 1);
|
|
508
508
|
windowedSinc.resize(fft.size(), 0);
|
|
@@ -534,7 +534,7 @@ namespace delay {
|
|
|
534
534
|
windowedSinc[i] = cepstrum[i].real()*scaling;
|
|
535
535
|
}
|
|
536
536
|
}
|
|
537
|
-
|
|
537
|
+
|
|
538
538
|
// Re-order into FIR fractional-delay blocks
|
|
539
539
|
coefficients.resize(n*(subSampleSteps + 1));
|
|
540
540
|
for (int k = 0; k <= subSampleSteps; ++k) {
|
|
@@ -543,7 +543,7 @@ namespace delay {
|
|
|
543
543
|
}
|
|
544
544
|
}
|
|
545
545
|
}
|
|
546
|
-
|
|
546
|
+
|
|
547
547
|
template<class Data>
|
|
548
548
|
Sample fractional(const Data &data, Sample fractional) const {
|
|
549
549
|
Sample subSampleDelay = fractional*subSampleSteps;
|
|
@@ -551,7 +551,7 @@ namespace delay {
|
|
|
551
551
|
if (lowIndex >= subSampleSteps) lowIndex = subSampleSteps - 1;
|
|
552
552
|
Sample subSampleFractional = subSampleDelay - lowIndex;
|
|
553
553
|
int highIndex = lowIndex + 1;
|
|
554
|
-
|
|
554
|
+
|
|
555
555
|
Sample sumLow = 0, sumHigh = 0;
|
|
556
556
|
const Sample *coeffLow = coefficients.data() + lowIndex*n;
|
|
557
557
|
const Sample *coeffHigh = coefficients.data() + highIndex*n;
|
|
@@ -577,9 +577,9 @@ namespace delay {
|
|
|
577
577
|
template<typename Sample>
|
|
578
578
|
using InterpolatorKaiserSinc4Min = InterpolatorKaiserSincN<Sample, 4, true>;
|
|
579
579
|
/// @}
|
|
580
|
-
|
|
580
|
+
|
|
581
581
|
/** @brief A delay-line reader which uses an external buffer
|
|
582
|
-
|
|
582
|
+
|
|
583
583
|
This is useful if you have multiple delay-lines reading from the same buffer.
|
|
584
584
|
*/
|
|
585
585
|
template<class Sample, template<typename> class Interpolator=InterpolatorLinear>
|
|
@@ -589,12 +589,12 @@ namespace delay {
|
|
|
589
589
|
Reader () {}
|
|
590
590
|
/// Pass in a configured interpolator
|
|
591
591
|
Reader (const Interpolator<Sample> &interpolator) : Super(interpolator) {}
|
|
592
|
-
|
|
592
|
+
|
|
593
593
|
template<typename Buffer>
|
|
594
594
|
Sample read(const Buffer &buffer, Sample delaySamples) const {
|
|
595
595
|
int startIndex = delaySamples;
|
|
596
596
|
Sample remainder = delaySamples - startIndex;
|
|
597
|
-
|
|
597
|
+
|
|
598
598
|
// Delay buffers use negative indices, but interpolators use positive ones
|
|
599
599
|
using View = decltype(buffer - startIndex);
|
|
600
600
|
struct Flipped {
|
|
@@ -618,14 +618,14 @@ namespace delay {
|
|
|
618
618
|
Delay(int capacity=0) : buffer(1 + capacity + Super::inputLength) {}
|
|
619
619
|
/// Pass in a configured interpolator
|
|
620
620
|
Delay(const Interpolator<Sample> &interp, int capacity=0) : Super(interp), buffer(1 + capacity + Super::inputLength) {}
|
|
621
|
-
|
|
621
|
+
|
|
622
622
|
void reset(Sample value=Sample()) {
|
|
623
623
|
buffer.reset(value);
|
|
624
624
|
}
|
|
625
625
|
void resize(int minCapacity, Sample value=Sample()) {
|
|
626
626
|
buffer.resize(minCapacity + Super::inputLength, value);
|
|
627
627
|
}
|
|
628
|
-
|
|
628
|
+
|
|
629
629
|
/** Read a sample from `delaySamples` >= 0 in the past.
|
|
630
630
|
The interpolator may add its own latency on top of this (see `Delay::latency`). The default interpolation (linear) has 0 latency.
|
|
631
631
|
*/
|
|
@@ -658,14 +658,14 @@ namespace delay {
|
|
|
658
658
|
channels = nChannels;
|
|
659
659
|
multiBuffer.resize(channels, capacity + Super::inputLength, value);
|
|
660
660
|
}
|
|
661
|
-
|
|
661
|
+
|
|
662
662
|
/// A single-channel delay-line view, similar to a `const Delay`
|
|
663
663
|
struct ChannelView {
|
|
664
664
|
static constexpr Sample latency = Super::latency;
|
|
665
665
|
|
|
666
666
|
const Super &reader;
|
|
667
667
|
typename MultiBuffer<Sample>::ConstChannel channel;
|
|
668
|
-
|
|
668
|
+
|
|
669
669
|
Sample read(Sample delaySamples) const {
|
|
670
670
|
return reader.read(channel, delaySamples);
|
|
671
671
|
}
|
|
@@ -679,7 +679,7 @@ namespace delay {
|
|
|
679
679
|
Super &reader;
|
|
680
680
|
typename MultiBuffer<Sample>::ConstView view;
|
|
681
681
|
Sample delaySamples;
|
|
682
|
-
|
|
682
|
+
|
|
683
683
|
// Calculate samples on-the-fly
|
|
684
684
|
Sample operator [](int c) const {
|
|
685
685
|
return reader.read(view[c], delaySamples);
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
#include
|
|
1
|
+
#include <audioapi/libs/dsp/common.h>
|
|
2
2
|
|
|
3
3
|
#ifndef SIGNALSMITH_FFT_V5
|
|
4
4
|
#define SIGNALSMITH_FFT_V5
|
|
5
5
|
|
|
6
|
-
#include
|
|
6
|
+
#include <audioapi/libs/dsp/perf.h>
|
|
7
7
|
|
|
8
8
|
#include <vector>
|
|
9
9
|
#include <complex>
|
|
@@ -80,7 +80,7 @@ namespace signalsmith { namespace fft {
|
|
|
80
80
|
using complex = std::complex<V>;
|
|
81
81
|
size_t _size;
|
|
82
82
|
std::vector<complex> workingVector;
|
|
83
|
-
|
|
83
|
+
|
|
84
84
|
enum class StepType {
|
|
85
85
|
generic, step2, step3, step4
|
|
86
86
|
};
|
|
@@ -95,13 +95,13 @@ namespace signalsmith { namespace fft {
|
|
|
95
95
|
std::vector<size_t> factors;
|
|
96
96
|
std::vector<Step> plan;
|
|
97
97
|
std::vector<complex> twiddleVector;
|
|
98
|
-
|
|
98
|
+
|
|
99
99
|
struct PermutationPair {size_t from, to;};
|
|
100
100
|
std::vector<PermutationPair> permutation;
|
|
101
|
-
|
|
101
|
+
|
|
102
102
|
void addPlanSteps(size_t factorIndex, size_t start, size_t length, size_t repeats) {
|
|
103
103
|
if (factorIndex >= factors.size()) return;
|
|
104
|
-
|
|
104
|
+
|
|
105
105
|
size_t factor = factors[factorIndex];
|
|
106
106
|
if (factorIndex + 1 < factors.size()) {
|
|
107
107
|
if (factors[factorIndex] == 2 && factors[factorIndex + 1] == 2) {
|
|
@@ -163,7 +163,7 @@ namespace signalsmith { namespace fft {
|
|
|
163
163
|
twiddleVector.resize(0);
|
|
164
164
|
addPlanSteps(0, 0, _size, 1);
|
|
165
165
|
twiddleVector.shrink_to_fit();
|
|
166
|
-
|
|
166
|
+
|
|
167
167
|
permutation.resize(0);
|
|
168
168
|
permutation.reserve(_size);
|
|
169
169
|
permutation.push_back(PermutationPair{0, 0});
|
|
@@ -202,7 +202,7 @@ namespace signalsmith { namespace fft {
|
|
|
202
202
|
|
|
203
203
|
for (size_t outerRepeat = 0; outerRepeat < step.outerRepeats; ++outerRepeat) {
|
|
204
204
|
RandomAccessIterator data = origData;
|
|
205
|
-
|
|
205
|
+
|
|
206
206
|
const complex *twiddles = twiddleVector.data() + step.twiddleIndex;
|
|
207
207
|
const size_t factor = step.factor;
|
|
208
208
|
for (size_t repeat = 0; repeat < step.innerRepeats; ++repeat) {
|
|
@@ -234,7 +234,7 @@ namespace signalsmith { namespace fft {
|
|
|
234
234
|
for (RandomAccessIterator data = origData; data < origData + stride; ++data) {
|
|
235
235
|
complex A = data[0];
|
|
236
236
|
complex B = _fft_impl::complexMul<inverse>(data[stride], twiddles[1]);
|
|
237
|
-
|
|
237
|
+
|
|
238
238
|
data[0] = A + B;
|
|
239
239
|
data[stride] = A - B;
|
|
240
240
|
twiddles += 2;
|
|
@@ -248,14 +248,14 @@ namespace signalsmith { namespace fft {
|
|
|
248
248
|
constexpr complex factor3 = {-0.5, inverse ? 0.8660254037844386 : -0.8660254037844386};
|
|
249
249
|
const size_t stride = step.innerRepeats;
|
|
250
250
|
const complex *origTwiddles = twiddleVector.data() + step.twiddleIndex;
|
|
251
|
-
|
|
251
|
+
|
|
252
252
|
for (size_t outerRepeat = 0; outerRepeat < step.outerRepeats; ++outerRepeat) {
|
|
253
253
|
const complex* twiddles = origTwiddles;
|
|
254
254
|
for (RandomAccessIterator data = origData; data < origData + stride; ++data) {
|
|
255
255
|
complex A = data[0];
|
|
256
256
|
complex B = _fft_impl::complexMul<inverse>(data[stride], twiddles[1]);
|
|
257
257
|
complex C = _fft_impl::complexMul<inverse>(data[stride*2], twiddles[2]);
|
|
258
|
-
|
|
258
|
+
|
|
259
259
|
complex realSum = A + (B + C)*factor3.real();
|
|
260
260
|
complex imagSum = (B - C)*factor3.imag();
|
|
261
261
|
|
|
@@ -273,7 +273,7 @@ namespace signalsmith { namespace fft {
|
|
|
273
273
|
SIGNALSMITH_INLINE void fftStep4(RandomAccessIterator &&origData, const Step &step) {
|
|
274
274
|
const size_t stride = step.innerRepeats;
|
|
275
275
|
const complex *origTwiddles = twiddleVector.data() + step.twiddleIndex;
|
|
276
|
-
|
|
276
|
+
|
|
277
277
|
for (size_t outerRepeat = 0; outerRepeat < step.outerRepeats; ++outerRepeat) {
|
|
278
278
|
const complex* twiddles = origTwiddles;
|
|
279
279
|
for (RandomAccessIterator data = origData; data < origData + stride; ++data) {
|
|
@@ -295,7 +295,7 @@ namespace signalsmith { namespace fft {
|
|
|
295
295
|
origData += 4*stride;
|
|
296
296
|
}
|
|
297
297
|
}
|
|
298
|
-
|
|
298
|
+
|
|
299
299
|
template<typename InputIterator, typename OutputIterator>
|
|
300
300
|
void permute(InputIterator input, OutputIterator data) {
|
|
301
301
|
for (auto pair : permutation) {
|
|
@@ -306,7 +306,7 @@ namespace signalsmith { namespace fft {
|
|
|
306
306
|
template<bool inverse, typename InputIterator, typename OutputIterator>
|
|
307
307
|
void run(InputIterator &&input, OutputIterator &&data) {
|
|
308
308
|
permute(input, data);
|
|
309
|
-
|
|
309
|
+
|
|
310
310
|
for (const Step &step : plan) {
|
|
311
311
|
switch (step.type) {
|
|
312
312
|
case StepType::generic:
|
|
@@ -441,7 +441,7 @@ namespace signalsmith { namespace fft {
|
|
|
441
441
|
modifiedRotations[i] = {std::cos(rotPhase), std::sin(rotPhase)};
|
|
442
442
|
}
|
|
443
443
|
}
|
|
444
|
-
|
|
444
|
+
|
|
445
445
|
return complexFft.setSize(size/2);
|
|
446
446
|
}
|
|
447
447
|
size_t setFastSizeAbove(size_t size) {
|
|
@@ -464,16 +464,16 @@ namespace signalsmith { namespace fft {
|
|
|
464
464
|
complexBuffer1[i] = {input[2*i], input[2*i + 1]};
|
|
465
465
|
}
|
|
466
466
|
}
|
|
467
|
-
|
|
467
|
+
|
|
468
468
|
complexFft.fft(complexBuffer1.data(), complexBuffer2.data());
|
|
469
|
-
|
|
469
|
+
|
|
470
470
|
if (!modified) output[0] = {
|
|
471
471
|
complexBuffer2[0].real() + complexBuffer2[0].imag(),
|
|
472
472
|
complexBuffer2[0].real() - complexBuffer2[0].imag()
|
|
473
473
|
};
|
|
474
474
|
for (size_t i = modified ? 0 : 1; i <= hSize/2; ++i) {
|
|
475
475
|
size_t conjI = modified ? (hSize - 1 - i) : (hSize - i);
|
|
476
|
-
|
|
476
|
+
|
|
477
477
|
complex odd = (complexBuffer2[i] + conj(complexBuffer2[conjI]))*(V)0.5;
|
|
478
478
|
complex evenI = (complexBuffer2[i] - conj(complexBuffer2[conjI]))*(V)0.5;
|
|
479
479
|
complex evenRotMinusI = _fft_impl::complexMul<false>(evenI, twiddlesMinusI[i]);
|
|
@@ -497,13 +497,13 @@ namespace signalsmith { namespace fft {
|
|
|
497
497
|
complex odd = v + conj(v2);
|
|
498
498
|
complex evenRotMinusI = v - conj(v2);
|
|
499
499
|
complex evenI = _fft_impl::complexMul<true>(evenRotMinusI, twiddlesMinusI[i]);
|
|
500
|
-
|
|
500
|
+
|
|
501
501
|
complexBuffer1[i] = odd + evenI;
|
|
502
502
|
complexBuffer1[conjI] = conj(odd - evenI);
|
|
503
503
|
}
|
|
504
|
-
|
|
504
|
+
|
|
505
505
|
complexFft.ifft(complexBuffer1.data(), complexBuffer2.data());
|
|
506
|
-
|
|
506
|
+
|
|
507
507
|
for (size_t i = 0; i < hSize; ++i) {
|
|
508
508
|
complex v = complexBuffer2[i];
|
|
509
509
|
if (modified) v = _fft_impl::complexMul<true>(v, modifiedRotations[i]);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#include
|
|
1
|
+
#include <audioapi/libs/dsp/common.h>
|
|
2
2
|
|
|
3
3
|
#ifndef SIGNALSMITH_DSP_PERF_H
|
|
4
4
|
#define SIGNALSMITH_DSP_PERF_H
|
|
@@ -15,11 +15,11 @@ namespace signalsmith {
|
|
|
15
15
|
namespace perf {
|
|
16
16
|
/** @defgroup Performance Performance helpers
|
|
17
17
|
@brief Nothing serious, just some `#defines` and helpers
|
|
18
|
-
|
|
18
|
+
|
|
19
19
|
@{
|
|
20
20
|
@file
|
|
21
21
|
*/
|
|
22
|
-
|
|
22
|
+
|
|
23
23
|
/// *Really* insist that a function/method is inlined (mostly for performance in DEBUG builds)
|
|
24
24
|
#ifndef SIGNALSMITH_INLINE
|
|
25
25
|
#ifdef __GNUC__
|