Vendor dependencies for 0.3.0 release

This commit is contained in:
2025-09-27 10:29:08 -05:00
parent 0c8d39d483
commit 82ab7f317b
26803 changed files with 16134934 additions and 0 deletions

1175
vendor/lewton/src/audio.rs vendored Normal file

File diff suppressed because it is too large Load Diff

589
vendor/lewton/src/bitpacking.rs vendored Normal file
View File

@@ -0,0 +1,589 @@
// Vorbis decoder written in Rust
//
// Copyright (c) 2016 est31 <MTest31@outlook.com>
// and contributors. All rights reserved.
// Licensed under MIT license, or Apache 2 license,
// at your option. Please see the LICENSE file
// attached to this source distribution for details.
/*!
Vorbis bitpacking layer
Functionality to read content from the bitpacking layer.
Implements vorbis spec, section 2.
The most important struct of this mod is the `BitpackCursor` struct.
It can be instantiated using `BitpackCursor::new()`.
Note that this implementation doesn't fully align with the spec in the regard that it assumes a byte is an octet.
This is no problem on most architectures.
This non-alignment to the spec is due to the fact that the rust language is highly leaned towards byte == u8,
and doesn't even have a builtin single byte type.
*/
use ::huffman_tree::{VorbisHuffmanTree, PeekedDataLookupResult};
/// A Cursor on slices to read numbers and bitflags, bit aligned.
pub struct BitpackCursor <'a> {
bit_cursor :u8,
byte_cursor :usize,
inner :&'a[u8],
}
macro_rules! sign_extend {
( $num:expr, $desttype:ident, $bit_cnt_large:expr, $bit_cnt_small:expr) => { {
let n = $num;
let res :$desttype = n as $desttype;
let k :u8 = $bit_cnt_large - $bit_cnt_small;
res << k >> k
} }
}
#[test]
fn test_sign_extend() {
assert_eq!(sign_extend!(0b00, i8, 8, 2), 0);
assert_eq!(sign_extend!(0b01, i8, 8, 2), 1);
assert_eq!(sign_extend!(0b11, i8, 8, 2), -1);
assert_eq!(sign_extend!(0b111, i8, 8, 3), -1);
assert_eq!(sign_extend!(0b101, i8, 8, 3), -3);
assert_eq!(sign_extend!(0b01111110, i16, 16, 8), 126);
assert_eq!(sign_extend!(0b10000010, i16, 16, 8), -126);
}
/// Returns `num` bits of 1 (but never more than 8).
fn mask_bits(num : u8) -> u8 {
!((!0u8).wrapping_shl(num as u32)) | if num >= 8 { 0xff } else { 0 }
}
// Same as mask_bits but different in a special case: for num % 8 == 0
// Make sure that 0 <= num <= 8.
fn bmask_bits(num : u8) -> u8 {
(!0u8).wrapping_shr(8 - num as u32)
}
#[test]
fn test_mask_bits() {
assert_eq!(mask_bits(0), 0b00000000);
assert_eq!(mask_bits(1), 0b00000001);
assert_eq!(mask_bits(2), 0b00000011);
assert_eq!(mask_bits(3), 0b00000111);
assert_eq!(mask_bits(4), 0b00001111);
assert_eq!(mask_bits(5), 0b00011111);
assert_eq!(mask_bits(6), 0b00111111);
assert_eq!(mask_bits(7), 0b01111111);
assert_eq!(mask_bits(8), 0b11111111);
}
#[test]
fn test_bmask_bits() {
assert_eq!(bmask_bits(0), 0b11111111);
assert_eq!(bmask_bits(1), 0b00000001);
assert_eq!(bmask_bits(2), 0b00000011);
assert_eq!(bmask_bits(3), 0b00000111);
assert_eq!(bmask_bits(4), 0b00001111);
assert_eq!(bmask_bits(5), 0b00011111);
assert_eq!(bmask_bits(6), 0b00111111);
assert_eq!(bmask_bits(7), 0b01111111);
assert_eq!(bmask_bits(8), 0b11111111);
}
// The main macro to read bit aligned
// Note that `$octetnum` is the number of octets in $bitnum ($bitnum / 8 rounded down)
macro_rules! bpc_read_body {
( $rettype:ident, $bitnum:expr, $octetnum:expr, $selfarg:expr ) => { {
let last_octet_partial :usize = ($bitnum as i8 - $octetnum as i8 * 8 > 0) as usize;
let octetnum_rounded_up :usize = last_octet_partial + $octetnum;
let bit_cursor_after = ($selfarg.bit_cursor + $bitnum) % 8;
if ($selfarg.bit_cursor + $bitnum) as usize > 8 * octetnum_rounded_up {
/*println!("Reading {} bits (octetnum={}, last_partial={}, total_touched={}+1)",
$bitnum, $octetnum, last_octet_partial, $octetnum + last_octet_partial);
println!(" byte_c={}; bit_c={}", $selfarg.byte_cursor, $selfarg.bit_cursor);// */
/*print!("Reading {} bits (byte_c={}; bit_c={}) [] = {:?}", $bitnum,
$selfarg.byte_cursor, $selfarg.bit_cursor,
&$selfarg.inner[$selfarg.byte_cursor .. $selfarg.byte_cursor +
1 + octetnum_rounded_up]);// */
if $selfarg.byte_cursor + 1 + octetnum_rounded_up > $selfarg.inner.len() {
//println!(" => Out of bounds :\\");
return Err(());
}
let buf = &$selfarg.inner[$selfarg.byte_cursor
.. $selfarg.byte_cursor + 1 + octetnum_rounded_up];
let mut res :$rettype = buf[0] as $rettype;
res >>= $selfarg.bit_cursor;
let mut cur_bit_cursor = 8 - $selfarg.bit_cursor;
for i in 1 .. octetnum_rounded_up {
res |= (buf[i] as $rettype) << cur_bit_cursor;
cur_bit_cursor += 8;
}
let last_bits = buf[octetnum_rounded_up] & mask_bits(bit_cursor_after);
res |= (last_bits as $rettype) << cur_bit_cursor;
$selfarg.byte_cursor += octetnum_rounded_up;
$selfarg.bit_cursor = bit_cursor_after;
//println!(" => {:?}", res);
Ok(res)
} else {
/*println!("Reading {} bits (octetnum={}, last_partial={}, total_touched={})",
$bitnum, $octetnum, last_octet_partial, $octetnum + last_octet_partial);
println!(" byte_c={}; bit_c={}", $selfarg.byte_cursor, $selfarg.bit_cursor);// */
/*print!("Reading {} bits (byte_c={}; bit_c={}) [] = {:?}", $bitnum,
$selfarg.byte_cursor, $selfarg.bit_cursor,
&$selfarg.inner[$selfarg.byte_cursor .. $selfarg.byte_cursor +
octetnum_rounded_up]);// */
if $selfarg.byte_cursor + octetnum_rounded_up > $selfarg.inner.len() {
//println!(" => Out of bounds :\\");
return Err(());
}
let buf = &$selfarg.inner[$selfarg.byte_cursor ..
$selfarg.byte_cursor + octetnum_rounded_up];
let mut res :$rettype = buf[0] as $rettype;
res >>= $selfarg.bit_cursor;
if $bitnum <= 8 {
res &= mask_bits($bitnum) as $rettype;
}
let mut cur_bit_cursor = 8 - $selfarg.bit_cursor;
for i in 1 .. octetnum_rounded_up - 1 {
res |= (buf[i] as $rettype) << cur_bit_cursor;
cur_bit_cursor += 8;
}
if $bitnum > 8 {
let last_bits = buf[octetnum_rounded_up - 1] & bmask_bits(bit_cursor_after);
res |= (last_bits as $rettype) << cur_bit_cursor;
}
$selfarg.byte_cursor += $octetnum;
$selfarg.byte_cursor += ($selfarg.bit_cursor == 8 - ($bitnum % 8)) as usize;
$selfarg.bit_cursor = bit_cursor_after;
//println!(" => {:?}", res);
Ok(res)
}
} }
}
// The main macro to peek bit aligned
// Note that `$octetnum` is the number of octets in $bitnum ($bitnum / 8 rounded down)
macro_rules! bpc_peek_body {
( $rettype:ident, $bitnum:expr, $octetnum:expr, $selfarg:expr ) => { {
let last_octet_partial :usize = ($bitnum as i8 - $octetnum as i8 * 8 > 0) as usize;
let octetnum_rounded_up :usize = last_octet_partial + $octetnum;
let bit_cursor_after = ($selfarg.bit_cursor + $bitnum) % 8;
if ($selfarg.bit_cursor + $bitnum) as usize > 8 * octetnum_rounded_up {
/*println!("Reading {} bits (octetnum={}, last_partial={}, total_touched={}+1)",
$bitnum, $octetnum, last_octet_partial, $octetnum + last_octet_partial);
println!(" byte_c={}; bit_c={}", $selfarg.byte_cursor, $selfarg.bit_cursor);// */
/*print!("Reading {} bits (byte_c={}; bit_c={}) [] = {:?}", $bitnum,
$selfarg.byte_cursor, $selfarg.bit_cursor,
&$selfarg.inner[$selfarg.byte_cursor .. $selfarg.byte_cursor +
1 + octetnum_rounded_up]);// */
if $selfarg.byte_cursor + 1 + octetnum_rounded_up > $selfarg.inner.len() {
//println!(" => Out of bounds :\\");
return Err(());
}
let buf = &$selfarg.inner[$selfarg.byte_cursor
.. $selfarg.byte_cursor + 1 + octetnum_rounded_up];
let mut res :$rettype = buf[0] as $rettype;
res >>= $selfarg.bit_cursor;
let mut cur_bit_cursor = 8 - $selfarg.bit_cursor;
for i in 1 .. octetnum_rounded_up {
res |= (buf[i] as $rettype) << cur_bit_cursor;
cur_bit_cursor += 8;
}
let last_bits = buf[octetnum_rounded_up] & mask_bits(bit_cursor_after);
res |= (last_bits as $rettype) << cur_bit_cursor;
//println!(" => {:?}", res);
Ok(res)
} else {
/*println!("Reading {} bits (octetnum={}, last_partial={}, total_touched={})",
$bitnum, $octetnum, last_octet_partial, $octetnum + last_octet_partial);
println!(" byte_c={}; bit_c={}", $selfarg.byte_cursor, $selfarg.bit_cursor);// */
/*print!("Reading {} bits (byte_c={}; bit_c={}) [] = {:?}", $bitnum,
$selfarg.byte_cursor, $selfarg.bit_cursor,
&$selfarg.inner[$selfarg.byte_cursor .. $selfarg.byte_cursor +
octetnum_rounded_up]);// */
if $selfarg.byte_cursor + octetnum_rounded_up > $selfarg.inner.len() {
//println!(" => Out of bounds :\\");
return Err(());
}
let buf = &$selfarg.inner[$selfarg.byte_cursor ..
$selfarg.byte_cursor + octetnum_rounded_up];
let mut res :$rettype = buf[0] as $rettype;
res >>= $selfarg.bit_cursor;
if $bitnum <= 8 {
res &= mask_bits($bitnum) as $rettype;
}
let mut cur_bit_cursor = 8 - $selfarg.bit_cursor;
for i in 1 .. octetnum_rounded_up - 1 {
res |= (buf[i] as $rettype) << cur_bit_cursor;
cur_bit_cursor += 8;
}
if $bitnum > 8 {
let last_bits = buf[octetnum_rounded_up - 1] & bmask_bits(bit_cursor_after);
res |= (last_bits as $rettype) << cur_bit_cursor;
}
//println!(" => {:?}", res);
Ok(res)
}
} }
}
// The main macro to advance bit aligned
// Note that `$octetnum` is the number of octets in $bitnum ($bitnum / 8 rounded down)
macro_rules! bpc_advance_body {
( $bitnum:expr, $octetnum:expr, $selfarg:expr ) => { {
let last_octet_partial :usize = ($bitnum as i8 - $octetnum as i8 * 8 > 0) as usize;
let octetnum_rounded_up :usize = last_octet_partial + $octetnum;
let bit_cursor_after = ($selfarg.bit_cursor + $bitnum) % 8;
if ($selfarg.bit_cursor + $bitnum) as usize > 8 * octetnum_rounded_up {
$selfarg.byte_cursor += octetnum_rounded_up;
$selfarg.bit_cursor = bit_cursor_after;
//println!(" => {:?}", res);
Ok(())
} else {
$selfarg.byte_cursor += $octetnum;
$selfarg.byte_cursor += ($selfarg.bit_cursor == 8 - ($bitnum % 8)) as usize;
$selfarg.bit_cursor = bit_cursor_after;
//println!(" => {:?}", res);
Ok(())
}
} }
}
macro_rules! uk_reader {
( $fnname:ident, $rettype:ident, $bitnum:expr, $octetnum:expr) => {
#[inline]
pub fn $fnname(&mut self) -> Result<$rettype, ()> {
bpc_read_body!($rettype, $bitnum, $octetnum, self)
}
}
}
macro_rules! ik_reader {
( $fnname:ident, $rettype:ident, $bitnum_of_rettype:expr, $bitnum:expr, $octetnum:expr) => {
#[inline]
pub fn $fnname(&mut self) -> Result<$rettype, ()> {
Ok(sign_extend!(try!(
bpc_read_body!($rettype, $bitnum, $octetnum, self)),
$rettype, $bitnum_of_rettype, $bitnum))
}
}
}
macro_rules! ik_dynamic_reader {
( $fnname:ident, $rettype:ident, $bitnum_of_rettype:expr) => {
#[inline]
pub fn $fnname(&mut self, bit_num :u8) -> Result<$rettype, ()> {
let octet_num :usize = (bit_num / 8) as usize;
assert!(bit_num <= $bitnum_of_rettype);
Ok(sign_extend!(try!(
bpc_read_body!($rettype, bit_num, octet_num, self)),
$rettype, $bitnum_of_rettype, bit_num))
}
}
}
macro_rules! uk_dynamic_reader {
( $fnname:ident, $rettype:ident, $bit_num_max:expr) => {
#[inline]
pub fn $fnname(&mut self, bit_num :u8) -> Result<$rettype, ()> {
let octet_num :usize = (bit_num / 8) as usize;
if bit_num == 0 {
// TODO: one day let bpc_read_body handle this,
// if its smartly doable in there.
// For why it is required, see comment in the
// test_bitpacking_reader_empty function.
return Ok(0);
}
assert!(bit_num <= $bit_num_max);
bpc_read_body!($rettype, bit_num, octet_num, self)
}
}
}
fn float32_unpack(val :u32) -> f32 {
let sgn = val & 0x80000000;
let exp = (val & 0x7fe00000) >> 21;
let mantissa = (val & 0x1fffff) as f64;
let signed_mantissa = if sgn != 0 {
-mantissa
} else {
mantissa
};
return signed_mantissa as f32 * (exp as f32 - 788.0).exp2();
}
#[test]
fn test_float_32_unpack() {
// Values were printed out from what stb_vorbis
// calculated for this function from a test file.
assert_eq!(float32_unpack(1611661312), 1.000000);
assert_eq!(float32_unpack(1616117760), 5.000000);
assert_eq!(float32_unpack(1618345984), 11.000000);
assert_eq!(float32_unpack(1620115456), 17.000000);
assert_eq!(float32_unpack(1627381760), 255.000000);
assert_eq!(float32_unpack(3759144960), -1.000000);
assert_eq!(float32_unpack(3761242112), -2.000000);
assert_eq!(float32_unpack(3763339264), -4.000000);
assert_eq!(float32_unpack(3763601408), -5.000000);
assert_eq!(float32_unpack(3765436416), -8.000000);
assert_eq!(float32_unpack(3765829632), -11.000000);
assert_eq!(float32_unpack(3768451072), -30.000000);
assert_eq!(float32_unpack(3772628992), -119.000000);
assert_eq!(float32_unpack(3780634624), -1530.000000);
}
#[test]
fn test_float_32_unpack_issue_24() {
// Regression test for issue #24, a
// mismatch in decoded output for audio_simple_with_error.ogg
// and singlemap-test.ogg.
// The values are taken from the codebook_delta_value and
// codebook_minimum_value values of the singlemap-test.ogg file.
// The expected values come from stb_vorbis.
assert_eq!(float32_unpack(1628434432), 255.0);
assert_eq!(float32_unpack(1621655552), 17.0);
assert_eq!(float32_unpack(1619722240), 11.0);
assert_eq!(float32_unpack(1613234176), 1.0);
assert_eq!(float32_unpack(3760717824), -1.0);
assert_eq!(float32_unpack(3762814976), -2.0);
assert_eq!(float32_unpack(3764912128), -4.0);
assert_eq!(float32_unpack(3765043200), -5.0);
assert_eq!(float32_unpack(3767009280), -8.0);
assert_eq!(float32_unpack(3767205888), -11.0);
assert_eq!(float32_unpack(3769565184), -30.0);
assert_eq!(float32_unpack(3773751296), -119.0);
assert_eq!(float32_unpack(3781948416), -1530.0);
}
// allow some code that is only used in the tests
#[allow(dead_code)]
impl <'a> BitpackCursor <'a> {
/// Creates a new `BitpackCursor` for the given data array
pub fn new(arr : &'a[u8]) -> BitpackCursor {
return BitpackCursor::<'a> { bit_cursor: 0, byte_cursor: 0, inner: arr };
}
// Unsigned, non-dynamic reader methods
// u32 based
// TODO add here if needed
uk_reader!(read_u32, u32, 32, 4);
// TODO add here if needed
uk_reader!(read_u24, u32, 24, 3);
// TODO add here if needed
// u16 based
uk_reader!(read_u16, u16, 16, 2);
// TODO add here if needed
uk_reader!(read_u13, u16, 13, 1);
// TODO add here if needed
// u8 based
uk_reader!(read_u8, u8, 8, 1);
uk_reader!(read_u7, u8, 7, 0);
uk_reader!(read_u6, u8, 6, 0);
uk_reader!(read_u5, u8, 5, 0);
uk_reader!(read_u4, u8, 4, 0);
uk_reader!(read_u3, u8, 3, 0);
uk_reader!(read_u2, u8, 2, 0);
uk_reader!(read_u1, u8, 1, 0);
// Returning bool:
#[inline]
pub fn read_bit_flag(&mut self) -> Result<bool, ()> {
return Ok(try!(self.read_u1()) == 1);
}
// Unsigned dynamic reader methods
// They panic if you give them invalid params
// (bit_num larger than maximum allowed bit number for the type)
uk_dynamic_reader!(read_dyn_u8, u8, 8);
uk_dynamic_reader!(read_dyn_u16, u16, 16);
uk_dynamic_reader!(read_dyn_u32, u32, 32);
uk_dynamic_reader!(read_dyn_u64, u64, 64);
// Signed non-dynamic reader methods
ik_reader!(read_i32, i32, 32, 32, 4);
// TODO add here if needed
ik_reader!(read_i8, i8, 8, 8, 1);
ik_reader!(read_i7, i8, 8, 7, 0);
// TODO add here if needed
// Signed dynamic reader methods
// They panic if you give them invalid params
// (bit_num larger than maximum allowed bit number for the type)
ik_dynamic_reader!(read_dyn_i8, i8, 8);
ik_dynamic_reader!(read_dyn_i16, i16, 16);
ik_dynamic_reader!(read_dyn_i32, i32, 32);
// Float reading methods
/// Reads a single floating point number in the vorbis-float32 format
pub fn read_f32(&mut self) -> Result<f32, ()> {
let val = try!(self.read_u32());
Ok(float32_unpack(val))
}
/// Peeks 8 bits of non read yet content without advancing the reader
#[inline]
pub fn peek_u8(&self) -> Result<u8, ()> {
bpc_peek_body!(u8, 8, 1, self)
}
// Advances the reader by the given number of bits (up to 8).
pub fn advance_dyn_u8(&mut self, bit_num :u8) -> Result<(), ()> {
let octet_num :usize = (bit_num / 8) as usize;
if bit_num == 0 {
// TODO: one day let bpc_advance_body handle this,
// if its smartly doable in there.
// For why it is required, see comment in the
// test_bitpacking_reader_empty function.
return Ok(());
}
assert!(bit_num <= 8);
bpc_advance_body!(bit_num, octet_num, self)
}
/// Reads a huffman word using the codebook abstraction
pub fn read_huffman(&mut self, tree :&VorbisHuffmanTree) -> Result<u32, ()> {
//let mut c :usize = 0;
//let mut w :usize = 0;
let mut iter = match self.peek_u8() {
Ok(data) => match tree.lookup_peeked_data(8, data as u32) {
PeekedDataLookupResult::Iter(advance, iter) => {
try!(self.advance_dyn_u8(advance));
iter
},
PeekedDataLookupResult::PayloadFound(advance, payload) => {
try!(self.advance_dyn_u8(advance));
return Ok(payload);
},
},
Err(_) => tree.iter(),
};
loop {
let b = try!(self.read_bit_flag());
/*
c +=1;
w >>= 1;
w |= (b as usize) << 63;
// Put this into the Some arm of the match below in order to debug:
{print!("({}:{}:{}) ", w >> (64 - c), v, c); }
// */
match iter.next(b) {
Some(v) => return Ok(v),
None => (),
}
}
}
}
#[test]
fn test_bitpacking_reader_static() {
// Test vectors taken from Vorbis I spec, section 2.1.6
let test_arr = &[0b11111100, 0b01001000, 0b11001110, 0b00000110];
let mut cur = BitpackCursor::new(test_arr);
assert_eq!(cur.read_u4().unwrap(), 12);
assert_eq!(cur.read_u3().unwrap(), 7);
assert_eq!(cur.read_u7().unwrap(), 17);
assert_eq!(cur.read_u13().unwrap(), 6969);
}
#[test]
fn test_bitpacking_reader_dynamic() {
// Test vectors taken from Vorbis I spec, section 2.1.6
let test_arr = &[0b11111100, 0b01001000, 0b11001110, 0b00000110];
let mut cur = BitpackCursor::new(test_arr);
assert_eq!(cur.read_dyn_u8(4).unwrap(), 12);
assert_eq!(cur.read_dyn_u8(3).unwrap(), 7);
assert_eq!(cur.read_dyn_u16(7).unwrap(), 17);
assert_eq!(cur.read_dyn_u16(13).unwrap(), 6969);
// Regression test for bug
let test_arr = &[93, 92];
let mut cur = BitpackCursor::new(test_arr);
assert_eq!(cur.read_dyn_u32(10).unwrap(), 93);
}
#[test]
fn test_bitpacking_reader_empty() {
// Same as the normal bitpacking test
// but with some additional empty reads.
//
// This is expected to happen by the vorbis spec.
// For example, the mode_number read in the audio packet
// decode at first position may be 0 bit long (if there
// is only one mode, ilog([vorbis_mode_count] - 1) is zero).
let test_arr = &[0b11111100, 0b01001000, 0b11001110, 0b00000110];
let mut cur = BitpackCursor::new(test_arr);
assert_eq!(cur.read_dyn_u8(4).unwrap(), 12);
assert_eq!(cur.read_dyn_u8(0).unwrap(), 0);
assert_eq!(cur.read_dyn_u8(0).unwrap(), 0);
assert_eq!(cur.read_dyn_u8(3).unwrap(), 7);
assert_eq!(cur.read_dyn_u8(0).unwrap(), 0);
assert_eq!(cur.read_dyn_u16(7).unwrap(), 17);
assert_eq!(cur.read_dyn_u16(0).unwrap(), 0);
assert_eq!(cur.read_dyn_u16(0).unwrap(), 0);
assert_eq!(cur.read_dyn_u16(13).unwrap(), 6969);
assert_eq!(cur.read_dyn_u16(0).unwrap(), 0);
}
#[test]
fn test_bitpacking_reader_byte_aligned() {
// Check that bitpacking readers work with "normal" byte aligned types:
let test_arr = &[0x00, 0x00, 0x00, 0x00, 0x01];
let mut cur = BitpackCursor::new(test_arr);
assert_eq!(cur.read_dyn_u32(32).unwrap(), 0);
assert_eq!(cur.read_dyn_u8(8).unwrap(), 1);
// We not just check here whether it works for byte aligned
// "normal" (non-dynamic) reader methods, we also check
// whether, after reading first one, then seven bits,
// it "gets back" to byte alignment (and increases the byte ctr)
let test_arr = &[0x09, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01];
let mut cur = BitpackCursor::new(test_arr);
assert_eq!(cur.read_u1().unwrap(), 1);
assert_eq!(cur.read_u7().unwrap(), 4);
assert_eq!(cur.read_i8().unwrap(), 2);
assert_eq!(cur.read_u32().unwrap(), 0);
assert_eq!(cur.read_u8().unwrap(), 1);
}
#[test]
fn test_capture_pattern_nonaligned() {
// Regression test from test OGG file
// Tests for proper codebook capture
// pattern reading.
//
// The OGG vorbis capture pattern
// is a three octet (24 bits) value.
//
// The first block tests capture pattern
// reading in a byte aligned scenario.
// The actually problematic part was
// the second block: it tests capture
// pattern reading in a non-aligned
// situation.
let capture_pattern_arr = &[0x42, 0x43, 0x56];
let mut cur = BitpackCursor::new(capture_pattern_arr);
assert_eq!(cur.read_u24().unwrap(), 0x564342);
let test_arr = &[0x28, 0x81, 0xd0, 0x90, 0x55, 0x00, 0x00];
let mut cur = BitpackCursor::new(test_arr);
cur.read_u5().unwrap(); // some value we are not interested in
cur.read_u5().unwrap(); // some value we are not interested in
assert_eq!(cur.read_u4().unwrap(), 0);
assert_eq!(cur.read_u24().unwrap(), 0x564342);
// Ensure that we incremented by only three bytes, not four
assert_eq!(cur.read_u16().unwrap(), 1);
}

