mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
FFT: Add IPP implementation
This commit is contained in:
parent
f20b93a458
commit
9fa6c195ee
2 changed files with 147 additions and 2 deletions
|
|
@ -23,7 +23,7 @@ namespace dsp
|
||||||
|
|
||||||
struct FFT::Instance
|
struct FFT::Instance
|
||||||
{
|
{
|
||||||
virtual ~Instance() {}
|
virtual ~Instance() = default;
|
||||||
virtual void perform (const Complex<float>* input, Complex<float>* output, bool inverse) const noexcept = 0;
|
virtual void perform (const Complex<float>* input, Complex<float>* output, bool inverse) const noexcept = 0;
|
||||||
virtual void performRealOnlyForwardTransform (float*, bool) const noexcept = 0;
|
virtual void performRealOnlyForwardTransform (float*, bool) const noexcept = 0;
|
||||||
virtual void performRealOnlyInverseTransform (float*) const noexcept = 0;
|
virtual void performRealOnlyInverseTransform (float*) const noexcept = 0;
|
||||||
|
|
@ -38,7 +38,7 @@ struct FFT::Engine
|
||||||
std::sort (list.begin(), list.end(), [] (Engine* a, Engine* b) { return b->enginePriority < a->enginePriority; });
|
std::sort (list.begin(), list.end(), [] (Engine* a, Engine* b) { return b->enginePriority < a->enginePriority; });
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~Engine() {}
|
virtual ~Engine() = default;
|
||||||
|
|
||||||
virtual FFT::Instance* create (int order) const = 0;
|
virtual FFT::Instance* create (int order) const = 0;
|
||||||
|
|
||||||
|
|
@ -796,6 +796,145 @@ struct IntelFFT : public FFT::Instance
|
||||||
FFT::EngineImpl<IntelFFT> fftwEngine;
|
FFT::EngineImpl<IntelFFT> fftwEngine;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
//==============================================================================
|
||||||
|
// Visual Studio should define no more than one of these, depending on the
|
||||||
|
// setting at 'Project' > 'Properties' > 'Configuration Properties' > 'Intel
|
||||||
|
// Performance Libraries' > 'Use Intel(R) IPP'
|
||||||
|
#if _IPP_SEQUENTIAL_STATIC || _IPP_SEQUENTIAL_DYNAMIC || _IPP_PARALLEL_STATIC || _IPP_PARALLEL_DYNAMIC
|
||||||
|
class IntelPerformancePrimitivesFFT : public FFT::Instance
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static constexpr auto priority = 9;
|
||||||
|
|
||||||
|
static IntelPerformancePrimitivesFFT* create (const int order)
|
||||||
|
{
|
||||||
|
auto complexContext = Context<ComplexTraits>::create (order);
|
||||||
|
auto realContext = Context<RealTraits> ::create (order);
|
||||||
|
|
||||||
|
if (complexContext.isValid() && realContext.isValid())
|
||||||
|
return new IntelPerformancePrimitivesFFT (std::move (complexContext), std::move (realContext), order);
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void perform (const Complex<float>* input, Complex<float>* output, bool inverse) const noexcept override
|
||||||
|
{
|
||||||
|
if (inverse)
|
||||||
|
{
|
||||||
|
ippsFFTInv_CToC_32fc (reinterpret_cast<const Ipp32fc*> (input),
|
||||||
|
reinterpret_cast<Ipp32fc*> (output),
|
||||||
|
cplx.specPtr,
|
||||||
|
cplx.workBuf.get());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ippsFFTFwd_CToC_32fc (reinterpret_cast<const Ipp32fc*> (input),
|
||||||
|
reinterpret_cast<Ipp32fc*> (output),
|
||||||
|
cplx.specPtr,
|
||||||
|
cplx.workBuf.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void performRealOnlyForwardTransform (float* inoutData, bool ignoreNegativeFreqs) const noexcept override
|
||||||
|
{
|
||||||
|
ippsFFTFwd_RToCCS_32f_I (inoutData, real.specPtr, real.workBuf.get());
|
||||||
|
|
||||||
|
if (order == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto* out = reinterpret_cast<Complex<float>*> (inoutData);
|
||||||
|
const auto size = (1 << order);
|
||||||
|
|
||||||
|
if (! ignoreNegativeFreqs)
|
||||||
|
for (auto i = size >> 1; i < size; ++i)
|
||||||
|
out[i] = std::conj (out[size - i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void performRealOnlyInverseTransform (float* inoutData) const noexcept override
|
||||||
|
{
|
||||||
|
ippsFFTInv_CCSToR_32f_I (inoutData, real.specPtr, real.workBuf.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static constexpr auto flag = IPP_FFT_DIV_INV_BY_N;
|
||||||
|
static constexpr auto hint = ippAlgHintFast;
|
||||||
|
|
||||||
|
struct IppFree
|
||||||
|
{
|
||||||
|
template <typename Ptr>
|
||||||
|
void operator() (Ptr* ptr) const noexcept { ippsFree (ptr); }
|
||||||
|
};
|
||||||
|
|
||||||
|
using IppPtr = std::unique_ptr<Ipp8u[], IppFree>;
|
||||||
|
|
||||||
|
template <typename Traits>
|
||||||
|
struct Context
|
||||||
|
{
|
||||||
|
using SpecPtr = typename Traits::Spec*;
|
||||||
|
|
||||||
|
static Context create (const int order)
|
||||||
|
{
|
||||||
|
int specSize = 0, initSize = 0, workSize = 0;
|
||||||
|
|
||||||
|
if (Traits::getSize (order, flag, hint, &specSize, &initSize, &workSize) != ippStsNoErr)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
const auto initBuf = IppPtr (ippsMalloc_8u (initSize));
|
||||||
|
auto specBuf = IppPtr (ippsMalloc_8u (specSize));
|
||||||
|
SpecPtr specPtr = nullptr;
|
||||||
|
|
||||||
|
if (Traits::init (&specPtr, order, flag, hint, specBuf.get(), initBuf.get()) != ippStsNoErr)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
if (reinterpret_cast<const Ipp8u*> (specPtr) != specBuf.get())
|
||||||
|
return {};
|
||||||
|
|
||||||
|
return { std::move (specBuf), IppPtr (ippsMalloc_8u (workSize)), specPtr };
|
||||||
|
}
|
||||||
|
|
||||||
|
Context() noexcept = default;
|
||||||
|
|
||||||
|
Context (IppPtr&& spec, IppPtr&& work, typename Traits::Spec* ptr) noexcept
|
||||||
|
: specBuf (std::move (spec)), workBuf (std::move (work)), specPtr (ptr)
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool isValid() const noexcept { return specPtr != nullptr; }
|
||||||
|
|
||||||
|
IppPtr specBuf, workBuf;
|
||||||
|
SpecPtr specPtr = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ComplexTraits
|
||||||
|
{
|
||||||
|
static constexpr auto getSize = ippsFFTGetSize_C_32fc;
|
||||||
|
static constexpr auto init = ippsFFTInit_C_32fc;
|
||||||
|
using Spec = IppsFFTSpec_C_32fc;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RealTraits
|
||||||
|
{
|
||||||
|
static constexpr auto getSize = ippsFFTGetSize_R_32f;
|
||||||
|
static constexpr auto init = ippsFFTInit_R_32f;
|
||||||
|
using Spec = IppsFFTSpec_R_32f;
|
||||||
|
};
|
||||||
|
|
||||||
|
IntelPerformancePrimitivesFFT (Context<ComplexTraits>&& complexToUse,
|
||||||
|
Context<RealTraits>&& realToUse,
|
||||||
|
const int orderToUse)
|
||||||
|
: cplx (std::move (complexToUse)),
|
||||||
|
real (std::move (realToUse)),
|
||||||
|
order (orderToUse)
|
||||||
|
{}
|
||||||
|
|
||||||
|
Context<ComplexTraits> cplx;
|
||||||
|
Context<RealTraits> real;
|
||||||
|
int order = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
FFT::EngineImpl<IntelPerformancePrimitivesFFT> intelPerformancePrimitivesFFT;
|
||||||
|
#endif
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
FFT::FFT (int order)
|
FFT::FFT (int order)
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,12 @@
|
||||||
#include <mkl_dfti.h>
|
#include <mkl_dfti.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if _IPP_SEQUENTIAL_STATIC || _IPP_SEQUENTIAL_DYNAMIC || _IPP_PARALLEL_STATIC || _IPP_PARALLEL_DYNAMIC
|
||||||
|
#include <ippcore.h>
|
||||||
|
#include <ipps.h>
|
||||||
|
#define JUCE_IPP_AVAILABLE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "processors/juce_FIRFilter.cpp"
|
#include "processors/juce_FIRFilter.cpp"
|
||||||
#include "processors/juce_IIRFilter.cpp"
|
#include "processors/juce_IIRFilter.cpp"
|
||||||
#include "processors/juce_LadderFilter.cpp"
|
#include "processors/juce_LadderFilter.cpp"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue