1use crate::common::tables::{REAL_COEF_A_U16, REAL_COEF_A_U32, REAL_COEF_B_U16, REAL_COEF_B_U32};
2
3use super::{CfftI16, CfftI32};
4
5const REAL_COEF_MODULUS: usize = 8192;
6
7#[inline]
8fn i32_mul(a: i32, b: i32) -> i32 {
9 (((a as i64 * b as i64) + 0x8000_0000) >> 32) as i32
10}
11
12pub struct RfftI16 {
40 pub n_fft_real: usize,
41 pub ifft_flag: bool,
42 pub bit_reverse_flag: bool,
43 pub re_table: &'static [u16],
44 pub im_table: &'static [u16],
45}
46
47impl RfftI16 {
48 pub const fn new(n_fft_real: usize, ifft_flag: bool, bit_reverse_flag: bool) -> Self {
49 assert!(n_fft_real.is_power_of_two(), "n_fft must be a power of two");
50 assert!(
51 32 <= n_fft_real && n_fft_real <= 4096,
52 "n_fft must be in [32, 4096]",
53 );
54
55 let re_table: &'static [u16] = &REAL_COEF_A_U16;
56 let im_table: &'static [u16] = &REAL_COEF_B_U16;
57
58 Self {
59 n_fft_real,
60 ifft_flag,
61 bit_reverse_flag,
62 re_table,
63 im_table,
64 }
65 }
66
67 fn split_rfft_i16(
68 input: &[i16],
69 n_fft: usize,
70 re_table: &[u16],
71 im_table: &[u16],
72 output: &mut [i16],
73 modifier: usize,
74 ) {
75 for i in 1..n_fft {
76 let src1 = 2 * i;
77 let src2 = (2 * n_fft) - (2 * i);
78 let coef = 2 * i * modifier;
79
80 let a0 = re_table[coef] as i16 as i32;
81 let a1 = re_table[coef + 1] as i16 as i32;
82 let b0 = im_table[coef] as i16 as i32;
83 let b1 = im_table[coef + 1] as i16 as i32;
84
85 let s1r = input[src1] as i32;
86 let s1i = input[src1 + 1] as i32;
87 let s2r = input[src2] as i32;
88 let s2i = input[src2 + 1] as i32;
89
90 let out_r = ((s1r * a0) - (s1i * a1) + (s2r * b0) + (s2i * b1)) >> 16;
91 let out_i = ((s2r * b1) - (s2i * b0) + (s1i * a0) + (s1r * a1)) >> 16;
92
93 output[2 * i] = out_r as i16;
94 output[2 * i + 1] = out_i as i16;
95
96 let conj = (4 * n_fft) - src1;
97 output[conj] = out_r as i16;
98 output[conj + 1] = (out_i as i16).wrapping_neg();
99 }
100
101 output[2 * n_fft] = ((input[0] as i32 - input[1] as i32) >> 1) as i16;
102 output[2 * n_fft + 1] = 0;
103
104 output[0] = ((input[0] as i32 + input[1] as i32) >> 1) as i16;
105 output[1] = 0;
106 }
107
108 fn split_rifft_i16(
109 input: &[i16],
110 n_fft: usize,
111 re_table: &[u16],
112 im_table: &[u16],
113 output: &mut [i16],
114 modifier: usize,
115 ) {
116 for i in 0..n_fft {
117 let src1 = 2 * i;
118 let src2 = (2 * n_fft) - (2 * i);
119 let coef = 2 * i * modifier;
120
121 let a0 = re_table[coef] as i16 as i32;
122 let a1 = re_table[coef + 1] as i16 as i32;
123 let b0 = im_table[coef] as i16 as i32;
124 let b1 = im_table[coef + 1] as i16 as i32;
125
126 let s1r = input[src1] as i32;
127 let s1i = input[src1 + 1] as i32;
128 let s2r = input[src2] as i32;
129 let s2i = input[src2 + 1] as i32;
130
131 let out_r = ((s2r * b0) - (s2i * b1) + (s1r * a0) + (s1i * a1)) >> 16;
132 let out_i = ((s1i * a0) - (s1r * a1) - (s2r * b1) - (s2i * b0)) >> 16;
133
134 output[src1] = out_r as i16;
135 output[src1 + 1] = out_i as i16;
136 }
137 }
138
139 pub fn run(&self, input: &mut [i16], output: &mut [i16]) {
140 let n_fft = self.n_fft_real >> 1;
141 let modifier = REAL_COEF_MODULUS / self.n_fft_real;
142
143 if self.ifft_flag {
144 assert_eq!(
145 input.len(),
146 self.n_fft_real * 2,
147 "RIFFT input length must be 2 * n_fft_real"
148 );
149 assert_eq!(
150 output.len(),
151 self.n_fft_real,
152 "RIFFT output length must be n_fft_real"
153 );
154
155 Self::split_rifft_i16(input, n_fft, self.re_table, self.im_table, output, modifier);
156
157 CfftI16::new(n_fft, true, self.bit_reverse_flag).run(output);
158
159 for sample in output.iter_mut() {
160 let v = (*sample as i32) << 1;
161 *sample = v.clamp(i16::MIN as i32, i16::MAX as i32) as i16;
162 }
163 } else {
164 assert_eq!(
165 input.len(),
166 self.n_fft_real,
167 "RFFT input length must be n_fft_real"
168 );
169 assert_eq!(
170 output.len(),
171 self.n_fft_real * 2,
172 "RFFT output length must be 2 * n_fft_real"
173 );
174
175 CfftI16::new(n_fft, false, self.bit_reverse_flag).run(input);
176
177 Self::split_rfft_i16(input, n_fft, self.re_table, self.im_table, output, modifier);
178 }
179 }
180}
181
182pub struct RfftI32 {
210 pub n_fft_real: usize,
211 pub ifft_flag: bool,
212 pub bit_reverse_flag: bool,
213 pub re_table: &'static [u32],
214 pub im_table: &'static [u32],
215}
216
217impl RfftI32 {
218 pub const fn new(n_fft_real: usize, ifft_flag: bool, bit_reverse_flag: bool) -> Self {
219 assert!(n_fft_real.is_power_of_two(), "n_fft must be a power of two");
220 assert!(
221 32 <= n_fft_real && n_fft_real <= 8192,
222 "n_fft must be in [32, 8192]",
223 );
224
225 let re_table: &'static [u32] = &REAL_COEF_A_U32;
226 let im_table: &'static [u32] = &REAL_COEF_B_U32;
227
228 Self {
229 n_fft_real,
230 ifft_flag,
231 bit_reverse_flag,
232 re_table,
233 im_table,
234 }
235 }
236
237 fn split_rfft_i32(
238 input: &[i32],
239 n_fft: usize,
240 re_table: &[u32],
241 im_table: &[u32],
242 output: &mut [i32],
243 modifier: usize,
244 ) {
245 for i in 1..n_fft {
246 let src1 = 2 * i;
247 let src2 = (2 * n_fft) - (2 * i);
248 let coef = 2 * i * modifier;
249
250 let a0 = re_table[coef] as i32;
251 let a1 = re_table[coef + 1] as i32;
252 let b0 = im_table[coef] as i32;
253 let b1 = im_table[coef + 1] as i32;
254
255 let s1r = input[src1];
256 let s1i = input[src1 + 1];
257 let s2r = input[src2];
258 let s2i = input[src2 + 1];
259
260 let out_r = i32_mul(s1r, a0)
261 .wrapping_sub(i32_mul(s1i, a1))
262 .wrapping_add(i32_mul(s2r, b0))
263 .wrapping_add(i32_mul(s2i, b1));
264 let out_i = i32_mul(s2r, b1)
265 .wrapping_sub(i32_mul(s2i, b0))
266 .wrapping_add(i32_mul(s1i, a0))
267 .wrapping_add(i32_mul(s1r, a1));
268
269 output[2 * i] = out_r;
270 output[2 * i + 1] = out_i;
271
272 let conj = (4 * n_fft) - src1;
273 output[conj] = out_r;
274 output[conj + 1] = out_i.wrapping_neg();
275 }
276
277 output[2 * n_fft] = (input[0] - input[1]) >> 1;
278 output[2 * n_fft + 1] = 0;
279
280 output[0] = (input[0] + input[1]) >> 1;
281 output[1] = 0;
282 }
283
284 fn split_rifft_i32(
285 input: &[i32],
286 n_fft: usize,
287 re_table: &[u32],
288 im_table: &[u32],
289 output: &mut [i32],
290 modifier: usize,
291 ) {
292 for i in 0..n_fft {
293 let src1 = 2 * i;
294 let src2 = (2 * n_fft) - (2 * i);
295 let coef = 2 * i * modifier;
296
297 let a0 = re_table[coef] as i32;
298 let a1 = re_table[coef + 1] as i32;
299 let b0 = im_table[coef] as i32;
300 let b1 = im_table[coef + 1] as i32;
301
302 let s1r = input[src1];
303 let s1i = input[src1 + 1];
304 let s2r = input[src2];
305 let s2i = input[src2 + 1];
306
307 let out_r = i32_mul(s2r, b0)
308 .wrapping_sub(i32_mul(s2i, b1))
309 .wrapping_add(i32_mul(s1r, a0))
310 .wrapping_add(i32_mul(s1i, a1));
311 let out_i = i32_mul(s1i, a0)
312 .wrapping_sub(i32_mul(s1r, a1))
313 .wrapping_sub(i32_mul(s2r, b1))
314 .wrapping_sub(i32_mul(s2i, b0));
315
316 output[src1] = out_r;
317 output[src1 + 1] = out_i;
318 }
319 }
320
321 pub fn run(&self, input: &mut [i32], output: &mut [i32]) {
322 let n_fft = self.n_fft_real >> 1;
323 let modifier = REAL_COEF_MODULUS / self.n_fft_real;
324
325 if self.ifft_flag {
326 assert_eq!(
327 input.len(),
328 self.n_fft_real * 2,
329 "RIFFT input length must be 2 * n_fft_real"
330 );
331 assert_eq!(
332 output.len(),
333 self.n_fft_real,
334 "RIFFT output length must be n_fft_real"
335 );
336
337 Self::split_rifft_i32(input, n_fft, self.re_table, self.im_table, output, modifier);
338
339 CfftI32::new(n_fft, true, self.bit_reverse_flag).run(output);
340
341 for sample in output.iter_mut() {
342 *sample = sample.wrapping_shl(1);
343 }
344 } else {
345 assert_eq!(
346 input.len(),
347 self.n_fft_real,
348 "RFFT input length must be n_fft_real"
349 );
350 assert_eq!(
351 output.len(),
352 self.n_fft_real * 2,
353 "RFFT output length must be 2 * n_fft_real"
354 );
355
356 CfftI32::new(n_fft, false, self.bit_reverse_flag).run(input);
357
358 Self::split_rfft_i32(input, n_fft, self.re_table, self.im_table, output, modifier);
359 }
360 }
361}