use crate::io::{ReadBuffer, Sample};
use crate::{audio, errors, Result};
use super::crc::{Crc8Reader};
#[derive(Clone, Copy)]
enum BlockStrategy {
Fixed,
Variable,
}
#[derive(Clone, Copy)]
enum BlockTime {
FrameNumber(u32),
SampleNumber(u64),
}
#[derive(Clone, Copy, Debug)]
enum ChannelType {
Independent(u8),
LeftSideStereo,
RightSideStereo,
MidSideStereo,
}
#[derive(Clone, Copy)]
struct FrameHeader {
pub block_time: BlockTime,
pub block_size: u16,
pub sample_rate: u32,
pub channel_type: ChannelType,
pub bits_per_sample: u32,
}
pub struct Block<S: Sample> {
first_sample_index: u64,
block_size: u32,
no_channels: u32,
buffer: Vec<S>,
}
impl<S: Sample> Block<S> {
fn new(sample_index: u64, block_size: u32, buffer: Vec<S>) -> Block<S> {
Block {
first_sample_index: sample_index,
block_size: block_size,
no_channels: buffer.len() as u32 / block_size,
buffer: buffer,
}
}
pub fn empty() -> Block<S> {
Block {
first_sample_index: 0,
block_size: 0,
no_channels: 0,
buffer: Vec::with_capacity(0),
}
}
#[inline(always)]
pub fn total_samples(&self) -> u32 {
self.block_size
}
#[inline(always)]
pub fn len(&self) -> u32 {
self.block_size * self.no_channels
}
#[inline(always)]
pub fn into_buffer(self) -> Vec<S> {
self.buffer
}
#[inline(always)]
pub fn get_sample(&self, samples_read: u32) -> S {
self.buffer[samples_read as usize]
}
}
fn read_frame_header<R: ReadBuffer>(input: &mut R, audio_info: &audio::AudioInfo) -> Option<Result<FrameHeader>> {
let mut crc_reader = Crc8Reader::new();
let sync_code = match input.read_be_u16() {
Ok(sync_code) => sync_code,
Err(_) => return None
};
crc_reader.process_bytes(&sync_code.to_be_bytes());
if sync_code & 0b1111_1111_1111_1100 != 0b1111_1111_1111_1000 {
return Some(errors::parse_error("frame sync code incorrect"));
}
if sync_code & 0b0000_0000_0000_0010 != 0 {
return Some(errors::unsupported_error("invalid frame header, encountered reserved value"));
}
let blocking_strategy = if sync_code & 0b0000_0000_0000_0001 == 0 {
BlockStrategy::Fixed
} else {
BlockStrategy::Variable
};
let bs_sr = input.read_u8().unwrap();
crc_reader.process_byte(bs_sr);
let mut block_size = 0u16;
let mut read_bs_last = 0u8;
match bs_sr >> 4 {
0b0000 => return Some(errors::unsupported_error("invalid frame header, encountered reserved value")),
0b0001 => block_size = 192,
n if 0b0010 <= n && n <= 0b0101 => block_size = 576 * (1 << (n - 2) as usize),
0b0110 => read_bs_last = 1, 0b0111 => read_bs_last = 2, n => block_size = 256 * (1 << (n-8) as usize),
}
let mut sample_rate = 0;
let mut read_sr_last = 0u8;
match bs_sr & 0b00001111 {
0b0000 => sample_rate = audio_info.sample_rate, 0b0001 => sample_rate = 88_200,
0b0010 => sample_rate = 176400,
0b0011 => sample_rate = 192000,
0b0100 => sample_rate = 8000,
0b0101 => sample_rate = 16000,
0b0110 => sample_rate = 22050,
0b0111 => sample_rate = 24000,
0b1000 => sample_rate = 32000,
0b1001 => sample_rate = 44100,
0b1010 => sample_rate = 48000,
0b1011 => sample_rate = 96000,
0b1100 => read_sr_last = 1, 0b1101 => read_sr_last = 2, 0b1110 => read_sr_last = 3, _ => return Some(errors::parse_error("invalid frame header")),
}
let ch_bps_r = input.read_u8().unwrap();
crc_reader.process_byte(bs_sr);
let channel_type = match ch_bps_r >> 4 {
n if n < 8 => ChannelType::Independent(n + 1),
0b1000 => ChannelType::LeftSideStereo,
0b1001 => ChannelType::RightSideStereo,
0b1010 => ChannelType::MidSideStereo,
_ => return Some(errors::unsupported_error("Invalid frame header, encountered reserved value")),
};
Some(Ok(FrameHeader {
block_time: BlockTime::FrameNumber(0),
block_size: block_size,
sample_rate: sample_rate,
channel_type: channel_type,
bits_per_sample: 0,
}))
}
pub fn decode_next_frame<R: ReadBuffer, S: Sample>(
input: &mut R,
mut block_buffer: Vec<S>,
audio_info: &audio::AudioInfo,
) -> Option<Result<Block<S>>> {
let frame_header = match read_frame_header(input, audio_info) {
None => return None,
Some(h) => h,
};
None
}