1
// fft.cpp: implementation of the Cfft class.
2
// This is a slightly modified version of Takuya OOURA's
3
// original radix 4 FFT package.
4
//Copyright(C) 1996-1998 Takuya OOURA
5
// (email: ooura@mmm.t.u-tokyo.ac.jp).
6
//////////////////////////////////////////////////////////////////////
12
//////////////////////////////////////////////////////////////////////
14
//////////////////////////////////////////////////////////////////////
15
#define SQRT_FFT_SIZE 46//sqrt(2048)
16
#define K_2PI 6.283185307
18
//////////////////////////////////////////////////////////////////////
19
// A pure input sin wave ... Asin(wt)... will produce an fft output
20
// peak of (N*A/4)^2 where N is FFT_SIZE.
21
// To convert to a Power dB range:
22
// PdBmax = 10*log10( (N*A/4)^2 + K_C ) + K_B
23
// PdBmin = 10*log10( 0 + K_C ) + K_B
24
// if (N*A/4)^2 >> K_C
25
// Then K_B = PdBmax - 20*log10( N*A/4 )
26
// K_C = 10 ^ ( (PdBmin-K_B)/10 )
27
// for power range of 0 to 100 dB with input(A) of 32767 and N=4096
28
// K_B = -50.51473275 and K_C = 1.1258312e5
29
// To eliminate the multiply by 10, divide by 10 so for an output
30
// range of 0 to 100dB the stored value is 0.0 to 10.0
31
// so final constant K_B = -5.051473275
32
#define K_B (-5.051473275)
33
#define K_C (1.1258312e5)
34
//////////////////////////////////////////////////////////////////////
35
// Construction/Destruction
36
//////////////////////////////////////////////////////////////////////
39
InBuf = new double[FFT_SIZE];
40
WindowTbl = new double[FFT_SIZE];
41
SinCosTbl = new double[FFT_SIZE/2];
42
WorkArea = new int[SQRT_FFT_SIZE+2];
43
pFFTAveBuf = new double[FFT_SIZE]; //Even index's hold average
45
makewt(FFT_SIZE/4, WorkArea, SinCosTbl);
46
makect(FFT_SIZE/4, WorkArea, SinCosTbl + WorkArea[0]);
47
for(int i=0; i<FFT_SIZE; i++)
50
// Pick a data windowing function:
51
// WindowTbl[i] = 1.0; //rectangle
52
// WindowTbl[i] = .54 - .46*cos( (K_2PI*i)/(FFT_SIZE-1) ); //Hamming
53
WindowTbl[i] = (.5 - .5*cos( (K_2PI*i)/(FFT_SIZE-1) )); //Hanning
60
{ // free all resources
89
//////////////////////////////////////////////////////////////////////
90
// "InBuf[]" is first multiplied by a window function and then
91
// calculates an "FFT_SIZE" point FFT on "InBuf[]".
92
// The result is converted to dB, and the range "start" to "stop"
93
// is multiplied by "gain" and copied into "OutBuf[]".
94
// If "Ave" is > 1, a LP smoothing filter
95
// is calculated on the output.
96
// Execution times for 4096 point fft:
97
// ~820nSec/sample with 266MHz PII
98
// The function returns true if the input is overloaded
99
//////////////////////////////////////////////////////////////////////
100
bool Cfft::CalcFFT(double * InPut, int start, int stop,double gain, int Ave,int* OutBuf)
109
for(i=0; i<FFT_SIZE; i++)
111
if( InPut[i] > 16384.0 ) //flag overload if within 3dB of max
113
InBuf[i] = WindowTbl[i] * InPut[i]; //window the data
116
bitrv2(FFT_SIZE, WorkArea + 2, InBuf);
117
cftfsub(FFT_SIZE, InBuf, SinCosTbl);
118
rftfsub(FFT_SIZE, InBuf, WorkArea[1], SinCosTbl + WorkArea[0]);
119
for( i=start; i<=stop; i++ ) //copy and scale into OutBuf[]
120
OutBuf[i] = (int)(gain*pFFTAveBuf[i<<1]);
124
void Cfft::rftfsub(int n, double *a, int nc, double *c)
127
double wkr, wki, xr, xi, yr, yi;
134
for (k = 2; k <= m; k += 2 )
138
wkr = 0.5 - c[nc - kk];
141
xi = a[k + 1] + a[j + 1];
142
yr = wkr * xr - wki * xi;
143
yi = wkr * xi + wki * xr;
147
xi += ( a[k+1]*a[k+1]);
151
xr += (a[j+1]*a[j+1]);
152
pFFTAveBuf[k] = (1.0-1.0/m_AveSize)*pFFTAveBuf[k] +
153
(1.0/m_AveSize)*(log10(xi+K_C) + K_B);
154
pFFTAveBuf[j] = (1.0-1.0/m_AveSize)*pFFTAveBuf[j] +
155
(1.0/m_AveSize)*(log10(xr+K_C) + K_B);
161
for (k = 2; k <= m; k += 2 )
165
wkr = 0.5 - c[nc - kk];
168
xi = a[k + 1] + a[j + 1];
169
yr = wkr * xr - wki * xi;
170
yi = wkr * xi + wki * xr;
174
xi += ( a[k+1]*a[k+1]);
178
xr += (a[j+1]*a[j+1]);
179
pFFTAveBuf[k] = log10(xi+K_C)+K_B;
180
pFFTAveBuf[j] = log10(xr+K_C)+K_B;
185
/* -------- initializing routines -------- */
186
void Cfft::makewt(int nw, int *ip, double *w)
195
delta = atan(1.0) / nwh;
198
w[nwh] = cos(delta * nwh);
200
for (j = 2; j < nwh; j += 2) {
209
bitrv2(nw, ip + 2, w);
214
void Cfft::makect(int nc, int *ip, double *c)
222
delta = atan(1.0) / nch;
223
c[0] = cos(delta * nch);
225
for (j = 1; j < nch; j++) {
226
c[j] = 0.5 * cos(delta * j);
227
c[nc - j] = 0.5 * sin(delta * j);
233
/* -------- child routines -------- */
234
void Cfft::bitrv2(int n, int *ip, double *a)
236
int j, j1, k, k1, l, m, m2;
242
while ((m << 2) < l) {
244
for (j = 0; j < m; j++) {
245
ip[m + j] = ip[j] + l;
250
for (k = 1; k < m; k++) {
251
for (j = 0; j < k; j++) {
252
j1 = (j << 1) + ip[k];
253
k1 = (k << 1) + ip[j];
258
a[j1 + 1] = a[k1 + 1];
265
for (k = 1; k < m; k++) {
266
for (j = 0; j < k; j++) {
267
j1 = (j << 1) + ip[k];
268
k1 = (k << 1) + ip[j];
272
a[j1 + 1] = a[k1 + 1];
280
a[j1 + 1] = a[k1 + 1];
288
void Cfft::cftfsub(int n, double *a, double *w)
290
int j, j1, j2, j3, l;
291
double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
297
while ((l << 2) < n) {
303
for (j = 0; j < l; j += 2) {
308
x0i = a[j + 1] + a[j1 + 1];
310
x1i = a[j + 1] - a[j1 + 1];
312
x2i = a[j2 + 1] + a[j3 + 1];
314
x3i = a[j2 + 1] - a[j3 + 1];
316
a[j + 1] = x0i + x2i;
318
a[j2 + 1] = x0i - x2i;
320
a[j1 + 1] = x1i + x3r;
322
a[j3 + 1] = x1i - x3r;
325
for (j = 0; j < l; j += 2) {
328
x0i = a[j + 1] - a[j1 + 1];
330
a[j + 1] += a[j1 + 1];
339
void Cfft::cft1st(int n, double *a, double *w)
342
double wk1r, wk1i, wk2r, wk2i, wk3r, wk3i;
343
double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
376
a[10] = wk1r * (x0r - x0i);
377
a[11] = wk1r * (x0r + x0i);
380
a[14] = wk1r * (x0i - x0r);
381
a[15] = wk1r * (x0i + x0r);
383
for (j = 16; j < n; j += 16) {
390
wk3r = wk1r - 2 * wk2i * wk1i;
391
wk3i = 2 * wk2i * wk1r - wk1i;
392
x0r = a[j] + a[j + 2];
393
x0i = a[j + 1] + a[j + 3];
394
x1r = a[j] - a[j + 2];
395
x1i = a[j + 1] - a[j + 3];
396
x2r = a[j + 4] + a[j + 6];
397
x2i = a[j + 5] + a[j + 7];
398
x3r = a[j + 4] - a[j + 6];
399
x3i = a[j + 5] - a[j + 7];
401
a[j + 1] = x0i + x2i;
404
a[j + 4] = wk2r * x0r - wk2i * x0i;
405
a[j + 5] = wk2r * x0i + wk2i * x0r;
408
a[j + 2] = wk1r * x0r - wk1i * x0i;
409
a[j + 3] = wk1r * x0i + wk1i * x0r;
412
a[j + 6] = wk3r * x0r - wk3i * x0i;
413
a[j + 7] = wk3r * x0i + wk3i * x0r;
416
wk3r = wk1r - 2 * wk2r * wk1i;
417
wk3i = 2 * wk2r * wk1r - wk1i;
418
x0r = a[j + 8] + a[j + 10];
419
x0i = a[j + 9] + a[j + 11];
420
x1r = a[j + 8] - a[j + 10];
421
x1i = a[j + 9] - a[j + 11];
422
x2r = a[j + 12] + a[j + 14];
423
x2i = a[j + 13] + a[j + 15];
424
x3r = a[j + 12] - a[j + 14];
425
x3i = a[j + 13] - a[j + 15];
426
a[j + 8] = x0r + x2r;
427
a[j + 9] = x0i + x2i;
430
a[j + 12] = -wk2i * x0r - wk2r * x0i;
431
a[j + 13] = -wk2i * x0i + wk2r * x0r;
434
a[j + 10] = wk1r * x0r - wk1i * x0i;
435
a[j + 11] = wk1r * x0i + wk1i * x0r;
438
a[j + 14] = wk3r * x0r - wk3i * x0i;
439
a[j + 15] = wk3r * x0i + wk3i * x0r;
444
void Cfft::cftmdl(int n, int l, double *a, double *w)
446
int j, j1, j2, j3, k, k1, k2, m, m2;
447
double wk1r, wk1i, wk2r, wk2i, wk3r, wk3i;
448
double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
451
for (j = 0; j < l; j += 2) {
456
x0i = a[j + 1] + a[j1 + 1];
458
x1i = a[j + 1] - a[j1 + 1];
460
x2i = a[j2 + 1] + a[j3 + 1];
462
x3i = a[j2 + 1] - a[j3 + 1];
464
a[j + 1] = x0i + x2i;
466
a[j2 + 1] = x0i - x2i;
468
a[j1 + 1] = x1i + x3r;
470
a[j3 + 1] = x1i - x3r;
473
for (j = m; j < l + m; j += 2) {
478
x0i = a[j + 1] + a[j1 + 1];
480
x1i = a[j + 1] - a[j1 + 1];
482
x2i = a[j2 + 1] + a[j3 + 1];
484
x3i = a[j2 + 1] - a[j3 + 1];
486
a[j + 1] = x0i + x2i;
488
a[j2 + 1] = x0r - x2r;
491
a[j1] = wk1r * (x0r - x0i);
492
a[j1 + 1] = wk1r * (x0r + x0i);
495
a[j3] = wk1r * (x0i - x0r);
496
a[j3 + 1] = wk1r * (x0i + x0r);
500
for (k = m2; k < n; k += m2) {
507
wk3r = wk1r - 2 * wk2i * wk1i;
508
wk3i = 2 * wk2i * wk1r - wk1i;
509
for (j = k; j < l + k; j += 2) {
514
x0i = a[j + 1] + a[j1 + 1];
516
x1i = a[j + 1] - a[j1 + 1];
518
x2i = a[j2 + 1] + a[j3 + 1];
520
x3i = a[j2 + 1] - a[j3 + 1];
522
a[j + 1] = x0i + x2i;
526
a[j2] = wk2r * x0r - wk2i * x0i;
527
a[j2 + 1] = wk2r * x0i + wk2i * x0r;
530
a[j1] = wk1r * x0r - wk1i * x0i;
531
a[j1 + 1] = wk1r * x0i + wk1i * x0r;
534
a[j3] = wk3r * x0r - wk3i * x0i;
535
a[j3 + 1] = wk3r * x0i + wk3i * x0r;
539
wk3r = wk1r - 2 * wk2r * wk1i;
540
wk3i = 2 * wk2r * wk1r - wk1i;
541
for (j = k + m; j < l + (k + m); j += 2) {
546
x0i = a[j + 1] + a[j1 + 1];
548
x1i = a[j + 1] - a[j1 + 1];
550
x2i = a[j2 + 1] + a[j3 + 1];
552
x3i = a[j2 + 1] - a[j3 + 1];
554
a[j + 1] = x0i + x2i;
557
a[j2] = -wk2i * x0r - wk2r * x0i;
558
a[j2 + 1] = -wk2i * x0i + wk2r * x0r;
561
a[j1] = wk1r * x0r - wk1i * x0i;
562
a[j1 + 1] = wk1r * x0i + wk1i * x0r;
565
a[j3] = wk3r * x0r - wk3i * x0i;
566
a[j3 + 1] = wk3r * x0i + wk3i * x0r;