speexdsp-resampler 0.2.0

Pure rust port of the speexdsp resampler
Documentation
#![allow(clippy::unreadable_literal)]

mod speex;

pub struct State {
    st: speex::SpeexResamplerState,
}

#[derive(Debug, Clone, Copy)]
pub enum Error {
    AllocFailed,
    InvalidArg,
}

pub trait Sample: Copy + Clone {
    fn process(
        st: &mut speex::SpeexResamplerState,
        index: usize,
        input: &[Self],
        output: &mut [Self],
    ) -> Result<(usize, usize), Error>;

    fn process_interleaved(
        st: &mut speex::SpeexResamplerState,
        input: &[Self],
        output: &mut [Self],
    ) -> Result<(usize, usize), Error>;
}

impl Sample for i16 {
    fn process(
        st: &mut speex::SpeexResamplerState,
        index: usize,
        input: &[i16],
        output: &mut [i16],
    ) -> Result<(usize, usize), Error> {
        let mut in_len = input.len() as u32;
        let mut out_len = output.len() as u32;
        let ret = st.process_int(
            index as u32,
            input,
            &mut in_len,
            output,
            &mut out_len,
        );

        if ret != 0 {
            Err(Error::AllocFailed)
        } else {
            Ok((in_len as usize, out_len as usize))
        }
    }

    fn process_interleaved(
        st: &mut speex::SpeexResamplerState,
        input: &[i16],
        output: &mut [i16],
    ) -> Result<(usize, usize), Error> {
        let mut in_len = input.len() as u32;
        let mut out_len = output.len() as u32;
        let ret = st.process_interleaved_int(
            input,
            &mut in_len,
            output,
            &mut out_len,
        );

        if ret != 0 {
            Err(Error::AllocFailed)
        } else {
            Ok((in_len as usize, out_len as usize))
        }
    }
}

impl Sample for f32 {
    fn process(
        st: &mut speex::SpeexResamplerState,
        index: usize,
        input: &[f32],
        output: &mut [f32],
    ) -> Result<(usize, usize), Error> {
        let mut in_len = input.len() as u32;
        let mut out_len = output.len() as u32;
        let ret = st.process_float(
            index as u32,
            input,
            &mut in_len,
            output,
            &mut out_len,
        );

        if ret != 0 {
            Err(Error::AllocFailed)
        } else {
            Ok((in_len as usize, out_len as usize))
        }
    }

    fn process_interleaved(
        st: &mut speex::SpeexResamplerState,
        input: &[f32],
        output: &mut [f32],
    ) -> Result<(usize, usize), Error> {
        let mut in_len = input.len() as u32;
        let mut out_len = output.len() as u32;
        let ret = st.process_interleaved_float(
            input,
            &mut in_len,
            output,
            &mut out_len,
        );

        if ret != 0 {
            Err(Error::AllocFailed)
        } else {
            Ok((in_len as usize, out_len as usize))
        }
    }
}

impl State {
    pub fn new(
        channels: usize,
        in_rate: usize,
        out_rate: usize,
        quality: usize,
    ) -> Result<Self, Error> {
        let st = speex::SpeexResamplerState::new(
            channels, in_rate, out_rate, quality,
        );

        Ok(State { st })
    }

    pub fn set_rate(
        &mut self,
        in_rate: usize,
        out_rate: usize,
    ) -> Result<(), Error> {
        if self.st.set_rate(in_rate, out_rate) != 0 {
            Err(Error::InvalidArg)
        } else {
            Ok(())
        }
    }

    pub fn get_rate(&self) -> (usize, usize) {
        self.st.get_rate()
    }

    pub fn get_ratio(&self) -> (usize, usize) {
        self.st.get_ratio()
    }

    pub fn process<S: Sample>(
        &mut self,
        index: usize,
        input: &[S],
        output: &mut [S],
    ) -> Result<(usize, usize), Error> {
        S::process(&mut self.st, index, input, output)
    }

    pub fn process_interleaved<S: Sample>(
        &mut self,
        input: &[S],
        output: &mut [S],
    ) -> Result<(usize, usize), Error> {
        S::process_interleaved(&mut self.st, input, output)
    }

    pub fn skip_zeros(&mut self) {
        self.st.skip_zeros();
    }

    pub fn reset(&mut self) {
        self.st.reset_mem();
    }

    pub fn get_input_latency(&self) -> usize {
        self.st.get_input_latency()
    }

    pub fn get_output_latency(&self) -> usize {
        self.st.get_output_latency()
    }

    pub fn set_quality(&mut self, quality: usize) -> Result<(), Error> {
        if self.st.set_quality(quality) != 0 {
            Err(Error::InvalidArg)
        } else {
            Ok(())
        }
    }

    pub fn get_quality(&self) -> usize {
        self.st.get_quality()
    }
}