-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathFFT.c
179 lines (152 loc) · 4.91 KB
/
FFT.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
// FFT Code
/*
'********************************************************************
' Execution time for a 2048 point FFT on a 1700 MHz P4 was about 5 ms)
' Some optimization could be made if only real inputs are insured.
' Rick Muething KN6KB, Mar 31, 2004
'********************************************************************
'--------------------------------------------------------------------
' VB FFT Release 2-B
' by Murphy McCauley (MurphyMc@Concentric.NET)
' 10/01/99
'--------------------------------------------------------------------
' About:
' This code is very, very heavily based on Don Cross's fourier.pas
' Turbo Pascal Unit for calculating the Fast Fourier Transform.
' I've not implemented all of his functions, though I may well do
' so in the future.
' For more info, you can contact me by email, check my website at:
' http://www.fullspectrum.com/deeth/
' or check Don Cross's FFT web page at:
' http://www.intersrv.com/~dcross/fft.html
' You also may be intrested in the FFT.DLL that I put together based
' on Don Cross's FFT C code. It's callable with Visual Basic and
' includes VB declares. You can get it from either website.
'--------------------------------------------------------------------
' History of Release 2-B:
' Fixed a couple of errors that resulted from me mucking about with
' variable names after implementation and not re-checking. BAD ME.
' --------
' History of Release 2:
' Added FrequencyOfIndex() which is Don Cross's Index_to_frequency().
' FourierTransform() can now do inverse transforms.
' Added CalcFrequency() which can do a transform for a single
' frequency.
'--------------------------------------------------------------------
' Usage:
' The useful functions are:
' FourierTransform() performs a Fast Fourier Transform on an pair of
' Double arrays -- one real, one imaginary. Don't want/need
' imaginary numbers? Just use an array of 0s. This function can
' also do inverse FFTs.
' FrequencyOfIndex() can tell you what actual frequency a given index
' corresponds to.
' CalcFrequency() transforms a single frequency.
'--------------------------------------------------------------------
' Notes:
' All arrays must be 0 based (i.e. Dim TheArray(0 To 1023) or
' Dim TheArray(1023)).
' The number of samples must be a power of two (i.e. 2^x).
' FrequencyOfIndex() and CalcFrequency() haven't been tested much.
' Use this ENTIRELY AT YOUR OWN RISK.
'--------------------------------------------------------------------
*/
#include <math.h>
#ifdef M_PI
#undef M_PI
#endif
#define M_PI 3.1415926f
int ipow(int base, int exp)
{
int result = 1;
while (exp)
{
if (exp & 1)
result *= base;
exp >>= 1;
base *= base;
}
return result;
}
int NumberOfBitsNeeded(int PowerOfTwo)
{
int i;
for (i = 0; i <= 16; i++)
{
if ((PowerOfTwo & ipow(2, i)) != 0)
return i;
}
return 0;
}
int ReverseBits(int Index, int NumBits)
{
int i, Rev = 0;
for (i = 0; i < NumBits; i++)
{
Rev = (Rev * 2) | (Index & 1);
Index = Index /2;
}
return Rev;
}
void FourierTransform(int NumSamples, short * RealIn, float * RealOut, float * ImagOut, int InverseTransform)
{
float AngleNumerator;
unsigned char NumBits;
int I, j, K, n, BlockSize, BlockEnd;
float DeltaAngle, DeltaAr;
float Alpha, Beta;
float TR, TI, AR, AI;
if (InverseTransform)
AngleNumerator = -2.0f * M_PI;
else
AngleNumerator = 2.0f * M_PI;
NumBits = NumberOfBitsNeeded(NumSamples);
for (I = 0; I < NumSamples; I++)
{
j = ReverseBits(I, NumBits);
RealOut[j] = RealIn[I];
ImagOut[j] = 0.0f; // Not using I in ImageIn[I];
}
BlockEnd = 1;
BlockSize = 2;
while (BlockSize <= NumSamples)
{
DeltaAngle = AngleNumerator / BlockSize;
Alpha = sinf(0.5f * DeltaAngle);
Alpha = 2.0f * Alpha * Alpha;
Beta = sinf(DeltaAngle);
I = 0;
while (I < NumSamples)
{
AR = 1.0f;
AI = 0.0f;
j = I;
for (n = 0; n < BlockEnd; n++)
{
K = j + BlockEnd;
TR = AR * RealOut[K] - AI * ImagOut[K];
TI = AI * RealOut[K] + AR * ImagOut[K];
RealOut[K] = RealOut[j] - TR;
ImagOut[K] = ImagOut[j] - TI;
RealOut[j] = RealOut[j] + TR;
ImagOut[j] = ImagOut[j] + TI;
DeltaAr = Alpha * AR + Beta * AI;
AI = AI - (Alpha * AI - Beta * AR);
AR = AR - DeltaAr;
j = j + 1;
}
I = I + BlockSize;
}
BlockEnd = BlockSize;
BlockSize = BlockSize * 2;
}
if (InverseTransform)
{
// Normalize the resulting time samples...
for (I = 0; I < NumSamples; I++)
{
RealOut[I] = RealOut[I] / NumSamples;
ImagOut[I] = ImagOut[I] / NumSamples;
}
}
}