147
vendor/lewton/src/capi.rs vendored Normal file
View File

@@ -0,0 +1,147 @@
use std::os::raw::c_int;
use std::slice::from_raw_parts;
use std::ptr::null_mut;
use ::header::{read_header_setup, //read_header_comment,
read_header_ident, IdentHeader, //CommentHeader,
SetupHeader};
use ::audio::{PreviousWindowRight, read_audio_packet_generic};
/// Main Decoder State
///
/// It is created by `lewton_context_from_extradata` by passing a xiph-laced extradate bundle
pub struct LewtonContext {
pwr :PreviousWindowRight,
ident_hdr :IdentHeader,
//comment_hdr :CommentHeader,
setup_hdr :SetupHeader,
}
fn read_xiph_lacing(arr :&mut &[u8]) -> Option<u64> {
let mut r = 0;
loop {
if arr.len() == 0 {
return None;
}
let v = arr[0] as u64;
*arr = &arr[1..];
r += v;
if v < 255 {
return Some(r);
}
}
}
impl LewtonContext {
fn from_extradata(mut extradata :&[u8]) -> Option<Self> {
// We must start with a 2 as per matroska encapsulation spec
if extradata.len() == 0 || extradata[0] != 2 {
return None
}
extradata = &extradata[1..];
let ident_len = read_xiph_lacing(&mut extradata)? as usize;
let comment_len = read_xiph_lacing(&mut extradata)? as usize;
let ident_hdr = read_header_ident(&extradata[0..ident_len]).ok()?;
extradata = &extradata[ident_len..];
//let comment_hdr = read_header_comment(&extradata[0..comment_len]).ok()?;
extradata = &extradata[comment_len..];
let setup_hdr = read_header_setup(extradata, ident_hdr.audio_channels,
(ident_hdr.blocksize_0, ident_hdr.blocksize_1))
.ok()?;
Some(LewtonContext {
pwr : PreviousWindowRight::new(),
ident_hdr,
//comment_hdr,
setup_hdr,
})
}
}
/// A multichannel vector of samples
///
/// It is produced by `lewton_decode_packet`
///
/// Use `lewton_samples_count` to retrieve the number of samples available in each channel
/// Use `lewton_samples_channels` to retrieve the number of channels
/// Use `lewton_samples_for_channel_f32` to retrieve a reference to the data present in the
/// channel
///
/// use `lewton_samples_drop()` to deallocate the memory
pub struct LewtonSamples(Vec<Vec<f32>>);
/// Create a LewtonContext from an extradata buffer
///
/// Returns either NULL or a newly allocated LewtonContext
#[no_mangle]
pub unsafe extern fn lewton_context_from_extradata(
data :*const u8, len :usize) -> *mut LewtonContext {
if data.is_null() {
return null_mut();
}
let extradata = from_raw_parts(data, len);
if let Some(cx) = LewtonContext::from_extradata(extradata) {
let boxed = Box::new(cx);
Box::into_raw(boxed)
} else {
null_mut()
}
}
/// Reset the Decoder to support seeking.
#[no_mangle]
pub unsafe extern fn lewton_context_reset(ctx :*mut LewtonContext) {
(*ctx).pwr = PreviousWindowRight::new();
}
/// Decode a packet to LewtonSamples when possible
///
/// Returns 0 on success, non-zero if no samples can be produced
#[no_mangle]
pub unsafe extern fn lewton_decode_packet(ctx :*mut LewtonContext,
pkt :*const u8, len: usize,
sample_out :*mut *mut LewtonSamples) -> c_int {
if pkt.is_null() || ctx.is_null() || sample_out.is_null() {
return 1;
}
let pkt = from_raw_parts(pkt, len);
let decoded = read_audio_packet_generic(&(*ctx).ident_hdr,
&(*ctx).setup_hdr, &pkt, &mut (*ctx).pwr);
let decoded = if let Ok(v) = decoded {
v
} else {
return 2;
};
let boxed = Box::new(LewtonSamples(decoded));
*sample_out = Box::into_raw(boxed);
return 0;
}
/// Provide the number of samples present in each channel
#[no_mangle]
pub unsafe extern fn lewton_samples_count(samples :*const LewtonSamples) -> usize {
(*samples).0
.get(0)
.map(|v| v.len())
.unwrap_or(0)
}
/// Provide a reference to the channel sample data
pub unsafe extern fn lewton_samples_f32(samples :*const LewtonSamples, channel :usize) -> *const f32 {
(*samples).0
.get(channel)
.map(|v| v.as_ptr())
.unwrap_or(std::ptr::null())
}
#[no_mangle]
pub unsafe extern fn lewton_samples_drop(samples :*mut LewtonSamples) {
std::mem::drop(Box::from_raw(samples));
}
#[no_mangle]
pub unsafe extern fn lewton_context_drop(ctx :*mut LewtonContext) {
std::mem::drop(Box::from_raw(ctx));
}

