use crate::{
bits::BitReader,
error::{Error, InvalidData, Result},
input::{Input, SliceInput},
quantization::{self, SubbandSamples},
synthesis::Synthesis,
SAMPLES_PER_FRAME,
};
pub(crate) const FRAME_HEADER: [u8; 4] = [0xff, 0xf5, 0xe0, 0xc0];
#[derive(Debug)]
pub struct DecodedPacket<'a> {
pcm: &'a [i16; SAMPLES_PER_FRAME],
consumed: usize,
}
impl<'a> DecodedPacket<'a> {
pub fn pcm(&self) -> &'a [i16; SAMPLES_PER_FRAME] {
self.pcm
}
pub const fn consumed_bytes(&self) -> usize {
self.consumed
}
}
pub struct PacketDecoder {
synthesis: Synthesis,
}
impl core::fmt::Debug for PacketDecoder {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("PacketDecoder").finish_non_exhaustive()
}
}
impl Default for PacketDecoder {
fn default() -> Self {
Self::new()
}
}
impl PacketDecoder {
pub fn new() -> Self {
Self {
synthesis: Synthesis::new(),
}
}
pub fn decode_into<'a>(
&mut self,
input: &[u8],
pcm: &'a mut [i16],
) -> Result<DecodedPacket<'a>> {
let pcm = frame_buffer(pcm)?;
let consumed = self.decode_from(&mut SliceInput(input), pcm)?;
Ok(DecodedPacket { pcm, consumed })
}
pub(crate) fn decode_from(
&mut self,
input: &mut impl Input,
pcm: &mut [i16; SAMPLES_PER_FRAME],
) -> Result<usize> {
let frame = ParsedFrame::read(input)?;
frame.synthesize(&mut self.synthesis, pcm);
Ok(frame.consumed)
}
}
pub(crate) fn frame_buffer(pcm: &mut [i16]) -> Result<&mut [i16; SAMPLES_PER_FRAME]> {
let provided = pcm.len();
pcm.first_chunk_mut().ok_or(Error::BufferTooSmall {
required: SAMPLES_PER_FRAME,
provided,
})
}
struct ParsedFrame {
bands: SubbandSamples,
consumed: usize,
}
impl ParsedFrame {
fn read(input: &mut impl Input) -> Result<Self> {
let mut header = [0; FRAME_HEADER.len()];
input.read_exact(&mut header)?;
if header != FRAME_HEADER {
return Err(Error::Invalid(InvalidData::FrameHeader));
}
let mut bits = BitReader::new(input);
let bands = quantization::read_subbands(&mut bits)?;
Ok(Self {
bands,
consumed: bits.consumed_bytes(),
})
}
fn synthesize(&self, synthesis: &mut Synthesis, pcm: &mut [i16; SAMPLES_PER_FRAME]) {
let (blocks, _) = pcm.as_chunks_mut::<32>();
for (band, output) in self.bands.iter().zip(blocks) {
synthesis.decode(band, output);
}
}
}