-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfft.c
103 lines (94 loc) · 2.03 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
/**
* Algorithm from http://paulbourke.net/miscellaneous/dft/ (2020 April 22)
* Copyright Paul Bourke
* Modifications by Johannes Ehala, Prolab, Taltech
*/
#include <inttypes.h>
#include <math.h>
#include "fft.h"
uint32_t calc_power(uint32_t num_samples)
{
uint32_t p;
uint32_t power_of_two = 0;
if (num_samples != 0 && !(num_samples & (num_samples -1)))
{
p = num_samples;
while (((p & 1) == 0) && p > 1)
{
p >>= 1;
power_of_two++;
}
}
return power_of_two;
}
void fft_complex(float *signal, uint32_t num_samples)
{
uint32_t i, i1, j, l, l1, l2;
float c1, c2, t1, t2, u1, u2, z;
float* y_startpoint;
uint32_t p2;
p2 = calc_power(num_samples);
y_startpoint = signal + num_samples;
bit_alignment(signal, y_startpoint, num_samples);
if (p2 > 0)
{
c1 = -1.0;
c2 = 0.0;
l2 = 1;
for (l = 0; l < p2; l++)
{
l1 = l2;
l2 <<= 1;
u1 = 1.0;
u2 = 0.0;
for (j = 0; j < l1; j++)
{
for (i = j; i < num_samples; i += l2)
{
i1 = i + l1;
t1 = u1 * *(signal + i1) - u2 * y_startpoint[i1];
t2 = u1 * y_startpoint[i1] + u2 * *(signal + i1);
*(signal + i1) = *(signal + i) - t1;
y_startpoint[i1] = y_startpoint[i] - t2;
*(signal + i) += t1;
y_startpoint[i] += t2;
}
z = u1 * c1 - u2 * c2;
u2 = u1 * c2 + u2 * c1;
u1 = z;
}
c2 = -(sqrt((1.0 - c1) / 2.0));
c1 = sqrt((1.0 + c1) / 2.0);
}
for (i = 0; i < num_samples; i++)
{
*(signal + i) /= (double)num_samples;
*(y_startpoint + i) /= (double)num_samples;
*(signal + i) = sqrt(*(signal + i)* *(signal + i) + *(y_startpoint + i)* *(y_startpoint + i));
}
}
}
static void bit_alignment(float *data_startpoint, float *y_startpoint, uint32_t data_points)
{
uint32_t i,j,k,i2;
double tx;
i2 = data_points >> 1;
j = 0;
for (i = 0; i < data_points - 1; i++)
{
if (i < j)
{
tx = *(data_startpoint + i);
*(data_startpoint + i) = *(data_startpoint + j);
*(data_startpoint + j) = tx;
}
k = i2;
while (k <= j)
{
j -= k;
k >>= 1;
}
j += k;
*(y_startpoint + i) = 0.0;
}
}