12#include "../AudioBuffer.h"
13#include "../Convolver.h"
14#include "../FIRFilter.h"
27 int factor_, latency_ = 0;
41 return factor >= 1 && factor <= 16 && (factor & (factor - 1)) == 0 &&
42 settings.filterSpan >= 2 && settings.filterSpan <= 65536 &&
43 (settings.filterSpan & 1) == 0 && settings.partitionFrames >= 16 &&
44 settings.partitionFrames <= 4096 &&
45 (settings.partitionFrames & (settings.partitionFrames - 1)) == 0 &&
46 std::isfinite(settings.beta) && settings.beta >= 0 && settings.beta <= 30 &&
47 std::isfinite(settings.cutoff) && settings.cutoff > 0 && settings.cutoff <= 0.5;
53 bool withReference)
noexcept
55 assert(
valid(factor, settings));
56 const auto buffers =
static_cast<std::size_t
>(withReference ? 2 : 1);
57 const auto storage = buffers * 256 *
static_cast<std::size_t
>(factor) *
sizeof(
double);
60 const auto block =
static_cast<std::size_t
>(settings.partitionFrames * factor);
61 const auto length =
static_cast<std::size_t
>(settings.filterSpan * factor + 1);
62 return storage + 6 * (length *
sizeof(double) + 64) +
68 std::size_t length)
noexcept
70 const auto partitions = (length + block - 1) / block;
71 return ((4 * partitions + 17) * block + 4 * partitions + 2) *
sizeof(
double) +
72 2 * partitions *
sizeof(std::vector<double>) +
sizeof(
FFTReal<double>) + 2048 +
73 (2 * partitions + 12) * 64;
77 : factor_(factor), withReference_(withReference)
79 assert(
valid(factor, settings));
80 buffer_.
resize(1, 256 * factor);
82 reference_.
resize(1, 256 * factor);
86 const int length = settings.
filterSpan * factor + 1;
89 for (
auto &value : up)
91 up_.prepare(block, up.data(), length);
93 referenceUp_.prepare(block, up.data(), length);
94 down_.prepare(block, down.data(), length);
95 latency_ = (length - 1 + 2 * block) / factor;
98 [[nodiscard]]
int latency() const noexcept
106 referenceUp_.reset();
112 assert(withReference_ && count >= 0 && count <= 256);
114 std::fill_n(out, count * factor_, 0.);
115 for (
int i = 0; i < count; ++i)
116 out[i * factor_] = input[i];
118 referenceUp_.processInPlace(out, count * factor_);
124 const int count = input.getNumSamples();
125 assert(input.getNumChannels() == 1 && count <= 256);
127 std::fill_n(out, count * factor_, 0.);
128 for (
int i = 0; i < count; ++i)
129 out[i * factor_] = input.getChannel(0)[i];
131 up_.processInPlace(out, count * factor_);
132 return buffer_.
toView().getSubView(0, count * factor_);
137 const int count = output.getNumSamples();
138 assert(output.getNumChannels() == 1 && count <= 256);
141 down_.processInPlace(data, count * factor_);
142 for (
int i = 0; i < count; ++i)
143 output.getChannel(0)[i] = data[i * factor_];
Non-owning view over audio channel data.
Owning audio buffer with contiguous, 32-byte aligned storage.
AudioBufferView< T, MaxChannels > toView() noexcept
Returns a non-owning mutable view of this buffer. The view's channel capacity is propagated from MaxC...
T * getChannel(int ch) noexcept
Returns a pointer to the sample data.
void resize(int numChannels, int numSamples)
Allocates the buffer for the given dimensions.
Real-time partitioned convolution using overlap-save with FFT.
FFT optimised for real-valued input signals (the common audio case).
static std::vector< T > lowPass(double sampleRate, double cutoffHz, int numTaps, T beta=T(5))
Designs a low-pass FIR filter.
int latency() const noexcept
static std::size_t allocationBound(int factor, Settings settings, bool withReference) noexcept
AudioBufferView< double > upsample(AudioBufferView< double > input) noexcept
double * upsampleReference(const double *input, int count) noexcept
static bool valid(int factor, Settings settings) noexcept
static std::size_t convolutionAllocationBound(std::size_t block, std::size_t length) noexcept
ConvolutionRate(int factor, Settings settings, bool withReference)
void downsample(AudioBufferView< double > output) noexcept