samplerate_rs/
lib.rs

1extern crate libsamplerate;
2
3pub mod converter_type;
4pub mod error;
5pub mod samplerate;
6
7pub use crate::converter_type::*;
8pub use crate::error::*;
9pub use crate::samplerate::*;
10use libsamplerate::*;
11use std::convert::TryInto;
12use std::ffi::CStr;
13
14#[cfg(test)]
15extern crate rstest;
16
17#[cfg(test)]
18mod sanity_test;
19
20/// Perform a simple samplerate conversion of a large chunk of audio.
21/// This calls `src_simple` of libsamplerate which is not suitable for streamed audio. Use the
22/// `Samplerate` struct instead for this.
23///
24/// The length of `input` must be `input_frame_count * channels`.
25/// The length of result `Vec<f32>` should be `input_frames * to_rate + (from_rate - 1)) / from_rate`
26///
27/// # Example
28///
29/// ```
30/// use samplerate_rs::{convert, ConverterType};
31///
32/// // Generate a 880Hz sine wave for 1 second in 44100Hz with one channel.
33/// let freq = std::f32::consts::PI * 880f32 / 44100f32;
34/// let mut input: Vec<f32> = (0..44100).map(|i| (freq * i as f32).sin()).collect();
35///
36/// // Resample the input from 44100Hz to 48000Hz.
37/// let resampled = convert(44100, 48000, 1, ConverterType::SincBestQuality, &input).unwrap();
38/// assert_eq!(resampled.len(), 48000);
39/// ```
40pub fn convert(
41    from_rate: u32,
42    to_rate: u32,
43    channels: usize,
44    converter_type: ConverterType,
45    input: &[f32],
46) -> Result<Vec<f32>, Error> {
47    let input_len = input.len();
48    assert_eq!(input_len % channels, 0);
49    let input_frames = input_len / channels;
50    let ratio = to_rate as f64 / from_rate as f64;
51    let output_frames =
52        (input_frames * to_rate as usize + (from_rate as usize - 1)) / from_rate as usize;
53    let mut output = vec![0f32; output_frames * channels];
54    let mut src = SRC_DATA {
55        data_in: input.as_ptr(),
56        data_out: output.as_mut_ptr(),
57        input_frames: input_frames.try_into().unwrap(),
58        output_frames: output_frames.try_into().unwrap(),
59        src_ratio: ratio,
60        end_of_input: 0,
61        input_frames_used: 0,
62        output_frames_gen: 0,
63    };
64    let error_int = unsafe {
65        src_simple(
66            &mut src as *mut SRC_DATA,
67            converter_type as i32,
68            channels as i32,
69        )
70    };
71    let error_code = ErrorCode::from_int(error_int);
72    match error_code {
73        ErrorCode::NoError => Ok(output),
74        _ => Err(Error::from_code(error_code)),
75    }
76}
77
78/// Returns the version of `libsamplerate` used by this crate as a string.
79pub fn version() -> &'static str {
80    unsafe { CStr::from_ptr(src_get_version()) }
81        .to_str()
82        .unwrap()
83}
84
85#[cfg(test)]
86mod tests {
87    use super::*;
88
89    #[test]
90    fn correct_version() {
91        assert_eq!(
92            version(),
93            "libsamplerate-0.1.9 (c) 2002-2008 Erik de Castro Lopo"
94        );
95    }
96}