use crate::bitpack::{BitReader, ByteReader};
use crate::error;
use crate::x3;
use error::X3Error;
fn estimate_total_length(num_samples: usize, compressed_len: usize, remaining_bytes: usize) -> usize {
const ESTIMATION_FACTOR: f32 = 1.5;
const WORD_SIZE: f32 = (x3::Parameters::WAV_BIT_SIZE / 8) as f32;
let compression_ratio = num_samples as f32 / compressed_len as f32;
(compression_ratio * remaining_bytes as f32 * ESTIMATION_FACTOR * WORD_SIZE).round() as usize
}
fn peek_first_frame(bytes: &mut ByteReader) -> Result<usize, X3Error> {
let (payload_samples, payload_size) = read_frame_header(bytes)?;
let remaining_bytes = bytes.remaining_bytes()?;
bytes.dec_counter(x3::FrameHeader::LENGTH)?;
let estimated_length = estimate_total_length(payload_samples, payload_size, remaining_bytes);
Ok(estimated_length)
}
fn find_next_frame(bytes: &mut ByteReader) -> Result<(), X3Error> {
bytes.inc_counter(1)?;
Ok(())
}
pub fn decode_frames(bytes: &mut ByteReader, params: &x3::Parameters) -> Result<Vec<i16>, X3Error> {
let estimated_length = peek_first_frame(bytes)?;
let mut wav: Vec<i16> = vec![0; estimated_length];
let mut p_wav = 0;
let mut total_samples_written = 0;
while bytes.remaining_bytes()? > x3::FrameHeader::LENGTH {
let mut samples_written = 0;
match decode_frame(bytes, &mut wav, ¶ms, &mut p_wav, &mut samples_written) {
Ok(()) => {}
Err(X3Error::FrameHeaderInvalidPayloadLen) => eprintln!("The final frame was not complete"),
Err(_) => match find_next_frame(bytes) {
Ok(()) => (),
Err(_) => eprintln!("An error occurred decoding a frame"),
},
};
total_samples_written += samples_written;
}
wav.resize(total_samples_written, 0);
Ok(wav)
}
pub fn decode_frame(
bytes: &mut ByteReader,
wav: &mut Vec<i16>,
params: &x3::Parameters,
p_wav: &mut usize,
samples_written: &mut usize,
) -> Result<(), X3Error> {
let (ns, payload_size) = read_frame_header(bytes)?;
#[cfg(not(feature = "oceaninstruments"))]
let mut last_wav = bytes.read_be_i16()?;
#[cfg(feature = "oceaninstruments")]
let mut last_wav = i32::from(bytes.read_le_i16()?);
wav[*p_wav] = last_wav as i16;
*p_wav += 1;
*samples_written += 1;
let br_payload_size = payload_size - 2;
let mut buf = &mut vec![0; br_payload_size];
bytes.read(&mut buf)?;
let br = &mut BitReader::new(&mut buf);
let mut remaining_samples = ns - 1;
while remaining_samples > 0 {
let block_len = core::cmp::min(remaining_samples, params.block_len);
let block_len = decode_block(br, &mut wav[*p_wav..(*p_wav + block_len)], &mut last_wav, ¶ms)?;
*samples_written += block_len;
remaining_samples -= block_len;
*p_wav += block_len;
}
Ok(())
}
#[cfg(not(feature = "oceaninstruments"))]
pub fn read_frame_header(bytes: &mut ByteReader) -> Result<(usize, usize), X3Error> {
if bytes.remaining_bytes()? < x3::FrameHeader::LENGTH {
return Err(X3Error::FrameDecodeUnexpectedEnd);
}
let expected_header_crc = bytes.crc16(x3::FrameHeader::HEADER_CRC_BYTE)?;
if !bytes.eq(x3::FrameHeader::KEY_BUF)? {
return Err(X3Error::FrameHeaderInvalidKey);
}
bytes.inc_counter(x3::FrameHeader::KEY_BUF.len())?;
bytes.inc_counter(1)?;
let num_channels = bytes.read_u8()?;
if num_channels > 1 {
return Err(X3Error::MoreThanOneChannel);
}
let num_samples = bytes.read_be_u16()? as usize;
let payload_len = bytes.read_be_u16()? as usize;
if payload_len >= x3::Frame::MAX_LENGTH {
return Err(X3Error::FrameLength);
}
bytes.inc_counter(8)?;
let header_crc = bytes.read_be_u16()?;
if expected_header_crc != header_crc {
return Err(X3Error::FrameHeaderInvalidHeaderCRC);
}
let payload_crc = bytes.read_be_u16()?;
if bytes.remaining_bytes()? < payload_len {
return Err(X3Error::FrameHeaderInvalidPayloadLen);
}
let expected_payload_crc = bytes.crc16(payload_len)?;
if expected_payload_crc != payload_crc {
return Err(X3Error::FrameHeaderInvalidPayloadCRC);
}
Ok((num_samples, payload_len))
}
#[cfg(feature = "oceaninstruments")]
pub fn read_frame_header(bytes: &mut ByteReader) -> Result<(usize, usize), X3Error> {
if bytes.remaining_bytes()? < x3::FrameHeader::LENGTH {
return Err(X3Error::FrameDecodeUnexpectedEnd);
}
let _expected_header_crc = bytes.crc16(x3::FrameHeader::HEADER_CRC_BYTE)?;
if !bytes.eq(x3::FrameHeader::KEY_BUF)? {
return Err(X3Error::FrameHeaderInvalidKey);
}
bytes.inc_counter(x3::FrameHeader::KEY_BUF.len())?;
bytes.inc_counter(1)?;
let num_channels = bytes.read_u8()?;
if num_channels > 1 {
return Err(X3Error::MoreThanOneChannel);
}
let payload_len = bytes.read_be_u16()? as usize * 2;
if payload_len >= x3::Frame::MAX_LENGTH {
return Err(X3Error::FrameLength);
}
let num_samples = bytes.read_be_u16()? as usize;
bytes.inc_counter(8)?;
bytes.inc_counter(2)?;
let _sample_rate = bytes.inc_counter(2)?;
let _header_crc = bytes.read_be_u16()?;
let _payload_crc = bytes.read_be_u16()?;
if bytes.remaining_bytes()? < payload_len {
return Err(X3Error::FrameHeaderInvalidPayloadLen);
}
let _expected_payload_crc = bytes.crc16(payload_len)?;
Ok((num_samples, payload_len))
}
pub fn move_to_next_frame(bytes: &mut ByteReader) -> Result<(), X3Error> {
bytes.inc_counter(1)?;
bytes.find_le_u16(x3::FrameHeader::KEY);
Ok(())
}
#[cfg(not(feature = "oceaninstruments"))]
pub fn decode_block(
br: &mut BitReader,
wav: &mut [i16],
last_wav: &mut i16,
params: &x3::Parameters,
) -> Result<usize, X3Error> {
let ftype = br.read_nbits(2)? as usize;
if ftype == 0 {
decode_bpf_block(br, wav, last_wav)
} else {
decode_ricecode_block(br, wav, last_wav, params, ftype)
}
}
#[cfg(not(feature = "oceaninstruments"))]
fn decode_ricecode_block(
br: &mut BitReader,
wav: &mut [i16],
last_wav: &mut i16,
params: &x3::Parameters,
ftype: usize,
) -> Result<usize, X3Error> {
let code = params.rice_codes[ftype - 1];
if ftype == 1 {
for wav_value in wav.iter_mut() {
let n = br.read_zero_bits()?;
br.read_nbits(1)?;
*last_wav += code.inv[n];
*wav_value = *last_wav;
}
} else if ftype == 2 || ftype == 3 {
let nb = if ftype == 2 { 2 } else { 4 };
let level = 1 << code.nsubs;
for wav_value in wav.iter_mut() {
let n = br.read_zero_bits()? as i16;
let r = br.read_nbits(nb)? as i16;
let i = r + level * (n - 1);
if i as usize >= code.inv_len {
return Err(X3Error::OutOfBoundsInverse);
}
let diff = code.inv[i as usize];
*last_wav += diff;
*wav_value = *last_wav;
}
}
Ok(wav.len())
}
fn unsigned_to_i16(a: u16, num_bits: usize) -> i16 {
let mut a = i32::from(a);
let neg_thresh = 1 << (num_bits - 1);
let neg = 1 << num_bits;
if a > neg_thresh {
a -= neg;
}
a as i16
}
#[cfg(not(feature = "oceaninstruments"))]
fn decode_bpf_block(br: &mut BitReader, wav: &mut [i16], last_wav: &mut i16) -> Result<usize, X3Error> {
let num_bits = (br.read_nbits(4)? + 1) as usize;
if num_bits <= 5 {
return Err(X3Error::FrameDecodeInvalidBPF);
}
if num_bits == 16 {
for wav_value in wav.iter_mut() {
*wav_value = br.read_nbits(16)? as i16;
}
} else {
let mut value = *last_wav;
for wav_value in wav.iter_mut() {
let diff = br.read_nbits(num_bits)?;
value += unsigned_to_i16(diff, num_bits);
*wav_value = value as i16;
}
}
*last_wav = wav[wav.len() - 1];
Ok(wav.len())
}
#[cfg(feature = "oceaninstruments")]
const RSUFFS: [usize; 3] = [0, 1, 3];
#[cfg(feature = "oceaninstruments")]
const IRT: &'static [i16; 60] = &[
0, -1, 1, -2, 2, -3, 3, -4, 4, -5, 5, -6, 6, -7, 7, -8, 8, -9, 9, -10, 10, -11, 11, -12, 12, -13, 13, -14, 14, -15,
15, -16, 16, -17, 17, -18, 18, -19, 19, -20, 20, -21, 21, -22, 22, -23, 23, -24, 24, -25, 25, -26, 26, -27, 27, -28,
28, -29, 29, -30,
];
#[cfg(feature = "oceaninstruments")]
fn unpackr(br: &mut BitReader, wav: &mut [i16], n: usize, code: usize) -> Result<(), X3Error> {
let mut ow = 0;
let mut msk;
let mut ntogo = 0;
let mut ns;
let mut suff;
let nsuffix = RSUFFS[code];
let lev = 1 << nsuffix;
for k in 0..n {
ntogo = br.read_int_larger_than(lev, &mut ow)?;
ns = 1;
msk = 1 << (ntogo - 1);
while ns <= ntogo && (ow & msk) == 0 {
ns += 1;
msk >>= 1;
}
if ns > ntogo {
return Err(X3Error::FrameDecodeInvalidRiceCode);
}
ntogo -= ns + nsuffix;
suff = (ow >> ntogo) & (lev - 1);
ow &= (1 << ntogo) - 1;
let idx = lev * (ns - 1) + suff;
if idx >= IRT.len() {
return Err(X3Error::FrameDecodeInvalidIndex);
}
wav[k] = IRT[idx];
}
if ntogo > 0 {
return Err(X3Error::FrameDecodeInvalidNTOGO);
}
Ok(())
}
#[cfg(feature = "oceaninstruments")]
fn integrate(wav: &mut [i16], last_wav: &mut i32, count: usize) {
for k in 0..count {
*last_wav += i32::from(wav[k]);
wav[k] = *last_wav as i16;
}
}
#[cfg(feature = "oceaninstruments")]
fn unpack(br: &mut BitReader, wav: &mut [i16], nb: usize, count: usize) -> Result<(), X3Error> {
for i in 0..count {
wav[i] = unsigned_to_i16(br.read_nbits(nb)?, nb);
}
Ok(())
}
#[cfg(feature = "oceaninstruments")]
pub fn decode_block(
br: &mut BitReader,
wav: &mut [i16],
last_wav: &mut i32,
_params: &x3::Parameters,
) -> Result<usize, X3Error> {
let mut nb = 0;
let mut code = br.read_nbits(2)?;
let mut count = wav.len();
if code == 0 {
nb = br.read_nbits(4)?;
if nb > 0 {
nb += 1;
} else {
let nn = (br.read_nbits(6)? + 1) as usize;
if nn > wav.len() {
return Err(X3Error::FrameDecodeInvalidBlockLength);
}
count = nn;
code = br.read_nbits(2)?;
if code == 0 {
nb = br.read_nbits(4)? + 1;
}
}
}
if code > 0 {
unpackr(br, wav, count as usize, (code - 1) as usize)?;
} else {
unpack(br, wav, nb as usize, count)?;
if nb == 16 {
return Ok(count);
}
}
integrate(wav, last_wav, wav.len());
Ok(count)
}
#[cfg(not(feature = "oceaninstruments"))]
#[cfg(test)]
mod tests {
use crate::bitpack::BitReader;
use crate::byteorder::{BigEndian, ByteOrder};
use crate::decoder::decode_block;
use crate::x3;
#[test]
fn test_decode_block_ftype_1() {
let x3_inp: &mut [u8] = &mut [
0x01, 0x10, 0x23, 0x18, 0x14, 0x90, 0x40, 0x82, 0x58, 0x41, 0x02, 0x0C, 0x4C,
];
let wav: &mut [i16] = &mut [0i16; 20];
let expected_wavput = [
-375, -372, -374, -374, -376, -376, -373, -374, -373, -372, -375, -372, -375, -374, -375, -375, -373, -376, -373,
];
let mut last_wav = -373;
let mut br = BitReader::new(x3_inp);
let params = &x3::Parameters::default();
br.read_nbits(6).unwrap();
decode_block(&mut br, wav, &mut last_wav, params).unwrap();
assert_eq!(expected_wavput, &mut wav[0..expected_wavput.len()]);
}
#[test]
fn test_decode_block_ftype_2() {
let x3_inp: &mut [u8] = &mut [
0xf2, 0x76, 0xb1, 0x82, 0x14, 0xd0, 0x4, 0x4, 0x58, 0x18, 0x30, 0x20, 0x69, 0x86, 0x4, 0xfc, 0xc2, 0xf8, 0xaa,
0x7f, 0xa1, 0xa, 0xfa, 0xad, 0xbc, 0x9d, 0x8d, 0x13, 0xc9, 0x66, 0xea, 0x5, 0xa3, 0x63, 0x94, 0xc9, 0xf4, 0x88,
0x4e, 0xb3, 0x6, 0xc9, 0xdb, 0x8f, 0x70, 0x80, 0xb3, 0x8b, 0x6b, 0x14, 0x88, 0x5f, 0x6c, 0x2f, 0xaa, 0x5a, 0xae,
0xf4, 0x29, 0x46, 0xd9, 0x12, 0x43, 0x4b, 0x4f, 0xd6, 0xeb, 0x24, 0xa8, 0x48, 0xc6, 0x3d, 0x1a, 0xb8, 0x71, 0x72,
0xb5, 0x68, 0xb4, 0x5b, 0xa1, 0x7c, 0xb2, 0x48, 0x5f, 0x67, 0xd9, 0x1b, 0x65, 0x0,
];
let wav: &mut [i16] = &mut [0i16; 20];
let expected_wavput = [
-3467, -3471, -3466, -3463, -3463, -3465, -3464, -3456, -3450, -3448, -3449, -3456, -3462, -3456, -3462, -3461,
-3463, -3468, -3462,
];
let mut last_wav = BigEndian::read_i16(&x3_inp[0..2]);
let mut br = BitReader::new(&mut x3_inp[2..]);
let params = &x3::Parameters::default();
decode_block(&mut br, wav, &mut last_wav, params).unwrap();
assert_eq!(expected_wavput, &mut wav[0..expected_wavput.len()]);
}
#[test]
fn test_decode_block_ftype_3() {
let x3_inp: &mut [u8] = &mut [242, 123, 202, 56, 106, 202, 124, 8, 122, 249, 136, 173, 202, 23, 80];
let wav: &mut [i16] = &mut [0i16; 20];
let expected_wavput = [
-3452, -3441, -3456, -3462, -3453, -3461, -3461, -3449, -3457, -3463, -3460, -3454, -3450, -3449, -3452, -3450,
-3449, -3463, -3462,
];
let mut last_wav = BigEndian::read_i16(&x3_inp[0..2]);
let mut br = BitReader::new(&mut x3_inp[2..]);
let params = &x3::Parameters::default();
decode_block(&mut br, wav, &mut last_wav, params).unwrap();
assert_eq!(expected_wavput, &mut wav[0..expected_wavput.len()]);
}
#[test]
fn test_decode_block_bpf_eq16() {
let x3_inp: &mut [u8] = &mut [
129, 171, 62, 250, 4, 71, 75, 230, 252, 150, 153, 97, 24, 220, 83, 53, 143, 92, 101, 211, 155, 34, 73, 241, 221,
200, 202, 252, 149, 240, 72, 20, 156, 172, 146, 59, 245, 23, 131, 33, 100, 0,
];
let wav: &mut [i16] = &mut [0i16; 19];
let expected_wavput = [
-16767, 4562, -1601, 9638, 22598, 14100, -12957, -10471, 29926, -14190, 31863, 29234, -16603, 31762, 1319, 11044,
-28931, 17888, -14247,
];
let mut last_wav = BigEndian::read_i16(&x3_inp[0..2]);
let mut br = BitReader::new(&mut x3_inp[2..]);
let params = &x3::Parameters::default();
decode_block(&mut br, wav, &mut last_wav, params).unwrap();
assert_eq!(expected_wavput, &mut wav[0..expected_wavput.len()]);
}
#[test]
fn test_decode_block_bpf_lt16() {
let x3_inp: &mut [u8] = &mut [
242, 73, 24, 151, 240, 252, 191, 163, 225, 164, 48, 158, 196, 188, 251, 246, 20, 31, 240, 96,
];
let wav: &mut [i16] = &mut [0i16; 19];
let expected_wavput = [
-3493, -3494, -3487, -3501, -3502, -3467, -3483, -3506, -3500, -3491, -3501, -3483, -3490, -3495, -3500, -3495,
-3492, -3493, -3490,
];
let mut last_wav = BigEndian::read_i16(&x3_inp[0..2]);
let mut br = BitReader::new(&mut x3_inp[2..]);
let params = &x3::Parameters::default();
decode_block(&mut br, wav, &mut last_wav, params).unwrap();
assert_eq!(expected_wavput, &mut wav[0..expected_wavput.len()]);
}
}