#[cfg(test)]
use super::adts::AdtsHeader;
use super::bits::BitReader;
use super::cce::PendingChan;
use super::channel_map::{Element, PceChannelMap, map_planes_into, mono_mix, reorder};
use super::error::Result;
use super::fb_pool::FbPool;
use super::filterbank::Filterbank;
use super::pns::Lcg;
use super::sbr_attach::SbrPool;
use super::section::SectionData;
use super::sf::ScaleFactors;
pub(crate) const INV_S16: f32 = 1.0 / 32768.0;
#[cfg(test)]
#[derive(Debug, Clone, PartialEq)]
pub struct DecodedFrame {
pub planar: Vec<Vec<f32>>,
pub channels: usize,
pub sample_rate: u32,
}
#[derive(Debug, Default)]
pub struct StreamDecoder {
pub(crate) fb_l: Filterbank,
pub(crate) fb_r: Filterbank,
pub(crate) rng: Lcg,
pub mix_down_mono: bool,
pub(crate) sbr_pool: SbrPool,
pub(crate) sbr_active: bool,
sbr_declared: bool,
ps_declared: bool,
pub(crate) sbr_out_rate: Option<u32>,
pub(crate) pcm_l: Vec<f32>,
pub(crate) pcm_r: Vec<f32>,
pub(crate) frame_ch: Vec<Vec<f32>>,
pub(crate) n_ch: usize,
pub(crate) quant: Vec<i32>,
pub(crate) spec_l: Vec<f32>,
pub(crate) spec_r: Vec<f32>,
pub(crate) sections_l: SectionData,
pub(crate) sections_r: SectionData,
pub(crate) sf_l: ScaleFactors,
pub(crate) sf_r: ScaleFactors,
pub(crate) fast_mono: bool,
pub(crate) elems: Vec<Element>,
pub(crate) pce: Option<PceChannelMap>,
pub(crate) fb_pool: FbPool,
pub(crate) pending: Vec<PendingChan>,
pub(crate) cces: Vec<super::cce::CcePayload>,
pub(crate) last_rdb_bytes: usize,
last_meta: crate::layout::FrameMeta,
pub(crate) spec_pool: Vec<Vec<f32>>,
pub(crate) plane_order: Vec<super::channel_map::PlaneMap>,
pub(crate) cce_pcm: Vec<f32>,
pub(crate) tools: super::tools::Tools,
pub(crate) pns_shared: Vec<f32>,
pub(crate) pending_sbrs: Vec<(
(super::channel_map::ElemKind, u8),
Box<super::sbr_extension::SbrExtensionData>,
)>,
pub(crate) prof_lc: u64,
pub(crate) prof_fin: u64,
pub(crate) prof_sbr: u64,
pub(crate) prof_scale: u64,
pub(crate) prof_frames: u64,
pub(crate) frame_samples: u16,
}
impl StreamDecoder {
pub fn new() -> Box<Self> {
Box::default()
}
pub(crate) fn set_config_pce(&mut self, pce: PceChannelMap) {
self.pce = Some(pce);
}
pub(crate) fn set_he_config(&mut self, sbr: bool, ps: bool, output_rate: u32) {
self.sbr_declared = sbr;
self.ps_declared = ps;
if sbr && output_rate != 0 {
self.sbr_active = true;
self.sbr_out_rate = Some(output_rate);
}
}
#[cfg(test)]
pub(crate) fn he_config(&self) -> (bool, bool, Option<u32>) {
(self.sbr_declared, self.ps_declared, self.sbr_out_rate)
}
#[cfg(test)]
pub fn decode_frame(&mut self, header: &AdtsHeader, payload: &[u8]) -> Result<DecodedFrame> {
self.decode_raw_data_block(
header.audio_object_type(),
header.sampling_frequency_index,
header.sample_rate(),
header.channel_configuration,
header.number_of_raw_data_blocks_in_frame,
payload,
)
}
#[cfg(test)]
pub fn decode_raw_data_block(
&mut self,
aot: u8,
fs_index: u8,
sample_rate: u32,
channel_configuration: u8,
num_raw_data_blocks: u8,
payload: &[u8],
) -> Result<DecodedFrame> {
let sample_rate = if num_raw_data_blocks <= 1 {
self.decode_into_bufs(aot, fs_index, sample_rate, channel_configuration, payload)?
} else {
self.decode_adts_blocks(
aot,
fs_index,
sample_rate,
channel_configuration,
num_raw_data_blocks,
true,
payload,
)?
};
Ok(DecodedFrame {
planar: self.frame_ch.clone(),
channels: self.frame_ch.len(),
sample_rate,
})
}
pub(crate) fn decode_frame_scaled(
&mut self,
aot: u8,
fs_index: u8,
sample_rate: u32,
channel_configuration: u8,
payload: &[u8],
) -> Result<u32> {
let rate =
self.decode_into_bufs(aot, fs_index, sample_rate, channel_configuration, payload)?;
let t_sc = super::prof::stamp();
for ch in &mut self.frame_ch {
for v in ch.iter_mut() {
*v *= INV_S16;
}
}
self.prof_scale += super::prof::ns(t_sc);
if super::prof::on() {
self.prof_frames = self.prof_frames.saturating_add(1);
}
Ok(rate)
}
pub(crate) fn frame_planes(&self) -> &[Vec<f32>] {
&self.frame_ch
}
pub(crate) fn decode_into_bufs(
&mut self,
aot: u8,
fs_index: u8,
sample_rate: u32,
channel_configuration: u8,
payload: &[u8],
) -> Result<u32> {
meta::check_config(aot, channel_configuration)?;
self.refill_spec_bufs();
let core_aot = match aot {
1 | 3 | 4 | 23 => aot,
_ => 2,
};
self.tools.aot = core_aot;
let mut br = BitReader::new(payload);
let multichannel =
channel_configuration == 0 || channel_configuration >= 3 || self.pce.is_some();
self.tools.multichannel = multichannel;
self.tools.begin_frame();
if multichannel {
self.fast_mono = false;
}
self.n_ch = 0;
self.elems.clear();
self.pending.clear();
self.cces.clear();
self.fb_pool.begin_frame();
self.sbr_pool.begin_frame();
self.pending_sbrs.clear();
let t_lc = super::prof::stamp();
let ld = core_aot == super::asc::AOT_LD;
if ld {
self.decode_ld_elements(&mut br, fs_index, core_aot, channel_configuration)?;
} else {
self.decode_lc_elements(
&mut br,
fs_index,
core_aot,
sample_rate,
channel_configuration,
multichannel,
)?;
}
if self.frame_samples == 960
&& (self.sbr_declared
|| self.ps_declared
|| self.sbr_active
|| !self.pending_sbrs.is_empty())
{
return Err(super::error::Error::UnsupportedHeFrame960);
}
self.prof_lc += super::prof::ns(t_lc);
br.byte_align()?;
self.last_rdb_bytes = (br.bit_position() / 8) as usize;
let he = self.sbr_active || !self.pending_sbrs.is_empty();
let was_fast = self.fast_mono;
if he {
self.fast_mono = false;
}
let t_fin = super::prof::stamp();
self.finish_pending(fs_index, multichannel, he)?;
self.prof_fin += super::prof::ns(t_fin);
if was_fast && !he {
self.fb_pool.retain_seen();
self.tools.retain_seen();
self.fast_mono = was_fast;
self.store_meta(channel_configuration, sample_rate, sample_rate, None, 1);
return Ok(sample_rate);
}
if he {
for p in self.frame_ch.iter_mut().skip(self.n_ch) {
p.clear();
}
} else {
self.frame_ch.truncate(self.n_ch);
}
let mut order_buf = [super::channel_map::PlaneMap::default(); 8];
let mut n_order = 0usize;
let has_order = self.pce.is_some() || (multichannel && !self.frame_ch.is_empty());
if has_order {
map_planes_into(
&mut self.plane_order,
&self.elems,
self.pce.as_ref(),
channel_configuration,
fs_index,
)?;
n_order = self.plane_order.len().min(8);
order_buf[..n_order].copy_from_slice(&self.plane_order[..n_order]);
}
let order = has_order.then_some(&order_buf[..n_order]);
if !he {
if let Some(order) = order {
reorder(&mut self.frame_ch, order);
if self.mix_down_mono {
let mono = mono_mix(&self.frame_ch, order);
self.pcm_l.clear();
self.pcm_l.extend_from_slice(&mono);
self.frame_ch.truncate(1);
self.frame_ch[0] = mono;
}
}
self.fb_pool.retain_seen();
self.tools.retain_seen();
self.fast_mono = was_fast;
self.store_meta(
channel_configuration,
sample_rate,
sample_rate,
order,
self.frame_ch.len(),
);
return Ok(sample_rate);
}
let core = sample_rate;
let t_sbr = super::prof::stamp();
let out_rate = super::sbr_attach::apply_and_layout(
&mut self.sbr_pool,
&self.elems,
&mut self.frame_ch,
sample_rate,
self.sbr_out_rate,
&mut self.pending_sbrs,
&mut self.sbr_active,
self.mix_down_mono,
order,
)?;
self.prof_sbr += super::prof::ns(t_sbr);
self.fb_pool.retain_seen();
self.tools.retain_seen();
self.sbr_pool.retain_seen();
self.fast_mono = was_fast;
self.store_meta(
channel_configuration,
core,
out_rate,
order,
self.frame_ch.len(),
);
Ok(out_rate)
}
#[allow(clippy::too_many_arguments)]
pub fn decode_raw_mono_f32(
&mut self,
aot: u8,
fs_index: u8,
sample_rate: u32,
channel_configuration: u8,
_num_raw_data_blocks: u8,
payload: &[u8],
dst: &mut Vec<f32>,
) -> Result<u32> {
let was = self.mix_down_mono;
self.mix_down_mono = true;
self.fast_mono = true;
let rate = self.decode_adts_blocks(
aot,
fs_index,
sample_rate,
channel_configuration,
_num_raw_data_blocks,
true,
payload,
);
self.fast_mono = false;
self.mix_down_mono = was;
let rate = rate?;
let src = if self.sbr_active {
self.frame_ch.first().map(Vec::as_slice).unwrap_or(&[])
} else {
self.pcm_l.as_slice()
};
dst.extend(src.iter().map(|&v| v * INV_S16));
Ok(rate)
}
pub(crate) fn push_pcm(&mut self, right: bool) {
if self.fast_mono {
self.n_ch = 1;
return;
}
let i = self.n_ch;
let src = if right { &self.pcm_r } else { &self.pcm_l };
if i < self.frame_ch.len() {
self.frame_ch[i].clear();
self.frame_ch[i].extend_from_slice(src);
} else {
self.frame_ch.push(src.to_vec());
}
self.n_ch += 1;
}
}
impl Drop for StreamDecoder {
fn drop(&mut self) {
if self.prof_frames == 0 {
return;
}
let n = self.prof_frames;
eprintln!(
"dec_prof frames={n} lc_ms={:.3} fin_ms={:.3} sbr_ms={:.3} scale_ms={:.3}",
self.prof_lc as f64 / 1e6,
self.prof_fin as f64 / 1e6,
self.prof_sbr as f64 / 1e6,
self.prof_scale as f64 / 1e6
);
}
}
#[path = "decode_meta.rs"]
mod meta;
#[path = "decode_reset.rs"]
mod reset;