use std::i32;
use crc::{Crc8Reader, Crc16Reader};
use error::{Error, Result, fmt_err};
use input::{Bitstream, ReadBytes};
use subframe;
#[derive(Clone, Copy)]
enum BlockingStrategy {
Fixed,
Variable,
}
#[derive(Clone, Copy)]
enum BlockTime {
FrameNumber(u32),
SampleNumber(u64),
}
#[derive(Clone, Copy, Debug)]
enum ChannelAssignment {
Independent(u8),
LeftSideStereo,
RightSideStereo,
MidSideStereo,
}
#[derive(Clone, Copy)]
struct FrameHeader {
pub block_time: BlockTime,
pub block_size: u16,
pub sample_rate: Option<u32>,
pub channel_assignment: ChannelAssignment,
pub bits_per_sample: Option<u32>,
}
impl FrameHeader {
pub fn channels(&self) -> u8 {
match self.channel_assignment {
ChannelAssignment::Independent(n) => n,
ChannelAssignment::LeftSideStereo => 2,
ChannelAssignment::RightSideStereo => 2,
ChannelAssignment::MidSideStereo => 2,
}
}
}
fn read_var_length_int<R: ReadBytes>(input: &mut R) -> Result<u64> {
let first = try!(input.read_u8());
let mut read_additional = 0u8;
let mut mask_data = 0b0111_1111u8;
let mut mask_mark = 0b1000_0000u8;
while first & mask_mark != 0 {
read_additional = read_additional + 1;
mask_data = mask_data >> 1;
mask_mark = mask_mark >> 1;
}
if read_additional > 0 {
if read_additional == 1 {
return fmt_err("invalid variable-length integer");
} else {
read_additional = read_additional - 1;
}
}
let mut result = ((first & mask_data) as u64) << (6 * read_additional);
for i in (0..read_additional as i16).rev() {
let byte = try!(input.read_u8());
if byte & 0b1100_0000 != 0b1000_0000 {
return fmt_err("invalid variable-length integer");
}
result = result | (((byte & 0b0011_1111) as u64) << (6 * i as usize));
}
Ok(result)
}
#[test]
fn verify_read_var_length_int() {
use std::io;
use error::Error;
use input::BufferedReader;
let mut reader = BufferedReader::new(
io::Cursor::new(vec![0x24, 0xc2, 0xa2, 0xe2, 0x82, 0xac, 0xf0, 0x90, 0x8d,
0x88, 0xc2, 0x00, 0x80]));
assert_eq!(read_var_length_int(&mut reader).unwrap(), 0x24);
assert_eq!(read_var_length_int(&mut reader).unwrap(), 0xa2);
assert_eq!(read_var_length_int(&mut reader).unwrap(), 0x20ac);
assert_eq!(read_var_length_int(&mut reader).unwrap(), 0x010348);
assert_eq!(read_var_length_int(&mut reader).err().unwrap(),
Error::FormatError("invalid variable-length integer"));
assert_eq!(read_var_length_int(&mut reader).err().unwrap(),
Error::FormatError("invalid variable-length integer"));
}
fn read_frame_header_or_eof<R: ReadBytes>(input: &mut R) -> Result<Option<FrameHeader>> {
let mut crc_input = Crc8Reader::new(input);
let sync_res_block = match try!(crc_input.read_be_u16_or_eof()) {
None => return Ok(None),
Some(x) => x,
};
let sync_code = sync_res_block & 0b1111_1111_1111_1100;
if sync_code != 0b1111_1111_1111_1000 {
return fmt_err("frame sync code missing");
}
if sync_res_block & 0b0000_0000_0000_0010 != 0 {
return fmt_err("invalid frame header, encountered reserved value");
}
let blocking_strategy = if sync_res_block & 0b0000_0000_0000_0001 == 0 {
BlockingStrategy::Fixed
} else {
BlockingStrategy::Variable
};
let bs_sr = try!(crc_input.read_u8());
let mut block_size = 0u16;
let mut read_8bit_bs = false;
let mut read_16bit_bs = false;
match bs_sr >> 4 {
0b0000 => return fmt_err("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_8bit_bs = true,
0b0111 => read_16bit_bs = true,
n => block_size = 256 * (1 << (n - 8) as usize),
}
let mut sample_rate = None;
let mut read_8bit_sr = false;
let mut read_16bit_sr = false;
let mut read_16bit_sr_ten = false;
match bs_sr & 0b0000_1111 {
0b0000 => sample_rate = None, 0b0001 => sample_rate = Some(88_200),
0b0010 => sample_rate = Some(176_400),
0b0011 => sample_rate = Some(192_000),
0b0100 => sample_rate = Some(8_000),
0b0101 => sample_rate = Some(16_000),
0b0110 => sample_rate = Some(22_050),
0b0111 => sample_rate = Some(24_000),
0b1000 => sample_rate = Some(32_000),
0b1001 => sample_rate = Some(44_100),
0b1010 => sample_rate = Some(48_000),
0b1011 => sample_rate = Some(96_000),
0b1100 => read_8bit_sr = true, 0b1101 => read_16bit_sr = true, 0b1110 => read_16bit_sr_ten = true, _ => return fmt_err("invalid frame header"),
}
let chan_bps_res = try!(crc_input.read_u8());
let channel_assignment = match chan_bps_res >> 4 {
n if n < 8 => ChannelAssignment::Independent(n + 1),
0b1000 => ChannelAssignment::LeftSideStereo,
0b1001 => ChannelAssignment::RightSideStereo,
0b1010 => ChannelAssignment::MidSideStereo,
_ => return fmt_err("invalid frame header, encountered reserved value"),
};
let bits_per_sample = match (chan_bps_res & 0b0000_1110) >> 1 {
0b000 => None, 0b001 => Some(8),
0b010 => Some(12),
0b100 => Some(16),
0b101 => Some(20),
0b110 => Some(24),
_ => return fmt_err("invalid frame header, encountered reserved value"),
};
if chan_bps_res & 0b0000_0001 != 0 {
return fmt_err("invalid frame header, encountered reserved value");
}
let block_time = match blocking_strategy {
BlockingStrategy::Variable => {
let sample = try!(read_var_length_int(&mut crc_input));
BlockTime::SampleNumber(sample)
}
BlockingStrategy::Fixed => {
let frame = try!(read_var_length_int(&mut crc_input));
if frame > 0x7fffffff {
return fmt_err("invalid frame header, frame number too large");
}
BlockTime::FrameNumber(frame as u32)
}
};
if read_8bit_bs {
let bs = try!(crc_input.read_u8());
block_size = bs as u16 + 1;
}
if read_16bit_bs {
let bs = try!(crc_input.read_be_u16());
if bs == 0xffff {
return fmt_err("invalid block size, exceeds 65535");
}
block_size = bs + 1;
}
if read_8bit_sr {
let sr = try!(crc_input.read_u8());
sample_rate = Some(sr as u32);
}
if read_16bit_sr {
let sr = try!(crc_input.read_be_u16());
sample_rate = Some(sr as u32);
}
if read_16bit_sr_ten {
let sr_ten = try!(crc_input.read_be_u16());
sample_rate = Some(sr_ten as u32 * 10);
}
let computed_crc = crc_input.crc();
let presumed_crc = try!(crc_input.read_u8());
#[cfg(not(fuzzing))]
{
if computed_crc != presumed_crc {
return fmt_err("frame header CRC mismatch");
}
}
#[cfg(fuzzing)]
let _ = computed_crc == presumed_crc;
let frame_header = FrameHeader {
block_time: block_time,
block_size: block_size,
sample_rate: sample_rate,
channel_assignment: channel_assignment,
bits_per_sample: bits_per_sample,
};
Ok(Some(frame_header))
}
fn decode_left_side(buffer: &mut [i32]) {
let block_size = buffer.len() / 2;
let (mids, sides) = buffer.split_at_mut(block_size);
for (fst, snd) in mids.iter_mut().zip(sides) {
let left = *fst;
let side = *snd;
let right = left.wrapping_sub(side);
*snd = right;
}
}
#[test]
fn verify_decode_left_side() {
let mut buffer = vec![2, 5, 83, 113, 127, -63, -45, -15, 7, 38, 142, 238, 0, -152, -52, -18];
let result = vec![2, 5, 83, 113, 127, -63, -45, -15, -5, -33, -59, -125, 127, 89, 7, 3];
decode_left_side(&mut buffer);
assert_eq!(buffer, result);
}
fn decode_right_side(buffer: &mut [i32]) {
let block_size = buffer.len() / 2;
let (mids, sides) = buffer.split_at_mut(block_size);
for (fst, snd) in mids.iter_mut().zip(sides) {
let side = *fst;
let right = *snd;
let left = side.wrapping_add(right);
*fst = left;
}
}
#[test]
fn verify_decode_right_side() {
let mut buffer = vec![7, 38, 142, 238, 0, -152, -52, -18, -5, -33, -59, -125, 127, 89, 7, 3];
let result = vec![2, 5, 83, 113, 127, -63, -45, -15, -5, -33, -59, -125, 127, 89, 7, 3];
decode_right_side(&mut buffer);
assert_eq!(buffer, result);
}
fn decode_mid_side(buffer: &mut [i32]) {
let block_size = buffer.len() / 2;
let (mids, sides) = buffer.split_at_mut(block_size);
for (fst, snd) in mids.iter_mut().zip(sides) {
let mid = *fst;
let side = *snd;
let mid = mid.wrapping_mul(2) | (side & 1);
let left = mid.wrapping_add(side) / 2;
let right = mid.wrapping_sub(side) / 2;
*fst = left;
*snd = right;
}
}
#[test]
fn verify_decode_mid_side() {
let mut buffer = vec!(-2, -14, 12, -6, 127, 13, -19, -6,
7, 38, 142, 238, 0, -152, -52, -18);
let result = vec!(2, 5, 83, 113, 127, -63, -45, -15,
-5, -33, -59, -125, 127, 89, 7, 3);
decode_mid_side(&mut buffer);
assert_eq!(buffer, result);
}
pub struct Block {
first_sample_number: u64,
block_size: u32,
channels: u32,
buffer: Vec<i32>,
}
impl Block {
fn new(time: u64, bs: u32, buffer: Vec<i32>) -> Block {
Block {
first_sample_number: time,
block_size: bs,
channels: buffer.len() as u32 / bs,
buffer: buffer,
}
}
pub fn empty() -> Block {
Block {
first_sample_number: 0,
block_size: 0,
channels: 0,
buffer: Vec::with_capacity(0),
}
}
pub fn time(&self) -> u64 {
self.first_sample_number
}
#[inline(always)]
pub fn len(&self) -> u32 {
self.block_size * self.channels
}
#[inline(always)]
pub fn duration(&self) -> u32 {
self.block_size
}
#[inline(always)]
pub fn channels(&self) -> u32 {
self.channels
}
#[inline(always)]
pub fn channel(&self, ch: u32) -> &[i32] {
let bsz = self.block_size as usize;
let ch_usz = ch as usize;
&self.buffer[ch_usz * bsz..(ch_usz + 1) * bsz]
}
#[inline(always)]
pub fn sample(&self, ch: u32, sample: u32) -> i32 {
let bsz = self.block_size as usize;
return self.buffer[ch as usize * bsz + sample as usize];
}
pub fn into_buffer(self) -> Vec<i32> {
return self.buffer;
}
#[inline]
pub fn stereo_samples<'a>(&'a self) -> StereoSamples<'a> {
if self.channels != 2 {
panic!("stereo_samples() must only be called for blocks with two channels.");
}
assert!(self.buffer.len() >= self.block_size as usize * 2);
StereoSamples {
buffer: &self.buffer,
block_duration: self.block_size,
current_sample: 0,
}
}
}
#[test]
fn verify_block_sample() {
let block = Block {
first_sample_number: 0,
block_size: 5,
channels: 3,
buffer: vec![2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47],
};
assert_eq!(block.sample(0, 2), 5);
assert_eq!(block.sample(1, 3), 23);
assert_eq!(block.sample(2, 4), 47);
}
pub struct StereoSamples<'a> {
buffer: &'a [i32],
block_duration: u32,
current_sample: u32,
}
impl<'a> Iterator for StereoSamples<'a> {
type Item = (i32, i32);
#[inline(always)]
fn next(&mut self) -> Option<(i32, i32)> {
if self.current_sample == self.block_duration {
None
} else {
let ch_offset = self.block_duration as usize;
let idx = self.current_sample as usize;
let samples = unsafe {
let left = *self.buffer.get_unchecked(idx);
let right = *self.buffer.get_unchecked(idx + ch_offset);
(left, right)
};
self.current_sample += 1;
Some(samples)
}
}
}
#[test]
fn verify_block_stereo_samples_iterator() {
let block = Block {
first_sample_number: 0,
block_size: 3,
channels: 2,
buffer: vec![2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47],
};
let mut iter = block.stereo_samples();
assert_eq!(iter.next(), Some((2, 7)));
assert_eq!(iter.next(), Some((3, 11)));
assert_eq!(iter.next(), Some((5, 13)));
assert_eq!(iter.next(), None);
}
pub struct FrameReader<R: ReadBytes> {
input: R,
}
pub type FrameResult = Result<Option<Block>>;
fn ensure_buffer_len(mut buffer: Vec<i32>, new_len: usize) -> Vec<i32> {
if buffer.len() < new_len {
if buffer.capacity() < new_len {
buffer = vec![0; new_len];
} else {
buffer.resize(new_len, 0);
}
} else {
buffer.truncate(new_len);
}
buffer
}
#[test]
fn ensure_buffer_len_returns_buffer_with_new_len() {
for capacity in 0..10 {
for new_len in 0..10 {
let buffer = Vec::with_capacity(capacity);
let resized = ensure_buffer_len(buffer, new_len);
assert_eq!(resized.len(), new_len);
}
}
}
impl<R: ReadBytes> FrameReader<R> {
pub fn new(input: R) -> FrameReader<R> {
FrameReader {
input: input,
}
}
pub fn read_next_or_eof(&mut self, mut buffer: Vec<i32>) -> FrameResult {
let mut crc_input = Crc16Reader::new(&mut self.input);
let header = match try!(read_frame_header_or_eof(&mut crc_input)) {
None => return Ok(None),
Some(h) => h,
};
let total_samples = header.channels() as usize * header.block_size as usize;
buffer = ensure_buffer_len(buffer, total_samples);
let bps = match header.bits_per_sample {
Some(x) => x,
None => return Err(Error::Unsupported("header without bits per sample info")),
};
debug_assert!(bps as usize <= 32);
{
let mut bitstream = Bitstream::new(&mut crc_input);
let bs = header.block_size as usize;
match header.channel_assignment {
ChannelAssignment::Independent(n_ch) => {
for ch in 0..n_ch as usize {
try!(subframe::decode(&mut bitstream,
bps,
&mut buffer[ch * bs..(ch + 1) * bs]));
}
}
ChannelAssignment::LeftSideStereo => {
try!(subframe::decode(&mut bitstream, bps, &mut buffer[..bs]));
try!(subframe::decode(&mut bitstream,
bps + 1,
&mut buffer[bs..bs * 2]));
decode_left_side(&mut buffer[..bs * 2]);
}
ChannelAssignment::RightSideStereo => {
try!(subframe::decode(&mut bitstream, bps + 1, &mut buffer[..bs]));
try!(subframe::decode(&mut bitstream, bps, &mut buffer[bs..bs * 2]));
decode_right_side(&mut buffer[..bs * 2]);
}
ChannelAssignment::MidSideStereo => {
try!(subframe::decode(&mut bitstream, bps, &mut buffer[..bs]));
try!(subframe::decode(&mut bitstream,
bps + 1,
&mut buffer[bs..bs * 2]));
decode_mid_side(&mut buffer[..bs * 2]);
}
}
}
let computed_crc = crc_input.crc();
let presumed_crc = try!(crc_input.read_be_u16());
#[cfg(not(fuzzing))]
{
if computed_crc != presumed_crc {
return fmt_err("frame CRC mismatch");
}
}
#[cfg(fuzzing)]
let _ = computed_crc == presumed_crc;
let time = match header.block_time {
BlockTime::FrameNumber(fnr) => header.block_size as u64 * fnr as u64,
BlockTime::SampleNumber(snr) => snr,
};
let block = Block::new(time, header.block_size as u32, buffer);
Ok(Some(block))
}
pub fn into_inner(self) -> R {
self.input
}
}