use std::io::{Read, Result, Write};
use std::vec::Vec;
use crate::codecs::g729::impls::bitstream::itu_params::{BITSNO, BITSNO2};
pub const SYNC_WORD: u16 = 0x6B21;
pub const BIT_0: u16 = 0x007F;
pub const BIT_1: u16 = 0x0081;
pub const RATE_8000: i16 = 80;
pub const RATE_SID: i16 = 15;
pub const RATE_SID_OCTET: i16 = 16;
pub const RATE_0: i16 = 0;
pub fn frame_to_words(payload: &[u8], n_bits: usize) -> Vec<u16> {
let mut out = Vec::with_capacity(2 + n_bits);
out.push(SYNC_WORD);
out.push(n_bits as u16);
for i in 0..n_bits {
let byte = payload.get(i / 8).copied().unwrap_or(0);
let bit = (byte >> (7 - (i % 8))) & 1;
out.push(if bit == 1 { BIT_1 } else { BIT_0 });
}
out
}
pub fn words_to_frame(words: &[u16], n_bits: usize) -> Vec<u8> {
let mut out = vec![0u8; n_bits.div_ceil(8)];
for i in 0..n_bits {
let word = words.get(i).copied().unwrap_or(BIT_0);
let bit = if word == BIT_1 || word == 1 { 1u8 } else { 0u8 };
out[i / 8] |= bit << (7 - (i % 8));
}
out
}
pub fn parse_stream(raw: &[u8]) -> Vec<(u16, Vec<u16>)> {
let mut words = Vec::with_capacity(raw.len() / 2);
for chunk in raw.chunks_exact(2) {
words.push(u16::from_le_bytes([chunk[0], chunk[1]]));
}
let mut frames = Vec::new();
let mut idx = 0usize;
while idx + 1 < words.len() {
let sync = words[idx];
let size = words[idx + 1] as usize;
idx += 2;
if idx + size > words.len() {
break;
}
frames.push((sync, words[idx..idx + size].to_vec()));
idx += size;
}
frames
}
pub fn serialize_stream(frames: &[(u16, Vec<u16>)]) -> Vec<u8> {
let mut out = Vec::new();
for (sync, bits) in frames {
out.extend_from_slice(&sync.to_le_bytes());
out.extend_from_slice(&(bits.len() as u16).to_le_bytes());
for bit in bits {
out.extend_from_slice(&bit.to_le_bytes());
}
}
out
}
pub fn read_serial_frame<R: Read>(reader: &mut R, parm: &mut [i16], bfi: &mut i16) -> Result<i16> {
let sync = match read_i16_le(reader) {
Ok(v) => v,
Err(e) if e.kind() == std::io::ErrorKind::UnexpectedEof => return Ok(0),
Err(e) => return Err(e),
};
let size = match read_i16_le(reader) {
Ok(v) => v,
Err(e) if e.kind() == std::io::ErrorKind::UnexpectedEof => return Ok(0),
Err(e) => return Err(e),
};
let num_bits = size as usize;
let mut serial = [0i16; 82];
serial[0] = size;
for i in 0..num_bits {
serial[i + 1] = read_i16_le(reader)?;
}
bits2prm_ld8k_full(&serial, parm);
parm[0] = 0;
if size != 0 {
for i in 0..num_bits {
if serial[i + 1] == 0 {
parm[0] = 1;
break;
}
}
} else if sync != SYNC_WORD as i16 {
parm[0] = 1;
}
*bfi = parm[0];
Ok(1)
}
pub fn write_serial_frame<W: Write>(writer: &mut W, parm: &[i16], frame_size: i16) -> Result<()> {
write_i16_le(writer, SYNC_WORD as i16)?;
write_i16_le(writer, frame_size)?;
if frame_size == RATE_8000 {
let mut bits = [0i16; 80];
let mut bit_offset = 0usize;
for i in 0..11 {
let nbits = BITSNO[i] as usize;
int2bin_local(parm[i], BITSNO[i], &mut bits[bit_offset..]);
bit_offset += nbits;
}
for bit in bits {
write_i16_le(writer, bit)?;
}
} else if frame_size == RATE_SID || frame_size == RATE_SID_OCTET {
let mut bits = [BIT_0 as i16; 16];
let mut bit_offset = 0usize;
for i in 0..4 {
let nbits = BITSNO2[i] as usize;
int2bin_local(parm[i], BITSNO2[i], &mut bits[bit_offset..]);
bit_offset += nbits;
}
for bit in bits.iter().take(frame_size as usize) {
write_i16_le(writer, *bit)?;
}
}
Ok(())
}
fn bits2prm_ld8k_full(serial: &[i16], parm: &mut [i16]) {
let nb_bits = serial[0];
if nb_bits == RATE_8000 {
parm[1] = 1;
let mut bit_offset = 1usize;
for i in 0..11 {
parm[i + 2] = bin2int_local(BITSNO[i], &serial[bit_offset..]);
bit_offset += BITSNO[i] as usize;
}
} else if nb_bits == RATE_SID || nb_bits == RATE_SID_OCTET {
parm[1] = 2;
let mut bit_offset = 1usize;
for i in 0..4 {
parm[i + 2] = bin2int_local(BITSNO2[i], &serial[bit_offset..]);
bit_offset += BITSNO2[i] as usize;
}
} else {
parm[1] = 0;
}
}
fn bin2int_local(n_bits: u8, bits: &[i16]) -> i16 {
let mut value = 0i16;
for bit in bits.iter().take(n_bits as usize) {
value <<= 1;
if *bit == BIT_1 as i16 {
value += 1;
}
}
value
}
fn int2bin_local(value: i16, n_bits: u8, bits: &mut [i16]) {
let mut v = value;
for i in (0..n_bits as usize).rev() {
bits[i] = if (v & 1) == 0 {
BIT_0 as i16
} else {
BIT_1 as i16
};
v >>= 1;
}
}
fn read_i16_le<R: Read>(reader: &mut R) -> Result<i16> {
let mut buf = [0u8; 2];
reader.read_exact(&mut buf)?;
Ok(i16::from_le_bytes(buf))
}
fn write_i16_le<W: Write>(writer: &mut W, value: i16) -> Result<()> {
writer.write_all(&value.to_le_bytes())
}
#[cfg(test)]
#[path = "itu_serial_tests.rs"]
mod tests;