aac: SBR support (without PS)
[nihav.git] / nihav-mpeg / src / codecs / aac / sbr / mod.rs
diff --git a/nihav-mpeg/src/codecs/aac/sbr/mod.rs b/nihav-mpeg/src/codecs/aac/sbr/mod.rs
new file mode 100644 (file)
index 0000000..fb455cb
--- /dev/null
@@ -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<Self> {
+        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
+];