embedded_dsp/
resampling.rs1pub struct CicDecimator<const STAGES: usize> {
5 r: usize, integrator_state: [i32; STAGES],
7 comb_state: [i32; STAGES],
8 sample_counter: usize,
9}
10
11impl<const STAGES: usize> CicDecimator<STAGES> {
12 pub fn new(r: usize) -> Self {
14 Self {
15 r,
16 integrator_state: [0; STAGES],
17 comb_state: [0; STAGES],
18 sample_counter: 0,
19 }
20 }
21
22 pub fn process_sample(&mut self, input: i32) -> Option<i32> {
24 let mut val = input;
26 for i in 0..STAGES {
27 self.integrator_state[i] = self.integrator_state[i].wrapping_add(val);
28 val = self.integrator_state[i];
29 }
30
31 self.sample_counter += 1;
32 if self.sample_counter >= self.r {
33 self.sample_counter = 0;
34
35 for i in 0..STAGES {
37 let diff = val.wrapping_sub(self.comb_state[i]);
38 self.comb_state[i] = val;
39 val = diff;
40 }
41 Some(val)
42 } else {
43 None
44 }
45 }
46}
47
48pub struct CicInterpolator<const STAGES: usize> {
50 r: usize, comb_state: [i32; STAGES],
52 integrator_state: [i32; STAGES],
53}
54
55impl<const STAGES: usize> CicInterpolator<STAGES> {
56 pub fn new(r: usize) -> Self {
58 Self {
59 r,
60 comb_state: [0; STAGES],
61 integrator_state: [0; STAGES],
62 }
63 }
64
65 pub fn process_sample(&mut self, input: i32, out_buf: &mut [i32]) {
67 assert!(
68 out_buf.len() >= self.r,
69 "out_buf must hold at least R samples"
70 );
71
72 let mut val = input;
74 for i in 0..STAGES {
75 let diff = val.wrapping_sub(self.comb_state[i]);
76 self.comb_state[i] = val;
77 val = diff;
78 }
79
80 for step in 0..self.r {
82 let in_step = if step == 0 { val } else { 0 };
83 let mut stage_val = in_step;
84
85 for i in 0..STAGES {
86 self.integrator_state[i] = self.integrator_state[i].wrapping_add(stage_val);
87 stage_val = self.integrator_state[i];
88 }
89
90 out_buf[step] = stage_val;
91 }
92 }
93}
94
95pub fn resample_linear_f32(src: &[f32], dst: &mut [f32], ratio: f32) {
98 if src.is_empty() || dst.is_empty() || ratio <= 0.0 {
99 return;
100 }
101
102 for i in 0..dst.len() {
103 let src_idx_float = i as f32 * ratio;
104 let idx0 = src_idx_float as usize;
105 let idx1 = (idx0 + 1).min(src.len() - 1);
106
107 if idx0 >= src.len() {
108 dst[i] = src[src.len() - 1];
109 continue;
110 }
111
112 let frac = src_idx_float - idx0 as f32;
113 dst[i] = src[idx0] * (1.0 - frac) + src[idx1] * frac;
114 }
115}