rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
fft.hpp
Go to the documentation of this file.
1#pragma once
2
3namespace fft {
4
5#ifndef M_PI
6#define M_PI 3.1415926535897932
7#endif
8
9
10inline bool isPow(const size_t num)
11{
12 return num && (!(num & (num - 1)));
13}
14
15void rerrange(complex_type* data, const size_t num_elements)
16{
17 size_t target_index = 0;
18 size_t bit_mask;
19
21 for (size_t i = 0; i < num_elements; ++i)
22 {
23 if (target_index > i)
24 {
25 buffer = data[target_index];
26 data[target_index] = data[i];
27 data[i]= buffer;
28 }
29
30 bit_mask = num_elements;
31
32 while (target_index & (bit_mask >>= 1))
33 {
34 target_index &= ~bit_mask;
35 }
36
37 target_index |= bit_mask;
38 }
39}
40
41bool transform(complex_type* data, const size_t count)
42{
43 double local_pi = -M_PI;
44
45 size_t next, match;
46 real_type sine;
47 real_type delta;
48 complex_type mult, factor, product;
49
50 for (size_t i = 1; i < count; i <<= 1)
51 {
52 next = i << 1;
53 delta = local_pi / i;
54 sine = sin(0.5 * delta);
55
56 mult = complex_type(-2.0 * sine * sine, sin(delta));
57 factor = 1.0;
58
59 for (size_t j = 0; j < i; ++j)
60 {
61 for (size_t k = j; k < count; k += next)
62 {
63 match = k + i;
64
65 product = data[match] * factor;
66 data[match] = data[k] - product;
67 data[k] += product;
68 }
69
70 factor = mult * factor + factor;
71 }
72 }
73
74 return true;
75}
76
77static bool ffti(complex_type* data, const size_t size)
78{
79 if(!isPow(size)) {
80 return false;
81 }
82
83 rerrange(data, size);
84
85 return transform(data, size);
86}
87
88bool fft_adc_sample(float * w, float ratio, float sensitivity, const adcsample_t* data_in, complex_type* data_out, const size_t size)
89{
90 for(size_t i = 0; i < size; ++i) {
91 float voltage = ratio * data_in[i];
92 data_out[i] = complex_type(sensitivity * voltage * w[i], 0.0);
93 }
94
95 return ffti(data_out, size);
96}
97
98bool fft_adc_sample_filtered(Biquad& knockFilter, float * w, float ratio, float sensitivity, const adcsample_t* data_in, complex_type* data_out, const size_t size)
99{
100 for(size_t i = 0; i < size; ++i) {
101 float voltage = ratio * data_in[i];
102 float filtered = knockFilter.filter(voltage);
103 data_out[i] = complex_type(filtered * w[i] * sensitivity, 0.0);
104 }
105
106 return ffti(data_out, size);
107}
108
109bool fft(const real_type* data_in, complex_type* data_out, const size_t size)
110{
111 for(size_t i = 0; i < size; ++i) {
112 data_out[i] = complex_type(data_in[i], 0.0);
113 }
114
115 return ffti(data_out, size);
116}
117
118// Fast inverse square root aka "Quake 3 fast inverse square root"
119float fast_sqrt(float x) {
120 union
121 {
122 float x;
123 int32_t i;
124 } u;
125 u.x = x;
126 u.i = 0x5f375a86 - (u.i >> 1);
127 float xu = x * u.x;
128 float xu2 = xu * u.x;
129 u.x = (0.125 * 3.0) * xu * (5.0 - xu2 * ((10.0 / 3.0) - xu2));
130 return u.x;
131}
132
134 return fast_sqrt(fft.real()*fft.real() + fft.imag()*fft.imag());
135}
136
137void cosine_window(float * w, unsigned n, const float * coeff, unsigned ncoeff, bool sflag)
138{
139 if (n == 1)
140 {
141 w[0] = 1.0;
142 }
143 else
144 {
145 const unsigned wlength = sflag ? (n - 1) : n;
146
147 for (unsigned i = 0; i < n; ++i)
148 {
149 float wi = 0.0;
150
151 for (unsigned j = 0; j < ncoeff; ++j)
152 {
153 wi += coeff[j] * cos(i * j * 2.0 * M_PI / wlength);
154 }
155
156 w[i] = wi;
157 }
158 }
159}
160
161void rectwin(float * w, unsigned n)
162{
163 for (unsigned i = 0; i < n; ++i)
164 {
165 w[i] = 1.0;
166 }
167}
168
169void hann(float * w, unsigned n, bool sflag)
170{
171 const float coeff[2] = { 0.5, -0.5 };
172
173 cosine_window(w, n, coeff, sizeof(coeff) / sizeof(float), sflag);
174}
175
176void hamming(float * w, unsigned n, bool sflag)
177{
178 const float coeff[2] = { 0.54, -0.46 };
179 cosine_window(w, n, coeff, sizeof(coeff) / sizeof(float), sflag);
180}
181
182void blackman(float * w, unsigned n, bool sflag)
183{
184 const float coeff[3] = { 0.42, -0.5, 0.08 };
185 cosine_window(w, n, coeff, sizeof(coeff) / sizeof(float), sflag);
186}
187
188void blackmanharris(float * w, unsigned n, bool sflag)
189{
190 const float coeff[4] = { 0.35875, -0.48829, 0.14128, -0.01168 };
191 cosine_window(w, n, coeff, sizeof(coeff) / sizeof(float), sflag);
192}
193
194}
float filter(float input)
Definition biquad.cpp:74
uint16_t adcsample_t
ADC sample data type.
Definition fft.h:14
void rectwin(float *w, unsigned n)
Definition fft.hpp:161
static bool ffti(complex_type *data, const size_t size)
Definition fft.hpp:77
void blackman(float *w, unsigned n, bool sflag)
Definition fft.hpp:182
void rerrange(complex_type *data, const size_t num_elements)
Definition fft.hpp:15
std::complex< real_type > complex_type
Definition fft.h:17
void blackmanharris(float *w, unsigned n, bool sflag)
Definition fft.hpp:188
float amplitude(const complex_type &fft)
Definition fft.hpp:133
float fast_sqrt(float x)
Definition fft.hpp:119
void hamming(float *w, unsigned n, bool sflag)
Definition fft.hpp:176
void hann(float *w, unsigned n, bool sflag)
Definition fft.hpp:169
float real_type
Definition fft.h:16
bool transform(complex_type *data, const size_t count)
Definition fft.hpp:41
bool fft_adc_sample_filtered(Biquad &knockFilter, float *w, float ratio, float sensitivity, const adcsample_t *data_in, complex_type *data_out, const size_t size)
Definition fft.hpp:98
void cosine_window(float *w, unsigned n, const float *coeff, unsigned ncoeff, bool sflag)
Definition fft.hpp:137
bool fft_adc_sample(float *w, float ratio, float sensitivity, const adcsample_t *data_in, complex_type *data_out, const size_t size)
Definition fft.hpp:88
bool isPow(const size_t num)
Definition fft.hpp:10
static Biquad knockFilter
composite packet size
static BigBufferHandle buffer
uint16_t count
Definition tunerstudio.h:1