1152
vendor/lewton/src/header.rs vendored Normal file

File diff suppressed because it is too large Load Diff

156
vendor/lewton/src/header_cached.rs vendored Normal file
View File

@@ -0,0 +1,156 @@
// Vorbis decoder written in Rust
//
// Copyright (c) 2016 est31 <MTest31@outlook.com>
// and contributors. All rights reserved.
// Licensed under MIT license, or Apache 2 license,
// at your option. Please see the LICENSE file
// attached to this source distribution for details.
/*!
Cached header info
This mod contains logic to generate and deal with
data derived from header information
that's used later in the decode process.
The caching is done to speed up decoding.
*/
pub struct TwiddleFactors {
pub a :Vec<f32>,
pub b :Vec<f32>,
pub c :Vec<f32>,
}
pub struct CachedBlocksizeDerived {
pub twiddle_factors : TwiddleFactors,
pub window_slope : Vec<f32>,
pub bitrev : Vec<u32>,
}
impl CachedBlocksizeDerived {
pub fn from_blocksize(bs :u8) -> Self {
CachedBlocksizeDerived {
window_slope : generate_window((1 << (bs as u16)) >> 1),
twiddle_factors : compute_twiddle_factors(bs),
bitrev : compute_bitreverse(bs),
}
}
}
fn win_slope(x :u16, n :u16) -> f32 {
// please note that there might be a MISTAKE
// in how the spec specifies the right window slope
// function. See "4.3.1. packet type, mode and window decode"
// step 7 where it adds an "extra" pi/2.
// The left slope doesn't have it, only the right one.
// as stb_vorbis shares the window slope generation function,
// The *other* possible reason is that we don't need the right
// window for anything. TODO investigate this more.
let v = (0.5 * std::f32::consts::PI * (x as f32 + 0.5) / n as f32).sin();
return (0.5 * std::f32::consts::PI * v * v ).sin();
}
fn generate_window(n :u16) -> Vec<f32> {
let mut window = Vec::with_capacity(n as usize);
for i in 0 .. n {
window.push(win_slope(i, n));
}
return window;
}
fn compute_twiddle_factors(blocksize :u8) -> TwiddleFactors {
let n = 1 << (blocksize as u16);
let n2 = n >> 1;
let n4 = n >> 2;
let n8 = n >> 3;
let mut a = Vec::with_capacity(n2);
let mut b = Vec::with_capacity(n2);
let mut c = Vec::with_capacity(n4);
let mut k2 = 0;
let pi_4_n = 4.0 * std::f32::consts::PI / (n as f32);
let pi_05_n = 0.5 * std::f32::consts::PI / (n as f32);
let pi_2_n = 2.0 * std::f32::consts::PI / (n as f32);
for k in 0..n4 {
a.push( f32::cos((k as f32) * pi_4_n));
a.push(-f32::sin((k as f32) * pi_4_n));
b.push( f32::cos(((k2+1) as f32) * pi_05_n) * 0.5);
b.push( f32::sin(((k2+1) as f32) * pi_05_n) * 0.5);
k2 += 2;
}
k2 = 0;
for _ in 0..n8 {
c.push( f32::cos(((k2 + 1) as f32) * pi_2_n));
c.push(-f32::sin(((k2 + 1) as f32) * pi_2_n));
k2 += 2;
}
return TwiddleFactors {
a,
b,
c,
};
}
fn compute_bitreverse(blocksize :u8) -> Vec<u32> {
let ld = blocksize as u16;
let n = 1 << blocksize;
let n8 = n >> 3;
let mut rev = Vec::with_capacity(n8);
for i in 0 .. n8 {
rev.push((::bit_reverse(i as u32) as u32 >> (32 - ld + 3)) << 2);
}
return rev;
}
#[test]
fn test_compute_bitreverse() {
let br = compute_bitreverse(8);
// The output was generated from the output of the
// original stb_vorbis function.
let cmp_arr = &[
0, 64, 32, 96,
16, 80, 48, 112,
8, 72, 40, 104,
24, 88, 56, 120,
4, 68, 36, 100,
20, 84, 52, 116,
12, 76, 44, 108,
28, 92, 60, 124];
assert_eq!(br, cmp_arr);
}
#[inline]
fn bark(x :f32) -> f32 {
13.1 * (0.00074 * x).atan() + 2.24 * (0.0000000185*x*x).atan() + 0.0001 * x
}
/// Precomputes bark map values used by floor type 0 packets
///
/// Precomputes the cos(omega) values for use by floor type 0 computation.
///
/// Note that there is one small difference to the spec: the output
/// vec is n elements long, not n+1. The last element (at index n)
/// is -1 in the spec, we lack it. Users of the result of this function
/// implementation should use it "virtually".
pub fn compute_bark_map_cos_omega(n :u16, floor0_rate :u16,
floor0_bark_map_size :u16) -> Vec<f32> {
let mut res = Vec::with_capacity(n as usize);
let hfl = floor0_rate as f32 / 2.0;
let hfl_dn = hfl / n as f32;
let foobar_const_part = floor0_bark_map_size as f32 / bark(hfl);
// Bark map size minus 1:
let bms_m1 = floor0_bark_map_size as f32 - 1.0;
let omega_factor = std::f32::consts::PI / floor0_bark_map_size as f32;
for i in 0 .. n {
let foobar = (bark(i as f32 * hfl_dn) * foobar_const_part).floor();
let map_elem = foobar.min(bms_m1);
let cos_omega = (map_elem * omega_factor).cos();
res.push(cos_omega);
}
return res;
}

485
vendor/lewton/src/huffman_tree.rs vendored Normal file
View File

