From 31cf33aceca7798294e1ce5c01702ef5e6ef7adc Mon Sep 17 00:00:00 2001 From: Kostya Shishkov Date: Tue, 5 May 2020 16:21:47 +0200 Subject: [PATCH] add VivoActive (imperfect) format family support --- nihav-registry/src/detect.rs | 12 + nihav-registry/src/register.rs | 5 + nihav-vivo/Cargo.toml | 25 + nihav-vivo/src/codecs/g723_1.rs | 2203 +++++++++++++++++++++++++++++++ nihav-vivo/src/codecs/mod.rs | 31 + nihav-vivo/src/codecs/siren.rs | 895 +++++++++++++ nihav-vivo/src/codecs/vivo.rs | 513 +++++++ nihav-vivo/src/demuxers/mod.rs | 22 + nihav-vivo/src/demuxers/vivo.rs | 268 ++++ nihav-vivo/src/lib.rs | 8 + 10 files changed, 3982 insertions(+) create mode 100644 nihav-vivo/Cargo.toml create mode 100644 nihav-vivo/src/codecs/g723_1.rs create mode 100644 nihav-vivo/src/codecs/mod.rs create mode 100644 nihav-vivo/src/codecs/siren.rs create mode 100644 nihav-vivo/src/codecs/vivo.rs create mode 100644 nihav-vivo/src/demuxers/mod.rs create mode 100644 nihav-vivo/src/demuxers/vivo.rs create mode 100644 nihav-vivo/src/lib.rs diff --git a/nihav-registry/src/detect.rs b/nihav-registry/src/detect.rs index aeaa06d..7d0633a 100644 --- a/nihav-registry/src/detect.rs +++ b/nihav-registry/src/detect.rs @@ -247,6 +247,18 @@ const DETECTORS: &[DetectConditions] = &[ extensions: ".smk", conditions: &[CheckItem{offs: 0, cond: &CC::Or(&CC::Str(b"SMK2"), &CC::Str(b"SMK4"))}], }, + DetectConditions { + demux_name: "vivo", + extensions: ".viv", + conditions: &[CheckItem{offs: 0, cond: &CC::In(Arg::U16BE(1), Arg::U16BE(0xFF))}, + CheckItem{offs: 2, cond: &CC::Str(b"\x0D\x0AVersion:Vivo/")}], + }, + DetectConditions { + demux_name: "vivo", + extensions: ".viv", + conditions: &[CheckItem{offs: 0, cond: &CC::In(Arg::U16BE(1), Arg::U16BE(0xFF))}, + CheckItem{offs: 3, cond: &CC::Str(b"\x0D\x0AVersion:Vivo/")}], + }, DetectConditions { demux_name: "bmv", extensions: ".bmv", diff --git a/nihav-registry/src/register.rs b/nihav-registry/src/register.rs index cba6e2d..628cc6b 100644 --- a/nihav-registry/src/register.rs +++ b/nihav-registry/src/register.rs @@ -212,6 +212,11 @@ static CODEC_REGISTER: &'static [CodecDescription] = &[ desc!(audio; "lhst250f11", "L&H StreamTalk 25kbps at 11 kHz"), desc!(audio; "lhst500f22", "L&H StreamTalk 50kpbs at 22 kHz"), desc!(audio; "lhst48", "L&H StreamTalk CELP Codec 4.8kbps at 8 kHz"), + + desc!(video; "vivo1", "VivoActive Video 1.0"), + desc!(video; "vivo2", "VivoActive Video 2.0", CODEC_CAP_REORDER), + desc!(audio; "g723.1", "ITU G.723.1"), + desc!(audio; "siren", "Polycom Siren"), ]; static AVI_VIDEO_CODEC_REGISTER: &'static [(&[u8;4], &str)] = &[ diff --git a/nihav-vivo/Cargo.toml b/nihav-vivo/Cargo.toml new file mode 100644 index 0000000..5aa02d6 --- /dev/null +++ b/nihav-vivo/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "nihav_vivo" +version = "0.1.0" +authors = ["Kostya Shishkov "] +edition = "2018" + +[dependencies.nihav_core] +path = "../nihav-core" + +[dependencies.nihav_codec_support] +path = "../nihav-codec-support" +features = ["dsp_window", "mdct", "dct", "h263"] + +[features] +default = ["all_decoders", "demuxer_vivo"] + +all_decoders = ["decoder_vivo1", "decoder_vivo2", "decoder_siren", "decoder_g723_1"] +decoders = [] + +decoder_vivo1 = ["decoders"] +decoder_vivo2 = ["decoders"] +decoder_g723_1 = ["decoders"] +decoder_siren = ["decoders"] + +demuxer_vivo = [] diff --git a/nihav-vivo/src/codecs/g723_1.rs b/nihav-vivo/src/codecs/g723_1.rs new file mode 100644 index 0000000..840bb94 --- /dev/null +++ b/nihav-vivo/src/codecs/g723_1.rs @@ -0,0 +1,2203 @@ +use nihav_core::formats::SND_S16_FORMAT; +use nihav_core::frame::*; +use nihav_core::codecs::*; +use nihav_core::io::bitreader::*; +use std::str::FromStr; + +const SAMPLES: usize = 240; +const SUBFRAMES: usize = 4; +const SUBFRAME_LEN: usize = SAMPLES / SUBFRAMES; +const LPC_ORDER: usize = 10; +const MIN_PITCH_LAG: usize = 18; +const MAX_PITCH: usize = MIN_PITCH_LAG + 127; +const MAX_ERASED_FRAMES:u8 = 3; +const MAX_PULSES: usize = 6; + +#[derive(Clone,Copy,PartialEq)] +enum G7231FrameType { + Active, + SID, + Untransmitted, +} + +#[derive(Clone,Copy,Default)] +struct Subframe { + pitch_lag: usize, + acb_lag: usize, + acb_gain: usize, + dirac_train: bool, + pulse_sign: u8, + grid_index: usize, + amp_index: usize, + pulse_pos: usize, + + ppf_index: usize, + ppf_opt_gain: i32, + ppf_sc_gain: i32, +} + +impl Subframe { + fn read_acb_params(&mut self, br: &mut BitReader, is_6300: bool) -> DecoderResult<()> { + let mut val = br.read(12)? as usize; + let acb_len; + if is_6300 && (self.pitch_lag < SUBFRAME_LEN - 2) { + self.dirac_train = (val >> 11) != 0; + val &= 0x7FF; + acb_len = 85; + } else { + self.dirac_train = false; + acb_len = 170; + } + self.acb_gain = val / 24; + self.amp_index = val % 24; + validate!(self.acb_gain < acb_len); + + Ok(()) + } + fn gen_fcb_excitation(&self, dst: &mut [i16], is_6300: bool, max_pos: usize, npulses: usize) { + for el in dst.iter_mut().take(SUBFRAME_LEN) { + *el = 0; + } + let fcb_gain = FIXED_CB_GAIN[self.amp_index]; + if is_6300 { + if self.pulse_pos >= max_pos { + return; + } + let mut pulse = MAX_PULSES - npulses; + let mut ppos = self.pulse_pos; + for i in 0..SUBFRAME_LEN/2 { + let ret = ppos.checked_sub(PULSE_POSITIONS[pulse][i] as usize); + if let Some(new_ppos) = ret { + ppos = new_ppos; + continue; + } + pulse += 1; + let sign = (self.pulse_sign & (1 << (MAX_PULSES - pulse))) != 0; + dst[i * 2 + self.grid_index] = if !sign { fcb_gain } else { -fcb_gain }; + if pulse == MAX_PULSES { + break; + } + } + if self.dirac_train { + let mut orig = [0; SUBFRAME_LEN]; + orig.copy_from_slice(&dst[..SUBFRAME_LEN]); + for i in (self.pitch_lag..SUBFRAME_LEN).step_by(self.pitch_lag) { + for j in 0..SUBFRAME_LEN - i { + dst[i + j] += orig[j]; + } + } + } + } else { + let mut cb_pos = self.pulse_pos; + let mut cb_sign = self.pulse_sign; + for i in (0..8).step_by(2) { + let off = (cb_pos & 7) * 8 + i + self.grid_index; + dst[off] = if (cb_sign & 1) != 0 { fcb_gain } else { -fcb_gain }; + cb_pos >>= 3; + cb_sign >>= 1; + } + + let lag = (PITCH_CONTRIBUTION[self.acb_gain * 2] as isize + self.pitch_lag as isize + self.acb_lag as isize - 1) as usize; + let beta = PITCH_CONTRIBUTION[self.acb_gain * 2 + 1]; + if lag < SUBFRAME_LEN - 2 { + for i in lag..SUBFRAME_LEN { + dst[i] += ((beta * i32::from(dst[i - lag])) >> 15) as i16; + } + } + } + } + fn gen_acb_excitation(&mut self, acb_vector: &mut [i16; SUBFRAME_LEN], excitation: &[i16], is_6300: bool) { + let lag = self.pitch_lag + self.acb_lag - 1; + + let mut residual = [0; SUBFRAME_LEN + 5 - 1]; + residual[0] = excitation[MAX_PITCH - 2 - lag]; + residual[1] = excitation[MAX_PITCH - 1 - lag]; + for (i, dst) in residual.iter_mut().skip(2).enumerate() { + *dst = excitation[MAX_PITCH - lag + i % lag]; + } + + let codebook = if is_6300 && self.pitch_lag < SUBFRAME_LEN - 2 { + &ACB_GAIN85[self.acb_gain] + } else { + &ACB_GAIN170[self.acb_gain] + }; + for i in 0..SUBFRAME_LEN { + let sum = dot_product(&residual[i..], codebook, 5); + acb_vector[i] = (sum.saturating_add(sum).saturating_add(1 << 15) >> 16) as i16; + } + } + fn compute_ppf_coeffs(&mut self, src: &[i16], offset: usize, is_6300: bool) { + self.ppf_index = offset; + self.ppf_opt_gain = 0; + self.ppf_sc_gain = 0x7FFF; + + let (fwd_lag, fwd_energy) = autocorr_max(src, offset, SUBFRAME_LEN, self.pitch_lag, true); + let (bwd_lag, bwd_energy) = autocorr_max(src, offset, SUBFRAME_LEN, self.pitch_lag, false); + if fwd_lag == 0 && bwd_lag == 0 { + return; + } + + let tgt_energy = dot_product(&src[offset..], &src[offset..], SUBFRAME_LEN); + let fwd_res_energy = if fwd_lag != 0 { + dot_product(&src[offset + fwd_lag..], &src[offset + fwd_lag..], SUBFRAME_LEN) + } else { 0 }; + let bwd_res_energy = if bwd_lag != 0 { + dot_product(&src[offset - bwd_lag..], &src[offset - bwd_lag..], SUBFRAME_LEN) + } else { 0 }; + + let max_energy = tgt_energy.max(fwd_energy).max(fwd_res_energy).max(bwd_energy).max(bwd_res_energy); + let scale = norm_bits(max_energy, 31); + let tgt_energy = tgt_energy << scale >> 16; + let fwd_energy = fwd_energy << scale >> 16; + let fwd_res_energy = fwd_res_energy << scale >> 16; + let bwd_energy = bwd_energy << scale >> 16; + let bwd_res_energy = bwd_res_energy << scale >> 16; + + let use_fwd = if fwd_lag != 0 && bwd_lag == 0 { + true + } else if fwd_lag == 0 { + false + } else { + let tmp1 = bwd_res_energy * ((fwd_energy * fwd_energy + (1 << 14)) >> 15); + let tmp2 = fwd_res_energy * ((bwd_energy * bwd_energy + (1 << 14)) >> 15); + tmp1 >= tmp2 + }; + if use_fwd { + self.compute_ppf_gains(offset + fwd_lag, is_6300, tgt_energy, fwd_energy, fwd_res_energy); + } else { + self.compute_ppf_gains(offset - bwd_lag, is_6300, tgt_energy, bwd_energy, bwd_res_energy); + } + } + fn compute_ppf_gains(&mut self, offset: usize, is_6300: bool, tgt_energy: i32, corr_energy: i32, res_energy: i32) { + self.ppf_index = offset; + + let tmp1 = tgt_energy * res_energy >> 1; + let tmp2 = corr_energy * corr_energy * 2; + if tmp1 >= tmp2 { + return; + } + let gain_weight = if is_6300 { 0x1800 } else { 0x2000 }; + self.ppf_opt_gain = if corr_energy >= res_energy { + gain_weight + } else { + (corr_energy << 15) / res_energy * gain_weight >> 15 + }; + + let tmp1 = (tgt_energy << 15) + (corr_energy * self.ppf_opt_gain * 2); + let tmp2 = (self.ppf_opt_gain * self.ppf_opt_gain >> 15) * res_energy; + + let residual = tmp1.saturating_add(tmp2).saturating_add(1 << 15) >> 16; + + if tgt_energy >= residual * 2 { + self.ppf_sc_gain = square_root_i32(0x7FFF0000); + } else { + let val = (tgt_energy << 14) / residual; + self.ppf_sc_gain = square_root_i32(val << 16); + } + + self.ppf_opt_gain = i32::from(clip16(self.ppf_opt_gain * self.ppf_sc_gain >> 15)); + } +} + +fn square_root_i32(val: i32) -> i32 { + let mut res = 0; + let mut exp = 1 << 14; + + for _ in 0..14 { + let res_exp = res + exp; + if val >= res_exp * res_exp * 2 { + res += exp; + } + exp >>= 1; + } + + res +} + +struct PRNG { + seed: i32, +} + +const CNG_RND_SEED: i32 = 12345; +impl PRNG { + fn new() -> Self { Self { seed: 0 } } + fn new_cng() -> Self { Self { seed: CNG_RND_SEED } } + fn reset(&mut self) { self.seed = CNG_RND_SEED; } + fn next(&mut self) -> i32 { + self.seed = self.seed.wrapping_mul(521).wrapping_add(259); + self.seed + } + fn next_range(&mut self, range: usize) -> usize { + let val = (self.next() & 0x7FFF) as usize; + val * range >> 15 + } +} + +struct G7231Decoder { + chmap: NAChannelMap, + ainfo: NAAudioInfo, + info: NACodecInfoRef, + + is_6300: bool, + prev_lsp: [i16; LPC_ORDER], + sid_lsp: [i16; LPC_ORDER], + prev_ftype: G7231FrameType, + cur_ftype: G7231FrameType, + lsp_index: [usize; 3], + subframe: [Subframe; SUBFRAMES], + excitation: [i16; MAX_PITCH + SAMPLES + 4], + prev_excitation: [i16; MAX_PITCH], + lpc: [[i16; LPC_ORDER]; SUBFRAMES], + + filt_mem: [i16; LPC_ORDER], + + interp_index: usize, + interp_gain: i16, + sid_gain: i32, + cur_gain: i32, + + fir_mem: [i16; LPC_ORDER], + iir_mem: [i32; LPC_ORDER], + reflection_coef: i32, + pf_gain: i32, + + cng_rnd: PRNG, + rnd: PRNG, + erased_frames: u8, + + synth_buf: [i16; SAMPLES + LPC_ORDER + MAX_PITCH + 4], +} + +macro_rules! weighted_sum { + ($dst: expr, $src1: expr, $weight1: expr, $src2: expr, $weight2: expr, $shift: expr) => { + let bias = 1 << ($shift - 1); + for (dst, (src1, src2)) in $dst.iter_mut().zip($src1.iter().zip($src2.iter())) { + let val = (i32::from(*src1) * $weight1 + i32::from(*src2) * $weight2 + bias) >> $shift; + *dst = clip16(val); + } + } +} + +impl G7231Decoder { + fn new() -> Self { + let prev_lsp = DC_LSP; + let sid_lsp = DC_LSP; + G7231Decoder { + chmap: NAChannelMap::from_str("C").unwrap(), + ainfo: NAAudioInfo::new(8000, 1, SND_S16_FORMAT, SAMPLES), + info: NACodecInfo::new_dummy(), + + is_6300: true, + prev_lsp, sid_lsp, + prev_ftype: G7231FrameType::SID, + cur_ftype: G7231FrameType::Untransmitted, + lsp_index: [0; 3], + subframe: [Subframe::default(); SUBFRAMES], + excitation: [0; MAX_PITCH + SAMPLES + 4], + prev_excitation: [0; MAX_PITCH], + lpc: [[0; LPC_ORDER]; SUBFRAMES], + + filt_mem: [0; LPC_ORDER], + + interp_index: 0, + interp_gain: 0, + sid_gain: 0, + cur_gain: 0, + + fir_mem: [0; LPC_ORDER], + iir_mem: [0; LPC_ORDER], + reflection_coef: 0, + pf_gain: 1 << 12, + + cng_rnd: PRNG::new_cng(), + rnd: PRNG::new(), + erased_frames: 0, + + synth_buf: [0; SAMPLES + LPC_ORDER + MAX_PITCH + 4], + } + } + fn unpack_frame(&mut self, br: &mut BitReader) -> DecoderResult<()> { + const FRAME_SIZE: [isize; 4] = [ 24, 20, 4, 1 ]; + let ftype = br.read(2)? as usize; + validate!(br.left() + 2 >= FRAME_SIZE[ftype] * 8); + if ftype == 3 { + self.cur_ftype = G7231FrameType::Untransmitted; + return Ok(()); + } + + for lsp_index in self.lsp_index.iter_mut().rev() { + *lsp_index = br.read(8)? as usize; + } + + if ftype == 2 { + self.cur_ftype = G7231FrameType::Untransmitted; + self.subframe[0].amp_index = br.read(8)? as usize; + return Ok(()); + } + + self.cur_ftype = G7231FrameType::Active; + self.is_6300 = ftype == 0; + + for i in (0..4).step_by(2) { + self.subframe[i].pitch_lag = (br.read(7)? as usize) + MIN_PITCH_LAG; + validate!(self.subframe[i].pitch_lag < MIN_PITCH_LAG + 124); + self.subframe[i + 1].pitch_lag = self.subframe[i].pitch_lag; + self.subframe[i].acb_lag = 1; + self.subframe[i + 1].acb_lag = br.read(2)? as usize; + } + + for subframe in self.subframe.iter_mut() { + subframe.read_acb_params(br, self.is_6300)?; + } + for subframe in self.subframe.iter_mut() { + subframe.grid_index = br.read(1)? as usize; + } + if self.is_6300 { + br.read(1)?; + let mut ppos = br.read(13)? as usize; + self.subframe[0].pulse_pos = ppos / 810; + ppos = ppos % 810; + self.subframe[1].pulse_pos = ppos / 90; + ppos = ppos % 90; + self.subframe[2].pulse_pos = ppos / 9; + self.subframe[3].pulse_pos = ppos % 9; + + for (i, subframe) in self.subframe.iter_mut().enumerate() { + let bits = if (i & 1) == 0 { 16 } else { 14 }; + let val = br.read(bits)? as usize; + subframe.pulse_pos = (subframe.pulse_pos << bits) | val; + } + for (i, subframe) in self.subframe.iter_mut().enumerate() { + let bits = if (i & 1) == 0 { 6 } else { 5 }; + subframe.pulse_sign = br.read(bits)? as u8; + } + } else { + for subframe in self.subframe.iter_mut() { + subframe.pulse_pos = br.read(12)? as usize; + } + for subframe in self.subframe.iter_mut() { + subframe.pulse_sign = br.read(4)? as u8; + } + } + + Ok(()) + } + fn synth_frame_active(&mut self, dst: &mut [i16], bad_frame: bool) { + const FCB_MAX_POS: [usize; 4] = [ 593775, 142506, 593775, 142506 ]; + if !bad_frame { + self.erased_frames = 0; + } else { + self.erased_frames = (self.erased_frames + 1).min(MAX_ERASED_FRAMES); + } + if bad_frame { + self.lsp_index = [0; 3]; + } + let mut cur_lsp = [0; LPC_ORDER]; + Self::inverse_quant(&self.prev_lsp, &mut cur_lsp, &self.lsp_index, bad_frame); + Self::interpolate_lsp(&mut self.lpc, &cur_lsp, &self.prev_lsp); + self.prev_lsp.copy_from_slice(&cur_lsp); + (&mut self.excitation[..MAX_PITCH]).copy_from_slice(&self.prev_excitation); + if self.erased_frames == 0 { + let mut acb_vector = [0; SUBFRAME_LEN]; + self.interp_gain = FIXED_CB_GAIN[(self.subframe[2].amp_index + self.subframe[3].amp_index) >> 1]; + let mut exc_start = MAX_PITCH; + for (i, subframe) in self.subframe.iter_mut().enumerate() { + subframe.gen_fcb_excitation(&mut self.excitation[exc_start..], self.is_6300, FCB_MAX_POS[i], if (i & 1) == 0 { 6 } else { 5 }); + subframe.gen_acb_excitation(&mut acb_vector, &self.excitation[SUBFRAME_LEN * i..], self.is_6300); + for i in 0..SUBFRAME_LEN { + let val = self.excitation[exc_start + i]; + self.excitation[exc_start + i] = val.saturating_add(val).saturating_add(acb_vector[i]); + } + exc_start += SUBFRAME_LEN; + } + self.compute_interp_index(); + let mut offset = MAX_PITCH; + for subframe in self.subframe.iter_mut() { + subframe.compute_ppf_coeffs(&self.synth_buf[LPC_ORDER..], offset, self.is_6300); + offset += SUBFRAME_LEN; + } + for i in 0..SUBFRAMES { + let src1 = &self.excitation[MAX_PITCH + i * SUBFRAME_LEN..][..SUBFRAME_LEN]; + let src2 = &self.excitation[self.subframe[i].ppf_index..][..SUBFRAME_LEN]; + let dst = &mut self.synth_buf[LPC_ORDER + i * SUBFRAME_LEN..][..SUBFRAME_LEN]; + weighted_sum!(dst, src1, self.subframe[i].ppf_sc_gain, src2, self.subframe[i].ppf_opt_gain, 15); + } + self.prev_excitation.copy_from_slice(&self.excitation[SAMPLES..][..MAX_PITCH]); + } else { + self.interp_gain = (self.interp_gain * 3 + 2) >> 2; + if self.erased_frames == MAX_ERASED_FRAMES { + for el in self.excitation.iter_mut() { + *el = 0; + } + for el in self.prev_excitation.iter_mut() { + *el = 0; + } + for el in dst.iter_mut() { + *el = 0; + } + } else { + if self.interp_index != 0 { + for i in 0..self.interp_index { + let sample = i32::from(self.excitation[MAX_PITCH + i]) * 3 >> 2; + self.synth_buf[LPC_ORDER + i] = sample as i16; + } + for i in self.interp_index..SAMPLES { + self.synth_buf[LPC_ORDER + i] = self.synth_buf[LPC_ORDER + i - self.interp_index]; + } + } else { + for i in 0..SAMPLES { + let sample = self.rnd.next().wrapping_mul(i32::from(self.interp_gain)) >> 15; + self.synth_buf[LPC_ORDER + i] = sample as i16; + } + } + self.prev_excitation.copy_from_slice(&self.synth_buf[LPC_ORDER + SAMPLES - MAX_PITCH..][..MAX_PITCH]); + } + } + self.cng_rnd.reset(); + } + fn amp_index_to_sid_gain(val: usize) -> i32 { + if val < 0x10 { + (val as i32) << 6 + } else if val < 0x20 { + ((val as i32) - 8) << 7 + } else { + ((val as i32) - 20) << 8 + } + } + fn estimate_sid_gain(cur_gain: i32, sid_gain: i32) -> i32 { + const CNG_BSEG: [i32; 3] = [ 2048, 18432, 231233 ]; + let shift = 16 - cur_gain * 2; + let t = if shift > 0 { sid_gain << shift } else { sid_gain >> -shift }; + let x = t * 273 >> 16; + if x >= CNG_BSEG[2] { + return 63; + } + let (shift, seg) = if x >= CNG_BSEG[1] { (4, 3) } else { (3, if x >= CNG_BSEG[0] { 1 } else { 0 }) }; + let seg2 = seg.min(3); + + let mut val = 1 << shift; + let mut val_add = val >> 1; + for _ in 0..shift { + let t = seg * 32 + (val << seg2); + let t2 = t * t; + if x >= t2 { + val += val_add; + } else { + val -= val_add; + } + val_add >>= 1; + } + + let t = seg * 32 + (val << seg2); + let y = t * t - x; + if y <= 0 { + let t = seg * 32 + ((val + 1) << seg2); + let t2 = t * t - x; + let val = (seg2 - 1) * 16 + val; + if t2 >= y { + val + 1 + } else { + val + } + } else { + let t = seg * 32 + ((val - 1) << seg2); + let t2 = t * t - x; + let val = (seg2 - 1) * 16 + val; + if t2 >= y { + val - 1 + } else { + val + } + } + } + fn synth_frame_other(&mut self) { + if self.cur_ftype == G7231FrameType::SID { + self.sid_gain = Self::amp_index_to_sid_gain(self.subframe[0].amp_index); + Self::inverse_quant(&self.prev_lsp, &mut self.sid_lsp, &self.lsp_index, false); + } else if self.prev_ftype == G7231FrameType::Active { + self.sid_gain = Self::estimate_sid_gain(self.cur_gain, self.sid_gain); + } + if self.prev_ftype == G7231FrameType::Active { + self.cur_gain = self.sid_gain; + } else { + self.cur_gain = (self.cur_gain * 7 + self.sid_gain) >> 3; + } + self.generate_noise(); + Self::interpolate_lsp(&mut self.lpc, &self.sid_lsp, &self.prev_lsp); + self.prev_lsp = self.sid_lsp; + } + fn generate_noise(&mut self) { + const ADAPTIVE_LAG: [usize; SUBFRAMES] = [1, 0, 1, 3]; + self.subframe[0].pitch_lag = self.cng_rnd.next_range(21) + 123; + self.subframe[1].pitch_lag = self.subframe[0].pitch_lag; + self.subframe[2].pitch_lag = self.cng_rnd.next_range(19) + 123; + self.subframe[3].pitch_lag = self.subframe[2].pitch_lag; + + for (i, subframe) in self.subframe.iter_mut().enumerate() { + subframe.acb_gain = self.cng_rnd.next_range(50) + 1; + subframe.acb_lag = ADAPTIVE_LAG[i]; + } + + let mut off = [0; 4]; + let mut signs = [[0; 11]; 2]; + for i in (0..4).step_by(2) { + let t = self.cng_rnd.next_range(1 << 13); + off[i] = t & 1; + off[i + 1] = ((t >> 1) & 1) + SUBFRAME_LEN; + for j in 0..11 { + signs[i/2][j] = ((((t >> (j + 2)) & 1) * 2 - 1) << 14) as i32; + } + } + + let mut pos = [0; 11 * SUBFRAMES]; + let mut pidx = 0; + let mut tmp = [0; SUBFRAME_LEN / 2]; + for i in 0..SUBFRAMES { + let npulses = if (i & 1) == 0 { 6 } else { 5 }; + for j in 0..npulses { + let idx = self.cng_rnd.next_range(SUBFRAME_LEN / 2 - j); + pos[pidx] = tmp[idx] * 2 + off[i]; + pidx += 1; + tmp[idx] = tmp[SUBFRAME_LEN / 2 - 1 - j]; + } + } + + (&mut self.synth_buf[LPC_ORDER..][..MAX_PITCH]).copy_from_slice(&self.prev_excitation); + let mut acb_vec = [0; SUBFRAME_LEN]; + let mut tmp = [0; SUBFRAME_LEN * 2]; + for i in (0..SUBFRAMES).step_by(2) { + let buf = &mut self.synth_buf[LPC_ORDER + SUBFRAME_LEN * i..]; + self.subframe[i].gen_acb_excitation(&mut acb_vec, buf, self.is_6300); + (&mut buf[..SUBFRAME_LEN]).copy_from_slice(&acb_vec); + self.subframe[i + 1].gen_acb_excitation(&mut acb_vec, &buf[SUBFRAME_LEN..], self.is_6300); + (&mut buf[SUBFRAME_LEN..][..SUBFRAME_LEN]).copy_from_slice(&acb_vec); + + let mut max = 0; + for j in 0..SUBFRAME_LEN*2 { + max |= i32::from(buf[j]).abs(); + } + let shift = if max == 0 { 0 } else { + (-10 + (32 - max.min(0x7FFF).leading_zeros()) as i32).max(-2) + }; + let mut sum = 0; + if shift < 0 { + for j in 0..SUBFRAME_LEN*2 { + let val = buf[j] << -shift; + sum += i64::from(val) * i64::from(val); + tmp[j] = val; + } + } else { + for j in 0..SUBFRAME_LEN*2 { + let val = buf[j] >> shift; + sum += i64::from(val) * i64::from(val); + tmp[j] = val; + } + } + + let mut b0 = 0; + for j in 0..11 { + b0 += i32::from(tmp[pos[i / 2 * 11 + j]]) * signs[i / 2][j]; + } + b0 = ((i64::from(b0) * 2 * 2979 + (1 << 29)) >> 30) as i32; + + let mut c = self.cur_gain * (self.cur_gain * (SUBFRAME_LEN as i32) >> 5); + if shift * 2 + 3 >= 0 { + c >>= shift * 2 + 3; + } else { + c <<= -(shift * 2 + 3); + } + c = (i64::from(clip32(sum * 2) - c) * 2979 >> 15) as i32; + + let delta = b0 * b0 * 2 - c; + let x = if delta <= 0 { + -b0 + } else { + let d0 = i32::from(square_root_i32(delta)); + let x0 = d0 - b0; + let t = d0 + b0; + if t.abs() < x0.abs() { + -t + } else { + x0 + } + }; + let shift = shift + 1; + let x = (if shift >= 0 { x << shift } else { x >> -shift }).min(10000).max(-10000); + for j in 0..11 { + let val = x * signs[i / 2][j] >> 15; + buf[pos[i / 2 * 11 + j]] = buf[pos[i / 2 * 11 + j]].saturating_add(val as i16); + } + + for j in 0..SUBFRAME_LEN*2 { + buf[MAX_PITCH + j] = buf[j]; + } + } + self.prev_excitation.copy_from_slice(&self.synth_buf[LPC_ORDER + SAMPLES..][..MAX_PITCH]); + } + fn compute_interp_index(&mut self) { + let pitch_lag = self.subframe[3].pitch_lag; + + self.cur_gain = Self::scale_vector(&mut self.synth_buf[LPC_ORDER..][..SAMPLES + MAX_PITCH], &self.excitation[..SAMPLES + MAX_PITCH]); + + let (pos, cre) = autocorr_max(&self.synth_buf[LPC_ORDER..], MAX_PITCH + SUBFRAME_LEN * 2, SUBFRAME_LEN * 2, pitch_lag, false); + let corr_energy = cre.saturating_add(1 << 15) >> 16; + + let tgt_energy = dot_product(&self.synth_buf[LPC_ORDER + MAX_PITCH + SUBFRAME_LEN * 2..], &self.synth_buf[LPC_ORDER + MAX_PITCH + SUBFRAME_LEN * 2..], SUBFRAME_LEN * 2); + self.sid_gain = tgt_energy.saturating_add(1 << 15) >> 16; + + if corr_energy <= 0 { + self.interp_index = 0; + return; + } + + let best_energy = dot_product(&self.synth_buf[LPC_ORDER + MAX_PITCH + SUBFRAME_LEN * 2 - pos..], &self.synth_buf[LPC_ORDER + MAX_PITCH + SUBFRAME_LEN * 2 - pos..], SUBFRAME_LEN * 2); + let best_energy = best_energy.saturating_add(1 << 15) >> 16; + + let tmp = best_energy * self.sid_gain >> 3; + + if tmp < corr_energy * corr_energy { + self.interp_index = pos; + } else { + self.interp_index = 0; + } + } + fn scale_vector(dst: &mut [i16], src: &[i16]) -> i32 { + let mut max = 0; + for el in src.iter() { + max = max.max(i32::from(*el).abs()); + } + max = max.min(0x7FFF); + let shift = norm_bits(max, 15); + for (dst, src) in dst.iter_mut().zip(src.iter()) { + *dst = *src << shift >> 3; + } + i32::from(shift) - 3 + } + fn inverse_quant(prev_lsp: &[i16; LPC_ORDER], lsp: &mut [i16; LPC_ORDER], lsp_index: &[usize; 3], bad_frame: bool) { + let (min_dist, pred) = if !bad_frame { (0x100, 12288) } else { (0x200, 23552) }; + lsp[0] = LSP_CODEBOOK0[lsp_index[0]][0]; + lsp[1] = LSP_CODEBOOK0[lsp_index[0]][1]; + lsp[2] = LSP_CODEBOOK0[lsp_index[0]][2]; + lsp[3] = LSP_CODEBOOK1[lsp_index[1]][0]; + lsp[4] = LSP_CODEBOOK1[lsp_index[1]][1]; + lsp[5] = LSP_CODEBOOK1[lsp_index[1]][2]; + lsp[6] = LSP_CODEBOOK2[lsp_index[2]][0]; + lsp[7] = LSP_CODEBOOK2[lsp_index[2]][1]; + lsp[8] = LSP_CODEBOOK2[lsp_index[2]][2]; + lsp[9] = LSP_CODEBOOK2[lsp_index[2]][3]; + + for i in 0..LPC_ORDER { + let diff = ((i32::from(prev_lsp[i]) - i32::from(DC_LSP[i])) * pred + (1 << 14)) >> 15; + lsp[i] = (i32::from(lsp[i]) + i32::from(DC_LSP[i]) + diff) as i16; + } + + let mut stable = false; + + for _ in 0..LPC_ORDER { + lsp[0] = lsp[0].max(0x100); + lsp[LPC_ORDER - 1] = lsp[LPC_ORDER - 1].min(0x7E00); + + for i in 1..LPC_ORDER { + let mut val = min_dist + lsp[i - 1] - lsp[i]; + if val > 0 { + val >>= 1; + lsp[i - 1] -= val; + lsp[i] += val; + } + } + stable = true; + for i in 1..LPC_ORDER { + let val = lsp[i - 1] + min_dist - lsp[i] - 4; + if val > 0 { + stable = false; + break; + } + } + if stable { + break; + } + } + if !stable { + lsp.copy_from_slice(prev_lsp); + } + } + fn interpolate_lsp(lpc: &mut [[i16; LPC_ORDER]; SUBFRAMES], lsp: &[i16; LPC_ORDER], prev_lsp: &[i16; LPC_ORDER]) { + weighted_sum!(lpc[0], lsp, 0x1000, prev_lsp, 0x3000, 14); + weighted_sum!(lpc[1], lsp, 0x2000, prev_lsp, 0x2000, 14); + weighted_sum!(lpc[2], lsp, 0x3000, prev_lsp, 0x1000, 14); + lpc[3].copy_from_slice(lsp); + for clpc in lpc.iter_mut() { + Self::lsp2lpc(clpc); + } + } + fn lsp2lpc(lpc: &mut [i16; LPC_ORDER]) { + let mut tmp1 = [0; LPC_ORDER/2 + 1]; + let mut tmp2 = [0; LPC_ORDER/2 + 1]; + + for lpc in lpc.iter_mut() { + let index = ((*lpc >> 7) & 0x1FF) as usize; + let offset = (i32::from(*lpc & 0x7F) << 8) + 0x80; + let val1 = i32::from(COS_TAB[index]); + let val2 = (i32::from(COS_TAB[index + 1]) - val1) * offset * 2; + *lpc = -(((val1 << 17) + val2 * 2).saturating_add(1 << 15) >> 16) as i16; + } + + tmp1[0] = 1 << 28; + tmp1[1] = (i32::from(lpc[0]) << 14) + (i32::from(lpc[2]) << 14); + tmp1[2] = i32::from(lpc[0]) * i32::from(lpc[2]) + (2 << 28); + + tmp2[0] = 1 << 28; + tmp2[1] = (i32::from(lpc[1]) << 14) + (i32::from(lpc[3]) << 14); + tmp2[2] = i32::from(lpc[1]) * i32::from(lpc[3]) + (2 << 28); + + for i in 2..LPC_ORDER/2 { + tmp1[i + 1] = tmp1[i - 1] + mul16(tmp1[i], lpc[i * 2]); + tmp2[i + 1] = tmp2[i - 1] + mul16(tmp2[i], lpc[i * 2 + 1]); + + for j in (2..=i).rev() { + tmp1[j] = mul16(tmp1[j - 1], lpc[i * 2]) + (tmp1[j] >> 1) + (tmp1[j - 2] >> 1); + tmp2[j] = mul16(tmp2[j - 1], lpc[i * 2 + 1]) + (tmp2[j] >> 1) + (tmp2[j - 2] >> 1); + } + + tmp1[0] >>= 1; + tmp2[0] >>= 1; + tmp1[1] = (tmp1[1] + (i32::from(lpc[2 * i]) << 16 >> i)) >> 1; + tmp2[1] = (tmp2[1] + (i32::from(lpc[2 * i + 1]) << 16 >> i)) >> 1; + } + + for i in 0..LPC_ORDER/2 { + let c0 = i64::from(tmp1[i + 1]) + i64::from(tmp1[i]); + let c1 = i64::from(tmp2[i + 1]) - i64::from(tmp2[i]); + lpc[i] = (clip32((c0 + c1) * 8 + (1 << 15)) >> 16) as i16; + lpc[LPC_ORDER - i - 1] = (clip32((c0 - c1) * 8 + (1 << 15)) >> 16) as i16; + } + } + fn do_lpc(buf: &mut [i16], offset: usize, lpc: &[i16; LPC_ORDER]) { + for i in 0..SUBFRAME_LEN { + let mut sum = 0i32; + for j in 0..LPC_ORDER { + sum = sum.wrapping_sub(i32::from(buf[offset + i - j - 1]) * i32::from(lpc[j])); + } + let pred = (sum + (1 << 12)) >> 12; + buf[offset + i] = clip16((i32::from(buf[offset + i]) + pred) >> 1); + } + } + fn formant_postfilter(&mut self, dst: &mut [i16]) { + (&mut self.synth_buf[..LPC_ORDER]).copy_from_slice(&self.fir_mem); + let mut filter_data = [0; LPC_ORDER + SAMPLES]; + (&mut filter_data[..LPC_ORDER]).copy_from_slice(&self.iir_mem); + + let mut filter_coef = [[0; LPC_ORDER]; 2]; + for i in 0..SUBFRAMES { + for j in 0..LPC_ORDER { + filter_coef[0][j] = (i32::from(-self.lpc[i][j]) * i32::from(POSTFILTER_COEFFS[0][j]) + (1 << 14)) >> 15; + filter_coef[1][j] = (i32::from(-self.lpc[i][j]) * i32::from(POSTFILTER_COEFFS[1][j]) + (1 << 14)) >> 15; + } + Self::iir_filter(&filter_coef, &self.synth_buf, &mut filter_data, LPC_ORDER + i * SUBFRAME_LEN); + } + self.fir_mem.copy_from_slice(&self.synth_buf[SAMPLES..][..LPC_ORDER]); + self.iir_mem.copy_from_slice(&filter_data[SAMPLES..]); + let mut offset = 0; + for _ in 0..SUBFRAMES { + let scale = Self::scale_vector(&mut dst[offset..][..SUBFRAME_LEN], &self.synth_buf[offset + LPC_ORDER..][..SUBFRAME_LEN]); + let ac1 = dot_product(&dst[offset..], &dst[offset + 1..], SUBFRAME_LEN - 1); + let ac0 = dot_product(&dst[offset..], &dst[offset..], SUBFRAME_LEN); + let tmp = if (ac0 >> 16) != 0 { (ac1 >> 2) / (ac0 >> 16) } else { 0 }; + self.reflection_coef = (3 * self.reflection_coef + tmp + 2) >> 2; + let gain = (-self.reflection_coef >> 1) & !3; + + for i in 0..SUBFRAME_LEN { + let val = (filter_data[offset + LPC_ORDER + i - 1] >> 16) * gain; + dst[offset + i] = (filter_data[offset + LPC_ORDER + i].saturating_add(val).saturating_add(val) >> 16) as i16; + } + + let shift = 2 * scale + 4; + let energy = if shift < 0 { clip32(i64::from(ac0) << -shift) } else { ac0 >> shift }; + Self::gain_scale(&mut self.pf_gain, &mut dst[offset..], energy); + + offset += SUBFRAME_LEN; + } + } + fn iir_filter(coef: &[[i32; LPC_ORDER]; 2], src: &[i16], dst: &mut [i32], offset: usize) { + for i in 0..SUBFRAME_LEN { + let mut sum = 0; + for j in 0..LPC_ORDER { + sum -= i64::from(coef[0][j]) * i64::from(src[offset - 1 + i - j]) - + i64::from(coef[1][j]) * i64::from(dst[offset - 1 + i - j] >> 16); + } + dst[offset + i] = clip32((i64::from(src[offset + i]) << 16) + (sum << 3) + (1 << 15)); + } + } + fn gain_scale(pf_gain: &mut i32, buf: &mut [i16], energy: i32) { + let mut den = 0i32; + for i in 0..SUBFRAME_LEN { + let val = i32::from(buf[i] >> 2); + den = den.saturating_add(val * val).saturating_add(val * val); + } + let mut num = energy; + let gain; + if (num != 0) && (den != 0) { + let bits1 = norm_bits(num, 31); + let bits2 = norm_bits(den, 31); + num = num << bits1 >> 1; + den <<= bits2; + let shift = (5 + bits1 - bits2).max(0); + + gain = square_root_i32(((num >> 1) / (den >> 16)) << 16 >> shift); + } else { + gain = 1 << 12; + } + + for i in 0..SUBFRAME_LEN { + *pf_gain = (15 * *pf_gain + gain + (1 << 3)) >> 4; + buf[i] = clip16((i32::from(buf[i]) * (*pf_gain + (*pf_gain >> 4)) + (1 << 10)) >> 11); + } + } +} + +fn clip16(a: i32) -> i16 { + a.min(i32::from(std::i16::MAX)).max(i32::from(std::i16::MIN)) as i16 +} + +fn clip32(a: i64) -> i32 { + a.min(i64::from(std::i32::MAX)).max(i64::from(std::i32::MIN)) as i32 +} + +fn mul16(a: i32, b: i16) -> i32 { + let b = i32::from(b); + (a >> 16) * b * 2 + (((a & 0xFFFF) * b) >> 15) +} + +fn norm_bits(val: i32, target: u8) -> u8 { + if val == 0 { + target + } else { + target - (32 - val.leading_zeros()) as u8 + } +} + +fn autocorr_max(src: &[i16], offset: usize, length: usize, pitch_lag: usize, forward: bool) -> (usize, i32) { + let pitch_lag = pitch_lag.min(MAX_PITCH - 3); + let mut max_energy = 0; + let mut lag = 0; + + if forward { + let end = (pitch_lag + 3).min(SAMPLES + MAX_PITCH - offset - length); + for i in pitch_lag-3..=end { + let energy = dot_product(&src[offset..], &src[offset + i..], length); + if max_energy < energy { + max_energy = energy; + lag = i; + } + } + } else { + for i in pitch_lag-3..=pitch_lag+3 { + let energy = dot_product(&src[offset..], &src[offset - i..], length); + if max_energy < energy { + max_energy = energy; + lag = i; + } + } + } + (lag, max_energy) +} + +fn dot_product(src1: &[i16], src2: &[i16], length: usize) -> i32 { + let mut sum = 0; + for (a, b) in src1.iter().zip(src2.iter()).take(length) { + sum += i64::from(*a) * i64::from(*b) + } + clip32(sum << 1) +} + +impl NADecoder for G7231Decoder { + fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> { + if let NACodecTypeInfo::Audio(_ainfo) = info.get_properties() { + self.info = info.replace_info(NACodecTypeInfo::Audio(self.ainfo)); + Ok(()) + } else { + Err(DecoderError::InvalidData) + } + } + fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult { + let info = pkt.get_stream().get_info(); + validate!(info.get_properties().is_audio()); + let src = pkt.get_buffer(); + + let mut bad_frame = false; + + let mut br = BitReader::new(src.as_slice(), BitReaderMode::LE); + if let Err(_) = self.unpack_frame(&mut br) { + bad_frame = true; + self.cur_ftype = if self.prev_ftype == G7231FrameType::Active { + G7231FrameType::Active + } else { + G7231FrameType::Untransmitted + }; + } + + let abuf = alloc_audio_buffer(self.ainfo, SAMPLES, self.chmap.clone())?; + let mut adata = abuf.get_abuf_i16().unwrap(); + let mut asamples = adata.get_data_mut().unwrap(); + if self.cur_ftype == G7231FrameType::Active { + self.synth_frame_active(&mut asamples, bad_frame); + } else { + self.synth_frame_other(); + } + self.prev_ftype = self.cur_ftype; + (&mut self.synth_buf[..LPC_ORDER]).copy_from_slice(&self.filt_mem); + for i in 0..SUBFRAMES { + Self::do_lpc(&mut self.synth_buf, LPC_ORDER + i * SUBFRAME_LEN, &self.lpc[i]); + } + self.filt_mem.copy_from_slice(&self.synth_buf[SAMPLES..][..LPC_ORDER]); + self.formant_postfilter(asamples); + + let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), abuf); + frm.set_keyframe(true); + Ok(frm.into_ref()) + } + fn flush(&mut self) { + } +} + +pub fn get_decoder() -> Box { + Box::new(G7231Decoder::new()) +} + +#[cfg(test)] +mod test { + use nihav_core::codecs::RegisteredDecoders; + use nihav_core::demuxers::RegisteredDemuxers; + use nihav_codec_support::test::dec_video::*; + use crate::vivo_register_all_codecs; + use crate::vivo_register_all_demuxers; + #[test] + fn test_g723_1() { + let mut dmx_reg = RegisteredDemuxers::new(); + vivo_register_all_demuxers(&mut dmx_reg); + let mut dec_reg = RegisteredDecoders::new(); + vivo_register_all_codecs(&mut dec_reg); + + let file = "assets/Misc/adalogo.viv"; + //let file = "assets/Misc/gr_al.viv"; + //test_decode_audio("vivo", file, Some(1500), None/*Some("g7231")*/, &dmx_reg, &dec_reg); + test_decoding("vivo", "g723.1", file, None, &dmx_reg, &dec_reg, + ExpectedTestResult::MD5([0x94e60e2f, 0x578493e7, 0xe7ab1f1c, 0xae155977])); + } +} + +const DC_LSP: [i16; LPC_ORDER] = [ + 0x0c3b, 0x1271, 0x1e0a, 0x2a36, 0x3630, + 0x406f, 0x4d28, 0x56f4, 0x638c, 0x6c46 +]; + +const LSP_CODEBOOK0: [[i16; 3]; 256] = [ + [ 0, 0, 0], [ -270, -1372, -1032], [ -541, -1650, -1382], + [ -723, -2011, -2213], [ -941, -1122, -1942], [ -780, -1145, -2454], + [ -884, -1309, -1373], [-1051, -1523, -1766], [-1083, -1622, -2300], + [ -777, -1377, -2147], [ -935, -1467, -2763], [ -802, -1327, -3471], + [ -935, -1959, -3999], [ -240, -89, 222], [ -661, -257, -160], + [ -994, -466, -419], [ -188, -164, -278], [ -342, -512, -415], + [ -607, -511, -797], [ 16, 19, -716], [ 374, 425, -972], + [ -346, 245, -282], [ -265, 506, -754], [ -620, -147, 1955], + [ -742, -860, 2597], [ -150, -352, 2704], [ 305, 880, 1954], + [ 123, 731, 2766], [ -348, 765, 3327], [ 618, 221, 3258], + [ -178, -47, 4219], [ 393, 1304, 3842], [ 698, 1702, 4801], + [ 63, -584, 1229], [ -215, -732, 1704], [ 172, -335, 1909], + [ -2, 216, 1797], [ 353, 127, 2205], [-1208, 188, 11], + [ -513, -75, -683], [ -973, 222, -646], [ -616, -843, -388], + [ -950, -1113, -359], [-1431, -623, -705], [-1398, -1063, -178], + [ -45, -461, 35], [ -9, -657, -216], [ 127, -1078, 95], + [ -950, -1156, 584], [-1480, -1494, 449], [ -120, -705, 516], + [ -368, -961, 727], [ -378, -526, 973], [ -793, -614, 676], + [ -801, -755, 1287], [-1476, -340, 1636], [ -505, -1254, 1543], + [-1243, -1622, 1532], [ -776, -1477, -655], [-1151, -1296, -823], + [-1153, -1672, -1124], [-1291, -2003, -1702], [ -622, -1283, 57], + [ -471, -1611, 509], [-1060, -1570, -139], [ -873, -2156, -536], + [-1716, -2021, -364], [-2150, -3218, -1291], [-1248, -1945, -2904], + [-1215, -2633, -2855], [ 167, -244, 84], [ 349, -412, -217], + [ -40, -352, 632], [ 227, -529, 405], [ 68, -383, -443], + [ 167, -558, -706], [ -275, -854, -14], [ -351, -1089, -449], + [ 341, -72, -289], [ 603, -106, -474], [ 322, -219, -649], + [ 179, -317, -998], [ 450, -291, -996], [ 555, 195, -525], + [ 784, 272, -831], [ -148, -384, -849], [ 82, -536, -1357], + [ 238, -172, -1354], [ 422, -268, -1841], [ 297, -737, -2079], + [ -111, -801, -598], [ 1, -668, -984], [ -131, -818, -1299], + [ -329, -521, -1310], [ -151, -778, -1834], [ -93, -352, -1746], + [ -568, -640, -1821], [ -509, -941, -2183], [ 464, -815, -1250], + [ 79, -1133, -1597], [ -184, -1353, -2123], [ -196, -410, -2427], + [ -192, -833, -2810], [ -259, -1382, -3045], [ -217, 4, -1166], + [ -800, -325, -1219], [ -363, -830, -898], [ -661, -1134, -960], + [ -386, -980, -1501], [ -627, -1159, -1722], [ -903, -829, -855], + [ -685, -829, -1313], [-1065, -959, -1405], [ 441, 25, -847], + [ 655, -27, -1181], [ 1159, -110, -705], [ 856, 253, -1671], + [ 415, 404, -1], [ 322, 903, -398], [ 670, 499, -292], + [ 803, 591, -610], [ 1144, 591, -814], [ 717, 183, 393], + [ 857, 381, 106], [ 609, 62, -27], [ 792, 198, -325], + [ 735, 805, 88], [ 1142, 812, 78], [ 1028, 366, -292], + [ 1309, 743, -237], [ 1615, 589, -79], [ 1010, 639, -243], + [ 999, 964, -311], [ 1500, 1137, -615], [ 988, 357, 646], + [ 1227, 667, 683], [ 1164, 1565, 894], [ 1392, 2015, 477], + [ 1138, 533, 250], [ 1437, 896, 391], [ 1765, 1118, 99], + [ 1112, 1090, 802], [ 1596, 846, 1134], [ 937, 1161, 279], + [ 1719, 1254, 683], [ 1338, 1086, 35], [ 1419, 1324, 428], + [ 1428, 1524, 40], [ 2108, 1594, 89], [ 1015, 544, 1222], + [ 1121, 925, 1263], [ 1030, 1318, 1485], [ 1295, 789, 1817], + [ 1323, 1272, 1909], [ 1724, 1237, 1803], [ 1797, 1689, 858], + [ 2149, 1367, 1301], [ 2302, 1867, 761], [ 2863, 2351, 1053], + [ 52, 163, -76], [ 230, 309, -492], [ -71, 619, 39], + [ -218, 856, 499], [ -654, 736, -207], [ -535, 1259, 155], + [ -480, 1476, 643], [ 262, 1081, 102], [ 309, 1592, -182], + [ 627, 1629, 534], [ 337, 643, 456], [ 758, 670, 713], + [ 202, 1126, 658], [ 612, 1131, 666], [ 686, 1223, 1136], + [ -131, 377, 525], [ 42, 708, 907], [ 87, 1488, 1035], + [ 432, 2117, 904], [ 137, 981, 1332], [ -447, 1014, 1136], + [ -839, 1793, 1246], [ -559, 297, 198], [ -850, 685, 446], + [-1273, 632, 826], [ -401, -544, 173], [ -753, -793, 144], + [ -436, -9, 772], [ -115, -243, 1310], [ -670, -269, 374], + [-1027, -13, 639], [ -887, -81, 1137], [-1277, -455, 158], + [-1411, -720, 736], [ 172, 88, 403], [ 386, 255, 756], + [ -500, 522, 910], [ -958, 659, 1388], [ -395, 301, 1344], + [ -356, 768, 1813], [ -613, 841, 2419], [ 445, -122, 252], + [ 629, -87, 723], [ 283, -253, 870], [ 456, -116, 1381], + [ 757, 180, 1059], [ 532, 408, 1509], [ 947, 288, 1806], + [ 1325, 994, 2524], [ 892, 1219, 3023], [ 1397, 1596, 3406], + [ 1143, 1552, 2546], [ 1850, 1433, 2710], [ -10, 134, 1002], + [ 154, 499, 1323], [ 508, 792, 1117], [ 509, 1340, 1616], + [ 762, 862, 1608], [ 787, 740, 2320], [ 794, 1727, 1283], + [ 465, 2108, 1660], [ -120, 1451, 1613], [ -386, 2016, 2169], + [ 891, 1225, 2050], [ 456, 1480, 2185], [ 1493, 1283, 1209], + [ 1397, 1636, 1518], [ 1776, 1738, 1552], [ 1572, 1698, 2141], + [ 1389, 2126, 1271], [ 1959, 2413, 1119], [ 1365, 2892, 1505], + [ 2206, 1971, 1623], [ 2076, 1950, 2280], [ 1717, 2291, 1867], + [ 2366, 2515, 1953], [ 2865, 2838, 2522], [ 2535, 3465, 2011], + [ 3381, 4127, 2638], [ 836, 2667, 2289], [ 1761, 2773, 2337], + [ 1415, 3325, 2911], [ 2354, 3138, 3126], [ 2659, 4192, 4010], + [ 1048, 1786, 1818], [ 1242, 2111, 2240], [ 1512, 2079, 2780], + [ 1573, 2491, 3138], [ 2230, 2377, 2782], [ 416, 1773, 2704], + [ 725, 2336, 3297], [ 1252, 2373, 3978], [ 2094, 2268, 3568], + [ 2011, 2712, 4528], [ 1341, 3507, 3876], [ 1216, 3919, 4922], + [ 1693, 4793, 6012] +]; + +const LSP_CODEBOOK1: [[i16; 3]; 256] = [ + [ 0, 0, 0], [-2114, -1302, 76], [-2652, -1278, -1368], + [-2847, -828, -349], [-3812, -2190, -349], [-3946, -364, -449], + [-2725, -4492, -3607], [-3495, -4764, -1744], [ -51, -756, 84], + [ -153, -1191, 504], [ 108, -1418, 1167], [ -835, -896, 390], + [ -569, -1702, 87], [-1151, -1818, 933], [-1826, -2547, 411], + [-1842, -1818, 1451], [-2438, -1611, 781], [-2747, -2477, 1311], + [ -940, 1252, 477], [-1629, 1688, 602], [-1202, 617, 280], + [-1737, 393, 580], [-1528, 1077, 1199], [-2165, -161, 1408], + [-2504, -1087, 2371], [-3458, -175, 1395], [-1397, -98, -843], + [-2252, -177, -1149], [-1489, -726, -1283], [-1558, -265, -1744], + [-1867, -821, -1897], [-2062, -1516, -2340], [-2595, -1142, -2861], + [ 170, 46, -819], [ -193, -204, -1151], [ 326, -196, -1532], + [ 780, 329, -816], [ 201, 369, -1243], [ 650, -209, -1060], + [ 1144, -15, -1216], [ 1203, -259, -1867], [ -890, -564, -1430], + [ -638, -852, -1921], [ 177, -739, -1358], [ -261, -526, -1666], + [ 206, -407, -2255], [ 338, -526, -822], [ 421, -1095, -1009], + [ 765, -607, -1408], [ 825, -1295, -2004], [ 357, -905, -1815], + [ -58, -1248, -1588], [ -596, -1436, -2046], [ -73, -1159, -2116], + [ -115, -1382, -2581], [ -160, -1723, -1952], [ -6, -2196, -2954], + [ -649, -1705, -2603], [ -617, -1453, -3282], [ -949, -2019, -3102], + [ -812, 1544, 1937], [-1854, 574, 2000], [-1463, 1140, 2649], + [-2683, 1748, 1452], [-2486, 2241, 2523], [ 783, 1910, 1435], + [ 581, 2682, 1376], [ 236, 2197, 1885], [ -453, 2943, 2057], + [ -682, 2178, 2565], [-1342, 3201, 3328], [ -288, -184, 262], + [ 121, -149, -183], [ 758, -412, 206], [ 1038, -204, 853], + [ 1577, -457, 700], [ 937, -640, -567], [ 1508, -528, -1024], + [ -225, -527, -427], [ -564, -1095, -332], [ -742, -353, -186], + [-1288, -459, 84], [-1853, -484, -274], [-1554, -731, 825], + [-2425, -234, 382], [-1722, 293, -271], [-2515, 425, -564], + [-2599, 818, 464], [ -358, 118, -375], [ -613, 198, -874], + [ -690, 683, -324], [-1352, 1155, -168], [-1093, 129, -324], + [-1184, 611, -858], [ 433, 386, -372], [ -120, 486, -634], + [ 234, 851, -631], [ 602, 128, 46], [ 1099, 410, 159], + [ 715, -145, -424], [ 1198, -85, -593], [ 1390, 367, -358], + [ 1683, 362, -964], [ 1711, 622, 45], [ 2033, 833, -383], + [ 2890, 549, -506], [ 7, 401, 52], [ 72, 811, 415], + [ 566, 668, 41], [ 467, 1218, 130], [ 68, 957, -187], + [ -25, 1649, -103], [ -661, 260, 214], [ -925, -94, 612], + [ -321, -422, 965], [ -788, -672, 1783], [ 400, -673, 779], + [ 741, -595, 1635], [ -161, 307, 657], [ -382, 836, 871], + [ -814, 400, 1223], [ 364, 606, 1247], [ 57, 75, 1571], + [ 151, 471, 2287], [ -81, 1021, 1502], [ 227, 1470, 1097], + [ 658, 1275, 1653], [ 664, 1478, 2377], [ 263, -127, 444], + [ 264, 89, 969], [ 794, 171, 576], [ 821, 186, 1226], + [ 404, 462, 517], [ 339, 918, 794], [ 1280, 1423, 196], + [ 1453, 2019, 365], [ 1615, 1481, 672], [ 2394, 1708, 508], + [ 806, 1238, 573], [ 713, 1158, 1078], [ 1285, 1436, 1232], + [ 1790, 1188, 1141], [ 765, 643, 864], [ 1032, 797, 1279], + [ 900, 563, 1827], [ 1514, 673, 2312], [ 1544, 1129, 3240], + [ 1469, 1050, 1594], [ 1945, 1318, 1988], [ 2397, 2026, 2060], + [ 3538, 2057, 2620], [ 1249, -118, 74], [ 1727, 194, 421], + [ 2078, -50, -463], [ 970, 688, -432], [ 1149, 952, -110], + [ 1254, 1275, -651], [ 1386, 929, 401], [ 1960, 1167, 232], + [ 407, -752, -243], [ 859, -1118, 172], [ -227, -860, -992], + [ -796, -1175, -1380], [ 8, -1282, -388], [ 353, -1781, -1037], + [ -732, -397, -807], [ -853, -28, -1342], [-1229, -1207, -1959], + [-1015, -1125, -2543], [-1452, -1791, -2725], [-1891, -2416, -3269], + [ -918, -1629, -783], [ -580, -2155, -698], [-1097, -2364, -96], + [-1387, -1513, 7], [-1588, -2076, -664], [-1473, -2740, -784], + [-2378, -3149, -56], [-2856, -2092, -169], [-3391, -3708, 316], + [-1176, -890, -614], [-1944, -1061, -800], [ -299, -1517, -1000], + [ -640, -1850, -1526], [-1454, -1536, -1233], [-1890, -1955, -1756], + [-1086, -1921, -2122], [ -750, -2325, -2260], [-1325, -2413, -2673], + [-1114, -2542, -3459], [-1341, -2901, -3963], [-1160, -2226, -1393], + [-1001, -2772, -1573], [-1594, -2641, -1978], [-1534, -3046, -2624], + [-2224, -2196, -675], [-2807, -3054, -1102], [-2008, -2840, -1186], + [-1980, -3332, -1695], [-1715, -3562, -505], [-2527, -4000, -1887], + [-2333, -2734, -2296], [-3440, -2401, -3211], [-2008, -3528, -3337], + [-2247, -3291, -4510], [ -475, 949, 155], [ -149, 1365, 545], + [ -757, 1644, 1083], [ -217, 2053, 1353], [-1433, 2301, 1462], + [ 495, 1661, 529], [ 10, 2037, 740], [ 2082, 1898, 978], + [ 2831, 2294, 911], [ 842, 793, 420], [ 1223, 1023, 863], + [ 1237, 451, 780], [ 1744, 708, 822], [ 1533, 284, 1384], + [ 2135, 609, 1538], [ 2305, 626, 540], [ 2368, 1187, 955], + [ 2586, 1255, -7], [ 3116, 1131, 726], [ 3431, 1730, 428], + [ 2734, 1648, 1307], [ 2988, 1231, 2010], [ 3523, 2024, 1488], + [ 1034, 1657, 871], [ 1206, 2163, 1036], [ 1807, 2372, 1233], + [ 1808, 1769, 1493], [ 1573, 2332, 1779], [ 1216, 1609, 1866], + [ 1480, 1898, 2513], [ 465, 2708, 2776], [ 771, 3638, 3338], + [ 1869, 2599, 2623], [ 2825, 2745, 2468], [ 2638, 2439, 1585], + [ 2094, 2970, 1308], [ 2022, 3057, 1999], [ 3428, 2912, 1816], + [ 4536, 2974, 2129], [ 1046, 2563, 2086], [ 1363, 3562, 2318], + [ 2511, 1891, 2984], [ 1866, 2306, 3986], [ 3272, 2924, 3682], + [ 3146, 3564, 2272], [ 3592, 3968, 2822], [ 2431, 3369, 3069], + [ 1931, 4709, 3090], [ 2629, 4220, 3986], [ 4639, 4056, 3664], + [ 4035, 5334, 4912] +]; + +const LSP_CODEBOOK2: [[i16; 4]; 256] = [ + [ 0, 0, 0, 0], [ 601, 512, -542, 334], + [ 428, 1087, -484, -132], [ 652, 622, -391, -572], + [ 378, 799, 141, -860], [ 1040, 409, 112, -554], + [ 1123, 670, -75, -847], [ 1421, 494, -315, -1095], + [ 787, 1001, 114, -460], [ 988, 1672, 216, -681], + [ 1007, 1241, -132, -1247], [ 1073, 399, 186, -5], + [ 1262, 193, -694, -129], [ 325, 196, 51, -641], + [ 861, -59, 350, -458], [ 1261, 567, 586, -346], + [ 1532, 885, 210, -517], [ 2027, 937, 113, -792], + [ 1383, 1064, 334, 38], [ 1964, 1468, 459, 133], + [ 2062, 1186, -98, -121], [ 2577, 1445, 506, -373], + [ 2310, 1682, -2, -960], [ 2876, 1939, 765, 138], + [ 3581, 2360, 649, -414], [ 219, 176, -398, -309], + [ 434, -78, -435, -880], [ -344, 301, 265, -552], + [ -915, 470, 657, -380], [ 419, -432, -163, -453], + [ 351, -953, 8, -562], [ 789, -43, 20, -958], + [ 302, -594, -352, -1159], [ 1040, 108, -668, -924], + [ 1333, 210, -1217, -1663], [ 483, 589, -350, -1140], + [ 1003, 824, -802, -1184], [ 745, 58, -589, -1443], + [ 346, 247, -915, -1683], [ 270, 796, -720, -2043], + [ 1208, 722, -222, -193], [ 1486, 1180, -412, -672], + [ 1722, 179, -69, -521], [ 2047, 860, -666, -1410], + [ -146, 222, -281, -805], [ -189, 90, -114, -1307], + [ -152, 1086, -241, -764], [ -439, 733, -601, -1302], + [ -833, -167, -351, -601], [ -856, -422, -411, -1059], + [ -747, -355, -582, -1644], [ -837, 210, -916, -1144], + [-1800, 32, -878, -1687], [ -48, -23, -1146, 52], + [ -350, -409, -1656, -364], [ 265, -728, -858, -577], + [ 458, -247, -1141, -997], [ 691, -407, -1988, -1161], + [ -66, -104, -705, -1249], [ -431, -93, -1191, -1844], + [ 203, -732, -1000, -1693], [ 10, -832, -1846, -1819], + [ 493, -128, -1436, -1768], [ 488, -311, -1730, -2540], + [ -653, -532, -1150, -1172], [-1086, -289, -1706, -1533], + [ -699, -1205, -1216, -1766], [-1032, -1481, -2074, -1523], + [ -721, -1220, -2277, -2600], [ 12, -539, -1484, -1131], + [ -40, -911, -2106, -441], [ -471, -484, -2267, -1549], + [ -141, -988, -3006, -1721], [-1545, -2102, -583, 342], + [-1383, -2772, -386, -13], [-2118, -2589, -1205, 72], + [-2147, -3231, -965, 390], [-2949, -3300, -621, 637], + [-3907, -4138, -865, 803], [-1287, -845, -375, -548], + [-1416, -1169, -487, -1277], [-1400, -1690, -1027, -418], + [-2018, -1909, -1188, -1260], [-1418, -2222, -2029, -128], + [-2067, -2998, -2693, -310], [ -950, -1028, -1538, 185], + [-1616, -915, -2205, -549], [ 19, -821, -1145, 352], + [ 184, -1175, -1356, -627], [ -547, -1088, -1661, -911], + [ -216, -1502, -2197, -948], [ -795, -1306, -2374, -451], + [ -924, -1889, -2796, -680], [ -600, -1614, -3609, -885], + [-2392, -2528, 319, 303], [-2908, -2095, -310, 573], + [-3460, -2141, 49, -113], [-2231, -448, 675, -146], + [-2805, -532, 1231, 479], [-2684, -486, -200, 611], + [-3525, -971, -198, 704], [-3707, 173, 349, 254], + [-4734, -1447, -34, 880], [ 777, -512, 114, -10], + [ 1250, -66, 442, -5], [ 604, 613, 452, -352], + [ 1224, 777, 675, -1014], [-1372, -79, -1208, -238], + [-2389, -17, -1157, -818], [-1504, -673, -1133, -1060], + [-1984, -799, -2005, -1973], [-2037, -798, -1068, -105], + [-3190, -899, -1817, -194], [ -156, -886, 394, -318], + [ -258, -1283, 551, 202], [ -536, -1729, 910, 331], + [ -847, -1109, 795, -163], [-1171, -1128, 715, 519], + [-1080, -1319, 1685, 668], [-1000, -1921, 96, 211], + [-1487, -2148, 831, 174], [-1139, -374, 414, -4], + [-1517, -1383, 396, -352], [-1012, 439, -59, -967], + [-1812, 706, -440, -1030], [-1971, -329, -34, -827], + [-2472, -1588, -151, -606], [-2161, 374, -281, 76], + [-3012, 231, -15, -690], [ 1104, 566, 721, 209], + [ 1685, 564, 383, 98], [ 1898, 750, 792, -97], + [ 556, -64, 561, -93], [ 876, 162, 913, -22], + [ 961, 675, 1296, 140], [ 756, -396, 851, 544], + [ 360, -303, 1341, 396], [ 878, -22, 1464, 863], + [ -309, -273, 642, -129], [ -686, -82, 842, 454], + [ -5, -47, 1069, 998], [ -94, 967, 1277, 298], + [ -489, 385, 1473, 746], [ -369, -717, 1333, 242], + [ 281, -993, 1726, 924], [ 464, 601, 1575, 1376], + [ -250, 206, 2339, 1175], [ -438, 377, -597, -285], + [-1020, 787, -790, -287], [ -458, -410, 215, 295], + [ -589, -860, -121, 797], [-1175, 122, -437, 466], + [-1480, -121, 367, 924], [ 234, 323, 770, -555], + [ 145, 30, 996, 26], [ 66, 849, 93, -145], + [ -117, 1261, 474, -399], [-1495, 1051, 218, -506], + [-1390, 694, 994, 88], [ 616, 7, 78, 304], + [ 1060, 52, -62, 835], [ 833, 454, 649, 1359], + [ -770, 464, 47, 93], [ -574, 1199, -39, 379], + [ 114, -98, 488, 485], [ 727, 244, 606, 696], + [ -76, 455, 671, 546], [ -565, -13, 145, 819], + [ -376, 569, 448, 1128], [ 218, 122, 265, 1167], + [ 230, 738, 932, 1003], [ 138, 477, 36, 450], + [ 404, 787, -73, 1000], [ 497, 1259, 387, 1231], + [ 17, 207, 195, -79], [ 562, 358, 53, -158], + [ 493, 387, 478, 189], [ 678, 831, 640, 558], + [ -197, 523, 613, 57], [ 429, 894, 769, 111], + [ 67, 1174, 568, 511], [ 1242, 824, 251, 840], + [ 1419, 1074, 864, 481], [ 924, 1474, 669, 724], + [ 1539, 1879, 654, 1590], [ 445, 337, 1111, 541], + [ 472, 1421, 1264, 1094], [ 794, 735, 1103, 668], + [ 1055, 863, 1192, 1020], [ 778, 1105, 806, 1798], + [ 1052, 1527, 1587, 2151], [ 881, 1552, 1265, 391], + [ 726, 872, 1812, 601], [ 1469, 280, 1008, 616], + [ 1403, 577, 1803, 1244], [ 1650, 1314, 1148, 1072], + [ 1297, 1669, 1911, 1026], [ 2093, 1044, 2115, 1189], + [ 1644, 1961, 2587, 1512], [ 25, -315, -9, -106], + [ 290, -339, 428, -444], [ -68, -783, 735, 772], + [ 245, -555, 468, 47], [ 334, -895, 814, 146], + [ 235, 368, -964, -959], [ -203, 315, -1566, -1217], + [ 801, 17, -276, -354], [ 894, -495, -789, -635], + [ 716, 291, -1189, -357], [ 560, -260, -733, -2], + [ 679, -508, -1429, 211], [ -51, -62, -428, 557], + [ 322, -638, -211, 614], [ -878, -1057, -84, -71], + [ -388, -1415, -167, -318], [ -754, -1574, 214, -539], + [-1419, -2004, -92, -787], [ -47, -856, -347, -255], + [ 23, -1211, -173, 320], [ -658, -487, -893, 353], + [ -783, -1587, -584, 507], [-1420, -859, -378, 441], + [-2095, -1491, -137, 439], [ -321, -1450, -1288, -12], + [ -359, -2113, -553, -8], [ -831, -1918, -1561, 32], + [-1014, -2487, -1359, -939], [ -475, -311, -169, -236], + [ -907, -426, 276, -611], [ -96, -400, 50, -710], + [ -426, -1022, -10, -985], [ -197, -258, -744, -575], + [ -611, -930, -771, -394], [ -267, -776, -612, -939], + [ -256, -1346, -802, -1122], [ -796, -1570, -825, -754], + [ 712, 876, 141, 227], [ 981, 1509, 85, 124], + [ 1462, 1228, 979, -39], [ 1734, 999, 1481, 440], + [ 2293, 1116, 769, 440], [ 2504, 1480, 1241, 356], + [ 2474, 1909, 1558, 810], [ 917, 1134, 607, -134], + [ 509, 1809, 781, -123], [ 1712, 1506, 559, -423], + [ 2037, 2317, 726, -155], [ 3031, 2676, 1203, 331], + [ 3664, 3274, 1768, 531], [ 1610, 1839, 867, 183], + [ 1774, 1972, 1538, 97], [ 1822, 2158, 1282, 659], + [ 2222, 2758, 1818, 900], [ 3251, 2124, 1723, 996], + [ 3633, 2336, 2408, 1453], [ 2923, 3517, 2567, 1318], +]; + +const COS_TAB: [i16; 513] = [ + 16384, 16383, 16379, 16373, 16364, 16353, 16340, 16324, + 16305, 16284, 16261, 16235, 16207, 16176, 16143, 16107, + 16069, 16029, 15986, 15941, 15893, 15843, 15791, 15736, + 15679, 15619, 15557, 15493, 15426, 15357, 15286, 15213, + 15137, 15059, 14978, 14896, 14811, 14724, 14635, 14543, + 14449, 14354, 14256, 14155, 14053, 13949, 13842, 13733, + 13623, 13510, 13395, 13279, 13160, 13039, 12916, 12792, + 12665, 12537, 12406, 12274, 12140, 12004, 11866, 11727, + 11585, 11442, 11297, 11151, 11003, 10853, 10702, 10549, + 10394, 10238, 10080, 9921, 9760, 9598, 9434, 9269, + 9102, 8935, 8765, 8595, 8423, 8250, 8076, 7900, + 7723, 7545, 7366, 7186, 7005, 6823, 6639, 6455, + 6270, 6084, 5897, 5708, 5520, 5330, 5139, 4948, + 4756, 4563, 4370, 4176, 3981, 3786, 3590, 3393, + 3196, 2999, 2801, 2603, 2404, 2205, 2006, 1806, + 1606, 1406, 1205, 1005, 804, 603, 402, 201, + 0, -201, -402, -603, -804, -1005, -1205, -1406, + -1606, -1806, -2006, -2205, -2404, -2603, -2801, -2999, + -3196, -3393, -3590, -3786, -3981, -4176, -4370, -4563, + -4756, -4948, -5139, -5330, -5520, -5708, -5897, -6084, + -6270, -6455, -6639, -6823, -7005, -7186, -7366, -7545, + -7723, -7900, -8076, -8250, -8423, -8595, -8765, -8935, + -9102, -9269, -9434, -9598, -9760, -9921, -10080, -10238, + -10394, -10549, -10702, -10853, -11003, -11151, -11297, -11442, + -11585, -11727, -11866, -12004, -12140, -12274, -12406, -12537, + -12665, -12792, -12916, -13039, -13160, -13279, -13395, -13510, + -13623, -13733, -13842, -13949, -14053, -14155, -14256, -14354, + -14449, -14543, -14635, -14724, -14811, -14896, -14978, -15059, + -15137, -15213, -15286, -15357, -15426, -15493, -15557, -15619, + -15679, -15736, -15791, -15843, -15893, -15941, -15986, -16029, + -16069, -16107, -16143, -16176, -16207, -16235, -16261, -16284, + -16305, -16324, -16340, -16353, -16364, -16373, -16379, -16383, + -16384, -16383, -16379, -16373, -16364, -16353, -16340, -16324, + -16305, -16284, -16261, -16235, -16207, -16176, -16143, -16107, + -16069, -16029, -15986, -15941, -15893, -15843, -15791, -15736, + -15679, -15619, -15557, -15493, -15426, -15357, -15286, -15213, + -15137, -15059, -14978, -14896, -14811, -14724, -14635, -14543, + -14449, -14354, -14256, -14155, -14053, -13949, -13842, -13733, + -13623, -13510, -13395, -13279, -13160, -13039, -12916, -12792, + -12665, -12537, -12406, -12274, -12140, -12004, -11866, -11727, + -11585, -11442, -11297, -11151, -11003, -10853, -10702, -10549, + -10394, -10238, -10080, -9921, -9760, -9598, -9434, -9269, + -9102, -8935, -8765, -8595, -8423, -8250, -8076, -7900, + -7723, -7545, -7366, -7186, -7005, -6823, -6639, -6455, + -6270, -6084, -5897, -5708, -5520, -5330, -5139, -4948, + -4756, -4563, -4370, -4176, -3981, -3786, -3590, -3393, + -3196, -2999, -2801, -2603, -2404, -2205, -2006, -1806, + -1606, -1406, -1205, -1005, -804, -603, -402, -201, + 0, 201, 402, 603, 804, 1005, 1205, 1406, + 1606, 1806, 2006, 2205, 2404, 2603, 2801, 2999, + 3196, 3393, 3590, 3786, 3981, 4176, 4370, 4563, + 4756, 4948, 5139, 5330, 5520, 5708, 5897, 6084, + 6270, 6455, 6639, 6823, 7005, 7186, 7366, 7545, + 7723, 7900, 8076, 8250, 8423, 8595, 8765, 8935, + 9102, 9269, 9434, 9598, 9760, 9921, 10080, 10238, + 10394, 10549, 10702, 10853, 11003, 11151, 11297, 11442, + 11585, 11727, 11866, 12004, 12140, 12274, 12406, 12537, + 12665, 12792, 12916, 13039, 13160, 13279, 13395, 13510, + 13623, 13733, 13842, 13949, 14053, 14155, 14256, 14354, + 14449, 14543, 14635, 14724, 14811, 14896, 14978, 15059, + 15137, 15213, 15286, 15357, 15426, 15493, 15557, 15619, + 15679, 15736, 15791, 15843, 15893, 15941, 15986, 16029, + 16069, 16107, 16143, 16176, 16207, 16235, 16261, 16284, + 16305, 16324, 16340, 16353, 16364, 16373, 16379, 16383, + 16384 +]; + +const FIXED_CB_GAIN: [i16; 24] = [ + 1, 2, 3, 4, 6, 9, 13, 18, + 26, 38, 55, 80, 115, 166, 240, 348, + 502, 726, 1050, 1517, 2193, 3170, 4582, 6623 +]; + +const ACB_GAIN170: [[i16; 20]; 170] = [ + [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + ], [ + 776, 212, 715, 670, 809, -36, -2, -31, -27, -39, + -10, -33, -9, -31, -8, -29, -38, -10, -35, -33 + ], [ + 1296, 1316, -168, -320, -815, -102, -105, -1, -6, -40, + -104, 13, 13, 25, 25, -3, 64, 65, -8, -15 + ], [ + -589, 680, 2478, 308, -596, -21, -28, -375, -5, -21, + 24, 89, -102, 11, -12, -46, -21, 24, 90, 11 + ], [ + -735, -487, -5, 2948, 468, -33, -14, 0, -530, -13, + -21, 0, 0, 132, 87, 0, 21, 13, 0, -84 + ], [ + 1042, 1730, 1068, 333, 626, -66, -182, -69, -6, -23, + -110, -67, -112, -21, -35, -21, -39, -66, -40, -12 + ], [ + 486, -769, 4074, 2825, -1107, -14, -36, -1013, -487, -74, + 22, -120, 191, -83, 132, -702, 32, -52, 275, 191 + ], [ + 1521, -767, -124, 4320, 1026, -141, -35, 0, -1139, -64, + 71, 11, -5, -401, 202, 32, -95, 48, 7, -270 + ], [ + 2425, 1267, 3439, -91, -1166, -359, -98, -722, 0, -83, + -187, -509, -266, 13, 7, 19, 172, 90, 244, -6 + ], [ + -1251, 975, 173, 4039, 2005, -95, -58, -1, -996, -245, + 74, 13, -10, 308, -240, -42, 153, -119, -21, -494 + ], [ + 1820, 632, 1322, 2062, 1031, -202, -24, -106, -259, -64, + -70, -146, -51, -229, -79, -166, -114, -39, -83, -129 + ], [ + -447, 4904, 244, -315, -2038, -12, -1467, -3, -6, -253, + 134, 6, -73, -8, 94, 4, -55, 610, 30, -39 + ], [ + -208, -1102, 463, -448, 5653, -2, -74, -13, -12, -1950, + -14, 5, 31, -5, -30, 12, 71, 380, -159, 154 + ], [ + 4739, 2600, -1864, 856, -1554, -1371, -412, -212, -44, -147, + -752, 539, 295, -247, -135, 97, 449, 246, -176, 81 + ], [ + 1894, 3533, 35, -26, 2145, -219, -762, 0, 0, -280, + -408, -4, -7, 3, 5, 0, -248, -462, -4, 3 + ], [ + -2699, 1841, 4072, 2443, 1582, -444, -207, -1012, -364, -152, + 303, 670, -457, 402, -274, -607, 260, -177, -393, -236 + ], [ + -844, 3358, 6106, -1059, -537, -43, -688, -2275, -68, -17, + 173, 314, -1251, -54, 217, 395, -27, 110, 200, -34 + ], [ + 1251, 1016, 3020, 2210, 1445, -95, -63, -556, -298, -127, + -77, -230, -187, -168, -137, -407, -110, -89, -266, -194 + ], [ + 2099, 2277, 4038, 3533, -2870, -269, -316, -995, -762, -503, + -291, -517, -561, -452, -491, -871, 367, 399, 707, 619 + ], [ + 400, -1114, 8516, 2422, -1117, -9, -75, -4426, -358, -76, + 27, -208, 579, -59, 164, -1259, 27, -75, 580, 165 + ], [ + -4398, -2011, 3912, -2407, 2258, -1180, -247, -934, -353, -311, + -540, 1050, 480, -646, -295, 575, 606, 277, -539, 331 + ], [ + 1767, -1447, 4240, 6160, -757, -190, -127, -1097, -2316, -35, + 156, -457, 374, -664, 544, -1594, 81, -66, 195, 284 + ], [ + 1594, -1463, 1035, 6938, 1920, -155, -130, -65, -2938, -225, + 142, -100, 92, -675, 619, -438, -186, 171, -121, -813 + ], [ + -562, 4716, 4085, -591, 2421, -19, -1357, -1018, -21, -357, + 162, 140, -1175, -20, 170, 147, 83, -696, -603, 87 + ], [ + 1552, 8778, -935, 354, -1424, -147, -4703, -53, -7, -123, + -831, 88, 501, -33, -189, 20, 134, 763, -81, 30 + ], [ + 4831, -4431, 41, -1479, -2976, -1424, -1198, 0, -133, -540, + 1306, -12, 11, 436, -400, 3, 877, -804, 7, -268 + ], [ + 2090, 1192, 1006, 1645, 4853, -266, -86, -61, -165, -1437, + -152, -128, -73, -210, -119, -101, -619, -353, -298, -487 + ], [ + 2386, 5712, 1426, -94, 1350, -347, -1991, -124, 0, -111, + -832, -207, -497, 13, 32, 8, -196, -470, -117, 7 + ], [ + -1349, 1091, 1659, 8891, 313, -111, -72, -168, -4825, -5, + 89, 136, -110, 732, -592, -900, 25, -20, -31, -170 + ], [ + 9980, 916, -381, -808, 88, -6080, -51, -8, -39, 0, + -558, 232, 21, 492, 45, -18, -53, -4, 2, 4 + ], [ + 2338, -1031, -248, 3928, 6484, -333, -64, -3, -942, -2566, + 147, 35, -15, -560, 247, 59, -925, 408, 98, -1555 + ], [ + 6166, -1240, -337, 3672, -1277, -2320, -93, -6, -823, -99, + 466, 126, -25, -1382, 278, 75, 480, -96, -26, 286 + ], [ + 4377, -132, -2588, 1701, 4865, -1169, -1, -409, -176, -1444, + 35, 691, -20, -454, 13, 268, -1299, 39, 768, -505 + ], [ + 2594, 3295, 3944, 1481, 682, -410, -662, -949, -133, -28, + -521, -624, -793, -234, -297, -356, -108, -137, -164, -61 + ], [ + 4151, 624, 815, 4485, 2229, -1052, -23, -40, -1228, -303, + -158, -206, -31, -1136, -170, -223, -565, -84, -111, -610 + ], [ + -3575, -361, 4924, 2791, 4698, -780, -7, -1480, -475, -1347, + -78, 1074, 108, 609, 61, -839, 1025, 103, -1412, -800 + ], [ + -2518, 3791, 8623, 315, 2465, -387, -877, -4538, -6, -370, + 582, 1325, -1995, 48, -73, -166, 378, -570, -1297, -47 + ], [ + -691, 2989, 9957, -421, -1142, -29, -545, -6051, -10, -79, + 126, 420, -1817, -17, 76, 256, -48, 208, 694, -29 + ], [ + -1918, 104, -3190, -3410, -4440, -224, 0, -621, -709, -1203, + 12, -373, 20, -399, 21, -664, -519, 28, -864, -924 + ], [ + -3359, -1668, 1854, 6939, 1430, -688, -169, -209, -2939, -124, + -341, 380, 188, 1422, 706, -785, 293, 145, -161, -606 + ], [ + 42, 9706, 3164, -952, 907, 0, -5750, -611, -55, -50, + -25, -8, -1874, 2, 564, 183, -2, -537, -175, 52 + ], [ + 1607, 785, 2862, 4327, 3307, -157, -37, -500, -1143, -667, + -77, -280, -137, -424, -207, -756, -324, -158, -577, -873 + ], [ + 6801, 3416, 2227, 1682, -3217, -2823, -712, -302, -172, -631, + -1418, -924, -464, -698, -350, -228, 1335, 670, 437, 330 + ], [ + 3459, 3898, 364, 7841, -2640, -730, -927, -8, -3753, -425, + -823, -76, -86, -1655, -1865, -174, 557, 628, 58, 1263 + ], [ + -5902, -3458, -2465, -1886, 4334, -2126, -730, -371, -217, -1146, + -1245, -888, -520, -679, -398, -283, 1561, 915, 652, 499 + ], [ + -3710, 1133, 7849, 3443, -215, -840, -78, -3760, -723, -2, + 256, 1777, -543, 779, -238, -1649, -48, 14, 103, 45 + ], [ + 4132, 2828, 2, -4212, -4116, -1042, -488, 0, -1083, -1034, + -713, 0, 0, 1062, 727, 0, 1038, 710, 0, -1058 + ], [ + 5875, 8496, -1796, 1376, -1786, -2107, -4406, -197, -115, -194, + -3047, 644, 931, -493, -713, 150, 640, 926, -195, 150 + ], [ + 3143, 3483, 3546, -793, 4489, -603, -740, -767, -38, -1230, + -668, -680, -754, 152, 168, 171, -861, -954, -971, 217 + ], [ + 2845, 7965, 3695, -5432, 3978, -494, -3873, -833, -1801, -966, + -1383, -641, -1796, 943, 2641, 1225, -691, -1934, -897, 1319 + ], [ + 1538, 150, 7139, 2049, 3097, -144, -1, -3110, -256, -585, + -14, -670, -65, -192, -18, -892, -290, -28, -1349, -387 + ], [ + 618, 7520, 4729, -238, -3373, -23, -3452, -1365, -3, -694, + -283, -178, -2170, 8, 109, 68, 127, 1548, 973, -49 + ], [ + 2965, -3013, 7912, 7076, -1997, -536, -554, -3821, -3056, -243, + 545, -1431, 1455, -1280, 1301, -3417, 361, -367, 964, 862 + ], [ + 2443, -929, -1113, 9677, 4138, -364, -52, -75, -5716, -1045, + 138, 166, -63, -1443, 549, 657, -617, 234, 281, -2444 + ], [ + 1966, 3309, 10085, -3399, 2105, -236, -668, -6207, -705, -270, + -397, -1210, -2037, 408, 686, 2092, -252, -425, -1295, 436 + ], [ + -112, -1368, 8868, 4822, 2048, 0, -114, -4800, -1419, -256, + -9, 61, 740, 33, 402, -2610, 14, 171, -1108, -602 + ], [ + -2597, 438, -1839, 6229, 7266, -411, -11, -206, -2368, -3223, + 69, -291, 49, 987, -166, 699, 1152, -194, 816, -2763 + ], [ + 3454, 553, 9127, 4946, -5596, -728, -18, -5084, -1493, -1911, + -116, -1924, -308, -1042, -166, -2755, 1179, 188, 3117, 1689 + ], [ + -532, -663, 12262, 2495, -1004, -17, -26, -9177, -380, -61, + -21, 398, 496, 81, 101, -1867, -32, -40, 751, 152 + ], [ + -2100, 1317, -1509, 11425, 2997, -269, -105, -139, -7967, -548, + 168, -193, 121, 1464, -918, 1052, 384, -240, 276, -2090 + ], [ + 1193, -2697, 11259, 5373, -763, -86, -444, -7737, -1762, -35, + 196, -819, 1853, -391, 884, -3692, 55, -125, 525, 250 + ], [ + 2405, -471, 11079, 203, 782, -353, -13, -7491, -2, -37, + 69, -1626, 318, -29, 5, -137, -114, 22, -529, -9 + ], [ + -1871, 5685, 11290, -2662, 1353, -213, -1972, -7780, -432, -111, + 649, 1289, -3917, -304, 923, 1834, 154, -469, -932, 220 + ], [ + -3768, 5927, -3093, 5041, 5212, -866, -2144, -584, -1551, -1658, + 1363, -711, 1119, 1159, -1824, 951, 1198, -1885, 984, -1603 + ], [ + -2546, 9502, 5969, -2440, 1928, -395, -5511, -2175, -363, -226, + 1477, 927, -3462, -379, 1415, 889, 299, -1118, -702, 287 + ], [ + -4963, 3568, 4592, 5508, 3451, -1503, -777, -1287, -1851, -727, + 1080, 1391, -1000, 1668, -1199, -1543, 1045, -751, -967, -1160 + ], [ + 1745, -2586, 3983, 10899, -1551, -186, -408, -968, -7250, -146, + 275, -424, 628, -1161, 1720, -2649, 165, -244, 377, 1032 + ], [ + 867, -456, -727, 3369, 11822, -45, -12, -32, -692, -8531, + 24, 38, -20, -178, 93, 149, -625, 329, 525, -2431 + ], [ + 7535, 2422, 1926, 1405, 1599, -3466, -358, -226, -120, -156, + -1114, -886, -284, -646, -207, -165, -735, -236, -188, -137 + ], [ + 1041, -735, -142, 13209, 1515, -66, -33, -1, -10649, -140, + 46, 9, -6, -839, 593, 114, -96, 68, 13, -1222 + ], [ + 7950, 6745, -1444, -1008, 2721, -3857, -2777, -127, -62, -452, + -3273, 700, 594, 489, 415, -88, -1320, -1120, 239, 167 + ], [ + -4754, -1379, 4522, -578, -5733, -1379, -116, -1248, -20, -2006, + -400, 1312, 380, -167, -48, 159, -1663, -482, 1582, -202 + ], [ + 3220, 5978, 5923, 2430, -2689, -633, -2181, -2141, -360, -441, + -1175, -1164, -2161, -477, -886, -878, 528, 981, 972, 398 + ], [ + 377, 1312, 13978, -1470, 677, -8, -105, -11925, -132, -28, + -30, -321, -1119, 33, 117, 1254, -15, -54, -577, 60 + ], [ + -3435, 6770, 314, -885, 5686, -720, -2797, -6, -47, -1973, + 1419, 65, -129, -185, 366, 16, 1192, -2349, -109, 307 + ], [ + 3171, 8774, -2260, 2679, 3069, -613, -4699, -312, -438, -575, + -1698, 437, 1210, -518, -1435, 369, -594, -1643, 423, -501 + ], [ + 5557, 1509, 5407, -125, -7386, -1884, -139, -1784, 0, -3330, + -511, -1834, -498, 42, 11, 41, 2505, 680, 2438, -56 + ], [ + -2838, 2595, 13228, 271, 1793, -491, -411, -10680, -4, -196, + 449, 2291, -2095, 47, -42, -219, 310, -284, -1447, -29 + ], [ + 664, -278, 14966, 951, -711, -26, -4, -13672, -55, -30, + 11, -606, 253, -38, 16, -869, 28, -12, 650, 41 + ], [ + 808, 1770, 8658, 5863, -1486, -39, -191, -4576, -2098, -134, + -87, -427, -935, -289, -633, -3098, 73, 160, 785, 531 + ], [ + 3063, 1539, 2000, -542, 9576, -572, -144, -244, -17, -5597, + -287, -374, -188, 101, 51, 66, -1790, -900, -1169, 317 + ], [ + 514, 14083, -323, 896, -891, -16, -12106, -6, -49, -48, + -442, 10, 277, -28, -770, 17, 27, 766, -17, 48 + ], [ + 892, 158, 5237, 11057, -1603, -48, -1, -1674, -7462, -156, + -8, -285, -50, -602, -106, -3534, 87, 15, 512, 1082 + ], [ + -1612, 2564, -4296, 12526, 5710, -158, -401, -1126, -9576, -1990, + 252, -422, 672, 1232, -1960, 3284, 561, -893, 1497, -4365 + ], [ + 4889, -6878, 612, 6109, 4753, -1459, -2887, -22, -2277, -1379, + 2052, -182, 257, -1823, 2564, -228, -1418, 1995, -177, -1772 + ], [ + 3053, -506, 2403, 9625, 1322, -569, -15, -352, -5655, -106, + 94, -448, 74, -1794, 297, -1412, -246, 40, -194, -777 + ], [ + -754, 12904, 4480, -2113, 1471, -34, -10163, -1225, -272, -132, + 594, 206, -3529, -97, 1664, 577, 67, -1159, -402, 189 + ], [ + 4255, 1476, 5055, 2393, 2912, -1105, -132, -1559, -349, -517, + -383, -1313, -455, -621, -215, -738, -756, -262, -898, -425 + ], [ + -1371, 535, 1417, 14604, -997, -114, -17, -122, -13017, -60, + 44, 118, -46, 1222, -477, -1263, -83, 32, 86, 888 + ], [ + 5368, -1744, 4083, -1236, 3753, -1758, -185, -1017, -93, -860, + 571, -1338, 434, 405, -131, 308, -1229, 399, -935, 283 + ], [ + 1588, -3097, 14415, 3699, -1171, -154, -585, -12683, -835, -83, + 300, -1397, 2725, -358, 699, -3255, 113, -221, 1030, 264 + ], [ + 212, 7989, 9471, -3344, 2009, -2, -3895, -5475, -682, -246, + -103, -123, -4618, 43, 1630, 1933, -26, -979, -1161, 410 + ], [ + 856, 2294, -627, 6930, 6929, -44, -321, -24, -2931, -2930, + -119, 32, 87, -362, -970, 265, -362, -970, 265, -2931 + ], [ + 2357, -4187, 7162, 7683, 3371, -339, -1070, -3131, -3603, -693, + 602, -1030, 1830, -1105, 1963, -3359, -485, 861, -1474, -1581 + ], [ + 350, 4585, 14053, -3819, 1218, -7, -1283, -12054, -890, -90, + -97, -300, -3933, 81, 1068, 3275, -26, -341, -1045, 284 + ], [ + -3248, 3531, 475, 2137, 11711, -644, -761, -13, -278, -8372, + 700, 94, -102, 423, -460, -62, 2322, -2524, -340, -1528 + ], [ + -3017, 3852, 1725, 8440, 5257, -555, -905, -181, -4348, -1686, + 709, 317, -405, 1554, -1984, -889, 968, -1236, -553, -2708 + ], [ + -909, 3196, 15512, -2528, 1066, -50, -623, -14686, -390, -69, + 177, 861, -3026, -140, 493, 2393, 59, -208, -1009, 164 + ], [ + 959, -3370, 9617, 9545, -1761, -56, -693, -5645, -5561, -189, + 197, -563, 1978, -558, 1963, -5603, 103, -362, 1034, 1026 + ], [ + 7575, 11796, -4845, 3252, -1703, -3502, -8493, -1433, -645, -177, + -5454, 2240, 3488, -1503, -2341, 961, 787, 1226, -503, 338 + ], [ + 6409, 1722, 1764, -4191, 6015, -2507, -181, -189, -1072, -2208, + -673, -690, -185, 1639, 440, 451, -2353, -632, -647, 1538 + ], [ + -2420, 12161, 5038, 1286, -2098, -357, -9027, -1549, -100, -268, + 1796, 744, -3740, 190, -954, -395, -310, 1557, 645, 164 + ], [ + -2232, -1341, 7246, 9470, -1977, -304, -109, -3204, -5474, -238, + -182, 987, 593, 1290, 775, -4188, -269, -161, 874, 1143 + ], [ + 1030, 7034, 4231, 1551, 3077, -64, -3019, -1093, -146, -577, + -442, -266, -1816, -97, -666, -400, -193, -1321, -794, -291 + ], [ + 5121, 11835, -477, -1749, 2298, -1601, -8549, -13, -186, -322, + -3699, 149, 344, 546, 1264, -50, -718, -1660, 66, 245 + ], [ + -3328, 3827, 5921, 9976, -1045, -676, -894, -2140, -6075, -66, + 777, 1203, -1383, 2027, -2330, -3605, -212, 244, 377, 636 + ], [ + 3813, 5718, -4666, -3412, 5674, -887, -1995, -1329, -710, -1965, + -1331, 1086, 1628, 794, 1191, -972, -1320, -1980, 1616, 1181 + ], [ + 1348, -3672, 13154, 6938, -1690, -110, -823, -10561, -2938, -174, + 302, -1082, 2948, -570, 1555, -5570, 139, -379, 1357, 716 + ], [ + 2151, -3586, 6949, 12131, -1224, -282, -785, -2947, -8982, -91, + 470, -912, 1521, -1592, 2655, -5145, 160, -268, 519, 906 + ], [ + -2889, 9647, 10276, -2728, 995, -509, -5680, -6445, -454, -60, + 1701, 1812, -6051, -481, 1606, 1711, 175, -586, -624, 165 + ], [ + 6177, 2184, 555, 1985, 6589, -2329, -291, -18, -240, -2650, + -823, -209, -74, -748, -264, -67, -2484, -878, -223, -798 + ], [ + -492, 391, 17166, -681, 240, -14, -9, -17987, -28, -3, + 11, 515, -410, -20, 16, 713, 7, -5, -252, 10 + ], [ + 12628, 5448, -2630, 3011, -2695, -9733, -1811, -422, -553, -443, + -4199, 2027, 874, -2321, -1001, 483, 2077, 896, -432, 495 + ], [ + -3628, -534, 3447, 7002, 6751, -803, -17, -725, -2992, -2782, + -118, 763, 112, 1550, 228, -1473, 1495, 220, -1420, -2885 + ], [ + -5239, 5901, 8107, 3650, 4846, -1675, -2125, -4012, -813, -1433, + 1887, 2592, -2920, 1167, -1315, -1806, 1550, -1745, -2398, -1080 + ], [ + 6157, 6678, 4099, -1074, 2348, -2314, -2722, -1025, -70, -336, + -2509, -1540, -1670, 403, 437, 268, -882, -957, -587, 153 + ], [ + 1079, 16099, 242, -881, 1690, -71, -15820, -3, -47, -174, + -1060, -16, -238, 58, 865, 13, -111, -1661, -25, 90 + ], [ + -278, 227, -1039, 1636, 16945, -4, -3, -65, -163, -17526, + 3, -17, 14, 27, -22, 103, 287, -234, 1074, -1693 + ], [ + 15778, -1454, 574, -603, -107, -15195, -129, -20, -22, 0, + 1400, -553, 51, 581, -53, 21, 103, -9, 3, -3 + ], [ + 2406, -836, 13224, 7993, -4266, -353, -42, -10673, -3899, -1111, + 122, -1942, 674, -1174, 407, -6451, 626, -217, 3443, 2081 + ], [ + 3184, 14368, -3336, 2255, -1801, -619, -12600, -679, -310, -198, + -2793, 648, 2926, -438, -1977, 459, 350, 1580, -366, 247 + ], [ + -1698, 17076, 2504, -539, -646, -176, -17798, -382, -17, -25, + 1770, 259, -2610, -55, 561, 82, -67, 673, 98, -21 + ], [ + 2375, -797, -2696, 14483, 5383, -344, -38, -443, -12803, -1769, + 115, 391, -131, -2100, 705, 2384, -780, 262, 886, -4759 + ], [ + -2691, 2554, -4520, 9573, 10655, -442, -398, -1247, -5594, -6930, + 419, -742, 704, 1572, -1492, 2641, 1750, -1661, 2939, -6226 + ], [ + -4332, -4399, -1657, 4880, 7375, -1145, -1181, -167, -1453, -3319, + -1163, -438, -444, 1290, 1310, 493, 1950, 1980, 745, -2196 + ], [ + -3498, 7405, 9955, 2693, -2971, -746, -3347, -6049, -442, -538, + 1581, 2125, -4499, 575, -1217, -1636, -634, 1342, 1805, 488 + ], [ + 6717, -3792, 7739, 2798, 3489, -2754, -877, -3655, -477, -743, + 1554, -3173, 1791, -1147, 647, -1321, -1430, 807, -1648, -595 + ], [ + 5263, 9770, 3463, 1069, -3971, -1690, -5826, -732, -69, -962, + -3138, -1112, -2065, -343, -637, -226, 1275, 2368, 839, 259 + ], [ + 1243, -2634, 16772, 1871, 332, -94, -423, -17169, -213, -6, + 199, -1273, 2696, -142, 300, -1915, -25, 53, -339, -37 + ], [ + 2691, 2836, 3105, 5711, 4817, -442, -491, -588, -1991, -1416, + -465, -510, -537, -938, -988, -1082, -791, -834, -913, -1679 + ], [ + 4366, 2944, 7210, 3627, 1161, -1163, -529, -3172, -803, -82, + -784, -1921, -1295, -966, -651, -1596, -309, -208, -511, -257 + ], [ + 13888, 3951, -671, -2305, 3354, -11773, -953, -27, -324, -686, + -3349, 569, 161, 1954, 556, -94, -2843, -809, 137, 472 + ], [ + 7053, 5847, 2929, 8378, -4794, -3036, -2086, -523, -4284, -1403, + -2517, -1261, -1045, -3607, -2990, -1498, 2064, 1711, 857, 2451 + ], [ + -2191, 12838, 9182, -3915, 1617, -293, -10059, -5146, -935, -159, + 1717, 1228, -7195, -523, 3068, 2194, 216, -1267, -906, 386 + ], [ + -4881, 13114, 5767, -435, 4155, -1454, -10498, -2030, -11, -1054, + 3907, 1718, -4616, -129, 348, 153, 1238, -3326, -1462, 110 + ], [ + 7843, -1250, 210, 7106, -5203, -3754, -95, -2, -3082, -1652, + 598, -100, 16, -3402, 542, -91, 2491, -397, 66, 2257 + ], [ + -2463, 8168, 14551, -3908, 1828, -370, -4072, -12923, -932, -204, + 1228, 2188, -7254, -587, 1948, 3471, 274, -911, -1623, 436 + ], [ + -1579, 347, -272, -2735, 16031, -152, -7, -4, -456, -15686, + 33, -26, 5, -263, 58, -45, 1545, -340, 266, 2676 + ], [ + -6327, 1328, 5093, -5079, 7617, -2443, -107, -1583, -1574, -3541, + 513, 1967, -413, -1961, 411, 1578, 2941, -617, -2367, 2361 + ], [ + 3286, -4509, 11306, 11025, -2623, -659, -1241, -7802, -7419, -420, + 904, -2267, 3112, -2211, 3034, -7608, 526, -722, 1810, 1765 + ], [ + 5567, 17853, -3754, 1166, -519, -1892, -19455, -860, -83, -16, + -6067, 1275, 4090, -396, -1271, 267, 176, 566, -119, 37 + ], [ + -2136, -424, 15292, 5108, -1648, -278, -10, -14273, -1593, -165, + -55, 1993, 396, 666, 132, -4768, -214, -42, 1538, 514 + ], [ + 2267, -3297, 2549, 16563, -791, -313, -663, -396, -16745, -38, + 456, -352, 513, -2291, 3333, -2576, 109, -159, 123, 799 + ], [ + 3655, 1899, -3364, 6279, 12510, -815, -220, -690, -2406, -9552, + -423, 750, 390, -1400, -728, 1289, -2791, -1450, 2568, -4794 + ], [ + 8052, 2285, -6193, 5138, 6003, -3957, -318, -2341, -1611, -2199, + -1123, 3044, 864, -2525, -716, 1942, -2950, -837, 2269, -1882 + ], [ + -386, -2291, 7679, 15387, -2723, -9, -320, -3599, -14452, -452, + -54, 181, 1074, 362, 2152, -7212, -64, -380, 1276, 2557 + ], [ + 2777, -1173, 3984, 13079, 2508, -470, -84, -969, -10440, -384, + 198, -675, 285, -2217, 936, -3180, -425, 179, -610, -2002 + ], [ + -1879, 1771, -2684, 16705, 1833, -215, -191, -439, -17032, -205, + 203, -308, 290, 1916, -1805, 2736, 210, -198, 300, -1869 + ], [ + 1052, 4495, 15519, 1467, -4032, -67, -1233, -14700, -131, -992, + -288, -997, -4257, -94, -402, -1389, 259, 1106, 3819, 361 + ], [ + 3010, 2544, 6969, 7559, 1996, -553, -395, -2964, -3487, -243, + -467, -1280, -1082, -1388, -1174, -3215, -366, -310, -849, -921 + ], [ + -5209, -1867, 8713, 10351, 1549, -1656, -212, -4634, -6540, -146, + -593, 2770, 993, 3291, 1180, -5505, 492, 176, -824, -979 + ], [ + -4314, 8513, 913, 7547, -2723, -1135, -4423, -50, -3476, -452, + 2241, 240, -474, 1987, -3921, -420, -717, 1415, 151, 1254 + ], [ + 12929, -1219, 2448, 1757, 6303, -10204, -90, -365, -188, -2425, + 962, -1932, 182, -1386, 130, -262, -4974, 469, -941, -676 + ], [ + 6465, 4132, 3167, 3160, 5697, -2551, -1042, -612, -609, -1981, + -1630, -1249, -798, -1247, -797, -611, -2248, -1437, -1101, -1099 + ], [ + -3636, 4859, 18914, -1335, 810, -807, -1441, -21836, -108, -40, + 1078, 4198, -5609, -296, 396, 1541, 179, -240, -936, 66 + ], [ + 8844, 7864, 654, -4063, -5680, -4774, -3774, -26, -1007, -1969, + -4245, -353, -314, 2193, 1950, 162, 3066, 2726, 226, -1408 + ], [ + 1859, 2634, 9228, 996, 9464, -211, -423, -5197, -60, -5467, + -299, -1047, -1483, -113, -160, -561, -1074, -1521, -5330, -575 + ], [ + 2949, 12260, 10290, -497, -3943, -530, -9174, -6463, -15, -949, + -2206, -1852, -7700, 89, 372, 312, 709, 2950, 2476, -119 + ], [ + -2903, 1552, 14867, 9970, -496, -514, -147, -13491, -6068, -15, + 275, 2634, -1408, 1766, -944, -9047, -87, 47, 450, 302 + ], [ + 3243, 8234, 7586, 3373, 2151, -642, -4138, -3512, -694, -282, + -1630, -1501, -3812, -667, -1695, -1561, -425, -1081, -996, -442 + ], [ + -9631, 60, 3501, 5359, 10150, -5662, 0, -748, -1752, -6288, + 35, 2058, -12, 3150, -19, -1145, 5967, -37, -2169, -3320 + ], [ + -6874, -2553, -5446, -2195, -7841, -2884, -397, -1810, -294, -3753, + -1071, -2285, -848, -921, -342, -729, -3290, -1221, -2606, -1050 + ], [ + -3413, -1141, 4630, 13612, 7897, -711, -79, -1308, -11310, -3806, + -237, 964, 322, 2836, 948, -3847, 1645, 550, -2231, -6561 + ], [ + 4410, -5678, 8006, -3992, 3811, -1187, -1968, -3912, -973, -886, + 1528, -2155, 2775, 1074, -1383, 1951, -1025, 1321, -1862, 928 + ], [ + 5659, 11535, 2203, -452, 7169, -1954, -8121, -296, -12, -3137, + -3984, -761, -1551, 156, 318, 60, -2476, -5048, -964, 197 + ], [ + 2914, -2914, 3485, -3965, 13675, -518, -518, -741, -959, -11414, + 518, -620, 620, 705, -705, 843, -2433, 2432, -2909, 3310 + ], [ + 7843, 1907, 1022, 8882, 7972, -3755, -222, -63, -4815, -3879, + -913, -489, -119, -4252, -1034, -554, -3816, -928, -497, -4322 + ], [ + 13807, 9531, 1436, 1612, 1779, -11636, -5544, -125, -158, -193, + -8032, -1210, -835, -1358, -938, -141, -1499, -1035, -156, -175 + ], [ + 13620, -5337, 5450, -2263, 1723, -11322, -1738, -1813, -312, -181, + 4436, -4531, 1775, 1881, -737, 752, -1432, 561, -573, 238 + ], [ + 5297, 8374, 8872, 7694, 6538, -1712, -4280, -4804, -3613, -2609, + -2707, -2868, -4534, -2487, -3932, -4166, -2113, -3341, -3540, -3070 + ] +]; +const ACB_GAIN85: [[i16; 20]; 85] = [ + [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + ], [ + 800, 1496, 167, -256, -338, -39, -136, -1, -4, -6, + -73, -8, -15, 12, 23, 2, 16, 30, 3, -5 + ], [ + -462, -686, 493, 2575, 311, -13, -28, -14, -404, -5, + -19, 13, 20, 72, 107, -77, 8, 13, -9, -48 + ], [ + 1483, 144, 784, 928, 1243, -134, -1, -37, -52, -94, + -13, -71, -6, -84, -8, -44, -112, -10, -59, -70 + ], [ + -77, 275, 3522, 1056, -1254, 0, -4, -757, -68, -95, + 1, 16, -59, 4, -17, -227, -5, 21, 269, 80 + ], [ + -125, -40, -264, 381, 5027, 0, 0, -4, -8, -1542, + 0, -2, 0, 2, 0, 6, 38, 12, 81, -117 + ], [ + 138, 332, 2215, 2574, 1339, -1, -6, -299, -404, -109, + -2, -18, -44, -21, -52, -348, -11, -27, -181, -210 + ], [ + 3685, 2883, -887, 866, -1639, -828, -507, -48, -45, -164, + -648, 199, 156, -194, -152, 46, 368, 288, -88, 86 + ], [ + 1396, 2146, 2235, 345, 942, -118, -281, -305, -7, -54, + -182, -190, -292, -29, -45, -47, -80, -123, -128, -19 + ], [ + 13, 4475, 3549, -804, -655, 0, -1222, -768, -39, -26, + -3, -2, -969, 0, 219, 174, 0, 179, 141, -32 + ], [ + -724, 254, 242, 6049, 2462, -32, -3, -3, -2233, -370, + 11, 10, -3, 267, -94, -89, 108, -38, -36, -909 + ], [ + 626, -1713, 6121, 4561, -1061, -23, -179, -2287, -1270, -68, + 65, -233, 640, -174, 477, -1704, 40, -111, 396, 295 + ], [ + -350, 1391, 7985, 511, -405, -7, -118, -3892, -15, -10, + 29, 170, -678, 10, -43, -249, -8, 34, 197, 12 + ], [ + 3144, -529, 608, 2530, 3878, -603, -17, -22, -390, -918, + 101, -116, 19, -485, 81, -93, -744, 125, -144, -599 + ], [ + 2589, -689, 3045, 5603, -404, -409, -29, -566, -1916, -10, + 108, -481, 128, -885, 235, -1041, 63, -17, 75, 138 + ], [ + 3107, 513, 1374, -3594, -4922, -589, -16, -115, -788, -1478, + -97, -260, -43, 681, 112, 301, 933, 154, 413, -1079 + ], [ + 2468, 6010, 1107, -390, 1961, -372, -2204, -74, -9, -234, + -905, -166, -406, 58, 143, 26, -295, -719, -132, 46 + ], [ + 4773, 2766, 2368, 4862, -4044, -1390, -467, -342, -1443, -998, + -806, -690, -399, -1416, -821, -702, 1178, 682, 584, 1200 + ], [ + 1665, -1879, 1443, 1701, 8562, -169, -215, -127, -176, -4475, + 190, -146, 165, -172, 195, -149, -870, 982, -754, -889 + ], [ + 2716, 9011, -1007, 755, -1785, -450, -4956, -61, -34, -194, + -1493, 167, 554, -125, -415, 46, 296, 982, -109, 82 + ], [ + -2727, 7548, 1285, 938, 3420, -453, -3478, -100, -53, -714, + 1256, 213, -592, 156, -432, -73, 569, -1576, -268, -196 + ], [ + 3677, 882, 4050, 1202, 2323, -825, -47, -1001, -88, -329, + -198, -909, -218, -269, -64, -297, -521, -125, -574, -170 + ], [ + 2046, -753, 122, 10102, 603, -255, -34, 0, -6229, -22, + 94, -15, 5, -1261, 464, -75, -75, 27, -4, -372 + ], [ + 449, -1815, 10690, 3870, -527, -12, -201, -6976, -914, -16, + 49, -293, 1184, -106, 428, -2525, 14, -58, 344, 124 + ], [ + -941, 2352, 5049, 3650, 2637, -54, -337, -1556, -813, -424, + 135, 290, -725, 209, -524, -1125, 151, -378, -812, -587 + ], [ + -1879, 796, 3117, 9569, -404, -215, -38, -593, -5589, -9, + 91, 357, -151, 1097, -464, -1821, -46, 19, 76, 236 + ], [ + -1715, 2043, -2096, 9946, 4001, -179, -254, -268, -6038, -977, + 213, -219, 261, 1041, -1240, 1272, 418, -498, 511, -2429 + ], [ + -5772, -618, -3921, 284, -3155, -2033, -23, -938, -4, -607, + -218, -1381, -148, 100, 10, 68, -1111, -119, -755, 54 + ], [ + 382, 4748, 8003, -2064, 2198, -8, -1376, -3909, -260, -294, + -110, -186, -2319, 48, 598, 1008, -51, -637, -1073, 277 + ], [ + -867, 3015, 11926, -1675, 947, -45, -555, -8681, -171, -54, + 159, 631, -2195, -88, 308, 1219, 50, -174, -690, 96 + ], [ + -4933, -432, 6757, 3771, 1352, -1485, -11, -2786, -867, -111, + -130, 2034, 178, 1135, 99, -1555, 407, 35, -557, -311 + ], [ + 152, 9726, 4231, -1928, 1490, -1, -5774, -1092, -226, -135, + -90, -39, -2511, 17, 1144, 498, -13, -884, -384, 175 + ], [ + 2512, 193, 9033, 5361, -3148, -385, -2, -4980, -1754, -605, + -29, -1385, -106, -822, -63, -2956, 482, 37, 1735, 1030 + ], [ + 8464, 2844, 12, 549, 2132, -4373, -493, 0, -18, -277, + -1469, -6, -2, -284, -95, 0, -1101, -370, -1, -71 + ], [ + 2141, -2602, 7166, 9046, -1350, -279, -413, -3134, -4994, -111, + 340, -936, 1138, -1182, 1436, -3957, 176, -214, 590, 745 + ], [ + -244, 278, 13307, 1227, -161, -3, -4, -10808, -91, -1, + 4, 198, -226, 18, -20, -997, -2, 2, 131, 12 + ], [ + -1947, 8217, 6269, 917, -2559, -231, -4121, -2399, -51, -399, + 976, 745, -3144, 108, -460, -350, -304, 1283, 979, 143 + ], [ + -1810, 2061, -2781, 6056, 10058, -200, -259, -472, -2238, -6174, + 227, -307, 349, 669, -761, 1028, 1111, -1265, 1707, -3717 + ], [ + 7827, 9161, -3409, 2473, -1510, -3739, -5122, -709, -373, -139, + -4376, 1628, 1906, -1181, -1382, 514, 721, 844, -314, 228 + ], [ + -1430, 8313, 9541, -2955, 1626, -124, -4218, -5556, -533, -161, + 725, 832, -4841, -257, 1499, 1721, 142, -825, -947, 293 + ], [ + 2819, -4247, 5391, 8673, 2756, -485, -1101, -1774, -4591, -463, + 730, -927, 1397, -1492, 2248, -2854, -474, 714, -907, -1459 + ], [ + 141, 14552, 690, 257, -112, -1, -12926, -29, -4, 0, + -125, -5, -613, -2, -228, -10, 0, 99, 4, 1 + ], [ + 11938, -1859, 1806, -962, -884, -8699, -211, -199, -56, -47, + 1355, -1316, 205, 701, -109, 106, 644, -100, 97, -51 + ], [ + 3728, 1982, 2264, 4584, 3131, -848, -239, -312, -1282, -598, + -451, -515, -273, -1043, -554, -633, -712, -378, -432, -876 + ], [ + -1181, 766, 720, 14303, -216, -85, -35, -31, -12486, -2, + 55, 51, -33, 1031, -668, -628, -15, 10, 9, 189 + ], [ + -4385, 4826, 10112, 1569, 3388, -1173, -1421, -6242, -150, -700, + 1291, 2706, -2979, 420, -462, -969, 906, -998, -2091, -324 + ], [ + -448, 1932, 15591, -1842, 657, -12, -227, -14837, -207, -26, + 52, 427, -1838, -50, 217, 1753, 18, -77, -626, 74 + ], [ + -4141, 1844, 3962, 5517, 6220, -1046, -207, -958, -1858, -2361, + 466, 1001, -446, 1394, -621, -1334, 1572, -700, -1504, -2094 + ], [ + 729, -2299, 14755, 3657, -952, -32, -322, -13288, -816, -55, + 102, -656, 2071, -162, 513, -3294, 42, -133, 857, 212 + ], [ + -1385, 5801, 13339, -3137, 1344, -117, -2054, -10861, -600, -110, + 490, 1127, -4723, -265, 1111, 2554, 113, -476, -1094, 257 + ], [ + 4710, 9661, 1073, -2467, 3274, -1354, -5697, -70, -371, -654, + -2777, -308, -633, 709, 1455, 161, -941, -1930, -214, 493 + ], [ + 1843, -3624, 12422, 6898, -1559, -207, -802, -9419, -2904, -148, + 407, -1397, 2748, -775, 1526, -5230, 175, -344, 1182, 656 + ], [ + 1433, 2394, 2507, 1380, 8780, -125, -349, -383, -116, -4705, + -209, -219, -366, -120, -201, -211, -768, -1283, -1343, -740 + ], [ + -1712, 12915, 5883, -2197, 991, -179, -10181, -2112, -294, -60, + 1350, 615, -4638, -229, 1732, 789, 103, -781, -356, 133 + ], [ + 15072, 2158, -1245, 910, -496, -13865, -284, -94, -50, -15, + -1986, 1145, 164, -837, -119, 69, 456, 65, -37, 27 + ], [ + 4655, 7319, 4916, 586, -3381, -1322, -3270, -1475, -20, -697, + -2079, -1396, -2196, -166, -261, -175, 960, 1510, 1014, 120 + ], [ + 1191, -2140, 5120, 13498, -1418, -86, -279, -1600, -11121, -122, + 155, -372, 669, -981, 1763, -4218, 103, -185, 443, 1168 + ], [ + -1530, -817, 8191, 9632, -1452, -143, -40, -4095, -5663, -128, + -76, 765, 408, 900, 480, -4815, -135, -72, 726, 854 + ], [ + -3236, 607, 1696, -2106, 11485, -639, -22, -175, -270, -8051, + 119, 335, -62, -416, 78, 218, 2268, -425, -1189, 1476 + ], [ + 3203, -1903, -837, 9679, 7057, -626, -221, -42, -5718, -3039, + 372, 163, -97, -1892, 1124, 494, -1380, 819, 360, -4169 + ], [ + 213, -655, 17015, 620, -384, -2, -26, -17671, -23, -9, + 8, -221, 681, -8, 24, -644, 5, -15, 399, 14 + ], [ + 5088, 35, -3339, 3726, 8488, -1580, 0, -680, -847, -4397, + -10, 1037, 7, -1157, -8, 759, -2636, -18, 1730, -1930 + ], [ + -988, 1454, -2688, 15039, 2682, -59, -129, -441, -13805, -439, + 87, -162, 238, 907, -1335, 2467, 161, -238, 440, -2462 + ], [ + -4865, -2842, -53, 5495, 6523, -1445, -493, 0, -1843, -2597, + -844, -16, -9, 1632, 953, 18, 1937, 1131, 21, -2188 + ], [ + 3076, 15069, -2914, 1810, -971, -577, -13860, -518, -200, -57, + -2829, 547, 2680, -339, -1665, 322, 182, 893, -172, 107 + ], [ + 1311, 5355, 11054, 2299, -3654, -105, -1750, -7458, -322, -814, + -428, -885, -3613, -184, -751, -1551, 292, 1194, 2465, 512 + ], [ + 4035, 5619, 4618, 1815, 1912, -994, -1927, -1301, -201, -223, + -1384, -1137, -1583, -447, -622, -511, -471, -656, -539, -211 + ], [ + -2131, 2754, -4501, 12879, 7432, -277, -463, -1236, -10124, -3371, + 358, -585, 756, 1675, -2165, 3538, 967, -1249, 2042, -5842 + ], [ + 5618, -515, 3219, -4149, 4857, -1926, -16, -632, -1050, -1440, + 176, -1104, 101, 1422, -130, 815, -1666, 152, -954, 1230 + ], [ + 1838, -1709, 1139, 16867, 716, -206, -178, -79, -17366, -31, + 191, -127, 118, -1892, 1759, -1173, -80, 74, -49, -737 + ], [ + 1978, -3845, 10050, 11854, -2492, -238, -902, -6164, -8576, -379, + 464, -1213, 2358, -1431, 2782, -7271, 301, -585, 1529, 1803 + ], [ + -2600, 11246, 11289, -3647, 1463, -412, -7720, -7778, -812, -130, + 1784, 1791, -7749, -578, 2504, 2513, 232, -1004, -1008, 325 + ], [ + 3442, 907, 2725, 8970, 3638, -723, -50, -453, -4911, -808, + -190, -572, -150, -1884, -496, -1492, -764, -201, -605, -1992 + ], [ + -126, 17498, 3481, -2003, 1090, 0, -18689, -739, -244, -72, + 135, 26, -3717, -15, 2139, 425, 8, -1165, -231, 133 + ], [ + -1814, 1048, -2164, 4070, 16272, -200, -67, -285, -1011, -16160, + 116, -239, 138, 450, -260, 537, 1801, -1041, 2149, -4042 + ], [ + 9354, 12580, -1883, 962, -617, -5341, -9660, -216, -56, -23, + -7183, 1075, 1446, -549, -738, 110, 352, 474, -71, 36 + ], [ + 1708, 4199, 7387, 6335, 1003, -178, -1076, -3330, -2449, -61, + -437, -770, -1893, -660, -1623, -2856, -104, -257, -452, -388 + ], [ + -2624, 5623, 17310, -2353, 592, -420, -1930, -18288, -338, -21, + 900, 2772, -5941, -376, 807, 2486, 94, -203, -625, 85 + ], [ + 1211, -850, 1193, -1926, 15992, -89, -44, -86, -226, -15609, + 62, -88, 61, 142, -100, 140, -1182, 830, -1165, 1880 + ], [ + 3983, -2054, 11506, -19, 3622, -968, -257, -8080, 0, -801, + 499, -2797, 1442, 4, -2, 13, -880, 454, -2544, 4 + ], [ + -786, -1354, 16092, 7246, -1665, -37, -111, -15805, -3205, -169, + -65, 772, 1330, 348, 599, -7117, -80, -137, 1636, 736 + ], [ + -4316, -511, 6674, 11665, 4633, -1137, -15, -2719, -8305, -1310, + -134, 1758, 208, 3073, 364, -4752, 1220, 144, -1887, -3299 + ], [ + 7912, 4557, 1937, 1885, 7037, -3821, -1267, -229, -216, -3022, + -2200, -935, -538, -910, -524, -222, -3398, -1957, -832, -809 + ], [ + 3434, 2967, 5867, 8196, 8766, -720, -537, -2101, -4100, -4690, + -622, -1230, -1062, -1718, -1484, -2935, -1837, -1588, -3139, -4385 + ], [ + 5881, 9176, 8119, 3934, 3355, -2111, -5139, -4023, -944, -687, + -3294, -2914, -4547, -1412, -2203, -1949, -1204, -1879, -1662, -805 + ] +]; + +const PULSE_POSITIONS: [[u32; SUBFRAME_LEN/2]; MAX_PULSES] = [ + [ + 118755, 98280, 80730, 65780, 53130, 42504, 33649, 26334, 20349, 15504, + 11628, 8568, 6188, 4368, 3003, 2002, 1287, 792, 462, 252, + 126, 56, 21, 6, 1, 0, 0, 0, 0, 0 + ], [ + 23751, 20475, 17550, 14950, 12650, 10626, 8855, 7315, 5985, 4845, + 3876, 3060, 2380, 1820, 1365, 1001, 715, 495, 330, 210, + 126, 70, 35, 15, 5, 1, 0, 0, 0, 0 + ], [ + 3654, 3276, 2925, 2600, 2300, 2024, 1771, 1540, 1330, 1140, + 969, 816, 680, 560, 455, 364, 286, 220, 165, 120, + 84, 56, 35, 20, 10, 4, 1, 0, 0, 0 + ], [ + 406, 378, 351, 325, 300, 276, 253, 231, 210, 190, + 171, 153, 136, 120, 105, 91, 78, 66, 55, 45, + 36, 28, 21, 15, 10, 6, 3, 1, 0, 0 + ], [ + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, + 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 + ], [ + 1; SUBFRAME_LEN/2 + ] +]; + +const PITCH_CONTRIBUTION: [i32; 340] = [ + 60, 0, 0, 2489, 60, 0, 0, 5217, 1, 6171, 0, 3953, 0, 10364, 1, 9357, + -1, 8843, 1, 9396, 0, 5794, -1, 10816, 2, 11606, -2, 12072, 0, 8616, 1, 12170, + 0, 14440, 0, 7787, -1, 13721, 0, 18205, 0, 14471, 0, 15807, 1, 15275, 0, 13480, + -1, 18375, -1, 0, 1, 11194, -1, 13010, 1, 18836, -2, 20354, 1, 16233, -1, 0, + 60, 0, 0, 12130, 0, 13385, 1, 17834, 1, 20875, 0, 21996, 1, 0, 1, 18277, + -1, 21321, 1, 13738, -1, 19094, -1, 20387, -1, 0, 0, 21008, 60, 0, -2, 22807, + 0, 15900, 1, 0, 0, 17989, -1, 22259, 1, 24395, 1, 23138, 0, 23948, 1, 22997, + 2, 22604, -1, 25942, 0, 26246, 1, 25321, 0, 26423, 0, 24061, 0, 27247, 60, 0, + -1, 25572, 1, 23918, 1, 25930, 2, 26408, -1, 19049, 1, 27357, -1, 24538, 60, 0, + -1, 25093, 0, 28549, 1, 0, 0, 22793, -1, 25659, 0, 29377, 0, 30276, 0, 26198, + 1, 22521, -1, 28919, 0, 27384, 1, 30162, -1, 0, 0, 24237, -1, 30062, 0, 21763, + 1, 30917, 60, 0, 0, 31284, 0, 29433, 1, 26821, 1, 28655, 0, 31327, 2, 30799, + 1, 31389, 0, 32322, 1, 31760, -2, 31830, 0, 26936, -1, 31180, 1, 30875, 0, 27873, + -1, 30429, 1, 31050, 0, 0, 0, 31912, 1, 31611, 0, 31565, 0, 25557, 0, 31357, + 60, 0, 1, 29536, 1, 28985, -1, 26984, -1, 31587, 2, 30836, -2, 31133, 0, 30243, + -1, 30742, -1, 32090, 60, 0, 2, 30902, 60, 0, 0, 30027, 0, 29042, 60, 0, + 0, 31756, 0, 24553, 0, 25636, -2, 30501, 60, 0, -1, 29617, 0, 30649, 60, 0, + 0, 29274, 2, 30415, 0, 27480, 0, 31213, -1, 28147, 0, 30600, 1, 31652, 2, 29068, + 60, 0, 1, 28571, 1, 28730, 1, 31422, 0, 28257, 0, 24797, 60, 0, 0, 0, + 60, 0, 0, 22105, 0, 27852, 60, 0, 60, 0, -1, 24214, 0, 24642, 0, 23305, + 60, 0, 60, 0, 1, 22883, 0, 21601, 60, 0, 2, 25650, 60, 0, -2, 31253, + -2, 25144, 0, 17998 +]; + +const POSTFILTER_COEFFS: [[i16; LPC_ORDER]; 2] = [ + [ 21299, 13844, 8999, 5849, 3802, 2471, 1606, 1044, 679, 441 ], + [ 24576, 18432, 13824, 10368, 7776, 5832, 4374, 3281, 2460, 1845 ] +]; diff --git a/nihav-vivo/src/codecs/mod.rs b/nihav-vivo/src/codecs/mod.rs new file mode 100644 index 0000000..b2ceb12 --- /dev/null +++ b/nihav-vivo/src/codecs/mod.rs @@ -0,0 +1,31 @@ +use nihav_core::codecs::*; + +#[allow(unused_macros)] +macro_rules! validate { + ($a:expr) => { if !$a { println!("check failed at {}:{}", file!(), line!()); return Err(DecoderError::InvalidData); } }; +} + +#[cfg(any(feature="decoder_vivo1", feature="decoder_vivo2"))] +mod vivo; +#[cfg(feature="decoder_g723_1")] +mod g723_1; +#[cfg(feature="decoder_siren")] +mod siren; + +const VIVO_CODECS: &[DecoderInfo] = &[ +#[cfg(feature="decoder_vivo1")] + DecoderInfo { name: "vivo1", get_decoder: vivo::get_decoder }, +#[cfg(feature="decoder_vivo2")] + DecoderInfo { name: "vivo2", get_decoder: vivo::get_decoder }, +#[cfg(feature="decoder_g723_1")] + DecoderInfo { name: "g723.1", get_decoder: g723_1::get_decoder }, +#[cfg(feature="decoder_siren")] + DecoderInfo { name: "siren", get_decoder: siren::get_decoder }, +]; + +/// Registers all available codecs provided by this crate. +pub fn vivo_register_all_codecs(rd: &mut RegisteredDecoders) { + for decoder in VIVO_CODECS.iter() { + rd.add_decoder(decoder.clone()); + } +} diff --git a/nihav-vivo/src/codecs/siren.rs b/nihav-vivo/src/codecs/siren.rs new file mode 100644 index 0000000..a9a1e2e --- /dev/null +++ b/nihav-vivo/src/codecs/siren.rs @@ -0,0 +1,895 @@ +use nihav_core::formats::SND_F32P_FORMAT; +use nihav_core::frame::*; +use nihav_core::codecs::*; +use nihav_core::io::bitreader::*; +use nihav_core::io::codebook::*; +use nihav_codec_support::dsp::mdct::IMDCT; +use nihav_codec_support::dsp::window::{generate_window, WindowType}; +use std::str::FromStr; + +const SAMPLES: usize = 320; +const NUM_REGIONS: usize = 14; +const REGION_SIZE: usize = 20; +const NUM_DIFF_CB: usize = NUM_REGIONS - 1; + +struct PRNG { + dw: [u16; 4], +} + +impl PRNG { + fn new() -> Self { Self{ dw: [1; 4] } } + fn get_dw(&mut self) -> u16 { + let mut ret = self.dw[0].wrapping_add(self.dw[3]); + if (ret & 0x8000) != 0 { + ret = ret.wrapping_add(1); + } + + self.dw[0] = self.dw[1]; + self.dw[1] = self.dw[2]; + self.dw[2] = self.dw[3]; + self.dw[3] = ret; + + ret + } +} + +struct SirenDecoder { + chmap: NAChannelMap, + ainfo: NAAudioInfo, + info: NACodecInfoRef, + diff_cb: Vec>, + vec_cb: [Codebook; 7], + imdct: IMDCT, + + coeffs: [f32; SAMPLES], + delay: [f32; SAMPLES], + synth_buf: [f32; SAMPLES * 2], + last_good_frame: [f32; SAMPLES], + window: [f32; SAMPLES], + quant_tab: [f32; 64], + + pow_index: [i32; NUM_REGIONS], + region_quant: [f32; NUM_REGIONS], + power_cat: [usize; NUM_REGIONS], + cat_balance: [usize; 16], + + rng: PRNG, +} + +fn map_idx_diff(idx: usize) -> i8 { (idx as i8) - 12 } +fn map_idx0(idx: usize) -> u16 { VEC_CB0_SYMS[idx] } +fn map_idx1(idx: usize) -> u16 { VEC_CB1_SYMS[idx] } +fn map_idx2(idx: usize) -> u16 { VEC_CB2_SYMS[idx] } +fn map_idx3(idx: usize) -> u16 { VEC_CB3_SYMS[idx] } +fn map_idx4(idx: usize) -> u16 { VEC_CB4_SYMS[idx] } +fn map_idx5(idx: usize) -> u16 { VEC_CB5_SYMS[idx] } +fn map_idx6(idx: usize) -> u16 { VEC_CB6_SYMS[idx] } +impl SirenDecoder { + fn new() -> Self { + let mut diff_cb = Vec::with_capacity(NUM_DIFF_CB); + for i in 0..NUM_DIFF_CB { + let mut cr = TableCodebookDescReader::new(&DIFF_CODE_BITS[i], &DIFF_CODE_LENS[i], map_idx_diff); + let cb = Codebook::new(&mut cr, CodebookMode::MSB).unwrap(); + diff_cb.push(cb); + } + let mut cr = TableCodebookDescReader::new(&VEC_CB0_BITS, &VEC_CB0_LENS, map_idx0); + let vec_cb0 = Codebook::new(&mut cr, CodebookMode::MSB).unwrap(); + let mut cr = TableCodebookDescReader::new(&VEC_CB1_BITS, &VEC_CB1_LENS, map_idx1); + let vec_cb1 = Codebook::new(&mut cr, CodebookMode::MSB).unwrap(); + let mut cr = TableCodebookDescReader::new(&VEC_CB2_BITS, &VEC_CB2_LENS, map_idx2); + let vec_cb2 = Codebook::new(&mut cr, CodebookMode::MSB).unwrap(); + let mut cr = TableCodebookDescReader::new(&VEC_CB3_BITS, &VEC_CB3_LENS, map_idx3); + let vec_cb3 = Codebook::new(&mut cr, CodebookMode::MSB).unwrap(); + let mut cr = TableCodebookDescReader::new(&VEC_CB4_BITS, &VEC_CB4_LENS, map_idx4); + let vec_cb4 = Codebook::new(&mut cr, CodebookMode::MSB).unwrap(); + let mut cr = TableCodebookDescReader::new(&VEC_CB5_BITS, &VEC_CB5_LENS, map_idx5); + let vec_cb5 = Codebook::new(&mut cr, CodebookMode::MSB).unwrap(); + let mut cr = TableCodebookDescReader::new(&VEC_CB6_BITS, &VEC_CB6_LENS, map_idx6); + let vec_cb6 = Codebook::new(&mut cr, CodebookMode::MSB).unwrap(); + let vec_cb = [vec_cb0, vec_cb1, vec_cb2, vec_cb3, vec_cb4, vec_cb5, vec_cb6]; + + let mut window = [0.0f32; SAMPLES]; + generate_window(WindowType::Sine, 1.0 / 320.0 / 8.0, SAMPLES, true, &mut window); + + let mut quant_tab = [0.0; 64]; + for i in 0..64 { + quant_tab[i] = 2.0f32.powf((((i as i32) - 24) as f32) / 2.0); + } + + SirenDecoder { + chmap: NAChannelMap::from_str("C").unwrap(), + ainfo: NAAudioInfo::new(16000, 1, SND_F32P_FORMAT, SAMPLES), + info: NACodecInfo::new_dummy(), + diff_cb, vec_cb, + + coeffs: [0.0; SAMPLES], + delay: [0.0; SAMPLES], + synth_buf: [0.0; SAMPLES * 2], + last_good_frame: [0.0; SAMPLES], + imdct: IMDCT::new(SAMPLES * 2, false), + window, quant_tab, + + pow_index: [0; NUM_REGIONS], + region_quant: [0.0; NUM_REGIONS], + power_cat: [0; NUM_REGIONS], + cat_balance: [0; 16], + + rng: PRNG::new(), + } + } + fn decode_envelope(&mut self, br: &mut BitReader) -> DecoderResult<()> { + self.pow_index[0] = (br.read(5)? as i32) - 7; + + for i in 1..NUM_REGIONS { + let diff = br.read_cb(&self.diff_cb[i - 1])?; + self.pow_index[i] = (self.pow_index[i - 1] + i32::from(diff)).max(-24).min(39); + } + for i in 0..NUM_REGIONS { + self.region_quant[i] = self.quant_tab[(self.pow_index[i] + 24) as usize]; + } + + Ok(()) + } + fn allocate_bits(&mut self, tot_bits: u32, rate_ctl: usize) -> DecoderResult<()> { + const CATEGORY_BITS: [u32; 8] = [ 52, 47, 43, 37, 29, 22, 16, 0 ]; + const MAX_RC: usize = 15; + + let mut offset = -32; + let mut delta = 32; + while delta > 0 { + let mut bitpool = 0; + for reg in 0..NUM_REGIONS { + let cat = ((delta + offset - self.pow_index[reg]) >> 1).max(0).min(7) as usize; + //self.power_cat[reg] = cat; + bitpool += CATEGORY_BITS[cat]; + } + if bitpool >= tot_bits - 32 { + offset += delta; + } + delta >>= 1; + } + + let mut bitpool = 0; + let mut max_rate_cat = [0; NUM_REGIONS]; + let mut min_rate_cat = [0; NUM_REGIONS]; + for reg in 0..NUM_REGIONS { + let cat = ((offset - self.pow_index[reg]) >> 1).max(0).min(7) as usize; + max_rate_cat[reg] = cat; + min_rate_cat[reg] = cat; + self.power_cat[reg] = cat; + bitpool += CATEGORY_BITS[cat]; + } + + let mut min_bitpool = bitpool; + let mut max_bitpool = bitpool; + let mut min_offset = MAX_RC + 1; + let mut max_offset = MAX_RC + 1; + let mut temp_cat = [0; 64]; + for _ in 0..MAX_RC { + if min_bitpool + max_bitpool > tot_bits * 2 { + let mut max_value = -99; + let mut min_idx = 0; + for reg in (0..NUM_REGIONS).rev() { + if min_rate_cat[reg] >= 7 { continue; } + let val = offset - self.pow_index[reg] - 2 * (min_rate_cat[reg] as i32); + if max_value < val { + max_value = val; + min_idx = reg; + } + } + validate!(max_value != -99); + temp_cat[min_offset] = min_idx; + min_offset += 1; + min_bitpool = min_bitpool + CATEGORY_BITS[min_rate_cat[min_idx] + 1] - CATEGORY_BITS[min_rate_cat[min_idx]]; + min_rate_cat[min_idx] += 1; + } else { + let mut min_value = 99; + let mut max_idx = 0; + for reg in 0..NUM_REGIONS { + if max_rate_cat[reg] == 0 { continue; } + let val = offset - self.pow_index[reg] - 2 * (max_rate_cat[reg] as i32); + if min_value > val { + min_value = val; + max_idx = reg; + } + } + validate!(min_value != 99); + max_offset -= 1; + temp_cat[max_offset] = max_idx; + max_bitpool = max_bitpool + CATEGORY_BITS[max_rate_cat[max_idx] - 1] - CATEGORY_BITS[max_rate_cat[max_idx]]; + max_rate_cat[max_idx] -= 1; + } + } + + self.power_cat = max_rate_cat; + + for i in 0..MAX_RC { + self.cat_balance[i] = temp_cat[max_offset + i]; + } + + for cat in self.cat_balance.iter().take(rate_ctl) { + self.power_cat[*cat] += 1; + } + Ok(()) + } + fn decode_coefficients(&mut self, br: &mut BitReader) -> DecoderResult { + const NUM_VECTORS: [u8; 8] = [ 10, 10, 10, 5, 5, 4, 4, 20 ]; + const VECTOR_SIZE: [u8; 8] = [ 2, 2, 2, 4, 4, 5, 5, 1 ]; + const INDEX_BITS: [u8; 8] = [ 4, 4, 3, 3, 2, 2, 1, 0 ]; + + let mut error = false; + self.coeffs = [0.0; SAMPLES]; + for (reg, coeffs) in self.coeffs.chunks_exact_mut(REGION_SIZE).take(NUM_REGIONS).enumerate() { + let mut cat = self.power_cat[reg]; + if cat < 7 { + let cb = &self.vec_cb[cat]; + let num_vecs = NUM_VECTORS[cat] as usize; + let vec_len = VECTOR_SIZE[cat] as usize; + + 'vec_loop: for i in 0..num_vecs { + let ret = br.read_cb(cb); + if let Err(_) = ret { + error = true; + break 'vec_loop; + } + let mut idx = ret.ok().unwrap_or(0) as usize; + let mask = (1 << INDEX_BITS[cat]) - 1; + for j in 0..vec_len { + let coef = QUANT_LEVELS[cat][idx & mask] * self.region_quant[reg]; + idx >>= INDEX_BITS[cat]; + if coef != 0.0 { + if br.left() == 0 { + break 'vec_loop; + } + coeffs[i * vec_len + j] = if br.read_bool()? { -coef } else { coef }; + } + } + } + if error { + cat = 7; + for i in reg..NUM_REGIONS { + self.power_cat[i] = 7; + } + } + } + let noise_val = match cat { + 5 => { + let mut nz_count = 0; + for el in coeffs.iter() { + if *el != 0.0 { + if *el > 2.0 * self.region_quant[reg] { + nz_count += 4; + } + nz_count += 1; + } + } + if nz_count < REGION_SIZE { + self.region_quant[reg] * CAT5_NOISE_FACTOR[nz_count] + } else { + 0.0 + } + }, + 6 => { + let mut nz_count = 0; + for el in coeffs.iter() { + if *el != 0.0 { + nz_count += 1; + } + } + self.region_quant[reg] * CAT6_NOISE_FACTOR[nz_count] + }, + 7 => { + self.region_quant[reg] * 0.70711 + }, + _ => 0.0, + }; + if cat >= 5 { + let mut dw1 = self.rng.get_dw(); + let mut dw2 = self.rng.get_dw(); + for pair in coeffs.chunks_exact_mut(2) { + if (cat == 7) || pair[0] == 0.0 { + pair[0] = if (dw1 & 1) != 0 { noise_val } else { -noise_val }; + } + if (cat == 7) || pair[1] == 0.0 { + pair[1] = if (dw2 & 1) != 0 { noise_val } else { -noise_val }; + } + dw1 >>= 1; + dw2 >>= 1; + } + } + } + Ok(error) + } +} + +impl NADecoder for SirenDecoder { + fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> { + if let NACodecTypeInfo::Audio(_ainfo) = info.get_properties() { + self.info = info.replace_info(NACodecTypeInfo::Audio(self.ainfo)); + Ok(()) + } else { + Err(DecoderError::InvalidData) + } + } + fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult { + let info = pkt.get_stream().get_info(); + validate!(info.get_properties().is_audio()); + let src = pkt.get_buffer(); + + let mut br = BitReader::new(src.as_slice(), BitReaderMode::BE); + self.decode_envelope(&mut br)?; + let rate_ctl = br.read(4)? as usize; + self.allocate_bits(br.left() as u32, rate_ctl)?; + self.decode_coefficients(&mut br)?; + + let mut bad_frame = false; + while br.left() > 0 { + bad_frame |= !br.read_bool().ok().unwrap_or(true); + } + for el in self.pow_index.iter() { + if *el > 33 { + bad_frame = true; + } + } + + if bad_frame { + self.coeffs.copy_from_slice(&self.last_good_frame); + self.last_good_frame = [0.0; SAMPLES]; + } else { + self.last_good_frame.copy_from_slice(&self.coeffs); + } + + let abuf = alloc_audio_buffer(self.ainfo, SAMPLES, self.chmap.clone())?; + let mut adata = abuf.get_abuf_f32().unwrap(); + let asamples = adata.get_data_mut().unwrap(); + + self.imdct.imdct_half(&self.coeffs, &mut self.synth_buf); + for i in (0..SAMPLES/2).step_by(2) { + let idx0 = i; + let idx1 = SAMPLES / 2 - 1 - i; + let idx2 = SAMPLES / 2 + i; + let idx3 = SAMPLES - 1 - i; + // samples are actually in reverse order + let c3 = self.synth_buf[idx0]; + let c2 = self.synth_buf[idx1]; + let c1 = self.synth_buf[idx2]; + let c0 = self.synth_buf[idx3]; + + let d0 = self.delay[idx0]; + let d1 = self.delay[idx1]; + + let w0 = self.window[idx0]; + let w1 = self.window[idx1]; + let w2 = self.window[idx2]; + let w3 = self.window[idx3]; + + asamples[idx3] = c1 * w3 - d0 * w0; + asamples[idx2] = c0 * w2 - d1 * w1; + asamples[idx1] = d1 * w2 + c0 * w1; + asamples[idx0] = d0 * w3 + c1 * w0; + + self.delay[idx0] = c2; + self.delay[idx1] = c3; + } + + let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), abuf); + frm.set_keyframe(true); + Ok(frm.into_ref()) + } + fn flush(&mut self) { + self.delay = [0.0; SAMPLES]; + self.last_good_frame = [0.0; SAMPLES]; + } +} + +pub fn get_decoder() -> Box { + Box::new(SirenDecoder::new()) +} + +#[cfg(test)] +mod test { + use nihav_core::codecs::RegisteredDecoders; + use nihav_core::demuxers::RegisteredDemuxers; + use nihav_codec_support::test::dec_video::*; + use crate::vivo_register_all_codecs; + use crate::vivo_register_all_demuxers; + #[test] + fn test_siren() { + let mut dmx_reg = RegisteredDemuxers::new(); + vivo_register_all_demuxers(&mut dmx_reg); + let mut dec_reg = RegisteredDecoders::new(); + vivo_register_all_codecs(&mut dec_reg); + + let file = "assets/Misc/favmovie.viv"; + //let file = "assets/Misc/gr_al.viv"; + test_decode_audio("vivo", file, None, None/*Some("siren")*/, &dmx_reg, &dec_reg); + } +} + +const DIFF_CODE_BITS: [[u16; 24]; NUM_DIFF_CB] = [ + [ + 0x0008, 0x0026, 0x0012, 0x000A, 0x0007, 0x0006, 0x0003, 0x0002, + 0x0000, 0x0001, 0x0007, 0x0006, 0x0005, 0x0004, 0x000B, 0x004E, + 0x009E, 0x013E, 0x04FE, 0x04FF, 0x09F8, 0x09F9, 0x09FA, 0x09FB + ], [ + 0x0024, 0x0008, 0x0003, 0x0005, 0x0000, 0x0001, 0x0007, 0x0006, + 0x0004, 0x0003, 0x0002, 0x0005, 0x0003, 0x0004, 0x0005, 0x0013, + 0x004A, 0x0096, 0x012E, 0x04BD, 0x04BE, 0x04BF, 0x0978, 0x0979 + ], [ + 0x0A16, 0x0284, 0x00A0, 0x0029, 0x0005, 0x000B, 0x0007, 0x0005, + 0x0004, 0x0001, 0x0000, 0x0006, 0x0004, 0x0007, 0x0003, 0x0006, + 0x0004, 0x0015, 0x0051, 0x0143, 0x050A, 0x142F, 0x285C, 0x285D + ], [ + 0x0B7C, 0x016E, 0x00B5, 0x00B4, 0x002F, 0x002E, 0x001B, 0x000A, + 0x0008, 0x0005, 0x0001, 0x0000, 0x0003, 0x0007, 0x0004, 0x0009, + 0x000C, 0x001A, 0x002C, 0x00B6, 0x02DE, 0x0B7D, 0x0B7E, 0x0B7F + ], [ + 0x0F8E, 0x1F1F, 0x03E2, 0x00F9, 0x003F, 0x001A, 0x0013, 0x0012, + 0x000E, 0x0008, 0x0006, 0x0001, 0x0000, 0x0002, 0x0005, 0x0007, + 0x000C, 0x001E, 0x001B, 0x007D, 0x01F0, 0x07C6, 0x3E3C, 0x3E3D + ], [ + 0x0CB6, 0x065A, 0x0197, 0x00CE, 0x00CA, 0x0064, 0x001E, 0x000E, + 0x0003, 0x0005, 0x0003, 0x0000, 0x0002, 0x0004, 0x0002, 0x000D, + 0x0018, 0x001F, 0x0066, 0x00CF, 0x032C, 0x196F, 0x32DC, 0x32DD + ], [ + 0x0456, 0x08A8, 0x0457, 0x008B, 0x0023, 0x0009, 0x0003, 0x0014, + 0x000B, 0x0004, 0x0002, 0x0001, 0x0003, 0x0003, 0x0001, 0x0000, + 0x0015, 0x0005, 0x0010, 0x0044, 0x0114, 0x08A9, 0x08AA, 0x08AB + ], [ + 0x03F5, 0x03F6, 0x007F, 0x003E, 0x001D, 0x0006, 0x0004, 0x0010, + 0x0000, 0x0001, 0x0003, 0x0002, 0x0003, 0x0001, 0x0005, 0x0009, + 0x0011, 0x0005, 0x001C, 0x001E, 0x00FC, 0x03F7, 0x07E8, 0x07E9 + ], [ + 0x017D, 0x017C, 0x0174, 0x00BF, 0x005E, 0x002C, 0x0010, 0x000A, + 0x0007, 0x0003, 0x0001, 0x0000, 0x0002, 0x0006, 0x0009, 0x0011, + 0x002D, 0x005C, 0x00BB, 0x02EA, 0x05D6, 0x0BAF, 0x175C, 0x175D + ], [ + 0x0BDC, 0x02F6, 0x00BC, 0x002D, 0x002B, 0x000A, 0x0004, 0x0003, + 0x0006, 0x0004, 0x0002, 0x0000, 0x0003, 0x0007, 0x000B, 0x0014, + 0x002A, 0x002C, 0x002E, 0x005F, 0x017A, 0x0BDD, 0x0BDE, 0x0BDF + ], [ + 0x02EF, 0x005C, 0x002D, 0x0014, 0x001A, 0x0004, 0x000C, 0x0007, + 0x0004, 0x0000, 0x0004, 0x0001, 0x0003, 0x0005, 0x0005, 0x0003, + 0x001B, 0x0015, 0x002C, 0x002F, 0x00BA, 0x0176, 0x05DC, 0x05DD + ], [ + 0xB204, 0x1641, 0x0B21, 0x0591, 0x0165, 0x002D, 0x0017, 0x0006, + 0x000A, 0x0007, 0x0002, 0x0002, 0x0003, 0x0000, 0x0004, 0x0006, + 0x0007, 0x0058, 0x00B3, 0x02C9, 0x2C80, 0xB205, 0xB206, 0xB207 + ], [ + 0x09CF, 0x1398, 0x139A, 0x1399, 0x0138, 0x004F, 0x0026, 0x0024, + 0x001E, 0x000E, 0x0006, 0x0000, 0x0002, 0x0001, 0x0003, 0x0005, + 0x0008, 0x001F, 0x0025, 0x009D, 0x0272, 0x139B, 0x139C, 0x139D + ] +]; +const DIFF_CODE_LENS: [[u8; 24]; 13/*27*/] = [ + [ 4, 6, 5, 5, 4, 4, 4, 4, 4, 4, 3, 3, 3, 4, 5, 7, 8, 9, 11, 11, 12, 12, 12, 12 ], + [ 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 3, 3, 4, 5, 7, 9, 11, 12, 13, 15, 15, 15, 16, 16 ], + [ 12, 10, 8, 6, 5, 4, 4, 4, 4, 4, 4, 3, 3, 3, 4, 4, 5, 5, 7, 9, 11, 13, 14, 14 ], + [ 13, 10, 9, 9, 7, 7, 5, 5, 4, 3, 3, 3, 3, 3, 4, 4, 4, 5, 7, 9, 11, 13, 13, 13 ], + [ 12, 13, 10, 8, 6, 6, 5, 5, 4, 4, 3, 3, 3, 3, 3, 4, 5, 5, 6, 7, 9, 11, 14, 14 ], + [ 12, 11, 9, 8, 8, 7, 5, 4, 4, 3, 3, 3, 3, 3, 4, 4, 5, 5, 7, 8, 10, 13, 14, 14 ], + [ 15, 16, 15, 12, 10, 8, 6, 5, 4, 3, 3, 3, 2, 3, 4, 5, 5, 7, 9, 11, 13, 16, 16, 16 ], + [ 14, 14, 11, 10, 9, 7, 7, 5, 5, 4, 3, 3, 2, 3, 3, 4, 5, 7, 9, 9, 12, 14, 15, 15 ], + [ 9, 9, 9, 8, 7, 6, 5, 4, 3, 3, 3, 3, 3, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 13 ], + [ 14, 12, 10, 8, 6, 6, 5, 4, 3, 3, 3, 3, 3, 3, 4, 5, 6, 8, 8, 9, 11, 14, 14, 14 ], + [ 13, 10, 9, 8, 6, 6, 5, 4, 4, 4, 3, 3, 2, 3, 4, 5, 6, 8, 9, 9, 11, 12, 14, 14 ], + [ 16, 13, 12, 11, 9, 6, 5, 5, 4, 4, 4, 3, 2, 3, 3, 4, 5, 7, 8, 10, 14, 16, 16, 16 ], + [ 13, 14, 14, 14, 10, 8, 7, 7, 5, 4, 3, 3, 2, 3, 3, 4, 5, 5, 7, 9, 11, 14, 14, 14 ] +]; + +const VEC_CB0_BITS: [u16; 181] = [ + 0x0000, 0x0001, 0x0001, 0x0010, 0x0044, 0x0114, 0x0115, 0x008B, + 0x0023, 0x0009, 0x0005, 0x0018, 0x0019, 0x000D, 0x0007, 0x0001, + 0x0010, 0x0044, 0x0114, 0x0115, 0x022C, 0x045A, 0x045B, 0x0117, + 0x0046, 0x0047, 0x0009, 0x0014, 0x0015, 0x0016, 0x002E, 0x005E, + 0x005F, 0x000C, 0x001A, 0x0036, 0x0037, 0x000E, 0x001E, 0x003E, + 0x00FC, 0x00FD, 0x01FC, 0x01FD, 0x01FE, 0x01FF, 0x0008, 0x0090, + 0x0091, 0x0049, 0x004A, 0x004B, 0x004C, 0x009A, 0x0136, 0x09B8, + 0x1372, 0x1373, 0x1374, 0x1375, 0x1376, 0x1377, 0x026F, 0x004E, + 0x004F, 0x000A, 0x0016, 0x0017, 0x0018, 0x0032, 0x0033, 0x00D0, + 0x01A2, 0x0346, 0x0347, 0x0069, 0x00D4, 0x00D5, 0x01AC, 0x06B4, + 0x06B5, 0x06B6, 0x1ADC, 0x1ADD, 0x0D6F, 0x00D7, 0x0036, 0x0037, + 0x000E, 0x0078, 0x0079, 0x003D, 0x003E, 0x003F, 0x0002, 0x0003, + 0x0020, 0x0420, 0x0421, 0x0422, 0x0423, 0x0212, 0x0426, 0x0427, + 0x0085, 0x010C, 0x010D, 0x010E, 0x010F, 0x0044, 0x0114, 0x022A, + 0x022B, 0x0116, 0x08B8, 0x08B9, 0x045D, 0x1178, 0x1179, 0x08BD, + 0x045F, 0x008C, 0x008D, 0x0047, 0x0012, 0x0098, 0x0099, 0x0134, + 0x0135, 0x0136, 0x0137, 0x004E, 0x0278, 0x0279, 0x013D, 0x013E, + 0x09F8, 0x27E4, 0x27E5, 0x13F3, 0x04FD, 0x027F, 0x000A, 0x0016, + 0x005C, 0x00BA, 0x00BB, 0x005E, 0x02F8, 0x02F9, 0x017D, 0x00BF, + 0x0018, 0x0032, 0x0033, 0x0034, 0x0350, 0x0351, 0x0352, 0x0353, + 0x00D5, 0x006B, 0x006C, 0x00DA, 0x00DB, 0x006E, 0x01BC, 0x01BD, + 0x00DF, 0x001C, 0x003A, 0x03B0, 0x0762, 0x0763, 0x01D9, 0x01DA, + 0x01DB, 0x00EE, 0x00EF, 0x000F, 0x0001 +]; +const VEC_CB0_LENS: [u8; 181] = [ + 9, 9, 8, 11, 13, 15, 15, 14, 12, 10, 9, 11, 11, 10, 9, 6, + 9, 11, 13, 13, 14, 15, 15, 13, 11, 11, 8, 9, 9, 9, 10, 11, + 11, 8, 9, 10, 10, 8, 9, 10, 12, 12, 13, 13, 13, 13, 7, 11, + 11, 10, 10, 10, 10, 11, 12, 15, 16, 16, 16, 16, 16, 16, 13, 10, + 10, 7, 8, 8, 8, 9, 9, 11, 12, 13, 13, 10, 11, 11, 12, 14, + 14, 14, 16, 16, 15, 11, 9, 9, 7, 10, 10, 9, 9, 9, 4, 4, + 7, 12, 12, 12, 12, 11, 12, 12, 9, 10, 10, 10, 10, 8, 10, 11, + 11, 10, 13, 13, 12, 14, 14, 13, 12, 9, 9, 8, 6, 9, 9, 10, + 10, 10, 10, 8, 11, 11, 10, 10, 13, 15, 15, 14, 12, 11, 5, 6, + 8, 9, 9, 8, 11, 11, 10, 9, 6, 7, 7, 7, 11, 11, 11, 11, + 9, 8, 8, 9, 9, 8, 10, 10, 9, 6, 7, 11, 12, 12, 10, 10, + 10, 9, 9, 5, 1 +]; +const VEC_CB0_SYMS: [u16; 181] = [ + 37, 51, 5, 102, 76, 139, 155, 169, 151, 41, 82, 103, + 118, 100, 8, 32, 113, 134, 211, 182, 213, 214, 124, 183, + 28, 29, 96, 52, 24, 67, 146, 193, 104, 35, 144, 176, + 115, 21, 129, 70, 210, 45, 123, 197, 92, 61, 49, 74, + 164, 56, 11, 177, 42, 192, 195, 109, 185, 156, 140, 216, + 171, 201, 212, 27, 57, 19, 81, 50, 6, 145, 38, 12, + 60, 122, 77, 131, 119, 59, 166, 153, 199, 93, 125, 141, + 215, 13, 98, 53, 64, 101, 85, 9, 25, 114, 16, 1, + 4, 137, 106, 150, 121, 149, 91, 167, 83, 116, 117, 71, + 178, 112, 162, 179, 44, 147, 152, 198, 181, 154, 170, 138, + 107, 10, 39, 97, 18, 40, 54, 86, 72, 88, 43, 22, + 209, 90, 163, 133, 108, 186, 200, 184, 196, 165, 17, 33, + 7, 26, 68, 36, 135, 208, 87, 99, 48, 20, 80, 34, + 105, 180, 75, 194, 161, 66, 23, 160, 84, 128, 58, 148, + 55, 3, 65, 120, 136, 168, 132, 73, 89, 69, 130, 2, 0 +]; + +const VEC_CB1_BITS: [u16; 94] = [ + 0x0000, 0x0010, 0x0044, 0x0045, 0x0023, 0x0009, 0x0005, 0x000C, + 0x000D, 0x000E, 0x001E, 0x001F, 0x0001, 0x0002, 0x000C, 0x0034, + 0x01A8, 0x0352, 0x0353, 0x00D5, 0x006B, 0x0036, 0x006E, 0x006F, + 0x01C0, 0x01C1, 0x00E1, 0x0071, 0x0072, 0x0073, 0x01D0, 0x03A2, + 0x03A3, 0x00E9, 0x0075, 0x003B, 0x0078, 0x00F2, 0x01E6, 0x01E7, + 0x003D, 0x001F, 0x0020, 0x0021, 0x0088, 0x0112, 0x0113, 0x0045, + 0x0023, 0x0024, 0x0094, 0x0095, 0x004B, 0x004C, 0x009A, 0x0136, + 0x04DC, 0x4DD0, 0x4DD1, 0x26E9, 0x1375, 0x09BB, 0x026F, 0x0027, + 0x000A, 0x000B, 0x0018, 0x0064, 0x00CA, 0x0196, 0x0197, 0x0066, + 0x0067, 0x001A, 0x001B, 0x000E, 0x0078, 0x0790, 0x0F22, 0x1E46, + 0x1E47, 0x03C9, 0x01E5, 0x00F3, 0x007A, 0x00F6, 0x03DC, 0x07BA, + 0x1EEC, 0x1EED, 0x0F77, 0x01EF, 0x001F, 0x0001 +]; +const VEC_CB1_LENS: [u8; 94] = [ + 5, 9, 11, 11, 10, 8, 7, 8, 8, 8, 9, 9, 4, 4, 6, 8, + 11, 12, 12, 10, 9, 8, 9, 9, 11, 11, 10, 9, 9, 9, 11, 12, + 12, 10, 9, 8, 9, 10, 11, 11, 8, 7, 7, 7, 9, 10, 10, 8, + 7, 7, 9, 9, 8, 8, 9, 10, 12, 16, 16, 15, 14, 13, 11, 7, + 5, 5, 6, 8, 9, 10, 10, 8, 8, 6, 6, 5, 8, 12, 13, 14, + 14, 11, 10, 9, 8, 9, 11, 12, 14, 14, 13, 10, 6, 1 +]; +const VEC_CB1_SYMS: [u16; 94] = [ + 17, 23, 86, 131, 85, 80, 49, 21, 5, 36, 83, 112, + 1, 16, 33, 51, 71, 87, 88, 70, 39, 81, 53, 113, + 145, 117, 55, 68, 98, 7, 41, 118, 57, 100, 84, 66, + 99, 115, 116, 132, 52, 64, 20, 65, 54, 25, 128, 37, + 4, 35, 8, 69, 22, 6, 24, 144, 147, 120, 105, 150, + 135, 148, 102, 50, 2, 32, 3, 82, 114, 9, 56, 97, + 67, 19, 48, 18, 96, 103, 73, 104, 149, 146, 130, 40, + 38, 129, 72, 133, 119, 89, 134, 101, 34, 0 +]; + +const VEC_CB2_BITS: [u16; 48] = [ + 0x0000, 0x0008, 0x0024, 0x004A, 0x004B, 0x0013, 0x000A, 0x000B, + 0x0018, 0x0019, 0x0034, 0x0035, 0x006C, 0x00DA, 0x01B6, 0x01B7, + 0x0037, 0x001C, 0x001D, 0x001E, 0x003E, 0x003F, 0x0002, 0x0018, + 0x0019, 0x000D, 0x0007, 0x0008, 0x0009, 0x000A, 0x0160, 0x0161, + 0x0162, 0x0163, 0x0059, 0x00B4, 0x2D40, 0x5A82, 0x5A83, 0x16A1, + 0x0B51, 0x05A9, 0x02D5, 0x016B, 0x005B, 0x0017, 0x0003, 0x0001 +]; +const VEC_CB2_LENS: [u8; 48] = [ + 4, 7, 9, 10, 10, 8, 7, 7, 8, 8, 9, 9, 10, 11, 12, 12, + 9, 8, 8, 8, 9, 9, 4, 7, 7, 6, 5, 5, 5, 5, 10, 10, + 10, 10, 8, 9, 15, 16, 16, 14, 13, 12, 11, 10, 8, 6, 3, 1 +]; +const VEC_CB2_SYMS: [u16; 48] = [ + 8, 25, 13, 42, 14, 12, 3, 24, 33, 4, 28, 41, + 36, 22, 44, 30, 35, 32, 27, 20, 40, 21, 9, 19, + 26, 18, 2, 10, 17, 16, 49, 29, 43, 50, 34, 6, + 45, 53, 46, 52, 38, 51, 37, 48, 5, 11, 1, 0 +]; + +const VEC_CB3_BITS: [u16; 520] = [ + 0x0000, 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, + 0x0087, 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x008D, 0x008E, + 0x008F, 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, + 0x0097, 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, + 0x013E, 0x013F, 0x0005, 0x0003, 0x0002, 0x000C, 0x001A, 0x001B, + 0x0038, 0x0039, 0x003A, 0x003B, 0x000F, 0x0008, 0x0090, 0x0091, + 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, + 0x009A, 0x009B, 0x0027, 0x0005, 0x000C, 0x000D, 0x000E, 0x001E, + 0x001F, 0x0040, 0x0041, 0x0042, 0x0860, 0x0861, 0x0862, 0x0863, + 0x0864, 0x0865, 0x0866, 0x0867, 0x0868, 0x0869, 0x086A, 0x086B, + 0x086C, 0x086D, 0x086E, 0x086F, 0x0870, 0x0871, 0x0872, 0x0873, + 0x0874, 0x0875, 0x0876, 0x0877, 0x0878, 0x0879, 0x087A, 0x087B, + 0x087C, 0x087D, 0x087E, 0x087F, 0x0880, 0x0881, 0x0882, 0x0883, + 0x0884, 0x0885, 0x0886, 0x0887, 0x0888, 0x0889, 0x088A, 0x088B, + 0x088C, 0x088D, 0x088E, 0x088F, 0x0890, 0x0891, 0x0892, 0x0893, + 0x0894, 0x0895, 0x0896, 0x0897, 0x0898, 0x0899, 0x089A, 0x089B, + 0x089C, 0x089D, 0x089E, 0x089F, 0x08A0, 0x08A1, 0x08A2, 0x08A3, + 0x08A4, 0x08A5, 0x08A6, 0x08A7, 0x08A8, 0x08A9, 0x08AA, 0x08AB, + 0x08AC, 0x08AD, 0x08AE, 0x08AF, 0x08B0, 0x08B1, 0x08B2, 0x08B3, + 0x08B4, 0x08B5, 0x08B6, 0x08B7, 0x08B8, 0x08B9, 0x08BA, 0x08BB, + 0x08BC, 0x08BD, 0x08BE, 0x08BF, 0x08C0, 0x08C1, 0x08C2, 0x08C3, + 0x08C4, 0x08C5, 0x08C6, 0x08C7, 0x08C8, 0x08C9, 0x08CA, 0x08CB, + 0x08CC, 0x08CD, 0x08CE, 0x08CF, 0x08D0, 0x08D1, 0x08D2, 0x08D3, + 0x08D4, 0x08D5, 0x08D6, 0x08D7, 0x08D8, 0x08D9, 0x08DA, 0x08DB, + 0x08DC, 0x08DD, 0x08DE, 0x08DF, 0x08E0, 0x08E1, 0x08E2, 0x08E3, + 0x08E4, 0x08E5, 0x08E6, 0x08E7, 0x08E8, 0x08E9, 0x08EA, 0x08EB, + 0x08EC, 0x08ED, 0x08EE, 0x08EF, 0x08F0, 0x08F1, 0x08F2, 0x08F3, + 0x08F4, 0x08F5, 0x08F6, 0x08F7, 0x08F8, 0x08F9, 0x08FA, 0x08FB, + 0x08FC, 0x08FD, 0x08FE, 0x08FF, 0x0009, 0x0A00, 0x0A01, 0x0A02, + 0x0A03, 0x0A04, 0x0A05, 0x0A06, 0x0A07, 0x0A08, 0x0A09, 0x0A0A, + 0x0A0B, 0x0A0C, 0x0A0D, 0x0A0E, 0x0A0F, 0x0A10, 0x0A11, 0x0A12, + 0x0A13, 0x0A14, 0x0A15, 0x0A16, 0x0A17, 0x0A18, 0x0A19, 0x0A1A, + 0x0A1B, 0x0A1C, 0x0A1D, 0x0A1E, 0x0A1F, 0x0A20, 0x0A21, 0x0A22, + 0x0A23, 0x0A24, 0x0A25, 0x0A26, 0x0A27, 0x0A28, 0x0A29, 0x0A2A, + 0x0A2B, 0x0A2C, 0x0A2D, 0x0A2E, 0x0A2F, 0x00A3, 0x0029, 0x002A, + 0x0056, 0x0057, 0x000B, 0x0003, 0x0004, 0x0005, 0x0030, 0x0062, + 0x18C0, 0x18C1, 0x18C2, 0x18C3, 0x18C4, 0x18C5, 0x18C6, 0x18C7, + 0x0319, 0x018D, 0x00C7, 0x0032, 0x0198, 0x0199, 0x019A, 0x019B, + 0x0067, 0x001A, 0x0360, 0x0361, 0x0362, 0x0363, 0x0364, 0x0365, + 0x0366, 0x0367, 0x0368, 0x0369, 0x036A, 0x036B, 0x00DB, 0x006E, + 0x006F, 0x001C, 0x00E8, 0x00E9, 0x0075, 0x0076, 0x0077, 0x0780, + 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0786, 0x0787, 0x0788, + 0x0789, 0x078A, 0x078B, 0x078C, 0x078D, 0x078E, 0x078F, 0x0079, + 0x003D, 0x007C, 0x07D0, 0x07D1, 0x07D2, 0x07D3, 0x01F5, 0x00FB, + 0x00FC, 0x00FD, 0x00FE, 0x01FE, 0x01FF, 0x0004, 0x0005, 0x000C, + 0x0068, 0x00D2, 0x00D3, 0x0035, 0x0036, 0x0037, 0x0038, 0x00E4, + 0x00E5, 0x0073, 0x003A, 0x0076, 0x01DC, 0x01DD, 0x00EF, 0x000F, + 0x0008, 0x0009, 0x0050, 0x0144, 0x0145, 0x0146, 0x028E, 0x051E, + 0x051F, 0x0052, 0x0530, 0x0531, 0x0532, 0x0533, 0x0534, 0x0535, + 0x0536, 0x0537, 0x014E, 0x0A78, 0x0A79, 0x0A7A, 0x0A7B, 0x0A7C, + 0x0A7D, 0x0A7E, 0x0A7F, 0x0015, 0x0016, 0x0017, 0x0006, 0x0070, + 0x00E2, 0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x038D, 0x01C7, 0x0039, + 0x01D0, 0x03A2, 0x0E8C, 0x0E8D, 0x0747, 0x00E9, 0x0075, 0x003B, + 0x001E, 0x007C, 0x00FA, 0x03EC, 0x03ED, 0x03EE, 0x07DE, 0x07DF, + 0x07E0, 0x07E1, 0x07E2, 0x07E3, 0x01F9, 0x00FD, 0x007F, 0x0008, + 0x0090, 0x0091, 0x0092, 0x0093, 0x0128, 0x0129, 0x012A, 0x0958, + 0x9590, 0x9591, 0x4AC9, 0x2565, 0x12B3, 0x04AD, 0x0257, 0x004B, + 0x0098, 0x0264, 0x0265, 0x0266, 0x04CE, 0x04CF, 0x004D, 0x009C, + 0x013A, 0x0276, 0x0277, 0x004F, 0x00A0, 0x0284, 0x050A, 0x050B, + 0x050C, 0x0A1A, 0x0A1B, 0x0A1C, 0x0A1D, 0x0A1E, 0x0A1F, 0x00A2, + 0x0A30, 0x0A31, 0x0A32, 0x0A33, 0x028D, 0x028E, 0x1478, 0x1479, + 0x147A, 0x147B, 0x147C, 0x147D, 0x147E, 0x147F, 0x0029, 0x0015, + 0x0058, 0x0059, 0x00B4, 0x16A0, 0x16A1, 0x16A2, 0x16A3, 0x16A4, + 0x16A5, 0x16A6, 0x2D4E, 0x2D4F, 0x02D5, 0x016B, 0x02D8, 0x02D9, + 0x016D, 0x016E, 0x05BC, 0x05BD, 0x02DF, 0x002E, 0x002F, 0x0003 +]; +const VEC_CB3_LENS: [u8; 520] = [ + 8, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 16, 16, 10, 9, 8, 10, 11, 11, 12, 12, 12, 12, 10, 9, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 11, 8, 9, 9, 9, 10, + 10, 11, 11, 11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 8, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 12, 10, 10, 11, 11, 8, 6, 6, 6, 9, 10, + 16, 16, 16, 16, 16, 16, 16, 16, 13, 12, 11, 9, 12, 12, 12, 12, + 10, 8, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 11, 10, + 10, 8, 11, 11, 10, 10, 10, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 10, 9, 10, 14, 14, 14, 14, 12, 11, + 11, 11, 11, 12, 12, 5, 5, 6, 9, 10, 10, 8, 8, 8, 8, 10, + 10, 9, 8, 9, 11, 11, 10, 6, 5, 5, 8, 10, 10, 10, 11, 12, + 12, 8, 12, 12, 12, 12, 12, 12, 12, 12, 10, 13, 13, 13, 13, 13, + 13, 13, 13, 6, 6, 6, 4, 8, 9, 13, 13, 13, 13, 11, 10, 7, + 10, 11, 13, 13, 12, 9, 8, 7, 6, 8, 9, 11, 11, 11, 12, 12, + 12, 12, 12, 12, 10, 9, 8, 4, 8, 8, 8, 8, 9, 9, 9, 12, + 16, 16, 15, 14, 13, 11, 10, 7, 8, 10, 10, 10, 11, 11, 7, 8, + 9, 10, 10, 7, 8, 10, 11, 11, 11, 12, 12, 12, 12, 12, 12, 8, + 12, 12, 12, 12, 10, 10, 13, 13, 13, 13, 13, 13, 13, 13, 6, 5, + 7, 7, 8, 13, 13, 13, 13, 13, 13, 13, 14, 14, 10, 9, 10, 10, + 9, 9, 11, 11, 10, 6, 6, 2 +]; +const VEC_CB3_SYMS: [u16; 520] = [ + 74, 1120, 1682, 1745, 1801, 274, 1050, 730, 546, 1058, 1729, 1539, + 2240, 1547, 1163, 1730, 2064, 1624, 723, 1235, 1115, 35, 2248, 1304, + 644, 196, 1625, 1036, 1548, 1185, 652, 1044, 2136, 1753, 1664, 129, + 640, 83, 665, 130, 1225, 1232, 602, 76, 587, 1161, 1049, 545, + 265, 1218, 2113, 202, 98, 131, 643, 1288, 524, 785, 720, 1096, + 704, 528, 657, 601, 67, 537, 33, 579, 1746, 2258, 1248, 786, + 1298, 1810, 2265, 2313, 1761, 1562, 2074, 2264, 1569, 2257, 225, 2138, + 1056, 2081, 2249, 1690, 2202, 736, 2186, 1242, 1754, 282, 794, 1306, + 1792, 1561, 2201, 1570, 2073, 281, 1122, 1634, 2178, 674, 1186, 1698, + 226, 738, 1250, 1240, 289, 800, 1738, 2051, 1632, 1121, 793, 1603, + 2115, 1633, 2250, 737, 1667, 2179, 195, 707, 1219, 1731, 2243, 259, + 771, 1283, 1795, 2304, 2144, 2305, 1249, 2059, 2192, 2072, 2200, 1611, + 2123, 1689, 288, 1696, 1675, 2187, 203, 792, 1227, 1739, 2251, 267, + 779, 1291, 1803, 1802, 2256, 2242, 1555, 2067, 1560, 258, 1688, 1619, + 2131, 770, 2145, 2114, 1683, 2195, 211, 1057, 2065, 1747, 275, 787, + 1299, 1817, 1697, 1051, 1563, 2075, 1794, 2050, 801, 1627, 2139, 1800, + 667, 1179, 1691, 219, 731, 1243, 1755, 283, 795, 2066, 547, 1059, + 1571, 1184, 611, 1123, 1635, 163, 675, 1187, 227, 739, 1568, 1760, + 1028, 1540, 2052, 2193, 1752, 1092, 1604, 2116, 1793, 2177, 1156, 1668, + 649, 1618, 708, 1220, 1732, 260, 772, 1808, 1816, 280, 2312, 2060, + 1305, 1241, 1297, 1612, 2124, 140, 2122, 1164, 1676, 204, 716, 1228, + 1740, 268, 780, 2241, 1809, 2194, 1556, 2137, 2058, 1108, 1620, 148, + 660, 1172, 1684, 212, 724, 1236, 28, 540, 1052, 1564, 92, 604, + 1116, 666, 1105, 1153, 1673, 1162, 522, 584, 513, 73, 712, 650, + 1628, 156, 668, 1180, 220, 732, 36, 548, 672, 777, 32, 656, + 1233, 1113, 1602, 1665, 523, 586, 609, 1538, 728, 1112, 1289, 257, + 1280, 1234, 216, 610, 1091, 2121, 1026, 1224, 1608, 1600, 96, 536, + 713, 1104, 26, 1296, 1282, 2130, 1626, 218, 162, 1744, 1155, 2129, + 715, 1043, 1281, 147, 1171, 224, 99, 1169, 144, 1672, 132, 1100, + 2185, 596, 264, 768, 664, 1168, 1106, 154, 651, 64, 8, 585, + 594, 201, 90, 1097, 593, 11, 1089, 2048, 1098, 89, 3, 75, + 208, 91, 1090, 65, 576, 9, 137, 642, 658, 515, 20, 1736, + 1728, 1025, 194, 784, 722, 538, 34, 1099, 769, 2176, 1544, 608, + 1666, 1546, 217, 160, 2184, 544, 1027, 577, 521, 520, 1, 1032, + 145, 2049, 1680, 659, 273, 97, 2112, 16, 138, 1217, 580, 588, + 729, 4, 514, 81, 2, 592, 192, 1042, 531, 595, 2120, 1610, + 714, 1170, 139, 1737, 1034, 88, 578, 512, 18, 1536, 1033, 66, + 24, 200, 530, 84, 100, 612, 2080, 266, 1177, 209, 1601, 80, + 1160, 146, 600, 152, 1035, 776, 17, 82, 25, 1609, 153, 648, + 529, 1216, 1545, 27, 68, 272, 1552, 161, 1176, 1048, 1617, 641, + 210, 1114, 1553, 1616, 1040, 705, 2057, 706, 2128, 1674, 1226, 1554, + 1178, 1107, 10, 72, 136, 128, 1152, 1681, 539, 603, 155, 516, + 673, 532, 778, 1290, 1537, 12, 721, 256, 1041, 19, 1154, 2056, + 193, 1024, 1088, 0 +]; + +const VEC_CB4_BITS: [u16; 209] = [ + 0x0000, 0x0004, 0x000A, 0x0016, 0x002E, 0x0178, 0x0179, 0x00BD, + 0x05F0, 0x05F1, 0x05F2, 0x05F3, 0x05F4, 0x05F5, 0x05F6, 0x05F7, + 0x05F8, 0x05F9, 0x05FA, 0x05FB, 0x05FC, 0x05FD, 0x05FE, 0x05FF, + 0x0018, 0x0019, 0x000D, 0x001C, 0x001D, 0x000F, 0x0001, 0x0002, + 0x0018, 0x0064, 0x0328, 0x0CA4, 0x0CA5, 0x0CA6, 0x0CA7, 0x0CA8, + 0x0CA9, 0x0655, 0x032B, 0x00CB, 0x0066, 0x0067, 0x000D, 0x000E, + 0x000F, 0x0001, 0x0010, 0x0440, 0x1104, 0x220A, 0x220B, 0x0883, + 0x0221, 0x0111, 0x0089, 0x0045, 0x0118, 0x0119, 0x0468, 0x08D2, + 0x08D3, 0x08D4, 0x08D5, 0x046B, 0x011B, 0x008E, 0x023C, 0x047A, + 0x08F6, 0x23DC, 0x23DD, 0x23DE, 0x23DF, 0x011F, 0x0009, 0x000A, + 0x0058, 0x02C8, 0x0592, 0x164C, 0x164D, 0x164E, 0x164F, 0x0B28, + 0x0B29, 0x0595, 0x0596, 0x0597, 0x02CC, 0x059A, 0x0B36, 0x0B37, + 0x0B38, 0x2CE4, 0x59CA, 0x59CB, 0x1673, 0x059D, 0x02CF, 0x00B4, + 0x00B5, 0x005B, 0x0017, 0x0018, 0x0019, 0x001A, 0x0036, 0x01B8, + 0x06E4, 0x1B94, 0x1B95, 0x0DCB, 0x0373, 0x06E8, 0x06E9, 0x0375, + 0x01BB, 0x006F, 0x001C, 0x0074, 0x00EA, 0x01D6, 0x0EB8, 0x1D72, + 0x75CC, 0x75CD, 0x75CE, 0x75CF, 0x75D0, 0x75D1, 0x75D2, 0x75D3, + 0x75D4, 0x75D5, 0x75D6, 0x75D7, 0x75D8, 0x75D9, 0x75DA, 0x75DB, + 0x75DC, 0x75DD, 0x75DE, 0x75DF, 0x75E0, 0x75E1, 0x75E2, 0x75E3, + 0x75E4, 0x75E5, 0x75E6, 0x75E7, 0x75E8, 0x75E9, 0x75EA, 0x75EB, + 0x75EC, 0x75ED, 0x75EE, 0x75EF, 0x75F0, 0x75F1, 0x75F2, 0x75F3, + 0x75F4, 0x75F5, 0x75F6, 0x75F7, 0x75F8, 0x75F9, 0x75FA, 0x75FB, + 0x75FC, 0x75FD, 0x75FE, 0x75FF, 0x00EC, 0x01DA, 0x76C0, 0x76C1, + 0x76C2, 0x76C3, 0x76C4, 0x76C5, 0x76C6, 0x76C7, 0x76C8, 0x76C9, + 0x76CA, 0x76CB, 0x76CC, 0x76CD, 0x76CE, 0x76CF, 0x76D0, 0x76D1, + 0x76D2, 0x76D3, 0x76D4, 0x76D5, 0x3B6B, 0x0EDB, 0x03B7, 0x0077, 0x000F +]; +const VEC_CB4_LENS: [u8; 209] = [ + 5, 7, 8, 9, 10, 13, 13, 12, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 9, 9, 8, 9, 9, 8, 4, 4, + 7, 9, 12, 14, 14, 14, 14, 14, 14, 13, 12, 10, 9, 9, 6, 6, + 6, 2, 5, 11, 13, 14, 14, 12, 10, 9, 8, 7, 9, 9, 11, 12, + 12, 12, 12, 11, 9, 8, 10, 11, 12, 14, 14, 14, 14, 9, 4, 4, + 7, 10, 11, 13, 13, 13, 13, 12, 12, 11, 11, 11, 10, 11, 12, 12, + 12, 14, 15, 15, 13, 11, 10, 8, 8, 7, 5, 5, 5, 5, 6, 9, + 11, 13, 13, 12, 10, 11, 11, 10, 9, 7, 5, 7, 8, 9, 12, 13, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 8, 9, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 12, 10, 7, 4 +]; +const VEC_CB4_SYMS: [u16; 209] = [ + 80, 128, 96, 132, 160, 134, 92, 23, 180, 228, 232, 214, + 225, 166, 54, 138, 121, 131, 147, 99, 141, 75, 27, 91, + 37, 66, 24, 129, 145, 36, 1, 64, 6, 73, 34, 57, + 49, 42, 106, 14, 56, 130, 98, 7, 33, 97, 69, 81, + 85, 0, 20, 12, 76, 11, 44, 212, 40, 70, 22, 144, + 86, 149, 165, 196, 102, 137, 146, 52, 72, 148, 192, 28, + 19, 120, 30, 224, 169, 82, 4, 16, 8, 208, 48, 93, + 168, 193, 53, 152, 67, 161, 112, 29, 41, 74, 77, 150, + 71, 87, 114, 178, 213, 116, 164, 18, 101, 32, 65, 21, + 84, 17, 2, 3, 153, 113, 83, 117, 105, 38, 90, 13, + 10, 100, 68, 9, 89, 133, 197, 209, 181, 61, 245, 198, + 205, 125, 156, 220, 233, 172, 216, 230, 109, 118, 182, 217, + 176, 173, 202, 204, 108, 154, 218, 184, 185, 170, 58, 122, + 124, 78, 142, 201, 94, 158, 46, 110, 157, 200, 240, 195, + 244, 60, 210, 211, 35, 241, 163, 51, 115, 221, 229, 135, + 88, 26, 199, 177, 45, 151, 215, 39, 103, 167, 55, 119, + 140, 162, 139, 226, 50, 155, 43, 107, 15, 79, 31, 95, + 194, 136, 104, 25, 5 +]; + +const VEC_CB5_BITS: [u16; 192] = [ + 0x0000, 0x0004, 0x0005, 0x0060, 0x0184, 0x030A, 0x0616, 0x0617, + 0x030C, 0x061A, 0x061B, 0x0187, 0x0031, 0x0019, 0x001A, 0x001B, + 0x000E, 0x003C, 0x003D, 0x003E, 0x007E, 0x01FC, 0x03FA, 0x1FD8, + 0x1FD9, 0x0FED, 0x0FEE, 0x0FEF, 0x00FF, 0x0010, 0x0044, 0x008A, + 0x008B, 0x0023, 0x0009, 0x000A, 0x000B, 0x0060, 0x1840, 0x1841, + 0x1842, 0x1843, 0x0C22, 0x0C23, 0x0612, 0x184C, 0x309A, 0x309B, + 0x0C27, 0x030A, 0x0616, 0x0617, 0x0186, 0x1870, 0x1871, 0x0C39, + 0x0C3A, 0x0C3B, 0x061E, 0x0C3E, 0x0C3F, 0x0031, 0x0019, 0x001A, + 0x0036, 0x00DC, 0x0DD0, 0x0DD1, 0x06E9, 0x0375, 0x01BB, 0x01BC, + 0x0DE8, 0x37A4, 0x6F4A, 0x6F4B, 0x1BD3, 0x06F5, 0x06F6, 0x1BDC, + 0x1BDD, 0x0DEF, 0x0DF0, 0x0DF1, 0x6F90, 0x6F91, 0x6F92, 0x6F93, + 0x6F94, 0x6F95, 0x6F96, 0x6F97, 0x6F98, 0x6F99, 0x6F9A, 0x6F9B, + 0x6F9C, 0x6F9D, 0x6F9E, 0x6F9F, 0x6FA0, 0x6FA1, 0x6FA2, 0x6FA3, + 0x6FA4, 0x6FA5, 0x6FA6, 0x6FA7, 0x6FA8, 0x6FA9, 0x6FAA, 0x6FAB, + 0x6FAC, 0x6FAD, 0x6FAE, 0x6FAF, 0x6FB0, 0x6FB1, 0x6FB2, 0x6FB3, + 0x6FB4, 0x6FB5, 0x6FB6, 0x6FB7, 0x6FB8, 0x6FB9, 0x6FBA, 0x6FBB, + 0x6FBC, 0x6FBD, 0x6FBE, 0x6FBF, 0x6FC0, 0x6FC1, 0x6FC2, 0x6FC3, + 0x6FC4, 0x6FC5, 0x6FC6, 0x6FC7, 0x6FC8, 0x6FC9, 0x6FCA, 0x6FCB, + 0x6FCC, 0x6FCD, 0x6FCE, 0x6FCF, 0x6FD0, 0x6FD1, 0x6FD2, 0x6FD3, + 0x6FD4, 0x6FD5, 0x6FD6, 0x6FD7, 0x6FD8, 0x6FD9, 0x6FDA, 0x6FDB, + 0x6FDC, 0x6FDD, 0x37EF, 0x0DFC, 0x0DFD, 0x0DFE, 0x37FC, 0x37FD, + 0x37FE, 0x37FF, 0x001C, 0x003A, 0x0076, 0x0077, 0x00F0, 0x00F1, + 0x03C8, 0x0792, 0x1E4C, 0x1E4D, 0x1E4E, 0x1E4F, 0x1E50, 0x1E51, + 0x1E52, 0x1E53, 0x0F2A, 0x0F2B, 0x03CB, 0x00F3, 0x003D, 0x001F +]; +const VEC_CB5_LENS: [u8; 192] = [ + 2, 4, 4, 8, 10, 11, 12, 12, 11, 12, 12, 10, 7, 6, 6, 6, + 5, 7, 7, 7, 8, 10, 11, 14, 14, 13, 13, 13, 9, 5, 7, 8, + 8, 6, 4, 4, 4, 7, 13, 13, 13, 13, 12, 12, 11, 13, 14, 14, + 12, 10, 11, 11, 9, 13, 13, 12, 12, 12, 11, 12, 12, 6, 5, 5, + 6, 8, 12, 12, 11, 10, 9, 9, 12, 14, 15, 15, 13, 11, 11, 13, + 13, 12, 12, 12, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 14, 12, 12, 12, 14, 14, 14, 14, 5, 6, 7, 7, 8, 8, + 10, 11, 13, 13, 13, 13, 13, 13, 13, 13, 12, 12, 10, 8, 6, 5 +]; +const VEC_CB5_SYMS: [u16; 192] = [ + 0, 1, 256, 277, 24, 25, 262, 88, 100, 132, 70, 384, + 81, 17, 272, 68, 5, 321, 69, 276, 337, 144, 72, 10, + 389, 289, 532, 517, 32, 320, 324, 325, 2, 260, 4, 64, + 16, 273, 352, 265, 264, 329, 97, 148, 66, 86, 533, 149, + 37, 36, 400, 22, 128, 280, 326, 516, 101, 292, 528, 577, + 592, 21, 20, 80, 336, 512, 133, 580, 33, 96, 576, 9, + 274, 593, 597, 581, 356, 513, 288, 338, 278, 328, 388, 73, + 405, 661, 344, 660, 549, 152, 417, 613, 165, 421, 392, 296, + 521, 645, 641, 585, 137, 393, 608, 416, 537, 656, 609, 601, + 153, 409, 420, 297, 105, 361, 360, 408, 514, 164, 40, 578, + 130, 386, 548, 544, 530, 584, 545, 594, 146, 402, 600, 290, + 98, 354, 644, 136, 518, 657, 520, 582, 134, 390, 104, 536, + 534, 161, 342, 598, 150, 406, 38, 294, 102, 358, 612, 266, + 74, 330, 26, 282, 90, 346, 41, 293, 322, 82, 34, 640, + 401, 160, 257, 84, 340, 85, 341, 6, 258, 129, 353, 529, + 404, 357, 281, 89, 345, 596, 385, 145, 18, 8, 261, 65 +]; + +const VEC_CB6_BITS: [u16; 32] = [ + 0x0000, 0x0004, 0x0005, 0x0003, 0x0001, 0x0002, 0x0003, 0x0001, + 0x0002, 0x0003, 0x0004, 0x0005, 0x0018, 0x00C8, 0x0192, 0x0326, + 0x0327, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x01A8, 0x01A9, + 0x00D5, 0x006B, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, 0x0001 +]; +const VEC_CB6_LENS: [u8; 32] = [ + 7, 9, 9, 8, 6, 6, 6, 4, 4, 4, 4, 4, 6, 9, 10, 11, + 11, 8, 8, 8, 8, 8, 10, 10, 9, 8, 6, 6, 6, 6, 6, 1 +]; +const VEC_CB6_SYMS: [u16; 32] = [ + 9, 19, 22, 7, 3, 24, 6, 1, 16, 2, 8, 4, + 12, 21, 27, 29, 31, 28, 14, 13, 11, 26, 30, 23, + 15, 25, 5, 10, 20, 17, 18, 0 +]; + +const QUANT_LEVELS: [[f32; 14]; 7] = [ + [ 0.0, 0.392, 0.761, 1.120, 1.477, 1.832, 2.183, 2.541, 2.893, 3.245, 3.598, 3.942, 4.288, 4.724 ], + [ 0.0, 0.544, 1.060, 1.563, 2.068, 2.571, 3.072, 3.562, 4.070, 4.620, 0.0, 0.0, 0.0, 0.0 ], + [ 0.0, 0.746, 1.464, 2.180, 2.882, 3.584, 4.316, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ], + [ 0.0, 1.006, 2.000, 2.993, 3.985, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ], + [ 0.0, 1.321, 2.703, 3.983, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ], + [ 0.0, 1.657, 3.491, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ], + [ 0.0, 1.964, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ] +]; + +const CAT5_NOISE_FACTOR: [f32; REGION_SIZE + 1] = [ + 0.70711, 0.6179, 0.5005, 0.3220, 0.17678, 0.17678, 0.17678, 0.17678, 0.17678, 0.17678, + 0.17678, 0.17678, 0.17678, 0.17678, 0.17678, 0.17678, 0.17678, 0.17678, 0.17678, 0.17678, 0.0 +]; +const CAT6_NOISE_FACTOR: [f32; REGION_SIZE + 1] = [ + 0.70711, 0.5686, 0.3563, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.0 +]; diff --git a/nihav-vivo/src/codecs/vivo.rs b/nihav-vivo/src/codecs/vivo.rs new file mode 100644 index 0000000..807814d --- /dev/null +++ b/nihav-vivo/src/codecs/vivo.rs @@ -0,0 +1,513 @@ +use nihav_core::io::bitreader::*; +use nihav_core::io::codebook::*; +use nihav_core::formats; +use nihav_core::frame::*; +use nihav_core::codecs::*; +use nihav_codec_support::codecs::{MV, ZIGZAG}; +use nihav_codec_support::codecs::h263::*; +use nihav_codec_support::codecs::h263::code::H263BlockDSP; +use nihav_codec_support::codecs::h263::decoder::*; +use nihav_codec_support::codecs::h263::data::*; + +#[allow(dead_code)] +struct Tables { + intra_mcbpc_cb: Codebook, + inter_mcbpc_cb: Codebook, + cbpy_cb: Codebook, + rl_cb: Codebook, + aic_rl_cb: Codebook, + mv_cb: Codebook, +} + +struct VivoDecoder { + info: NACodecInfoRef, + dec: H263BaseDecoder, + tables: Tables, + bdsp: H263BlockDSP, + lastframe: Option, + lastpts: Option, + width: usize, + height: usize, +} + +struct VivoBR<'a> { + br: BitReader<'a>, + tables: &'a Tables, + gob_no: usize, + mb_w: usize, + is_pb: bool, + is_ipb: bool, + ref_w: usize, + ref_h: usize, + aic: bool, +} + +fn check_marker<'a>(br: &mut BitReader<'a>) -> DecoderResult<()> { + let mark = br.read(1)?; + validate!(mark == 1); + Ok(()) +} + +impl<'a> VivoBR<'a> { + fn new(src: &'a [u8], tables: &'a Tables, ref_w: usize, ref_h: usize) -> Self { + VivoBR { + br: BitReader::new(src, BitReaderMode::BE), + tables, + gob_no: 0, + mb_w: 0, + is_pb: false, + is_ipb: false, + ref_w, ref_h, + aic: false, + } + } + + fn decode_block(&mut self, quant: u8, intra: bool, coded: bool, blk: &mut [i16; 64], plane_no: usize, acpred: ACPredMode) -> DecoderResult<()> { + let br = &mut self.br; + let mut idx = 0; + if !self.aic && intra { + let mut dc = br.read(8)? as i16; + if dc == 255 { dc = 128; } + blk[0] = dc << 3; + idx = 1; + } + if !coded { return Ok(()); } + let scan = match acpred { + ACPredMode::Hor => H263_SCAN_V, + ACPredMode::Ver => H263_SCAN_H, + _ => &ZIGZAG, + }; + + let rl_cb = if self.aic && intra { &self.tables.aic_rl_cb } else { &self.tables.rl_cb }; + let q = if plane_no == 0 { (quant * 2) as i16 } else { (H263_CHROMA_QUANT[quant as usize] * 2) as i16 }; + let q_add = if q == 0 || self.aic { 0i16 } else { (((q >> 1) - 1) | 1) as i16 }; + while idx < 64 { + let code = br.read_cb(rl_cb)?; + let run; + let mut level; + let last; + if !code.is_escape() { + run = code.get_run(); + level = code.get_level(); + last = code.is_last(); + if br.read_bool()? { level = -level; } + if level >= 0 { + level = (level * q) + q_add; + } else { + level = (level * q) - q_add; + } + } else { + last = br.read_bool()?; + run = br.read(6)? as u8; + level = br.read_s(8)? as i16; + if level == -128 { + let low = br.read(5)? as i16; + let top = br.read_s(6)? as i16; + level = (top << 5) | low; + } + if level >= 0 { + level = (level * q) + q_add; + } else { + level = (level * q) - q_add; + } + if level < -2048 { level = -2048; } + if level > 2047 { level = 2047; } + } + idx += run; + validate!(idx < 64); + let oidx = scan[idx as usize]; + blk[oidx] = level; + idx += 1; + if last { break; } + } + Ok(()) + } +} + +fn decode_mv_component(br: &mut BitReader, mv_cb: &Codebook) -> DecoderResult { + let code = i16::from(br.read_cb(mv_cb)?); + if code == 0 { return Ok(0) } + if !br.read_bool()? { + Ok(code) + } else { + Ok(-code) + } +} + +fn decode_mv(br: &mut BitReader, mv_cb: &Codebook) -> DecoderResult { + let xval = decode_mv_component(br, mv_cb)?; + let yval = decode_mv_component(br, mv_cb)?; + Ok(MV::new(xval, yval)) +} + +fn decode_b_info(br: &mut BitReader, is_pb: bool, is_ipb: bool, is_intra: bool) -> DecoderResult { + if is_pb { // as improved pb + if is_ipb { + let pb_mv_add = if is_intra { 1 } else { 0 }; + if br.read_bool()?{ + if br.read_bool()? { + let pb_mv_count = 1 - (br.read(1)? as usize); + let cbpb = br.read(6)? as u8; + Ok(BBlockInfo::new(true, cbpb, pb_mv_count + pb_mv_add, pb_mv_count == 1)) + } else { + Ok(BBlockInfo::new(true, 0, 1 + pb_mv_add, true)) + } + } else { + Ok(BBlockInfo::new(true, 0, pb_mv_add, false)) + } + } else { + let mvdb = br.read_bool()?; + let cbpb = if mvdb && br.read_bool()? { br.read(6)? as u8 } else { 0 }; + Ok(BBlockInfo::new(true, cbpb, if mvdb { 1 } else { 0 }, false)) + } + } else { + Ok(BBlockInfo::new(false, 0, 0, false)) + } +} + +impl<'a> BlockDecoder for VivoBR<'a> { + +#[allow(unused_variables)] + fn decode_pichdr(&mut self) -> DecoderResult { + let br = &mut self.br; + let syncw = br.read(22)?; + validate!(syncw == 0x000020); + let tr = (br.read(8)? << 8) as u16; + check_marker(br)?; + let id = br.read(1)?; + validate!(id == 0); + br.read(1)?; // split screen indicator + br.read(1)?; // document camera indicator + br.read(1)?; // freeze picture release + let mut sfmt = br.read(3)?; + validate!(sfmt != 0b000); + let is_intra = !br.read_bool()?; + let umv = br.read_bool()?; + br.read(1)?; // syntax arithmetic coding + let apm = br.read_bool()?; + self.is_pb = br.read_bool()?; + let deblock; + let pbplus; + let aic; + if sfmt == 0b110 { + sfmt = br.read(3)?; + validate!(sfmt != 0b000 && sfmt != 0b110); + aic = br.read_bool()?; + br.read(1)?; // umv mode + deblock = br.read_bool()?; + br.read(3)?; // unknown flags + pbplus = br.read_bool()?; + br.read(4)?; // unknown flags + } else { + aic = false; + deblock = false; + pbplus = false; + } + self.is_ipb = pbplus; + let (w, h) = match sfmt { + 0b001 => ( 64, 48), + 0b011 => ( 88, 72), + 0b010 => (176, 144), + 0b100 => (352, 288), + 0b101 => (704, 576), + 0b111 => { + validate!((self.ref_w != 0) && (self.ref_h != 0)); + ((self.ref_w + 15) & !15, (self.ref_h + 15) & !15) + }, + _ => return Err(DecoderError::InvalidData), + }; + let quant = br.read(5)?; + let cpm = br.read_bool()?; + validate!(!cpm); + + let pbinfo; + if self.is_pb { + let trb = br.read(3)?; + let dbquant = br.read(2)?; + pbinfo = Some(PBInfo::new(trb as u8, dbquant as u8, pbplus)); + } else { + pbinfo = None; + } + while br.read_bool()? { // skip PEI + br.read(8)?; + } + self.gob_no = 0; + self.mb_w = (w + 15) >> 4; + self.aic = aic; + + let ftype = if is_intra { Type::I } else { Type::P }; + let plusinfo = Some(PlusInfo::new(aic, deblock, false, false)); + let mvmode = if umv { MVMode::UMV } else { MVMode::Old }; + let picinfo = PicInfo::new(w, h, ftype, mvmode, umv, apm, quant as u8, tr, pbinfo, plusinfo); + Ok(picinfo) + } + + #[allow(unused_variables)] + fn decode_slice_header(&mut self, info: &PicInfo) -> DecoderResult { + let br = &mut self.br; + let gbsc = br.read(17)?; + validate!(gbsc == 1); + let gn = br.read(5)?; + let gfid = br.read(2)?; + let gquant = br.read(5)?; + let ret = SliceInfo::new_gob(0, self.gob_no, gquant as u8); + self.gob_no += 1; + Ok(ret) + } + + #[allow(unused_variables)] + fn decode_block_header(&mut self, info: &PicInfo, slice: &SliceInfo, sstate: &SliceState) -> DecoderResult { + let br = &mut self.br; + let mut q = slice.get_quant(); + match info.get_mode() { + Type::I => { + let mut cbpc = br.read_cb(&self.tables.intra_mcbpc_cb)?; + while cbpc == 8 { cbpc = br.read_cb(&self.tables.intra_mcbpc_cb)?; } + let mut acpred = ACPredMode::None; + if let Some(ref pi) = info.plusinfo { + if pi.aic { + let acpp = br.read_bool()?; + acpred = ACPredMode::DC; + if acpp { + acpred = if !br.read_bool()? { ACPredMode::Hor } else { ACPredMode::Ver }; + } + } + } + let cbpy = br.read_cb(&self.tables.cbpy_cb)?; + let cbp = (cbpy << 2) | (cbpc & 3); + let dquant = (cbpc & 4) != 0; + if dquant { + let idx = br.read(2)? as usize; + q = (i16::from(q) + i16::from(H263_DQUANT_TAB[idx])) as u8; + } + let mut binfo = BlockInfo::new(Type::I, cbp, q); + binfo.set_acpred(acpred); + Ok(binfo) + }, + Type::P => { + if br.read_bool()? { return Ok(BlockInfo::new(Type::Skip, 0, info.get_quant())); } + let mut cbpc = br.read_cb(&self.tables.inter_mcbpc_cb)?; + while cbpc == 20 { cbpc = br.read_cb(&self.tables.inter_mcbpc_cb)?; } + let is_intra = (cbpc & 0x04) != 0; + let dquant = (cbpc & 0x08) != 0; + let is_4x4 = (cbpc & 0x10) != 0; + if is_intra { + let mut acpred = ACPredMode::None; + if let Some(ref pi) = info.plusinfo { + if pi.aic { + let acpp = br.read_bool()?; + acpred = ACPredMode::DC; + if acpp { + acpred = if !br.read_bool()? { ACPredMode::Hor } else { ACPredMode::Ver }; + } + } + } + let mut mvec: Vec = Vec::new(); + let bbinfo = decode_b_info(br, self.is_pb, self.is_ipb, true)?; + let cbpy = br.read_cb(&self.tables.cbpy_cb)?; + let cbp = (cbpy << 2) | (cbpc & 3); + if dquant { + let idx = br.read(2)? as usize; + q = (i16::from(q) + i16::from(H263_DQUANT_TAB[idx])) as u8; + } + let mut binfo = BlockInfo::new(Type::I, cbp, q); + binfo.set_bpart(bbinfo); + binfo.set_acpred(acpred); + if self.is_pb { + for _ in 0..bbinfo.get_num_mv() { + mvec.push(decode_mv(br, &self.tables.mv_cb)?); + } + binfo.set_b_mv(mvec.as_slice()); + } + return Ok(binfo); + } + + let bbinfo = decode_b_info(br, self.is_pb, self.is_ipb, false)?; + let mut cbpy = br.read_cb(&self.tables.cbpy_cb)?; +// if /* !aiv && */(cbpc & 3) != 3 { + cbpy ^= 0xF; +// } + let cbp = (cbpy << 2) | (cbpc & 3); + if dquant { + let idx = br.read(2)? as usize; + q = (i16::from(q) + i16::from(H263_DQUANT_TAB[idx])) as u8; + } + let mut binfo = BlockInfo::new(Type::P, cbp, q); + binfo.set_bpart(bbinfo); + if !is_4x4 { + let mvec: [MV; 1] = [decode_mv(br, &self.tables.mv_cb)?]; + binfo.set_mv(&mvec); + } else { + let mvec: [MV; 4] = [ + decode_mv(br, &self.tables.mv_cb)?, + decode_mv(br, &self.tables.mv_cb)?, + decode_mv(br, &self.tables.mv_cb)?, + decode_mv(br, &self.tables.mv_cb)? + ]; + binfo.set_mv(&mvec); + } + if self.is_pb { + let mut mvec: Vec = Vec::with_capacity(bbinfo.get_num_mv()); + for _ in 0..bbinfo.get_num_mv() { + let mv = decode_mv(br, &self.tables.mv_cb)?; + mvec.push(mv); + } + binfo.set_b_mv(mvec.as_slice()); + } + Ok(binfo) + }, + _ => Err(DecoderError::InvalidData), + } + } + + #[allow(unused_variables)] + fn decode_block_intra(&mut self, info: &BlockInfo, _sstate: &SliceState, quant: u8, no: usize, coded: bool, blk: &mut [i16; 64]) -> DecoderResult<()> { + self.decode_block(quant, true, coded, blk, if no < 4 { 0 } else { no - 3 }, info.get_acpred()) + } + + #[allow(unused_variables)] + fn decode_block_inter(&mut self, info: &BlockInfo, _sstate: &SliceState, quant: u8, no: usize, coded: bool, blk: &mut [i16; 64]) -> DecoderResult<()> { + self.decode_block(quant, false, coded, blk, if no < 4 { 0 } else { no - 3 }, ACPredMode::None) + } + + fn is_slice_end(&mut self) -> bool { self.br.peek(16) == 0 } +} + +impl VivoDecoder { + fn new() -> Self { + let mut coderead = H263ShortCodeReader::new(H263_INTRA_MCBPC); + let intra_mcbpc_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap(); + let mut coderead = H263ShortCodeReader::new(H263_INTER_MCBPC); + let inter_mcbpc_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap(); + let mut coderead = H263ShortCodeReader::new(H263_CBPY); + let cbpy_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap(); + let mut coderead = H263RLCodeReader::new(H263_RL_CODES); + let rl_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap(); + let mut coderead = H263RLCodeReader::new(H263_RL_CODES_AIC); + let aic_rl_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap(); + let mut coderead = H263ShortCodeReader::new(H263_MV); + let mv_cb = Codebook::new(&mut coderead, CodebookMode::MSB).unwrap(); + let tables = Tables { + intra_mcbpc_cb, + inter_mcbpc_cb, + cbpy_cb, + rl_cb, + aic_rl_cb, + mv_cb, + }; + + VivoDecoder{ + info: NACodecInfo::new_dummy(), + dec: H263BaseDecoder::new(true), + tables, + bdsp: H263BlockDSP::new(), + lastframe: None, + lastpts: None, + width: 0, + height: 0, + } + } +} + +impl NADecoder for VivoDecoder { + fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> { + if let NACodecTypeInfo::Video(vinfo) = info.get_properties() { + let w = vinfo.get_width(); + let h = vinfo.get_height(); + let fmt = formats::YUV420_FORMAT; + let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(w, h, false, fmt)); + self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref(); + self.width = w; + self.height = h; + Ok(()) + } else { + Err(DecoderError::InvalidData) + } + } + fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult { + let src = pkt.get_buffer(); + + if src.len() == 0 { + let buftype; + let ftype; + if self.lastframe.is_none() { + buftype = NABufferType::None; + ftype = FrameType::Skip; + } else { + let mut buf = None; + std::mem::swap(&mut self.lastframe, &mut buf); + buftype = buf.unwrap(); + ftype = FrameType::B; + } + let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), buftype); + frm.set_keyframe(false); + frm.set_frame_type(ftype); + if self.lastpts.is_some() { + frm.set_pts(self.lastpts); + self.lastpts = None; + } + return Ok(frm.into_ref()); + } + let mut ibr = VivoBR::new(&src, &self.tables, self.width, self.height); + + let bufinfo = self.dec.parse_frame(&mut ibr, &self.bdsp)?; + + let mut cur_pts = pkt.get_pts(); + if !self.dec.is_intra() { + let bret = self.dec.get_bframe(&self.bdsp); + if let Ok(b_buf) = bret { + self.lastframe = Some(b_buf); + self.lastpts = pkt.get_pts(); + if let Some(pts) = pkt.get_pts() { + cur_pts = Some(pts + 1); + } + } + } + + let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo); + frm.set_keyframe(self.dec.is_intra()); + frm.set_frame_type(if self.dec.is_intra() { FrameType::I } else { FrameType::P }); + frm.set_pts(cur_pts); + Ok(frm.into_ref()) + } + fn flush(&mut self) { + self.dec.flush(); + } +} + + +pub fn get_decoder() -> Box { + Box::new(VivoDecoder::new()) +} + +#[cfg(test)] +mod test { + use nihav_core::codecs::RegisteredDecoders; + use nihav_core::demuxers::RegisteredDemuxers; + use nihav_codec_support::test::dec_video::*; + use crate::vivo_register_all_codecs; + use crate::vivo_register_all_demuxers; + #[test] + fn test_vivo1() { + let mut dmx_reg = RegisteredDemuxers::new(); + vivo_register_all_demuxers(&mut dmx_reg); + let mut dec_reg = RegisteredDecoders::new(); + vivo_register_all_codecs(&mut dec_reg); + +test_file_decoding("vivo", "assets/Misc/gr_al.viv", Some(16), true, false, Some("viv1"), &dmx_reg, &dec_reg); +// test_decoding("vivo", "vivo1", "assets/Misc/gr_al.viv", Some(16), +// &dmx_reg, &dec_reg, ExpectedTestResult::GenerateMD5Frames)); + } + #[test] + fn test_vivo2() { + let mut dmx_reg = RegisteredDemuxers::new(); + vivo_register_all_demuxers(&mut dmx_reg); + let mut dec_reg = RegisteredDecoders::new(); + vivo_register_all_codecs(&mut dec_reg); + +test_file_decoding("vivo", "assets/Misc/02-KimagureOrangeRoad.viv", Some(50), true, false, Some("viv2"), &dmx_reg, &dec_reg); +panic!("end"); +// test_decoding("vivo", "vivo2", "assets/Misc/greetings.viv", Some(16), +// &dmx_reg, &dec_reg, ExpectedTestResult::GenerateMD5Frames)); + } +} diff --git a/nihav-vivo/src/demuxers/mod.rs b/nihav-vivo/src/demuxers/mod.rs new file mode 100644 index 0000000..c76f106 --- /dev/null +++ b/nihav-vivo/src/demuxers/mod.rs @@ -0,0 +1,22 @@ +use nihav_core::demuxers::*; + + +#[allow(unused_macros)] +macro_rules! validate { + ($a:expr) => { if !$a { println!("check failed at {}:{}", file!(), line!()); return Err(DemuxerError::InvalidData); } }; +} + +#[cfg(feature="demuxer_vivo")] +mod vivo; + +const DEMUXERS: &[&DemuxerCreator] = &[ +#[cfg(feature="demuxer_vivo")] + &vivo::VivoDemuxerCreator {}, +]; + +/// Registers all available demuxers provided by this crate. +pub fn vivo_register_all_demuxers(rd: &mut RegisteredDemuxers) { + for demuxer in DEMUXERS.iter() { + rd.add_demuxer(*demuxer); + } +} diff --git a/nihav-vivo/src/demuxers/vivo.rs b/nihav-vivo/src/demuxers/vivo.rs new file mode 100644 index 0000000..06decd1 --- /dev/null +++ b/nihav-vivo/src/demuxers/vivo.rs @@ -0,0 +1,268 @@ +use nihav_core::demuxers::*; + +struct VivoDemuxer<'a> { + src: &'a mut ByteReader<'a>, + video_id: usize, + audio_id: usize, + video_buf: Vec, + vpts: u64, + apts: u64, + v_num: u32, + v_den: u32, + a_num: u32, + a_den: u32, + fps: f32, + width: usize, + height: usize, + vname: &'static str, + aname: &'static str, +} + +fn read_size(br: &mut ByteReader) -> DemuxerResult { + let mut ret = 0; + loop { + let c = br.read_byte()?; + ret = (ret << 7) | ((c & 0x7F) as usize); + if (c & 0x80) == 0 { + break; + } + } + Ok(ret) +} + +impl<'a> DemuxCore<'a> for VivoDemuxer<'a> { + fn open(&mut self, strmgr: &mut StreamManager, _seek_idx: &mut SeekIndex) -> DemuxerResult<()> { + let mut hdr_data: Vec = Vec::with_capacity(256); + loop { + let hdr = self.src.peek_byte()?; + if (hdr & 0xF0) != 0 { break; } + self.src.read_skip(1)?; + let hdr_len = read_size(&mut self.src)?; + hdr_data.resize(hdr_len, 0); + self.src.read_buf(&mut hdr_data)?; + self.parse_header_packet(&hdr_data)?; + } + + validate!(self.vname != "none"); + if self.width == 0 && self.height == 0 { + self.width = 160; + self.height = 120; + } + validate!(self.fps > 0.0 || (self.v_num > 0 && self.v_den > 0)); + + if self.v_num == 0 { + self.v_num = 1000; + self.v_den = (self.fps * 1000.0) as u32; + } + + let vhdr = NAVideoInfo::new(self.width, self.height, false, YUV420_FORMAT); + let vinfo = NACodecInfo::new(self.vname, NACodecTypeInfo::Video(vhdr), None); + let res = strmgr.add_stream(NAStream::new(StreamType::Video, 0, vinfo, self.v_num, self.v_den)); + validate!(res.is_some()); + self.video_id = res.unwrap(); + + if self.aname == "none" && self.vname == "vivo1" { + self.aname = "g723.1"; + self.a_num = 240; + self.a_den = 8000; + } + if self.aname != "none" { + let ahdr = NAAudioInfo::new(self.a_den, 1, SND_S16_FORMAT, self.a_num as usize); + let ainfo = NACodecInfo::new(self.aname, NACodecTypeInfo::Audio(ahdr), None); + let res = strmgr.add_stream(NAStream::new(StreamType::Audio, 1, ainfo, self.a_num, self.a_den)); + validate!(res.is_some()); + self.audio_id = res.unwrap(); + } + + Ok(()) + } + fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult { + let br = &mut self.src; + + loop { + let ret = br.read_byte(); + let hdr1 = match ret { + Err(ByteIOError::EOF) => return Err(DemuxerError::EOF), + Err(error) => return Err(error.into()), + Ok(val) => val, + }; + let force_size = hdr1 == 0x82; + let hdr = if force_size { br.read_byte()? } else { hdr1 }; + let (is_video, mut size) = match hdr >> 4 { + 1 => { (true, 128) }, + 2 => { validate!(!force_size); (true, read_size(br)?) }, + 3 => { (false, 40) }, + 4 => { (false, 24) }, + _ => return Err(DemuxerError::InvalidData), + }; + if force_size { + size = read_size(br)?; + } + if is_video { + validate!(self.v_den != 0); + let cur_size = self.video_buf.len(); + let new_size = cur_size + size; + self.video_buf.resize(new_size, 0); + br.read_buf(&mut self.video_buf[cur_size..])?; + if (hdr >> 4) == 2 { + let mut buf = Vec::new(); + std::mem::swap(&mut self.video_buf, &mut buf); + let strres = strmgr.get_stream(self.video_id); + validate!(strres.is_some()); + let stream = strres.unwrap(); + let ts = NATimeInfo::new(Some(self.vpts), None, None, self.v_num, self.v_den); + let pkt = NAPacket::new(stream, ts, self.vpts == 0, buf); + self.vpts += 1; + return Ok(pkt); + } + } else { + validate!(self.a_den != 0); + let mut buf: Vec = vec![0; size]; + br.read_buf(&mut buf)?; + let strres = strmgr.get_stream(self.audio_id); + validate!(strres.is_some()); + let stream = strres.unwrap(); + let ts = NATimeInfo::new(Some(self.apts), None, None, self.a_num, self.a_den); + let pkt = NAPacket::new(stream, ts, true, buf); + self.apts += 1; + return Ok(pkt); + } + } + } + fn seek(&mut self, _time: u64, _seek_idx: &SeekIndex) -> DemuxerResult<()> { + Err(DemuxerError::NotPossible) + } +} + +impl<'a> VivoDemuxer<'a> { + fn new(io: &'a mut ByteReader<'a>) -> Self { + VivoDemuxer { + src: io, + video_id: 0, + audio_id: 0, + video_buf: Vec::new(), + vpts: 0, + apts: 0, + v_num: 0, + v_den: 0, + a_num: 0, + a_den: 0, + width: 0, + height: 0, + fps: 0.0, + vname: "none", + aname: "none", + } + } + fn parse_header_packet(&mut self, pkt: &[u8]) -> DemuxerResult<()> { + for entry in pkt.split(|ch| *ch == 0xD) { + if entry.len() < 3 || !entry.contains(&b':') { continue; } + let entry = if entry.len() > 0 && entry[0] == 0xA { &entry[1..] } else { entry }; + let mut split = entry.split(|ch| *ch == b':'); + let name = split.next().unwrap(); + let value = split.next().unwrap(); + + let valstr = String::from_utf8_lossy(value); + match name { + b"Version" => { + match value { + b"Vivo/0.90" => { self.vname = "vivo1"; }, + b"Vivo/1.00" => { self.vname = "vivo1"; }, + b"Vivo/2.00" => { self.vname = "vivo2"; }, + _ => { + println!("Unknown codec name {}", valstr); + return Err(DemuxerError::InvalidData); + }, + }; + }, + b"FPS" => { + self.fps = if let Ok(val) = valstr.parse() { + val + } else { return Err(DemuxerError::InvalidData); }; + validate!(self.fps > 0.0 && self.fps < 1000.0); + }, + b"Width" => { + self.width = if let Ok(val) = valstr.parse() { + val + } else { return Err(DemuxerError::InvalidData); }; + validate!(self.width > 0 && self.width <= 1024); + }, + b"Height" => { + self.height = if let Ok(val) = valstr.parse() { + val + } else { return Err(DemuxerError::InvalidData); }; + validate!(self.height > 0 && self.height <= 768); + }, + b"SamplingFrequency" => { + let samp_freq: u32 = if let Ok(val) = valstr.parse() { + val + } else { return Err(DemuxerError::InvalidData); }; + validate!(samp_freq == 8000 || samp_freq == 16000); + if samp_freq == 8000 { + self.aname = "g723.1"; + self.a_num = 240; + self.a_den = 8000; + } else if samp_freq == 16000 { + self.aname = "siren"; + self.a_num = 320; + self.a_den = 16000; + } else { + return Err(DemuxerError::InvalidData); + }; + }, +/* b"TimeUnitNumerator" => { + self.v_num = if let Ok(val) = valstr.parse() { + val + } else { return Err(DemuxerError::InvalidData); }; + validate!(self.v_num > 0); + println!(" video codec tb_num {}", self.v_num); + }, + b"TimeUnitDenominator" => { + self.v_den = if let Ok(val) = valstr.parse() { + val + } else { return Err(DemuxerError::InvalidData); }; + validate!(self.v_den > 0); + println!(" video codec tb_den {}", self.v_den); + },*/ + _ => { }, + }; + } + Ok(()) + } +} + +pub struct VivoDemuxerCreator { } + +impl DemuxerCreator for VivoDemuxerCreator { + fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box + 'a> { + Box::new(VivoDemuxer::new(br)) + } + fn get_name(&self) -> &'static str { "vivo" } +} + +#[cfg(test)] +mod test { + use super::*; + use std::fs::File; + + #[test] + fn test_vivo_demux() { +// let mut file = File::open("assets/Misc/greetings.viv").unwrap(); + let mut file = File::open("assets/Misc/favmovie.viv").unwrap(); + let mut fr = FileReader::new_read(&mut file); + let mut br = ByteReader::new(&mut fr); + let mut dmx = VivoDemuxer::new(&mut br); + let mut sm = StreamManager::new(); + let mut si = SeekIndex::new(); + dmx.open(&mut sm, &mut si).unwrap(); + loop { + let pktres = dmx.get_frame(&mut sm); + if let Err(e) = pktres { + if (e as i32) == (DemuxerError::EOF as i32) { break; } + panic!("error {:?}", e); + } + let pkt = pktres.unwrap(); + println!("Got {}", pkt); + } + } +} diff --git a/nihav-vivo/src/lib.rs b/nihav-vivo/src/lib.rs new file mode 100644 index 0000000..74bdb98 --- /dev/null +++ b/nihav-vivo/src/lib.rs @@ -0,0 +1,8 @@ +extern crate nihav_core; +extern crate nihav_codec_support; + +mod codecs; +mod demuxers; + +pub use crate::codecs::vivo_register_all_codecs; +pub use crate::demuxers::vivo_register_all_demuxers; -- 2.39.5