20#include <Accelerate/Accelerate.h>
25namespace jsa::cicuetea {
29 DFTImpl(
size_t fftSize) :
30 workData(fftSize / 2, 4),
31 fftOrder(log2(fftSize)),
33 inverseFactor(1.0 / double(fftSize))
35 assert(exp2(fftOrder) == fftSize);
36 setup = vDSP_create_fftsetupD(log2(fftSize), kFFTRadix2);
38 assert(setup !=
nullptr);
43 if (setup) vDSP_destroy_fftsetupD(setup);
46 void dft(
const dcomplex* inPtr, dcomplex* outPtr)
48 DSPDoubleComplex* inPtr_ =
reinterpret_cast<DSPDoubleComplex*
>(
const_cast<dcomplex*
>(inPtr));
49 DSPDoubleComplex* outPtr_ =
reinterpret_cast<DSPDoubleComplex*
>(outPtr);
50 DSPDoubleSplitComplex splitComplex = {workData.col(0).data(), workData.col(2).data()};
51 vDSP_ctozD(inPtr_, doubleStride, &splitComplex, singleStride, fftSize);
52 vDSP_fft_zipD(setup, &splitComplex, singleStride, fftOrder, kFFTDirection_Forward);
53 vDSP_ztocD(&splitComplex, singleStride, outPtr_, doubleStride, fftSize);
56 void idft(
const dcomplex* inPtr, dcomplex* outPtr)
58 DSPDoubleComplex* inPtr_ =
reinterpret_cast<DSPDoubleComplex*
>(
const_cast<dcomplex*
>(inPtr));
59 DSPDoubleComplex* outPtr_ =
reinterpret_cast<DSPDoubleComplex*
>(outPtr);
60 double* mulPtr =
reinterpret_cast<double*
>(outPtr);
61 DSPDoubleSplitComplex splitComplex = {workData.col(0).data(), workData.col(2).data()};
62 vDSP_ctozD(inPtr_, doubleStride, &splitComplex, singleStride, fftSize);
63 vDSP_fft_zipD(setup, &splitComplex, singleStride, fftOrder, kFFTDirection_Inverse);
64 vDSP_ztocD(&splitComplex, singleStride, outPtr_, doubleStride, fftSize);
65 vDSP_vsmulD(mulPtr, singleStride, &inverseFactor, mulPtr, singleStride, 2 * fftSize);
68 void rdft(
const double* inPtr, dcomplex* outPtr)
70 DSPDoubleComplex* inPtr_ =
reinterpret_cast<DSPDoubleComplex*
>(
const_cast<double*
>(inPtr));
71 DSPDoubleComplex* outPtr_ =
reinterpret_cast<DSPDoubleComplex*
>(outPtr);
72 double* mulPtr =
reinterpret_cast<double*
>(outPtr);
73 DSPDoubleSplitComplex splitComplex = {workData.col(0).data(), workData.col(1).data()};
74 vDSP_ctozD(inPtr_, doubleStride, &splitComplex, singleStride, fftSize / 2);
75 vDSP_fft_zripD(setup, &splitComplex, singleStride, fftOrder, kFFTDirection_Forward);
76 vDSP_ztocD(&splitComplex, singleStride, outPtr_, doubleStride, fftSize / 2);
77 vDSP_vsmulD(mulPtr, singleStride, &forwardFactor, mulPtr, singleStride, fftSize);
78 outPtr_[fftSize / 2].real = outPtr_[0].imag;
79 outPtr_[0].imag = 0.0;
82 void irdft(
const dcomplex* inPtr,
double* outPtr)
84 DSPDoubleComplex* inPtr_ =
reinterpret_cast<DSPDoubleComplex*
>(
const_cast<dcomplex*
>(inPtr));
85 DSPDoubleComplex* outPtr_ =
reinterpret_cast<DSPDoubleComplex*
>(outPtr);
86 double* mulPtr =
reinterpret_cast<double*
>(outPtr);
87 DSPDoubleSplitComplex splitComplex = {workData.col(0).data(), workData.col(1).data()};
88 vDSP_ctozD(inPtr_, doubleStride, &splitComplex, singleStride, fftSize / 2);
89 splitComplex.imagp[0] = inPtr_[fftSize / 2].real;
90 vDSP_fft_zripD(setup, &splitComplex, singleStride, fftOrder, kFFTDirection_Inverse);
91 vDSP_ztocD(&splitComplex, singleStride, outPtr_, doubleStride, fftSize / 2);
92 vDSP_vsmulD(mulPtr, singleStride, &inverseFactor, mulPtr, singleStride, fftSize);
95 static const std::string getName()
101 FFTSetupD setup =
nullptr;
102 Eigen::ArrayX4d workData;
103 const vDSP_Length fftOrder;
104 const size_t fftSize;
105 double forwardFactor = 0.5;
106 double inverseFactor = NAN;
107 const vDSP_Stride singleStride = 1;
108 const vDSP_Stride doubleStride = 2;