@@ -0,0 +1,485 @@
// Vorbis decoder written in Rust
//
// Copyright (c) 2016 est31 <MTest31@outlook.com>
// and contributors. All rights reserved.
// Licensed under MIT license, or Apache 2 license,
// at your option. Please see the LICENSE file
// attached to this source distribution for details.
/*!
Huffman tree unpacking and traversal
This mod contains the `VorbisHuffmanTree` struct which
can be loaded from the `codebook_codeword_lengths` array
specified for each codebook in the vorbis setup header.
Once decoding is happening, you are more interested in
the `VorbisHuffmanIter` struct which provides you with
facilities to load a value bit by bit.
*/
struct HuffTree {
// True iff every sub-tree in this tree
// either has two direct children or none
even_childs :bool,
payload :Option<u32>,
l :Option<Box<HuffTree>>,
r :Option<Box<HuffTree>>,
}
/*
use std::fmt;
impl fmt::Debug for HuffTree {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fn fmt_rec(s :&HuffTree, f: &mut fmt::Formatter, depth :u32) -> fmt::Result {
macro_rules! depth_print {
($f:ident, $depth:ident) => {
for _ in 0..$depth {
try!(write!($f, "| "));
}
}}
if s.l.is_some() || s.r.is_some() {
try!(writeln!(f, "ec: {:?}, pl: {:?}, LIS {:?} RIS {:?}",
s.even_childs, s.payload, s.l.is_some(), s.r.is_some()));
} else {
try!(writeln!(f, "ec: {:?}, pl: {:?}", s.even_childs, s.payload));
}
if let Some(ref v) = s.l {
depth_print!(f, depth);
try!(write!(f, "LEFT "));
try!(fmt_rec(&*v, f, depth + 1));
}
if let Some(ref v) = s.r {
depth_print!(f, depth);
try!(write!(f, "RIGT "));
try!(fmt_rec(&*v, f, depth + 1));
}
return Ok(());
}
try!(fmt_rec(self, f, 1));
return Ok(());
}
} // */
impl HuffTree {
/// Returns whether the addition was successful
pub fn insert_rec(&mut self, payload :u32, depth :u8) -> bool {
//print!("INSERT payload {:?} depth {:?} ", payload, depth);
if self.payload.is_some() {
//println!(" => OCCUPIED AS LEAF");
return false;
}
if depth == 0 {
if !(self.l.is_none() && self.r.is_none()) {
//println!(" => INNER NODE");
return false;
}
self.payload = Some(payload);
//println!(" => ADDED");
return true;
}
if self.even_childs {
//println!(" => HAS EVEN CHILDS");
match &mut self.l {
&mut Some(_) => return false,
&mut None => {
let mut new_node = HuffTree { even_childs :true, payload :None, l :None, r :None };
new_node.insert_rec(payload, depth - 1);
self.l = Some(Box::new(new_node));
self.even_childs = false;
return true;
}
}
} else {
//println!(" => HAS NOT EVEN CHILDS");
// First try left branch
let left = self.l.as_mut().unwrap();
if !left.even_childs {
if left.insert_rec(payload, depth - 1) {
self.even_childs = left.even_childs &&
if let &mut Some(ref mut right) = &mut self.r.as_mut() { right.even_childs } else { false };
return true;
}
}
// Left sub tree was either full or leaf
// Therefore, put it in the right branch now
// As left has even_childs == true, right causes
// us to have even_childs == false.
return match self.r {
Some(ref mut right) => {
let success = right.insert_rec(payload, depth - 1);
self.even_childs = left.even_childs && right.even_childs;
success
},
None => {
let mut new_node = HuffTree { even_childs :true, payload :None, l :None, r :None };
let success = new_node.insert_rec(payload, depth - 1);
self.even_childs = left.even_childs && new_node.even_childs;
self.r = Some(Box::new(new_node));
success
}
};
}
}
}
#[derive(Debug)]
pub enum HuffmanError {
Overspecified,
Underpopulated,
InvalidSingleEntry,
}
#[derive(Clone, Copy)]
enum UnrolledLookupEntry {
/// The specified entry was found in the lookup array
///
/// First param: offset by which to advance the reader
/// Second param: the payload
HasEntry(u8, u32),
/// Seems the given input is inconclusive and not complete yet.
///
/// The argument contains a hint that is an offset inside desc_prog
/// to help to advance the reader.
InconclusiveWithHint(u32),
/// Seems the given input is inconclusive and not complete yet.
Inconclusive,
}
pub enum PeekedDataLookupResult<'l> {
/// The supplied info is not enough to result in a payload directly.
///
/// First param is the number of bits to advance.
///
/// The returned iterator has state up to the count of bits that could be used.
Iter(u8, VorbisHuffmanIter<'l>),
/// The supplied info is enough to map to a payload
///
/// First param is the number of bits to advance. Second is payload.
PayloadFound(u8, u32),
}
/// Huffman tree representation
pub struct VorbisHuffmanTree {
// Format: three bytes per non leaf node, one byte per leaf node.
// First byte is the payload container,
// second and third point to the indices inside the vector that
// have left and right children.
// If the node is a leaf the highest bit of the payload container 0,
// if it has children the bit is 1. If its a leaf the lower 31 bits of the
// payload container form the actual payload.
desc_prog :Vec<u32>,
unrolled_entries :[UnrolledLookupEntry; 256],
}
impl VorbisHuffmanTree {
/// Constructs a new `VorbisHuffmanTree` instance from the passed array,
/// like the vorbis spec demands.
///
/// Returns the resulting tree if the array results in a valid (neither
/// underspecified nor overspecified) tree.
pub fn load_from_array(codebook_codeword_lengths :&[u8]) -> Result<VorbisHuffmanTree, HuffmanError> {
// First step: generate a simple tree representing the
// Huffman tree
let mut simple_tree = HuffTree { even_childs :true, payload :None, l :None, r :None };
let mut cnt :usize = 0;
let mut last_valid_idx = None;
for (i, &codeword_length) in codebook_codeword_lengths.iter().enumerate() {
if codeword_length == 0 {
continue;
}
cnt += 1;
last_valid_idx = Some(i);
if !simple_tree.insert_rec(i as u32, codeword_length) {
try!(Err(HuffmanError::Overspecified)) /* Overspecified, can't be put into tree */
}
}
//println!("The tree:\n{:?}", simple_tree);
// Single entry codebook special handling
if cnt == 1 {
let decoded = last_valid_idx.unwrap();
let encoded_len = codebook_codeword_lengths[decoded];
if encoded_len == 1 {
// Return a vorbis tree that returns decoded for any single bit input
return Ok(VorbisHuffmanTree {
desc_prog :vec![1u32 << 31, 3, 3, decoded as u32],
unrolled_entries :[
UnrolledLookupEntry::HasEntry(1, decoded as u32); 256
],
});
} else {
// Single entry codebooks must have 1 as their only length entry
try!(Err(HuffmanError::InvalidSingleEntry))
}
}
if !simple_tree.even_childs {
try!(Err(HuffmanError::Underpopulated)); /* Underpopulated */
}
// Second step: generate the actual desc_prog
// by pre_order traversal of the tree.
//
// The general advantage of this approach over one with only the simple tree
// is better cache locality and less memory requirements (at least after the
// setup with the simple tree).
let mut desc_prog = Vec::with_capacity(cnt);
fn traverse(tree :& HuffTree, desc_prog :&mut Vec<u32>) -> u32 {
let cur_pos = desc_prog.len() as u32;
let has_children = tree.l.is_some() || tree.r.is_some();
let entry = ((has_children as u32) << 31) | tree.payload.unwrap_or(0);
//println!("push node (w_children : {:?}) at {:?} : {:?}", has_children, cur_pos, entry);
desc_prog.push(entry);
if has_children {
desc_prog.push(0);
desc_prog.push(0);
desc_prog[cur_pos as usize + 1] =
traverse(tree.l.as_ref().unwrap(), desc_prog);
/*println!("left child of node {:?}: at {:?}", cur_pos,
desc_prog[cur_pos as usize + 1]);// */
desc_prog[cur_pos as usize + 2] =
traverse(tree.r.as_ref().unwrap(), desc_prog);
/*println!("right child of node {:?}: at {:?}", cur_pos,
desc_prog[cur_pos as usize + 2]);// */
}
return cur_pos;
}
assert_eq!(traverse(&simple_tree, &mut desc_prog), 0);
// Third step: generate unrolled entries array
// Also by pre_order traversal.
//
// This gives us a speedup over desc_prog as reading the unrolled
// entries should involve less branching and less lookups overall.
let mut unrolled_entries = [UnrolledLookupEntry::Inconclusive; 256];
fn uroll_traverse(tree :& HuffTree,
unrolled_entries :&mut [UnrolledLookupEntry; 256],
prefix :u32, prefix_idx :u8,
desc_prog :&[u32], desc_prog_idx :u32) {
let has_children = tree.l.is_some() || tree.r.is_some();
if has_children {
// There are children.
// We'd like to recurse deeper. Can we?
if prefix_idx == 8 {
// No we can't.
// The tree is too deep.
unrolled_entries[prefix as usize] =
UnrolledLookupEntry::InconclusiveWithHint(desc_prog_idx);
} else {
// Recurse deeper.
uroll_traverse(tree.l.as_ref().unwrap(),
unrolled_entries,
prefix + (0 << prefix_idx), prefix_idx + 1,
desc_prog, desc_prog[desc_prog_idx as usize + 1]);
uroll_traverse(tree.r.as_ref().unwrap(),
unrolled_entries,
prefix + (1 << prefix_idx), prefix_idx + 1,
desc_prog, desc_prog[desc_prog_idx as usize + 2]);
}
} else {
// No children, fill the entries in the range according to
// the prefix we have.
let payload = tree.payload.unwrap();
let it = 1 << prefix_idx;
let mut i = prefix as usize;
for _ in 1 .. (1u16 << (8 - prefix_idx)) {
unrolled_entries[i] =
UnrolledLookupEntry::HasEntry(prefix_idx, payload);
i += it;
}
}
}
if cnt > 0 {
uroll_traverse(&simple_tree,
&mut unrolled_entries, 0, 0, &desc_prog, 0);
}
// Now we are done, return the result
return Ok(VorbisHuffmanTree {
desc_prog,
unrolled_entries,
});
}
/// Returns an iterator over this tree.
pub fn iter<'l>(&'l self) -> VorbisHuffmanIter<'l> {
return VorbisHuffmanIter { desc_prog :&self.desc_prog, pos :0 };
}
/// Resolves a given number of peeked bits.
///
/// Returns whether the data given is enough to uniquely identify a
/// tree element, or whether only an iterator that's progressed by
/// a given amount can be returned. Also, info is returned about how
/// far the reader can be advanced.
pub fn lookup_peeked_data<'l>(&'l self, bit_count :u8, peeked_data :u32)
-> PeekedDataLookupResult<'l> {
if bit_count > 8 {
panic!("Bit count {} larger than allowed 8", bit_count);
}
use self::UnrolledLookupEntry::*;
use self::PeekedDataLookupResult::*;
return match self.unrolled_entries[peeked_data as usize] {
// If cnt_to_remove is bigger than bit_count the result is inconclusive.
// Return in this case.
HasEntry(cnt_to_remove, payload) if cnt_to_remove <= bit_count
=> PayloadFound(cnt_to_remove, payload),
InconclusiveWithHint(hint)
=> Iter(8, VorbisHuffmanIter { desc_prog : &self.desc_prog, pos : hint }),
_
=> Iter(0, VorbisHuffmanIter { desc_prog : &self.desc_prog, pos : 0 }),
};
}
}
/// Iterator on the Huffman tree
pub struct VorbisHuffmanIter<'a> {
desc_prog :&'a Vec<u32>,
pos :u32,
}
impl<'a> VorbisHuffmanIter<'a> {
/// Iterate one level deeper inside the tree.
/// Returns `Some(p)` if it encounters a leaf with a payload p,
/// None if it only processed an inner node.
///
/// Inner nodes don't carry payloads in huffman trees.
///
/// If this function encounters a leaf, it automatically resets
/// the iterator to its starting state.
///
/// # Panics
///
/// Panics if the vorbis huffman treee is empty. It has to be found out
/// what to do if the huffman tree is empty, whether to reject the stream,
/// or whether to do sth else. Finding this out is a TODO.
pub fn next(&mut self, bit :bool) -> Option<u32> {
// Assertion test for the paranoid and testing, comment out if you are:
/*let cur_entry = self.desc_prog[self.pos as usize];
assert!((cur_entry & (1u32 << 31)) != 0);*/
//print!("With bit {:?}, pos {:?} becomes pos ", bit, self.pos);
self.pos = self.desc_prog[self.pos as usize + 1 + bit as usize];
//print!("{:?}", self.pos);
let child = self.desc_prog[self.pos as usize];
if (child & (1u32 << 31)) != 0 {
//println!(" => None");
// child has children
return None;
} else {
//println!(" => Some({:?})", child);
// child has no children, it's a leaf
self.pos = 0;
return Some(child);
}
}
}
#[cfg(test)]
impl VorbisHuffmanTree {
fn iter_test(&self, path :u32, path_len :u8, expected_val :u32) {
let mut itr = self.iter();
for i in 1 .. path_len {
assert_eq!(itr.next((path & (1 << (path_len - i))) != 0), None);
}
assert_eq!(itr.next((path & 1) != 0), Some(expected_val));
}
}
#[test]
fn test_huffman_tree() {
// Official example from the vorbis spec section 3.2.1
let tree = VorbisHuffmanTree::load_from_array(&[2, 4, 4, 4, 4, 2, 3, 3]).unwrap();
tree.iter_test(0b00, 2, 0);
tree.iter_test(0b0100, 4, 1);
tree.iter_test(0b0101, 4, 2);
tree.iter_test(0b0110, 4, 3);
tree.iter_test(0b0111, 4, 4);
tree.iter_test(0b10, 2, 5);
tree.iter_test(0b110, 3, 6);
tree.iter_test(0b111, 3, 7);
// Some other example
// we mostly test the length (max 32) here
VorbisHuffmanTree::load_from_array(&[
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 32]).unwrap();
}
#[test]
fn test_issue_8() {
// regression test for issue 8
// make sure that it doesn't panic.
let _ = VorbisHuffmanTree::load_from_array(&[0; 625]);
}
#[test]
fn test_under_over_spec() {
// All trees base on the official example from the vorbis spec section 3.2.1
// but with modifications to under- or overspecify them
// underspecified
let tree = VorbisHuffmanTree::load_from_array(&[2, 4, 4, 4, 4, 2, 3/*, 3*/]);
assert!(tree.is_err());
// underspecified
let tree = VorbisHuffmanTree::load_from_array(&[2, 4, 4, 4, /*4,*/ 2, 3, 3]);
assert!(tree.is_err());
// overspecified
let tree = VorbisHuffmanTree::load_from_array(&[2, 4, 4, 4, 4, 2, 3, 3/*]*/,3]);
assert!(tree.is_err());
}
#[test]
fn test_single_entry_huffman_tree() {
// Special testing for single entry codebooks, as required by the vorbis spec
let tree = VorbisHuffmanTree::load_from_array(&[1]).unwrap();
tree.iter_test(0b0, 1, 0);
tree.iter_test(0b1, 1, 0);
let tree = VorbisHuffmanTree::load_from_array(&[0, 0, 1, 0]).unwrap();
tree.iter_test(0b0, 1, 2);
tree.iter_test(0b1, 1, 2);
let tree = VorbisHuffmanTree::load_from_array(&[2]);
assert!(tree.is_err());
}
#[test]
fn test_unordered_huffman_tree() {
// Reordered the official example from the vorbis spec section 3.2.1
//
// Ensuring that unordered huffman trees work as well is important
// because the spec does not disallow them, and unordered
// huffman trees appear in "the wild".
let tree = VorbisHuffmanTree::load_from_array(&[2, 4, 4, 2, 4, 4, 3, 3]).unwrap();
tree.iter_test(0b00, 2, 0);
tree.iter_test(0b0100, 4, 1);
tree.iter_test(0b0101, 4, 2);
tree.iter_test(0b10, 2, 3);
tree.iter_test(0b0110, 4, 4);
tree.iter_test(0b0111, 4, 5);
tree.iter_test(0b110, 3, 6);
tree.iter_test(0b111, 3, 7);
}
#[test]
fn test_extracted_huffman_tree() {
// Extracted from a real-life vorbis file.
VorbisHuffmanTree::load_from_array(&[
5, 6, 11, 11, 11, 11, 10, 10, 12, 11, 5, 2, 11, 5, 6, 6,
7, 9, 11, 13, 13, 10, 7, 11, 6, 7, 8, 9, 10, 12, 11, 5,
11, 6, 8, 7, 9, 11, 14, 15, 11, 6, 6, 8, 4, 5, 7, 8,
10,13, 10, 5, 7, 7, 5, 5, 6, 8, 10, 11, 10, 7, 7, 8,
6, 5, 5, 7, 9, 9, 11, 8, 8, 11, 8, 7, 6, 6, 7, 9,
12,11, 10, 13, 9, 9, 7, 7, 7, 9, 11, 13, 12, 15, 12, 11,
9, 8, 8, 8]).unwrap();
}

847
vendor/lewton/src/imdct.rs vendored Normal file
View File

