fixed_resample/
non_realtime.rs

1use std::num::NonZeroUsize;
2
3use rubato::Sample;
4
5use crate::{ResampleQuality, ResamplerType};
6
7/// An easy to use resampler for use in non-realtime applications.
8pub struct NonRtResampler<T: Sample> {
9    resampler: ResamplerType<T>,
10    in_buf: Vec<Vec<T>>,
11    out_buf: Vec<Vec<T>>,
12    intlv_buf: Vec<T>,
13    in_buf_len: usize,
14    num_channels: NonZeroUsize,
15    input_frames_max: usize,
16    output_frames_max: usize,
17    output_delay: usize,
18    delay_frames_left: usize,
19}
20
21impl<T: Sample> NonRtResampler<T> {
22    /// Create a new non-realtime resampler.
23    ///
24    /// * `in_sample_rate` - The sample rate of the input stream.
25    /// * `out_sample_rate` - The sample rate of the output stream.
26    /// * `num_channels` - The number of channels.
27    /// * `interleaved` - If you are planning to use [`NonRtResampler::process_interleaved`],
28    /// set this to `true`. Otherwise you can set this to `false` to save a bit of
29    /// memory.
30    /// * `quality` - The quality of the resampling algorithm.
31    ///
32    /// # Panics
33    ///
34    /// Panics if:
35    /// * `in_sample_rate == 0`
36    /// * `out_sample_rate == 0`
37    /// * `num_channels == 0`,
38    pub fn new(
39        in_sample_rate: u32,
40        out_sample_rate: u32,
41        num_channels: usize,
42        quality: ResampleQuality,
43    ) -> Self {
44        let resampler =
45            ResamplerType::from_quality(in_sample_rate, out_sample_rate, num_channels, quality);
46        Self::from_custom(resampler)
47    }
48
49    /// Create a new non-realtime resampler using the given rubato resampler.
50    ///
51    /// # Panics
52    /// Panics if `max_out_frames == 0`.
53    pub fn from_custom(resampler: impl Into<ResamplerType<T>>) -> Self {
54        let mut resampler: ResamplerType<T> = resampler.into();
55
56        let num_channels = resampler.num_channels();
57        assert!(num_channels > 0);
58
59        let input_frames_max = resampler.input_frames_max();
60        let output_frames_max = resampler.output_frames_max();
61        let output_delay = resampler.output_delay();
62
63        Self {
64            resampler,
65            in_buf: (0..num_channels)
66                .map(|_| vec![T::zero(); input_frames_max])
67                .collect(),
68            out_buf: (0..num_channels)
69                .map(|_| vec![T::zero(); output_frames_max])
70                .collect(),
71            intlv_buf: Vec::new(),
72            in_buf_len: 0,
73            num_channels: NonZeroUsize::new(num_channels).unwrap(),
74            input_frames_max,
75            output_frames_max,
76            output_delay,
77            delay_frames_left: output_delay,
78        }
79    }
80
81    /// Get the number of channels this resampler is configured for.
82    pub fn num_channels(&self) -> NonZeroUsize {
83        self.num_channels
84    }
85
86    /// Reset the resampler state and clear all internal buffers.
87    pub fn reset(&mut self) {
88        self.resampler.reset();
89        self.in_buf_len = 0;
90        self.delay_frames_left = self.output_delay;
91    }
92
93    /// Get the delay of the internal resampler, reported as a number of output frames.
94    ///
95    /// Note, this resampler automatically truncates the starting padded zero frames for
96    /// you.
97    pub fn output_delay(&self) -> usize {
98        self.output_delay
99    }
100
101    /// The maximum number of frames that can appear in a single call to the closure in
102    /// [`NonRtResampler::process()`] and [`NonRtResampler::process_interleaved()`].
103    pub fn max_processed_frames(&self) -> usize {
104        self.output_frames_max
105    }
106
107    /// The length of an output buffer in frames for a given input buffer.
108    ///
109    /// Note, the resampler may add extra padded zeros to the end of the output buffer,
110    /// so prefer to use [`NonRtResampler::out_alloc_frames()`] instead to reserve the
111    /// capacity for an output buffer.
112    pub fn out_frames(&self, in_sample_rate: u32, out_sample_rate: u32, in_frames: usize) -> usize {
113        (in_frames as f64 * out_sample_rate as f64 / in_sample_rate as f64).ceil() as usize
114    }
115
116    /// The number of frames needed to allocate an output buffer for a given input buffer.
117    pub fn out_alloc_frames(
118        &self,
119        in_sample_rate: u32,
120        out_sample_rate: u32,
121        in_frames: usize,
122    ) -> usize {
123        self.out_frames(in_sample_rate, out_sample_rate, in_frames)
124            + (self.max_processed_frames() * 2)
125    }
126
127    /// Resample the given input data.
128    ///
129    /// * `input` - The input data.
130    /// * `on_processed` - Called whenever there is new resampled data. The first argument
131    /// is the buffers containing the new data, and the second argument is the length of
132    /// the new data in frames (NOTE, the second argument may be less than the length of
133    /// the `Vec`s in the first argument).
134    /// * `is_last_packet` - Whether or not this is the last (or only) packet of data that
135    /// will be resampled. This ensures that any leftover samples in the internal resampler
136    /// are flushed to the output.
137    ///
138    /// If you want to flush the remaining samples out of the internal resampler when there
139    /// is no more input data left, set the `input` to an empty slice with no channels
140    /// (`&[]`), and set `is_last_packet` to `true`.
141    ///
142    /// Note, when flushing the remaining data with `is_last_packet`, the resulting output
143    /// may have a few extra padded zero samples on the end.
144    ///
145    /// The delay of the internal resampler is automatically accounted for (the starting
146    /// padded zero frames are automatically truncated). Call [`NonRtResampler::reset()`]
147    /// before reusing this resampler for a new sample.
148    ///
149    /// Note, this method is *NOT* realtime-safe.
150    pub fn process<Vin: AsRef<[T]>>(
151        &mut self,
152        input: &[Vin],
153        mut on_processed: impl FnMut(&[Vec<T>], usize),
154        is_last_packet: bool,
155    ) {
156        let mut resample = |self_: &mut Self| {
157            let (_, out_frames) = self_
158                .resampler
159                .process_into_buffer(&self_.in_buf, &mut self_.out_buf, None)
160                .unwrap();
161
162            if self_.delay_frames_left == 0 {
163                (on_processed)(self_.out_buf.as_slice(), out_frames);
164            } else if self_.delay_frames_left < out_frames {
165                for b in self_.out_buf.iter_mut() {
166                    b.copy_within(self_.delay_frames_left..out_frames, 0);
167                }
168
169                (on_processed)(
170                    self_.out_buf.as_slice(),
171                    out_frames - self_.delay_frames_left,
172                );
173
174                self_.delay_frames_left = 0;
175            } else {
176                self_.delay_frames_left -= out_frames;
177            }
178        };
179
180        if input.is_empty() && is_last_packet {
181            for b in self.in_buf.iter_mut() {
182                b.fill(T::zero());
183            }
184
185            resample(self);
186
187            return;
188        }
189
190        let in_ch_0 = input[0].as_ref();
191        let total_in_frames = in_ch_0.len();
192
193        let mut in_frames_copied = 0;
194        while in_frames_copied < total_in_frames {
195            if self.in_buf_len < self.input_frames_max {
196                let copy_frames = (self.input_frames_max - self.in_buf_len)
197                    .min(total_in_frames - in_frames_copied);
198
199                self.in_buf[0][self.in_buf_len..self.in_buf_len + copy_frames]
200                    .copy_from_slice(&in_ch_0[in_frames_copied..in_frames_copied + copy_frames]);
201                for (in_buf_ch, in_ch) in self.in_buf.iter_mut().zip(input.iter()).skip(1) {
202                    let in_ch = in_ch.as_ref();
203                    in_buf_ch[self.in_buf_len..self.in_buf_len + copy_frames]
204                        .copy_from_slice(&in_ch[in_frames_copied..in_frames_copied + copy_frames]);
205                }
206
207                self.in_buf_len += copy_frames;
208                in_frames_copied += copy_frames;
209
210                if self.in_buf_len < self.input_frames_max && !is_last_packet {
211                    // Must wait for more input data before continuing.
212                    return;
213                }
214            }
215
216            if is_last_packet && in_frames_copied == total_in_frames {
217                for ch in self.in_buf.iter_mut() {
218                    ch[self.in_buf_len..].fill(T::zero());
219                }
220
221                resample(self);
222
223                for ch in self.in_buf.iter_mut() {
224                    ch.fill(T::zero());
225                }
226
227                resample(self);
228            } else {
229                resample(self);
230            }
231
232            self.in_buf_len = 0;
233        }
234    }
235
236    /// Resample the given input data in interleaved format.
237    ///
238    /// * `input` - The input data in interleaved format.
239    /// * `on_processed` - Called whenever there is new resampled data. This data is in
240    /// interleaved format.
241    /// * `is_last_packet` - Whether or not this is the last (or only) packet of data that
242    /// will be resampled. This ensures that any leftover samples in the internal resampler
243    /// are flushed to the output.
244    ///
245    /// If you want to flush the remaining samples out of the internal resampler when there
246    /// is no more input data left, set the `input` to an empty slice (`&[]`), and set
247    /// `is_last_packet` to `true`.
248    ///
249    /// Note, when flushing the remaining data with `is_last_packet`, the resulting output
250    /// may have a few extra padded zero samples on the end.
251    ///
252    /// The delay of the internal resampler is automatically accounted for (the starting
253    /// padded zero frames are automatically truncated). Call [`NonRtResampler::reset()`]
254    /// before reusing this resampler for a new sample.
255    ///
256    /// Note, this method is *NOT* realtime-safe.
257    pub fn process_interleaved(
258        &mut self,
259        input: &[T],
260        mut on_processed: impl FnMut(&[T]),
261        is_last_packet: bool,
262    ) {
263        let num_channels = self.num_channels;
264
265        let mut resample = |self_: &mut Self| {
266            let (_, out_frames) = self_
267                .resampler
268                .process_into_buffer(&self_.in_buf, &mut self_.out_buf, None)
269                .unwrap();
270
271            if self_.delay_frames_left < out_frames {
272                if num_channels.get() == 1 {
273                    // Mono, no need to copy to an intermediate buffer.
274                    (on_processed)(&self_.out_buf[0][self_.delay_frames_left..out_frames]);
275                } else {
276                    crate::interleave::interleave(
277                        &self_.out_buf,
278                        &mut self_.intlv_buf,
279                        num_channels,
280                        0..out_frames,
281                    );
282
283                    (on_processed)(
284                        &self_.intlv_buf[self_.delay_frames_left * num_channels.get()
285                            ..out_frames * num_channels.get()],
286                    );
287                }
288
289                self_.delay_frames_left = 0;
290            } else {
291                self_.delay_frames_left -= out_frames;
292            }
293        };
294
295        if input.is_empty() && is_last_packet {
296            for b in self.in_buf.iter_mut() {
297                b.fill(T::zero());
298            }
299
300            resample(self);
301
302            return;
303        }
304
305        let total_in_frames = input.len() / num_channels;
306
307        if self.intlv_buf.is_empty() {
308            let alloc_frames = self.resampler.output_frames_max() * num_channels.get();
309
310            self.intlv_buf.reserve_exact(alloc_frames);
311            self.intlv_buf.resize(alloc_frames, T::zero());
312        }
313
314        let mut in_frames_copied = 0;
315        while in_frames_copied < total_in_frames {
316            if self.in_buf_len < self.input_frames_max {
317                let copy_frames = (self.input_frames_max - self.in_buf_len)
318                    .min(total_in_frames - in_frames_copied);
319
320                crate::interleave::deinterleave(
321                    &input[in_frames_copied * num_channels.get()
322                        ..(in_frames_copied + copy_frames) * num_channels.get()],
323                    &mut self.in_buf,
324                    self.num_channels,
325                    self.in_buf_len..self.in_buf_len + copy_frames,
326                );
327
328                self.in_buf_len += copy_frames;
329                in_frames_copied += copy_frames;
330
331                if self.in_buf_len < self.input_frames_max && !is_last_packet {
332                    // Must wait for more input data before continuing.
333                    return;
334                }
335            }
336
337            if is_last_packet && in_frames_copied == total_in_frames {
338                for ch in self.in_buf.iter_mut() {
339                    ch[self.in_buf_len..].fill(T::zero());
340                }
341
342                resample(self);
343
344                for ch in self.in_buf.iter_mut() {
345                    ch.fill(T::zero());
346                }
347
348                resample(self);
349            } else {
350                resample(self);
351            }
352
353            self.in_buf_len = 0;
354        }
355    }
356
357    pub fn resampler_type(&self) -> &ResamplerType<T> {
358        &self.resampler
359    }
360
361    pub fn resampler_type_mut(&mut self) -> &mut ResamplerType<T> {
362        &mut self.resampler
363    }
364}
365
366impl<T: Sample> Into<ResamplerType<T>> for NonRtResampler<T> {
367    fn into(self) -> ResamplerType<T> {
368        self.resampler
369    }
370}