wavekat_vad/preprocessing/
resample.rs1use rubato::{FftFixedIn, Resampler};
6
7pub struct AudioResampler {
11 resampler: FftFixedIn<f64>,
12 input_buffer: Vec<f64>,
13 output_buffer: Vec<i16>,
14}
15
16impl AudioResampler {
17 pub fn new(source_rate: u32, target_rate: u32) -> Result<Self, String> {
26 let chunk_size = 1024;
27 let resampler = FftFixedIn::<f64>::new(
28 source_rate as usize,
29 target_rate as usize,
30 chunk_size,
31 2, 1, )
34 .map_err(|e| format!("failed to create resampler: {e}"))?;
35
36 Ok(Self {
37 resampler,
38 input_buffer: Vec::new(),
39 output_buffer: Vec::new(),
40 })
41 }
42
43 pub fn process(&mut self, samples: &[i16]) -> Vec<i16> {
48 self.input_buffer
50 .extend(samples.iter().map(|&s| s as f64 / i16::MAX as f64));
51
52 let input_frames_needed = self.resampler.input_frames_next();
54 while self.input_buffer.len() >= input_frames_needed {
55 let chunk: Vec<f64> = self.input_buffer.drain(..input_frames_needed).collect();
56 match self.resampler.process(&[chunk], None) {
57 Ok(output) => {
58 if !output.is_empty() {
59 self.output_buffer
60 .extend(output[0].iter().map(|&s| (s * i16::MAX as f64) as i16));
61 }
62 }
63 Err(e) => {
64 eprintln!("resampling error: {e}");
66 }
67 }
68 }
69
70 std::mem::take(&mut self.output_buffer)
72 }
73
74 pub fn reset(&mut self) {
76 self.input_buffer.clear();
77 self.output_buffer.clear();
78 }
81
82 pub fn buffered_input(&self) -> usize {
84 self.input_buffer.len()
85 }
86
87 pub fn buffered_output(&self) -> usize {
89 self.output_buffer.len()
90 }
91}
92
93impl std::fmt::Debug for AudioResampler {
94 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
95 f.debug_struct("AudioResampler")
96 .field("input_buffer_len", &self.input_buffer.len())
97 .field("output_buffer_len", &self.output_buffer.len())
98 .finish_non_exhaustive()
99 }
100}
101
102#[cfg(test)]
103mod tests {
104 use super::*;
105
106 #[test]
107 fn test_resampler_creation() {
108 let resampler = AudioResampler::new(16000, 48000);
109 assert!(resampler.is_ok());
110 }
111
112 #[test]
113 fn test_resample_16k_to_48k() {
114 let mut resampler = AudioResampler::new(16000, 48000).unwrap();
115
116 let input: Vec<i16> = vec![1000; 2048];
118 let output = resampler.process(&input);
119
120 assert!(!output.is_empty(), "Should have some output");
123 }
124
125 #[test]
126 fn test_resample_48k_to_16k() {
127 let mut resampler = AudioResampler::new(48000, 16000).unwrap();
128
129 let input: Vec<i16> = vec![1000; 2048];
131 let output = resampler.process(&input);
132
133 assert!(!output.is_empty(), "Should have some output");
135 }
136
137 #[test]
138 fn test_resampler_reset() {
139 let mut resampler = AudioResampler::new(16000, 48000).unwrap();
140
141 let input: Vec<i16> = vec![1000; 100];
143 let _ = resampler.process(&input);
144 assert!(resampler.buffered_input() > 0);
145
146 resampler.reset();
148 assert_eq!(resampler.buffered_input(), 0);
149 assert_eq!(resampler.buffered_output(), 0);
150 }
151}