use std::marker::PhantomData;
use crate::error::{check, null_handle_error, Result};
use crate::ffi;
use crate::options::ResampleOptions;
use crate::samples::{channel_pointers, OwnedSamples};
pub struct AudioResampler {
handle: *mut ffi::AvfResampler,
_not_sync: PhantomData<std::cell::Cell<()>>,
}
impl AudioResampler {
pub fn new(options: &ResampleOptions) -> Result<Self> {
let raw = options.to_ffi();
let handle = unsafe { ffi::avf_resampler_new(&raw) };
if handle.is_null() {
return Err(null_handle_error());
}
Ok(Self {
handle,
_not_sync: PhantomData,
})
}
pub fn process(&mut self, samples: &[Vec<f32>]) -> Result<Vec<Vec<f32>>> {
let (pointers, num_samples) = channel_pointers(samples)?;
let owned = OwnedSamples::from_call(|out| {
unsafe {
ffi::avf_resampler_process(
self.handle,
pointers.as_ptr(),
pointers.len() as i32,
num_samples,
out,
)
}
})?;
Ok(owned.to_vecs())
}
pub fn flush(&mut self) -> Result<Vec<Vec<f32>>> {
let owned = OwnedSamples::from_call(|out| {
unsafe { ffi::avf_resampler_flush(self.handle, out) }
})?;
Ok(owned.to_vecs())
}
pub fn output_sample_rate(&self) -> Result<i32> {
let mut rate = 0;
check(unsafe { ffi::avf_resampler_output_sample_rate(self.handle, &mut rate) })?;
Ok(rate)
}
pub fn output_num_channels(&self) -> Result<i32> {
let mut channels = 0;
check(unsafe { ffi::avf_resampler_output_num_channels(self.handle, &mut channels) })?;
Ok(channels)
}
}
impl std::fmt::Debug for AudioResampler {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("AudioResampler")
.field("output_sample_rate", &self.output_sample_rate().ok())
.field("output_num_channels", &self.output_num_channels().ok())
.finish()
}
}
impl Drop for AudioResampler {
fn drop(&mut self) {
unsafe { ffi::avf_resampler_free(self.handle) };
}
}
unsafe impl Send for AudioResampler {}
pub fn resample(
samples: &[Vec<f32>],
input_sample_rate: i32,
output_sample_rate: i32,
output_num_channels: Option<i32>,
) -> Result<Vec<Vec<f32>>> {
let (pointers, num_samples) = channel_pointers(samples)?;
let owned = OwnedSamples::from_call(|out| {
unsafe {
ffi::avf_resample(
pointers.as_ptr(),
pointers.len() as i32,
num_samples,
input_sample_rate,
output_sample_rate,
output_num_channels.unwrap_or(0),
i32::from(output_num_channels.is_some()),
out,
)
}
})?;
Ok(owned.to_vecs())
}