X-Git-Url: https://git.nihav.org/?p=nihav.git;a=blobdiff_plain;f=nihav-mpeg%2Fsrc%2Fcodecs%2Faac%2Fsbr%2Fmod.rs;fp=nihav-mpeg%2Fsrc%2Fcodecs%2Faac%2Fsbr%2Fmod.rs;h=fb455cbce997e60d9fb0f36ee23b8edab42e5e4d;hp=0000000000000000000000000000000000000000;hb=0e18270ddb438c765a4597404f9053a15ce84704;hpb=9c3cd867ce7645f6f828675bd5d383033d6263f7 diff --git a/nihav-mpeg/src/codecs/aac/sbr/mod.rs b/nihav-mpeg/src/codecs/aac/sbr/mod.rs new file mode 100644 index 0000000..fb455cb --- /dev/null +++ b/nihav-mpeg/src/codecs/aac/sbr/mod.rs @@ -0,0 +1,427 @@ +use nihav_core::codecs::{DecoderResult, DecoderError}; +use nihav_core::io::bitreader::*; + +mod bs; +mod dsp; +mod synth; + +pub use bs::{SBRCodebooks, sbr_read_sce, sbr_read_cpe}; +pub use dsp::SBRDSP; +pub use synth::SBRChannel; + +pub const NUM_ENVELOPES: usize = 8; +pub const NUM_PATCHES: usize = 5; +pub const SBR_BANDS: usize = 64; +pub const QMF_DELAY: usize = 8; +pub const HF_ADJ: usize = 2; +pub const MAX_SLOTS: usize = 16; + +#[derive(Clone, Copy, Debug)] +pub struct SBRHeader { + pub amp_res: bool, + start_freq: usize, + stop_freq: usize, + xover_band: usize, + freq_scale: u8, + alter_scale: bool, + noise_bands: u8, + limiter_bands: u8, + limiter_gains: u8, + interpol_freq: bool, + smoothing_mode: bool, +} + +impl SBRHeader { + pub fn new() -> Self { + let mut obj: Self = unsafe { std::mem::zeroed() }; + obj.reset(); + obj + } + fn reset(&mut self) { + self.freq_scale = 2; + self.alter_scale = true; + self.noise_bands = 2; + self.limiter_bands = 2; + self.limiter_gains = 2; + self.interpol_freq = true; + self.smoothing_mode = true; + } + + pub fn read(br: &mut BitReader) -> DecoderResult { + let mut sbrh = Self::new(); + sbrh.reset(); + sbrh.amp_res = br.read_bool()?; + sbrh.start_freq = br.read(4)? as usize; + sbrh.stop_freq = br.read(4)? as usize; + sbrh.xover_band = br.read(3)? as usize; + br.skip(2)?; + let header_extra_1 = br.read_bool()?; + let header_extra_2 = br.read_bool()?; + if header_extra_1 { + sbrh.freq_scale = br.read(2)? as u8; + sbrh.alter_scale = br.read_bool()?; + sbrh.noise_bands = br.read(2)? as u8; + } + if header_extra_2 { + sbrh.limiter_bands = br.read(2)? as u8; + sbrh.limiter_gains = br.read(2)? as u8; + sbrh.interpol_freq = br.read_bool()?; + if !sbrh.interpol_freq { + return Err(DecoderError::NotImplemented); + } + sbrh.smoothing_mode = br.read_bool()?; + } + Ok(sbrh) + } + + pub fn differs_from(&self, rval: &Self) -> bool { + self.start_freq != rval.start_freq || + self.stop_freq != rval.stop_freq || + self.xover_band != rval.xover_band || + self.freq_scale != rval.freq_scale || + self.alter_scale != rval.alter_scale || + self.noise_bands != rval.noise_bands + } +} + +#[derive(Clone)] +pub struct SBRState { + num_env_bands: [usize; 2], + num_master: usize, + num_noise_bands: usize, + num_lim: usize, + k_x: usize, + low_to_high_res: [usize; SBR_BANDS], + high_to_low_res: [usize; SBR_BANDS], + f: [usize; SBR_BANDS], + f_low: [usize; SBR_BANDS], + f_noise: [usize; SBR_BANDS], + f_lim: [usize; SBR_BANDS], + patch_num_subbands: [usize; SBR_BANDS], + patch_start_subband: [usize; SBR_BANDS], + num_patches: usize, +} + +impl SBRState { + pub fn new() -> Self { + Self { + num_env_bands: [0; 2], + num_master: 0, + num_noise_bands: 0, + num_lim: 0, + k_x: 0, + low_to_high_res: [0; SBR_BANDS], + high_to_low_res: [0; SBR_BANDS], + f: [0; SBR_BANDS], + f_low: [0; SBR_BANDS], + f_noise: [0; SBR_BANDS], + f_lim: [0; SBR_BANDS], + patch_num_subbands: [0; SBR_BANDS], + patch_start_subband: [0; SBR_BANDS], + num_patches: 0, + } + } + pub fn init(&mut self, hdr: &SBRHeader, srate: u32) -> DecoderResult<()> { + let offset_tab = match srate { + 0..=16000 => &SBR_OFFSETS[0], + 16001..=22050 => &SBR_OFFSETS[1], + 22051..=24000 => &SBR_OFFSETS[2], + 24001..=32000 => &SBR_OFFSETS[3], + 32001..=64000 => &SBR_OFFSETS[4], + _ => &SBR_OFFSETS[5], + }; + let smult = match srate { + 0..=31999 => 3000, + 32000..=63999 => 4000, + _ => 5000, + }; + let start_min = (128 * smult + srate / 2) / srate; + let stop_min = (128 * smult * 2 + srate / 2) / srate; + + let k0 = ((start_min as i32) + i32::from(offset_tab[hdr.start_freq])).max(0) as usize; + let k2 = (match hdr.stop_freq { + 14 => 2 * k0, + 15 => 3 * k0, + _ => { + let mut stop_dk = [0; 14]; + generate_vdk(&mut stop_dk, stop_min as usize, SBR_BANDS, 13); + let dk_sum: usize = stop_dk[..hdr.stop_freq].iter().sum(); + (stop_min as usize) + dk_sum + }, + }).min(SBR_BANDS); + + let max_bands = match srate { + 0..=32000 => 48, + 32001..=47999 => 35, + _ => 32, + }; + validate!(k2 - k0 <= max_bands); + + self.num_master = calculate_master_frequencies(&mut self.f, k0, k2, hdr); + let num_high = self.num_master - hdr.xover_band; + let num_low = (num_high + 1) / 2; // INT(num_high / 2) + (num_high - 2 * INT(num_high / 2)) + + self.num_env_bands = [num_low, num_high]; + + let f_high = &self.f[hdr.xover_band..]; + let m = f_high[num_high] - f_high[0]; + let k_x = f_high[0]; + self.k_x = k_x; + self.f_low = [0; SBR_BANDS]; + if (num_high & 1) == 0 { + for k in 0..=num_low { + self.f_low[k] = f_high[k * 2]; + } + } else { + self.f_low[0] = f_high[0]; + for k in 1..=num_low { + self.f_low[k] = f_high[k * 2 - 1]; + } + } + + let high_src = &f_high[..=num_high]; + let low_src = &self.f_low[..=num_low]; + for (dst, low) in self.high_to_low_res.iter_mut().zip(low_src.iter()) { + if let Ok(idx) = high_src.binary_search(low) { + *dst = idx; + } else { + return Err(DecoderError::Bug); + } + } + for (dst, high) in self.low_to_high_res.iter_mut().zip(high_src.iter()) { + match low_src.binary_search(high) { + Ok(idx) | Err(idx) => *dst = idx, + }; + } + + let num_q = (((hdr.noise_bands as f32) * ((k2 as f32) / (k_x as f32)).log2()).round() as usize).max(1); + self.num_noise_bands = num_q; + self.f_noise = [0; SBR_BANDS]; + let mut prev = 0; + self.f_noise[0] = self.f_low[0]; + for k in 1..=num_q { + let idx = prev + ((num_low - prev) / (num_q + 1 - k)); + self.f_noise[k] = self.f_low[idx]; + prev = idx; + } + + let mut num_patches = 0; + self.patch_num_subbands = [0; SBR_BANDS]; + self.patch_start_subband = [0; SBR_BANDS]; + let mut msb = k0; + let mut usb = k_x; + let goal_sb = ((2048000 + srate / 2) / srate) as usize; + let last_band = k_x + m; + let mut k = if goal_sb < last_band { + let mut kk = 0; + for i in 0..self.num_master { + if self.f[i] >= goal_sb { + break; + } + kk = i + 1; + } + kk + } else { + self.num_master + }; + loop { + let mut sb; + let mut odd; + let mut j = k; + loop { + sb = self.f[j]; + odd = (sb - 2 + k0) & 1; + if sb <= k0 + msb - 1 - odd { + break; + } + j -= 1; + } + + self.patch_num_subbands[num_patches] = sb.saturating_sub(usb); + self.patch_start_subband[num_patches] = k0 - odd - self.patch_num_subbands[num_patches]; + + if self.patch_num_subbands[num_patches] > 0 { + usb = sb; + msb = sb; + num_patches += 1; + } else { + msb = k_x; + } + + if self.f[k] < sb + 3 { + k = self.num_master; + } + + if sb == last_band { + break; + } + } + if (num_patches > 1) && (self.patch_num_subbands[num_patches - 1] < 3) { + num_patches -= 1; + } + validate!(num_patches <= NUM_PATCHES); + self.num_patches = num_patches; + + self.f_lim = [0; SBR_BANDS]; + let num_l = if hdr.limiter_bands == 0 { + self.f_lim[0] = self.f_low[0]; + self.f_lim[1] = self.f_low[num_low]; + 1 + } else { + let lim_bands = match hdr.limiter_bands { + 1 => 1.2f32, + 2 => 2.0, + _ => 3.0, + }; + let mut patch_borders = [0; NUM_PATCHES + 1]; + patch_borders[0] = k_x; + for k in 0..num_patches { + patch_borders[k + 1] = patch_borders[k] + self.patch_num_subbands[k]; + } + self.f_lim = self.f_low; + let f_lim_ptr = &mut self.f_lim[..num_low + num_patches]; + for &pborder in patch_borders[1..num_patches].iter() { + let mut i = 0; + for &el in f_lim_ptr.iter() { + if el > pborder { + break; + } + i += 1; + } + for j in (i..num_low + num_patches - 1).rev() { + f_lim_ptr[j + 1] = f_lim_ptr[j]; + } + f_lim_ptr[i] = pborder; + } + let mut nr_lim = num_low + num_patches - 1; + let mut k = 1; + let pbord = &patch_borders[..=num_patches]; + while k <= nr_lim { + let n_octaves = ((self.f_lim[k] as f32) / (self.f_lim[k - 1] as f32)).log2(); + if (n_octaves * lim_bands) < 0.49 { + if self.f_lim[k] == self.f_lim[k - 1] || !pbord.contains(&self.f_lim[k]) { + for l in k..nr_lim { + self.f_lim[l] = self.f_lim[l + 1]; + } + nr_lim -= 1; + } else if !pbord.contains(&self.f_lim[k - 1]) { + for l in (k - 1)..nr_lim { + self.f_lim[l] = self.f_lim[l + 1]; + } + nr_lim -= 1; + } else { + k += 1; + } + } else { + k += 1; + } + } + + nr_lim + }; + self.num_lim = num_l; + + Ok(()) + } +} + +fn generate_vdk(v_dk: &mut [usize], k0: usize, k1: usize, num_bands: usize) { + let mut last = k0; + let k0 = k0 as f64; + let factor = (k1 as f64) / k0; + for k in 0..num_bands { + let next = (k0 * factor.powf((k + 1) as f64 / (num_bands as f64))).round() as usize; + let newval = next - last; + last = next; + let mut idx = k; + for (j, &el) in v_dk[..k].iter().enumerate() { + if newval < el { + idx = j; + break; + } + } + for j in (idx..k).rev() { + v_dk[j + 1] = v_dk[j]; + } + v_dk[idx] = newval; + } +} + +fn calculate_master_frequencies(f: &mut [usize; SBR_BANDS], k0: usize, k2: usize, hdr: &SBRHeader) -> usize { + if hdr.freq_scale == 0 { + let (dk, num_bands) = if !hdr.alter_scale { + (1, 2 * ((k2 - k0) / 2)) + } else { + (2, 2 * ((k2 - k0 + 2) / (2 * 2))) + }; + let k2_achieved = k0 + num_bands * dk; + let mut k2_diff = (k2 as isize) - (k2_achieved as isize); + let mut v_dk = [dk; SBR_BANDS]; + if k2_diff < 0 { + let mut k = 0; + while k2_diff != 0 { + v_dk[k] -= 1; + k += 1; + k2_diff += 1; + } + } else if k2_diff > 0 { + let mut k = num_bands - 1; + while k2_diff != 0 { + v_dk[k] += 1; + k -= 1; + k2_diff -= 1; + } + } + f[0] = k0; + for i in 0..num_bands { + f[i + 1] = f[i] + v_dk[i]; + } + + num_bands + } else { + let bands = 14 - hdr.freq_scale * 2; + let warp = if !hdr.alter_scale { 1.0f32 } else { 1.3f32 }; + let two_regions = (k2 as f32) / (k0 as f32) > 2.2449; + let k1 = if two_regions { 2 * k0 } else { k2 }; + let num_bands0 = 2 * (((bands as f32) * ((k1 as f32) / (k0 as f32)).log2() / 2.0).round() as usize); + let mut v_dk0 = [0; SBR_BANDS]; + generate_vdk(&mut v_dk0, k0, k1, num_bands0); + let mut v_k0 = [0; SBR_BANDS]; + v_k0[0] = k0; + for i in 0..num_bands0 { + v_k0[i + 1] = v_k0[i] + v_dk0[i]; + } + + if two_regions { + let num_bands1 = 2 * (((bands as f32) * ((k2 as f32) / (k1 as f32)).log2() / (2.0 * warp)).round() as usize); + let mut v_dk1 = [0; SBR_BANDS]; + generate_vdk(&mut v_dk1, k1, k2, num_bands1); + let max_vdk0 = v_dk0[num_bands0 - 1]; + if v_dk1[0] < max_vdk0 { + let change = (max_vdk0 - v_dk1[0]).min((v_dk1[num_bands1 - 1] - v_dk1[0]) / 2); + v_dk1[0] += change; + v_dk1[num_bands1 - 1] -= change; + } + let mut v_k1 = [0; SBR_BANDS]; + v_k1[0] = k1; + for i in 0..num_bands1 { + v_k1[i + 1] = v_k1[i] + v_dk1[i]; + } + f[..=num_bands0].copy_from_slice(&v_k0[..=num_bands0]); + f[num_bands0 + 1..][..=num_bands1].copy_from_slice(&v_k1[1..][..=num_bands1]); + num_bands0 + num_bands1 + } else { + f[..=num_bands0].copy_from_slice(&v_k0[..=num_bands0]); + num_bands0 + } + } +} + +const SBR_OFFSETS: [[i8; 16]; 6] = [ + [ -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7 ], // 16kHz + [ -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13 ], // 22kHz + [ -5, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16 ], // 24kHz + [ -6, -4, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16 ], // 32kHz + [ -4, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16, 20 ], // 44kHz + [ -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16, 20, 24 ] // 64kHz +];