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> {
let mut quant = Vec::new();
let mut spec = Vec::new();
let mut sections = SectionData::default();
let mut sf = ScaleFactors::default();
let (ics, tns) = parse_ics_into(
br,
fs_index,
aot,
common,
&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>,
quant: &mut Vec<i32>,
spec: &mut Vec<f32>,
sections: &mut SectionData,
sf: &mut ScaleFactors,
) -> Result<(IcsInfo, Option<super::tns::TnsData>)> {
let global_gain = br.read(8)? as u8;
let ics = if let Some(shared) = common {
*shared
} else {
IcsInfo::parse(br, fs_index, false)?
};
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 tns = if tns_present {
Some(super::tns::TnsData::parse(br, &ics)?)
} else {
None
};
let gain_present = br.read_bit()?;
if gain_present {
return Err(Error::Format("gain_control_data is SSR, not LC"));
}
spectrum::parse_quant_into(br, &ics, sections, fs_index, quant)?;
if let Some(p) = pulse.as_ref() {
spectrum::apply_pulse(quant, fs_index, p)?;
}
spectrum::rescale_into(quant, &ics, sections, sf, fs_index, spec)?;
Ok((ics, tns))
}