Audacity 3.2.0
Macros | Enumerations | Functions | Variables
RealFFTf.cpp File Reference
#include "RealFFTf.h"
#include <vector>
#include <stdlib.h>
#include <math.h>
#include <wx/thread.h>
Include dependency graph for RealFFTf.cpp:

Go to the source code of this file.

Macros

#define M_PI   3.14159265358979323846 /* pi */
 

Enumerations

enum  : size_t { MAX_HFFT = 10 }
 

Functions

HFFT InitializeFFT (size_t fftlen)
 
static std::vector< std::unique_ptr< FFTParam > > hFFTArray (MAX_HFFT)
 
HFFT GetFFT (size_t fftlen)
 
void RealFFTf (fft_type *buffer, const FFTParam *h)
 
void InverseRealFFTf (fft_type *buffer, const FFTParam *h)
 
void ReorderToFreq (const FFTParam *hFFT, const fft_type *buffer, fft_type *RealOut, fft_type *ImagOut)
 
void ReorderToTime (const FFTParam *hFFT, const fft_type *buffer, fft_type *TimeOut)
 

Variables

wxCriticalSection getFFTMutex
 

Macro Definition Documentation

◆ M_PI

#define M_PI   3.14159265358979323846 /* pi */

Definition at line 48 of file RealFFTf.cpp.

Enumeration Type Documentation

◆ anonymous enum

anonymous enum : size_t
Enumerator
MAX_HFFT 

Definition at line 96 of file RealFFTf.cpp.

96: size_t { MAX_HFFT = 10 };
@ MAX_HFFT
Definition: RealFFTf.cpp:96

Function Documentation

◆ GetFFT()

HFFT GetFFT ( size_t  fftlen)

Definition at line 104 of file RealFFTf.cpp.

105{
106 // To do: smarter policy about when to retain in the pool and when to
107 // allocate a unique instance.
108
109 wxCriticalSectionLocker locker{ getFFTMutex };
110
111 size_t h = 0;
112 auto n = fftlen/2;
113 auto size = hFFTArray.size();
114 for(;
115 (h < size) && hFFTArray[h] && (n != hFFTArray[h]->Points);
116 h++)
117 ;
118 if(h < size) {
119 if(hFFTArray[h] == NULL) {
120 hFFTArray[h].reset( InitializeFFT(fftlen).release() );
121 }
122 return HFFT{ hFFTArray[h].get() };
123 } else {
124 // All buffers used, so fall back to allocating a NEW set of tables
125 return InitializeFFT(fftlen);
126 }
127}
static std::vector< std::unique_ptr< FFTParam > > hFFTArray(MAX_HFFT)
HFFT InitializeFFT(size_t fftlen)
Definition: RealFFTf.cpp:55
wxCriticalSection getFFTMutex
Definition: RealFFTf.cpp:100
std::unique_ptr< FFTParam, FFTDeleter > HFFT
Definition: RealFFTf.h:22

References getFFTMutex, hFFTArray(), InitializeFFT(), and size.

Referenced by SpectrogramSettings::CacheWindows(), InverseRealFFT(), PowerSpectrum(), and RealFFT().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ hFFTArray()

static std::vector< std::unique_ptr< FFTParam > > hFFTArray ( MAX_HFFT  )
static

Referenced by GetFFT(), and FFTDeleter::operator()().

Here is the caller graph for this function:

◆ InitializeFFT()

HFFT InitializeFFT ( size_t  fftlen)

Definition at line 55 of file RealFFTf.cpp.

56{
57 int temp;
59
60 /*
61 * FFT size is only half the number of data points
62 * The full FFT output can be reconstructed from this FFT's output.
63 * (This optimization can be made since the data is real.)
64 */
65 h->Points = fftlen / 2;
66
67 h->SinTable.reinit(2*h->Points);
68
69 h->BitReversed.reinit(h->Points);
70
71 for(size_t i = 0; i < h->Points; i++)
72 {
73 temp = 0;
74 for(size_t mask = h->Points / 2; mask > 0; mask >>= 1)
75 temp = (temp >> 1) + (i & mask ? h->Points : 0);
76
77 h->BitReversed[i] = temp;
78 }
79
80 for(size_t i = 0; i < h->Points; i++)
81 {
82 h->SinTable[h->BitReversed[i] ]=(fft_type)-sin(2*M_PI*i/(2*h->Points));
83 h->SinTable[h->BitReversed[i]+1]=(fft_type)-cos(2*M_PI*i/(2*h->Points));
84 }
85
86#ifdef EXPERIMENTAL_EQ_SSE_THREADED
87 // NEW SSE FFT routines work on live data
88 for(size_t i = 0; i < 32; i++)
89 if((1 << i) & fftlen)
90 h->pow2Bits = i;
91#endif
92
93 return h;
94}
#define safenew
Definition: MemoryX.h:10
float fft_type
Definition: RealFFTf48x.h:6
#define M_PI
Definition: RealFFTf.cpp:48
size_t Points
Definition: RealFFTf.h:10