@@ -0,0 +1,847 @@
// Vorbis decoder written in Rust
//
// Copyright (c) 2016 est31 <MTest31@outlook.com>
// and contributors. All rights reserved.
// Licensed under MIT license, or Apache 2 license,
// at your option. Please see the LICENSE file
// attached to this source distribution for details.
// This file is a very close translation of the
// implementation of the algorithm from stb_vorbis.
use ::header_cached::CachedBlocksizeDerived;
fn imdct_step3_iter0_loop(n :usize, e :&mut[f32], i_off :usize, k_off :isize, a :&[f32]) {
let mut a_offs = 0;
let mut i_offs = i_off;
let mut k_offs = i_off as isize + k_off;
macro_rules! ee0 {
(-$x:expr) => {e[i_offs - ($x as usize)]};
($x:expr) => {e[i_offs + ($x as usize)]}
}
macro_rules! ee2 {
(-$x:expr) => {e[(k_offs - $x) as usize]};
($x:expr) => {e[(k_offs + $x) as usize]}
}
macro_rules! aa {
($x:expr) => {a[a_offs + ($x as usize)]}
}
assert_eq!((n & 3), 0);
for _ in 0 .. n >> 2 {
let mut k00_20 = ee0![ 0] - ee2![ 0];
let mut k01_21 = ee0![-1] - ee2![-1];
ee0![ 0] += ee2![ 0];
ee0![-1] += ee2![-1];
ee2![ 0] = k00_20 * aa![0] - k01_21 * aa![1];
ee2![-1] = k01_21 * aa![0] + k00_20 * aa![1];
a_offs += 8;
k00_20 = ee0![-2] - ee2![-2];
k01_21 = ee0![-3] - ee2![-3];
ee0![-2] += ee2![-2];
ee0![-3] += ee2![-3];
ee2![-2] = k00_20 * aa![0] - k01_21 * aa![1];
ee2![-3] = k01_21 * aa![0] + k00_20 * aa![1];
a_offs += 8;
k00_20 = ee0![-4] - ee2![-4];
k01_21 = ee0![-5] - ee2![-5];
ee0![-4] += ee2![-4];
ee0![-5] += ee2![-5];
ee2![-4] = k00_20 * aa![0] - k01_21 * aa![1];
ee2![-5] = k01_21 * aa![0] + k00_20 * aa![1];
a_offs += 8;
k00_20 = ee0![-6] - ee2![-6];
k01_21 = ee0![-7] - ee2![-7];
ee0![-6] += ee2![-6];
ee0![-7] += ee2![-7];
ee2![-6] = k00_20 * aa![0] - k01_21 * aa![1];
ee2![-7] = k01_21 * aa![0] + k00_20 * aa![1];
a_offs += 8;
i_offs -= 8;
k_offs -= 8;
}
}
fn imdct_step3_inner_r_loop(lim :usize, e :&mut [f32],
d0 :usize, k_off :isize, a :&[f32], k1 :usize) {
let mut a_offs = 0;
let mut d0_offs = d0;
let mut k_offs = d0 as isize + k_off;
macro_rules! e0 {
(-$x:expr) => {e[d0_offs - ($x as usize)]};
($x:expr) => {e[d0_offs + ($x as usize)]}
}
macro_rules! e2 {
(-$x:expr) => {e[(k_offs - $x) as usize]};
($x:expr) => {e[(k_offs + $x) as usize]}
}
macro_rules! aa {
($x:expr) => {a[a_offs + ($x as usize)]}
}
for _ in 0 .. lim >> 2 {
let mut k00_20 = e0![-0] - e2![-0];
let mut k01_21 = e0![-1] - e2![-1];
e0![-0] += e2![-0];
e0![-1] += e2![-1];
e2![-0] = (k00_20) * aa![0] - (k01_21) * aa![1];
e2![-1] = (k01_21) * aa![0] + (k00_20) * aa![1];
a_offs += k1;
k00_20 = e0![-2] - e2![-2];
k01_21 = e0![-3] - e2![-3];
e0![-2] += e2![-2];
e0![-3] += e2![-3];
e2![-2] = (k00_20) * aa![0] - (k01_21) * aa![1];
e2![-3] = (k01_21) * aa![0] + (k00_20) * aa![1];
a_offs += k1;
k00_20 = e0![-4] - e2![-4];
k01_21 = e0![-5] - e2![-5];
e0![-4] += e2![-4];
e0![-5] += e2![-5];
e2![-4] = (k00_20) * aa![0] - (k01_21) * aa![1];
e2![-5] = (k01_21) * aa![0] + (k00_20) * aa![1];
a_offs += k1;
k00_20 = e0![-6] - e2![-6];
k01_21 = e0![-7] - e2![-7];
e0![-6] += e2![-6];
e0![-7] += e2![-7];
e2![-6] = (k00_20) * aa![0] - (k01_21) * aa![1];
e2![-7] = (k01_21) * aa![0] + (k00_20) * aa![1];
d0_offs -= 8;
k_offs -= 8;
a_offs += k1;
}
}
fn imdct_step3_inner_s_loop(n :usize, e :&mut [f32], i_off :usize, k_off :isize,
a :&[f32], a_off :usize, k0 :usize) {
let a0 = a[0];
let a1 = a[0+1];
let a2 = a[0+a_off];
let a3 = a[0+a_off+1];
let a4 = a[0+a_off*2+0];
let a5 = a[0+a_off*2+1];
let a6 = a[0+a_off*3+0];
let a7 = a[0+a_off*3+1];
let mut i_offs = i_off;
let mut k_offs = (i_off as isize + k_off) as usize;
macro_rules! ee0 {
(-$x:expr) => {e[i_offs - ($x as usize)]};
($x:expr) => {e[i_offs + ($x as usize)]}
}
macro_rules! ee2 {
(-$x:expr) => {e[k_offs - ($x as usize)]};
($x:expr) => {e[k_offs + ($x as usize)]}
}
let mut i = 0;
loop {
let mut k00 = ee0![ 0] - ee2![ 0];
let mut k11 = ee0![-1] - ee2![-1];
ee0![ 0] = ee0![ 0] + ee2![ 0];
ee0![-1] = ee0![-1] + ee2![-1];
ee2![ 0] = (k00) * a0 - (k11) * a1;
ee2![-1] = (k11) * a0 + (k00) * a1;
k00 = ee0![-2] - ee2![-2];
k11 = ee0![-3] - ee2![-3];
ee0![-2] = ee0![-2] + ee2![-2];
ee0![-3] = ee0![-3] + ee2![-3];
ee2![-2] = (k00) * a2 - (k11) * a3;
ee2![-3] = (k11) * a2 + (k00) * a3;
k00 = ee0![-4] - ee2![-4];
k11 = ee0![-5] - ee2![-5];
ee0![-4] = ee0![-4] + ee2![-4];
ee0![-5] = ee0![-5] + ee2![-5];
ee2![-4] = (k00) * a4 - (k11) * a5;
ee2![-5] = (k11) * a4 + (k00) * a5;
k00 = ee0![-6] - ee2![-6];
k11 = ee0![-7] - ee2![-7];
ee0![-6] = ee0![-6] + ee2![-6];
ee0![-7] = ee0![-7] + ee2![-7];
ee2![-6] = (k00) * a6 - (k11) * a7;
ee2![-7] = (k11) * a6 + (k00) * a7;
i += 1;
// we have this check instead of a for loop
// over an iterator because otherwise we
// overflow.
if i >= n {
break;
}
i_offs -= k0;
k_offs -= k0;
}
}
#[inline]
fn iter_54(zm7 :&mut [f32]) {
// difference from stb_vorbis implementation:
// zm7 points to z minus 7
// (Rust disallows negative indices)
let k00 = zm7[7] - zm7[3];
let y0 = zm7[7] + zm7[3];
let y2 = zm7[5] + zm7[1];
let k22 = zm7[5] - zm7[1];
zm7[7] = y0 + y2; // z0 + z4 + z2 + z6
zm7[5] = y0 - y2; // z0 + z4 - z2 - z6
// done with y0,y2
let k33 = zm7[4] - zm7[0];
zm7[3] = k00 + k33; // z0 - z4 + z3 - z7
zm7[1] = k00 - k33; // z0 - z4 - z3 + z7
// done with k33
let k11 = zm7[6] - zm7[2];
let y1 = zm7[6] + zm7[2];
let y3 = zm7[4] + zm7[0];
zm7[6] = y1 + y3; // z1 + z5 + z3 + z7
zm7[4] = y1 - y3; // z1 + z5 - z3 - z7
zm7[2] = k11 - k22; // z1 - z5 + z2 - z6
zm7[0] = k11 + k22; // z1 - z5 - z2 + z6
}
fn imdct_step3_inner_s_loop_ld654(n :usize, e :&mut [f32], i_off :usize,
a :&[f32], base_n :usize)
{
let a_off = base_n >> 3;
let a2 = a[a_off];
let mut z_offs = i_off;
let basep16 = i_off - 16 * (n - 1 as usize);
macro_rules! z {
(-$x:expr) => {e[z_offs - ($x as usize)]}
}
loop {
let mut k00 = z![-0] - z![-8];
let mut k11 = z![-1] - z![-9];
z![-0] = z![-0] + z![-8];
z![-1] = z![-1] + z![-9];
z![-8] = k00;
z![-9] = k11;
k00 = z![ -2] - z![-10];
k11 = z![ -3] - z![-11];
z![ -2] = z![ -2] + z![-10];
z![ -3] = z![ -3] + z![-11];
z![-10] = (k00+k11) * a2;
z![-11] = (k11-k00) * a2;
k00 = z![-12] - z![ -4]; // reverse to avoid a unary negation
k11 = z![ -5] - z![-13];
z![ -4] = z![ -4] + z![-12];
z![ -5] = z![ -5] + z![-13];
z![-12] = k11;
z![-13] = k00;
k00 = z![-14] - z![ -6]; // reverse to avoid a unary negation
k11 = z![ -7] - z![-15];
z![ -6] = z![ -6] + z![-14];
z![ -7] = z![ -7] + z![-15];
z![-14] = (k00+k11) * a2;
z![-15] = (k00-k11) * a2;
iter_54(e.split_at_mut(z_offs - 7).1);
iter_54(e.split_at_mut(z_offs - 7 - 8).1);
// We need to compare with basep16 here
// in order to prevent a possible overflow
// in calculation of base, and in calculation
// of z_offs.
if z_offs <= basep16 {
break;
}
z_offs -= 16;
}
}
#[allow(dead_code)]
pub fn inverse_mdct(cached_bd :&CachedBlocksizeDerived, buffer :&mut [f32], bs :u8) {
let n = buffer.len();
// Pre-condition.
assert_eq!(n, 1 << bs);
let n2 = n >> 1;
let n4 = n >> 2;
let n8 = n >> 3;
// TODO later on we might want to do Vec::with_capacity here,
// and use buf2.push everywhere...
let mut buf2 :Vec<f32> = vec![0.0; n2];
let ctf = &cached_bd.twiddle_factors;
let a :&[f32] = &ctf.a;
let b :&[f32] = &ctf.b;
let c :&[f32] = &ctf.c;
macro_rules! break_if_sub_overflows {
($i:ident, $x:expr) => {
$i = match $i.checked_sub($x) {
Some(v) => v,
None => break,
};
}
}
// IMDCT algorithm from "The use of multirate filter banks for coding of high quality digital audio"
// See notes about bugs in that paper in less-optimal implementation 'inverse_mdct_old' in stb_vorbis original.
// kernel from paper
// merged:
// copy and reflect spectral data
// step 0
// note that it turns out that the items added together during
// this step are, in fact, being added to themselves (as reflected
// by step 0). inexplicable inefficiency! this became obvious
// once I combined the passes.
// so there's a missing 'times 2' here (for adding X to itself).
// this propogates through linearly to the end, where the numbers
// are 1/2 too small, and need to be compensated for.
{
let mut a_offs = 0;
let mut d_offs = n2 - 2;
let mut e_offs = 0;
let e_stop = n2;
macro_rules! d {
($x:expr) => {buf2[d_offs + ($x as usize)]}
}
macro_rules! aa {
($x:expr) => {a[a_offs + ($x as usize)]}
}
macro_rules! e {
($x:expr) => {buffer[e_offs + ($x as usize)]}
}
// TODO replace the while with a for once step_by on iterators
// is stabilized
while e_offs != e_stop {
d![1] = e![0] * aa![0] - e![2]*aa![1];
d![0] = e![0] * aa![1] + e![2]*aa![0];
d_offs -= 2;
a_offs += 2;
e_offs += 4;
}
e_offs = n2 - 3;
loop {
d![1] = -e![2] * aa![0] - -e![0]*aa![1];
d![0] = -e![2] * aa![1] + -e![0]*aa![0];
break_if_sub_overflows!(d_offs, 2);
a_offs += 2;
e_offs -= 4;
}
}
{
// now we use symbolic names for these, so that we can
// possibly swap their meaning as we change which operations
// are in place
let u = &mut *buffer;
let v = &mut *buf2;
// step 2 (paper output is w, now u)
// this could be in place, but the data ends up in the wrong
// place... _somebody_'s got to swap it, so this is nominated
{
let mut a_offs = n2 - 8;
let mut d0_offs = n4;
let mut d1_offs = 0;
let mut e0_offs = n4;
let mut e1_offs = 0;
macro_rules! aa {
($x:expr) => {a[a_offs + ($x as usize)]}
}
macro_rules! d0 {
($x:expr) => {u[d0_offs + ($x as usize)]}
}
macro_rules! d1 {
($x:expr) => {u[d1_offs + ($x as usize)]}
}
macro_rules! e0 {
($x:expr) => {v[e0_offs + ($x as usize)]}
}
macro_rules! e1 {
($x:expr) => {v[e1_offs + ($x as usize)]}
}
loop {
let mut v41_21 = e0![1] - e1![1];
let mut v40_20 = e0![0] - e1![0];
d0![1] = e0![1] + e1![1];
d0![0] = e0![0] + e1![0];
d1![1] = v41_21*aa![4] - v40_20*aa![5];
d1![0] = v40_20*aa![4] + v41_21*aa![5];
v41_21 = e0![3] - e1![3];
v40_20 = e0![2] - e1![2];
d0![3] = e0![3] + e1![3];
d0![2] = e0![2] + e1![2];
d1![3] = v41_21*aa![0] - v40_20*aa![1];
d1![2] = v40_20*aa![0] + v41_21*aa![1];
break_if_sub_overflows!(a_offs, 8);
d0_offs += 4;
d1_offs += 4;
e0_offs += 4;
e1_offs += 4;
}
}
// step 3
let ld = bs as usize;
// optimized step 3:
// the original step3 loop can be nested r inside s or s inside r;
// it's written originally as s inside r, but this is dumb when r
// iterates many times, and s few. So I have two copies of it and
// switch between them halfway.
// this is iteration 0 of step 3
imdct_step3_iter0_loop(n >> 4, u, n2-1-n4*0, -(n as isize >> 3), a);
imdct_step3_iter0_loop(n >> 4, u, n2-1-n4*1, -(n as isize >> 3), a);
// this is iteration 1 of step 3
imdct_step3_inner_r_loop(n >> 5, u, n2-1 - n8*0, -(n as isize >> 4), a, 16);
imdct_step3_inner_r_loop(n >> 5, u, n2-1 - n8*1, -(n as isize >> 4), a, 16);
imdct_step3_inner_r_loop(n >> 5, u, n2-1 - n8*2, -(n as isize >> 4), a, 16);
imdct_step3_inner_r_loop(n >> 5, u, n2-1 - n8*3, -(n as isize >> 4), a, 16);
for l in 2 .. (ld - 3) >> 1 {
let k0 = n >> (l + 2);
let k0_2 = k0 as isize >> 1;
let lim = 1 << (l+1);
for i in 0 .. lim {
imdct_step3_inner_r_loop(n >> (l + 4),
u, n2-1 - k0*i, -k0_2, a, 1 << (l+3));
}
}
for l in (ld - 3) >> 1 .. ld - 6 {
let k0 = n >> (l + 2);
let k1 = 1 << (l + 3);
let k0_2 = k0 as isize >> 1;
let rlim = n >> (l + 6);
let lim = 1 << (l + 1);
let mut i_off = n2 - 1;
let mut a_off = 0;
for _ in 0 .. rlim {
let a0 = a.split_at(a_off).1;
imdct_step3_inner_s_loop(lim, u, i_off, -k0_2, a0, k1, k0);
a_off += k1 * 4;
i_off -= 8;
}
}
// iterations with count:
// ld-6,-5,-4 all interleaved together
// the big win comes from getting rid of needless flops
// due to the constants on pass 5 & 4 being all 1 and 0;
// combining them to be simultaneous to improve cache made little difference
imdct_step3_inner_s_loop_ld654(n >> 5, u, n2 - 1, a, n);
// output is u
// step 4, 5, and 6
// cannot be in-place because of step 5
{
let bitrev_vec = &cached_bd.bitrev;
// weirdly, I'd have thought reading sequentially and writing
// erratically would have been better than vice-versa, but in
// fact that's not what my testing showed. (That is, with
// j = bitreverse(i), do you read i and write j, or read j and write i.)
let mut d0_offs = n4 - 4;
let mut d1_offs = n2 - 4;
let mut bitrev_offs = 0;
macro_rules! d0 {
($x:expr) => {v[d0_offs + ($x as usize)]}
}
macro_rules! d1 {
($x:expr) => {v[d1_offs + ($x as usize)]}
}
macro_rules! bitrev {
($x:expr) => {bitrev_vec[bitrev_offs + ($x as usize)]}
}
loop {
let mut k4 = bitrev![0] as usize;
d1![3] = u[k4 + 0];
d1![2] = u[k4 + 1];
d0![3] = u[k4 + 2];
d0![2] = u[k4 + 3];
k4 = bitrev![1] as usize;
d1![1] = u[k4 + 0];
d1![0] = u[k4 + 1];
d0![1] = u[k4 + 2];
d0![0] = u[k4 + 3];
break_if_sub_overflows!(d0_offs, 4);
d1_offs -= 4;
bitrev_offs += 2;
}
}
// (paper output is u, now v)
// step 7 (paper output is v, now v)
// this is now in place
{
let mut c_offs = 0;
let mut d_offs = 0;
let mut e_offs = n2 - 4;
macro_rules! cc {
($x:expr) => {c[c_offs + ($x as usize)]}
}
macro_rules! d {
($x:expr) => {v[d_offs + ($x as usize)]}
}
macro_rules! e {
($x:expr) => {v[e_offs + ($x as usize)]}
}
while d_offs < e_offs {
let mut a02 = d![0] - e![2];
let mut a11 = d![1] + e![3];
let mut b0 = cc![1]*a02 + cc![0]*a11;
let mut b1 = cc![1]*a11 - cc![0]*a02;
let mut b2 = d![0] + e![ 2];
let mut b3 = d![1] - e![ 3];
d![0] = b2 + b0;
d![1] = b3 + b1;
e![2] = b2 - b0;
e![3] = b1 - b3;
a02 = d![2] - e![0];
a11 = d![3] + e![1];
b0 = cc![3]*a02 + cc![2]*a11;
b1 = cc![3]*a11 - cc![2]*a02;
b2 = d![2] + e![ 0];
b3 = d![3] - e![ 1];
d![2] = b2 + b0;
d![3] = b3 + b1;
e![0] = b2 - b0;
e![1] = b1 - b3;
c_offs += 4;
d_offs += 4;
e_offs -= 4;
}
}
}
// step 8+decode (paper output is X, now buffer)
// this generates pairs of data a la 8 and pushes them directly through
// the decode kernel (pushing rather than pulling) to avoid having
// to make another pass later
// this cannot POSSIBLY be in place, so we refer to the buffers directly
{
let mut d0_offs = 0;
let mut d1_offs = n2 - 4;
let mut d2_offs = n2;
let mut d3_offs = n - 4;
let mut b_offs = n2 - 8;
let mut e_offs = n2 - 8;
macro_rules! d0 {
($x:expr) => {buffer[d0_offs + ($x as usize)]}
}
macro_rules! d1 {
($x:expr) => {buffer[d1_offs + ($x as usize)]}
}
macro_rules! d2 {
($x:expr) => {buffer[d2_offs + ($x as usize)]}
}
macro_rules! d3 {
($x:expr) => {buffer[d3_offs + ($x as usize)]}
}
macro_rules! b {
($x:expr) => {b[b_offs + ($x as usize)]}
}
macro_rules! e {
($x:expr) => {buf2[e_offs + ($x as usize)]}
}
loop {
let mut p3 = e![6]*b![7] - e![7]*b![6];
let mut p2 = -e![6]*b![6] - e![7]*b![7];
d0![0] = p3;
d1![3] = - p3;
d2![0] = p2;
d3![3] = p2;
let mut p1 = e![4]*b![5] - e![5]*b![4];
let mut p0 = -e![4]*b![4] - e![5]*b![5];
d0![1] = p1;
d1![2] = - p1;
d2![1] = p0;
d3![2] = p0;
p3 = e![2]*b![3] - e![3]*b![2];
p2 = -e![2]*b![2] - e![3]*b![3];
d0![2] = p3;
d1![1] = - p3;
d2![2] = p2;
d3![1] = p2;
p1 = e![0]*b![1] - e![1]*b![0];
p0 = -e![0]*b![0] - e![1]*b![1];
d0![3] = p1;
d1![0] = - p1;
d2![3] = p0;
d3![0] = p0;
break_if_sub_overflows!(e_offs, 8);
b_offs -= 8;
d0_offs += 4;
d2_offs += 4;
d1_offs -= 4;
d3_offs -= 4;
}
}
}
#[allow(dead_code)]
pub fn inverse_mdct_naive(cached_bd :&CachedBlocksizeDerived, buffer :&mut[f32]) {
let n = buffer.len();
let n2 = n >> 1;
let n4 = n >> 2;
let n8 = n >> 3;
let n3_4 = n - n4;
let mut u = [0.0; 1 << 13];
let mut xa = [0.0; 1 << 13];
let mut v = [0.0; 1 << 13];
let mut w = [0.0; 1 << 13];
// retrieve the cached twiddle factors
let ctf = &cached_bd.twiddle_factors;
let a :&[f32] = &ctf.a;
let b :&[f32] = &ctf.b;
let c :&[f32] = &ctf.c;
// IMDCT algorithm from "The use of multirate filter banks for coding of high quality digital audio"
// Note there are bugs in that pseudocode, presumably due to them attempting
// to rename the arrays nicely rather than representing the way their actual
// implementation bounces buffers back and forth. As a result, even in the
// "some formulars corrected" version, a direct implementation fails. These
// are noted below as "paper bug".
// copy and reflect spectral data
for k in 0 .. n2 {
u[k] = buffer[k];
}
for k in n2 .. n {
u[k] = -buffer[n - k - 1];
}
let mut k2 = 0;
let mut k4 = 0;
// kernel from paper
// step 1
while k2 < n2 { // n4 iterations
v[n-k4-1] = (u[k4] - u[n-k4-1]) * a[k2] - (u[k4+2] - u[n-k4-3])*a[k2+1];
v[n-k4-3] = (u[k4] - u[n-k4-1]) * a[k2+1] + (u[k4+2] - u[n-k4-3])*a[k2];
k2 += 2;
k4 += 4;
}
// step 2
k4 = 0;
while k4 < n2 { // n8 iterations
w[n2+3+k4] = v[n2+3+k4] + v[k4+3];
w[n2+1+k4] = v[n2+1+k4] + v[k4+1];
w[k4+3] = (v[n2+3+k4] - v[k4+3])*a[n2-4-k4] - (v[n2+1+k4]-v[k4+1])*a[n2-3-k4];
w[k4+1] = (v[n2+1+k4] - v[k4+1])*a[n2-4-k4] + (v[n2+3+k4]-v[k4+3])*a[n2-3-k4];
k4 += 4;
}
// step 3
let ld :usize = (::ilog(n as u64) - 1) as usize;
for l in 0 .. ld - 3 {
let k0 = n >> (l+2);
let k1 = 1 << (l+3);
let rlim = n >> (l+4);
let slim = 1 << (l+1);
let mut r4 = 0;
for r in 0 .. rlim {
let mut s2 = 0;
for _ in 0 .. slim {
u[n-1-k0*s2-r4] = w[n-1-k0*s2-r4] + w[n-1-k0*(s2+1)-r4];
u[n-3-k0*s2-r4] = w[n-3-k0*s2-r4] + w[n-3-k0*(s2+1)-r4];
u[n-1-k0*(s2+1)-r4] = (w[n-1-k0*s2-r4] - w[n-1-k0*(s2+1)-r4]) * a[r*k1]
- (w[n-3-k0*s2-r4] - w[n-3-k0*(s2+1)-r4]) * a[r*k1+1];
u[n-3-k0*(s2+1)-r4] = (w[n-3-k0*s2-r4] - w[n-3-k0*(s2+1)-r4]) * a[r*k1]
+ (w[n-1-k0*s2-r4] - w[n-1-k0*(s2+1)-r4]) * a[r*k1+1];
s2 += 2;
}
r4 += 4;
}
if l+1 < ld-3 {
// paper bug: ping-ponging of u&w here is omitted
w.copy_from_slice(&u);
}
}
// step 4
for i in 0 .. n8 {
let j = (::bit_reverse(i as u32) >> (32-ld+3)) as usize;
assert!(j < n8);
if i == j {
// paper bug: original code probably swapped in place; if copying,
// need to directly copy in this case
let ii = i << 3;
v[ii+1] = u[ii+1];
v[ii+3] = u[ii+3];
v[ii+5] = u[ii+5];
v[ii+7] = u[ii+7];
} else if i < j {
let ii = i << 3;
let j8 = j << 3;
v[j8+1] = u[ii+1];
v[ii+1] = u[j8 + 1];
v[j8+3] = u[ii+3];
v[ii+3] = u[j8 + 3];
v[j8+5] = u[ii+5];
v[ii+5] = u[j8 + 5];
v[j8+7] = u[ii+7];
v[ii+7] = u[j8 + 7];
}
}
// step 5
for k in 0 .. n2 {
w[k] = v[k*2+1];
}
// step 6
let mut k2 = 0;
let mut k4 = 0;
while k2 < n4 { // n8 iterations
u[n-1-k2] = w[k4];
u[n-2-k2] = w[k4+1];
u[n3_4 - 1 - k2] = w[k4+2];
u[n3_4 - 2 - k2] = w[k4+3];
k2 += 2;
k4 += 4;
}
// step 7
k2 = 0;
while k2 < n4 { // n8 iterations
v[n2 + k2 ] = ( u[n2 + k2] + u[n-2-k2] + c[k2+1]*(u[n2+k2]-u[n-2-k2]) + c[k2]*(u[n2+k2+1]+u[n-2-k2+1]))/2.0;
v[n-2 - k2] = ( u[n2 + k2] + u[n-2-k2] - c[k2+1]*(u[n2+k2]-u[n-2-k2]) - c[k2]*(u[n2+k2+1]+u[n-2-k2+1]))/2.0;
v[n2+1+ k2] = ( u[n2+1+k2] - u[n-1-k2] + c[k2+1]*(u[n2+1+k2]+u[n-1-k2]) - c[k2]*(u[n2+k2]-u[n-2-k2]))/2.0;
v[n-1 - k2] = (-u[n2+1+k2] + u[n-1-k2] + c[k2+1]*(u[n2+1+k2]+u[n-1-k2]) - c[k2]*(u[n2+k2]-u[n-2-k2]))/2.0;
k2 += 2;
}
// step 8
k2 = 0;
for k in 0 .. n4 {
xa[k] = v[k2+n2]*b[k2 ] + v[k2+1+n2]*b[k2+1];
xa[n2-1-k] = v[k2+n2]*b[k2+1] - v[k2+1+n2]*b[k2 ];
k2 += 2;
}
// decode kernel to output
for i in 0 .. n4 {
buffer[i] = xa[i + n4];
}
for i in n4 .. n3_4 {
buffer[i] = -xa[n3_4 - i - 1];
}
for i in n3_4 .. n {
buffer[i] = -xa[i - n3_4];
}
}
#[cfg(test)]
#[test]
fn test_imdct_naive() {
use imdct_test::*;
let mut arr_1 = imdct_prepare(&IMDCT_INPUT_TEST_ARR_1);
let cbd = CachedBlocksizeDerived::from_blocksize(8);
inverse_mdct_naive(&cbd, &mut arr_1);
let mismatches = fuzzy_compare_array(
&arr_1, &IMDCT_OUTPUT_TEST_ARR_1,
0.00005, true);
let mismatches_limit = 0;
if mismatches > mismatches_limit {
panic!("Numer of mismatches {} was larger than limit of {}",
mismatches, mismatches_limit);
}
}
#[cfg(test)]
#[test]
fn test_imdct() {
use imdct_test::*;
let mut arr_1 = imdct_prepare(&IMDCT_INPUT_TEST_ARR_1);
let blocksize = 8;
let cbd = CachedBlocksizeDerived::from_blocksize(blocksize);
inverse_mdct(&cbd, &mut arr_1, blocksize);
let mismatches = fuzzy_compare_array(
&arr_1, &IMDCT_OUTPUT_TEST_ARR_1,
0.00005, true);
let mismatches_limit = 0;
if mismatches > mismatches_limit {
panic!("Numer of mismatches {} was larger than limit of {}",
mismatches, mismatches_limit);
}
}

