use crate::base::{Error, Format};
use crate::frames::{Frames, FramesMut};
use crate::resampling::ResampleAlgorithm;
use miniaudio_sys as sys;
#[repr(transparent)]
pub struct DataConverterConfig(sys::ma_data_converter_config);
impl DataConverterConfig {
pub fn new(
format_in: Format,
format_out: Format,
channels_in: u32,
channels_out: u32,
sample_rate_in: u32,
sample_rate_out: u32,
) -> DataConverterConfig {
DataConverterConfig(unsafe {
sys::ma_data_converter_config_init(
format_in as _,
format_out as _,
channels_in,
channels_out,
sample_rate_in,
sample_rate_out,
)
})
}
#[inline]
pub fn format_in(&self) -> Format {
Format::from_c(self.0.formatIn)
}
#[inline]
pub fn set_format_in(&mut self, format: Format) {
self.0.formatIn = format as _;
}
#[inline]
pub fn format_out(&self) -> Format {
Format::from_c(self.0.formatOut)
}
#[inline]
pub fn set_format_out(&mut self, format: Format) {
self.0.formatOut = format as _;
}
#[inline]
pub fn channels_in(&self) -> u32 {
self.0.channelsIn
}
#[inline]
pub fn set_channels_in(&mut self, channels: u32) {
self.0.channelsIn = channels;
}
#[inline]
pub fn channels_out(&self) -> u32 {
self.0.channelsOut
}
#[inline]
pub fn set_channels_out(&mut self, channels: u32) {
self.0.channelsOut = channels;
}
pub fn sample_rate_in(&self) -> u32 {
self.0.sampleRateIn
}
pub fn set_sample_rate_in(&mut self, rate: u32) {
self.0.sampleRateIn = rate;
}
pub fn sample_rate_out(&self) -> u32 {
self.0.sampleRateOut
}
pub fn set_resampling(&mut self, algo: ResampleAlgorithm) {
match algo {
ResampleAlgorithm::Linear {
lpf_order,
lpf_nyquist_factor,
} => {
self.0.resampling.algorithm = sys::ma_resample_algorithm_linear;
self.0.resampling.linear.lpfOrder = lpf_order;
self.0.resampling.linear.lpfNyquistFactor = lpf_nyquist_factor;
}
ResampleAlgorithm::Speex { quality } => {
self.0.resampling.algorithm = sys::ma_resample_algorithm_speex;
self.0.resampling.speex.quality = quality as _;
}
}
}
pub fn resampling(&self) -> ResampleAlgorithm {
match self.0.resampling.algorithm {
sys::ma_resample_algorithm_linear => ResampleAlgorithm::Linear {
lpf_order: self.0.resampling.linear.lpfOrder,
lpf_nyquist_factor: self.0.resampling.linear.lpfNyquistFactor,
},
sys::ma_resample_algorithm_speex => ResampleAlgorithm::Speex {
quality: self.0.resampling.speex.quality as _,
},
_ => unreachable!(),
}
}
}
impl Default for DataConverterConfig {
fn default() -> Self {
DataConverterConfig(unsafe { sys::ma_data_converter_config_init_default() })
}
}
#[repr(transparent)]
pub struct DataConverter(sys::ma_data_converter);
impl DataConverter {
pub fn new(config: &DataConverterConfig) -> Result<DataConverter, Error> {
let mut converter = std::mem::MaybeUninit::<DataConverter>::uninit();
unsafe {
Error::from_c_result(sys::ma_data_converter_init(
&config.0 as *const _,
converter.as_mut_ptr().cast(),
))?;
Ok(converter.assume_init())
}
}
#[inline]
pub fn process_pcm_frames(
&mut self,
output: &mut FramesMut,
input: &Frames,
) -> Result<(u64, u64), Error> {
let mut input_frame_count = input.frame_count() as u64;
let mut output_frame_count = output.frame_count() as u64;
Error::from_c_result(unsafe {
sys::ma_data_converter_process_pcm_frames(
&mut self.0,
input.as_ptr() as *const _,
&mut input_frame_count,
output.as_mut_ptr() as *mut _,
&mut output_frame_count,
)
})?;
Ok((output_frame_count, input_frame_count))
}
pub fn set_rate(&mut self, sample_rate_in: u32, sample_rate_out: u32) -> Result<(), Error> {
Error::from_c_result(unsafe {
sys::ma_data_converter_set_rate(&mut self.0, sample_rate_in, sample_rate_out)
})
}
pub fn set_rate_ratio(&mut self, ratio_in_out: f32) -> Result<(), Error> {
Error::from_c_result(unsafe {
sys::ma_data_converter_set_rate_ratio(&mut self.0, ratio_in_out)
})
}
pub fn required_input_frame_count(&self, output_frame_count: u64) -> u64 {
unsafe {
sys::ma_data_converter_get_required_input_frame_count(
&self as *const _ as *mut _,
output_frame_count,
)
}
}
pub fn expected_output_frame_count(&self, input_frame_count: u64) -> u64 {
unsafe {
sys::ma_data_converter_get_expected_output_frame_count(
&self as *const _ as *mut _,
input_frame_count,
)
}
}
pub fn input_latency(&self) -> u64 {
unsafe { sys::ma_data_converter_get_input_latency(&self as *const _ as *mut _) }
}
pub fn output_latency(&self) -> u64 {
unsafe { sys::ma_data_converter_get_output_latency(&self as *const _ as *mut _) }
}
}
impl Drop for DataConverter {
fn drop(&mut self) {
unsafe {
sys::ma_data_converter_uninit(&mut self.0);
}
}
}
unsafe impl Send for DataConverter {}
unsafe impl Sync for DataConverter {}