Skip to content
This repository was archived by the owner on Jan 6, 2023. It is now read-only.

Commit

Permalink
Added basic support for decoders
Browse files Browse the repository at this point in the history
  • Loading branch information
Nazariglez authored and ExPixel committed Jul 5, 2020
1 parent 8af8552 commit d51f1a3
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
target/
Cargo.lock
.idea
121 changes: 121 additions & 0 deletions miniaudio/src/decoder.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
use crate::{Error, Format, FramesMut};
use bitflags::_core::ops::Deref;
use miniaudio_sys as sys;
use std::ffi::CString;
use std::mem::MaybeUninit;
use std::sync::Arc;

#[repr(transparent)]
#[derive(Clone)]
pub struct DecoderConfig(sys::ma_decoder_config);

impl DecoderConfig {
#[inline]
pub fn new(format: Format, output_channels: u32, output_sample_rate: u32) -> Self {
DecoderConfig(unsafe {
sys::ma_decoder_config_init(format as _, output_channels as _, output_sample_rate as _)
})
}
}

#[derive(Clone)]
pub struct Decoder(Arc<RawDecoder>);

impl Decoder {
#[inline]
pub fn from_file(file: &str, config: Option<&DecoderConfig>) -> Result<Decoder, Error> {
RawDecoder::from_file(file, config).map(Decoder)
}

#[inline]
pub fn from_memory(data: &[u8], config: Option<&DecoderConfig>) -> Result<Decoder, Error> {
RawDecoder::from_memory(data, config).map(Decoder)
}

#[inline]
pub fn output_format(&self) -> Format {
Format::from_c(self.raw().outputFormat)
}

#[inline]
pub fn output_channels(&self) -> u32 {
self.raw().outputChannels
}

#[inline]
pub fn output_sample_rate(&self) -> u32 {
self.raw().outputSampleRate
}

#[inline]
pub fn read_pcm_frames(&mut self, output: &mut FramesMut) -> u64 {
unsafe {
sys::ma_decoder_read_pcm_frames(
Arc::deref(&self.0) as *const _ as *mut _,
output.as_mut_ptr() as *mut _,
output.frame_count() as u64,
);
}

1
}

#[inline]
fn raw(&self) -> &sys::ma_decoder {
&(self.0).0
}
}

impl std::ops::Deref for Decoder {
type Target = RawDecoder;

fn deref(&self) -> &Self::Target {
&self.0
}
}

#[repr(transparent)]
#[derive(Clone)]
pub struct RawDecoder(sys::ma_decoder);

unsafe impl Send for RawDecoder {}
unsafe impl Sync for RawDecoder {}

impl RawDecoder {
fn from_file(file: &str, config: Option<&DecoderConfig>) -> Result<Arc<Self>, Error> {
let decoder = Arc::new(MaybeUninit::<RawDecoder>::uninit());
let filename = CString::new(file.to_string()).map_err(|_err| Error::InvalidFile)?;

let result = unsafe {
sys::ma_decoder_init_file(
filename.as_ptr() as *const _,
config.map(|c| &c.0 as *const _).unwrap_or(std::ptr::null()),
Arc::deref(&decoder).as_ptr() as *mut _,
)
};

map_result!(result, unsafe { std::mem::transmute(decoder) })
}

fn from_memory(data: &[u8], config: Option<&DecoderConfig>) -> Result<Arc<Self>, Error> {
let decoder = Arc::new(MaybeUninit::<RawDecoder>::uninit());

let result = unsafe {
sys::ma_decoder_init_memory(
data.as_ptr() as *const _,
data.len() as _,
config.map(|c| &c.0 as *const _).unwrap_or(std::ptr::null()),
Arc::deref(&decoder).as_ptr() as *mut _,
)
};

map_result!(result, unsafe { std::mem::transmute(decoder) })
}
}

impl Drop for RawDecoder {
fn drop(&mut self) {
Error::from_c_result(unsafe { sys::ma_decoder_uninit(&mut self.0) })
.expect("failed to uninit decoder");
}
}
2 changes: 2 additions & 0 deletions miniaudio/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ mod base;
mod channel_conv;
mod conversion;
mod data_conv;
mod decoder;
mod device_io;
mod filters;
mod frames;
Expand All @@ -56,6 +57,7 @@ pub use base::*;
pub use channel_conv::*;
pub use conversion::*;
pub use data_conv::*;
pub use decoder::*;
pub use device_io::*;
pub use filters::*;
pub use frames::*;
Expand Down

0 comments on commit d51f1a3

Please sign in to comment.