use std::cmp;
use std::num;
use error::{Error, Result, fmt_err};
use input::{Bitstream, ReadBytes};
#[derive(Clone, Copy, Debug)]
enum SubframeType {
Constant,
Verbatim,
Fixed(u8),
Lpc(u8),
}
#[derive(Clone, Copy)]
struct SubframeHeader {
sf_type: SubframeType,
wasted_bits_per_sample: u32,
}
fn read_subframe_header<R: ReadBytes>(input: &mut Bitstream<R>) -> Result<SubframeHeader> {
if try!(input.read_bit()) {
return fmt_err("invalid subframe header");
}
let sf_type = match try!(input.read_leq_u8(6)) {
0 => SubframeType::Constant,
1 => SubframeType::Verbatim,
n if (n & 0b111_110 == 0b000_010) || (n & 0b111_100 == 0b000_100) ||
(n & 0b110_000 == 0b010_000) => {
return fmt_err("invalid subframe header, encountered reserved value");
}
n if n & 0b111_000 == 0b001_000 => {
let order = n & 0b000_111;
if order > 4 {
return fmt_err("invalid subframe header, encountered reserved value");
}
SubframeType::Fixed(order)
}
n => {
let order_mo = n & 0b011_111;
SubframeType::Lpc(order_mo + 1)
}
};
let wastes_bits = try!(input.read_bit());
let wasted_bits = if !wastes_bits {
0
} else {
1 + try!(input.read_unary())
};
if wasted_bits > 31 {
return fmt_err("wasted bits per sample must not exceed 31");
}
let subframe_header = SubframeHeader {
sf_type: sf_type,
wasted_bits_per_sample: wasted_bits,
};
Ok(subframe_header)
}
#[inline(always)]
fn extend_sign_u16(val: u16, bits: u32) -> i16 {
return ((val << (16 - bits)) as i16) >> (16 - bits);
}
#[test]
fn verify_extend_sign_u16() {
assert_eq!(5, extend_sign_u16(5, 4));
assert_eq!(0x3ffe, extend_sign_u16(0x3ffe, 15));
assert_eq!(-5, extend_sign_u16(16 - 5, 4));
assert_eq!(-3, extend_sign_u16(512 - 3, 9));
assert_eq!(-1, extend_sign_u16(0xffff, 16));
assert_eq!(-2, extend_sign_u16(0xfffe, 16));
assert_eq!(-1, extend_sign_u16(0x7fff, 15));
}
#[inline(always)]
pub fn extend_sign_u32(val: u32, bits: u32) -> i32 {
((val << (32 - bits)) as i32) >> (32 - bits)
}
#[test]
fn verify_extend_sign_u32() {
assert_eq!(5, extend_sign_u32(5, 4));
assert_eq!(0x3ffffffe, extend_sign_u32(0x3ffffffe, 31));
assert_eq!(-5, extend_sign_u32(16 - 5, 4));
assert_eq!(-3, extend_sign_u32(512 - 3, 9));
assert_eq!(-2, extend_sign_u32(0xfffe, 16));
assert_eq!(-1, extend_sign_u32(0xffffffff_u32, 32));
assert_eq!(-2, extend_sign_u32(0xfffffffe_u32, 32));
assert_eq!(-1, extend_sign_u32(0x7fffffff, 31));
assert_eq!(-6392, extend_sign_u32(124680, 17));
assert_eq!(-6605, extend_sign_u32(124467, 17));
assert_eq!(-6850, extend_sign_u32(124222, 17));
assert_eq!(-7061, extend_sign_u32(124011, 17));
}
#[inline(always)]
fn rice_to_signed(val: u32) -> i32 {
let half = (val >> 1) as i32;
let extended_bit_0 = ((val << 31) as i32) >> 31;
half ^ extended_bit_0
}
#[test]
fn verify_rice_to_signed() {
assert_eq!(rice_to_signed(0), 0);
assert_eq!(rice_to_signed(1), -1);
assert_eq!(rice_to_signed(2), 1);
assert_eq!(rice_to_signed(3), -2);
assert_eq!(rice_to_signed(4), 2);
}
pub fn decode<R: ReadBytes>(input: &mut Bitstream<R>,
bps: u32,
buffer: &mut [i32])
-> Result<()> {
debug_assert!(32 >= bps);
let header = try!(read_subframe_header(input));
if header.wasted_bits_per_sample >= bps {
return fmt_err("subframe has no non-wasted bits");
}
let sf_bps = bps - header.wasted_bits_per_sample;
match header.sf_type {
SubframeType::Constant => try!(decode_constant(input, sf_bps, buffer)),
SubframeType::Verbatim => try!(decode_verbatim(input, sf_bps, buffer)),
SubframeType::Fixed(ord) => try!(decode_fixed(input, sf_bps, ord as u32, buffer)),
SubframeType::Lpc(ord) => try!(decode_lpc(input, sf_bps, ord as u32, buffer)),
}
if header.wasted_bits_per_sample > 0 {
debug_assert!(header.wasted_bits_per_sample <= 31,
"Cannot shift by more than the sample width.");
for s in buffer {
*s = s.wrapping_shl(header.wasted_bits_per_sample);
}
}
Ok(())
}
#[derive(Copy, Clone)]
enum RicePartitionType {
Rice,
Rice2,
}
fn decode_residual<R: ReadBytes>(input: &mut Bitstream<R>,
block_size: u16,
buffer: &mut [i32])
-> Result<()> {
let partition_type = match try!(input.read_leq_u8(2)) {
0b00 => RicePartitionType::Rice,
0b01 => RicePartitionType::Rice2,
_ => return fmt_err("invalid residual, encountered reserved value"),
};
let order = try!(input.read_leq_u8(4));
let n_partitions = 1u32 << order;
let n_samples_per_partition = block_size >> order;
if block_size & (n_partitions - 1) as u16 != 0 {
return fmt_err("invalid partition order")
}
debug_assert_eq!(n_partitions * n_samples_per_partition as u32, block_size as u32);
let n_warm_up = block_size - buffer.len() as u16;
if n_warm_up > n_samples_per_partition {
return fmt_err("invalid residual");
}
match partition_type {
RicePartitionType::Rice => {
let mut start = 0;
let mut len = n_samples_per_partition - n_warm_up;
for _ in 0..n_partitions {
let slice = &mut buffer[start..start + len as usize];
try!(decode_rice_partition(input, slice));
start = start + len as usize;
len = n_samples_per_partition;
}
}
RicePartitionType::Rice2 => {
let mut start = 0;
let mut len = n_samples_per_partition - n_warm_up;
for _ in 0..n_partitions {
let slice = &mut buffer[start..start + len as usize];
try!(decode_rice2_partition(input, slice));
start = start + len as usize;
len = n_samples_per_partition;
}
}
}
Ok(())
}
#[inline(always)]
fn decode_rice_partition<R: ReadBytes>(input: &mut Bitstream<R>,
buffer: &mut [i32])
-> Result<()> {
let rice_param = try!(input.read_leq_u8(4)) as u32;
if rice_param == 0b1111 {
return Err(Error::Unsupported("unencoded binary is not yet implemented"))
}
if rice_param <= 8 {
for sample in buffer.iter_mut() {
let q = try!(input.read_unary());
let r = try!(input.read_leq_u8(rice_param)) as u32;
*sample = rice_to_signed((q << rice_param) | r);
}
} else {
for sample in buffer.iter_mut() {
let q = try!(input.read_unary());
let r = try!(input.read_gt_u8_leq_u16(rice_param));
*sample = rice_to_signed((q << rice_param) | r);
}
}
Ok(())
}
#[inline(never)]
#[cold]
fn decode_rice2_partition<R: ReadBytes>(input: &mut Bitstream<R>,
buffer: &mut [i32])
-> Result<()> {
let rice_param = try!(input.read_leq_u8(5)) as u32;
if rice_param == 0b11111 {
return Err(Error::Unsupported("unencoded binary is not yet implemented"))
}
for sample in buffer.iter_mut() {
let q = try!(input.read_unary());
let r = try!(input.read_leq_u32(rice_param));
*sample = rice_to_signed((q << rice_param) | r);
}
Ok(())
}
fn decode_constant<R: ReadBytes>(input: &mut Bitstream<R>,
bps: u32,
buffer: &mut [i32])
-> Result<()> {
let sample_u32 = try!(input.read_leq_u32(bps));
let sample = extend_sign_u32(sample_u32, bps);
for s in buffer {
*s = sample;
}
Ok(())
}
#[cold]
fn decode_verbatim<R: ReadBytes>(input: &mut Bitstream<R>,
bps: u32,
buffer: &mut [i32])
-> Result<()> {
debug_assert!(bps <= 32);
for s in buffer {
*s = extend_sign_u32(try!(input.read_leq_u32(bps)), bps);
}
Ok(())
}
fn predict_fixed(order: u32, buffer: &mut [i32]) -> Result<()> {
debug_assert!(order <= 4);
let o0 = [];
let o1 = [1];
let o2 = [-1, 2];
let o3 = [1, -3, 3];
let o4 = [-1, 4, -6, 4];
let coefficients: &[i32] = match order {
0 => &o0,
1 => &o1,
2 => &o2,
3 => &o3,
4 => &o4,
_ => unreachable!(),
};
let window_size = order as usize + 1;
for i in 0..buffer.len() - order as usize {
let window = &mut buffer[i..i + window_size];
let prediction = coefficients.iter()
.zip(window.iter())
.map(|(&c, &s)| num::Wrapping(c) * num::Wrapping(s))
.fold(num::Wrapping(0), |a, x| a + x).0;
let delta = window[coefficients.len()];
window[coefficients.len()] = prediction.wrapping_add(delta);
}
Ok(())
}
#[test]
fn verify_predict_fixed() {
let mut buffer = [-729, -722, -667, -19, -16, 17, -23, -7,
16, -16, -5, 3, -8, -13, -15, -1];
assert!(predict_fixed(3, &mut buffer).is_ok());
assert_eq!(&buffer, &[-729, -722, -667, -583, -486, -359, -225, -91,
59, 209, 354, 497, 630, 740, 812, 845]);
let mut buffer = [21877, 27482, -6513];
assert!(predict_fixed(2, &mut buffer).is_ok());
assert_eq!(&buffer, &[21877, 27482, 26574]);
}
fn decode_fixed<R: ReadBytes>(input: &mut Bitstream<R>,
bps: u32,
order: u32,
buffer: &mut [i32])
-> Result<()> {
if buffer.len() < order as usize {
return fmt_err("invalid fixed subframe, order is larger than block size")
}
try!(decode_verbatim(input, bps, &mut buffer[..order as usize]));
try!(decode_residual(input,
buffer.len() as u16,
&mut buffer[order as usize..]));
try!(predict_fixed(order, buffer));
Ok(())
}
fn predict_lpc_low_order(
raw_coefficients: &[i16],
qlp_shift: i16,
buffer: &mut [i32],
) {
debug_assert!(qlp_shift >= 0, "Right-shift by negative value is not allowed.");
debug_assert!(qlp_shift < 64, "Cannot shift by more than integer width.");
let order = raw_coefficients.len();
let coefficients = {
let mut buf = [0i64; 12];
let mut i = 12 - order;
for c in raw_coefficients {
buf[i] = *c as i64;
i = i + 1;
}
buf
};
let left = cmp::min(12, buffer.len()) - order;
for i in 0..left {
let prediction = raw_coefficients.iter()
.zip(&buffer[i..order + i])
.map(|(&c, &s)| c as i64 * s as i64)
.sum::<i64>() >> qlp_shift;
let delta = buffer[order + i] as i64;
buffer[order + i] = (prediction + delta) as i32;
}
if buffer.len() <= 12 {
return
}
for i in 12..buffer.len() {
let prediction = coefficients.iter()
.zip(&buffer[i - 12..i])
.map(|(&c, &s)| c * s as i64)
.sum::<i64>() >> qlp_shift;
let delta = buffer[i] as i64;
buffer[i] = (prediction + delta) as i32;
}
}
fn predict_lpc_high_order(
coefficients: &[i16],
qlp_shift: i16,
buffer: &mut [i32],
) {
let order = coefficients.len();
debug_assert!(qlp_shift >= 0, "Right-shift by negative value is not allowed.");
debug_assert!(qlp_shift < 64, "Cannot shift by more than integer width.");
debug_assert!(order > 12, "Use the faster predict_lpc_low_order for LPC order <= 12.");
debug_assert!(buffer.len() >= order, "Buffer must fit at least `order` warm-up samples.");
for i in order..buffer.len() {
let prediction = coefficients.iter()
.zip(&buffer[i - order..i])
.map(|(&c, &s)| c as i64 * s as i64)
.sum::<i64>() >> qlp_shift;
let delta = buffer[i] as i64;
buffer[i] = (prediction + delta) as i32;
}
}
#[test]
fn verify_predict_lpc() {
let coefficients = [-75, 166, 121, -269, -75, -399, 1042];
let mut buffer = [-796, -547, -285, -32, 199, 443, 670, -2,
-23, 14, 6, 3, -4, 12, -2, 10];
predict_lpc_low_order(&coefficients, 9, &mut buffer);
assert_eq!(&buffer, &[-796, -547, -285, -32, 199, 443, 670, 875,
1046, 1208, 1343, 1454, 1541, 1616, 1663, 1701]);
let coefficients = [119, -255, 555, -836, 879, -1199, 1757];
let mut buffer = [-21363, -21951, -22649, -24364, -27297, -26870, -30017, 3157];
predict_lpc_low_order(&coefficients, 10, &mut buffer);
assert_eq!(&buffer, &[-21363, -21951, -22649, -24364, -27297, -26870, -30017, -29718]);
let coefficients = [
709, -2589, 4600, -4612, 1350, 4220, -9743, 12671, -12129, 8586,
-3775, -645, 3904, -5543, 4373, 182, -6873, 13265, -15417, 11550,
];
let mut buffer = [
213238, 210830, 234493, 209515, 235139, 201836, 208151, 186277, 157720, 148176,
115037, 104836, 60794, 54523, 412, 17943, -6025, -3713, 8373, 11764, 30094,
];
predict_lpc_high_order(&coefficients, 12, &mut buffer);
assert_eq!(&buffer, &[
213238, 210830, 234493, 209515, 235139, 201836, 208151, 186277, 157720, 148176,
115037, 104836, 60794, 54523, 412, 17943, -6025, -3713, 8373, 11764, 33931,
]);
}
fn decode_lpc<R: ReadBytes>(input: &mut Bitstream<R>,
bps: u32,
order: u32,
buffer: &mut [i32])
-> Result<()> {
debug_assert!(order <= 32);
if buffer.len() < order as usize {
return fmt_err("invalid LPC subframe, lpc order is larger than block size")
}
try!(decode_verbatim(input, bps, &mut buffer[..order as usize]));
let qlp_precision = try!(input.read_leq_u8(4)) as u32 + 1;
if qlp_precision - 1 == 0b1111 {
return fmt_err("invalid subframe, qlp precision value invalid");
}
let qlp_shift_unsig = try!(input.read_leq_u16(5));
let qlp_shift = extend_sign_u16(qlp_shift_unsig, 5);
if qlp_shift < 0 {
let msg = "a negative quantized linear predictor coefficient shift is \
not supported, please file a bug.";
return Err(Error::Unsupported(msg))
}
let mut coefficients = [0; 32];
for coef in coefficients[..order as usize].iter_mut().rev() {
let coef_unsig = try!(input.read_leq_u16(qlp_precision));
*coef = extend_sign_u16(coef_unsig, qlp_precision);
}
try!(decode_residual(input,
buffer.len() as u16,
&mut buffer[order as usize..]));
if order <= 12 {
predict_lpc_low_order(&coefficients[..order as usize], qlp_shift, buffer);
} else {
predict_lpc_high_order(&coefficients[..order as usize], qlp_shift, buffer);
}
Ok(())
}