use crate::types::Msf;
pub fn swap_audio_endianness(data: &mut [u8]) {
let (chunks, _) = data.as_chunks_mut::<2>();
for chunk in chunks {
chunk.swap(0, 1);
}
}
pub fn compute_subcode_crc(data: &[u8]) -> u16 {
let mut crc: u16 = 0;
for &b in data {
let mut byte = b;
for _ in 0..8 {
let bit = ((byte >> 7) & 1) as u16;
let crc_bit = (crc >> 15) & 1;
crc <<= 1;
if bit ^ crc_bit != 0 {
crc ^= 0x1021;
}
byte <<= 1;
}
}
!crc
}
#[inline]
pub fn to_bcd(val: u8) -> u8 {
((val / 10) << 4) | (val % 10)
}
pub fn generate_q_subcode(
ctl_adr: u8,
track_num: u8,
index: u8,
rel_lba: u32,
abs_lba: u32,
) -> [u8; 12] {
let rel_msf = Msf::from_lba(rel_lba);
let abs_msf = Msf::from_lba(abs_lba);
let mut q = [0u8; 12];
q[0] = ctl_adr;
q[1] = to_bcd(track_num);
q[2] = to_bcd(index);
q[3] = to_bcd(rel_msf.m);
q[4] = to_bcd(rel_msf.s);
q[5] = to_bcd(rel_msf.f);
q[6] = 0x00;
q[7] = to_bcd(abs_msf.m);
q[8] = to_bcd(abs_msf.s);
q[9] = to_bcd(abs_msf.f);
let crc = compute_subcode_crc(&q[0..10]);
q[10] = (crc >> 8) as u8;
q[11] = crc as u8;
q
}
pub fn deinterleave_subcode(frame_subcode: &[u8; 96], channels: &mut [[u8; 12]; 8]) {
for ch in channels.iter_mut() {
ch.fill(0);
}
for (i, &byte) in frame_subcode.iter().enumerate() {
let byte_idx = i / 8;
let bit_shift = 7 - (i % 8);
for (c, ch) in channels.iter_mut().enumerate() {
let bit = (byte >> (7 - c)) & 1;
ch[byte_idx] |= bit << bit_shift;
}
}
}
pub fn interleave_subcode(channels: &[[u8; 12]; 8], frame_subcode: &mut [u8; 96]) {
frame_subcode.fill(0);
for (i, byte) in frame_subcode.iter_mut().enumerate() {
let byte_idx = i / 8;
let bit_shift = 7 - (i % 8);
let mut out_byte = 0u8;
for (c, ch) in channels.iter().enumerate() {
let bit = (ch[byte_idx] >> bit_shift) & 1;
out_byte |= bit << (7 - c);
}
*byte = out_byte;
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_swap_audio_endianness() {
let mut data = vec![0x12, 0x34, 0x56, 0x78];
swap_audio_endianness(&mut data);
assert_eq!(data, vec![0x34, 0x12, 0x78, 0x56]);
}
#[test]
fn test_subcode_interleave_roundtrip() {
let mut original = [0u8; 96];
for (i, b) in original.iter_mut().enumerate() {
*b = (i as u8).wrapping_mul(31);
}
let mut channels = [[0u8; 12]; 8];
deinterleave_subcode(&original, &mut channels);
let mut reconstructed = [0u8; 96];
interleave_subcode(&channels, &mut reconstructed);
assert_eq!(original, reconstructed);
}
#[test]
fn test_q_subcode_crc() {
let q = generate_q_subcode(0x01, 1, 1, 0, 150);
let crc = compute_subcode_crc(&q[0..10]);
assert_eq!(q[10], (crc >> 8) as u8);
assert_eq!(q[11], crc as u8);
}
}