sea-codec 0.7.0

Low-complexity, lossy audio codec designed for embedded devices
Documentation
use alloc::vec::Vec;

use crate::{
    codec::{
        common::SeaError,
        file::{SeaFile, SeaFileHeader},
    },
    cursor::Cursor,
};

pub struct SeaDecoder<'inp> {
    cursor: Cursor<'inp>,
    file: SeaFile,
    frames_read: usize,
}

impl<'inp> SeaDecoder<'inp> {
    #[cfg(feature = "std")]
    pub fn from_reader<R: std::io::Read + 'inp>(reader: R) -> Result<Self, SeaError> {
        let mut cursor = Cursor::from_reader(reader);

        let file = SeaFile::from_reader(&mut cursor)?;

        Ok(Self {
            cursor,
            file,
            frames_read: 0,
        })
    }

    pub fn from_slice(data: &'inp [u8]) -> Result<Self, SeaError> {
        let mut cursor = Cursor::from_slice(data);

        let file = SeaFile::from_reader(&mut cursor)?;

        Ok(Self {
            cursor,
            file,
            frames_read: 0,
        })
    }

    pub fn decode_frame(&mut self, result: &mut Vec<i16>) -> Result<bool, SeaError> {
        if self.file.header.total_frames != 0
            && (self.file.header.total_frames as usize) <= self.frames_read
        {
            return Ok(false);
        }

        let remaining_frames = if self.file.header.total_frames > 0 {
            Some(self.file.header.total_frames as usize - self.frames_read)
        } else {
            None
        };

        let samples_written =
            self.file
                .samples_from_reader(&mut self.cursor, remaining_frames, result)?;

        if samples_written == 0 {
            Ok(false)
        } else {
            self.frames_read += samples_written / self.file.header.channels as usize;
            Ok(true)
        }
    }

    pub fn get_header(&self) -> SeaFileHeader {
        self.file.header.clone()
    }
}