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}