use super::bits::BitReader;
use super::error::{Error, Result};
use super::ics::IcsInfo;
use super::section::SectionData;
use super::sf::{self, ScaleFactors};
use super::spectrum::{self, PulseData};
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct ChannelBody {
pub ics: IcsInfo,
pub sections: SectionData,
pub sf: ScaleFactors,
pub spec: Vec<f32>,
pub tns: Option<super::tns::TnsData>,
}
pub fn parse_ics(
br: &mut BitReader<'_>,
fs_index: u8,
aot: u8,
common: Option<&IcsInfo>,
) -> Result<ChannelBody> {
parse_ics_len(br, fs_index, aot, common, 0)
}
pub(crate) fn parse_ics_len(
br: &mut BitReader<'_>,
fs_index: u8,
aot: u8,
common: Option<&IcsInfo>,
frame_len: u16,
) -> Result<ChannelBody> {
let mut quant = Vec::new();
let mut spec = Vec::new();
let mut sections = SectionData::default();
let mut sf = ScaleFactors::default();
let (ics, tns, _gain) = parse_ics_into(
br,
fs_index,
aot,
common,
frame_len,
&mut quant,
&mut spec,
&mut sections,
&mut sf,
)?;
Ok(ChannelBody {
ics,
sections,
sf,
spec,
tns,
})
}
#[allow(clippy::too_many_arguments)]
pub fn parse_ics_into(
br: &mut BitReader<'_>,
fs_index: u8,
aot: u8,
common: Option<&IcsInfo>,
frame_len: u16,
quant: &mut Vec<i32>,
spec: &mut Vec<f32>,
sections: &mut SectionData,
sf: &mut ScaleFactors,
) -> Result<(
IcsInfo,
Option<super::tns::TnsData>,
Option<super::ssr::GainControl>,
)> {
let ld = aot == super::asc::AOT_LD;
let global_gain = br.read(8)? as u8;
let ics = if let Some(shared) = common {
*shared
} else {
IcsInfo::parse_mode(br, fs_index, false, aot, frame_len)?
};
sections.parse_into(br, &ics)?;
sf::parse_into(br, &ics, §ions.sfb_cb, global_gain, sf)?;
let pulse_present = br.read_bit()?;
let pulse = if pulse_present {
if ics.window_sequence.is_eight_short() {
return Err(Error::Format("pulse_data on eight_short"));
}
Some(PulseData::parse(br)?)
} else {
None
};
let tns_present = br.read_bit()?;
let gain_present = if ld { br.read_bit()? } else { false };
let tns = if tns_present {
Some(super::tns::TnsData::parse(br, &ics)?)
} else {
None
};
let gain_present = if ld { gain_present } else { br.read_bit()? };
let gain = if gain_present {
if aot != super::asc::AOT_SSR {
return Err(Error::Format("gain_control_data is SSR, not LC"));
}
Some(super::ssr::read_gain(br, ics.window_sequence)?)
} else {
None
};
if let Some(p) = pulse.as_ref() {
spectrum::parse_quant_into(br, &ics, sections, fs_index, quant)?;
spectrum::apply_pulse(quant, ics.swb_offsets(fs_index)?, p)?;
spectrum::rescale_into(quant, &ics, sections, sf, fs_index, spec)?;
} else {
super::spectrum_scaled::decode_scaled_into(br, &ics, sections, sf, fs_index, spec)?;
}
Ok((ics, tns, gain))
}