1#![no_std]
45
46use core::slice;
47use num_complex::Complex;
48
49type Q15 = i16;
50
51pub enum Direction {
52 Forward,
54
55 ForwardScaled,
59
60 Inverse,
62}
63
64#[derive(Debug, Clone, Copy, PartialEq)]
65pub enum FFTError {
66 InvalidFFTSize,
67 InvalidDataSize,
68}
69
70const SINETAB_LD_N: usize = 10;
71const SINETAB_N: usize = 1 << SINETAB_LD_N;
72
73static SINETAB: [i16; SINETAB_N - SINETAB_N / 4] = [
75 0, 201, 402, 603, 804, 1005, 1206, 1407, 1608, 1809, 2009, 2210, 2410, 2611, 2811, 3012, 3212,
76 3412, 3612, 3811, 4011, 4210, 4410, 4609, 4808, 5007, 5205, 5404, 5602, 5800, 5998, 6195, 6393,
77 6590, 6786, 6983, 7179, 7375, 7571, 7767, 7962, 8157, 8351, 8545, 8739, 8933, 9126, 9319, 9512,
78 9704, 9896, 10087, 10278, 10469, 10659, 10849, 11039, 11228, 11417, 11605, 11793, 11980, 12167,
79 12353, 12539, 12725, 12910, 13094, 13279, 13462, 13645, 13828, 14010, 14191, 14372, 14553,
80 14732, 14912, 15090, 15269, 15446, 15623, 15800, 15976, 16151, 16325, 16499, 16673, 16846,
81 17018, 17189, 17360, 17530, 17700, 17869, 18037, 18204, 18371, 18537, 18703, 18868, 19032,
82 19195, 19357, 19519, 19680, 19841, 20000, 20159, 20317, 20475, 20631, 20787, 20942, 21096,
83 21250, 21403, 21554, 21705, 21856, 22005, 22154, 22301, 22448, 22594, 22739, 22884, 23027,
84 23170, 23311, 23452, 23592, 23731, 23870, 24007, 24143, 24279, 24413, 24547, 24680, 24811,
85 24942, 25072, 25201, 25329, 25456, 25582, 25708, 25832, 25955, 26077, 26198, 26319, 26438,
86 26556, 26674, 26790, 26905, 27019, 27133, 27245, 27356, 27466, 27575, 27683, 27790, 27896,
87 28001, 28105, 28208, 28310, 28411, 28510, 28609, 28706, 28803, 28898, 28992, 29085, 29177,
88 29268, 29358, 29447, 29534, 29621, 29706, 29791, 29874, 29956, 30037, 30117, 30195, 30273,
89 30349, 30424, 30498, 30571, 30643, 30714, 30783, 30852, 30919, 30985, 31050, 31113, 31176,
90 31237, 31297, 31356, 31414, 31470, 31526, 31580, 31633, 31685, 31736, 31785, 31833, 31880,
91 31926, 31971, 32014, 32057, 32098, 32137, 32176, 32213, 32250, 32285, 32318, 32351, 32382,
92 32412, 32441, 32469, 32495, 32521, 32545, 32567, 32589, 32609, 32628, 32646, 32663, 32678,
93 32692, 32705, 32717, 32728, 32737, 32745, 32752, 32757, 32761, 32765, 32766, 32767, 32766,
94 32765, 32761, 32757, 32752, 32745, 32737, 32728, 32717, 32705, 32692, 32678, 32663, 32646,
95 32628, 32609, 32589, 32567, 32545, 32521, 32495, 32469, 32441, 32412, 32382, 32351, 32318,
96 32285, 32250, 32213, 32176, 32137, 32098, 32057, 32014, 31971, 31926, 31880, 31833, 31785,
97 31736, 31685, 31633, 31580, 31526, 31470, 31414, 31356, 31297, 31237, 31176, 31113, 31050,
98 30985, 30919, 30852, 30783, 30714, 30643, 30571, 30498, 30424, 30349, 30273, 30195, 30117,
99 30037, 29956, 29874, 29791, 29706, 29621, 29534, 29447, 29358, 29268, 29177, 29085, 28992,
100 28898, 28803, 28706, 28609, 28510, 28411, 28310, 28208, 28105, 28001, 27896, 27790, 27683,
101 27575, 27466, 27356, 27245, 27133, 27019, 26905, 26790, 26674, 26556, 26438, 26319, 26198,
102 26077, 25955, 25832, 25708, 25582, 25456, 25329, 25201, 25072, 24942, 24811, 24680, 24547,
103 24413, 24279, 24143, 24007, 23870, 23731, 23592, 23452, 23311, 23170, 23027, 22884, 22739,
104 22594, 22448, 22301, 22154, 22005, 21856, 21705, 21554, 21403, 21250, 21096, 20942, 20787,
105 20631, 20475, 20317, 20159, 20000, 19841, 19680, 19519, 19357, 19195, 19032, 18868, 18703,
106 18537, 18371, 18204, 18037, 17869, 17700, 17530, 17360, 17189, 17018, 16846, 16673, 16499,
107 16325, 16151, 15976, 15800, 15623, 15446, 15269, 15090, 14912, 14732, 14553, 14372, 14191,
108 14010, 13828, 13645, 13462, 13279, 13094, 12910, 12725, 12539, 12353, 12167, 11980, 11793,
109 11605, 11417, 11228, 11039, 10849, 10659, 10469, 10278, 10087, 9896, 9704, 9512, 9319, 9126,
110 8933, 8739, 8545, 8351, 8157, 7962, 7767, 7571, 7375, 7179, 6983, 6786, 6590, 6393, 6195, 5998,
111 5800, 5602, 5404, 5205, 5007, 4808, 4609, 4410, 4210, 4011, 3811, 3612, 3412, 3212, 3012, 2811,
112 2611, 2410, 2210, 2009, 1809, 1608, 1407, 1206, 1005, 804, 603, 402, 201, 0, -201, -402, -603,
113 -804, -1005, -1206, -1407, -1608, -1809, -2009, -2210, -2410, -2611, -2811, -3012, -3212,
114 -3412, -3612, -3811, -4011, -4210, -4410, -4609, -4808, -5007, -5205, -5404, -5602, -5800,
115 -5998, -6195, -6393, -6590, -6786, -6983, -7179, -7375, -7571, -7767, -7962, -8157, -8351,
116 -8545, -8739, -8933, -9126, -9319, -9512, -9704, -9896, -10087, -10278, -10469, -10659, -10849,
117 -11039, -11228, -11417, -11605, -11793, -11980, -12167, -12353, -12539, -12725, -12910, -13094,
118 -13279, -13462, -13645, -13828, -14010, -14191, -14372, -14553, -14732, -14912, -15090, -15269,
119 -15446, -15623, -15800, -15976, -16151, -16325, -16499, -16673, -16846, -17018, -17189, -17360,
120 -17530, -17700, -17869, -18037, -18204, -18371, -18537, -18703, -18868, -19032, -19195, -19357,
121 -19519, -19680, -19841, -20000, -20159, -20317, -20475, -20631, -20787, -20942, -21096, -21250,
122 -21403, -21554, -21705, -21856, -22005, -22154, -22301, -22448, -22594, -22739, -22884, -23027,
123 -23170, -23311, -23452, -23592, -23731, -23870, -24007, -24143, -24279, -24413, -24547, -24680,
124 -24811, -24942, -25072, -25201, -25329, -25456, -25582, -25708, -25832, -25955, -26077, -26198,
125 -26319, -26438, -26556, -26674, -26790, -26905, -27019, -27133, -27245, -27356, -27466, -27575,
126 -27683, -27790, -27896, -28001, -28105, -28208, -28310, -28411, -28510, -28609, -28706, -28803,
127 -28898, -28992, -29085, -29177, -29268, -29358, -29447, -29534, -29621, -29706, -29791, -29874,
128 -29956, -30037, -30117, -30195, -30273, -30349, -30424, -30498, -30571, -30643, -30714, -30783,
129 -30852, -30919, -30985, -31050, -31113, -31176, -31237, -31297, -31356, -31414, -31470, -31526,
130 -31580, -31633, -31685, -31736, -31785, -31833, -31880, -31926, -31971, -32014, -32057, -32098,
131 -32137, -32176, -32213, -32250, -32285, -32318, -32351, -32382, -32412, -32441, -32469, -32495,
132 -32521, -32545, -32567, -32589, -32609, -32628, -32646, -32663, -32678, -32692, -32705, -32717,
133 -32728, -32737, -32745, -32752, -32757, -32761, -32765, -32766,
134];
135
136fn q15_cmul(a: Complex<Q15>, b: Complex<Q15>) -> Complex<Q15> {
138 let rnd: i32 = 1 << 14; Complex::new(
140 ((a.re as i32 * b.re as i32 - a.im as i32 * b.im as i32 + rnd) >> 15) as i16,
141 ((a.re as i32 * b.im as i32 + a.im as i32 * b.re as i32 + rnd) >> 15) as i16,
142 )
143}
144
145fn check_size(size: usize) -> Result<(), FFTError> {
146 if !(2..=SINETAB_N).contains(&size) {
147 return Err(FFTError::InvalidFFTSize);
148 }
149 const MSB: usize = (usize::MAX >> 1) + 1;
150 let allowed_size = MSB >> (size.leading_zeros());
151 if allowed_size != size {
152 return Err(FFTError::InvalidFFTSize);
153 }
154 Ok(())
155}
156
157pub fn fft_radix2_q15(data: &mut [Complex<Q15>], dir: Direction) -> Result<(), FFTError> {
165 let fft_size = data.len();
166 check_size(fft_size)?;
167 let (inverse, shift) = match dir {
168 Direction::Forward => (false, 0),
169 Direction::ForwardScaled => (false, 1),
170 Direction::Inverse => (true, 1),
171 };
172
173 let mut mr = 0usize; for m in 1..fft_size {
176 const MSB: usize = (usize::MAX >> 1) + 1;
177 let l = MSB >> (fft_size - 1 - mr).leading_zeros();
178 mr = (mr & (l - 1)) + l;
179 if mr > m {
180 data.swap(m, mr);
181 }
182 }
183
184 let mut stage = 1;
185 let mut sine_step = (SINETAB_LD_N - 1) as isize;
186 while stage < fft_size {
188 let twiddle_step = stage << 1;
190 for group in 0..stage {
191 let sin_ndx = group << sine_step;
193 let wr = SINETAB[sin_ndx + SINETAB_N / 4] >> shift;
194 let wi = match inverse {
195 false => -SINETAB[sin_ndx],
196 true => SINETAB[sin_ndx],
197 } >> shift;
198 let w = Complex::new(wr, wi);
199 let mut i = group;
201 while i < fft_size {
202 let j = i + stage;
203 let temp = q15_cmul(w, data[j]);
204
205 let q = Complex::new(data[i].re >> shift, data[i].im >> shift);
206 data[i] = q + temp;
207 data[j] = q - temp;
208 i += twiddle_step;
209 }
210 }
211 sine_step -= 1;
212 stage = twiddle_step;
213 }
214 Ok(())
215}
216
217pub fn fft_radix2_real_q15(
224 input: &mut [i16],
225 output: &mut [Complex<Q15>],
226 scale: bool,
227) -> Result<(), FFTError> {
228 let fft_len = input.len();
229 check_size(fft_len)?;
230 let half_fft_len = fft_len / 2;
231 if output.len() < half_fft_len + 1 {
232 return Err(FFTError::InvalidDataSize);
233 }
234
235 let ptr = input.as_mut_ptr() as *mut Complex<Q15>;
238 let fft_out = unsafe { slice::from_raw_parts_mut(ptr, half_fft_len) };
239
240 fft_radix2_q15(
242 &mut fft_out[0..half_fft_len],
243 if scale {
244 Direction::ForwardScaled
245 } else {
246 Direction::Forward
247 },
248 )?;
249
250 let shift = scale as usize;
251 output[0] = Complex::new((fft_out[0].im + fft_out[0].re) >> shift, 0);
253 for k in 1..half_fft_len {
254 let sin_ndx = k * SINETAB_N / fft_len;
256 let w = Complex::new(SINETAB[sin_ndx + SINETAB_N / 4], -SINETAB[sin_ndx]);
257
258 let zo = Complex::new(
260 (fft_out[half_fft_len - k].im + fft_out[k].im) >> (shift + 1),
261 (fft_out[half_fft_len - k].re - fft_out[k].re) >> (shift + 1),
262 );
263 let ze = Complex::new(
264 (fft_out[k].re + fft_out[half_fft_len - k].re) >> (shift + 1),
265 (fft_out[k].im - fft_out[half_fft_len - k].im) >> (shift + 1),
266 );
267 let r = ze + q15_cmul(zo, w);
268 output[k] = r;
269 }
270 output[half_fft_len] = Complex::new((fft_out[0].re - fft_out[0].im) >> shift, 0);
271
272 Ok(())
273}
274
275#[cfg(test)]
276mod tests {
277
278 extern crate alloc;
279 use super::{check_size, FFTError, Q15, SINETAB, SINETAB_LD_N, SINETAB_N};
280 use alloc::vec::Vec;
281 use core::f64;
282 use core::mem::size_of;
283 use num_complex::Complex;
284
285 #[test]
287 fn verify_sinewave() {
288 for (i, v) in SINETAB.iter().enumerate() {
289 let fval = 32767.0 * f64::sin(2.0 * f64::consts::PI * (i as f64) / (SINETAB_N as f64));
290 let rval = fval.round() as i16;
291 assert_eq!(*v, rval);
292 }
293 }
294
295 #[test]
298 fn check_complex_lenth() {
299 assert_eq!(size_of::<Complex<Q15>>(), 2 * size_of::<Q15>());
300 }
301
302 #[test]
303 fn check_size_test() {
304 let valid = (1..=SINETAB_LD_N).map(|k| 1 << k).collect::<Vec<usize>>();
305 for s in 0..=SINETAB_N * 2 {
306 let result = check_size(s);
307 if valid.contains(&s) {
308 assert_eq!(result, Ok(()));
309 } else {
310 assert_eq!(result, Err(FFTError::InvalidFFTSize))
311 }
312 }
313 }
314}