Vital
Loading...
Searching...
No Matches
fourier_transform.h
Go to the documentation of this file.
1#pragma once
2
3#include "JuceHeader.h"
4
9namespace vital {
10
11#if INTEL_IPP
12
13 #include "ipps.h"
14
25class FourierTransform {
26 public:
35 FourierTransform(int bits) : size_(1 << bits) {
36 int spec_size = 0;
37 int spec_buffer_size = 0;
38 int buffer_size = 0;
39 ippsFFTGetSize_R_32f(bits, IPP_FFT_DIV_INV_BY_N, ippAlgHintNone, &spec_size, &spec_buffer_size, &buffer_size);
40
41 spec_ = std::make_unique<Ipp8u[]>(spec_size);
42 spec_buffer_ = std::make_unique<Ipp8u[]>(spec_buffer_size);
43 buffer_ = std::make_unique<Ipp8u[]>(buffer_size);
44
45 ippsFFTInit_R_32f(&ipp_specs_, bits, IPP_FFT_DIV_INV_BY_N, ippAlgHintNone, spec_.get(), spec_buffer_.get());
46 }
47
56 void transformRealForward(float* data) {
57 data[size_] = 0.0f;
58 ippsFFTFwd_RToPerm_32f_I((Ipp32f*)data, ipp_specs_, buffer_.get());
59 data[size_] = data[1];
60 data[size_ + 1] = 0.0f;
61 data[1] = 0.0f;
62 }
63
72 void transformRealInverse(float* data) {
73 data[1] = data[size_];
74 ippsFFTInv_PermToR_32f_I((Ipp32f*)data, ipp_specs_, buffer_.get());
75 memset(data + size_, 0, size_ * sizeof(float));
76 }
77
78 private:
79 int size_;
80 IppsFFTSpec_R_32f* ipp_specs_;
81 std::unique_ptr<Ipp8u[]> spec_;
82 std::unique_ptr<Ipp8u[]> spec_buffer_;
83 std::unique_ptr<Ipp8u[]> buffer_;
84
85 JUCE_LEAK_DETECTOR(FourierTransform)
86};
87
88#elif JUCE_MODULE_AVAILABLE_juce_dsp
89
98 class FourierTransform {
99 public:
105 FourierTransform(int bits) : fft_(bits) { }
106
112 void transformRealForward(float* data) { fft_.performRealOnlyForwardTransform(data, true); }
113
120 void transformRealInverse(float* data) { fft_.performRealOnlyInverseTransform(data); }
121
122 private:
123 dsp::FFT fft_;
124
125 JUCE_LEAK_DETECTOR(FourierTransform)
126 };
127
128#elif __APPLE__
129
130 #define VIMAGE_H
131#include <Accelerate/Accelerate.h>
132
141class FourierTransform {
142 public:
148 FourierTransform(vDSP_Length bits) : setup_(vDSP_create_fftsetup(bits, 2)), bits_(bits), size_(1 << bits) { }
149
154 vDSP_destroy_fftsetup(setup_);
155 }
156
162 void transformRealForward(float* data) {
163 static const float kMult = 0.5f;
164 data[size_] = 0.0f;
165 DSPSplitComplex split = { data, data + 1 };
166 vDSP_fft_zrip(setup_, &split, 2, bits_, kFFTDirection_Forward);
167 vDSP_vsmul(data, 1, &kMult, data, 1, size_);
168
169 data[size_] = data[1];
170 data[size_ + 1] = 0.0f;
171 data[1] = 0.0f;
172 }
173
179 void transformRealInverse(float* data) {
180 float multiplier = 1.0f / size_;
181 DSPSplitComplex split = { data, data + 1 };
182 data[1] = data[size_];
183
184 vDSP_fft_zrip(setup_, &split, 2, bits_, kFFTDirection_Inverse);
185 vDSP_vsmul(data, 1, &multiplier, data, 1, size_ * 2);
186 memset(data + size_, 0, size_ * sizeof(float));
187 }
188
189 private:
190 FFTSetup setup_;
191 vDSP_Length bits_;
192 vDSP_Length size_;
193
194 JUCE_LEAK_DETECTOR(FourierTransform)
195};
196
197#else
198
199#include "kissfft/kissfft.h"
200
211 public:
217 FourierTransform(size_t bits) : bits_(bits), size_(1 << bits), forward_(size_, false), inverse_(size_, true) {
218 buffer_ = std::make_unique<std::complex<float>[]>(size_);
219 }
220
225
234 void transformRealForward(float* data) {
235 for (int i = size_ - 1; i >= 0; --i) {
236 data[2 * i] = data[i];
237 data[2 * i + 1] = 0.0f;
238 }
239
240 forward_.transform((std::complex<float>*)data, buffer_.get());
241
242 int num_floats = size_ * 2;
243 memcpy(data, buffer_.get(), num_floats * sizeof(float));
244 data[size_] = data[1];
245 data[size_ + 1] = 0.0f;
246 data[1] = 0.0f;
247 }
248
257 void transformRealInverse(float* data) {
258 data[0] *= 0.5f;
259 data[1] = data[size_];
260 inverse_.transform((std::complex<float>*)data, buffer_.get());
261 int num_floats = size_ * 2;
262
263 float multiplier = 2.0f / size_;
264 for (int i = 0; i < size_; ++i)
265 data[i] = buffer_[i].real() * multiplier;
266
267 memset(data + size_, 0, size_ * sizeof(float));
268 }
269
270 private:
271 size_t bits_;
272 size_t size_;
273 std::unique_ptr<std::complex<float>[]> buffer_;
274 kissfft<float> forward_;
275 kissfft<float> inverse_;
276
277 JUCE_LEAK_DETECTOR(FourierTransform)
278};
279
280#endif
281
290 template <size_t bits>
291 class FFT {
292 public:
299 static FFT<bits> instance;
300 return &instance.fourier_transform_;
301 }
302
303 private:
307 FFT() : fourier_transform_(bits) { }
308
309 FourierTransform fourier_transform_;
310 };
311
312} // namespace vital
A template class to provide a statically allocated FourierTransform instance for a given number of bi...
Definition fourier_transform.h:291
static FourierTransform * transform()
Provides access to a static FourierTransform instance for the specified bits.
Definition fourier_transform.h:298
A Fourier transform implementation using KissFFT for platforms where other accelerations are unavaila...
Definition fourier_transform.h:210
void transformRealForward(float *data)
Performs an in-place forward real FFT using KissFFT.
Definition fourier_transform.h:234
void transformRealInverse(float *data)
Performs an in-place inverse real FFT using KissFFT.
Definition fourier_transform.h:257
FourierTransform(size_t bits)
Constructs a FourierTransform with the given bits using KissFFT.
Definition fourier_transform.h:217
~FourierTransform()
Default destructor.
Definition fourier_transform.h:224
Contains classes and functions used within the Vital synthesizer framework.