add nihav_qt crate with some QuickTime codecs
[nihav.git] / nihav-qt / src / codecs / qdm2qmf.rs
diff --git a/nihav-qt/src/codecs/qdm2qmf.rs b/nihav-qt/src/codecs/qdm2qmf.rs
new file mode 100644 (file)
index 0000000..ece74c2
--- /dev/null
@@ -0,0 +1,806 @@
+use nihav_core::codecs::*;
+use nihav_core::io::codebook::*;
+use nihav_codec_support::dsp::qmf::QMF;
+use super::qdmcommon::*;
+use super::qdm2::TONE_SCALES;
+
+const MAX_BANDS: usize = 30;
+
+const NOISE_TAB_LEN: usize = 3840;
+
+struct NoiseGen {
+    noise_tab:          [f32; NOISE_TAB_LEN],
+    idx:                usize,
+}
+
+impl NoiseGen {
+    fn new() -> Self {
+        let mut noise_tab = [0.0; NOISE_TAB_LEN];
+        let mut rnd = RNG::new();
+        for el in noise_tab.iter_mut() {
+            *el = rnd.next_float() * 1.3;
+        }
+
+        Self { noise_tab, idx: 0 }
+    }
+    fn next(&mut self, band: usize) -> f32 {
+        let ret = self.noise_tab[self.idx];
+        self.idx += 1;
+        if self.idx >= NOISE_TAB_LEN {
+            self.idx -= NOISE_TAB_LEN;
+        }
+        ret * SB_NOISE_ATTENUATION[band]
+    }
+}
+
+struct Tables {
+    noise_samples:  [f32; 128],
+    mod3:           [[u8; 5]; 243],
+    mod5:           [[u8; 3]; 125],
+}
+
+impl Tables {
+    fn new() -> Self {
+        let mut noise_samples = [0.0; 128];
+        let mut rnd = RNG::new();
+        for el in noise_samples.iter_mut() {
+            *el = rnd.next_float();
+        }
+
+        let mut mod3 = [[0u8; 5]; 243];
+        for (i, row) in mod3.iter_mut().enumerate() {
+            let mut base = 81u8;
+            let mut low = i as u8;
+            for el in row.iter_mut() {
+                *el = low / base;
+                low %= base;
+                base /= 3;
+            }
+        }
+
+        let mut mod5 = [[0u8; 3]; 125];
+        for (i, row) in mod5.iter_mut().enumerate() {
+            let mut base = 25u8;
+            let mut low = i as u8;
+            for el in row.iter_mut() {
+                *el = low / base;
+                low %= base;
+                base /= 5;
+            }
+        }
+
+        Self {
+            noise_samples, mod3, mod5,
+        }
+    }
+}
+
+struct Codebooks {
+    level_cb:               Codebook<u8>,
+    level_diff_cb:          Codebook<u8>,
+    run_cb:                 Codebook<u8>,
+    tone_idx_mid_cb:        Codebook<u8>,
+    tone_idx_high1_cb:      Codebook<u8>,
+    tone_idx_high2_cb:      Codebook<u8>,
+    type30_codes_cb:        Codebook<u8>,
+    type34_codes_cb:        Codebook<u8>,
+}
+
+fn map_idx(idx: usize) -> u8 { idx as u8 }
+
+macro_rules! create_codebook {
+    ($codes: expr, $bits: expr) => ({
+        let mut cbr = TableCodebookDescReader::new($codes, $bits, map_idx);
+        Codebook::new(&mut cbr, CodebookMode::LSB).unwrap()
+    })
+}
+
+impl Codebooks {
+    fn new() -> Self {
+        let level_cb = create_codebook!(LEVEL_CODES, LEVEL_BITS);
+        let level_diff_cb = create_codebook!(LEVEL_DIFF_CODES, LEVEL_DIFF_BITS);
+        let run_cb = create_codebook!(RUN_CODES, RUN_BITS);
+
+        let tone_idx_mid_cb = create_codebook!(TONE_IDX_MID_CODES, TONE_IDX_MID_BITS);
+        let tone_idx_high1_cb = create_codebook!(TONE_IDX_HIGH1_CODES, TONE_IDX_HIGH1_BITS);
+        let tone_idx_high2_cb = create_codebook!(TONE_IDX_HIGH2_CODES, TONE_IDX_HIGH2_BITS);
+
+        let type30_codes_cb = create_codebook!(TYPE30_CODES, TYPE30_BITS);
+        let type34_codes_cb = create_codebook!(TYPE34_CODES, TYPE34_BITS);
+        Self {
+            level_cb, level_diff_cb, run_cb,
+            tone_idx_mid_cb, tone_idx_high1_cb, tone_idx_high2_cb,
+            type30_codes_cb, type34_codes_cb,
+        }
+    }
+}
+
+pub struct QDM2QMF {
+    qmf:        [QMF; 2],
+    cbs:        Codebooks,
+    tables:     Tables,
+    noisegen:   NoiseGen,
+
+    pub is_intra:       bool,
+
+    num_bands:          usize,
+    subsampling:        u8,
+    cm_selector:        usize,
+    coef_per_sb_sel:    usize,
+    channels:           usize,
+
+    grid_2_quant:       [[[i8; 8]; 10]; 2],
+    grid_1_quant:       [[[[i8; 8]; 8]; 3]; 2],
+    grid_3_quant:       [[i8; MAX_BANDS]; 2],
+    tone_idx_mid:       [[[i8; 8]; MAX_BANDS]; 2],
+    tone_idx_base:      [[[i8; 8]; MAX_BANDS]; 2],
+    tone_idx:           [[[i8; 64]; MAX_BANDS]; 2],
+    quant_weight:       [[[u8; 64]; MAX_BANDS]; 2],
+    sb_samples:         [[[f32; 32]; 128]; 2],
+    tone_scale:         [[[f32; 64]; MAX_BANDS]; 2],
+}
+
+impl QDM2QMF {
+    pub fn new() -> Self {
+        Self {
+            qmf:        [QMF::new(), QMF::new()],
+            cbs:        Codebooks::new(),
+            tables:     Tables::new(),
+            noisegen:   NoiseGen::new(),
+
+            num_bands:          0,
+            subsampling:        0,
+            cm_selector:        0,
+            coef_per_sb_sel:    0,
+            channels:           0,
+            is_intra:           false,
+
+            grid_2_quant:       [[[0; 8]; 10]; 2],
+            grid_1_quant:       [[[[0; 8]; 8]; 3]; 2],
+            grid_3_quant:       [[0; MAX_BANDS]; 2],
+            tone_idx_mid:       [[[0; 8]; MAX_BANDS]; 2],
+            tone_idx_base:      [[[0; 8]; MAX_BANDS]; 2],
+            tone_idx:           [[[0; 64]; MAX_BANDS]; 2],
+            quant_weight:       [[[0; 64]; MAX_BANDS]; 2],
+            sb_samples:         [[[0.0; 32]; 128]; 2],
+            tone_scale:         [[[0.0; 64]; MAX_BANDS]; 2],
+        }
+    }
+    pub fn set_ch_and_subsampling(&mut self, channels: usize, subsampling: u8, full_bitrate: u32) {
+        self.channels    = channels;
+        self.subsampling = subsampling;
+        self.num_bands   = (8 << self.subsampling).min(MAX_BANDS);
+
+        let br = match self.subsampling * 2 + (channels as u8) - 1 {
+                0 => 40,
+                1 => 48,
+                2 => 56,
+                3 => 72,
+                4 => 80,
+                5 => 100,
+                _ => unreachable!(),
+            };
+        self.cm_selector = if br * 1000 < full_bitrate {
+                1
+            } else if br * 1440 < full_bitrate {
+                2
+            } else if br * 1760 < full_bitrate {
+                3
+            } else if br * 2240 < full_bitrate {
+                4
+            } else {
+                0
+            };
+        self.coef_per_sb_sel = if full_bitrate <= 8000 { 0 } else if full_bitrate < 16000 { 1 } else { 2 };
+    }
+    fn average_grid_quants(&mut self) {
+        let ncoef = (COEFFS_PER_SB_AVG[self.coef_per_sb_sel][self.subsampling as usize] as usize) + 1;
+        for ch in 0..self.channels {
+            for i in 0..ncoef {
+                let mut sum = 0;
+                for el in self.grid_2_quant[ch][i].iter() {
+                    sum += i16::from(*el);
+                }
+                sum /= 8;
+                if sum > 0 {
+                    sum -= 1;
+                }
+                self.grid_2_quant[ch][i] = [sum as i8; 8];
+            }
+        }
+    }
+    fn read_array(br: &mut QdmBitReader, dst: &mut [i8; 8], codebooks: &Codebooks) -> DecoderResult<()> {
+        if br.left() < 15 { return Ok(()); }
+        let mut last                    = br.read_code(&codebooks.level_cb)? as i32;
+        dst[0] = last as i8;
+        let mut idx = 1;
+        while idx < 8 {
+            let len                     = (br.read_code(&codebooks.run_cb)? as usize) + 1;
+            let diff                    = br.read_code(&codebooks.level_diff_cb)? as i32;
+            let diff = to_signed(diff);
+            let val = last + diff;
+            validate!(len + idx <= 8);
+            for i in 1..=len {
+                dst[idx] = (last + (i as i32) * diff / (len as i32)) as i8;
+                idx += 1;
+            }
+            last = val;
+        }
+        Ok(())
+    }
+    pub fn read_type_9(&mut self, br: &mut QdmBitReader) -> DecoderResult<()> {
+        let nbands = (COEFFS_PER_SB_AVG[self.coef_per_sb_sel][self.subsampling as usize] as usize) + 1;
+        for i in 1..nbands {
+            for ch in 0..self.channels {
+                Self::read_array(br, &mut self.grid_2_quant[ch][i], &self.cbs)?;
+            }
+        }
+        for ch in 0..self.channels {
+            self.grid_2_quant[ch][0] = [0; 8];
+        }
+        Ok(())
+    }
+    pub fn read_type_10(&mut self, br: &mut QdmBitReader) -> DecoderResult<()> {
+        for ch in 0..self.channels {
+            let _ret = Self::read_array(br, &mut self.grid_2_quant[ch][0], &self.cbs);
+            if br.left() < 16 {
+                self.grid_2_quant[ch][0] = [0; 8];
+                break;
+            }
+        }
+
+        let n = (self.subsampling as usize) + 1;
+        for band in 0..n {
+            for ch in 0..self.channels {
+                for i in 0..8 {
+                    if br.read_bool() {
+                        for el in self.grid_1_quant[ch][band][i].iter_mut() {
+                            *el         = br.read_code(&self.cbs.tone_idx_high1_cb)? as i8;
+                        }
+                    } else {
+                        self.grid_1_quant[ch][band][i] = [0; 8];
+                    }
+                }
+            }
+        }
+        for band in 0..self.num_bands - 4 {
+            for ch in 0..self.channels {
+                if br.left() < 16 { break; }
+                self.grid_3_quant[ch][band] = br.read_code(&self.cbs.tone_idx_high2_cb)? as i8;
+                if band > 19 {
+                    self.grid_3_quant[ch][band] -= 16;
+                } else {
+                    self.tone_idx_mid[ch][band] = [-16; 8];
+                }
+            }
+        }
+        for band in 0..self.num_bands - 5 {
+            for ch in 0..self.channels {
+                for i in 0..8 {
+                    if br.left() < 16 { break; }
+                    self.tone_idx_mid[ch][band][i] = (br.read_code(&self.cbs.tone_idx_mid_cb)? as i8) - 32;
+                }
+            }
+        }
+
+        self.set_tone_scales(true);
+        Ok(())
+    }
+    fn inc_quant_weight(&mut self, band: usize) -> bool {
+        let rlen = 128 / self.channels;
+        for ch in 0..self.channels {
+            let mut idx = 0;
+            while idx < rlen {
+                if self.quant_weight[ch][band][idx] < 8 {
+                    return false;
+                }
+                let (val, run) = match self.quant_weight[ch][band][idx] {
+                        8  => (10, 16),
+                        10 => (16, 1),
+                        16 => (24, 5),
+                        24 => (30, 3),
+                        30 => (30, 1),
+                        _  => (8, 1),
+                    };
+                let len = run.min(rlen - idx);
+                let ref_val = self.quant_weight[ch][band][idx];
+                for _ in 0..len {
+                    if self.quant_weight[ch][band + idx / 64][idx % 64] > ref_val {
+                        self.quant_weight[ch][band][idx] = val;
+unimplemented!();
+                    }
+                    idx += 1;
+                }
+            }
+        }
+        true
+    }
+    fn set_tone_scales(&mut self, has_data: bool) {
+        const LAST_COEFF: [usize; 3] = [ 4, 7, 10 ];
+
+        let csel = self.coef_per_sb_sel;
+        for ch in 0..self.channels {
+            for band in 0..MAX_BANDS {
+                for i in 0..8 {
+                    let csb = COEFFS_PER_SB_DEQUANT[csel][band] as usize;
+                    let mut q = i32::from(self.grid_2_quant[ch][csb][i]) * i32::from(DEQUANT[csel][csb][band]);
+                    if csb < LAST_COEFF[csel] - 1 {
+                        q += i32::from(self.grid_2_quant[ch][csb + 1][i]) * i32::from(DEQUANT[csel][csb + 1][band]);
+                    }
+                    if q < 0 {
+                        q += 255;
+                    }
+                    self.tone_idx_base[ch][band][i] = (q / 256) as i8;
+                }
+            }
+        }
+        if !self.is_intra && !has_data {
+            for band in 0..self.num_bands {
+                for ch in 0..self.channels {
+                    for i in 0..64 {
+                        self.tone_idx[ch][band][i] = self.tone_idx[ch][band][i / 8];
+                        if self.tone_idx[ch][band][i] >= 0 {
+                            self.tone_scale[ch][band][i] = TONE_SCALES[0][(self.tone_idx[ch][band][i] & 0x3F) as usize];
+                        } else {
+                            self.tone_scale[ch][band][i] = 0.0;
+                        }
+                    }
+                }
+            }
+        } else {
+            for band in 0..self.num_bands {
+                for ch in 0..self.channels {
+                    for i in 0..64 {
+                        let mut q = self.tone_idx_base[ch][band][i / 8];
+                        if band >= 4 {
+                            q = q.wrapping_sub(self.grid_1_quant[ch][(band / 8).min(2)][i / 8][i % 8]);
+                            if band < 24 {
+                                q = q.wrapping_sub(self.tone_idx_mid[ch][band - 4][i / 8]);
+                            }
+                            q = q.wrapping_sub(self.grid_3_quant[ch][band - 4]);
+                        }
+                        self.tone_idx[ch][band][i] = q as i8;
+                        if q > 0 || (self.is_intra && q == 0) {
+                            self.tone_scale[ch][band][i] = TONE_SCALES[0][(q & 0x3F) as usize];
+                        } else {
+                            self.tone_scale[ch][band][i] = 0.0;
+                        }
+                    }
+                }
+            }
+        }
+    }
+    #[allow(clippy::cyclomatic_complexity)]
+    fn read_noise_band(&mut self, br: &mut QdmBitReader, ch: usize, band: usize, samples: &mut [f32; 10], signs: &[bool; 16], jstereo: bool) -> DecoderResult<()> {
+        let mut type34_first = true;
+        let mut type34_pred = 0.0;
+        let mut type34_scale = 0.0;
+        let zero_coding                 = br.read_bool();
+        let mut idx = 0;
+        while idx < 128 {
+            let len;
+            match self.quant_weight[ch][band][idx / 2] {
+                8 => {
+                    if br.left() >= 10 {
+                        if zero_coding {
+                            for i in 0..5 {
+                                if idx + i * 2 >= 128 { break; }
+                                samples[i * 2] = if br.read_bool() {
+                                        let ix = (br.read(1) as usize) * 2;
+                                        QUANT_1BIT[jstereo as usize][ix]
+                                    } else { 0.0 };
+                            }
+                        } else {
+                            let idx = br.read(8) as usize;
+                            validate!(idx < self.tables.mod3.len());
+                            for i in 0..5 {
+                                let k = self.tables.mod3[idx][i] as usize; 
+                                samples[i * 2] = QUANT_1BIT[jstereo as usize][k];
+                            }
+                        }
+                        for el in samples.chunks_mut(2) {
+                            el[1] = self.noisegen.next(band);
+                        }
+                    } else {
+                        for el in samples.iter_mut() {
+                            *el = self.noisegen.next(band);
+                        }
+                    }
+                    len = 10;
+                },
+                10 => {
+                    if br.left() > 0 {
+                        let mut scale   = if br.read_bool() { -0.81 } else { 0.81 };
+                        scale -= self.tables.noise_samples[((band + 1) * (idx + 5 * ch + 1)) & 0x7F] * 9.0 / 40.0;
+                        samples[0] = scale;
+                    } else {
+                        samples[0] = self.noisegen.next(band);
+                    }
+                    len = 1;
+                },
+                16 => {
+                    if br.left() >= 10 {
+                        if zero_coding {
+                            for i in 0..5 {
+                                if idx + i >= 128 { break; }
+                                samples[i] = if br.read_bool() {
+                                        let ix = (br.read(1) as usize) * 2;
+                                        QUANT_1BIT[jstereo as usize][ix]
+                                    } else { 0.0 };
+                            }
+                        } else {
+                            let idx = br.read(8) as usize;
+                            validate!(idx < self.tables.mod3.len());
+                            for i in 0..5 {
+                                let k = self.tables.mod3[idx][i] as usize; 
+                                samples[i] = QUANT_1BIT[jstereo as usize][k];
+                            }
+                        }
+                    } else {
+                        for el in samples.iter_mut().take(5) {
+                            *el = self.noisegen.next(band);
+                        }
+                    }
+                    len = 5;
+                },
+                24 => {
+                    if br.left() >= 7 {
+                        let idx         = br.read(7) as usize;
+                        validate!(idx < self.tables.mod5.len());
+                        for i in 0..3 {
+                            let k = self.tables.mod5[idx][i] as usize; 
+                            samples[i] = ((k as f32) - 2.0) * 0.5;
+                        }
+                    } else {
+                        for el in samples.iter_mut().take(3) {
+                            *el = self.noisegen.next(band);
+                        }
+                    }
+                    len = 3;
+                },
+                30 => {
+                    if br.left() >= 4 {
+                        let idx         = br.read_code(&self.cbs.type30_codes_cb).unwrap_or(99) as usize;
+                        if idx < QUANT_TYPE30.len() - 1 {
+                            samples[0] = QUANT_TYPE30[idx];
+                        } else {
+                            samples[0] = self.noisegen.next(band);
+                        }
+                    } else {
+                        samples[0] = self.noisegen.next(band);
+                    }
+                    len = 1;
+                },
+                34 => {
+                    if br.left() >= 7 {
+                        if type34_first {
+                            type34_first = false;
+                            type34_scale = 1.0 / ((1 << br.read(2)) as f32);
+                            type34_pred = ((br.read(5) as f32) - 16.0) / 15.0;
+                            samples[0] = type34_pred;
+                        } else {
+                            let idx     = br.read_code(&self.cbs.type34_codes_cb).unwrap_or(99) as usize;
+                            if idx < TYPE34_DIFF.len() - 1 {
+                                samples[0] = type34_pred + TYPE34_DIFF[idx] * type34_scale;
+                                type34_pred = samples[0];
+                            } else {
+                                samples[0] = self.noisegen.next(band);
+                            }
+                        }
+                    } else {
+                        samples[0] = self.noisegen.next(band);
+                    }
+                    len = 1;
+                },
+                _ => {
+                    len = 1;
+                },
+            };
+            let llen = len.min(128 - idx);
+            if !jstereo {
+                for samp in samples.iter().take(llen) {
+                    self.sb_samples[ch][idx][band] = self.tone_scale[ch][band][idx / 2] * *samp;
+                    idx += 1;
+                }
+            } else {
+                for samp in samples.iter().take(llen) {
+                    self.sb_samples[0][idx][band] = self.tone_scale[0][band][idx / 2] * *samp;
+                    if self.channels == 2 {
+                        let sample = if signs[idx / 8] { -*samp } else { *samp };
+                        self.sb_samples[1][idx][band] = self.tone_scale[1][band][idx / 2] * sample;
+                    }
+                    idx += 1;
+                }
+            }
+        }
+        Ok(())
+    }
+    fn read_band_data(&mut self, br: &mut QdmBitReader, start: usize, end: usize) -> DecoderResult<()> {
+        let mut samples = [0.0f32; 10];
+        let mut signs = [false; 16];
+        for band in start..end {
+            let jstereo = if self.channels == 1 || band < 12 {
+                    false
+                } else if band >= 24 {
+                    true
+                } else {
+                                        br.read_bool()
+                };
+            if jstereo {
+                if br.left() >= 16 {
+                    for el in signs.iter_mut() {
+                        *el             = br.read_bool();
+                    }
+                }
+                for i in 0..64 {
+                    self.quant_weight[0][band][i] = self.quant_weight[0][band][i].max(self.quant_weight[1][band][i]);
+                }
+                if !self.inc_quant_weight(band) {
+                    self.fill_noise(band);
+                    continue;
+                }
+            }
+
+            let band_chan = if jstereo { 1 } else { self.channels };
+            for ch in 0..band_chan {
+                self.read_noise_band(br, ch, band, &mut samples, &signs, jstereo)?;
+            }
+        }
+        Ok(())
+    }
+    fn fill_noise(&mut self, band: usize) {
+        for ch in 0..self.channels {
+            for i in 0..128 {
+                self.sb_samples[ch][i][band] = self.noisegen.next(band) * self.tone_scale[ch][band][i / 2];
+            }
+        }
+    }
+    pub fn read_type_11(&mut self, br: &mut QdmBitReader) -> DecoderResult<()> {
+        if br.left() >= 32 {
+            let c                       = br.read(13);
+            if c > 3 {
+                if self.is_intra {
+                    for ch in 0..self.channels {
+                        for band in 0..MAX_BANDS {
+                            let sb = QUANT_WEIGHT[self.cm_selector][band];
+                            self.quant_weight[ch][band] = [sb; 64];
+                        }
+                    }
+                } else {
+unimplemented!();
+                }
+            }
+        }
+        self.read_band_data(br, 0, 8)?;
+        Ok(())
+    }
+    pub fn read_type_12(&mut self, br: &mut QdmBitReader) -> DecoderResult<()> {
+        self.read_band_data(br, 8, self.num_bands)?;
+        Ok(())
+    }
+    pub fn fill_default(&mut self, id: u8) {
+        match id {
+            10 => {
+                self.set_tone_scales(false);
+            },
+            11 => {
+                for band in 0..8 {
+                    self.fill_noise(band);
+                }
+            },
+            12 => {
+                for band in 8..self.num_bands {
+                    self.fill_noise(band);
+                }
+            },
+            _ => {},
+        };
+    }
+    pub fn new_frame(&mut self) {
+        self.grid_1_quant = [[[[0; 8]; 8]; 3]; 2];
+        self.grid_3_quant = [[0; MAX_BANDS]; 2];
+        self.tone_idx_mid = [[[0; 8]; MAX_BANDS]; 2];
+        self.average_grid_quants();
+    }
+    pub fn synth(&mut self, dst: &mut [f32], sf: usize, ch: usize) {
+        let mut osamps = [0.0f32; 32 * 8];
+        let ssamp = 4 >> self.subsampling;
+        for (i, out) in osamps.chunks_mut(32).enumerate() {
+            self.qmf[ch].synth(&self.sb_samples[ch][sf * 8 + i], out);
+        }
+        let scale = 1.0 / ((1 << self.subsampling) as f32);
+        for (src, dst) in osamps.chunks(ssamp).zip(dst.iter_mut()) {
+            *dst += src[0] * scale;
+        }
+    }
+    pub fn flush(&mut self) {
+        for qmf in self.qmf.iter_mut() {
+            qmf.reset();
+        }
+    }
+}
+
+const LEVEL_CODES: &[u16; 24] = &[
+    0x37C, 0x004, 0x03C, 0x04C, 0x03A, 0x02C, 0x01C, 0x01A,
+    0x024, 0x014, 0x001, 0x002, 0x000, 0x003, 0x007, 0x005,
+    0x006, 0x008, 0x009, 0x00A, 0x00C, 0x0FC, 0x07C, 0x17C
+];
+const LEVEL_BITS: &[u8; 24] = &[
+    10,  6,  7,  7,  6,  6,  6,  6,  6,  5,  4,  4,  4,  3,  3,  3,
+     3,  4,  4,  5,  7,  8,  9, 10
+];
+
+const LEVEL_DIFF_CODES: &[u16; 37] = &[
+    0x1C57, 0x0004, 0x0000, 0x0001, 0x0003, 0x0002, 0x000F, 0x000E,
+    0x0007, 0x0016, 0x0037, 0x0027, 0x0026, 0x0066, 0x0006, 0x0097,
+    0x0046, 0x01C6, 0x0017, 0x0786, 0x0086, 0x0257, 0x00D7, 0x0357,
+    0x00C6, 0x0386, 0x0186, 0x0000, 0x0157, 0x0C57, 0x0057, 0x0000,
+    0x0B86, 0x0000, 0x1457, 0x0000, 0x0457
+];
+const LEVEL_DIFF_BITS: &[u8; 37] = &[
+    13,  3,  3,  2,  3,  3,  4,  4,  6,  5,  6,  6,  7,  7,  8,  8,
+     8,  9,  8, 11,  9, 10,  8, 10,  9, 12, 10,  0, 10, 13, 11,  0,
+    12,  0, 13,  0, 13
+];
+
+const RUN_CODES: &[u8; 6] = &[ 0x1F, 0x00, 0x01, 0x03, 0x07, 0x0F ];
+const RUN_BITS: &[u8; 6] = &[ 5, 1, 2, 3, 4, 5 ];
+
+const TONE_IDX_HIGH1_CODES: &[u16; 20] = &[
+    0x5714, 0x000C, 0x0002, 0x0001, 0x0000, 0x0004, 0x0034, 0x0054,
+    0x0094, 0x0014, 0x0114, 0x0214, 0x0314, 0x0614, 0x0E14, 0x0F14,
+    0x2714, 0x0714, 0x1714, 0x3714
+];
+const TONE_IDX_HIGH1_BITS: &[u8; 20] = &[
+    15, 4, 2, 1, 3, 5, 6, 7, 8, 10, 10, 11, 11, 12, 12, 12, 14, 14, 15, 14
+];
+
+const TONE_IDX_HIGH2_CODES: &[u16; 24] = &[
+    0x0664, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0064, 0x00E4,
+    0x00A4, 0x0068, 0x0004, 0x0008, 0x0014, 0x0018, 0x0000, 0x0001,
+    0x0002, 0x0003, 0x000C, 0x0028, 0x0024, 0x0164, 0x0000, 0x0264
+];
+const TONE_IDX_HIGH2_BITS: &[u8; 24] = &[
+    11, 0, 0, 0, 0, 0, 10, 8, 8, 7, 6, 6, 5, 5, 4, 2, 2, 2, 4, 7, 8, 9, 0, 11
+];
+
+const TONE_IDX_MID_CODES: &[u16; 24] = &[
+    0x0FEA, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+    0x0000, 0x0000, 0x0000, 0x0000, 0x03EA, 0x00EA, 0x002A, 0x001A,
+    0x0006, 0x0001, 0x0000, 0x0002, 0x000A, 0x006A, 0x01EA, 0x07EA
+];
+const TONE_IDX_MID_BITS: &[u8; 24] = &[
+    12,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 11,  9,  7,  5,
+     3,  1,  2,  4,  6,  8, 10, 12
+];
+
+const TYPE30_CODES: &[u8; 9] = &[ 0x3C, 0x06, 0x00, 0x01, 0x03, 0x02, 0x04, 0x0C, 0x1C ];
+const TYPE30_BITS: &[u8; 9] = &[ 6, 3, 3, 2, 2, 3, 4, 5, 6 ];
+
+const TYPE34_CODES: &[u8; 10] = &[ 0x18, 0x00, 0x01, 0x04, 0x05, 0x07, 0x03, 0x02, 0x06, 0x08 ];
+const TYPE34_BITS: &[u8; 10] = &[ 5, 4, 3, 3, 3, 3, 3, 3, 3, 5 ];
+
+const SB_NOISE_ATTENUATION: [f32; 32] = [
+    0.0, 0.0, 0.3, 0.4, 0.5, 0.7, 1.0, 1.0,
+    1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
+    1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
+    1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0
+];
+
+const QUANT_1BIT: [[f32; 3]; 2] = [[ -0.92, 0.0, 0.92 ], [ -0.89, 0.0, 0.89 ]];
+
+const QUANT_TYPE30: [f32; 8] = [
+    -1.0, -0.625, -0.291666656732559, 0.0, 0.25, 0.5, 0.75, 1.0
+];
+
+const TYPE34_DIFF: [f32; 10] = [
+    -1.0, -0.60947573184967, -0.333333343267441, -0.138071194291115, 0.0,
+    0.138071194291115, 0.333333343267441, 0.60947573184967, 1.0, 0.0
+];
+
+const DEQUANT: [[[u16; 30]; 10]; 3] = [
+  [
+    [ 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
+    [ 0, 256, 256, 205, 154, 102, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
+    [ 0, 0, 0, 51, 102, 154, 205, 256, 238, 219, 201, 183, 165, 146, 128, 110, 91, 73, 55, 37, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
+    [ 0, 0, 0, 0, 0, 0, 0, 0, 18, 37, 55, 73, 91, 110, 128, 146, 165, 183, 201, 219, 238, 256, 228, 199, 171, 142, 114, 85, 57, 28 ],
+    [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
+    [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
+    [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
+    [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
+    [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
+    [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
+  ], [
+    [ 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
+    [ 0, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
+    [ 0, 0, 256, 171, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
+    [ 0, 0, 0, 85, 171, 256, 171, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
+    [ 0, 0, 0, 0, 0, 0, 85, 171, 256, 219, 183, 146, 110, 73, 37, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
+    [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 73, 110, 146, 183, 219, 256, 228, 199, 171, 142, 114, 85, 57, 28, 0, 0, 0, 0, 0, 0 ],
+    [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 57, 85, 114, 142, 171, 199, 228, 256, 213, 171, 128, 85, 43 ],
+    [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
+    [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
+    [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
+  ], [
+    [ 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
+    [ 0, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
+    [ 0, 0, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
+    [ 0, 0, 0, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
+    [ 0, 0, 0, 0, 256, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
+    [ 0, 0, 0, 0, 0, 0, 256, 171, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
+    [ 0, 0, 0, 0, 0, 0, 0, 85, 171, 256, 192, 128, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
+    [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 128, 192, 256, 205, 154, 102, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
+    [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 102, 154, 205, 256, 213, 171, 128, 85, 43, 0, 0, 0, 0, 0, 0 ],
+    [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 85, 128, 171, 213, 256, 213, 171, 128, 85, 43 ]
+  ]
+];
+
+/*const TONE_LEVEL_IDX_OFFSET: [[i8; 4]; 30] = [
+    [ -50, -50,  0, -50 ],
+    [ -50, -50,  0, -50 ],
+    [ -50,  -9,  0, -19 ],
+    [ -16,  -6,  0, -12 ],
+    [ -11,  -4,  0,  -8 ],
+    [  -8,  -3,  0,  -6 ],
+    [  -7,  -3,  0,  -5 ],
+    [  -6,  -2,  0,  -4 ],
+    [  -5,  -2,  0,  -3 ],
+    [  -4,  -1,  0,  -3 ],
+    [  -4,  -1,  0,  -2 ],
+    [  -3,  -1,  0,  -2 ],
+    [  -3,  -1,  0,  -2 ],
+    [  -3,  -1,  0,  -2 ],
+    [  -2,  -1,  0,  -1 ],
+    [  -2,  -1,  0,  -1 ],
+    [  -2,  -1,  0,  -1 ],
+    [  -2,   0,  0,  -1 ],
+    [  -2,   0,  0,  -1 ],
+    [  -1,   0,  0,  -1 ],
+    [  -1,   0,  0,  -1 ],
+    [  -1,   0,  0,  -1 ],
+    [  -1,   0,  0,  -1 ],
+    [  -1,   0,  0,  -1 ],
+    [  -1,   0,  0,  -1 ],
+    [  -1,   0,  0,  -1 ],
+    [  -1,   0,  0,   0 ],
+    [  -1,   0,  0,   0 ],
+    [  -1,   0,  0,   0 ],
+    [  -1,   0,  0,   0 ]
+];*/
+
+const COEFFS_PER_SB_AVG: [[u8; 4]; 3] = [
+    [ 2, 3, 3, 3 ],
+    [ 4, 5, 6, 6 ],
+    [ 5, 7, 9, 9 ]
+];
+
+/*const COEFFS_PER_SB_AVG: [[u8; 30]; 3] = [
+  [ 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ],
+  [ 0, 1, 2, 2, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 ],
+  [ 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9 ]
+];*/
+
+const COEFFS_PER_SB_DEQUANT: [[u8; 30]; 3] = [
+  [ 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3 ],
+  [ 0, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6 ],
+  [ 0, 1, 2, 3, 4, 4, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9 ]
+];
+
+const QUANT_WEIGHT: [[u8; 30]; 5] = [
+  [
+    34, 30, 24, 24, 16, 16, 16, 16, 10, 10, 10, 10, 10, 10, 10,
+    10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10
+  ], [
+    34, 30, 24, 24, 16, 16, 16, 16, 10, 10, 10, 10, 10, 10, 10,
+    10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10
+  ], [
+    34, 30, 30, 30, 24, 24, 16, 16, 16, 16, 16, 16, 10, 10, 10,
+    10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10
+  ], [
+    34, 34, 30, 30, 24, 24, 24, 24, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 10, 10, 10, 10, 10, 10, 10, 10
+  ], [
+    34, 34, 30, 30, 30, 30, 30, 30, 24, 24, 24, 24, 24, 24, 24,
+    24, 24, 24, 24, 24, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16
+  ]
+];