1use crate::types::*;
4
5pub struct FirInstanceF32<'a> {
9 pub num_taps: u16,
10 pub coeffs: &'a [f32],
11 pub state: &'a mut [f32],
12}
13
14impl<'a> FirInstanceF32<'a> {
15 pub fn init(num_taps: u16, coeffs: &'a [f32], state: &'a mut [f32]) -> Self {
16 state.fill(0.0);
17 Self {
18 num_taps,
19 coeffs,
20 state,
21 }
22 }
23}
24
25pub fn fir_f32(instance: &mut FirInstanceF32, src: &[f32], dst: &mut [f32]) {
26 let num_taps = instance.num_taps as usize;
27 let block_size = src.len().min(dst.len());
28
29 for i in 0..block_size {
30 for k in (1..num_taps).rev() {
32 instance.state[k] = instance.state[k - 1];
33 }
34 instance.state[0] = src[i];
35
36 let mut acc = 0.0f32;
38 for k in 0..num_taps {
39 acc += instance.state[k] * instance.coeffs[k];
40 }
41 dst[i] = acc;
42 }
43}
44
45pub struct FirInstanceQ31<'a> {
47 pub num_taps: u16,
48 pub coeffs: &'a [q31],
49 pub state: &'a mut [q31],
50}
51
52impl<'a> FirInstanceQ31<'a> {
53 pub fn init(num_taps: u16, coeffs: &'a [q31], state: &'a mut [q31]) -> Self {
54 state.fill(0);
55 Self {
56 num_taps,
57 coeffs,
58 state,
59 }
60 }
61}
62
63pub fn fir_q31(instance: &mut FirInstanceQ31, src: &[q31], dst: &mut [q31]) {
64 let num_taps = instance.num_taps as usize;
65 let block_size = src.len().min(dst.len());
66
67 for i in 0..block_size {
68 for k in (1..num_taps).rev() {
69 instance.state[k] = instance.state[k - 1];
70 }
71 instance.state[0] = src[i];
72
73 let mut acc: i64 = 0;
74 for k in 0..num_taps {
75 acc += (instance.state[k] as i64 * instance.coeffs[k] as i64) >> 31;
76 }
77 dst[i] = acc.clamp(i32::MIN as i64, i32::MAX as i64) as q31;
78 }
79}
80
81pub struct FirInstanceQ15<'a> {
83 pub num_taps: u16,
84 pub coeffs: &'a [q15],
85 pub state: &'a mut [q15],
86}
87
88impl<'a> FirInstanceQ15<'a> {
89 pub fn init(num_taps: u16, coeffs: &'a [q15], state: &'a mut [q15]) -> Self {
90 state.fill(0);
91 Self {
92 num_taps,
93 coeffs,
94 state,
95 }
96 }
97}
98
99pub fn fir_q15(instance: &mut FirInstanceQ15, src: &[q15], dst: &mut [q15]) {
100 let num_taps = instance.num_taps as usize;
101 let block_size = src.len().min(dst.len());
102
103 for i in 0..block_size {
104 for k in (1..num_taps).rev() {
105 instance.state[k] = instance.state[k - 1];
106 }
107 instance.state[0] = src[i];
108
109 let mut acc: i32 = 0;
110 for k in 0..num_taps {
111 acc += (instance.state[k] as i32 * instance.coeffs[k] as i32) >> 15;
112 }
113 dst[i] = acc.clamp(i16::MIN as i32, i16::MAX as i32) as q15;
114 }
115}
116
117pub struct BiquadCascadeInstanceF32<'a> {
121 pub num_stages: u8,
122 pub coeffs: &'a [f32], pub state: &'a mut [f32], }
125
126impl<'a> BiquadCascadeInstanceF32<'a> {
127 pub fn init(num_stages: u8, coeffs: &'a [f32], state: &'a mut [f32]) -> Self {
128 state.fill(0.0);
129 Self {
130 num_stages,
131 coeffs,
132 state,
133 }
134 }
135}
136
137pub fn biquad_cascade_df1_f32(
138 instance: &mut BiquadCascadeInstanceF32,
139 src: &[f32],
140 dst: &mut [f32],
141) {
142 let num_stages = instance.num_stages as usize;
143 let block_size = src.len().min(dst.len());
144
145 let mut in_val;
146 let mut out_val;
147
148 for i in 0..block_size {
149 in_val = src[i];
150 for stage in 0..num_stages {
151 let b0 = instance.coeffs[stage * 5];
152 let b1 = instance.coeffs[stage * 5 + 1];
153 let b2 = instance.coeffs[stage * 5 + 2];
154 let a1 = instance.coeffs[stage * 5 + 3];
155 let a2 = instance.coeffs[stage * 5 + 4];
156
157 let x1 = instance.state[stage * 4];
158 let x2 = instance.state[stage * 4 + 1];
159 let y1 = instance.state[stage * 4 + 2];
160 let y2 = instance.state[stage * 4 + 3];
161
162 out_val = b0 * in_val + b1 * x1 + b2 * x2 + a1 * y1 + a2 * y2;
163
164 instance.state[stage * 4 + 1] = x1;
165 instance.state[stage * 4] = in_val;
166 instance.state[stage * 4 + 3] = y1;
167 instance.state[stage * 4 + 2] = out_val;
168
169 in_val = out_val;
170 }
171 dst[i] = in_val;
172 }
173}
174
175pub struct LmsInstanceF32<'a> {
179 pub num_taps: u16,
180 pub coeffs: &'a mut [f32],
181 pub state: &'a mut [f32],
182 pub mu: f32,
183}
184
185impl<'a> LmsInstanceF32<'a> {
186 pub fn init(num_taps: u16, coeffs: &'a mut [f32], state: &'a mut [f32], mu: f32) -> Self {
187 state.fill(0.0);
188 coeffs.fill(0.0);
189 Self {
190 num_taps,
191 coeffs,
192 state,
193 mu,
194 }
195 }
196}
197
198pub fn lms_f32(
199 instance: &mut LmsInstanceF32,
200 src: &[f32],
201 ref_signal: &[f32],
202 out: &mut [f32],
203 err: &mut [f32],
204) {
205 let num_taps = instance.num_taps as usize;
206 let block_size = src
207 .len()
208 .min(ref_signal.len())
209 .min(out.len())
210 .min(err.len());
211
212 for i in 0..block_size {
213 for k in (1..num_taps).rev() {
214 instance.state[k] = instance.state[k - 1];
215 }
216 instance.state[0] = src[i];
217
218 let mut acc = 0.0f32;
219 for k in 0..num_taps {
220 acc += instance.state[k] * instance.coeffs[k];
221 }
222 out[i] = acc;
223 let e = ref_signal[i] - acc;
224 err[i] = e;
225
226 let alpha = 2.0 * instance.mu * e;
228 for k in 0..num_taps {
229 instance.coeffs[k] += alpha * instance.state[k];
230 }
231 }
232}
233
234pub fn conv_f32(src_a: &[f32], src_b: &[f32], dst: &mut [f32]) {
237 let len_a = src_a.len();
238 let len_b = src_b.len();
239 let out_len = (len_a + len_b - 1).min(dst.len());
240
241 dst[..out_len].fill(0.0);
242 for i in 0..len_a {
243 for j in 0..len_b {
244 if i + j < out_len {
245 dst[i + j] += src_a[i] * src_b[j];
246 }
247 }
248 }
249}
250
251pub fn conv_q31(src_a: &[q31], src_b: &[q31], dst: &mut [q31]) {
252 let len_a = src_a.len();
253 let len_b = src_b.len();
254 let out_len = (len_a + len_b - 1).min(dst.len());
255
256 for n in 0..out_len {
257 let mut acc: i64 = 0;
258 let k_min = if n >= len_b - 1 { n - (len_b - 1) } else { 0 };
259 let k_max = n.min(len_a - 1);
260 for k in k_min..=k_max {
261 acc += (src_a[k] as i64 * src_b[n - k] as i64) >> 31;
262 }
263 dst[n] = acc.clamp(i32::MIN as i64, i32::MAX as i64) as q31;
264 }
265}
266
267pub fn conv_q15(src_a: &[q15], src_b: &[q15], dst: &mut [q15]) {
268 let len_a = src_a.len();
269 let len_b = src_b.len();
270 let out_len = (len_a + len_b - 1).min(dst.len());
271
272 for n in 0..out_len {
273 let mut acc: i32 = 0;
274 let k_min = if n >= len_b - 1 { n - (len_b - 1) } else { 0 };
275 let k_max = n.min(len_a - 1);
276 for k in k_min..=k_max {
277 acc += (src_a[k] as i32 * src_b[n - k] as i32) >> 15;
278 }
279 dst[n] = acc.clamp(i16::MIN as i32, i16::MAX as i32) as q15;
280 }
281}
282
283pub fn conv_q7(src_a: &[q7], src_b: &[q7], dst: &mut [q7]) {
284 let len_a = src_a.len();
285 let len_b = src_b.len();
286 let out_len = (len_a + len_b - 1).min(dst.len());
287
288 for n in 0..out_len {
289 let mut acc: i32 = 0;
290 let k_min = if n >= len_b - 1 { n - (len_b - 1) } else { 0 };
291 let k_max = n.min(len_a - 1);
292 for k in k_min..=k_max {
293 acc += (src_a[k] as i32 * src_b[n - k] as i32) >> 7;
294 }
295 dst[n] = acc.clamp(i8::MIN as i32, i8::MAX as i32) as q7;
296 }
297}
298
299pub fn correlate_f32(src_a: &[f32], src_b: &[f32], dst: &mut [f32]) {
302 let len_a = src_a.len();
303 let len_b = src_b.len();
304 let out_len = (len_a + len_b - 1).min(dst.len());
305
306 dst[..out_len].fill(0.0);
307 for n in 0..out_len {
308 let mut acc = 0.0f32;
309 for k in 0..len_a {
310 let idx_b = (k as isize) + (len_b as isize - 1) - (n as isize);
311 if idx_b >= 0 && (idx_b as usize) < len_b {
312 acc += src_a[k] * src_b[idx_b as usize];
313 }
314 }
315 dst[n] = acc;
316 }
317}
318
319pub fn correlate_q31(src_a: &[q31], src_b: &[q31], dst: &mut [q31]) {
320 let len_a = src_a.len();
321 let len_b = src_b.len();
322 let out_len = (len_a + len_b - 1).min(dst.len());
323
324 for n in 0..out_len {
325 let mut acc: i64 = 0;
326 for k in 0..len_a {
327 let idx_b = (k as isize) + (len_b as isize - 1) - (n as isize);
328 if idx_b >= 0 && (idx_b as usize) < len_b {
329 acc += (src_a[k] as i64 * src_b[idx_b as usize] as i64) >> 31;
330 }
331 }
332 dst[n] = acc.clamp(i32::MIN as i64, i32::MAX as i64) as q31;
333 }
334}
335
336pub fn correlate_q15(src_a: &[q15], src_b: &[q15], dst: &mut [q15]) {
337 let len_a = src_a.len();
338 let len_b = src_b.len();
339 let out_len = (len_a + len_b - 1).min(dst.len());
340
341 for n in 0..out_len {
342 let mut acc: i32 = 0;
343 for k in 0..len_a {
344 let idx_b = (k as isize) + (len_b as isize - 1) - (n as isize);
345 if idx_b >= 0 && (idx_b as usize) < len_b {
346 acc += (src_a[k] as i32 * src_b[idx_b as usize] as i32) >> 15;
347 }
348 }
349 dst[n] = acc.clamp(i16::MIN as i32, i16::MAX as i32) as q15;
350 }
351}
352
353#[allow(unused_imports)]
356use crate::math::FloatMath;
357use crate::transform::cfft_f32;
358
359pub fn median_filter_1d_f32(
366 src: &[f32],
367 dst: &mut [f32],
368 window_len: usize,
369 threshold: f32,
370) -> Status {
371 let n = src.len();
372 if n == 0 || dst.len() < n {
373 return Status::LengthError;
374 }
375 if window_len == 0 || window_len % 2 == 0 || window_len > 63 {
376 return Status::ArgumentError;
377 }
378
379 let half = window_len / 2;
380 let mut sort_buf = [0.0f32; 64];
381
382 for i in 0..n {
383 for j in 0..window_len {
385 let idx = (i as isize + j as isize - half as isize).clamp(0, (n - 1) as isize) as usize;
386 sort_buf[j] = src[idx];
387 }
388
389 for a in 1..window_len {
391 let mut b = a;
392 while b > 0 && sort_buf[b - 1] > sort_buf[b] {
393 sort_buf.swap(b - 1, b);
394 b -= 1;
395 }
396 }
397
398 let med = sort_buf[half];
399 let center = src[i];
400 if (center - med).abs() >= threshold {
401 dst[i] = med;
402 } else {
403 dst[i] = center;
404 }
405 }
406
407 Status::Success
408}
409
410pub fn median_filter_1d_q15(
412 src: &[q15],
413 dst: &mut [q15],
414 window_len: usize,
415 threshold: q15,
416) -> Status {
417 let n = src.len();
418 if n == 0 || dst.len() < n {
419 return Status::LengthError;
420 }
421 if window_len == 0 || window_len % 2 == 0 || window_len > 63 {
422 return Status::ArgumentError;
423 }
424
425 let half = window_len / 2;
426 let mut sort_buf = [0i16; 64];
427
428 for i in 0..n {
429 for j in 0..window_len {
430 let idx = (i as isize + j as isize - half as isize).clamp(0, (n - 1) as isize) as usize;
431 sort_buf[j] = src[idx];
432 }
433
434 for a in 1..window_len {
435 let mut b = a;
436 while b > 0 && sort_buf[b - 1] > sort_buf[b] {
437 sort_buf.swap(b - 1, b);
438 b -= 1;
439 }
440 }
441
442 let med = sort_buf[half];
443 let center = src[i];
444 let diff = (center as i32 - med as i32).abs();
445 if diff >= threshold as i32 {
446 dst[i] = med;
447 } else {
448 dst[i] = center;
449 }
450 }
451
452 Status::Success
453}
454
455pub fn median_filter_1d_q31(
457 src: &[q31],
458 dst: &mut [q31],
459 window_len: usize,
460 threshold: q31,
461) -> Status {
462 let n = src.len();
463 if n == 0 || dst.len() < n {
464 return Status::LengthError;
465 }
466 if window_len == 0 || window_len % 2 == 0 || window_len > 63 {
467 return Status::ArgumentError;
468 }
469
470 let half = window_len / 2;
471 let mut sort_buf = [0i32; 64];
472
473 for i in 0..n {
474 for j in 0..window_len {
475 let idx = (i as isize + j as isize - half as isize).clamp(0, (n - 1) as isize) as usize;
476 sort_buf[j] = src[idx];
477 }
478
479 for a in 1..window_len {
480 let mut b = a;
481 while b > 0 && sort_buf[b - 1] > sort_buf[b] {
482 sort_buf.swap(b - 1, b);
483 b -= 1;
484 }
485 }
486
487 let med = sort_buf[half];
488 let center = src[i];
489 let diff = (center as i64 - med as i64).abs();
490 if diff >= threshold as i64 {
491 dst[i] = med;
492 } else {
493 dst[i] = center;
494 }
495 }
496
497 Status::Success
498}
499
500pub fn fast_convolve_f32(signal: &[f32], kernel: &[f32], dst: &mut [f32]) -> Status {
505 let len_sig = signal.len();
506 let len_ker = kernel.len();
507 if len_sig == 0 || len_ker == 0 {
508 return Status::LengthError;
509 }
510 let total_len = len_sig + len_ker - 1;
511 if dst.len() < total_len {
512 return Status::LengthError;
513 }
514
515 let mut fft_n = 1;
517 while fft_n < total_len {
518 fft_n <<= 1;
519 }
520
521 if fft_n > 512 {
522 conv_f32(signal, kernel, dst);
524 return Status::Success;
525 }
526
527 let mut sig_buf = [0.0f32; 1024]; let mut ker_buf = [0.0f32; 1024];
529
530 for i in 0..len_sig {
531 sig_buf[2 * i] = signal[i];
532 }
533 for i in 0..len_ker {
534 ker_buf[2 * i] = kernel[i];
535 }
536
537 cfft_f32(&mut sig_buf[..2 * fft_n], fft_n, 0, 1);
538 cfft_f32(&mut ker_buf[..2 * fft_n], fft_n, 0, 1);
539
540 for i in 0..fft_n {
542 let a = sig_buf[2 * i];
543 let b = sig_buf[2 * i + 1];
544 let c = ker_buf[2 * i];
545 let d = ker_buf[2 * i + 1];
546 sig_buf[2 * i] = a * c - b * d;
547 sig_buf[2 * i + 1] = a * d + b * c;
548 }
549
550 cfft_f32(&mut sig_buf[..2 * fft_n], fft_n, 1, 1);
552
553 for i in 0..total_len {
554 dst[i] = sig_buf[2 * i];
555 }
556
557 Status::Success
558}
559
560#[derive(Debug, Clone, Copy)]
564pub struct CircularBuffer<T, const N: usize> {
565 buffer: [T; N],
566 head: usize,
567 count: usize,
568}
569
570impl<T: Copy, const N: usize> CircularBuffer<T, N> {
571 pub const fn new(init_val: T) -> Self {
573 Self {
574 buffer: [init_val; N],
575 head: 0,
576 count: 0,
577 }
578 }
579
580 #[inline(always)]
582 pub fn push(&mut self, sample: T) {
583 if N == 0 {
584 return;
585 }
586 self.buffer[self.head] = sample;
587 self.head = (self.head + 1) % N;
588 if self.count < N {
589 self.count += 1;
590 }
591 }
592
593 #[inline(always)]
596 pub fn get(&self, lag: usize) -> Option<T> {
597 if lag >= self.count || N == 0 {
598 return None;
599 }
600 let idx = (self.head + N - 1 - (lag % N)) % N;
601 Some(self.buffer[idx])
602 }
603
604 #[inline(always)]
606 pub fn latest(&self) -> Option<T> {
607 self.get(0)
608 }
609
610 #[inline(always)]
612 pub fn oldest(&self) -> Option<T> {
613 if self.count == 0 {
614 None
615 } else {
616 self.get(self.count - 1)
617 }
618 }
619
620 #[inline(always)]
622 pub const fn len(&self) -> usize {
623 self.count
624 }
625
626 #[inline(always)]
628 pub const fn capacity(&self) -> usize {
629 N
630 }
631
632 #[inline(always)]
634 pub const fn is_empty(&self) -> bool {
635 self.count == 0
636 }
637
638 #[inline(always)]
640 pub const fn is_full(&self) -> bool {
641 self.count == N
642 }
643
644 pub fn clear(&mut self, reset_val: T) {
646 self.buffer = [reset_val; N];
647 self.head = 0;
648 self.count = 0;
649 }
650}
651
652#[derive(Debug, Clone, Copy, Default)]
660#[cfg_attr(feature = "defmt", derive(defmt::Format))]
661pub struct SinglePoleFilter {
662 b0: f32,
663 b1: f32,
664 a1: f32,
665 x1: f32,
666 y1: f32,
667}
668
669impl SinglePoleFilter {
670 pub fn lowpass(decay: f32) -> Self {
673 Self {
674 b0: 1.0 - decay,
675 b1: 0.0,
676 a1: decay,
677 x1: 0.0,
678 y1: 0.0,
679 }
680 }
681
682 pub fn highpass(decay: f32) -> Self {
685 let b0 = (1.0 + decay) / 2.0;
686 Self {
687 b0,
688 b1: -b0,
689 a1: decay,
690 x1: 0.0,
691 y1: 0.0,
692 }
693 }
694
695 #[inline(always)]
697 pub fn process(&mut self, x: f32) -> f32 {
698 let y = self.b0 * x + self.b1 * self.x1 + self.a1 * self.y1;
699 self.x1 = x;
700 self.y1 = y;
701 y
702 }
703
704 pub fn reset(&mut self) {
706 self.x1 = 0.0;
707 self.y1 = 0.0;
708 }
709}
710
711#[derive(Debug, Clone)]
717#[cfg_attr(feature = "defmt", derive(defmt::Format))]
718pub struct RecursiveMovingAverage<const N: usize> {
719 history: CircularBuffer<f32, N>,
720 sum: f32,
721}
722
723impl<const N: usize> RecursiveMovingAverage<N> {
724 pub const fn new() -> Self {
726 Self {
727 history: CircularBuffer::new(0.0),
728 sum: 0.0,
729 }
730 }
731
732 #[inline(always)]
735 pub fn process(&mut self, x: f32) -> f32 {
736 let oldest = if self.history.is_full() {
737 self.history.oldest().unwrap_or(0.0)
738 } else {
739 0.0
740 };
741 self.sum += x - oldest;
742 self.history.push(x);
743 if self.history.len() == 0 {
744 0.0
745 } else {
746 self.sum / self.history.len() as f32
747 }
748 }
749
750 pub fn reset(&mut self) {
752 self.history.clear(0.0);
753 self.sum = 0.0;
754 }
755}
756
757impl<const N: usize> Default for RecursiveMovingAverage<N> {
758 fn default() -> Self {
759 Self::new()
760 }
761}