sea-codec 0.5.3

Low-complexity, lossy audio codec designed for embedded devices
Documentation
use std::io;

use bytemuck::cast_slice;

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

pub struct SeaDecoder<R, W> {
    reader: R,
    writer: W,
    file: SeaFile,
    frames_read: usize,
}

impl<R, W> SeaDecoder<R, W>
where
    R: io::Read,
    W: io::Write,
{
    pub fn new(mut reader: R, writer: W) -> Result<Self, SeaError> {
        let file = SeaFile::from_reader(&mut reader)?;

        Ok(Self {
            reader,
            writer,
            file,
            frames_read: 0,
        })
    }

    pub fn decode_frame(&mut self) -> 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 reader_res = self
            .file
            .samples_from_reader(&mut self.reader, remaining_frames)?;

        match reader_res {
            Some(samples) => {
                self.frames_read += samples.len() / self.file.header.channels as usize;
                let samples_u8: &[u8] = cast_slice(&samples);
                self.writer.write_all(samples_u8)?;
                Ok(true)
            }
            None => Ok(false),
        }
    }

    pub fn flush(&mut self) {
        let _ = self.writer.flush();
    }

    pub fn finalize(&mut self) -> Result<(), SeaError> {
        self.writer.flush()?;
        Ok(())
    }

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