References M_PI, FFTParam::Points, and safenew.

Referenced by GetFFT().

Here is the caller graph for this function:

◆ InverseRealFFTf()

void InverseRealFFTf ( fft_type buffer,
const FFTParam h 
)

Definition at line 263 of file RealFFTf.cpp.

264{
265 fft_type *A,*B;
266 const fft_type *sptr;
267 const fft_type *endptr1,*endptr2;
268 const int *br1;
269 fft_type HRplus,HRminus,HIplus,HIminus;
270 fft_type v1,v2,sin,cos;
271
272 auto ButterfliesPerGroup = h->Points / 2;
273
274 /* Massage input to get the input for a real output sequence. */
275 A = buffer + 2;
276 B = buffer + h->Points * 2 - 2;
277 br1 = h->BitReversed.get() + 1;
278 while(A<B)
279 {
280 sin=h->SinTable[*br1];
281 cos=h->SinTable[*br1+1];
282 HRplus = (HRminus = *A - *B ) + (*B * 2);
283 HIplus = (HIminus = *(A+1) - *(B+1)) + (*(B+1) * 2);
284 v1 = (sin*HRminus + cos*HIplus);
285 v2 = (cos*HRminus - sin*HIplus);
286 *A = (HRplus + v1) * (fft_type)0.5;
287 *B = *A - v1;
288 *(A+1) = (HIminus - v2) * (fft_type)0.5;
289 *(B+1) = *(A+1) - HIminus;
290
291 A+=2;
292 B-=2;
293 br1++;
294 }
295 /* Handle center bin (just need conjugate) */
296 *(A+1)=-*(A+1);
297 /* Handle DC bin separately - this ignores any Fs/2 component
298 buffer[1]=buffer[0]=buffer[0]/2;*/
299 /* Handle DC and Fs/2 bins specially */
300 /* The DC bin is passed in as the real part of the DC complex value */
301 /* The Fs/2 bin is passed in as the imaginary part of the DC complex value */
302 /* (v1+v2) = buffer[0] == the DC component */
303 /* (v1-v2) = buffer[1] == the Fs/2 component */
304 v1=0.5f*(buffer[0]+buffer[1]);
305 v2=0.5f*(buffer[0]-buffer[1]);
306 buffer[0]=v1;
307 buffer[1]=v2;
308
309 /*
310 * Butterfly:
311 * Ain-----Aout
312 * \ /
313 * / \
314 * Bin-----Bout
315 */
316
317 endptr1 = buffer + h->Points * 2;
318
319 while(ButterfliesPerGroup > 0)
320 {
321 A = buffer;
322 B = buffer + ButterfliesPerGroup * 2;
323 sptr = h->SinTable.get();
324
325 while(A < endptr1)
326 {
327 sin = *(sptr++);
328 cos = *(sptr++);
329 endptr2 = B;
330 while(A < endptr2)
331 {
332 v1 = *B * cos - *(B + 1) * sin;
333 v2 = *B * sin + *(B + 1) * cos;
334 *B = (*A + v1) * (fft_type)0.5;
335 *(A++) = *(B++) - v1;
336 *B = (*A + v2) * (fft_type)0.5;
337 *(A++) = *(B++) - v2;
338 }
339 A = B;
340 B += ButterfliesPerGroup * 2;
341 }
342 ButterfliesPerGroup >>= 1;
343 }
344}
#define A(N)
Definition: ToChars.cpp:62
ArrayOf< int > BitReversed
Definition: RealFFTf.h:8
ArrayOf< fft_type > SinTable
Definition: RealFFTf.h:9

References A, FFTParam::BitReversed, FFTParam::Points, and FFTParam::SinTable.

Referenced by EqualizationFilter::Filter(), InverseRealFFT(), and SpectrumTransformer::OutputStep().

Here is the caller graph for this function:

◆ RealFFTf()

void RealFFTf ( fft_type buffer,
const FFTParam h 
)

Definition at line 161 of file RealFFTf.cpp.

