samplerate_rs/
samplerate.rs

1use crate::converter_type::ConverterType;
2use crate::error::{Error, ErrorCode};
3use libsamplerate::*;
4use std::clone::Clone;
5
6/// A samplerate converter. This is a wrapper around libsamplerate's `SRC_STATE` which also
7/// stores the source and target samplerates.
8///
9/// # Example
10///
11/// ```
12/// use samplerate_rs::{Samplerate, ConverterType};
13///
14/// // Generate a 880Hz sine wave for 1 second in 44100Hz with one channel.
15/// let freq = std::f32::consts::PI * 880f32 / 44100f32;
16/// let mut input: Vec<f32> = (0..44100).map(|i| (freq * i as f32).sin()).collect();
17///
18/// // Instanciate a new converter.
19/// let mut converter = Samplerate::new(ConverterType::SincBestQuality, 44100, 48000, 1).unwrap();
20///
21/// // Resample the input from 44100Hz to 48000Hz.
22/// let resampled = converter.process_last(&input).unwrap();
23/// assert_eq!(resampled.len(), 48000);
24/// ```
25pub struct Samplerate {
26    ptr: *mut SRC_STATE,
27    from_rate: u32,
28    to_rate: u32,
29}
30
31impl Samplerate {
32    /// Create a new samplerate converter with the given rates and channels.
33    pub fn new(
34        converter_type: ConverterType,
35        from_rate: u32,
36        to_rate: u32,
37        channels: usize,
38    ) -> Result<Samplerate, Error> {
39        // First, check that the provided ratio is supported by libsamplerate.
40        let ratio = to_rate as f64 / from_rate as f64;
41        if unsafe { src_is_valid_ratio(ratio) } == 0 {
42            return Err(Error::from_code(ErrorCode::BadSrcRatio));
43        }
44        // Construct the `SRC_STATE` struct and check if that worked.
45        let mut error_int = 0i32;
46        let ptr: *mut SRC_STATE = unsafe {
47            src_new(
48                converter_type as i32,
49                channels as i32,
50                &mut error_int as *mut i32,
51            )
52        };
53        match ErrorCode::from_int(error_int) {
54            ErrorCode::NoError => Ok(Samplerate {
55                ptr,
56                from_rate,
57                to_rate,
58            }),
59            _ => Err(Error::from_int(error_int)),
60        }
61    }
62
63    /// Reset the internal converter's state.
64    pub fn reset(&mut self) -> Result<(), Error> {
65        let error_code = ErrorCode::from_int(unsafe { src_reset(self.ptr) });
66        match error_code {
67            ErrorCode::NoError => Ok(()),
68            _ => Err(Error::from_code(error_code)),
69        }
70    }
71
72    /// Retrieve the currently used source samplerate.
73    pub fn from_rate(&self) -> u32 {
74        self.from_rate
75    }
76
77    /// Retrieve the currently used target samplerate.
78    pub fn to_rate(&self) -> u32 {
79        self.to_rate
80    }
81
82    /// Change the source samplerate.
83    pub fn set_from_rate(&mut self, from_rate: u32) {
84        self.from_rate = from_rate;
85    }
86
87    /// Change the target samplerate.
88    pub fn set_to_rate(&mut self, to_rate: u32) {
89        self.to_rate = to_rate;
90    }
91
92    /// Calculate the ratio (target samplerate divided by source samplerate).
93    pub fn ratio(&self) -> f64 {
94        self.to_rate as f64 / self.from_rate as f64
95    }
96
97    /// Retrieve the number of channels used.
98    pub fn channels(&self) -> Result<usize, Error> {
99        let channels = unsafe { src_get_channels(self.ptr) };
100        if channels >= 0 {
101            Ok(channels as usize)
102        } else {
103            Err(Error::from_int(channels))
104        }
105    }
106
107    fn _process(
108        &self,
109        input: &[f32],
110        output_len: usize,
111        end_of_input: bool,
112    ) -> Result<Vec<f32>, Error> {
113        let channels = self.channels()?;
114        let mut output = vec![0f32; output_len];
115        let mut src = SRC_DATA {
116            data_in: input.as_ptr(),
117            data_out: output.as_mut_ptr(),
118            input_frames: (input.len() as i32 / channels as i32).into(),
119            output_frames: (output_len as i32 / channels as i32).into(),
120            src_ratio: self.ratio(),
121            end_of_input: if end_of_input { 1 } else { 0 },
122            input_frames_used: 0,
123            output_frames_gen: 0,
124        };
125        let error_int = unsafe { src_process(self.ptr, &mut src as *mut SRC_DATA) };
126        match ErrorCode::from_int(error_int) {
127            ErrorCode::NoError => Ok(output[..src.output_frames_gen as usize * channels].into()),
128            _ => Err(Error::from_int(error_int)),
129        }
130    }
131
132    /// Perform a samplerate conversion on a block of data (use `process_last` if it is the last one)
133    /// If the number of channels used was not `1` (Mono), the samples are expected to be stored
134    /// interleaved.
135    pub fn process(&self, input: &[f32]) -> Result<Vec<f32>, Error> {
136        let channels = self.channels()?;
137        self._process(
138            input,
139            (self.ratio() * input.len() as f64) as usize + channels,
140            false,
141        )
142    }
143
144    /// Perform a samplerate conversion on last block of given input data.
145    /// If the number of channels used was not `1` (Mono), the samples are expected to be stored
146    /// interleaved.
147    pub fn process_last(&self, input: &[f32]) -> Result<Vec<f32>, Error> {
148        let channels = self.channels()?;
149        let output_len = (self.ratio() * input.len() as f64) as usize + channels;
150        match self._process(input, output_len, true) {
151            Ok(mut output) => {
152                loop {
153                    match self._process(&[0f32; 0], output_len, true) {
154                        Ok(output_last) => {
155                            if output_last.len() < 1 {
156                                break;
157                            } else {
158                                output.extend(output_last);
159                            }
160                        }
161                        Err(err) => return Err(err),
162                    }
163                }
164                Ok(output)
165            }
166            Err(err) => Err(err),
167        }
168    }
169}
170
171impl Drop for Samplerate {
172    fn drop(&mut self) {
173        unsafe { src_delete(self.ptr) };
174    }
175}
176
177impl Clone for Samplerate {
178    /// Might panic if the underlying `src_clone` method from libsamplerate returns an error.
179    fn clone(&self) -> Samplerate {
180        let mut error_int = 0i32;
181        let ptr: *mut SRC_STATE = unsafe { src_clone(self.ptr, &mut error_int as *mut i32) };
182        let error_code = ErrorCode::from_int(error_int);
183        if error_code != ErrorCode::NoError {
184            panic!(
185                "Error when cloning Samplerate struct: {}",
186                error_code.description()
187            );
188        }
189        Samplerate {
190            ptr,
191            from_rate: self.from_rate,
192            to_rate: self.to_rate,
193        }
194    }
195}
196
197#[cfg(test)]
198mod tests {
199    use super::*;
200    use std::usize;
201
202    #[test]
203    fn samplerate_new_channels_error() {
204        match Samplerate::new(ConverterType::Linear, 44100, 48000, usize::MAX) {
205            Ok(_) => assert!(false),
206            Err(error) => assert_eq!(error, Error::from_code(ErrorCode::BadChannelCount)),
207        };
208    }
209
210    #[test]
211    fn samplerate_new_channels_correct() {
212        let converter = Samplerate::new(ConverterType::Linear, 44100, 48000, 4).unwrap();
213        assert_eq!(converter.channels().unwrap(), 4);
214    }
215
216    #[test]
217    fn samplerate_clone() {
218        let converter = Samplerate::new(ConverterType::Linear, 44100, 48000, 4).unwrap();
219        let cloned = converter.clone();
220        assert_eq!(cloned.channels().unwrap(), 4);
221    }
222
223    #[test]
224    fn samplerate_conversion() {
225        // Generate a 880Hz sine wave for 1 second in 44100Hz with one channel.
226        let freq = std::f32::consts::PI * 880f32 / 44100f32;
227        let input: Vec<f32> = (0..44100).map(|i| (freq * i as f32).sin()).collect();
228
229        // Create a new converter.
230        let mut converter =
231            Samplerate::new(ConverterType::SincBestQuality, 44100, 48000, 1).unwrap();
232
233        // Resample the audio in chunks.
234        let mut resampled = vec![0f32; 0];
235        let chunk_size = 4410; // 100ms
236        for i in 0..input.len() / chunk_size {
237            resampled.extend(if i < (input.len() / chunk_size - 1) {
238                converter
239                    .process(&input[i * chunk_size..(i + 1) * chunk_size])
240                    .unwrap()
241            } else {
242                converter
243                    .process_last(&input[i * chunk_size..(i + 1) * chunk_size])
244                    .unwrap()
245            });
246        }
247        assert_eq!(resampled.len(), 48000);
248
249        // Resample the audio back.
250        converter.reset().unwrap();
251        converter.set_to_rate(44100);
252        converter.set_from_rate(48000);
253        let mut output = vec![0f32; 0];
254        let chunk_size = 4800; // 100ms
255        for i in 0..resampled.len() / chunk_size {
256            output.extend(if i < (resampled.len() / chunk_size - 1) {
257                converter
258                    .process(&resampled[i * chunk_size..(i + 1) * chunk_size])
259                    .unwrap()
260            } else {
261                converter
262                    .process_last(&resampled[i * chunk_size..(i + 1) * chunk_size])
263                    .unwrap()
264            });
265        }
266        assert_eq!(output.len(), 44100);
267
268        // Expect the difference between all input frames and all output frames to be less than
269        // an epsilon.
270        let error = input
271            .iter()
272            .zip(output)
273            .fold(0f32, |max, (input, output)| max.max((input - output).abs()));
274        assert!(error < 0.002);
275    }
276}