resample.rs

 1use std::time::Duration;
 2
 3use rodio::{Sample, SampleRate, Source};
 4use rubato::{FftFixedInOut, Resampler};
 5
 6pub struct FixedResampler<S> {
 7    input: S,
 8    next_channel: usize,
 9    next_frame: usize,
10    output_buffer: Vec<Vec<Sample>>,
11    input_buffer: Vec<Vec<Sample>>,
12    target_sample_rate: SampleRate,
13    resampler: FftFixedInOut<Sample>,
14}
15
16impl<S: Source> FixedResampler<S> {
17    pub fn new(input: S, target_sample_rate: SampleRate) -> Self {
18        let chunk_size_in =
19            Duration::from_millis(50).as_secs_f32() * input.sample_rate().get() as f32;
20        let chunk_size_in = chunk_size_in.ceil() as usize;
21
22        let resampler = FftFixedInOut::new(
23            input.sample_rate().get() as usize,
24            target_sample_rate.get() as usize,
25            chunk_size_in,
26            input.channels().get() as usize,
27        )
28        .expect(
29            "sample rates are non zero, and we are not changing it so there is no resample ratio",
30        );
31
32        Self {
33            next_channel: 0,
34            next_frame: 0,
35            output_buffer: resampler.output_buffer_allocate(true),
36            input_buffer: resampler.input_buffer_allocate(false),
37            target_sample_rate,
38            resampler,
39            input,
40        }
41    }
42}
43
44impl<S: Source> Source for FixedResampler<S> {
45    fn current_span_len(&self) -> Option<usize> {
46        None
47    }
48
49    fn channels(&self) -> rodio::ChannelCount {
50        self.input.channels()
51    }
52
53    fn sample_rate(&self) -> rodio::SampleRate {
54        self.target_sample_rate
55    }
56
57    fn total_duration(&self) -> Option<std::time::Duration> {
58        self.input.total_duration()
59    }
60}
61
62impl<S: Source> FixedResampler<S> {
63    fn next_sample(&mut self) -> Option<Sample> {
64        let sample = self.output_buffer[self.next_channel]
65            .get(self.next_frame)
66            .copied();
67        self.next_channel = (self.next_channel + 1) % self.input.channels().get() as usize;
68        self.next_frame += 1;
69
70        sample
71    }
72}
73
74impl<S: Source> Iterator for FixedResampler<S> {
75    type Item = Sample;
76
77    fn next(&mut self) -> Option<Self::Item> {
78        if let Some(sample) = self.next_sample() {
79            return Some(sample);
80        }
81
82        for input_channel in &mut self.input_buffer {
83            input_channel.clear();
84        }
85
86        for _ in 0..self.resampler.input_frames_next() {
87            for input_channel in &mut self.input_buffer {
88                input_channel.push(self.input.next()?);
89            }
90        }
91
92        self.resampler
93            .process_into_buffer(&mut self.input_buffer, &mut self.output_buffer, None).expect("Input and output buffer channels are correct as they have been set by the resampler. The buffer for each channel is the same length. The buffer length is what is requested the resampler.");
94
95        self.next_frame = 0;
96        self.next_sample()
97    }
98}