use crate::error::{check, Result};
use crate::ffi;
pub(crate) struct OwnedSamples {
handle: *mut ffi::AvfSamples,
}
impl OwnedSamples {
pub(crate) fn from_call<F>(f: F) -> Result<Self>
where
F: FnOnce(*mut *mut ffi::AvfSamples) -> std::os::raw::c_int,
{
let mut handle: *mut ffi::AvfSamples = std::ptr::null_mut();
check(f(&mut handle))?;
Ok(Self { handle })
}
pub(crate) fn to_vecs(&self) -> Vec<Vec<f32>> {
if self.handle.is_null() {
return Vec::new();
}
unsafe {
let num_channels = ffi::avf_samples_num_channels(self.handle);
let num_samples = ffi::avf_samples_num_samples(self.handle);
if num_channels <= 0 || num_samples <= 0 {
return Vec::new();
}
let len = num_samples as usize;
let mut result = Vec::with_capacity(num_channels as usize);
for channel in 0..num_channels {
let data = ffi::avf_samples_channel(self.handle, channel);
if data.is_null() {
result.push(Vec::new());
} else {
result.push(std::slice::from_raw_parts(data, len).to_vec());
}
}
result
}
}
}
impl Drop for OwnedSamples {
fn drop(&mut self) {
if !self.handle.is_null() {
unsafe { ffi::avf_samples_free(self.handle) };
self.handle = std::ptr::null_mut();
}
}
}
pub(crate) fn channel_pointers(samples: &[Vec<f32>]) -> Result<(Vec<*const f32>, i64)> {
if samples.is_empty() {
return Ok((Vec::new(), 0));
}
let num_samples = samples[0].len();
if let Some(index) = samples.iter().position(|c| c.len() != num_samples) {
return Err(crate::error::Error::new(
crate::error::ErrorKind::InvalidArgument,
format!(
"all channels must have the same length: channel 0 has {} samples, \
channel {index} has {}",
num_samples,
samples[index].len()
),
));
}
let pointers = samples.iter().map(|c| c.as_ptr()).collect();
Ok((pointers, num_samples as i64))
}