CiCueTea v0.0.1
Loading...
Searching...
No Matches
FFT_vDSP.h
Go to the documentation of this file.
1//
2// FFT_vDSP.h
3// CQTDSP
4//
5// Created by Juan Sierra on 4/8/25.
6//
7
15
16#pragma once
17
18#include <cassert>
19
20#include <Accelerate/Accelerate.h>
21#include <Eigen/Core>
22
23using namespace Eigen;
24
25namespace jsa::cicuetea {
26class DFTImpl
27{
28 public:
29 DFTImpl(size_t fftSize) :
30 workData(fftSize / 2, 4),
31 fftOrder(log2(fftSize)),
32 fftSize(fftSize),
33 inverseFactor(1.0 / double(fftSize))
34 {
35 assert(exp2(fftOrder) == fftSize);
36 setup = vDSP_create_fftsetupD(log2(fftSize), kFFTRadix2);
37 workData.setZero();
38 assert(setup != nullptr);
39 }
40
41 ~DFTImpl()
42 {
43 if (setup) vDSP_destroy_fftsetupD(setup);
44 }
45
46 void dft(const dcomplex* inPtr, dcomplex* outPtr)
47 {
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);
54 }
55
56 void idft(const dcomplex* inPtr, dcomplex* outPtr)
57 {
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);
66 }
67
68 void rdft(const double* inPtr, dcomplex* outPtr)
69 {
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;
80 }
81
82 void irdft(const dcomplex* inPtr, double* outPtr)
83 {
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);
93 }
94
95 static const std::string getName()
96 {
97 return "vDSP";
98 }
99
100 private:
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;
109};
110} // namespace jsa::cicuetea
Definition FFT_FFTW.h:25