use nom::bits::bits;
use nom::bits::streaming::tag as bit_tag;
use nom::bits::streaming::take as bit_take;
use nom::branch::alt;
use nom::bytes::streaming::tag as byte_tag;
use nom::bytes::streaming::take as byte_take;
use nom::combinator::into;
use nom::combinator::map;
use nom::combinator::verify;
use nom::error::ParseError;
use nom::error_position;
use nom::multi::many_m_n;
use nom::multi::many_till;
use nom::number::streaming::be_u16;
use nom::number::streaming::be_u24;
use nom::number::streaming::be_u8;
use nom::IResult;
use nom::Offset;
use crate::component;
use crate::component::bitrepr::FRAME_CRC;
use crate::component::bitrepr::HEADER_CRC;
use crate::component::FrameOffset;
use crate::constant::MAX_BITS_PER_SAMPLE;
use crate::error::VerifyError;
type BitInput<'a> = (&'a [u8], usize);
pub fn stream<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], component::Stream, E>
where
E: ParseError<&'a [u8]>,
{
let remaining_input = input;
let (remaining_input, _) = byte_tag("fLaC")(remaining_input)?;
let (remaining_input, stream_info_block) = metadata_block(remaining_input)?;
let stream_info = stream_info_block
.data
.as_stream_info()
.ok_or_else(|| nom::Err::Error(error_position!(input, nom::error::ErrorKind::Verify)))?;
let (remaining_input, rest_mdblocks): (_, Vec<component::MetadataBlock>) =
if stream_info_block.is_last {
(remaining_input, vec![])
} else {
let mut is_last = stream_info_block.is_last;
let mut blocks = vec![];
let mut remaining_input = remaining_input;
while !is_last {
let (i, b) = metadata_block(remaining_input)?;
is_last = b.is_last;
remaining_input = i;
blocks.push(b);
}
(remaining_input, blocks)
};
let (remaining_input, (frames, _)) =
many_till(frame(stream_info, true), nom::combinator::eof)(remaining_input)?;
let mut stream = component::Stream::with_stream_info(stream_info.clone());
for mdblock in &rest_mdblocks {
stream.add_metadata_block(mdblock.data.clone());
}
for f in &frames {
stream.frames_mut().push(f.clone());
}
Ok((remaining_input, stream))
}
fn metadata_block<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], component::MetadataBlock, E>
where
E: ParseError<&'a [u8]>,
{
let remaining_input = input;
let (remaining_input, first_byte) = be_u8(remaining_input)?;
let is_last = (first_byte >> 7) != 0;
let block_type = first_byte & 0x7F;
let (remaining_input, length) = be_u24(remaining_input)?;
#[allow(clippy::single_match_else)]
let (remaining_input, body) = match block_type {
0 => map(stream_info, Into::into)(remaining_input)?,
_ => {
let (i, blob) = byte_take(length)(remaining_input)?;
(
i,
component::MetadataBlockData::new_unknown(block_type, blob).map_err(|_e| {
nom::Err::Error(error_position!(
remaining_input,
nom::error::ErrorKind::TagBits
))
})?,
)
}
};
Ok((
remaining_input,
component::MetadataBlock::from_parts(is_last, body),
))
}
pub fn stream_info<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], component::StreamInfo, E>
where
E: ParseError<&'a [u8]>,
{
let remaining_input = input;
let (remaining_input, min_block_size) = be_u16(remaining_input)?;
let (remaining_input, max_block_size) = be_u16(remaining_input)?;
let (remaining_input, min_frame_size) = be_u24(remaining_input)?;
let (remaining_input, max_frame_size) = be_u24(remaining_input)?;
let (remaining_input, (sample_rate, channels, bits_per_sample, total_samples)) =
bits(|input| {
let remaining_input = input;
let (remaining_input, sr) = bit_take(20usize)(remaining_input)?;
let (remaining_input, ch): (_, usize) = bit_take(3usize)(remaining_input)?;
let (remaining_input, bps): (_, usize) = bit_take(5usize)(remaining_input)?;
let (remaining_input, total): (_, usize) = bit_take(36usize)(remaining_input)?;
let ret: IResult<_, _, (BitInput<'a>, nom::error::ErrorKind)> =
Ok((remaining_input, (sr, ch + 1, bps + 1, total)));
ret
})(remaining_input)
.map_err(convert_bits_err)?;
let (remaining_input, md5) = byte_take(16usize)(remaining_input)?;
let info_fn = || {
let mut info = component::StreamInfo::new(sample_rate, channels, bits_per_sample)?;
info.set_total_samples(total_samples);
info.set_md5_digest(md5.try_into().expect("Internal error"));
info.set_block_sizes(min_block_size as usize, max_block_size as usize)?;
info.set_frame_sizes(min_frame_size as usize, max_frame_size as usize)?;
let ret: Result<_, VerifyError> = Ok(info);
ret
};
let info = info_fn().map_err(|_e| {
nom::Err::Error(error_position!(
remaining_input,
nom::error::ErrorKind::Verify
))
})?;
Ok((remaining_input, info))
}
pub fn frame<'a, E>(
stream_info: &component::StreamInfo,
check_crc: bool,
) -> impl FnMut(&'a [u8]) -> IResult<&'a [u8], component::Frame, E>
where
E: ParseError<&'a [u8]>,
{
let channels_from_header = stream_info.channels();
let bits_per_sample_from_header = stream_info.bits_per_sample();
move |input| {
let input_start = input;
let remaining_input = input;
let (remaining_input, header) = frame_header(true)(remaining_input)?;
let channels = header.channel_assignment().channels();
if channels != channels_from_header {
return Err(nom::Err::Error(error_position!(
remaining_input,
nom::error::ErrorKind::TagBits
)));
}
let block_size = header.block_size();
let bits_per_sample = header
.bits_per_sample()
.unwrap_or(bits_per_sample_from_header);
if bits_per_sample != bits_per_sample_from_header {
return Err(nom::Err::Error(error_position!(
remaining_input,
nom::error::ErrorKind::TagBits
)));
}
let mut ch = 0;
let (remaining_input, subframes) = bits(many_m_n(channels, channels, |i| {
let ret = subframe::<(BitInput<'a>, nom::error::ErrorKind)>(
block_size,
bits_per_sample + header.channel_assignment().bits_per_sample_offset(ch),
)(i);
ch += 1;
ret
}))(remaining_input)
.map_err(convert_bits_err)?;
let test_crc16 = check_crc.then(|| {
let frame_bytes = &input_start[..input_start.offset(remaining_input)];
FRAME_CRC.checksum(frame_bytes)
});
#[allow(clippy::unnecessary_map_or)] let (remaining_input, _) =
verify(be_u16, |crc| test_crc16.map_or(true, |x| x == *crc))(remaining_input)?;
let frame = component::Frame::from_parts(header, subframes);
Ok((remaining_input, frame))
}
}
fn convert_bits_err<'a, E>(e: nom::Err<(&'a [u8], nom::error::ErrorKind)>) -> nom::Err<E>
where
E: ParseError<&'a [u8]>,
{
e.map(|(inp, kind)| E::from_error_kind(inp, kind))
}
pub fn frame_header<'a, E>(
check_crc: bool,
) -> impl FnMut(&'a [u8]) -> IResult<&'a [u8], component::FrameHeader, E>
where
E: ParseError<&'a [u8]>,
{
move |input| {
let input_start = input;
let (
remaining_input,
(blocking_type, block_size_tag, sample_rate_tag, channel_tag, sample_size_tag),
) = bits(|bit_input| {
let remaining_input = bit_input;
let (remaining_input, _sync) = bit_tag(0x7FFCu16, 15usize)(remaining_input)?;
let (remaining_input, blocking_type): (_, u8) = bit_take(1usize)(remaining_input)?;
let (remaining_input, block_size_tag): (_, u8) = bit_take(4usize)(remaining_input)?;
let (remaining_input, sample_rate_tag): (_, u8) = bit_take(4usize)(remaining_input)?;
let (remaining_input, channel_tag): (_, u8) = bit_take(4usize)(remaining_input)?;
let (remaining_input, sample_size_tag): (_, u8) = bit_take(3usize)(remaining_input)?;
let (remaining_input, _reserved) = bit_tag(0, 1usize)(remaining_input)?;
let ret: IResult<BitInput<'a>, _, (BitInput<'a>, nom::error::ErrorKind)> = Ok((
remaining_input,
(
blocking_type,
block_size_tag,
sample_rate_tag,
channel_tag,
sample_size_tag,
),
));
ret
})(input)
.map_err(convert_bits_err)?;
let bits_per_sample =
component::SampleSizeSpec::from_tag(sample_size_tag).ok_or_else(|| {
nom::Err::Error(error_position!(
remaining_input,
nom::error::ErrorKind::TagBits
))
})?;
let channel_assignment =
component::ChannelAssignment::from_tag(channel_tag).ok_or_else(|| {
nom::Err::Error(error_position!(
remaining_input,
nom::error::ErrorKind::TagBits
))
})?;
let (remaining_input, offset) = if blocking_type == 0 {
map(utf8_code, |x| FrameOffset::Frame(x as u32))(remaining_input)?
} else {
map(utf8_code, FrameOffset::StartSample)(remaining_input)?
};
let (remaining_input, block_size_spec): (&[u8], component::BlockSizeSpec) =
block_size_code(block_size_tag)(remaining_input)?;
let (remaining_input, sample_rate) = sample_rate_code(sample_rate_tag)(remaining_input)?;
let test_crc8 = check_crc.then(|| {
let header_bytes = &input_start[..input_start.offset(remaining_input)];
HEADER_CRC.checksum(header_bytes)
});
#[allow(clippy::unnecessary_map_or)] let (remaining_input, _) =
verify(be_u8, |crc| test_crc8.map_or(true, |x| x == *crc))(remaining_input)?;
let mut frame_header = component::FrameHeader::from_specs(
block_size_spec,
channel_assignment,
bits_per_sample,
sample_rate,
);
frame_header.set_frame_offset(offset);
Ok((remaining_input, frame_header))
}
}
fn block_size_code<'a, E>(
tag: u8,
) -> impl FnMut(&'a [u8]) -> IResult<&'a [u8], component::BlockSizeSpec, E>
where
E: ParseError<&'a [u8]>,
{
move |input| match tag {
0b0001 => Ok((input, component::BlockSizeSpec::S192)),
0b0010..=0b0101 => Ok((input, component::BlockSizeSpec::Pow2Mul576(tag - 0b0010))),
0b0110 => {
let (i, x) = be_u8(input)?;
Ok((i, component::BlockSizeSpec::ExtraByte(x)))
}
0b0111 => {
let (i, x) = be_u16(input)?;
Ok((i, component::BlockSizeSpec::ExtraTwoBytes(x)))
}
0b1000..=0b1111 => Ok((input, component::BlockSizeSpec::Pow2Mul256(tag - 0b1000))),
_ => Err(nom::Err::Error(error_position!(
input,
nom::error::ErrorKind::TagBits
))),
}
}
fn sample_rate_code<'a, E>(
tag: u8,
) -> impl FnMut(&'a [u8]) -> IResult<&'a [u8], component::SampleRateSpec, E>
where
E: ParseError<&'a [u8]>,
{
debug_assert!(tag <= 0b1110);
move |input| {
let remaining_input = input;
let (remaining_input, data) = if tag == 0b1100 {
let (r, x) = be_u8(remaining_input)?;
(r, Some(x as usize))
} else if tag == 0b1101 || tag == 0b1110 {
let (r, x) = be_u16(remaining_input)?;
(r, Some(x as usize))
} else {
(remaining_input, None)
};
let spec = component::SampleRateSpec::from_tag_and_data(tag, data).ok_or_else(|| {
nom::Err::Error(error_position!(
remaining_input,
nom::error::ErrorKind::TagBits
))
})?;
Ok((remaining_input, spec))
}
}
fn utf8_code<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], u64, E>
where
E: ParseError<&'a [u8]>,
{
let remaining_input = input;
let (remaining_input, head): (_, u64) =
map(byte_take(1usize), |x: &[u8]| x[0].into())(remaining_input)?;
let (tail_count, mut acc) = if head < 128 {
(0usize, head & 0x7F)
} else if head < 0xE0 {
(1, head & 0x1F)
} else if head < 0xF0 {
(2, head & 0x0F)
} else if head < 0xF8 {
(3, head & 0x07)
} else if head < 0xFC {
(4, head & 0x03)
} else if head < 0xFE {
(5, head & 0x01)
} else if head == 0xFE {
(6, 0)
} else {
return Err(nom::Err::Error(error_position!(
remaining_input,
nom::error::ErrorKind::TagBits
)));
};
let (remaining_input, tail): (_, &[u8]) = byte_take(tail_count)(remaining_input)?;
for b in tail {
acc = (acc << 6) | u64::from(*b & 0x3F);
}
Ok((remaining_input, acc))
}
pub fn subframe<'a, E>(
block_size: usize,
bits_per_sample: usize,
) -> impl FnMut(BitInput<'a>) -> IResult<BitInput<'a>, component::SubFrame, E>
where
E: ParseError<BitInput<'a>>,
{
debug_assert!(bits_per_sample <= MAX_BITS_PER_SAMPLE + 1);
alt((
into(constant::<E>(block_size, bits_per_sample)),
into(fixed_lpc::<E>(block_size, bits_per_sample)),
into(lpc::<E>(block_size, bits_per_sample)),
into(verbatim::<E>(block_size, bits_per_sample)),
))
}
fn subframe_header<'a, E>(input: BitInput<'a>) -> IResult<BitInput<'a>, (u8, bool), E>
where
E: ParseError<BitInput<'a>>,
{
let remaining_input = input;
let (remaining_input, typetag) = bit_take(7usize)(remaining_input)?;
let (remaining_input, wasted_flag): (_, u8) = bit_take(1usize)(remaining_input)?;
assert!(wasted_flag == 0);
Ok((remaining_input, (typetag, wasted_flag != 0)))
}
pub fn constant<'a, E>(
block_size: usize,
bits_per_sample: usize,
) -> impl FnMut(BitInput<'a>) -> IResult<BitInput<'a>, component::Constant, E>
where
E: ParseError<BitInput<'a>>,
{
debug_assert!(bits_per_sample <= MAX_BITS_PER_SAMPLE + 1);
move |input| {
let remaining_input = input;
let (remaining_input, (typetag, _wasted_flag)) = subframe_header(remaining_input)?;
if typetag != 0x00 {
return Err(nom::Err::Error(error_position!(
remaining_input,
nom::error::ErrorKind::TagBits
)));
}
let (remaining_input, dc_offset) =
map(bit_take(bits_per_sample), |u| u_to_i(u, bits_per_sample))(remaining_input)?;
Ok((
remaining_input,
component::Constant::from_parts(block_size, dc_offset, bits_per_sample as u8),
))
}
}
pub fn fixed_lpc<'a, E>(
block_size: usize,
bits_per_sample: usize,
) -> impl FnMut(BitInput<'a>) -> IResult<BitInput<'a>, component::FixedLpc, E>
where
E: ParseError<BitInput<'a>>,
{
debug_assert!(bits_per_sample <= MAX_BITS_PER_SAMPLE + 1);
move |input| {
let remaining_input = input;
let (remaining_input, (typetag, _wasted_flag)) = subframe_header(remaining_input)?;
if !(0x08..=0x0C).contains(&typetag) {
return Err(nom::Err::Error(error_position!(
remaining_input,
nom::error::ErrorKind::TagBits
)));
}
let order = (typetag as usize) - 0x08;
let (remaining_input, warm_up) = raw_samples(bits_per_sample, order)(remaining_input)?;
let warm_up = heapless::Vec::try_from(warm_up.as_slice()).expect("Unexpected error");
let (remaining_input, residual) = residual(block_size, order)(remaining_input)?;
Ok((
remaining_input,
component::FixedLpc::from_parts(warm_up, residual, bits_per_sample as u8),
))
}
}
pub fn lpc<'a, E>(
block_size: usize,
bits_per_sample: usize,
) -> impl FnMut(BitInput<'a>) -> IResult<BitInput<'a>, component::Lpc, E>
where
E: ParseError<BitInput<'a>>,
{
debug_assert!(bits_per_sample <= MAX_BITS_PER_SAMPLE + 1);
move |input| {
let remaining_input = input;
let (remaining_input, (typetag, _wasted_flag)) = subframe_header(remaining_input)?;
if !(0x20..0x40).contains(&typetag) {
return Err(nom::Err::Error(error_position!(
remaining_input,
nom::error::ErrorKind::TagBits
)));
}
let order = (typetag as usize) - 0x20 + 1;
let (remaining_input, warm_up) = raw_samples(bits_per_sample, order)(remaining_input)?;
let warm_up = heapless::Vec::try_from(warm_up.as_slice()).expect("Unexpected error");
let (remaining_input, parameters) = quantized_parameters(order)(remaining_input)?;
let (remaining_input, residual) = residual(block_size, order)(remaining_input)?;
Ok((
remaining_input,
component::Lpc::from_parts(warm_up, parameters, residual, bits_per_sample as u8),
))
}
}
pub fn quantized_parameters<'a, E>(
order: usize,
) -> impl FnMut(BitInput<'a>) -> IResult<BitInput<'a>, component::QuantizedParameters, E>
where
E: ParseError<BitInput<'a>>,
{
move |input| {
let remaining_input = input;
let (remaining_input, precision): (_, usize) =
map(bit_take(4usize), |p: u8| p as usize + 1)(remaining_input)?;
let (remaining_input, shift): (_, i8) =
map(bit_take(5usize), |x: u8| u_to_i(u32::from(x), 5) as i8)(remaining_input)?;
let (remaining_input, coefs) = raw_samples(precision, order)(remaining_input)?;
let coefs: Vec<i16> = coefs.into_iter().map(|x| x as i16).collect();
let ret = component::QuantizedParameters::new(&coefs, order, shift, precision)
.expect("Unexpected error");
Ok((remaining_input, ret))
}
}
pub fn verbatim<'a, E>(
block_size: usize,
bits_per_sample: usize,
) -> impl FnMut(BitInput<'a>) -> IResult<BitInput<'a>, component::Verbatim, E>
where
E: ParseError<BitInput<'a>>,
{
debug_assert!(bits_per_sample <= MAX_BITS_PER_SAMPLE + 1);
move |input| {
let remaining_input = input;
let (remaining_input, (typetag, _wasted_flag)) = subframe_header(remaining_input)?;
if typetag != 0x01 {
return Err(nom::Err::Error(error_position!(
remaining_input,
nom::error::ErrorKind::TagBits
)));
}
let (remaining_input, data) = raw_samples(bits_per_sample, block_size)(remaining_input)?;
Ok((
remaining_input,
component::Verbatim::from_samples(&data, bits_per_sample as u8),
))
}
}
pub fn residual<'a, E>(
block_size: usize,
warmup_length: usize,
) -> impl FnMut(BitInput<'a>) -> IResult<BitInput<'a>, component::Residual, E>
where
E: ParseError<BitInput<'a>>,
{
move |input| {
let remaining_input = input;
let (remaining_input, method): (_, u8) = bit_take(2usize)(remaining_input)?;
let p_bits = match method {
0b00 => 4usize,
0b01 => 5usize,
_ => {
return Err(nom::Err::Error(error_position!(
remaining_input,
nom::error::ErrorKind::TagBits
)));
}
};
let (remaining_input, partition_order): (_, u8) = bit_take(4usize)(remaining_input)?;
let partition_count = 1usize << (partition_order as usize);
let partition_len = block_size / partition_count;
let mut rice_params = Vec::with_capacity(partition_count);
let mut quotients = Vec::with_capacity(block_size);
let mut remainders = Vec::with_capacity(block_size);
let mut remaining_input = remaining_input;
for part in 0..partition_count {
let (i, rice_p) = bit_take(p_bits)(remaining_input)?;
remaining_input = i;
rice_params.push(rice_p);
for t in (partition_len * part)..(partition_len * (part + 1)) {
if t < warmup_length {
quotients.push(0);
remainders.push(0);
continue;
}
let (i, q): (_, usize) = unary_code(remaining_input)?;
remaining_input = i;
let (i, r): (_, u32) = bit_take(rice_p as usize)(remaining_input)?;
remaining_input = i;
quotients.push(q as u32);
remainders.push(r);
}
}
let parsed = component::Residual::from_parts(
partition_order,
block_size,
warmup_length,
rice_params,
quotients,
remainders,
);
Ok((remaining_input, parsed))
}
}
fn u_to_i(x: u32, bits: usize) -> i32 {
let x: u64 = x.into(); let msb: u64 = 1u64 << (bits - 1);
let offset: i32 = if x >= msb { (1u32 << bits) as i32 } else { 0 };
i32::try_from(x).unwrap() - offset
}
fn raw_samples<'a, E>(
bits_per_sample: usize,
size: usize,
) -> impl FnMut(BitInput<'a>) -> IResult<BitInput<'a>, Vec<i32>, E>
where
E: ParseError<BitInput<'a>>,
{
debug_assert!(bits_per_sample <= MAX_BITS_PER_SAMPLE + 1);
move |input| {
let mut remaining_input = input;
let mut data = Vec::with_capacity(size);
for _t in 0..size {
let (i, u): (_, u32) = bit_take(bits_per_sample)(remaining_input)?;
remaining_input = i;
data.push(u_to_i(u, bits_per_sample));
}
Ok((remaining_input, data))
}
}
fn unary_code<'a, E>(input: BitInput<'a>) -> IResult<BitInput<'a>, usize, E>
where
E: ParseError<BitInput<'a>>,
{
let remaining_input = input;
let (remaining_input, ret) = nom::multi::many0_count(bit_tag(0, 1usize))(remaining_input)?;
let (remaining_input, _) = bit_tag(1, 1usize)(remaining_input)?;
Ok((remaining_input, ret))
}
#[cfg(test)]
mod tests {
use super::*;
use crate::coding;
use crate::component::bitrepr::encode_to_utf8like;
use crate::component::BitRepr;
use crate::config;
use crate::config::Encoder as EncoderConfig;
use crate::config::Window;
use crate::constant;
use crate::error::Verify;
use crate::lpc;
use crate::sigen;
use crate::sigen::Signal;
use crate::source;
use crate::test_helper::make_random_residual;
use crate::test_helper::make_verbatim_frame;
use nom::error::VerboseError;
use rand::distributions::Distribution;
use rand::distributions::Uniform;
use rand::Rng;
#[test]
fn decoding_stream() {
let channels = 2;
let bits_per_sample = 16;
let sample_rate = 16000;
let signal_len = 102;
let mut channel_signals = vec![];
for _ch in 0..channels {
channel_signals.push(
sigen::Sine::new(36, 0.4)
.noise(0.04)
.to_vec_quantized(bits_per_sample, signal_len),
);
}
let mut signal = vec![];
for t in 0..signal_len {
for s in &channel_signals {
signal.push(s[t]);
}
}
let source =
source::MemSource::from_samples(&signal, channels, bits_per_sample, sample_rate);
let config = EncoderConfig::default().into_verified().unwrap();
let comp = coding::encode_with_fixed_block_size(&config, source, config.block_size)
.expect("encoding error");
let bytes = comp.to_bytes();
let (_remaining_input, decoded) =
stream::<VerboseError<&[u8]>>(&bytes).expect("Unexpected parse error");
assert_eq!(
comp.stream_info().to_bytes(),
decoded.stream_info().to_bytes()
);
assert_eq!(comp.to_bytes(), decoded.to_bytes());
}
#[test]
fn decoding_metadata_block_and_stream_info() {
for is_last in [true, false] {
let nchannels: usize = 2;
let sample_rate: usize = 44100;
let bits_per_sample: usize = 24;
let mut stream_info =
component::StreamInfo::new(sample_rate, nchannels, bits_per_sample).unwrap();
stream_info.set_block_sizes(128, 1024).unwrap();
stream_info.set_frame_sizes(123, 4567).unwrap();
let comp = component::MetadataBlock::from_parts(is_last, stream_info.into());
let bytes = comp.to_bytes();
let (_remaining_input, decoded) =
metadata_block::<VerboseError<&[u8]>>(&bytes).expect("Unexpected parse error");
assert_eq!(comp.to_bytes(), decoded.to_bytes());
}
}
fn decoding_frame_testimpl(block_size: usize, bits_per_sample: usize, sample_rate: usize) {
let nchannels: usize = 2;
let stream_info =
component::StreamInfo::new(sample_rate, nchannels, bits_per_sample).unwrap();
let framebuf = vec![-1i32; block_size * nchannels];
let comp = make_verbatim_frame(&stream_info, &framebuf, 0);
let bytes = comp.to_bytes();
let (_remaining_input, decoded) = frame::<VerboseError<&[u8]>>(&stream_info, true)(&bytes)
.expect("Unexpected parse error");
assert_eq!(comp.to_bytes(), decoded.to_bytes());
}
#[test]
fn decoding_frame() {
for block_size in [1152, 1024] {
let bits_per_sample = 16;
let sample_rate = 65535;
decoding_frame_testimpl(block_size, bits_per_sample, sample_rate);
}
}
fn decoding_frame_header_testimpl(
block_size: usize,
bits_per_sample: usize,
sample_rate: usize,
) {
let nchannels: usize = 2;
let stream_info =
component::StreamInfo::new(sample_rate, nchannels, bits_per_sample).unwrap();
let framebuf = vec![-1i32; block_size * nchannels];
let frame = make_verbatim_frame(&stream_info, &framebuf, 0);
let comp = frame.header().clone();
let bytes = comp.to_bytes();
let (_remaining_input, decoded) =
frame_header::<VerboseError<&[u8]>>(true)(&bytes).expect("Unexpected parse error");
assert_eq!(comp.to_bytes(), decoded.to_bytes());
}
#[test]
fn decoding_frame_header() {
for block_size in [192, 1152, 127, 298, 1024] {
for bits_per_sample in [8, 16, 24] {
for sample_rate in [88200, 3, 65535, 95900] {
decoding_frame_header_testimpl(block_size, bits_per_sample, sample_rate);
}
}
}
}
#[test]
fn decoding_utf8_code() {
for x in &[
0u64,
76,
195,
256,
257,
1000,
1023,
1024,
65535,
65536,
68000,
68_719_476_735, ] {
let code = encode_to_utf8like(*x).expect("encode error");
let (remaining_input, y) =
utf8_code::<VerboseError<&[u8]>>(&code).expect("decode error");
assert_eq!(remaining_input, &[]);
assert_eq!(*x, y);
}
}
fn random_lpc<R: Rng>(mut rng: R) -> component::Lpc {
let block_size = Uniform::from(64..=256).sample(&mut rng);
let order = Uniform::from(1..=constant::qlpc::MAX_ORDER).sample(&mut rng);
let precision = Uniform::from(1..=constant::qlpc::MAX_PRECISION).sample(&mut rng);
let mut signal = Vec::with_capacity(block_size);
for _t in 0..block_size {
signal.push(Uniform::from(-127..=127).sample(&mut rng));
}
let lpc_coefs = lpc::lpc_from_autocorr(&signal, &Window::default(), order);
let qlpc = lpc::quantize_parameters(&lpc_coefs[0..order], precision);
let mut errors = vec![0i32; signal.len()];
lpc::compute_error(&qlpc, &signal, &mut errors);
let residual = coding::encode_residual(&config::Prc::default(), &errors, qlpc.order());
component::Lpc::from_parts(
heapless::Vec::from_slice(&signal[0..qlpc.order()])
.expect("LPC order exceeded the maximum"),
qlpc,
residual,
8,
)
}
#[test]
fn decoding_constant() {
let mut rng = rand::thread_rng();
let block_size = Uniform::from(64..=256).sample(&mut rng);
let offset = Uniform::from(-1000..1000).sample(&mut rng);
let comp = component::Constant::new(block_size, offset, 16).expect("construction error");
let bytes = comp.to_bytes();
let (_remaining_input, decoded) = constant::<VerboseError<BitInput>>(
comp.block_size(),
comp.bits_per_sample(),
)((&bytes, 0))
.expect("Unexpected parse error");
assert_eq!(comp.to_bytes(), decoded.to_bytes());
}
#[test]
fn decoding_fixedlpc() {
let residual = make_random_residual(rand::thread_rng(), 2);
let comp = component::FixedLpc::new(&[0, 0], residual, 16).expect("");
let bytes = comp.to_bytes();
let (_remaining_input, decoded) = fixed_lpc::<VerboseError<BitInput>>(
comp.residual().block_size(),
comp.bits_per_sample(),
)((&bytes, 0))
.expect("Unexpected parse error");
assert_eq!(comp.to_bytes(), decoded.to_bytes());
}
#[test]
fn decoding_lpc() {
let comp = random_lpc(rand::thread_rng());
let bytes = comp.to_bytes();
let (_remaining_input, decoded) = lpc::<VerboseError<BitInput>>(
comp.residual().block_size(),
comp.bits_per_sample(),
)((&bytes, 0))
.expect("Unexpected parse error");
assert_eq!(comp.to_bytes(), decoded.to_bytes());
}
#[test]
fn decoding_verbatim() {
let mut rng = rand::thread_rng();
let block_size = Uniform::from(1..=128).sample(&mut rng);
let mut samples = Vec::with_capacity(block_size);
for _t in 0..block_size {
samples.push(Uniform::from(-127..=127).sample(&mut rng));
}
let bits_per_sample = 12;
let comp = component::Verbatim::from_samples(samples.as_slice(), bits_per_sample as u8);
let bytes = comp.to_bytes();
let (_remaining_input, decoded) =
verbatim::<VerboseError<BitInput>>(block_size, bits_per_sample)((&bytes, 0))
.expect("Unexpected parse error");
assert_eq!(comp.to_bytes(), decoded.to_bytes());
}
#[test]
fn decoding_residual() {
let comp = make_random_residual(rand::thread_rng(), 0);
let bytes = comp.to_bytes();
let (_remaining_input, decoded) = residual::<VerboseError<BitInput>>(
comp.block_size(),
comp.warmup_length(),
)((&bytes, 0))
.expect("Unexpected parse error");
assert_eq!(comp.to_bytes(), decoded.to_bytes());
}
#[test]
fn decoding_unary_code() {
let (remaining_input, decoded) = unary_code::<VerboseError<BitInput>>((&[0x01], 0))
.expect("Unexpected error from `unary_code`.");
assert_eq!(decoded, 7);
assert_eq!(remaining_input, ([].as_slice(), 0));
let (remaining_input, decoded) = unary_code::<VerboseError<BitInput>>((&[0x81], 1))
.expect("Unexpected error from `unary_code`.");
assert_eq!(decoded, 6);
assert_eq!(remaining_input, ([].as_slice(), 0));
let (remaining_input, decoded) = unary_code::<VerboseError<BitInput>>((&[0x80, 0x0F], 1))
.expect("Unexpected error from `unary_code`.");
assert_eq!(decoded, 11);
assert_eq!(remaining_input, ([0x0F].as_slice(), 5));
let (_remaining_input, decoded) = unary_code::<VerboseError<BitInput>>((&[0xDF], 2))
.expect("Unexpected error from `unary_code`.");
assert_eq!(decoded, 1);
}
#[test]
fn unsigned_to_signed_conversion() {
assert_eq!(127, u_to_i(127, 8));
assert_eq!(-128, u_to_i(128, 8));
}
}