162{
163 fft_type *A,*B;
164 const fft_type *sptr;
165 const fft_type *endptr1,*endptr2;
166 const int *br1,*br2;
167 fft_type HRplus,HRminus,HIplus,HIminus;
168 fft_type v1,v2,sin,cos;
169
170 auto ButterfliesPerGroup = h->Points/2;
171
172 /*
173 * Butterfly:
174 * Ain-----Aout
175 * \ /
176 * / \
177 * Bin-----Bout
178 */
179
180 endptr1 = buffer + h->Points * 2;
181
182 while(ButterfliesPerGroup > 0)
183 {
184 A = buffer;
185 B = buffer + ButterfliesPerGroup * 2;
186 sptr = h->SinTable.get();
187
188 while(A < endptr1)
189 {
190 sin = *sptr;
191 cos = *(sptr+1);
192 endptr2 = B;
193 while(A < endptr2)
194 {
195 v1 = *B * cos + *(B + 1) * sin;
196 v2 = *B * sin - *(B + 1) * cos;
197 *B = (*A + v1);
198 *(A++) = *(B++) - 2 * v1;
199 *B = (*A - v2);
200 *(A++) = *(B++) + 2 * v2;
201 }
202 A = B;
203 B += ButterfliesPerGroup * 2;
204 sptr += 2;
205 }
206 ButterfliesPerGroup >>= 1;
207 }
208 /* Massage output to get the output for a real input sequence. */
209 br1 = h->BitReversed.get() + 1;
210 br2 = h->BitReversed.get() + h->Points - 1;
211
212 while(br1<br2)
213 {
214 sin=h->SinTable[*br1];
215 cos=h->SinTable[*br1+1];
216 A=buffer+*br1;
217 B=buffer+*br2;
218 HRplus = (HRminus = *A - *B ) + (*B * 2);
219 HIplus = (HIminus = *(A+1) - *(B+1)) + (*(B+1) * 2);
220 v1 = (sin*HRminus - cos*HIplus);
221 v2 = (cos*HRminus + sin*HIplus);
222 *A = (HRplus + v1) * (fft_type)0.5;
223 *B = *A - v1;
224 *(A+1) = (HIminus + v2) * (fft_type)0.5;
225 *(B+1) = *(A+1) - HIminus;
226
227 br1++;
228 br2--;
229 }
230 /* Handle the center bin (just need a conjugate) */
231 A=buffer+*br1+1;
232 *A=-*A;
233 /* Handle DC bin separately - and ignore the Fs/2 bin
234 buffer[0]+=buffer[1];
235 buffer[1]=(fft_type)0;*/
236 /* Handle DC and Fs/2 bins separately */
237 /* Put the Fs/2 value into the imaginary part of the DC bin */
238 v1=buffer[0]-buffer[1];
239 buffer[0]+=buffer[1];
240 buffer[1]=v1;
241}

References A, FFTParam::BitReversed, FFTParam::Points, and FFTParam::SinTable.

Referenced by SpecCache::CalculateOneSpectrum(), anonymous_namespace{SpectrumCache.cpp}::ComputeSpectrumUsingRealFFTf(), SpectrumTransformer::FillFirstWindow(), EqualizationFilter::Filter(), PowerSpectrum(), and RealFFT().

Here is the caller graph for this function:

◆ ReorderToFreq()

void ReorderToFreq ( const FFTParam hFFT,
const fft_type buffer,
fft_type RealOut,
fft_type ImagOut 
)

Definition at line 346 of file RealFFTf.cpp.

348{
349 // Copy the data into the real and imaginary outputs
350 for(size_t i = 1; i < hFFT->Points; i++) {
351 RealOut[i] = buffer[hFFT->BitReversed[i] ];
352 ImagOut[i] = buffer[hFFT->BitReversed[i]+1];
353 }
354 RealOut[0] = buffer[0]; // DC component
355 ImagOut[0] = 0;
356 RealOut[hFFT->Points] = buffer[1]; // Fs/2 component
357 ImagOut[hFFT->Points] = 0;
358}

References FFTParam::BitReversed, and FFTParam::Points.

◆ ReorderToTime()

void ReorderToTime ( const FFTParam hFFT,
const fft_type buffer,
fft_type TimeOut 
)

Definition at line 360 of file RealFFTf.cpp.

361{
362 // Copy the data into the real outputs
363 for(size_t i = 0; i < hFFT->Points; i++) {
364 TimeOut[i*2 ]=buffer[hFFT->BitReversed[i] ];
365 TimeOut[i*2+1]=buffer[hFFT->BitReversed[i]+1];
366 }
367}

References FFTParam::BitReversed, and FFTParam::Points.

Referenced by EqualizationFilter::Filter(), and InverseRealFFT().

Here is the caller graph for this function:

Variable Documentation

◆ getFFTMutex

wxCriticalSection getFFTMutex

Definition at line 100 of file RealFFTf.cpp.

Referenced by GetFFT(), and FFTDeleter::operator()().