#![allow(clippy::unwrap_used, clippy::expect_used)]
use super::asc::AudioSpecificConfig;
use super::bits::{BitReader, BitWriter};
use super::channel_map::{ElemKind, Element, PlaneMap, map_planes, mono_mix, parse_pce};
use super::decode::StreamDecoder;
use super::error::Error;
use super::huff_quad::{H1_CODE, H1_LEN};
const AUDIBLE_GAIN: u8 = 188;
fn quad_idx(w: i32, x: i32, y: i32, z: i32) -> usize {
((w + 1) * 27 + (x + 1) * 9 + (y + 1) * 3 + (z + 1)) as usize
}
fn write_ics_line(w: &mut BitWriter, line_sfb: u8) {
let max_sfb = line_sfb + 1;
w.write(u32::from(AUDIBLE_GAIN), 8);
w.write_bit(false); w.write(0, 2); w.write_bit(false); w.write(u32::from(max_sfb), 6);
w.write_bit(false); w.write(1, 4); w.write(u32::from(max_sfb), 5); for _ in 0..max_sfb {
w.write(0, 1); }
w.write_bit(false); w.write_bit(false); w.write_bit(false); for b in 0..max_sfb {
let idx = if b == line_sfb {
quad_idx(0, 0, 0, 1)
} else {
quad_idx(0, 0, 0, 0)
};
w.write(u32::from(H1_CODE[idx]), u32::from(H1_LEN[idx]));
}
}
fn write_sce(w: &mut BitWriter, tag: u8, line_sfb: u8) {
w.write(0, 3); w.write(u32::from(tag), 4);
write_ics_line(w, line_sfb);
}
fn write_lfe(w: &mut BitWriter, tag: u8, line_sfb: u8) {
w.write(3, 3); w.write(u32::from(tag), 4);
write_ics_line(w, line_sfb);
}
fn write_cpe(w: &mut BitWriter, tag: u8, line_l: u8, line_r: u8) {
w.write(1, 3); w.write(u32::from(tag), 4);
w.write_bit(false); write_ics_line(w, line_l);
write_ics_line(w, line_r);
}
fn write_cce_stub(w: &mut BitWriter) {
w.write(2, 3); w.write(0, 4); w.write_bit(false); w.write(0, 3); w.write_bit(false); w.write(0, 2); w.write_bit(false); w.write(0, 4); w.write(128, 8); w.write_bit(false); w.write(0, 2); w.write_bit(false); w.write(0, 6); w.write_bit(false); w.write_bit(false); w.write_bit(false); w.write_bit(false); }
fn write_pce(w: &mut BitWriter, front: &[(bool, u8)], back: &[(bool, u8)], lfe: &[u8]) {
w.write(5, 3); w.write(0, 4); w.write(0, 2); w.write(3, 4); w.write(front.len() as u32, 4);
w.write(0, 4); w.write(back.len() as u32, 4);
w.write(lfe.len() as u32, 2);
w.write(0, 3); w.write(0, 4); w.write_bit(false); w.write_bit(false); w.write_bit(false); for &(is_cpe, tag) in front {
w.write_bit(is_cpe);
w.write(u32::from(tag), 4);
}
for &(is_cpe, tag) in back {
w.write_bit(is_cpe);
w.write(u32::from(tag), 4);
}
for &tag in lfe {
w.write(u32::from(tag), 4);
}
let written =
3 + 4 + 2 + 4 + 4 + 4 + 4 + 2 + 3 + 4 + 3 + 5 * (front.len() + back.len()) + 4 * lfe.len();
let pad = (8 - written % 8) % 8;
for _ in 0..pad {
w.write_bit(false);
}
w.write(0, 8); }
fn sce_payload(tag: u8, line_sfb: u8) -> Vec<u8> {
let mut w = BitWriter::new();
write_sce(&mut w, tag, line_sfb);
w.write(7, 3); w.finish()
}
fn cpe_payload(tag: u8, line_l: u8, line_r: u8) -> Vec<u8> {
let mut w = BitWriter::new();
write_cpe(&mut w, tag, line_l, line_r);
w.write(7, 3);
w.finish()
}
fn lfe_payload(tag: u8, line_sfb: u8) -> Vec<u8> {
let mut w = BitWriter::new();
write_lfe(&mut w, tag, line_sfb);
w.write(7, 3);
w.finish()
}
fn decode_planes(payload: &[u8], config: u8) -> Result<Vec<Vec<f32>>, Error> {
let mut dec = StreamDecoder::new();
let frame = dec.decode_raw_data_block(2, 3, 48_000, config, 1, payload)?;
Ok(frame.planar)
}
#[test]
fn parse_pce_reads_front_back_lfe_lists() -> Result<(), Error> {
let mut w = BitWriter::new();
write_pce(&mut w, &[(false, 5), (true, 2)], &[(true, 1)], &[0]);
let bytes = w.finish();
let mut br = BitReader::new(&bytes);
let _id = br.read(3)?;
let pce = parse_pce(&mut br)?;
assert_eq!(pce.front, vec![(false, 5), (true, 2)]);
assert_eq!(pce.back, vec![(true, 1)]);
assert_eq!(pce.lfe, vec![0]);
Ok(())
}
#[test]
fn asc_channel_configuration_zero_parses() -> Result<(), Error> {
let mut w = BitWriter::new();
w.write(2, 5); w.write(3, 4); w.write(0, 4); w.write(0, 3); let (asc, _) = AudioSpecificConfig::parse(&w.finish())?;
assert_eq!(asc.channel_configuration, 0);
assert_eq!(asc.sample_rate, 48_000);
Ok(())
}
fn el(kind: ElemKind, tag: u8, plane: usize) -> Element {
Element { kind, tag, plane }
}
fn srcs(order: &[PlaneMap]) -> Vec<Option<usize>> {
order.iter().map(|p| p.src).collect()
}
#[test]
fn default_config_6_maps_to_lavc_5_1_order() {
let elems = [
el(ElemKind::Sce, 0, 0),
el(ElemKind::Cpe, 0, 1),
el(ElemKind::Cpe, 1, 3),
el(ElemKind::Lfe, 0, 5),
];
let order = map_planes(&elems, None, 6);
assert_eq!(
srcs(&order),
vec![Some(1), Some(2), Some(0), Some(5), Some(3), Some(4)]
);
let lfe: Vec<bool> = order.iter().map(|p| p.lfe).collect();
assert_eq!(lfe, vec![false, false, false, true, false, false]);
}
#[test]
fn default_configs_3_to_5_map_to_lavc_layouts() {
let elems = [
el(ElemKind::Sce, 0, 0),
el(ElemKind::Cpe, 0, 1),
el(ElemKind::Sce, 1, 3),
];
assert_eq!(
srcs(&map_planes(&elems[..2], None, 3)),
vec![Some(1), Some(2), Some(0)]
);
assert_eq!(
srcs(&map_planes(&elems, None, 4)),
vec![Some(1), Some(2), Some(0), Some(3)]
);
let elems5 = [
el(ElemKind::Sce, 0, 0),
el(ElemKind::Cpe, 0, 1),
el(ElemKind::Cpe, 1, 3),
];
assert_eq!(
srcs(&map_planes(&elems5, None, 5)),
vec![Some(1), Some(2), Some(0), Some(3), Some(4)]
);
}
#[test]
fn missing_element_maps_to_silence_extra_keeps_audio() {
let elems = [
el(ElemKind::Sce, 0, 0),
el(ElemKind::Cpe, 0, 1),
el(ElemKind::Cpe, 1, 3),
el(ElemKind::Sce, 7, 5),
];
let order = map_planes(&elems, None, 6);
assert_eq!(
srcs(&order),
vec![Some(1), Some(2), Some(0), None, Some(3), Some(4), Some(5)]
);
}
#[test]
fn mono_mix_is_mean_of_non_lfe_planes() {
let planes = vec![vec![1.0f32; 4], vec![3.0; 4], vec![5.0; 4]];
let order = [
PlaneMap {
src: Some(0),
lfe: false,
},
PlaneMap {
src: Some(1),
lfe: false,
},
PlaneMap {
src: Some(2),
lfe: true,
},
];
assert_eq!(mono_mix(&planes, &order), vec![2.0; 4]);
let all_lfe = [
PlaneMap {
src: Some(0),
lfe: true,
},
PlaneMap {
src: Some(1),
lfe: true,
},
];
assert_eq!(mono_mix(&planes[..2], &all_lfe), vec![2.0; 4]);
}
#[test]
fn pce_declaration_order_overrides_element_order() -> Result<(), Error> {
let ref_sce5 = decode_planes(&sce_payload(5, 1), 1)?;
let ref_cpe2 = decode_planes(&cpe_payload(2, 3, 5), 2)?;
let ref_cpe1 = decode_planes(&cpe_payload(1, 6, 8), 2)?;
let ref_lfe0 = decode_planes(&lfe_payload(0, 2), 1)?;
let mut w = BitWriter::new();
write_pce(&mut w, &[(false, 5), (true, 2)], &[(true, 1)], &[0]);
write_cpe(&mut w, 1, 6, 8);
write_lfe(&mut w, 0, 2);
write_sce(&mut w, 5, 1);
write_cpe(&mut w, 2, 3, 5);
w.write(7, 3); let planar = decode_planes(&w.finish(), 0)?;
let expect = [
&ref_sce5[0],
&ref_cpe2[0],
&ref_cpe2[1],
&ref_cpe1[0],
&ref_cpe1[1],
&ref_lfe0[0],
];
assert_eq!(planar.len(), expect.len(), "PCE plane count");
for (i, (got, want)) in planar.iter().zip(expect.iter()).enumerate() {
assert_eq!(got, *want, "plane {i} must follow PCE declaration order");
}
Ok(())
}
#[test]
fn cce_between_channels_does_not_corrupt_them() -> Result<(), Error> {
let ref_a = decode_planes(&sce_payload(0, 1), 1)?;
let ref_b = decode_planes(&sce_payload(1, 3), 1)?;
let mut w = BitWriter::new();
write_sce(&mut w, 0, 1);
write_cce_stub(&mut w);
write_sce(&mut w, 1, 3);
w.write(7, 3);
let planar = decode_planes(&w.finish(), 0)?;
assert_eq!(planar.len(), 2, "CCE must not emit a plane");
assert_eq!(planar[0], ref_a[0], "channel before CCE corrupted");
assert_eq!(planar[1], ref_b[0], "channel after CCE corrupted");
Ok(())
}