#[derive(Debug)]
pub struct Resampler {
ratio: f32, position: f32, channels: usize, prev: Vec<f32>, next: Vec<f32>, initialized: bool, }
impl Resampler {
pub fn new(in_rate: u32, out_rate: u32, channels: usize) -> Self {
Self {
ratio: in_rate as f32 / out_rate as f32,
position: 0.0,
channels,
prev: vec![0.0; channels],
next: vec![0.0; channels],
initialized: false,
}
}
pub fn process(&mut self, input_frame: &[f32], out: &mut Vec<f32>) {
debug_assert_eq!(input_frame.len(), self.channels);
if !self.initialized {
self.prev.copy_from_slice(input_frame);
self.initialized = true;
return;
}
self.next.copy_from_slice(input_frame);
while self.position < 1.0 {
let frac = self.position;
for c in 0..self.channels {
let sample = self.prev[c] * (1.0 - frac) + self.next[c] * frac;
out.push(sample);
}
self.position += self.ratio;
}
self.position -= 1.0;
self.prev.copy_from_slice(&self.next);
}
}
#[cfg(test)]
mod tests {
use super::Resampler;
#[test]
fn first_frame_primes_without_output() {
let mut resampler = Resampler::new(48_000, 48_000, 1);
let mut output = Vec::new();
resampler.process(&[0.25], &mut output);
assert!(output.is_empty());
}
#[test]
fn matching_rates_emit_next_frame() {
let mut resampler = Resampler::new(48_000, 48_000, 1);
let mut output = Vec::new();
resampler.process(&[0.0], &mut output);
resampler.process(&[1.0], &mut output);
assert_eq!(output, vec![0.0]);
}
#[test]
fn upsampling_emits_interpolated_frames() {
let mut resampler = Resampler::new(24_000, 48_000, 1);
let mut output = Vec::new();
resampler.process(&[0.0], &mut output);
resampler.process(&[1.0], &mut output);
assert_eq!(output, vec![0.0, 0.5]);
}
}