extern crate minimp3_sys as ffi;
extern crate slice_deque;
use slice_deque::SliceDeque;
use std::io::{self, Read};
use std::marker::Send;
use std::mem;
mod error;
pub use error::Error;
pub const MAX_SAMPLES_PER_FRAME: usize = ffi::MINIMP3_MAX_SAMPLES_PER_FRAME as usize;
const BUFFER_SIZE: usize = MAX_SAMPLES_PER_FRAME * 15;
const REFILL_TRIGGER: usize = MAX_SAMPLES_PER_FRAME * 8;
pub struct Decoder<R>
where
R: Read,
{
reader: R,
buffer: SliceDeque<u8>,
decoder: Box<ffi::mp3dec_t>,
}
unsafe impl<R> Send for Decoder<R>
where
R: Read,
{
}
pub struct Frame {
pub data: Vec<i16>,
pub sample_rate: i32,
pub channels: usize,
pub layer: usize,
pub bitrate: i32,
}
impl<R> Decoder<R>
where
R: Read,
{
pub fn new(reader: R) -> Decoder<R> {
let mut minidec = unsafe { Box::new(mem::zeroed()) };
unsafe { ffi::mp3dec_init(&mut *minidec) }
Decoder {
reader,
buffer: SliceDeque::with_capacity(BUFFER_SIZE),
decoder: minidec,
}
}
pub fn next_frame(&mut self) -> Result<Frame, Error> {
loop {
if self.buffer.len() < REFILL_TRIGGER {
if self.refill()? == 0 {
return Err(Error::Eof);
}
}
match self.decode_frame() {
Ok(frame) => return Ok(frame),
Err(Error::InsufficientData) | Err(Error::SkippedData) => {},
Err(e) => return Err(e),
}
}
}
fn decode_frame(&mut self) -> Result<Frame, Error> {
let mut frame_info = unsafe { mem::zeroed() };
let mut pcm = Vec::with_capacity(MAX_SAMPLES_PER_FRAME);
let samples: usize = unsafe {
ffi::mp3dec_decode_frame(
&mut *self.decoder,
self.buffer.as_ptr(),
self.buffer.len() as _,
pcm.as_mut_ptr(),
&mut frame_info,
) as _
};
if samples > 0 {
unsafe {
pcm.set_len(samples * frame_info.channels as usize);
}
}
let frame = Frame {
data: pcm,
sample_rate: frame_info.hz,
channels: frame_info.channels as usize,
layer: frame_info.layer as usize,
bitrate: frame_info.bitrate_kbps,
};
let current_len = self.buffer.len();
self.buffer
.truncate_front(current_len - frame_info.frame_bytes as usize);
if samples == 0 {
if frame_info.frame_bytes > 0 {
Err(Error::SkippedData)
} else {
Err(Error::InsufficientData)
}
} else {
Ok(frame)
}
}
fn refill(&mut self) -> Result<usize, io::Error> {
let mut dat: [u8; MAX_SAMPLES_PER_FRAME * 5] = [0; MAX_SAMPLES_PER_FRAME * 5];
let read_bytes = self.reader.read(&mut dat)?;
self.buffer.extend(dat.iter());
Ok(read_bytes)
}
}