1pub struct Resampler {
5 step: f64,
7 pos: f64,
9 prev: f32,
10}
11
12impl Resampler {
13 pub fn new(from_rate: u32, to_rate: u32) -> Self {
14 Self { step: from_rate as f64 / to_rate as f64, pos: 0.0, prev: 0.0 }
15 }
16
17 pub fn process(&mut self, input: &[f32], out: &mut Vec<f32>) {
19 if input.is_empty() {
20 return;
21 }
22 let prev = self.prev;
23 let at = |i: usize| if i == 0 { prev } else { input[i - 1] };
24 while self.pos < input.len() as f64 {
27 let i = self.pos as usize;
28 let frac = (self.pos - i as f64) as f32;
29 let a = at(i);
30 let b = at(i + 1);
31 out.push(a + (b - a) * frac);
32 self.pos += self.step;
33 }
34 self.prev = input[input.len() - 1];
35 self.pos -= input.len() as f64;
36 }
37}
38
39#[cfg(test)]
40mod tests {
41 use super::*;
42
43 #[test]
44 fn a_ramp_stays_a_ramp_across_block_boundaries() {
45 let mut rs = Resampler::new(48_000, 16_000);
46 let ramp: Vec<f32> = (0..96).map(|i| i as f32).collect();
47 let mut out = Vec::new();
48 for block in ramp.chunks(7) {
49 rs.process(block, &mut out);
50 }
51 assert!(out.len() >= 31 && out.len() <= 32, "{}", out.len());
52 for pair in out.windows(2).skip(1) {
53 assert!((pair[1] - pair[0] - 3.0).abs() < 1e-3, "{:?}", pair);
54 }
55 }
56
57 #[test]
58 fn upsampling_produces_the_expected_count() {
59 let mut rs = Resampler::new(16_000, 48_000);
60 let mut out = Vec::new();
61 rs.process(&vec![0.5; 160], &mut out);
62 rs.process(&vec![0.5; 160], &mut out);
63 assert!((out.len() as i64 - 960).abs() <= 3, "{}", out.len());
64 assert!(out.iter().skip(3).all(|s| (s - 0.5).abs() < 1e-6));
65 }
66}