use super::adts::ADTS_SAMPLE_RATES_HZ;
use super::enc_sbr_qmf::{EncAnalysisQmf, EncSlot};
use super::error::{Error, Result};
pub(crate) const OUT_FRAME: usize = 2048;
pub(crate) const CORE_FRAME: usize = 1024;
pub(crate) const QMF_SLOT: usize = 64;
pub(crate) const QMF_DRAIN: usize = 640;
pub(crate) const FIR_DELAY: usize = 8;
const HALF_BAND: [f32; 17] = [
0.0,
-1.728_078_9e-3,
0.0,
1.961_995_9e-2,
0.0,
-7.324_225e-2,
0.0,
3.057_3e-1,
4.992_407_6e-1,
3.057_3e-1,
0.0,
-7.324_225e-2,
0.0,
1.961_995_9e-2,
0.0,
-1.728_078_9e-3,
0.0,
];
const HE_OUTPUT_RATES: [u32; 6] = [16_000, 22_050, 24_000, 32_000, 44_100, 48_000];
pub(crate) fn he_core_rate(output_hz: u32) -> Result<u32> {
if !HE_OUTPUT_RATES.contains(&output_hz) {
return Err(Error::UnsupportedSampleRateIndex(0xFF));
}
let core = output_hz / 2;
if !ADTS_SAMPLE_RATES_HZ.contains(&core) {
return Err(Error::UnsupportedSampleRateIndex(0xFF));
}
Ok(core)
}
struct Halfband {
z: [f32; 16],
n: u64,
}
impl Halfband {
fn new() -> Self {
Self { z: [0.0; 16], n: 0 }
}
fn reset(&mut self) {
*self = Self::new();
}
fn push(&mut self, x: f32) -> Option<f32> {
let mut acc = HALF_BAND[0] * x;
for i in 0..16 {
acc += HALF_BAND[i + 1] * self.z[i];
}
for i in (1..16).rev() {
self.z[i] = self.z[i - 1];
}
self.z[0] = x;
let keep = self.n.is_multiple_of(2);
self.n += 1;
if keep { Some(acc) } else { None }
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub(crate) struct PrepCounts {
pub source: u64,
pub core: u64,
pub slots: u64,
}
pub(crate) struct SbrPrep {
fir: Halfband,
qmf: EncAnalysisQmf,
qmf_buf: [f32; QMF_SLOT],
qmf_n: usize,
counts: PrepCounts,
}
impl SbrPrep {
pub(crate) fn new() -> Self {
Self {
fir: Halfband::new(),
qmf: EncAnalysisQmf::new(),
qmf_buf: [0.0; QMF_SLOT],
qmf_n: 0,
counts: PrepCounts::default(),
}
}
pub(crate) fn reset(&mut self) {
self.fir.reset();
self.qmf.reset();
self.qmf_buf = [0.0; QMF_SLOT];
self.qmf_n = 0;
self.counts = PrepCounts::default();
}
#[cfg_attr(not(test), allow(dead_code))]
pub(crate) fn counts(&self) -> PrepCounts {
self.counts
}
pub(crate) fn push<F>(&mut self, pcm: &[f32], core: &mut Vec<f32>, mut on_slot: F) -> Result<()>
where
F: FnMut(&EncSlot),
{
for &x in pcm {
self.counts.source += 1;
if let Some(c) = self.fir.push(x) {
core.push(c);
self.counts.core += 1;
}
self.qmf_buf[self.qmf_n] = x;
self.qmf_n += 1;
if self.qmf_n == QMF_SLOT {
let slot = self.qmf.push_slot(&self.qmf_buf)?;
on_slot(&slot);
self.qmf_n = 0;
self.counts.slots += 1;
}
}
Ok(())
}
pub(crate) fn finish<F>(&mut self, core: &mut Vec<f32>, mut on_slot: F) -> Result<PrepCounts>
where
F: FnMut(&EncSlot),
{
let pad = FIR_DELAY + QMF_DRAIN;
let zeros = [0.0f32; 64];
let mut left = pad;
while left > 0 {
let n = left.min(zeros.len());
self.push(&zeros[..n], core, &mut on_slot)?;
left -= n;
}
Ok(self.counts)
}
}
impl Default for SbrPrep {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
#[path = "enc_sbr_prep_tests.rs"]
mod enc_sbr_prep_tests;