mod chunks;
use super::io::{AudioReader, MediaSource, ReadBuffer, AudioSamplesIterator, Sample};
use super::{audio, errors, Result};
use chunks::*;
const RIFF_MARKER : &'static [u8; 4] = b"RIFF";
const WAVE_MARKER : &'static [u8; 4] = b"WAVE";
pub struct WavReader {
reader: MediaSource,
}
impl WavReader {
pub fn new(reader: MediaSource) -> Result <Box<dyn AudioReader>> {
Ok(Box::new(WavReader {
reader: reader,
}))
}
}
impl AudioReader for WavReader {
fn read_header(&mut self) -> Result<audio::AudioInfo> {
if RIFF_MARKER != &(self.reader.read_bytes(4)?)[..] {
return errors::parse_error("no RIFF tag Found");
}
let _chunk_size = self.reader.read_le_u32()?;
if WAVE_MARKER != &(self.reader.read_bytes(4)?)[..] {
return errors::parse_error("no WAVE tag found");
}
let mut info: Option<audio::AudioInfo> = None;
while let Some(chunk) = read_next_chunk(&mut self.reader)? {
if let Chunk::Fmt(audio_info) = chunk {
info = Some(audio_info);
} else if let Chunk::Data(data_len) = chunk {
if let Some(mut _inf) = info {
_inf.total_samples = (data_len / (_inf.bits_per_sample / 8)) as u64;
return Ok(_inf);
}
}
}
return errors::parse_error("no 'fmt' chunk found");
}
fn buffer(&mut self) -> &mut MediaSource {
&mut self.reader
}
}
pub struct WavSamplesIterator<'r, S: Sample> {
reader: &'r mut Box<dyn AudioReader + 'static>,
audio_info: &'r audio::AudioInfo,
samples_left: u64,
phantom: std::marker::PhantomData<S>,
}
impl<'r, S: Sample + 'r> WavSamplesIterator<'r, S> {
pub fn new(reader: &'r mut Box<dyn AudioReader + 'static>, info: &'r audio::AudioInfo) ->
Box<dyn AudioSamplesIterator<S> + 'r> {
Box::new(WavSamplesIterator{
reader: reader,
audio_info: info,
samples_left: info.total_samples,
phantom: std::marker::PhantomData,
})
}
}
impl<'r, S: Sample> AudioSamplesIterator<S> for WavSamplesIterator<'r, S> {
fn next(&mut self) -> Option<Result<S>> {
if self.samples_left > 0 {
let sample = Sample::read::<MediaSource>(
&mut self.reader.buffer(),
self.audio_info.audio_format,
self.audio_info.bits_per_sample as u16,
);
self.samples_left = self.samples_left -1;
return Some(sample);
}
return None;
}
}