fixed_resample/
resampler_type.rs

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