From f7a54a54e46d8875f915e274924826c8ec215abb Mon Sep 17 00:00:00 2001 From: John Funnell Date: Sat, 19 Oct 2024 22:52:12 +0100 Subject: [PATCH] per-Bungee-instance FFT cache --- src/Basic.cpp | 9 +++++---- src/Basic.h | 4 +++- src/Fourier.cpp | 8 ++------ src/Fourier.h | 32 +++++++++----------------------- src/Input.cpp | 6 +++--- src/Input.h | 3 ++- src/Output.cpp | 6 +++--- src/Output.h | 2 +- src/Window.cpp | 6 +++--- src/Window.h | 3 ++- 10 files changed, 33 insertions(+), 46 deletions(-) diff --git a/src/Basic.cpp b/src/Basic.cpp index 0553dbe..890802e 100644 --- a/src/Basic.cpp +++ b/src/Basic.cpp @@ -36,9 +36,10 @@ bool Stretcher::isFlushed() const Basic::Basic(SampleRates sampleRates, int channelCount, int log2SynthesisHopOverride) : Timing(sampleRates, log2SynthesisHopOverride), - input(log2SynthesisHop, channelCount), + transforms(Fourier::transforms()), + input(log2SynthesisHop, channelCount, *transforms), grains(4), - output(log2SynthesisHop, channelCount, maxOutputFrameCount(true), 0.25f, {1.f, 0.5f}) + output(*transforms, log2SynthesisHop, channelCount, maxOutputFrameCount(true), 0.25f, {1.f, 0.5f}) { for (auto &grain : grains.vector) grain = std::make_unique(log2SynthesisHop, channelCount); @@ -68,7 +69,7 @@ void Basic::analyseGrain(const float *data, std::ptrdiff_t stride) auto log2TransformLength = input.applyAnalysisWindow(ref); - Fourier::transforms->forward(log2TransformLength, input.windowedInput, grain.transformed); + transforms->forward(log2TransformLength, input.windowedInput, grain.transformed); const auto n = Fourier::binCount(grain.log2TransformLength) - 1; grain.validBinCount = std::min(std::ceil(n / grain.resampleOperations.output.ratio), n) + 1; @@ -112,7 +113,7 @@ void Basic::synthesiseGrain(OutputChunk &outputChunk) else grain.transformed.topRows(grain.validBinCount).colwise() *= t; - Fourier::transforms->inverse(grain.log2TransformLength, output.inverseTransformed, grain.transformed); + transforms->inverse(grain.log2TransformLength, output.inverseTransformed, grain.transformed); } output.applySynthesisWindow(log2SynthesisHop, grains, output.synthesisWindow); diff --git a/src/Basic.h b/src/Basic.h index 1e666db..704a11d 100644 --- a/src/Basic.h +++ b/src/Basic.h @@ -9,12 +9,14 @@ #include "Output.h" #include "Timing.h" +#include + namespace Bungee { struct Basic : - Fourier::Bootstrap, Timing { + std::unique_ptr transforms; Input input; Grains grains; Output output; diff --git a/src/Fourier.cpp b/src/Fourier.cpp index ae093dd..10246da 100644 --- a/src/Fourier.cpp +++ b/src/Fourier.cpp @@ -57,13 +57,9 @@ void Kiss::Kernel::inverse(int, float *t, std::complex *f) con kiss_fftri((kiss_fftr_cfg)implementation, (kiss_fft_cpx *)f, t); } -Transforms *transforms{}; - -Bootstrap::Bootstrap() +std::unique_ptr transforms() { - BUNGEE_ASSERT1(!transforms); - static Fourier::Cache cache; - BUNGEE_ASSERT1(transforms == &cache); + return std::make_unique>(); } } // namespace Bungee::Fourier diff --git a/src/Fourier.h b/src/Fourier.h index ba7ae91..27e22e6 100644 --- a/src/Fourier.h +++ b/src/Fourier.h @@ -11,7 +11,6 @@ #include #include #include -#include #include namespace Bungee { @@ -68,14 +67,12 @@ inline void resize(int log2TransformLength, int channelCount, T &array, int extr struct Transforms { virtual ~Transforms() {} - virtual void prepareForward(int log2Length) = 0; - virtual void prepareInverse(int log2Length) = 0; + virtual void prepareForward(int log2TransformLength) = 0; + virtual void prepareInverse(int log2TransformLength) = 0; virtual void forward(int log2TransformLength, const Eigen::Ref &t, Eigen::Ref f) const = 0; virtual void inverse(int log2TransformLength, Eigen::Ref t, const Eigen::Ref &f) const = 0; }; -extern Transforms *transforms; - // General case when an FFT implementation has different states for forward and reverse transforms of same size. template struct KernelPair @@ -129,27 +126,19 @@ struct Cache : { typedef KernelPair Entry; typedef std::array Table; - std::mutex preparationMutex; Table table; - Cache() - { - transforms = this; - } - - void prepareForward(int log2Length) override + void prepareForward(int log2TransformLength) override { - std::scoped_lock lock(preparationMutex); - if (!table[log2Length].forward()) - table[log2Length].forward(new typename K::Forward(log2Length)); + if (!table[log2TransformLength].forward()) + table[log2TransformLength].forward(new typename K::Forward(log2TransformLength)); } - void prepareInverse(int log2Length) override + void prepareInverse(int log2TransformLength) override { - std::scoped_lock lock(preparationMutex); - if (!table[log2Length].inverse()) - table[log2Length].inverse(new typename K::Inverse(log2Length)); + if (!table[log2TransformLength].inverse()) + table[log2TransformLength].inverse(new typename K::Inverse(log2TransformLength)); } void forward(int log2TransformLength, const Eigen::Ref &t, Eigen::Ref f) const override @@ -177,9 +166,6 @@ struct Cache : } }; -struct Bootstrap -{ - Bootstrap(); -}; +std::unique_ptr transforms(); } // namespace Bungee::Fourier diff --git a/src/Input.cpp b/src/Input.cpp index 6f7309c..b714a15 100644 --- a/src/Input.cpp +++ b/src/Input.cpp @@ -14,12 +14,12 @@ static constexpr float pi = std::numbers::pi_v; static constexpr float gain = (3 * pi) / (3 * pi + 8); } // namespace -Input::Input(int log2SynthesisHop, int channelCount) : - analysisWindowBasic(Window::fromFrequencyDomainCoefficients(log2SynthesisHop + 3, gain / (8 << log2SynthesisHop), {1.f, 0.5f})), +Input::Input(int log2SynthesisHop, int channelCount, Fourier::Transforms &transforms) : + analysisWindowBasic(Window::fromFrequencyDomainCoefficients(transforms, log2SynthesisHop + 3, gain / (8 << log2SynthesisHop), {1.f, 0.5f})), windowedInput{(8 << log2SynthesisHop), channelCount} { windowedInput.setZero(); - Fourier::transforms->prepareForward(log2SynthesisHop + 3); + transforms.prepareForward(log2SynthesisHop + 3); } int Input::applyAnalysisWindow(const Eigen::Ref &input) diff --git a/src/Input.h b/src/Input.h index 00be666..c0b8f54 100644 --- a/src/Input.h +++ b/src/Input.h @@ -4,6 +4,7 @@ #pragma once #include "Assert.h" +#include "Fourier.h" #include @@ -14,7 +15,7 @@ struct Input Eigen::ArrayXf analysisWindowBasic; Eigen::ArrayXXf windowedInput; - Input(int log2SynthesisHop, int channelCount); + Input(int log2SynthesisHop, int channelCount, Fourier::Transforms &transforms); int applyAnalysisWindow(const Eigen::Ref &input); }; diff --git a/src/Output.cpp b/src/Output.cpp index 4b9d5ca..12b0f8d 100644 --- a/src/Output.cpp +++ b/src/Output.cpp @@ -7,12 +7,12 @@ namespace Bungee { -Output::Output(int log2SynthesisHop, int channelCount, int maxOutputChunkSize, float windowGain, std::initializer_list windowCoefficients) : - synthesisWindow{Window::fromFrequencyDomainCoefficients(log2SynthesisHop + 2, windowGain, windowCoefficients)}, +Output::Output(Fourier::Transforms &transforms, int log2SynthesisHop, int channelCount, int maxOutputChunkSize, float windowGain, std::initializer_list windowCoefficients) : + synthesisWindow{Window::fromFrequencyDomainCoefficients(transforms, log2SynthesisHop + 2, windowGain, windowCoefficients)}, inverseTransformed(8 << log2SynthesisHop, channelCount), bufferResampled(maxOutputChunkSize, channelCount) { - Fourier::transforms->prepareInverse(log2SynthesisHop + 3); + transforms.prepareInverse(log2SynthesisHop + 3); } void Output::applySynthesisWindow(int log2SynthesisHop, Grains &grains, const Eigen::Ref &window) diff --git a/src/Output.h b/src/Output.h index 291ed54..e36fe89 100644 --- a/src/Output.h +++ b/src/Output.h @@ -25,7 +25,7 @@ struct Output float resampleOffset = 0.f; Window::DispatchApply dispatchApply; - Output(int log2SynthesisHop, int channelCount, int maxOutputChunkSize, float windowGain, std::initializer_list windowCoefficients); + Output(Fourier::Transforms &transforms, int log2SynthesisHop, int channelCount, int maxOutputChunkSize, float windowGain, std::initializer_list windowCoefficients); void applySynthesisWindow(int log2SynthesisHop, Grains &grains, const Eigen::Ref &window); diff --git a/src/Window.cpp b/src/Window.cpp index 19fd790..ebccdfd 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -11,7 +11,7 @@ namespace Bungee::Window { -Eigen::ArrayXf fromFrequencyDomainCoefficients(int log2Size, float gain, std::initializer_list coefficients) +Eigen::ArrayXf fromFrequencyDomainCoefficients(Fourier::Transforms &transforms, int log2Size, float gain, std::initializer_list coefficients) { Eigen::ArrayXcf frequencyDomain(Fourier::binCount(log2Size)); @@ -22,8 +22,8 @@ Eigen::ArrayXf fromFrequencyDomainCoefficients(int log2Size, float gain, std::in frequencyDomain.bottomRows(frequencyDomain.rows() - i).setZero(); Eigen::ArrayXf window(1 << log2Size); - Fourier::transforms->prepareInverse(log2Size); - Fourier::transforms->inverse(log2Size, window, frequencyDomain); + transforms.prepareInverse(log2Size); + transforms.inverse(log2Size, window, frequencyDomain); return window; } diff --git a/src/Window.h b/src/Window.h index 87093f7..c2cb85c 100644 --- a/src/Window.h +++ b/src/Window.h @@ -5,6 +5,7 @@ #include "Assert.h" #include "Dispatch.h" +#include "Fourier.h" #include @@ -12,7 +13,7 @@ namespace Bungee::Window { -Eigen::ArrayXf fromFrequencyDomainCoefficients(int log2Size, float gain, std::initializer_list coefficients); +Eigen::ArrayXf fromFrequencyDomainCoefficients(Fourier::Transforms &transforms, int log2Size, float gain, std::initializer_list coefficients); struct Apply {