1005
vendor/lewton/src/imdct_test.rs vendored Normal file

File diff suppressed because it is too large Load Diff

390
vendor/lewton/src/inside_ogg.rs vendored Normal file
View File

@@ -0,0 +1,390 @@
// Vorbis decoder written in Rust
//
// Copyright (c) 2016 est31 <MTest31@outlook.com>
// and contributors. All rights reserved.
// Licensed under MIT license, or Apache 2 license,
// at your option. Please see the LICENSE file
// attached to this source distribution for details.
/*!
Higher-level utilities for Ogg streams and files
This module provides higher level access to the library functionality,
and useful helper methods for the Ogg `PacketReader` struct.
*/
use ogg::{PacketReader, Packet};
use header::*;
use VorbisError;
use std::io::{Read, Seek};
use ::audio::{PreviousWindowRight, read_audio_packet,
read_audio_packet_generic};
use ::header::HeaderSet;
use ::samples::{Samples, InterleavedSamples};
/// Reads the three vorbis headers from an ogg stream as well as stream serial information
///
/// Please note that this function doesn't work well with async
/// I/O. In order to support this use case, enable the `async_ogg` feature,
/// and use the `HeadersReader` struct instead.
pub fn read_headers<'a, T: Read + Seek + 'a>(rdr: &mut PacketReader<T>) ->
Result<(HeaderSet, u32), VorbisError> {
let pck :Packet = try!(rdr.read_packet_expected());
let ident_hdr = try!(read_header_ident(&pck.data));
let stream_serial = pck.stream_serial();
let mut pck :Packet = try!(rdr.read_packet_expected());
while pck.stream_serial() != stream_serial {
pck = try!(rdr.read_packet_expected());
}
let comment_hdr = try!(read_header_comment(&pck.data));
let mut pck :Packet = try!(rdr.read_packet_expected());
while pck.stream_serial() != stream_serial {
pck = try!(rdr.read_packet_expected());
}
let setup_hdr = try!(read_header_setup(&pck.data, ident_hdr.audio_channels,
(ident_hdr.blocksize_0, ident_hdr.blocksize_1)));
rdr.delete_unread_packets();
return Ok(((ident_hdr, comment_hdr, setup_hdr), pck.stream_serial()));
}
/**
Reading ogg/vorbis files or streams
This is a small helper struct to help reading ogg/vorbis files
or streams in that format.
It only supports the main use case of pure audio ogg files streams.
Reading a file where vorbis is only one of multiple streams, like
in the case of ogv, is not supported.
If you need support for this, you need to use the lower level methods
instead.
*/
pub struct OggStreamReader<T: Read + Seek> {
rdr :PacketReader<T>,
pwr :PreviousWindowRight,
stream_serial :u32,
pub ident_hdr :IdentHeader,
pub comment_hdr :CommentHeader,
pub setup_hdr :SetupHeader,
cur_absgp :Option<u64>,
}
impl<T: Read + Seek> OggStreamReader<T> {
/// Constructs a new OggStreamReader from a given implementation of `Read + Seek`.
///
/// Please note that this function doesn't work well with async
/// I/O. In order to support this use case, enable the `async_ogg` feature,
/// and use the `HeadersReader` struct instead.
pub fn new(rdr :T) ->
Result<Self, VorbisError> {
OggStreamReader::from_ogg_reader(PacketReader::new(rdr))
}
/// Constructs a new OggStreamReader from a given Ogg PacketReader.
///
/// The `new` function is a nice wrapper around this function that
/// also creates the ogg reader.
///
/// Please note that this function doesn't work well with async
/// I/O. In order to support this use case, enable the `async_ogg` feature,
/// and use the `HeadersReader` struct instead.
pub fn from_ogg_reader(mut rdr :PacketReader<T>) ->
Result<Self, VorbisError> {
let ((ident_hdr, comment_hdr, setup_hdr), stream_serial) =
try!(read_headers(&mut rdr));
return Ok(OggStreamReader {
rdr,
pwr : PreviousWindowRight::new(),
ident_hdr,
comment_hdr,
setup_hdr,
stream_serial,
cur_absgp : None,
});
}
pub fn into_inner(self) -> PacketReader<T> {
self.rdr
}
fn read_next_audio_packet(&mut self) -> Result<Option<Packet>, VorbisError> {
loop {
let pck = match try!(self.rdr.read_packet()) {
Some(p) => p,
None => return Ok(None),
};
if pck.stream_serial() != self.stream_serial {
if pck.first_in_stream() {
// We have a chained ogg file. This means we need to
// re-initialize the internal context.
let ident_hdr = try!(read_header_ident(&pck.data));
let pck :Packet = try!(self.rdr.read_packet_expected());
let comment_hdr = try!(read_header_comment(&pck.data));
let pck :Packet = try!(self.rdr.read_packet_expected());
let setup_hdr = try!(read_header_setup(&pck.data, ident_hdr.audio_channels,
(ident_hdr.blocksize_0, ident_hdr.blocksize_1)));
// Update the context
self.pwr = PreviousWindowRight::new();
self.ident_hdr = ident_hdr;
self.comment_hdr = comment_hdr;
self.setup_hdr = setup_hdr;
self.stream_serial = pck.stream_serial();
self.cur_absgp = None;
// Now, read the first audio packet to prime the pwr
// and discard the packet.
let pck = match try!(self.rdr.read_packet()) {
Some(p) => p,
None => return Ok(None),
};
let _decoded_pck = try!(read_audio_packet(&self.ident_hdr,
&self.setup_hdr, &pck.data, &mut self.pwr));
self.cur_absgp = Some(pck.absgp_page());
return Ok(try!(self.rdr.read_packet()));
} else {
// Ignore every packet that has a mismatching stream serial
}
} else {
return Ok(Some(pck));
}
}
}
/// Reads and decompresses an audio packet from the stream.
///
/// On read errors, it returns Err(e) with the error.
///
/// On success, it either returns None, when the end of the
/// stream has been reached, or Some(packet_data),
/// with the data of the decompressed packet.
pub fn read_dec_packet(&mut self) ->
Result<Option<Vec<Vec<i16>>>, VorbisError> {
let pck = try!(self.read_dec_packet_generic());
Ok(pck)
}
/// Reads and decompresses an audio packet from the stream (generic).
///
/// On read errors, it returns Err(e) with the error.
///
/// On success, it either returns None, when the end of the
/// stream has been reached, or Some(packet_data),
/// with the data of the decompressed packet.
pub fn read_dec_packet_generic<S :Samples>(&mut self) ->
Result<Option<S>, VorbisError> {
let pck = match try!(self.read_next_audio_packet()) {
Some(p) => p,
None => return Ok(None),
};
let mut decoded_pck :S = try!(read_audio_packet_generic(&self.ident_hdr,
&self.setup_hdr, &pck.data, &mut self.pwr));
// If this is the last packet in the logical bitstream,
// we need to truncate it so that its ending matches
// the absgp of the current page.
// This is what the spec mandates and also the behaviour
// of libvorbis.
if let (Some(absgp), true) = (self.cur_absgp, pck.last_in_stream()) {
let target_length = pck.absgp_page().saturating_sub(absgp) as usize;
decoded_pck.truncate(target_length);
}
if pck.last_in_page() {
self.cur_absgp = Some(pck.absgp_page());
} else if let &mut Some(ref mut absgp) = &mut self.cur_absgp {
*absgp += decoded_pck.num_samples() as u64;
}
return Ok(Some(decoded_pck));
}
/// Reads and decompresses an audio packet from the stream (interleaved).
///
/// On read errors, it returns Err(e) with the error.
///
/// On success, it either returns None, when the end of the
/// stream has been reached, or Some(packet_data),
/// with the data of the decompressed packet.
///
/// Unlike `read_dec_packet`, this function returns the
/// interleaved samples.
pub fn read_dec_packet_itl(&mut self) ->
Result<Option<Vec<i16>>, VorbisError> {
let decoded_pck :InterleavedSamples<_> = match try!(self.read_dec_packet_generic()) {
Some(p) => p,
None => return Ok(None),
};
return Ok(Some(decoded_pck.samples));
}
/// Returns the stream serial of the current stream
///
/// The stream serial can change in chained ogg files.
pub fn stream_serial(&self) -> u32 {
self.stream_serial
}
/// Returns the absolute granule position of the last read page.
///
/// In the case of ogg/vorbis, the absolute granule position is given
/// as number of PCM samples, on a per channel basis.
pub fn get_last_absgp(&self) -> Option<u64> {
self.cur_absgp
}
/// Seeks to the specified absolute granule position, with a page granularity.
///
/// The granularity is per-page, and the obtained position is
/// then <= the seeked absgp.
///
/// In the case of ogg/vorbis, the absolute granule position is given
/// as number of PCM samples, on a per channel basis.
pub fn seek_absgp_pg(&mut self, absgp :u64) -> Result<(), VorbisError> {
try!(self.rdr.seek_absgp(None, absgp));
// Reset the internal state after the seek
self.cur_absgp = None;
self.pwr = PreviousWindowRight::new();
Ok(())
}
}
#[cfg(feature = "async_ogg")]
/**
Support for async I/O
This module provides support for asyncronous I/O.
*/
pub mod async_api {
use super::*;
use ogg::OggReadError;
use ogg::reading::async_api::PacketReader;
use futures::stream::Stream;
use tokio_io::AsyncRead;
use futures::{Async, Future, Poll};
use std::io::{Error, ErrorKind};
use std::mem::replace;
/// Async ready creator utility to read headers out of an
/// ogg stream.
///
/// All functions this struct has are ready to be used for operation with async I/O.
pub struct HeadersReader<T: AsyncRead> {
pck_rd :PacketReader<T>,
ident_hdr :Option<IdentHeader>,
comment_hdr :Option<CommentHeader>,
}
impl<T: AsyncRead> HeadersReader<T> {
pub fn new(inner :T) -> Self {
HeadersReader::from_packet_reader(PacketReader::new(inner))
}
pub fn from_packet_reader(pck_rd :PacketReader<T>) -> Self {
HeadersReader {
pck_rd,
ident_hdr : None,
comment_hdr : None,
}
}
}
impl<T: AsyncRead> Future for HeadersReader<T> {
type Item = HeaderSet;
type Error = VorbisError;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
macro_rules! rd_pck {
() => {
if let Some(pck) = try_ready!(self.pck_rd.poll()) {
pck
} else {
// Note: we are stealing the Io variant from
// the ogg crate here which is not 100% clean,
// but I think in general it is what the
// read_packet_expected function of the ogg
// crate does too, and adding our own case
// to the VorbisError enum that only fires
// in an async mode is too complicated IMO.
try!(Err(OggReadError::ReadError(Error::new(ErrorKind::UnexpectedEof,
"Expected header packet but found end of stream"))))
}
}
}
if self.ident_hdr.is_none() {
let pck = rd_pck!();
self.ident_hdr = Some(try!(read_header_ident(&pck.data)));
}
if self.comment_hdr.is_none() {
let pck = rd_pck!();
self.comment_hdr = Some(try!(read_header_comment(&pck.data)));
}
let setup_hdr = {
let ident = self.ident_hdr.as_ref().unwrap();
let pck = rd_pck!();
try!(read_header_setup(&pck.data,
ident.audio_channels, (ident.blocksize_0, ident.blocksize_1)))
};
let ident_hdr = replace(&mut self.ident_hdr, None).unwrap();
let comment_hdr = replace(&mut self.comment_hdr, None).unwrap();
Ok(Async::Ready((ident_hdr, comment_hdr, setup_hdr)))
}
}
/// Reading ogg/vorbis files or streams
///
/// This is a small helper struct to help reading ogg/vorbis files
/// or streams in that format.
///
/// It only supports the main use case of pure audio ogg files streams.
/// Reading a file where vorbis is only one of multiple streams, like
/// in the case of ogv, is not supported.
///
/// If you need support for this, you need to use the lower level methods
/// instead.
pub struct OggStreamReader<T :AsyncRead> {
pck_rd :PacketReader<T>,
pwr :PreviousWindowRight,
pub ident_hdr :IdentHeader,
pub comment_hdr :CommentHeader,
pub setup_hdr :SetupHeader,
absgp_of_last_read :Option<u64>,
}
impl<T :AsyncRead> OggStreamReader<T> {
/// Creates a new OggStreamReader from the given parameters
pub fn new(hdr_rdr :HeadersReader<T>, hdrs :HeaderSet) -> Self {
OggStreamReader::from_pck_rdr(hdr_rdr.pck_rd, hdrs)
}
/// Creates a new OggStreamReader from the given parameters
pub fn from_pck_rdr(pck_rd :PacketReader<T>, hdrs :HeaderSet) -> Self {
OggStreamReader {
pck_rd,
pwr : PreviousWindowRight::new(),
ident_hdr : hdrs.0,
comment_hdr : hdrs.1,
setup_hdr : hdrs.2,
absgp_of_last_read : None,
}
}
}
impl<T :AsyncRead> Stream for OggStreamReader<T> {
type Item = Vec<Vec<i16>>;
type Error = VorbisError;
fn poll(&mut self) -> Poll<Option<Vec<Vec<i16>>>, VorbisError> {
let pck = match try_ready!(self.pck_rd.poll()) {
Some(p) => p,
None => return Ok(Async::Ready(None)),
};
let decoded_pck = try!(read_audio_packet(&self.ident_hdr,
&self.setup_hdr, &pck.data, &mut self.pwr));
self.absgp_of_last_read = Some(pck.absgp_page());
Ok(Async::Ready(Some(decoded_pck)))
}
}
}

