use crate::error::X3Error;
pub struct Decoder<'a> {
pub channels: &'a [Channel<'a>],
pub x3_inp: &'a mut [u8],
}
pub struct Channel<'a> {
pub id: u16,
pub wav: &'a [i16],
pub sample_rate: u32,
pub params: Parameters,
}
impl<'a> Channel<'a> {
pub fn new(id: u16, wav: &'a [i16], sample_rate: u32, params: Parameters) -> Self {
Channel {
id,
wav,
sample_rate,
params,
}
}
}
pub struct X3aSpec {
pub sample_rate: u32,
pub params: Parameters,
pub channels: u8,
}
pub struct Parameters {
pub block_len: usize,
pub blocks_per_frame: usize,
pub codes: [usize; 3],
pub thresholds: [usize; 3],
pub rice_codes: [&'static RiceCode; 3],
}
impl Parameters {
pub const MAX_BLOCK_LENGTH: usize = 60;
pub const WAV_BIT_SIZE: usize = 16;
pub const DEFAULT_BLOCK_LENGTH: usize = 20;
pub const DEFAULT_RICE_CODES: [usize; 3] = [0, 1, 3];
pub const DEFAULT_THRESHOLDS: [usize; 3] = [3, 8, 20];
pub const DEFAULT_BLOCKS_PER_FRAME: usize = 500;
pub fn new(
block_len: usize,
blocks_per_frame: usize,
codes: [usize; 3],
thresholds: [usize; 3],
) -> Result<Self, X3Error> {
let rice_codes = RiceCodes::get(codes);
for k in 0..2 {
let rc = rice_codes[k];
if thresholds[k] > rc.offset {
return Err(X3Error::InvalidEncodingThresh);
}
}
Ok(Parameters {
block_len,
blocks_per_frame,
codes,
thresholds,
rice_codes,
})
}
pub fn default() -> Self {
Parameters {
block_len: Self::DEFAULT_BLOCK_LENGTH,
blocks_per_frame: Self::DEFAULT_BLOCKS_PER_FRAME,
codes: Self::DEFAULT_RICE_CODES,
thresholds: Self::DEFAULT_THRESHOLDS,
rice_codes: RiceCodes::get(Self::DEFAULT_RICE_CODES),
}
}
}
pub struct Archive {}
impl Archive {
pub const ID: &'static [u8] = &[0x58, 0x33, 0x41, 0x52, 0x43, 0x48, 0x49, 0x56];
pub const ID_LEN: usize = 8;
}
pub struct Frame {}
impl Frame {
pub const MAX_LENGTH: usize = 0x7fe0;
}
pub struct FrameHeader {
pub source_id: u8,
pub samples: u16,
pub channels: u8,
pub payload_len: usize,
pub payload_crc: u16,
}
impl FrameHeader {
pub const LENGTH: usize = 20;
pub const KEY: u16 = 30771;
pub const KEY_BUF: &'static [u8] = &[0x78, 0x33];
pub const P_KEY: usize = 0;
pub const P_SOURCE_ID: usize = 2;
pub const P_CHANNELS: usize = 3;
pub const P_SAMPLES: usize = 4;
pub const P_PAYLOAD_SIZE: usize = 6;
pub const P_TIME: usize = 8;
pub const P_HEADER_CRC: usize = 16;
pub const P_PAYLOAD_CRC: usize = 18;
}
#[allow(dead_code)]
pub struct RiceCode {
pub nsubs: usize,
pub offset: usize,
pub code: &'static [usize],
pub num_bits: &'static [usize],
pub inv: &'static [i16],
pub inv_len: usize,
}
pub struct RiceCodes {}
const INV_RICE_CODE: &[i16] = &[
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,
];
impl RiceCodes {
const CODE: [RiceCode; 4] = [
RiceCode {
nsubs: 0,
offset: 6,
code: &[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
num_bits: &[12, 10, 8, 6, 4, 2, 1, 3, 5, 7, 9, 11, 13, 15],
inv: INV_RICE_CODE,
inv_len: 16,
},
RiceCode {
nsubs: 1,
offset: 11,
code: &[3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],
num_bits: &[12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
inv: INV_RICE_CODE,
inv_len: 26,
},
RiceCode {
nsubs: 2,
offset: 20,
code: &[
7, 5, 7, 5, 7, 5, 7, 5, 7, 5, 7, 5, 7, 5, 7, 5, 7, 5, 7, 5, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4, 6, 4,
6, 4, 6,
],
num_bits: &[
12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10,
10, 11, 11, 12, 12,
],
inv: INV_RICE_CODE,
inv_len: 44,
},
RiceCode {
nsubs: 3,
offset: 28,
code: &[
15, 13, 11, 9, 15, 13, 11, 9, 15, 13, 11, 9, 15, 13, 11, 9, 15, 13, 11, 9, 15, 13, 11, 9, 15, 13, 11, 9, 8, 10,
12, 14, 8, 10, 12, 14, 8, 10, 12, 14, 8, 10, 12, 14, 8, 10, 12, 14, 8, 10, 12, 14, 8, 10, 12, 14,
],
num_bits: &[
10, 10, 10, 10, 9, 9, 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5,
6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10,
],
inv: INV_RICE_CODE,
inv_len: 60,
},
];
pub fn get(code_list: [usize; 3]) -> [&'static RiceCode; 3] {
[
&RiceCodes::CODE[code_list[0]],
&RiceCodes::CODE[code_list[1]],
&RiceCodes::CODE[code_list[2]],
]
}
}