use crate::parsing::{parse_chunk_id, parse_chunks, ChunkID};
use alloc::vec::Vec;
use core::array::TryFromSliceError;
use core::convert::TryInto;
#[derive(Debug, Clone)]
pub enum Error {
UnknownChunkID([u8; 4]),
CantParseSliceInto(TryFromSliceError),
NoRiffChunkFound,
NoDataChunkFound,
NoFmtChunkFound,
UnsupportedBitDepth(u16),
}
#[derive(Debug, PartialEq)]
pub enum Samples {
BitDepth8(Vec<u8>),
BitDepth16(Vec<i16>),
BitDepth24(Vec<i32>),
}
#[derive(Debug, Clone)]
pub struct Header {
pub sample_rate: u32,
pub num_channels: u16,
pub bit_depth: u16,
}
#[derive(Debug)]
pub struct Wave {
pub header: Header,
pub data: Samples,
}
impl Wave {
pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
let riff = bytes[0..4]
.try_into()
.map_err(|e| Error::CantParseSliceInto(e))
.and_then(|b| parse_chunk_id(b))?;
let file_size = bytes[4..8]
.try_into()
.map_err(|e| Error::CantParseSliceInto(e))
.map(|b| u32::from_le_bytes(b))?;
if riff != ChunkID::RIFF {
return Err(Error::NoRiffChunkFound);
}
parse_chunks(&bytes[12..file_size as usize + 8])
}
}
#[cfg(test)]
mod tests {
#![allow(overflowing_literals)]
use super::*;
use alloc::vec;
#[test]
fn test_parse_wave_16_bit_stereo() {
let bytes: [u8; 60] = [
0x52, 0x49, 0x46, 0x46,
0x34, 0x00, 0x00, 0x00,
0x57, 0x41, 0x56, 0x45,
0x66, 0x6d, 0x74, 0x20,
0x10, 0x00, 0x00, 0x00,
0x01, 0x00,
0x02, 0x00,
0x22, 0x56, 0x00, 0x00,
0x88, 0x58, 0x01, 0x00,
0x04, 0x00,
0x10, 0x00,
0x64, 0x61, 0x74, 0x61,
0x10, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x24, 0x17, 0x1e, 0xf3,
0x3c, 0x13, 0x3c, 0x14,
0x16, 0xf9, 0x18, 0xf9,
];
let wave = Wave::from_bytes(&bytes).unwrap();
assert_eq!(wave.header.sample_rate, 22050);
assert_eq!(wave.header.bit_depth, 16);
assert_eq!(wave.header.num_channels, 2);
assert_eq!(
wave.data,
Samples::BitDepth16(vec![
0x0000, 0x0000,
0x1724, 0xf31e,
0x133c, 0x143c,
0xf916, 0xf918,
])
);
}
#[test]
fn test_parse_wave_24_bit_mono() {
let bytes: [u8; 56] = [
0x52, 0x49, 0x46, 0x46,
0x30, 0x00, 0x00, 0x00,
0x57, 0x41, 0x56, 0x45,
0x66, 0x6d, 0x74, 0x20,
0x10, 0x00, 0x00, 0x00,
0x01, 0x00,
0x01, 0x00,
0x44, 0xac, 0x00, 0x00,
0x88, 0x58, 0x01, 0x00,
0x04, 0x00,
0x18, 0x00,
0x64, 0x61, 0x74, 0x61,
0x0c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00,
0x00, 0x24, 0x17,
0x1e, 0xf3, 0x3c,
0x13, 0x3c, 0x14,
];
let wave = Wave::from_bytes(&bytes).unwrap();
assert_eq!(wave.header.sample_rate, 44100);
assert_eq!(wave.header.bit_depth, 24);
assert_eq!(wave.header.num_channels, 1);
assert_eq!(
wave.data,
Samples::BitDepth24(vec![
0x00000000,
0x17240000,
0x3cf31e00,
0x143c1300,
])
);
}
}