embedded_dsp/
transform.rs1#[allow(unused_imports)]
4use crate::math::FloatMath;
5use crate::types::*;
6
7pub fn bit_reversal(data: &mut [f32], n: usize) {
9 let mut j = 0;
10 for i in 0..n {
11 if i < j {
12 data.swap(2 * i, 2 * j);
13 data.swap(2 * i + 1, 2 * j + 1);
14 }
15 let mut m = n >> 1;
16 while m >= 1 && j >= m {
17 j -= m;
18 m >>= 1;
19 }
20 j += m;
21 }
22}
23
24pub fn cfft_f32(data: &mut [f32], n: usize, ifft_flag: u8, bit_reverse_flag: u8) {
29 if n < 2 || (n & (n - 1)) != 0 {
30 return;
31 }
32
33 if bit_reverse_flag != 0 {
34 bit_reversal(data, n);
35 }
36
37 let mut len = 2;
38 while len <= n {
39 let half_len = len / 2;
40 let angle =
41 (if ifft_flag != 0 { 2.0 } else { -2.0 }) * core::f32::consts::PI / (len as f32);
42 let w_step_re = angle.cos();
43 let w_step_im = angle.sin();
44
45 let mut i = 0;
46 while i < n {
47 let mut w_re = 1.0f32;
48 let mut w_im = 0.0f32;
49
50 for j in 0..half_len {
51 let u_idx = 2 * (i + j);
52 let v_idx = 2 * (i + j + half_len);
53
54 let u_re = data[u_idx];
55 let u_im = data[u_idx + 1];
56
57 let v_re = data[v_idx];
58 let v_im = data[v_idx + 1];
59
60 let t_re = v_re * w_re - v_im * w_im;
61 let t_im = v_re * w_im + v_im * w_re;
62
63 data[u_idx] = u_re + t_re;
64 data[u_idx + 1] = u_im + t_im;
65
66 data[v_idx] = u_re - t_re;
67 data[v_idx + 1] = u_im - t_im;
68
69 let next_w_re = w_re * w_step_re - w_im * w_step_im;
70 let next_w_im = w_re * w_step_im + w_im * w_step_re;
71 w_re = next_w_re;
72 w_im = next_w_im;
73 }
74 i += len;
75 }
76 len <<= 1;
77 }
78
79 if ifft_flag != 0 {
80 let norm = 1.0 / (n as f32);
81 for i in 0..(2 * n) {
82 data[i] *= norm;
83 }
84 }
85}
86
87pub fn cfft_q31(data: &mut [q31], n: usize, ifft_flag: u8, _bit_reverse_flag: u8) {
89 if n < 2 {
90 return;
91 }
92 let mut scratch = [0.0f32; 1024];
94 let total = 2 * n;
95 if total > scratch.len() {
96 return;
97 }
98
99 for i in 0..total {
100 scratch[i] = data[i] as f32 / 2147483648.0;
101 }
102 cfft_f32(&mut scratch[..total], n, ifft_flag, 1);
103 for i in 0..total {
104 data[i] = (scratch[i] * 2147483648.0).clamp(-2147483648.0, 2147483647.0) as q31;
105 }
106}
107
108pub fn cfft_q15(data: &mut [q15], n: usize, ifft_flag: u8, _bit_reverse_flag: u8) {
110 if n < 2 {
111 return;
112 }
113 let mut scratch = [0.0f32; 1024];
114 let total = 2 * n;
115 if total > scratch.len() {
116 return;
117 }
118
119 for i in 0..total {
120 scratch[i] = data[i] as f32 / 32768.0;
121 }
122 cfft_f32(&mut scratch[..total], n, ifft_flag, 1);
123 for i in 0..total {
124 data[i] = (scratch[i] * 32768.0).clamp(-32768.0, 32767.0) as q15;
125 }
126}
127
128pub fn rfft_f32(src: &[f32], dst: &mut [f32], n: usize, ifft_flag: u8) {
131 let len = src.len().min(n);
132 let mut c_data = [0.0f32; 1024];
133 if 2 * len > c_data.len() || dst.len() < 2 * len {
134 return;
135 }
136
137 for i in 0..len {
138 c_data[2 * i] = src[i];
139 c_data[2 * i + 1] = 0.0;
140 }
141
142 cfft_f32(&mut c_data[..2 * len], len, ifft_flag, 1);
143 dst[..2 * len].copy_from_slice(&c_data[..2 * len]);
144}
145
146pub fn rfft_q31(src: &[q31], dst: &mut [q31], n: usize, ifft_flag: u8) {
148 let len = src.len().min(n);
149 let mut c_data = [0; 1024];
150 if 2 * len > c_data.len() || dst.len() < 2 * len {
151 return;
152 }
153
154 for i in 0..len {
155 c_data[2 * i] = src[i];
156 c_data[2 * i + 1] = 0;
157 }
158 cfft_q31(&mut c_data[..2 * len], len, ifft_flag, 1);
159 dst[..2 * len].copy_from_slice(&c_data[..2 * len]);
160}
161
162pub fn rfft_q15(src: &[q15], dst: &mut [q15], n: usize, ifft_flag: u8) {
164 let len = src.len().min(n);
165 let mut c_data = [0; 1024];
166 if 2 * len > c_data.len() || dst.len() < 2 * len {
167 return;
168 }
169
170 for i in 0..len {
171 c_data[2 * i] = src[i];
172 c_data[2 * i + 1] = 0;
173 }
174 cfft_q15(&mut c_data[..2 * len], len, ifft_flag, 1);
175 dst[..2 * len].copy_from_slice(&c_data[..2 * len]);
176}
177
178pub fn dct4_f32(src: &[f32], dst: &mut [f32], n: usize) {
180 let len = src.len().min(dst.len()).min(n);
181 let pi_over_n = core::f32::consts::PI / (len as f32);
182
183 for k in 0..len {
184 let mut sum = 0.0f32;
185 let k_factor = (k as f32 + 0.5) * pi_over_n;
186 for n_idx in 0..len {
187 let angle = (n_idx as f32 + 0.5) * k_factor;
188 sum += src[n_idx] * angle.cos();
189 }
190 let norm = (2.0 / len as f32).sqrt();
191 dst[k] = sum * norm;
192 }
193}
194
195pub fn fwht_f32(data: &mut [f32]) -> Status {
201 let n = data.len();
202 if n < 2 || (n & (n - 1)) != 0 {
203 return Status::ArgumentError;
204 }
205
206 let mut h = 1;
207 while h < n {
208 let mut i = 0;
209 while i < n {
210 for j in i..(i + h) {
211 let x = data[j];
212 let y = data[j + h];
213 data[j] = x + y;
214 data[j + h] = x - y;
215 }
216 i += h * 2;
217 }
218 h *= 2;
219 }
220
221 Status::Success
222}
223
224pub fn ifwht_f32(data: &mut [f32]) -> Status {
226 let status = fwht_f32(data);
227 if status != Status::Success {
228 return status;
229 }
230 let norm = 1.0f32 / (data.len() as f32);
231 for val in data.iter_mut() {
232 *val *= norm;
233 }
234 Status::Success
235}
236
237pub fn fwht_i32(data: &mut [i32]) -> Status {
239 let n = data.len();
240 if n < 2 || (n & (n - 1)) != 0 {
241 return Status::ArgumentError;
242 }
243
244 let mut h = 1;
245 while h < n {
246 let mut i = 0;
247 while i < n {
248 for j in i..(i + h) {
249 let x = data[j];
250 let y = data[j + h];
251 data[j] = x.wrapping_add(y);
252 data[j + h] = x.wrapping_sub(y);
253 }
254 i += h * 2;
255 }
256 h *= 2;
257 }
258
259 Status::Success
260}
261
262pub fn haar_transform_f32(data: &mut [f32]) -> Status {
270 let n = data.len();
271 if n < 2 || (n & (n - 1)) != 0 {
272 return Status::ArgumentError;
273 }
274
275 let s2 = (0.5f32).sqrt();
276 let mut v = 1.0f32;
277 let mut js = 2;
278 while js <= n {
279 v *= s2;
280 let half = js >> 1;
281 let mut j = 0;
282 while j < n {
283 let t = j + half;
284 let x = data[j];
285 let y = data[t];
286 data[j] = x + y;
287 data[t] = (x - y) * v;
288 j += js;
289 }
290 js <<= 1;
291 }
292 data[0] *= v; Status::Success
295}
296
297pub fn inverse_haar_transform_f32(data: &mut [f32]) -> Status {
299 let n = data.len();
300 if n < 2 || (n & (n - 1)) != 0 {
301 return Status::ArgumentError;
302 }
303
304 let s2 = 2.0f32.sqrt();
305 let mut v = 1.0f32 / (n as f32).sqrt();
306 data[0] *= v;
307
308 let mut js = n;
309 while js >= 2 {
310 let half = js >> 1;
311 let mut j = 0;
312 while j < n {
313 let t = j + half;
314 let x = data[j];
315 let y = data[t] * v;
316 data[j] = x + y;
317 data[t] = x - y;
318 j += js;
319 }
320 v *= s2;
321 js >>= 1;
322 }
323
324 Status::Success
325}
326
327pub fn haar_transform_i32(data: &mut [i32]) -> Status {
336 let n = data.len();
337 if n < 2 || (n & (n - 1)) != 0 {
338 return Status::ArgumentError;
339 }
340
341 let mut js = 2;
342 while js <= n {
343 let half = js >> 1;
344 let mut j = 0;
345 while j < n {
346 let t = j + half;
347 let x = data[j];
348 let y = data[t];
349 data[j] = x.wrapping_add(y);
350 data[t] = x.wrapping_sub(y);
351 j += js;
352 }
353 js <<= 1;
354 }
355
356 Status::Success
357}
358
359pub fn hartley_transform_f32(data: &mut [f32]) -> Status {
373 let n = data.len();
374 if n < 2 || (n & (n - 1)) != 0 {
375 return Status::ArgumentError;
376 }
377 if 2 * n > 1024 {
378 return Status::LengthError;
379 }
380
381 let mut c_data = [0.0f32; 1024];
382 for i in 0..n {
383 c_data[2 * i] = data[i];
384 c_data[2 * i + 1] = 0.0;
385 }
386
387 cfft_f32(&mut c_data[..2 * n], n, 0, 1);
388
389 let inv_sqrt_n = 1.0 / (n as f32).sqrt();
390 for i in 0..n {
391 data[i] = (c_data[2 * i] - c_data[2 * i + 1]) * inv_sqrt_n;
392 }
393
394 Status::Success
395}
396
397pub const DAUBECHIES_4: [f32; 4] = [0.482_962_9, 0.836_516_3, 0.224_143_87, -0.129_409_52];
403
404#[inline(always)]
407fn wavelet_high_pass_tap(h: &[f32], k: usize) -> f32 {
408 let v = h[h.len() - 1 - k];
409 if k % 2 == 0 { v } else { -v }
410}
411
412pub fn wavelet_step_f32(data: &mut [f32], m: usize, h: &[f32]) -> Status {
419 let taps = h.len();
420 if m < 2 || (m & (m - 1)) != 0 || taps == 0 || taps % 2 != 0 || taps > m || data.len() < m {
421 return Status::ArgumentError;
422 }
423 if m > 1024 {
424 return Status::LengthError;
425 }
426
427 let mut scratch = [0.0f32; 1024];
428 let nh = m >> 1;
429 let mut i = 0;
430 while i < m {
431 let mut s = 0.0f32;
432 let mut d = 0.0f32;
433 for k in 0..taps {
434 let idx = (i + k) % m;
435 let x = data[idx];
436 s += h[k] * x;
437 d += wavelet_high_pass_tap(h, k) * x;
438 }
439 let j = i / 2;
440 scratch[j] = s;
441 scratch[nh + j] = d;
442 i += 2;
443 }
444 data[..m].copy_from_slice(&scratch[..m]);
445
446 Status::Success
447}
448
449pub fn inverse_wavelet_step_f32(data: &mut [f32], m: usize, h: &[f32]) -> Status {
453 let taps = h.len();
454 if m < 2 || (m & (m - 1)) != 0 || taps == 0 || taps % 2 != 0 || taps > m || data.len() < m {
455 return Status::ArgumentError;
456 }
457 if m > 1024 {
458 return Status::LengthError;
459 }
460
461 let mut scratch = [0.0f32; 1024];
462 let nh = m >> 1;
463 for j in 0..nh {
464 let s = data[j];
465 let d = data[nh + j];
466 for k in 0..taps {
467 let idx = (2 * j + k) % m;
468 scratch[idx] += h[k] * s + wavelet_high_pass_tap(h, k) * d;
469 }
470 }
471 data[..m].copy_from_slice(&scratch[..m]);
472
473 Status::Success
474}
475
476pub fn wavelet_transform_f32(data: &mut [f32], h: &[f32]) -> Status {
483 let n = data.len();
484 if n < 2 || (n & (n - 1)) != 0 || h.len() > n {
485 return Status::ArgumentError;
486 }
487
488 let mut m = n;
489 while m >= h.len() {
490 let status = wavelet_step_f32(&mut data[..m], m, h);
491 if status != Status::Success {
492 return status;
493 }
494 m >>= 1;
495 }
496
497 Status::Success
498}
499
500pub fn inverse_wavelet_transform_f32(data: &mut [f32], h: &[f32]) -> Status {
504 let n = data.len();
505 if n < 2 || (n & (n - 1)) != 0 || h.len() > n {
506 return Status::ArgumentError;
507 }
508
509 let mut smallest = n;
510 while smallest >= h.len() {
511 smallest >>= 1;
512 }
513 smallest <<= 1;
514
515 let mut m = smallest;
516 while m <= n {
517 let status = inverse_wavelet_step_f32(&mut data[..m], m, h);
518 if status != Status::Success {
519 return status;
520 }
521 m <<= 1;
522 }
523
524 Status::Success
525}