use crate::engine::bits::BitReader;
use crate::engine::{Error, Result};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FrameClass {
FixFix,
FixVar,
VarFix,
VarVar,
}
impl FrameClass {
fn from_bits(v: u32) -> Self {
match v & 0b11 {
0 => FrameClass::FixFix,
1 => FrameClass::FixVar,
2 => FrameClass::VarFix,
_ => FrameClass::VarVar,
}
}
#[cfg(test)]
pub fn to_bits(self) -> u32 {
match self {
FrameClass::FixFix => 0,
FrameClass::FixVar => 1,
FrameClass::VarFix => 2,
FrameClass::VarVar => 3,
}
}
}
pub const SBR_MAX_NUM_ENV: usize = 5;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SbrGrid {
pub frame_class: FrameClass,
pub num_env: usize,
pub num_noise: usize,
pub freq_res: Vec<bool>,
pub var_bord_0: u8,
pub var_bord_1: u8,
pub rel_bord_0: Vec<u8>,
pub rel_bord_1: Vec<u8>,
pub pointer: u32,
pub amp_res_override: bool,
}
fn ptr_bits(num_env: usize) -> u32 {
let n = (num_env + 1) as u32;
if n <= 1 {
0
} else {
let floor_log2 = 31 - n.leading_zeros();
if n.is_power_of_two() {
floor_log2
} else {
floor_log2 + 1
}
}
}
impl SbrGrid {
pub fn parse(reader: &mut BitReader<'_>) -> Result<Self> {
let frame_class = FrameClass::from_bits(read(reader, 2)?);
let mut var_bord_0 = 0u8;
let mut var_bord_1 = 0u8;
let mut rel_bord_0: Vec<u8> = Vec::new();
let mut rel_bord_1: Vec<u8> = Vec::new();
let mut pointer = 0u32;
let mut amp_res_override = false;
let (num_env, freq_res) = match frame_class {
FrameClass::FixFix => {
let raw = read(reader, 2)?;
let num_env = 1usize << raw; check_num_env(num_env)?;
if num_env == 1 {
amp_res_override = true; }
let fr0 = read_flag(reader)?;
let freq_res = vec![fr0; num_env];
(num_env, freq_res)
}
FrameClass::FixVar => {
var_bord_1 = read(reader, 2)? as u8;
let num_rel_1 = read(reader, 2)? as usize;
let num_env = num_rel_1 + 1;
check_num_env(num_env)?;
for _ in 0..num_env - 1 {
rel_bord_1.push(read(reader, 2)? as u8);
}
pointer = read(reader, ptr_bits(num_env))?;
let mut freq_res = vec![false; num_env];
for env in 0..num_env {
freq_res[num_env - 1 - env] = read_flag(reader)?;
}
(num_env, freq_res)
}
FrameClass::VarFix => {
var_bord_0 = read(reader, 2)? as u8;
let num_rel_0 = read(reader, 2)? as usize;
let num_env = num_rel_0 + 1;
check_num_env(num_env)?;
for _ in 0..num_env - 1 {
rel_bord_0.push(read(reader, 2)? as u8);
}
pointer = read(reader, ptr_bits(num_env))?;
let mut freq_res = Vec::with_capacity(num_env);
for _ in 0..num_env {
freq_res.push(read_flag(reader)?);
}
(num_env, freq_res)
}
FrameClass::VarVar => {
var_bord_0 = read(reader, 2)? as u8;
var_bord_1 = read(reader, 2)? as u8;
let num_rel_0 = read(reader, 2)? as usize;
let num_rel_1 = read(reader, 2)? as usize;
let num_env = num_rel_0 + num_rel_1 + 1;
check_num_env(num_env)?;
for _ in 0..num_rel_0 {
rel_bord_0.push(read(reader, 2)? as u8);
}
for _ in 0..num_rel_1 {
rel_bord_1.push(read(reader, 2)? as u8);
}
pointer = read(reader, ptr_bits(num_env))?;
let mut freq_res = Vec::with_capacity(num_env);
for _ in 0..num_env {
freq_res.push(read_flag(reader)?);
}
(num_env, freq_res)
}
};
let num_noise = if num_env > 1 { 2 } else { 1 };
Ok(SbrGrid {
frame_class,
num_env,
num_noise,
freq_res,
var_bord_0,
var_bord_1,
rel_bord_0,
rel_bord_1,
pointer,
amp_res_override,
})
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SbrDtdf {
pub df_env: Vec<bool>,
pub df_noise: Vec<bool>,
}
impl SbrDtdf {
pub fn parse(reader: &mut BitReader<'_>, num_env: usize, num_noise: usize) -> Result<Self> {
let mut df_env = Vec::with_capacity(num_env);
for _ in 0..num_env {
df_env.push(read_flag(reader)?);
}
let mut df_noise = Vec::with_capacity(num_noise);
for _ in 0..num_noise {
df_noise.push(read_flag(reader)?);
}
Ok(SbrDtdf { df_env, df_noise })
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SbrInvf {
pub invf_mode: Vec<u8>,
}
impl SbrInvf {
pub fn parse(reader: &mut BitReader<'_>, num_noise_bands: usize) -> Result<Self> {
let mut invf_mode = Vec::with_capacity(num_noise_bands);
for _ in 0..num_noise_bands {
invf_mode.push(read(reader, 2)? as u8);
}
Ok(SbrInvf { invf_mode })
}
}
#[inline]
fn read(reader: &mut BitReader<'_>, n: u32) -> Result<u32> {
reader.read_u32(n).map_err(|_| Error::SbrGridInvalid)
}
#[inline]
fn read_flag(reader: &mut BitReader<'_>) -> Result<bool> {
reader.read_bit().map_err(|_| Error::SbrGridInvalid)
}
#[inline]
fn check_num_env(num_env: usize) -> Result<()> {
if num_env == 0 || num_env > SBR_MAX_NUM_ENV {
Err(Error::SbrGridInvalid)
} else {
Ok(())
}
}
#[cfg(test)]
mod tests {
#![allow(clippy::unwrap_used, clippy::expect_used)]
use super::*;
use crate::engine::bits::BitWriter;
#[test]
fn ptr_bits_matches_ceil_log2() {
assert_eq!(ptr_bits(1), 1); assert_eq!(ptr_bits(2), 2); assert_eq!(ptr_bits(3), 2); assert_eq!(ptr_bits(4), 3); assert_eq!(ptr_bits(5), 3); }
#[test]
fn fixfix_single_env_forces_amp_res() {
let mut w = BitWriter::new();
w.write_u32(FrameClass::FixFix.to_bits(), 2);
w.write_u32(0, 2); w.write_bit(true); let bytes = w.finish();
let mut r = BitReader::new(&bytes);
let g = SbrGrid::parse(&mut r).unwrap();
assert_eq!(g.frame_class, FrameClass::FixFix);
assert_eq!(g.num_env, 1);
assert_eq!(g.num_noise, 1);
assert_eq!(g.freq_res, vec![true]);
assert!(g.amp_res_override);
}
#[test]
fn fixfix_four_env_shares_freq_res() {
let mut w = BitWriter::new();
w.write_u32(FrameClass::FixFix.to_bits(), 2);
w.write_u32(2, 2); w.write_bit(false); let bytes = w.finish();
let mut r = BitReader::new(&bytes);
let g = SbrGrid::parse(&mut r).unwrap();
assert_eq!(g.num_env, 4);
assert_eq!(g.num_noise, 2);
assert_eq!(g.freq_res, vec![false; 4]);
assert!(!g.amp_res_override);
}
#[test]
fn fixvar_reverses_freq_res() {
let mut w = BitWriter::new();
w.write_u32(FrameClass::FixVar.to_bits(), 2);
w.write_u32(1, 2); w.write_u32(2, 2); w.write_u32(0, 2); w.write_u32(3, 2); w.write_u32(1, 2); w.write_bit(true); w.write_bit(false); w.write_bit(true); let bytes = w.finish();
let mut r = BitReader::new(&bytes);
let g = SbrGrid::parse(&mut r).unwrap();
assert_eq!(g.frame_class, FrameClass::FixVar);
assert_eq!(g.num_env, 3);
assert_eq!(g.var_bord_1, 1);
assert_eq!(g.rel_bord_1, vec![0, 3]);
assert_eq!(g.pointer, 1);
assert_eq!(g.freq_res, vec![true, false, true]);
}
#[test]
fn varfix_forward_freq_res() {
let mut w = BitWriter::new();
w.write_u32(FrameClass::VarFix.to_bits(), 2);
w.write_u32(2, 2); w.write_u32(1, 2); w.write_u32(3, 2); w.write_u32(0, 2); w.write_bit(false); w.write_bit(true); let bytes = w.finish();
let mut r = BitReader::new(&bytes);
let g = SbrGrid::parse(&mut r).unwrap();
assert_eq!(g.frame_class, FrameClass::VarFix);
assert_eq!(g.num_env, 2);
assert_eq!(g.var_bord_0, 2);
assert_eq!(g.rel_bord_0, vec![3]);
assert_eq!(g.freq_res, vec![false, true]);
}
#[test]
fn varvar_both_borders() {
let mut w = BitWriter::new();
w.write_u32(FrameClass::VarVar.to_bits(), 2);
w.write_u32(1, 2); w.write_u32(2, 2); w.write_u32(1, 2); w.write_u32(1, 2); w.write_u32(0, 2); w.write_u32(3, 2); w.write_u32(2, 2); w.write_bit(true);
w.write_bit(false);
w.write_bit(true);
let bytes = w.finish();
let mut r = BitReader::new(&bytes);
let g = SbrGrid::parse(&mut r).unwrap();
assert_eq!(g.frame_class, FrameClass::VarVar);
assert_eq!(g.num_env, 3);
assert_eq!(g.num_noise, 2);
assert_eq!(g.var_bord_0, 1);
assert_eq!(g.var_bord_1, 2);
assert_eq!(g.rel_bord_0, vec![0]);
assert_eq!(g.rel_bord_1, vec![3]);
assert_eq!(g.pointer, 2);
assert_eq!(g.freq_res, vec![true, false, true]);
}
#[test]
fn dtdf_reads_per_env_and_noise() {
let mut w = BitWriter::new();
w.write_bit(true); w.write_bit(false); w.write_bit(true); w.write_bit(false); let bytes = w.finish();
let mut r = BitReader::new(&bytes);
let d = SbrDtdf::parse(&mut r, 2, 2).unwrap();
assert_eq!(d.df_env, vec![true, false]);
assert_eq!(d.df_noise, vec![true, false]);
}
#[test]
fn invf_reads_two_bits_per_band() {
let mut w = BitWriter::new();
w.write_u32(0, 2);
w.write_u32(1, 2);
w.write_u32(2, 2);
w.write_u32(3, 2);
let bytes = w.finish();
let mut r = BitReader::new(&bytes);
let inv = SbrInvf::parse(&mut r, 4).unwrap();
assert_eq!(inv.invf_mode, vec![0, 1, 2, 3]);
}
#[test]
fn truncated_grid_errors() {
let bytes = [0u8; 0];
let mut r = BitReader::new(&bytes);
assert!(matches!(SbrGrid::parse(&mut r), Err(Error::SbrGridInvalid)));
}
}