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 gain(&self) -> u64 {
24 let mut g: u64 = 1;
25 for _ in 0..STAGES {
26 g = g.saturating_mul(self.r as u64);
27 }
28 g
29 }
30
31 pub fn gain_bits(&self) -> u32 {
33 let g = self.gain();
34 if g <= 1 {
35 0
36 } else {
37 64 - (g - 1).leading_zeros()
38 }
39 }
40
41 pub fn process_sample(&mut self, input: i32) -> Option<i32> {
43 let mut val = input;
45 for i in 0..STAGES {
46 self.integrator_state[i] = self.integrator_state[i].wrapping_add(val);
47 val = self.integrator_state[i];
48 }
49
50 self.sample_counter += 1;
51 if self.sample_counter >= self.r {
52 self.sample_counter = 0;
53
54 for i in 0..STAGES {
56 let diff = val.wrapping_sub(self.comb_state[i]);
57 self.comb_state[i] = val;
58 val = diff;
59 }
60 Some(val)
61 } else {
62 None
63 }
64 }
65
66 pub fn process_sample_scaled(&mut self, input: i32) -> Option<i32> {
68 self.process_sample(input).map(|out| {
69 let shift = self.gain_bits();
70 if shift > 0 {
71 out >> shift
72 } else {
73 out
74 }
75 })
76 }
77}
78
79pub struct CicInterpolator<const STAGES: usize> {
81 r: usize, comb_state: [i32; STAGES],
83 integrator_state: [i32; STAGES],
84}
85
86impl<const STAGES: usize> CicInterpolator<STAGES> {
87 pub fn new(r: usize) -> Self {
89 Self {
90 r,
91 comb_state: [0; STAGES],
92 integrator_state: [0; STAGES],
93 }
94 }
95
96 pub fn gain(&self) -> u64 {
98 if STAGES <= 1 {
99 return 1;
100 }
101 let mut g: u64 = 1;
102 for _ in 0..(STAGES - 1) {
103 g = g.saturating_mul(self.r as u64);
104 }
105 g
106 }
107
108 pub fn gain_bits(&self) -> u32 {
110 let g = self.gain();
111 if g <= 1 {
112 0
113 } else {
114 64 - (g - 1).leading_zeros()
115 }
116 }
117
118 pub fn process_sample(&mut self, input: i32, out_buf: &mut [i32]) {
120 assert!(
121 out_buf.len() >= self.r,
122 "out_buf must hold at least R samples"
123 );
124
125 let mut val = input;
127 for i in 0..STAGES {
128 let diff = val.wrapping_sub(self.comb_state[i]);
129 self.comb_state[i] = val;
130 val = diff;
131 }
132
133 for step in 0..self.r {
135 let in_step = if step == 0 { val } else { 0 };
136 let mut stage_val = in_step;
137
138 for i in 0..STAGES {
139 self.integrator_state[i] = self.integrator_state[i].wrapping_add(stage_val);
140 stage_val = self.integrator_state[i];
141 }
142
143 out_buf[step] = stage_val;
144 }
145 }
146}
147
148use crate::types::q15;
153
154pub fn polyphase_decimate_q15(
160 src: &[q15],
161 coeffs: &[q15],
162 decimation_factor: usize,
163 dst: &mut [q15],
164) -> usize {
165 if decimation_factor == 0 || coeffs.is_empty() || src.is_empty() {
166 return 0;
167 }
168 let num_taps = coeffs.len();
169 let out_len = dst.len().min(if src.len() >= num_taps { (src.len() - num_taps) / decimation_factor + 1 } else { 0 });
170
171 for i in 0..out_len {
172 let src_offset = i * decimation_factor;
173 let mut acc: i64 = 0;
174 for k in 0..num_taps {
175 acc += (src[src_offset + k].to_bits() as i64 * coeffs[k].to_bits() as i64) >> 15;
176 }
177 dst[i] = q15::from_bits(acc.clamp(i16::MIN as i64, i16::MAX as i64) as i16);
178 }
179
180 out_len
181}
182
183pub fn polyphase_interpolate_q15(
189 src: &[q15],
190 coeffs: &[q15],
191 interpolation_factor: usize,
192 dst: &mut [q15],
193) -> usize {
194 let l = interpolation_factor;
195 if l == 0 || coeffs.is_empty() || src.is_empty() || coeffs.len() % l != 0 {
196 return 0;
197 }
198 let taps_per_phase = coeffs.len() / l;
199 let max_in_samples = if src.len() >= taps_per_phase { src.len() - taps_per_phase + 1 } else { 0 };
200 let out_len = dst.len().min(max_in_samples * l);
201
202 for in_idx in 0..max_in_samples {
203 for phase in 0..l {
204 let out_idx = in_idx * l + phase;
205 if out_idx >= dst.len() {
206 break;
207 }
208 let mut acc: i64 = 0;
209 for k in 0..taps_per_phase {
210 let coeff = coeffs[k * l + phase].to_bits() as i64;
211 let sample = src[in_idx + k].to_bits() as i64;
212 acc += (sample * coeff) >> 15;
213 }
214 dst[out_idx] =
215 q15::from_bits((acc * l as i64).clamp(i16::MIN as i64, i16::MAX as i64) as i16);
216 }
217 }
218
219 out_len
220}
221
222pub fn resample_linear_q15(src: &[q15], dst: &mut [q15], ratio_q16: i32) {
225 if src.is_empty() || dst.is_empty() || ratio_q16 <= 0 {
226 return;
227 }
228
229 let mut phase_acc: i64 = 0;
230 for i in 0..dst.len() {
231 let idx0 = (phase_acc >> 16) as usize;
232 let frac = (phase_acc & 0xFFFF) as i32; if idx0 >= src.len() {
235 dst[i] = src[src.len() - 1];
236 } else {
237 let s0 = src[idx0].to_bits() as i32;
238 let s1 = if idx0 + 1 < src.len() {
239 src[idx0 + 1].to_bits() as i32
240 } else {
241 s0
242 };
243 let diff = s1 - s0;
244 let interp = s0 + ((diff * frac) >> 16);
245 dst[i] = q15::from_bits(interp.clamp(i16::MIN as i32, i16::MAX as i32) as i16);
246 }
247
248 phase_acc += ratio_q16 as i64;
249 }
250}
251
252pub fn resample_linear_f32(src: &[f32], dst: &mut [f32], ratio: f32) {
255 if src.is_empty() || dst.is_empty() || ratio <= 0.0 {
256 return;
257 }
258
259 for i in 0..dst.len() {
260 let src_idx_float = i as f32 * ratio;
261 let idx0 = src_idx_float as usize;
262 let idx1 = (idx0 + 1).min(src.len() - 1);
263
264 if idx0 >= src.len() {
265 dst[i] = src[src.len() - 1];
266 continue;
267 }
268
269 let frac = src_idx_float - idx0 as f32;
270 dst[i] = src[idx0] * (1.0 - frac) + src[idx1] * frac;
271 }
272}
273
274#[cfg(feature = "transform")]
275use crate::transform::cfft_f32;
276#[cfg(feature = "transform")]
277use crate::types::Status;
278
279#[cfg(feature = "transform")]
286pub fn spectral_interpolate_2x_f32(src: &[f32], dst: &mut [f32]) -> Status {
287 let n = src.len();
288 if n < 4 || (n & (n - 1)) != 0 {
289 return Status::ArgumentError;
290 }
291 if dst.len() < 2 * n {
292 return Status::LengthError;
293 }
294 if 4 * n > 1024 {
295 return Status::LengthError; }
297
298 let mut c_buf = [0.0f32; 1024];
299
300 for i in 0..n {
302 c_buf[2 * i] = src[i];
303 c_buf[2 * i + 1] = 0.0;
304 }
305
306 cfft_f32(&mut c_buf[..2 * n], n, 0, 1);
308
309 let nyq_re = 0.5 * c_buf[n];
311 let nyq_im = 0.5 * c_buf[n + 1];
312 c_buf[n] = nyq_re;
313 c_buf[n + 1] = nyq_im;
314
315 let mut expanded = [0.0f32; 1024];
317 for i in 0..=(n / 2) {
319 expanded[2 * i] = c_buf[2 * i];
320 expanded[2 * i + 1] = c_buf[2 * i + 1];
321 }
322 expanded[2 * (3 * n / 2)] = nyq_re;
324 expanded[2 * (3 * n / 2) + 1] = nyq_im;
325
326 for i in (n / 2 + 1)..n {
328 expanded[2 * (i + n)] = c_buf[2 * i];
329 expanded[2 * (i + n) + 1] = c_buf[2 * i + 1];
330 }
331
332 cfft_f32(&mut expanded[..4 * n], 2 * n, 1, 1);
334
335 for i in 0..(2 * n) {
337 dst[i] = 2.0 * expanded[2 * i];
338 }
339
340 Status::Success
341}