fixed_resample/
resampler_type.rs

1use std::num::NonZeroUsize;
2
3use rubato::{FastFixedIn, ResampleResult, Resampler as RubatoResampler, Sample};
4
5use crate::ResampleQuality;
6
7/// The resampling algorithm used in `fixed_resample`.
8pub enum ResamplerType<T: Sample> {
9    /// Ok quality, fast performance
10    Fast(FastFixedIn<T>),
11    #[cfg(feature = "fft-resampler")]
12    /// Great quality, medium performance
13    Fft(rubato::FftFixedIn<T>),
14}
15
16impl<T: Sample> ResamplerType<T> {
17    pub fn from_quality(
18        in_sample_rate: u32,
19        out_sample_rate: u32,
20        num_channels: NonZeroUsize,
21        quality: ResampleQuality,
22    ) -> Self {
23        assert_ne!(in_sample_rate, 0);
24        assert_ne!(out_sample_rate, 0);
25
26        #[cfg(feature = "fft-resampler")]
27        if let ResampleQuality::High = quality {
28            return Self::Fft(
29                rubato::FftFixedIn::new(
30                    in_sample_rate as usize,
31                    out_sample_rate as usize,
32                    1024,
33                    2,
34                    num_channels.get(),
35                )
36                .unwrap(),
37            );
38        }
39
40        #[cfg(not(feature = "fft-resampler"))]
41        let _ = quality;
42
43        Self::Fast(
44            FastFixedIn::new(
45                out_sample_rate as f64 / in_sample_rate as f64,
46                1.0,
47                rubato::PolynomialDegree::Linear,
48                1024,
49                num_channels.get(),
50            )
51            .unwrap(),
52        )
53    }
54
55    /// Get the number of channels this Resampler is configured for.
56    pub fn num_channels(&self) -> usize {
57        match self {
58            Self::Fast(r) => r.nbr_channels(),
59            #[cfg(feature = "fft-resampler")]
60            Self::Fft(r) => r.nbr_channels(),
61        }
62    }
63
64    /// Reset the resampler state and clear all internal buffers.
65    pub fn reset(&mut self) {
66        match self {
67            Self::Fast(r) => r.reset(),
68            #[cfg(feature = "fft-resampler")]
69            Self::Fft(r) => r.reset(),
70        }
71    }
72
73    /// Get the number of frames per channel needed for the next call to
74    /// [`ResamplerRefMut::process_into_buffer`].
75    pub fn input_frames_next(&mut self) -> usize {
76        match self {
77            Self::Fast(r) => r.input_frames_next(),
78            #[cfg(feature = "fft-resampler")]
79            Self::Fft(r) => r.input_frames_next(),
80        }
81    }
82
83    /// Get the maximum number of input frames per channel the resampler could require.
84    pub fn input_frames_max(&mut self) -> usize {
85        match self {
86            Self::Fast(r) => r.input_frames_max(),
87            #[cfg(feature = "fft-resampler")]
88            Self::Fft(r) => r.input_frames_max(),
89        }
90    }
91
92    /// Get the delay for the resampler, reported as a number of output frames.
93    pub fn output_delay(&mut self) -> usize {
94        match self {
95            Self::Fast(r) => r.output_delay(),
96            #[cfg(feature = "fft-resampler")]
97            Self::Fft(r) => r.output_delay(),
98        }
99    }
100
101    /// Get the max number of output frames per channel.
102    pub fn output_frames_max(&mut self) -> usize {
103        match self {
104            Self::Fast(r) => r.output_frames_max(),
105            #[cfg(feature = "fft-resampler")]
106            Self::Fft(r) => r.output_frames_max(),
107        }
108    }
109
110    /// Resample a buffer of audio to a pre-allocated output buffer.
111    /// Use this in real-time applications where the unpredictable time required to allocate
112    /// memory from the heap can cause glitches. If this is not a problem, you may use
113    /// the [process](Resampler::process) method instead.
114    ///
115    /// The input and output buffers are used in a non-interleaved format.
116    /// The input is a slice, where each element of the slice is itself referenceable
117    /// as a slice ([AsRef<\[T\]>](AsRef)) which contains the samples for a single channel.
118    /// Because `[Vec<T>]` implements [`AsRef<\[T\]>`](AsRef), the input may be [`Vec<Vec<T>>`](Vec).
119    ///
120    /// The output data is a slice, where each element of the slice is a `[T]` which contains
121    /// the samples for a single channel. If the output channel slices do not have sufficient
122    /// capacity for all output samples, the function will return an error with the expected
123    /// size. You could allocate the required output buffer with
124    /// [output_buffer_allocate](Resampler::output_buffer_allocate) before calling this function
125    /// and reuse the same buffer for each call.
126    ///
127    /// The `active_channels_mask` is optional.
128    /// Any channel marked as inactive by a false value will be skipped during processing
129    /// and the corresponding output will be left unchanged.
130    /// If `None` is given, all channels will be considered active.
131    ///
132    /// Before processing, it checks that the input and outputs are valid.
133    /// If either has the wrong number of channels, or if the buffer for any channel is too short,
134    /// a [ResampleError] is returned.
135    /// Both input and output are allowed to be longer than required.
136    /// The number of input samples consumed and the number output samples written
137    /// per channel is returned in a tuple, `(input_frames, output_frames)`.
138    pub fn process_into_buffer<Vin: AsRef<[T]>, Vout: AsMut<[T]>>(
139        &mut self,
140        wave_in: &[Vin],
141        wave_out: &mut [Vout],
142        active_channels_mask: Option<&[bool]>,
143    ) -> ResampleResult<(usize, usize)> {
144        match self {
145            Self::Fast(r) => r.process_into_buffer(wave_in, wave_out, active_channels_mask),
146            #[cfg(feature = "fft-resampler")]
147            Self::Fft(r) => r.process_into_buffer(wave_in, wave_out, active_channels_mask),
148        }
149    }
150}
151
152impl<T: Sample> From<FastFixedIn<T>> for ResamplerType<T> {
153    fn from(r: FastFixedIn<T>) -> Self {
154        Self::Fast(r)
155    }
156}
157
158#[cfg(feature = "fft-resampler")]
159impl<T: Sample> From<rubato::FftFixedIn<T>> for ResamplerType<T> {
160    fn from(r: rubato::FftFixedIn<T>) -> Self {
161        Self::Fft(r)
162    }
163}