use core::num::NonZeroU32;
use crate::{
error::{Error, InvalidData, Result},
input::{Input, SliceInput},
packet::frame_buffer,
Metadata, PacketDecoder, SAMPLES_PER_FRAME,
};
const FOOTER: &[u8; 17] = b"\0\x80\x01\0\x0cAHXE(c)CRI\0\0";
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DecoderState {
Decoding {
remaining_samples: NonZeroU32,
},
Finished,
Failed,
}
struct Stream<S, P> {
input: S,
metadata: Metadata,
state: DecoderState,
codec: PacketDecoder,
pcm: P,
}
impl<S: Input, P: AsMut<[i16]>> Stream<S, P> {
fn new(mut input: S, mut pcm: P) -> Result<Self> {
frame_buffer(pcm.as_mut())?;
let metadata = Metadata::from_input(&mut input)?;
Ok(Self {
input,
metadata,
state: DecoderState::Decoding {
remaining_samples: metadata.sample_count(),
},
codec: PacketDecoder::new(),
pcm,
})
}
fn next_block(&mut self) -> Result<Option<&[i16]>> {
let remaining = match self.state {
DecoderState::Decoding { remaining_samples } => remaining_samples,
DecoderState::Finished => return Ok(None),
DecoderState::Failed => return Err(Error::Failed),
};
self.state = DecoderState::Failed;
let pcm = frame_buffer(self.pcm.as_mut())?;
self.codec.decode_from(&mut self.input, pcm)?;
let count = remaining.get().min(SAMPLES_PER_FRAME as u32);
let next = match NonZeroU32::new(remaining.get() - count) {
Some(remaining_samples) => DecoderState::Decoding { remaining_samples },
None => {
let mut footer = [0; FOOTER.len()];
self.input.read_exact(&mut footer)?;
if &footer != FOOTER {
return Err(Error::Invalid(InvalidData::EndMarker));
}
DecoderState::Finished
}
};
self.state = next;
Ok(Some(&pcm[..count as usize]))
}
}
pub struct SliceDecoder<'input, P = [i16; SAMPLES_PER_FRAME]> {
inner: Stream<SliceInput<'input>, P>,
}
impl<P> core::fmt::Debug for SliceDecoder<'_, P> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("SliceDecoder")
.field("metadata", &self.inner.metadata)
.field("state", &self.inner.state)
.field("remaining_bytes", &self.inner.input.0.len())
.finish_non_exhaustive()
}
}
impl<'input, P> SliceDecoder<'input, P> {
pub const fn metadata(&self) -> Metadata {
self.inner.metadata
}
pub const fn state(&self) -> DecoderState {
self.inner.state
}
pub fn into_inner(self) -> (&'input [u8], P) {
(self.inner.input.0, self.inner.pcm)
}
}
impl<'input> SliceDecoder<'input> {
pub fn new(input: &'input [u8]) -> Result<Self> {
Self::with_buffer(input, [0; SAMPLES_PER_FRAME])
}
}
impl<'input, P: AsMut<[i16]>> SliceDecoder<'input, P> {
pub fn with_buffer(input: &'input [u8], pcm: P) -> Result<Self> {
Ok(Self {
inner: Stream::new(SliceInput(input), pcm)?,
})
}
pub fn next_block(&mut self) -> Result<Option<&[i16]>> {
self.inner.next_block()
}
}
#[cfg(feature = "std")]
pub struct Decoder<R> {
inner: Stream<crate::input::ReaderInput<R>, [i16; SAMPLES_PER_FRAME]>,
}
#[cfg(feature = "std")]
impl<R> core::fmt::Debug for Decoder<R> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("Decoder")
.field("metadata", &self.inner.metadata)
.field("state", &self.inner.state)
.finish_non_exhaustive()
}
}
#[cfg(feature = "std")]
impl<R> Decoder<R> {
pub const fn metadata(&self) -> Metadata {
self.inner.metadata
}
pub const fn state(&self) -> DecoderState {
self.inner.state
}
pub fn into_inner(self) -> R {
self.inner.input.0
}
}
#[cfg(feature = "std")]
impl<R: std::io::Read> Decoder<R> {
pub fn new(reader: R) -> Result<Self> {
Ok(Self {
inner: Stream::new(crate::input::ReaderInput(reader), [0; SAMPLES_PER_FRAME])?,
})
}
pub fn next_block(&mut self) -> Result<Option<&[i16]>> {
self.inner.next_block()
}
}