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}
116
117#[cfg(feature = "transform")]
118use crate::transform::cfft_f32;
119#[cfg(feature = "transform")]
120use crate::types::Status;
121
122#[cfg(feature = "transform")]
129pub fn spectral_interpolate_2x_f32(src: &[f32], dst: &mut [f32]) -> Status {
130 let n = src.len();
131 if n < 4 || (n & (n - 1)) != 0 {
132 return Status::ArgumentError;
133 }
134 if dst.len() < 2 * n {
135 return Status::LengthError;
136 }
137 if 4 * n > 1024 {
138 return Status::LengthError; }
140
141 let mut c_buf = [0.0f32; 1024];
142
143 for i in 0..n {
145 c_buf[2 * i] = src[i];
146 c_buf[2 * i + 1] = 0.0;
147 }
148
149 cfft_f32(&mut c_buf[..2 * n], n, 0, 1);
151
152 let nyq_re = 0.5 * c_buf[n];
154 let nyq_im = 0.5 * c_buf[n + 1];
155 c_buf[n] = nyq_re;
156 c_buf[n + 1] = nyq_im;
157
158 let mut expanded = [0.0f32; 1024];
160 for i in 0..=(n / 2) {
162 expanded[2 * i] = c_buf[2 * i];
163 expanded[2 * i + 1] = c_buf[2 * i + 1];
164 }
165 expanded[2 * (3 * n / 2)] = nyq_re;
167 expanded[2 * (3 * n / 2) + 1] = nyq_im;
168
169 for i in (n / 2 + 1)..n {
171 expanded[2 * (i + n)] = c_buf[2 * i];
172 expanded[2 * (i + n) + 1] = c_buf[2 * i + 1];
173 }
174
175 cfft_f32(&mut expanded[..4 * n], 2 * n, 1, 1);
177
178 for i in 0..(2 * n) {
180 dst[i] = 2.0 * expanded[2 * i];
181 }
182
183 Status::Success
184}