264
vendor/lewton/src/lib.rs vendored Normal file
View File

@@ -0,0 +1,264 @@
// Vorbis decoder written in Rust
//
// Copyright (c) 2016 est31 <MTest31@outlook.com>
// and contributors. All rights reserved.
// Licensed under MIT license, or Apache 2 license,
// at your option. Please see the LICENSE file
// attached to this source distribution for details.
#![cfg_attr(not(cargo_c), forbid(unsafe_code))]
#![cfg_attr(test, deny(warnings))]
/*!
A `vorbis` decoder, written in Rust.
If you "just" want to decode `ogg/vorbis` files, take a look into
the `inside_ogg` module (make sure you haven't disabled the `ogg` feature).
For lower level, per-packet usage, you can have a look at the `audio` and `header`
modules.
*/
extern crate byteorder;
extern crate tinyvec;
#[cfg(feature = "ogg")]
extern crate ogg;
#[cfg(feature = "async_ogg")]
#[macro_use]
extern crate futures;
#[cfg(feature = "async_ogg")]
extern crate tokio_io;
macro_rules! try {
($expr:expr) => (match $expr {
$crate::std::result::Result::Ok(val) => val,
$crate::std::result::Result::Err(err) => {
return Err($crate::std::convert::From::from(err));
}
})
}
/*
// This little thing is very useful.
macro_rules! try {
($expr:expr) => (match $expr {
$crate::std::result::Result::Ok(val) => val,
$crate::std::result::Result::Err(err) => {
panic!("Panic on Err turned on for debug reasons. Encountered Err: {:?}", err)
}
})
}
// */
// The following macros are super useful for debugging
macro_rules! record_residue_pre_inverse {
($residue_vectors:expr) => {
// for v in $residue_vectors.iter() {
// for &re in v {
// println!("{}", re);
// }
// }
}
}
macro_rules! record_residue_post_inverse {
($residue_vectors:expr) => {
// for v in $residue_vectors.iter() {
// for &re in v {
// println!("{}", re);
// }
// }
}
}
macro_rules! record_pre_mdct {
($audio_spectri:expr) => {
// for v in $audio_spectri.iter() {
// for &s in v {
// println!("{:.5}", s);
// }
// }
}
}
macro_rules! record_post_mdct {
($audio_spectri:expr) => {
// for v in $audio_spectri.iter() {
// for &s in v {
// println!("{:.4}", s);
// }
// }
}
}
pub mod header;
mod header_cached;
mod huffman_tree;
mod imdct;
#[cfg(test)]
mod imdct_test;
pub mod audio;
mod bitpacking;
#[cfg(feature = "ogg")]
pub mod inside_ogg;
pub mod samples;
#[cfg(feature = "ogg")]
#[doc(no_inline)]
pub use ogg::OggReadError;
#[cfg(cargo_c)]
mod capi;
#[cfg(cargo_c)]
pub use capi::*;
/// Errors that can occur during decoding
#[derive(Debug)]
pub enum VorbisError {
BadAudio(audio::AudioReadError),
BadHeader(header::HeaderReadError),
#[cfg(feature = "ogg")]
OggError(OggReadError),
}
impl std::error::Error for VorbisError {}
impl std::fmt::Display for VorbisError {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
write!(fmt, "{}", match self {
VorbisError::BadAudio(_) => "Vorbis bitstream audio decode problem",
VorbisError::BadHeader(_) => "Vorbis bitstream header decode problem",
#[cfg(feature = "ogg")]
VorbisError::OggError(_) => "Ogg decode problem",
})
}
}
impl From<audio::AudioReadError> for VorbisError {
fn from(err :audio::AudioReadError) -> VorbisError {
VorbisError::BadAudio(err)
}
}
impl From<header::HeaderReadError> for VorbisError {
fn from(err :header::HeaderReadError) -> VorbisError {
VorbisError::BadHeader(err)
}
}
#[cfg(feature = "ogg")]
impl From<OggReadError> for VorbisError {
fn from(err :OggReadError) -> VorbisError {
VorbisError::OggError(err)
}
}
fn ilog(val :u64) -> u8 {
64 - val.leading_zeros() as u8
}
#[test]
fn test_ilog() {
// Uses the test vectors from the Vorbis I spec
assert_eq!(ilog(0), 0);
assert_eq!(ilog(1), 1);
assert_eq!(ilog(2), 2);
assert_eq!(ilog(3), 2);
assert_eq!(ilog(4), 3);
assert_eq!(ilog(7), 3);
}
fn bit_reverse(n :u32) -> u32 {
// From the stb_vorbis implementation
let mut nn = n;
nn = ((nn & 0xAAAAAAAA) >> 1) | ((nn & 0x55555555) << 1);
nn = ((nn & 0xCCCCCCCC) >> 2) | ((nn & 0x33333333) << 2);
nn = ((nn & 0xF0F0F0F0) >> 4) | ((nn & 0x0F0F0F0F) << 4);
nn = ((nn & 0xFF00FF00) >> 8) | ((nn & 0x00FF00FF) << 8);
return (nn >> 16) | (nn << 16);
}
#[allow(dead_code)]
fn print_u8_slice(arr :&[u8]) {
if arr.len() <= 4 {
for a in arr {
print!("0x{:02x} ", a);
}
println!("");
return;
}
println!("[");
let mut i :usize = 0;
while i * 4 < arr.len() - 4 {
println!("\t0x{:02x}, 0x{:02x}, 0x{:02x}, 0x{:02x},",
arr[i * 4], arr[i * 4 + 1], arr[i * 4 + 2], arr[i * 4 + 3]);
i += 1;
}
match arr.len() as i64 - i as i64 * 4 {
1 => println!("\t0x{:02x}];", arr[i * 4]),
2 => println!("\t0x{:02x}, 0x{:02x}];", arr[i * 4], arr[i * 4 + 1]),
3 => println!("\t0x{:02x}, 0x{:02x}, 0x{:02x}];",
arr[i * 4], arr[i * 4 + 1], arr[i * 4 + 2]),
4 => println!("\t0x{:02x}, 0x{:02x}, 0x{:02x}, 0x{:02x}];",
arr[i * 4], arr[i * 4 + 1], arr[i * 4 + 2], arr[i * 4 + 3]),
de => panic!("impossible value {}", de),
}
}
#[allow(dead_code)]
fn print_u32_slice(arr :&[u32]) {
if arr.len() <= 4 {
for a in arr {
print!("0x{:02x} ", a);
}
println!("");
return;
}
println!("[");
let mut i :usize = 0;
while i * 4 < arr.len() - 4 {
println!("\t0x{:08x}, 0x{:08x}, 0x{:08x}, 0x{:08x},",
arr[i * 4], arr[i * 4 + 1], arr[i * 4 + 2], arr[i * 4 + 3]);
i += 1;
}
match arr.len() as i64 - i as i64 * 4 {
1 => println!("\t0x{:08x}];", arr[i * 4]),
2 => println!("\t0x{:08x}, 0x{:08x}];", arr[i * 4], arr[i * 4 + 1]),
3 => println!("\t0x{:08x}, 0x{:08x}, 0x{:08x}];",
arr[i * 4], arr[i * 4 + 1], arr[i * 4 + 2]),
4 => println!("\t0x{:08x}, 0x{:08x}, 0x{:08x}, 0x{:08x}];",
arr[i * 4], arr[i * 4 + 1], arr[i * 4 + 2], arr[i * 4 + 3]),
de => panic!("impossible value {}", de),
}
}
#[allow(dead_code)]
fn print_f64_slice(arr :&[f64]) {
if arr.len() <= 4 {
for a in arr {
print!("0x{} ", a);
}
println!("");
return;
}
println!("[");
let mut i :usize = 0;
while i * 4 < arr.len() - 4 {
println!("\t{}, {}, {}, {},",
arr[i * 4], arr[i * 4 + 1], arr[i * 4 + 2], arr[i * 4 + 3]);
i += 1;
}
match arr.len() as i64 - i as i64 * 4 {
1 => println!("\t{}];", arr[i * 4]),
2 => println!("\t{}, {}];", arr[i * 4], arr[i * 4 + 1]),
3 => println!("\t{}, {}, {}];",
arr[i * 4], arr[i * 4 + 1], arr[i * 4 + 2]),
4 => println!("\t{}, {}, {}, {}];",
arr[i * 4], arr[i * 4 + 1], arr[i * 4 + 2], arr[i * 4 + 3]),
de => panic!("impossible value {}", de),
}
}

103
vendor/lewton/src/samples.rs vendored Normal file
View File

@@ -0,0 +1,103 @@
// Vorbis decoder written in Rust
//
// Copyright (c) 2019 est31 <MTest31@outlook.com>
// and contributors. All rights reserved.
// Licensed under MIT license, or Apache 2 license,
// at your option. Please see the LICENSE file
// attached to this source distribution for details.
/*!
Traits for sample formats
*/
/// Trait for a packet of multiple samples
pub trait Samples {
fn num_samples(&self) -> usize;
fn truncate(&mut self, limit :usize);
fn from_floats(floats :Vec<Vec<f32>>) -> Self;
}
impl<S :Sample> Samples for Vec<Vec<S>> {
fn num_samples(&self) -> usize {
self[0].len()
}
fn truncate(&mut self, limit :usize) {
for ch in self.iter_mut() {
if limit < ch.len() {
ch.truncate(limit);
}
}
}
fn from_floats(floats :Vec<Vec<f32>>) -> Self {
floats.into_iter()
.map(|samples| {
samples.into_iter()
.map(S::from_float)
.collect()
}).collect()
}
}
/// A packet of multi-channel interleaved samples
pub struct InterleavedSamples<S :Sample> {
pub samples :Vec<S>,
pub channel_count :usize,
}
impl<S :Sample> Samples for InterleavedSamples<S> {
fn num_samples(&self) -> usize {
self.samples.len() / self.channel_count
}
fn truncate(&mut self, limit :usize) {
self.samples.truncate(limit * self.channel_count);
}
fn from_floats(floats :Vec<Vec<f32>>) -> Self {
let channel_count = floats.len();
// Note that a channel count of 0 is forbidden
// by the spec and the header decoding code already
// checks for that.
assert!(floats.len() > 0);
let samples_interleaved = if channel_count == 1 {
// Because decoded_pck[0] doesn't work...
<Vec<Vec<S>> as Samples>::from_floats(floats).into_iter().next().unwrap()
} else {
let len = floats[0].len();
let mut samples = Vec::with_capacity(len * channel_count);
for i in 0 .. len {
for ref chan in floats.iter() {
samples.push(S::from_float(chan[i]));
}
}
samples
};
Self {
samples : samples_interleaved,
channel_count,
}
}
}
/// Trait representing a single sample
pub trait Sample {
fn from_float(fl :f32) -> Self;
}
impl Sample for f32 {
fn from_float(fl :f32) -> Self {
fl
}
}
impl Sample for i16 {
fn from_float(fl :f32) -> Self {
let fl = fl * 32768.0;
if fl > 32767. {
32767
} else if fl < -32768. {
-32768
} else {
fl as i16
}
}
}