--- /dev/null
+use nihav_core::codecs::*;
+use nihav_core::io::bitreader::*;
+use nihav_core::io::codebook::*;
+
+use super::SAMPLES;
+use super::mp3data::*;
+
+const MP3_MAX_BANDS: usize = MP3_BANDS_SHORT * 3 + 4;
+const IS_MODE: u8 = 1;
+const MS_MODE: u8 = 2;
+
+#[derive(Clone,Copy)]
+struct Granule {
+ part2_3_length: usize,
+ big_values: usize,
+ global_gain: u8,
+ scalefac_compress: usize,
+ blocksplit: bool,
+ block_type: u8,
+ switch_point: bool,
+ table_select: [u8; 3],
+ subblock_gain: [u8; 3],
+ region_address1: u8,
+ region_address2: u8,
+ preflag: bool,
+ scalefac_scale: bool,
+ count1table_select: bool,
+ scalefac: [u8; MP3_MAX_BANDS],
+ istereo: [u8; MP3_MAX_BANDS],
+
+ lastcoded: usize,
+ zero_part: usize,
+}
+
+impl Default for Granule {
+ fn default() -> Self { unsafe { std::mem::MaybeUninit::zeroed().assume_init() } }
+}
+
+impl Granule {
+ fn get_mpeg2_params(&self, bits: &mut [u8; 4], independent: bool) -> usize {
+ if independent {
+ match self.scalefac_compress {
+ 0..=399 => {
+ bits[0] = MP3_SCF_BITS5[(self.scalefac_compress >> 4) * 2];
+ bits[1] = MP3_SCF_BITS5[(self.scalefac_compress >> 4) * 2 + 1];
+ bits[2] = ((self.scalefac_compress >> 2) & 3) as u8;
+ bits[3] = (self.scalefac_compress & 3) as u8;
+ 0
+ },
+ 400..=499 => {
+ let idx = self.scalefac_compress - 400;
+ bits[0] = MP3_SCF_BITS5[(idx >> 2) * 2];
+ bits[1] = MP3_SCF_BITS5[(idx >> 2) * 2 + 1];
+ bits[2] = (idx & 3) as u8;
+ bits[3] = 0;
+ 1
+ },
+ _ => {
+ let idx = self.scalefac_compress - 500;
+ bits[0] = MP3_SCF_BITS3[idx * 2];
+ bits[1] = MP3_SCF_BITS3[idx * 2 + 1];
+ bits[2] = 0;
+ bits[3] = 0;
+ 2
+ },
+ }
+ } else {
+ bits[3] = 0;
+ let idx = self.scalefac_compress >> 1;
+ match idx {
+ 0..=179 => {
+ bits[0] = MP3_SCF_BITS6[idx * 3];
+ bits[1] = MP3_SCF_BITS6[idx * 3 + 1];
+ bits[2] = MP3_SCF_BITS6[idx * 3 + 2];
+ 3
+ },
+ 180..=243 => {
+ let val = (idx - 180) as u8;
+ bits[0] = val >> 4;
+ bits[1] = (val >> 2) & 3;
+ bits[2] = val & 3;
+ 4
+ },
+ _ => {
+ let idx = idx - 244;
+ bits[0] = MP3_SCF_BITS6[idx * 2];
+ bits[1] = MP3_SCF_BITS6[idx * 2 + 1];
+ bits[2] = 0;
+ 5
+ },
+ }
+ }
+ }
+}
+
+struct MDCTContext {
+ win36: [f32; 36],
+ win36f: [f32; 36],
+ win12: [f32; 12],
+ win12f: [f32; 12],
+ tmp: [f32; 36],
+}
+
+impl MDCTContext {
+ fn new() -> Self {
+ let mut win36 = [0.0; 36];
+ let mut win36f = [0.0; 36];
+ let mut win12 = [0.0; 12];
+ let mut win12f = [0.0; 12];
+
+ for i in 0..36 {
+ win36 [i] = ((i as f32 + 0.5) * std::f32::consts::PI / 36.0).sin();
+ win36f[i] = if (i & 1) == 0 { win36[i] } else { -win36[i] };
+ }
+ for i in 0..12 {
+ win12 [i] = ((i as f32 + 0.5) * std::f32::consts::PI / 12.0).sin();
+ win12f[i] = if (i & 1) == 0 { win12[i] } else { -win12[i] };
+ }
+
+ Self {
+ tmp: [0.0; 36],
+ win36, win36f, win12, win12f
+ }
+ }
+ fn mdct36(&mut self, src: &mut [f32], dst: &mut[f32], delay: &mut [f32], len: usize, block_type: u8) {
+ let mut flip = false;
+ for i in (0..len).step_by(18) {
+ let (win36, win12) = if flip { (&self.win36f, &self.win12f) } else { (&self.win36, &self.win12) };
+ dct36(&mut src[i..], &mut self.tmp);
+ match block_type {
+ 0 | 2 => {
+ for j in 0..9 {
+ dst[i + j] = delay[i + j] - self.tmp[8 - j] * win36[j];
+ delay[i + j] = self.tmp[j + 9] * win36[j + 18];
+ }
+ for j in 9..18 {
+ dst[i + j] = delay[i + j] + self.tmp[j - 9] * win36[j];
+ delay[i + j] = self.tmp[26 - j] * win36[j + 18];
+ }
+ },
+ 1 => {
+ for j in 0..9 {
+ dst[i + j] = delay[i + j] - self.tmp[8 - j] * win36[j];
+ }
+ for j in 9..18 {
+ dst[i + j] = delay[i + j] + self.tmp[j - 9] * win36[j];
+ }
+ delay[i..][..6].copy_from_slice(&self.tmp[9..][..6]);
+ if flip {
+ for j in (1..6).step_by(2) {
+ delay[i + j] = -delay[i + j];
+ }
+ }
+ for j in 6..9 {
+ delay[i + j] = self.tmp[j + 9] * win12[j];
+ }
+ for j in 9..12 {
+ delay[i + j] = self.tmp[26 - j] * win12[j];
+ }
+ for j in 12..18 {
+ delay[i + j] = 0.0;
+ }
+ },
+ _ => {
+ dst[i..][..6].copy_from_slice(&delay[i..][..6]);
+ for j in 6..9 {
+ dst[i + j] = delay[i + j] - self.tmp[8 - j] * win12[j - 6];
+ }
+ for j in 9..12 {
+ dst[i + j] = delay[i + j] + self.tmp[j - 9] * win12[j - 6];
+ }
+ if !flip {
+ for j in 12..18 {
+ dst[i + j] = delay[i + j] + self.tmp[j - 9];
+ }
+ } else {
+ for j in 12..18 {
+ dst[i + j] = delay[i + j] + if (j & 1) == 0 { self.tmp[j - 9] } else { -self.tmp[j - 9] };
+ }
+ }
+ for j in 0..9 {
+ delay[i + j] = self.tmp[j + 9] * win36[j + 18];
+ }
+ for j in 9..18 {
+ delay[i + j] = self.tmp[26 - j] * win36[j + 18];
+ }
+ },
+ };
+
+ flip = !flip;
+ }
+ }
+ fn mdct12(&mut self, src: &[f32], dst: &mut[f32], delay: &mut [f32], len: usize) {
+ let mut flip = false;
+ for i in (0..len).step_by(18) {
+ let window = if flip { &self.win12f } else { &self.win12 };
+ for j in 0..3 {
+ let tmp = &mut self.tmp[j * 12..];
+ dct12(&src[i + j * 6..], tmp);
+ for (el, &w) in tmp.iter_mut().zip(window.iter()) {
+ *el *= w;
+ }
+ }
+
+ for j in 0..6 {
+ dst[i + j] = delay[i + j];
+ delay[i + j] = self.tmp[j + 18] + self.tmp[j + 18 + 6];
+ }
+ for j in 6..12 {
+ dst[i + j] = delay[i + j] + self.tmp[j - 6];
+ delay[i + j] = self.tmp[j + 18 + 6];
+ }
+ for j in 12..18 {
+ dst[i + j] = delay[i + j] + self.tmp[j - 6] + self.tmp[j];
+ delay[i + j] = 0.0;
+ }
+
+ flip = !flip;
+ }
+ }
+}
+
+pub struct MP3Data {
+ cb: MP3Codebooks,
+ mdct: MDCTContext,
+ granule: [[Granule; 2]; 2],
+ scfsi: [[bool; 4]; 2],
+ pub main_data_end: usize,
+ is_mode: [i8; SAMPLES],
+ pub mpeg1: bool,
+ pub sf_idx: usize,
+
+ delay: [[f32; SAMPLES / 2]; 2],
+ tmp: [f32; SAMPLES / 2],
+}
+
+impl MP3Data {
+ pub fn new() -> Self {
+ Self {
+ cb: MP3Codebooks::new(),
+ mdct: MDCTContext::new(),
+ granule: [[Granule::default(); 2]; 2],
+ scfsi: [[false; 4]; 2],
+ main_data_end: 0,
+ is_mode: [0; SAMPLES],
+ mpeg1: false,
+ sf_idx: 0,
+
+ delay: [[0.0; SAMPLES / 2]; 2],
+ tmp: [0.0; SAMPLES / 2],
+ }
+ }
+ pub fn reset(&mut self) {
+ for dly in self.delay.iter_mut() {
+ for el in dly.iter_mut() {
+ *el = 0.0;
+ }
+ }
+ }
+ fn calc_scale(gr: &Granule, sb: usize, ssb: usize, sblk_gain: u8) -> i8 {
+ (i32::from(gr.global_gain) - 64 - 146
+ - 8 * i32::from(sblk_gain)
+ - if gr.scalefac_scale { 4 } else { 2 } * (i32::from(gr.scalefac[ssb])
+ + if gr.preflag { i32::from(MP3_PREEMP_SCALES[sb]) } else { 0 })
+ ).min(127).max(-124) as i8
+ }
+ fn read_mp3_coeffs(&mut self, br: &mut BitReader, end: usize, gr_no: usize, ch: usize, coeffs: &mut [f32]) -> DecoderResult<()> {
+ let mut scales = [0; SAMPLES / 2];
+ let gr = &mut self.granule[gr_no][ch];
+
+ // calculate scales first
+ if gr.block_type != 2 {
+ let mut off = 0;
+ let mut sb = 0;
+ while off < SAMPLES / 2 {
+ let end = MP3_SFB_LONG_OFFS[self.sf_idx][sb + 1];
+ let scale = Self::calc_scale(gr, sb, sb, 0);
+ for el in scales[off..end].iter_mut() {
+ *el = scale;
+ }
+
+ if ch == 1 {
+ let scf = gr.scalefac[sb.min(MP3_BANDS - 1)];
+ if scf != gr.istereo[sb] {
+ for el in self.is_mode[gr_no * SAMPLES/2..][off..end].iter_mut() {
+ *el = scf as i8;
+ }
+ }
+ }
+
+ sb += 1;
+ off = end;
+ }
+ } else {
+ let end_band = if self.mpeg1 { 8 } else { 6 };
+
+ let mut off = 0;
+ let mut sb = 0;
+ if gr.switch_point {
+ while sb < end_band {
+ let end = MP3_SFB_LONG_OFFS[self.sf_idx][sb + 1];
+ let scale = Self::calc_scale(gr, sb, sb, 0);
+ for el in scales[off..end].iter_mut() {
+ *el = scale;
+ }
+
+ if ch == 1 {
+ let scf = gr.scalefac[sb.min(MP3_BANDS - 1)];
+ if scf != gr.istereo[sb] {
+ for el in self.is_mode[gr_no * SAMPLES/2..][off..end].iter_mut() {
+ *el = scf as i8;
+ }
+ }
+ }
+ sb += 1;
+ off = end;
+ }
+ }
+ let mut ssb = if gr.switch_point { 8 } else { 0 };
+ let mut sb = if gr.switch_point { 3 } else { 0 };
+ while sb <= MP3_BANDS_SHORT {
+ let band_size = MP3_SFB_SHORT_SIZE[self.sf_idx][sb];
+ for win in 0..3 {
+ let scale = Self::calc_scale(gr, sb, ssb, gr.subblock_gain[win]);
+ for el in scales[off..][..band_size].iter_mut() {
+ *el = scale;
+ }
+
+ if ch == 1 {
+ if sb == MP3_BANDS_SHORT {
+ gr.scalefac[ssb] = gr.scalefac[ssb - 3];
+ gr.istereo[ssb] = gr.istereo[ssb - 3];
+ }
+ let scf = gr.scalefac[ssb];
+ if scf != gr.istereo[ssb] {
+ for el in self.is_mode[gr_no * SAMPLES/2 + off..][..band_size].iter_mut() {
+ *el = scf as i8;
+ }
+ }
+ }
+ off += band_size;
+ ssb += 1;
+ }
+ sb += 1;
+ }
+ }
+
+ // prepare for coefficients decoding
+ let region1_start = if gr.block_type != 2 {
+ MP3_SFB_LONG_OFFS[self.sf_idx][gr.region_address1 as usize + 1]
+ } else if gr.switch_point {
+ 36
+ } else {
+ MP3_SFB_SHORT_OFFS[self.sf_idx][3] * 3
+ }.min(gr.big_values);
+ let region2_start = MP3_SFB_LONG_OFFS[self.sf_idx][((gr.region_address1 + gr.region_address2 + 2) as usize).min(MP3_BANDS + 1)].min(gr.big_values);
+
+ for el in coeffs[..SAMPLES/2].iter_mut() {
+ *el = 0.0;
+ }
+
+ // read coefficients
+ gr.lastcoded = 0;
+ if let Some((cb, esc_bits)) = self.cb.get_cb(gr.table_select[0]) {
+ let lc = read_region(br, end, coeffs, &scales, 0, region1_start, cb, esc_bits)?;
+ gr.lastcoded = gr.lastcoded.max(lc);
+ }
+ if let Some((cb, esc_bits)) = self.cb.get_cb(gr.table_select[1]) {
+ let lc = read_region(br, end, coeffs, &scales, region1_start, region2_start, cb, esc_bits)?;
+ gr.lastcoded = gr.lastcoded.max(lc);
+ }
+ if let Some((cb, esc_bits)) = self.cb.get_cb(gr.table_select[2]) {
+ let lc = read_region(br, end, coeffs, &scales, region2_start, gr.big_values, cb, esc_bits)?;
+ gr.lastcoded = gr.lastcoded.max(lc);
+ }
+ let (lc, zp) = read_region_quad(br, end, coeffs, &scales, gr.big_values, if !gr.count1table_select { Some(&self.cb.quad_cb) } else { None })?;
+ gr.lastcoded = gr.lastcoded.max(lc);
+ gr.zero_part = if zp > 0 { zp } else { gr.lastcoded };
+
+ Ok(())
+ }
+ pub fn read_mp3_side_data(&mut self, br: &mut BitReader, channels: usize) -> DecoderResult<()> {
+ if self.mpeg1 {
+ self.main_data_end = br.read(9)? as usize;
+ let _private_bits = br.read(if channels == 1 { 5 } else { 3 })?;
+ for scfsis in self.scfsi[..channels].iter_mut() {
+ for scfsi in scfsis.iter_mut() {
+ *scfsi = br.read_bool()?;
+ }
+ }
+ } else {
+ self.main_data_end = br.read(8)? as usize;
+ let _private_bits = br.read(channels as u8)?;
+ }
+ let granules = if self.mpeg1 { 2 } else { 1 };
+ for grans in self.granule[..granules].iter_mut() {
+ for gr in grans[..channels].iter_mut() {
+ gr.part2_3_length = br.read(12)? as usize;
+ gr.big_values = (br.read(9)? as usize) * 2;
+ gr.global_gain = br.read(8)? as u8;
+ gr.scalefac_compress = br.read(if self.mpeg1 { 4 } else { 9 })? as usize;
+ gr.blocksplit = br.read_bool()?;
+ if gr.blocksplit {
+ gr.block_type = br.read(2)? as u8;
+ gr.switch_point = br.read_bool()?;
+ for tsel in gr.table_select[..2].iter_mut() {
+ *tsel = br.read(5)? as u8;
+ match *tsel {
+ 4 | 14 => return Err(DecoderError::InvalidData),
+ _ => {},
+ };
+ }
+ for gain in gr.subblock_gain.iter_mut() {
+ *gain = br.read(3)? as u8;
+ }
+ gr.region_address1 = 7;
+ gr.region_address2 = 13;
+ } else {
+ gr.block_type = 0;
+ gr.switch_point = false;
+ for tsel in gr.table_select.iter_mut() {
+ *tsel = br.read(5)? as u8;
+ match *tsel {
+ 4 | 14 => return Err(DecoderError::InvalidData),
+ _ => {},
+ };
+ }
+ gr.region_address1 = br.read(4)? as u8;
+ gr.region_address2 = br.read(3)? as u8;
+ }
+ if self.mpeg1 {
+ gr.preflag = br.read_bool()?;
+ } else {
+ gr.preflag = false;
+ }
+ gr.scalefac_scale = br.read_bool()?;
+ gr.count1table_select = br.read_bool()?
+ }
+ }
+ Ok(())
+ }
+ pub fn decode_mpeg1_layer3(&mut self, br: &mut BitReader, coeffs: &mut [[f32; SAMPLES]; 2], channels: usize) -> DecoderResult<()> {
+ let mut data_end = 0;
+ for gr_no in 0..2 {
+ for ch in 0..channels {
+ data_end += self.granule[gr_no][ch].part2_3_length;
+
+ if self.granule[gr_no][ch].block_type != 2 {
+ if gr_no != 0 {
+ self.granule[1][ch].scalefac = self.granule[0][ch].scalefac;
+ } else {
+ for scf in self.granule[gr_no][ch].scalefac.iter_mut() {
+ *scf = 0;
+ }
+ }
+
+ let gr = &mut self.granule[gr_no][ch];
+ let bits1 = MP3_SCALEFAC_BITS1[gr.scalefac_compress];
+ let bits2 = MP3_SCALEFAC_BITS2[gr.scalefac_compress];
+ for cb in 0..11 {
+ if !self.scfsi[ch][SCFSI_FROM_BAND[cb]] || (gr_no == 0) {
+ gr.scalefac[cb] = br.read(bits1)? as u8;
+ }
+ }
+ for cb in 11..MP3_BANDS {
+ if !self.scfsi[ch][SCFSI_FROM_BAND[cb]] || (gr_no == 0) {
+ gr.scalefac[cb] = br.read(bits2)? as u8;
+ }
+ }
+ for is in gr.istereo.iter_mut() {
+ *is = 7;
+ }
+ } else {
+ let gr = &mut self.granule[gr_no][ch];
+ let bits1 = MP3_SCALEFAC_BITS1[gr.scalefac_compress];
+ let bits2 = MP3_SCALEFAC_BITS2[gr.scalefac_compress];
+ let pivot = if gr.blocksplit && gr.switch_point { 17 } else { 18 };
+
+ for scf in gr.scalefac[..pivot].iter_mut() {
+ *scf = br.read(bits1)? as u8;
+ }
+ for scf in gr.scalefac[pivot..][..18].iter_mut() {
+ *scf = br.read(bits2)? as u8;
+ }
+ for is in gr.istereo.iter_mut() {
+ *is = 7;
+ }
+ }
+ self.read_mp3_coeffs(br, data_end, gr_no, ch, &mut coeffs[ch][gr_no * SAMPLES/2..])?;
+ validate!(br.tell() <= data_end);
+ br.seek(data_end as u32)?;
+ }
+ }
+ Ok(())
+ }
+ pub fn decode_mpeg2_layer3(&mut self, br: &mut BitReader, coeffs: &mut [[f32; SAMPLES]; 2], channels: usize, mode_ext: u8) -> DecoderResult<()> {
+ let mut data_end = 0;
+ for ch in 0..channels {
+ let gr = &mut self.granule[0][ch];
+ data_end += gr.part2_3_length;
+
+ let mut bits = [0; 4];
+ let idx = gr.get_mpeg2_params(&mut bits, (ch == 0) || ((mode_ext & IS_MODE) == 0));
+ let idx2 = if gr.block_type != 2 { 0 } else if !gr.switch_point { 1 } else { 2 };
+
+ gr.preflag = idx == 2;
+ let ends = &MP3_SCF_ENDS[idx][idx2];
+
+ for (scf, is) in gr.scalefac[0..ends[0]].iter_mut().zip(gr.istereo[0..ends[0]].iter_mut()) {
+ *scf = br.read(bits[0])? as u8;
+ *is = (1 << bits[0]) - 1;
+ }
+ for (scf, is) in gr.scalefac[ends[0]..ends[1]].iter_mut().zip(gr.istereo[ends[0]..ends[1]].iter_mut()) {
+ *scf = br.read(bits[1])? as u8;
+ *is = (1 << bits[1]) - 1;
+ }
+ for (scf, is) in gr.scalefac[ends[1]..ends[2]].iter_mut().zip(gr.istereo[ends[1]..ends[2]].iter_mut()) {
+ *scf = br.read(bits[2])? as u8;
+ *is = (1 << bits[2]) - 1;
+ }
+ for (scf, is) in gr.scalefac[ends[2]..ends[3]].iter_mut().zip(gr.istereo[ends[2]..ends[3]].iter_mut()) {
+ *scf = br.read(bits[3])? as u8;
+ *is = (1 << bits[3]) - 1;
+ }
+ self.read_mp3_coeffs(br, data_end, 0, ch, &mut coeffs[ch])?;
+ validate!(br.tell() <= data_end);
+ br.seek(data_end as u32)?;
+ }
+ Ok(())
+ }
+ pub fn synth(&mut self, coeffs: &mut [[f32; SAMPLES]; 2], output: &mut [[[f32; 32]; 36]; 2], mode: u8, mode_ext: u8) {
+ let channels = if mode == 3 { 1 } else { 2 };
+ let granules = if self.mpeg1 { 2 } else { 1 };
+
+ let mut end_freq = [[0; 2]; 2];
+ for gr_no in 0..granules {
+ for ch in 0..channels {
+ end_freq[gr_no][ch] = self.granule[gr_no][ch].lastcoded;
+ }
+ }
+
+ let mut band_flags = [[0; MP3_MAX_BANDS + 3]; 2];
+ let mut band_start = [[0; MP3_MAX_BANDS + 3]; 2];
+ let mut band_end = [[0; MP3_MAX_BANDS + 3]; 2];
+
+ if mode == 1 { // joint stereo
+ let mut bound_band = [0; 2];
+ let mut num_bands = [MP3_BANDS + 1; 2];
+
+ for (gr_no, grans) in self.granule[..granules].iter_mut().enumerate() {
+ if grans[1].block_type != 2 {
+ for band in 0..=MP3_BANDS {
+ band_flags[gr_no][band] = mode_ext;
+ band_start[gr_no][band] = MP3_SFB_LONG_OFFS[self.sf_idx][band];
+ band_end [gr_no][band] = MP3_SFB_LONG_OFFS[self.sf_idx][band + 1];
+ if (end_freq[gr_no][1] >= band_end[gr_no][band]) || (grans[1].scalefac[band.min(MP3_BANDS - 1)] == grans[1].istereo[band.min(MP3_BANDS - 1)]) {
+ band_flags[gr_no][band] &= !IS_MODE;
+ }
+ if band_start[gr_no][band] < end_freq[gr_no][1] {
+ bound_band[gr_no] = band;
+ }
+ if (band_flags[gr_no][band] & IS_MODE) == 0 {
+ for el in self.is_mode[gr_no * SAMPLES/2..][band_start[gr_no][band]..band_end[gr_no][band]].iter_mut() {
+ *el = -1;
+ }
+ }
+ }
+ } else {
+ let switch_off = if grans[1].switch_point { 3 } else { 0 };
+ let mut start = 0;
+ let mut band = 0;
+ if grans[1].switch_point {
+ let long_bands = if self.mpeg1 { 8 } else { 6 };
+ for _ in 0..long_bands {
+ band_flags[gr_no][band] = mode_ext;
+ band_start[gr_no][band] = MP3_SFB_LONG_OFFS[self.sf_idx][band];
+ band_end [gr_no][band] = MP3_SFB_LONG_OFFS[self.sf_idx][band + 1];
+ if end_freq[gr_no][1] >= band_end[gr_no][band] {
+ band_flags[gr_no][band] &= !IS_MODE;
+ }
+ start = band_end[gr_no][band];
+ band += 1;
+ }
+ }
+ for sb in switch_off..=MP3_BANDS_SHORT {
+ let band_size = MP3_SFB_SHORT_SIZE[self.sf_idx][sb];
+ for _win in 0..3 {
+ band_flags[gr_no][band] = mode_ext;
+ band_start[gr_no][band] = start;
+ band_end [gr_no][band] = start + band_size;
+ if end_freq[gr_no][1] >= band_end[gr_no][band] {
+ band_flags[gr_no][band] &= !IS_MODE;
+ }
+ start += band_size;
+ band += 1;
+ }
+ }
+ num_bands[gr_no] = band;
+ }
+ }
+ if (mode_ext & IS_MODE) != 0 {
+ for (gr_no, grans) in self.granule[..granules].iter_mut().enumerate() {
+ let (coef0, coef1) = coeffs.split_at_mut(1);
+ let coef0 = &mut coef0[0][gr_no * SAMPLES/2..];
+ let coef1 = &mut coef1[0][gr_no * SAMPLES/2..];
+ let is_mode = &self.is_mode[gr_no * SAMPLES/2..];
+ let start = band_end[gr_no][bound_band[gr_no]];
+ let end = grans[0].zero_part;
+
+ if self.mpeg1 {
+ let coef0 = &mut coef0[start..end];
+ let coef1 = &mut coef1[start..end];
+ let is_mode = &self.is_mode[gr_no * SAMPLES/2..][start..end];
+ for ((l, r), &is) in coef0.iter_mut().zip(coef1.iter_mut()).zip(is_mode.iter()) {
+ if is >= 0 && is < 7 {
+ let t = *l * MP3_ISTEREO_COEFFS[is as usize];
+ *l -= t;
+ *r = t;
+ }
+ }
+ } else {
+ let iscale = (grans[1].scalefac_compress & 1) as u8;
+ for band in 0..num_bands[gr_no] {
+ if (band_flags[gr_no][band] & IS_MODE) != 0 {
+ apply_istereo(&mut coef0[start..end], &mut coef1[start..end], is_mode[start], iscale, (band_flags[gr_no][band] & MS_MODE) != 0);
+ }
+ }
+ }
+ end_freq[gr_no][1] = end_freq[gr_no][1].min(end);
+ }
+ }
+ if (mode_ext & MS_MODE) != 0 {
+ for (gr_no, grans) in self.granule[..granules].iter_mut().enumerate() {
+ let end = grans[0].zero_part.max(grans[1].zero_part);
+ let (coef0, coef1) = coeffs.split_at_mut(1);
+ let coef0 = &mut coef0[0][gr_no * SAMPLES/2..];
+ let coef1 = &mut coef1[0][gr_no * SAMPLES/2..];
+ for band in 0..num_bands[gr_no] {
+ if band_start[gr_no][band] >= end {
+ break;
+ }
+ if (band_flags[gr_no][band] & MS_MODE) != 0 {
+ let start = band_start[gr_no][band];
+ let end = band_end[gr_no][band];
+ super::apply_ms(&mut coef0[start..end], &mut coef1[start..end]);
+ }
+ }
+ end_freq[gr_no][0] = end;
+ end_freq[gr_no][1] = end;
+ }
+ }
+ }
+ for (gr_no, grans) in self.granule[..granules].iter_mut().enumerate() {
+ for (ch, gr) in grans[..channels].iter_mut().enumerate() {
+ let src = &mut coeffs[ch][gr_no * SAMPLES/2..][..SAMPLES/2];
+ if gr.block_type != 2 {
+ dealias(src, SAMPLES/2);
+ self.mdct.mdct36(src, &mut self.tmp, &mut self.delay[ch], end_freq[gr_no][ch], gr.block_type);
+ } else {
+ let switch_off = if gr.switch_point { MP3_SFB_LONG_OFFS[self.sf_idx][if self.mpeg1 { 8 } else { 6 }] } else { 0 };
+ let mut band_buf = [0.0; 66 * 3];
+ let mut sb = if gr.switch_point { 3 } else { 0 };
+ let mut off = switch_off;
+
+ while sb < MP3_BANDS_SHORT {
+ let band_size = MP3_SFB_SHORT_SIZE[self.sf_idx][sb];
+ for win in 0..3 {
+ for i in 0..band_size {
+ band_buf[win + i * 3] = src[off + win * band_size + i];
+ }
+ }
+ src[off..][..band_size * 3].copy_from_slice(&band_buf[..band_size * 3]);
+ off += band_size * 3;
+ sb += 1;
+ }
+ if gr.switch_point {
+ dealias(src, switch_off);
+ self.mdct.mdct36(src, &mut self.tmp, &mut self.delay[ch], switch_off, gr.block_type);
+ }
+ self.mdct.mdct12(&src[switch_off..], &mut self.tmp[switch_off..], &mut self.delay[ch][switch_off..], end_freq[gr_no][ch] - switch_off);
+ }
+
+ let dst = &mut output[ch][gr_no * 18..];
+ let end = (end_freq[gr_no][ch] + 17) / 18;
+ for i in 0..end {
+ for j in 0..18 {
+ dst[j][i] = self.tmp[i * 18 + j];
+ }
+ }
+ for i in end..32 {
+ for j in 0..18 {
+ dst[j][i] = self.delay[ch][i * 18 + j];
+ }
+ for el in self.delay[ch][i * 18..][..18].iter_mut() {
+ *el = 0.0;
+ }
+ }
+ }
+ }
+ }
+}
+
+fn mp3_unquant(val: u32, scale: i8) -> f32 {
+ (val as f32) * (val as f32).cbrt() * 2.0f32.powf((scale as f32) * 0.25)
+}
+
+#[allow(clippy::too_many_arguments)]
+fn read_region(br: &mut BitReader, br_end: usize, coeffs: &mut [f32], scales: &[i8; SAMPLES/2], start: usize, end: usize, cb: &Codebook<u8>, esc_bits: u8) -> DecoderResult<usize> {
+ let mut lastcoded = 0;
+ for (i, (cpair, scpair)) in coeffs[start..end].chunks_exact_mut(2).zip(scales[start..end].chunks_exact(2)).enumerate() {
+ if br.tell() >= br_end { break; }
+ let val = br.read_cb(cb)?;
+ if val == 0 {
+ continue;
+ }
+ let a = if (val >> 4) != 0xF || esc_bits == 0 {
+ u32::from(val >> 4)
+ } else {
+ br.read(esc_bits)? + 15
+ };
+ if a != 0 {
+ let a = mp3_unquant(a, scpair[0]);
+ cpair[0] = if br.read_bool()? { -a } else { a };
+ }
+ let b = if (val & 0xF) != 0xF || esc_bits == 0 {
+ u32::from(val & 0xF)
+ } else {
+ br.read(esc_bits)? + 15
+ };
+ if b != 0 {
+ let b = mp3_unquant(b, scpair[1]);
+ cpair[1] = if br.read_bool()? { -b } else { b };
+ }
+ lastcoded = start + (i + 1) * 2;
+ }
+ Ok(lastcoded)
+}
+
+fn read_region_quad(br: &mut BitReader, br_end: usize, coeffs: &mut [f32], scales: &[i8; SAMPLES/2], start: usize, cb: Option<&Codebook<u8>>) -> DecoderResult<(usize, usize)> {
+ let mut lastcoded = 0;
+ let mut zero_part = 0;
+ if br.tell() >= br_end {
+ return Ok((0, 0));
+ }
+ for (i, (cquad, scquad)) in coeffs[start..SAMPLES/2].chunks_exact_mut(4).zip(scales[start..].chunks_exact(4)).enumerate() {
+ zero_part = start + i * 4 + 4;
+ if br.tell() >= br_end {
+ break;
+ }
+ let val = if let Some(cbook) = cb { br.read_cb(cbook)? } else { (br.read(4)? as u8) ^ 0xF };
+ if val == 0 {
+ continue;
+ }
+ for j in 0..4 {
+ if ((val >> (3 - j)) & 1) != 0 {
+ cquad[j] = mp3_unquant(1, scquad[j]);
+ if br.read_bool()? {
+ cquad[j] = -cquad[j];
+ }
+ lastcoded = start + i * 4 + j + 1;
+ }
+ }
+ }
+ Ok((lastcoded, zero_part))
+}
+
+const DCT12_0: f32 = -0.92387953251128675613;
+const DCT12_1: f32 = -0.38268343236508977174;
+
+const DCT12_2: f32 = -0.1305261922200516;
+const DCT12_3: f32 = -0.6087614290087205;
+const DCT12_4: f32 = 0.7933533402912348;
+const DCT12_5: f32 = 0.9914448613738103;
+
+fn dct12(src: &[f32], dst: &mut [f32]) {
+ let t0 = src[0] - src[3] - src[4];
+ let t1 = src[1] - src[2] - src[5];
+
+ dst[ 4] = t0 * DCT12_1 - t1 * DCT12_0;
+ dst[ 7] = t0 * DCT12_0 + t1 * DCT12_1;
+ dst[ 1] = -dst[4];
+ dst[10] = -dst[7];
+
+ let t0 = src[1] * DCT12_1 - src[4] * DCT12_0;
+ let t1 = src[1] * DCT12_0 + src[4] * DCT12_1;
+
+ dst[ 3] = src[0] * DCT12_2 + src[2] * DCT12_3 + src[3] * DCT12_4 + src[5] * DCT12_5 - t0;
+ dst[ 5] = src[0] * DCT12_3 - src[2] * DCT12_2 - src[3] * DCT12_5 + src[5] * DCT12_4 - t1;
+ dst[ 6] = -src[0] * DCT12_4 + src[2] * DCT12_5 - src[3] * DCT12_2 + src[5] * DCT12_3 - t0;
+ dst[ 8] = -src[0] * DCT12_5 - src[2] * DCT12_4 + src[3] * DCT12_3 + src[5] * DCT12_2 + t1;
+ dst[ 2] = -dst[3];
+ dst[ 0] = -dst[5];
+ dst[11] = dst[6];
+ dst[ 9] = dst[8];
+}
+
+const DCT36_PRESCALE: [f32; 18] = [
+ 0.99904822158185776240, 0.99144486137381041114, 0.97629600711993336597,
+ 0.95371695074822692114, 0.92387953251128675613, 0.88701083317822170105,
+ 0.84339144581288570127, 0.79335334029123516458, 0.73727733681012404139,
+ 0.67559020761566024435, 0.60876142900872063942, 0.53729960834682383185,
+ 0.46174861323503393057, 0.38268343236508977174, 0.30070579950427312163,
+ 0.21643961393810287977, 0.13052619222005159156, 0.04361938736533599979
+];
+const DCT36_TWIDDLE: [f32; 9] = [
+ 0.99619469809174553229, 0.96592582628906828675, 0.90630778703664996324,
+ 0.81915204428899178969, 0.70710678118654752440, 0.57357643635104609611,
+ 0.42261826174069943619, 0.25881904510252076236, 0.08715574274765817357
+];
+const SDCT2_TWIDDLE: [f32; 7] = [
+ -2.0 * 0.98480775301220805936, -2.0 * 0.86602540378443864676,
+ -2.0 * 0.76604444311897803520, -2.0 * 0.64278760968653932633,
+ -2.0 * 0.34202014332566873305, -2.0 * 0.17364817766693034887,
+ 2.0 * 0.93969262078590838404
+];
+
+fn sdct_ii(buf: &mut [f32]) {
+ let t0 = buf[ 6] + buf[10];
+ let t1 = buf[ 6] - buf[10];
+ let t2 = buf[12] + buf[ 4];
+ let t3 = buf[12] - buf[ 4];
+ let t4 = buf[16] + buf[ 0];
+ let t5 = buf[16] - buf[ 0];
+
+ let t6 = t0 + t2;
+ let t7 = (t0 - t2) * SDCT2_TWIDDLE[2];
+ let t8 = (t1 + t3) * SDCT2_TWIDDLE[3];
+ let t9 = t1 - t3;
+ let t0 = (t0 - t4) * SDCT2_TWIDDLE[5];
+ let t1 = (t1 - t5) * SDCT2_TWIDDLE[0];
+ let t2 = (t2 - t4) * SDCT2_TWIDDLE[6];
+ let t3 = (t3 + t5) * SDCT2_TWIDDLE[4];
+
+ let ta = t6 + t4;
+ let tb = (t9 + t5) * SDCT2_TWIDDLE[1];
+
+ let tc = buf[2] + buf[14];
+ let td = (buf[2] - buf[14]) * SDCT2_TWIDDLE[1];
+
+ let t6 = buf[8] + tc;
+ let t9 = buf[8] * 2.0 - tc;
+ let te = t9 + t2;
+ let tf = t9 - t2;
+ let t9 = t9 + t0;
+
+ buf[ 0] = ta + t6;
+ buf[ 2] = t8 - td - t1;
+ buf[ 4] = t7 - te;
+ buf[ 6] = tb;
+ buf[ 8] = tf - t0;
+ buf[10] = td - t3 - t1;
+ buf[12] = ta - t6 * 2.0;
+ buf[14] = t8 + t3 + td;
+ buf[16] = t9 + t7;
+}
+
+fn dct36(src: &mut [f32], dst: &mut [f32]) {
+ for (el, &w) in src.iter_mut().zip(DCT36_PRESCALE.iter()) {
+ *el *= w;
+ }
+
+ let mut tmp = [0.0; 18];
+ for i in 0..9 {
+ tmp[i * 2] = src[i] + src[17 - i];
+ tmp[i * 2 + 1] = (src[i] - src[17 - i]) * DCT36_TWIDDLE[i] * 2.0;
+ }
+ sdct_ii(&mut tmp);
+ sdct_ii(&mut tmp[1..]);
+
+ for i in (3..18).step_by(2) {
+ tmp[i] -= tmp[i - 2];
+ }
+ tmp[0] *= 0.5;
+ for i in 1..18 {
+ tmp[i] = tmp[i] * 0.5 - tmp[i - 1];
+ }
+ for i in 0..18 {
+ dst[i] = -tmp[17 - i] * 2.0;
+ }
+}
+
+const ALIAS_COEFFS_S: [f32; 8] = [
+ 0.85749292571254418689, 0.88174199731770518178,
+ 0.94962864910273289205, 0.98331459249179014599,
+ 0.99551781606758576429, 0.99916055817814750453,
+ 0.99989919524444704627, 0.99999315507028023572
+];
+const ALIAS_COEFFS_A: [f32; 8] = [
+ -0.51449575542752651213, -0.47173196856497227225,
+ -0.31337745420390185437, -0.18191319961098117700,
+ -0.09457419252642064760, -0.04096558288530404768,
+ -0.01419856857247114805, -0.00369997467376003687
+];
+fn dealias(buf: &mut [f32], len: usize) {
+ for i in (18..len).step_by(18) {
+ for (j, (&cs, &ca)) in ALIAS_COEFFS_S.iter().zip(ALIAS_COEFFS_A.iter()).enumerate() {
+ let a = buf[i - j - 1];
+ let b = buf[i + j];
+ let c0 = a * cs - b * ca;
+ let c1 = a * ca + b * cs;
+ buf[i - j - 1] = c0;
+ buf[i + j] = c1;
+ }
+ }
+}
+
+fn apply_istereo(ch0: &mut [f32], ch1: &mut [f32], is_mode: i8, iscale: u8, ms_mode: bool) {
+ match (is_mode, ms_mode) {
+ (-1, true) => {
+ for (c0, c1) in ch0.iter_mut().zip(ch1.iter_mut()) {
+ let a = (*c0 + *c1) * std::f32::consts::FRAC_1_SQRT_2;
+ let b = (*c0 - *c1) * std::f32::consts::FRAC_1_SQRT_2;
+ *c0 = a;
+ *c1 = b;
+ }
+ },
+ (-1, false) => {},
+ (0, _) => {
+ ch1.copy_from_slice(ch0);
+ },
+ _ => {
+ let scale = mp3_unquant(1, -((is_mode + 1) >> 1) << iscale);
+ if (is_mode & 1) == 0 {
+ for (&c0, c1) in ch0.iter().zip(ch1.iter_mut()) {
+ *c1 = c0 * scale;
+ }
+ } else {
+ for (c0, c1) in ch0.iter_mut().zip(ch1.iter_mut()) {
+ *c1 = *c0;
+ *c0 *= scale;
+ }
+ }
+ },
+ };
+}
--- /dev/null
+use nihav_core::io::codebook::*;
+
+pub const MP3_BANDS: usize = 21;
+pub const MP3_BANDS_SHORT: usize = 12;
+
+pub const MP3_PREEMP_SCALES: [i8; MP3_BANDS + 1] = [
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 3, 2, 0
+];
+
+pub const MP3_ISTEREO_COEFFS: [f32; 7] = [
+ 1.0, 0.78867513459481288226, 0.63397459621556135323, 0.5,
+ 0.36602540378443864677, 0.21132486540518711774, 0.0
+];
+
+pub const SCFSI_FROM_BAND: [usize; MP3_BANDS] = [
+ 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2,
+ 3, 3, 3, 3, 3
+];
+
+pub const MP3_SCALEFAC_BITS1: [u8; 16] = [ 0, 0, 0, 0, 3, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4 ];
+pub const MP3_SCALEFAC_BITS2: [u8; 16] = [ 0, 1, 2, 3, 0, 1, 2, 3, 1, 2, 3, 1, 2, 3, 2, 3 ];
+
+pub const MP3_SFB_LONG_OFFS: [[usize; MP3_BANDS + 2]; 9] = [
+ [ // 44.1
+ 0, 4, 8, 12, 16, 20, 24, 30, 36, 44, 52, 62, 74, 90, 110, 134, 162, 196, 238, 288, 342, 418, 576
+ ], [ // 48
+ 0, 4, 8, 12, 16, 20, 24, 30, 36, 42, 50, 60, 72, 88, 106, 128, 156, 190, 230, 276, 330, 384, 576
+ ], [ // 32
+ 0, 4, 8, 12, 16, 20, 24, 30, 36, 44, 54, 66, 82, 102, 126, 156, 194, 240, 296, 364, 448, 550, 576
+ ], [ // 22.05
+ 0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96, 116, 140, 168, 200, 238, 284, 336, 396, 464, 522, 576
+ ], [ // 24
+ 0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96, 114, 136, 162, 194, 232, 278, 332, 394, 464, 540, 576
+ ], [ // 16
+ 0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96, 116, 140, 168, 200, 238, 284, 336, 396, 464, 522, 576
+ ], [ // 11.025
+ 0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96, 116, 140, 168, 200, 238, 284, 336, 396, 464, 522, 576
+ ], [ // 12
+ 0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96, 116, 140, 168, 200, 238, 284, 336, 396, 464, 522, 576
+ ], [ // 8
+ 0, 12, 24, 36, 48, 60, 72, 88, 108, 132, 160, 192, 232, 280, 336, 400, 476, 566, 568, 570, 572, 574, 576
+ ]
+];
+
+pub const MP3_SFB_SHORT_OFFS: [[usize; MP3_BANDS_SHORT + 2]; 9] = [
+ [ 0, 4, 8, 12, 16, 22, 30, 40, 52, 66, 84, 106, 136, 192 ], // 44.1
+ [ 0, 4, 8, 12, 16, 22, 28, 38, 50, 64, 80, 100, 126, 192 ], // 48
+ [ 0, 4, 8, 12, 16, 22, 30, 42, 58, 78, 104, 138, 180, 192 ], // 32
+ [ 0, 4, 8, 12, 18, 24, 32, 42, 56, 74, 100, 132, 174, 192 ], // 22.05
+ [ 0, 4, 8, 12, 18, 26, 36, 48, 62, 80, 104, 136, 180, 192 ], // 24
+ [ 0, 4, 8, 12, 18, 26, 36, 48, 62, 80, 104, 134, 174, 192 ], // 16
+ [ 0, 4, 8, 12, 18, 26, 36, 48, 62, 80, 104, 134, 174, 192 ], // 11.025
+ [ 0, 4, 8, 12, 18, 26, 36, 48, 62, 80, 104, 134, 174, 192 ], // 12
+ [ 0, 8, 16, 24, 36, 52, 72, 96, 124, 160, 162, 164, 166, 192 ], // 8
+];
+pub const MP3_SFB_SHORT_SIZE: [[usize; MP3_BANDS_SHORT + 1]; 9] = [
+ [ 4, 4, 4, 4, 6, 8, 10, 12, 14, 18, 22, 30, 56 ], // 44.1
+ [ 4, 4, 4, 4, 6, 6, 10, 12, 14, 16, 20, 26, 66 ], // 48
+ [ 4, 4, 4, 4, 6, 8, 12, 16, 20, 26, 34, 42, 12 ], // 32
+ [ 4, 4, 4, 6, 6, 8, 10, 14, 18, 26, 32, 42, 18 ], // 22.05
+ [ 4, 4, 4, 6, 8, 10, 12, 14, 18, 24, 32, 44, 12 ], // 24
+ [ 4, 4, 4, 6, 8, 10, 12, 14, 18, 24, 30, 40, 18 ], // 16
+ [ 4, 4, 4, 6, 8, 10, 12, 14, 18, 24, 30, 40, 18 ], // 11.025
+ [ 4, 4, 4, 6, 8, 10, 12, 14, 18, 24, 30, 40, 18 ], // 12
+ [ 8, 8, 8, 12, 16, 20, 24, 28, 36, 2, 2, 2, 26 ], // 8
+];
+
+pub const MP3_SCF_BITS3: [u8; 12 * 2] = [
+ 0, 0, 0, 1, 0, 2,
+ 1, 0, 1, 1, 1, 2,
+ 2, 0, 2, 1, 2, 2,
+ 3, 0, 3, 1, 3, 2
+];
+pub const MP3_SCF_BITS5: [u8; 25 * 2] = [
+ 0, 0, 0, 1, 0, 2, 0, 3, 0, 4,
+ 1, 0, 1, 1, 1, 2, 1, 3, 1, 4,
+ 2, 0, 2, 1, 2, 2, 2, 3, 2, 4,
+ 3, 0, 3, 1, 3, 2, 3, 3, 3, 4,
+ 4, 0, 4, 1, 4, 2, 4, 3, 4, 4
+];
+pub const MP3_SCF_BITS6: [u8; 180 * 3] = [
+ 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 3, 0, 0, 4, 0, 0, 5,
+ 0, 1, 0, 0, 1, 1, 0, 1, 2, 0, 1, 3, 0, 1, 4, 0, 1, 5,
+ 0, 2, 0, 0, 2, 1, 0, 2, 2, 0, 2, 3, 0, 2, 4, 0, 2, 5,
+ 0, 3, 0, 0, 3, 1, 0, 3, 2, 0, 3, 3, 0, 3, 4, 0, 3, 5,
+ 0, 4, 0, 0, 4, 1, 0, 4, 2, 0, 4, 3, 0, 4, 4, 0, 4, 5,
+ 0, 5, 0, 0, 5, 1, 0, 5, 2, 0, 5, 3, 0, 5, 4, 0, 5, 5,
+ 1, 0, 0, 1, 0, 1, 1, 0, 2, 1, 0, 3, 1, 0, 4, 1, 0, 5,
+ 1, 1, 0, 1, 1, 1, 1, 1, 2, 1, 1, 3, 1, 1, 4, 1, 1, 5,
+ 1, 2, 0, 1, 2, 1, 1, 2, 2, 1, 2, 3, 1, 2, 4, 1, 2, 5,
+ 1, 3, 0, 1, 3, 1, 1, 3, 2, 1, 3, 3, 1, 3, 4, 1, 3, 5,
+ 1, 4, 0, 1, 4, 1, 1, 4, 2, 1, 4, 3, 1, 4, 4, 1, 4, 5,
+ 1, 5, 0, 1, 5, 1, 1, 5, 2, 1, 5, 3, 1, 5, 4, 1, 5, 5,
+ 2, 0, 0, 2, 0, 1, 2, 0, 2, 2, 0, 3, 2, 0, 4, 2, 0, 5,
+ 2, 1, 0, 2, 1, 1, 2, 1, 2, 2, 1, 3, 2, 1, 4, 2, 1, 5,
+ 2, 2, 0, 2, 2, 1, 2, 2, 2, 2, 2, 3, 2, 2, 4, 2, 2, 5,
+ 2, 3, 0, 2, 3, 1, 2, 3, 2, 2, 3, 3, 2, 3, 4, 2, 3, 5,
+ 2, 4, 0, 2, 4, 1, 2, 4, 2, 2, 4, 3, 2, 4, 4, 2, 4, 5,
+ 2, 5, 0, 2, 5, 1, 2, 5, 2, 2, 5, 3, 2, 5, 4, 2, 5, 5,
+ 3, 0, 0, 3, 0, 1, 3, 0, 2, 3, 0, 3, 3, 0, 4, 3, 0, 5,
+ 3, 1, 0, 3, 1, 1, 3, 1, 2, 3, 1, 3, 3, 1, 4, 3, 1, 5,
+ 3, 2, 0, 3, 2, 1, 3, 2, 2, 3, 2, 3, 3, 2, 4, 3, 2, 5,
+ 3, 3, 0, 3, 3, 1, 3, 3, 2, 3, 3, 3, 3, 3, 4, 3, 3, 5,
+ 3, 4, 0, 3, 4, 1, 3, 4, 2, 3, 4, 3, 3, 4, 4, 3, 4, 5,
+ 3, 5, 0, 3, 5, 1, 3, 5, 2, 3, 5, 3, 3, 5, 4, 3, 5, 5,
+ 4, 0, 0, 4, 0, 1, 4, 0, 2, 4, 0, 3, 4, 0, 4, 4, 0, 5,
+ 4, 1, 0, 4, 1, 1, 4, 1, 2, 4, 1, 3, 4, 1, 4, 4, 1, 5,
+ 4, 2, 0, 4, 2, 1, 4, 2, 2, 4, 2, 3, 4, 2, 4, 4, 2, 5,
+ 4, 3, 0, 4, 3, 1, 4, 3, 2, 4, 3, 3, 4, 3, 4, 4, 3, 5,
+ 4, 4, 0, 4, 4, 1, 4, 4, 2, 4, 4, 3, 4, 4, 4, 4, 4, 5,
+ 4, 5, 0, 4, 5, 1, 4, 5, 2, 4, 5, 3, 4, 5, 4, 4, 5, 5
+];
+
+pub const MP3_SCF_ENDS: [[[usize; 4]; 3]; 6] = [
+ [ [ 6, 11, 16, 21 ], [ 9, 18, 27, 36 ], [ 6, 15, 27, 33 ] ],
+ [ [ 6, 11, 18, 21 ], [ 9, 18, 30, 36 ], [ 6, 15, 27, 33 ] ],
+ [ [ 11, 21, 21, 21 ], [ 18, 36, 36, 36 ], [ 15, 33, 33, 33 ] ],
+ [ [ 7, 14, 21, 21 ], [ 12, 24, 36, 36 ], [ 6, 21, 33, 33 ] ],
+ [ [ 6, 12, 18, 21 ], [ 12, 21, 30, 36 ], [ 6, 18, 27, 33 ] ],
+ [ [ 8, 16, 21, 21 ], [ 15, 27, 36, 36 ], [ 6, 24, 33, 33 ] ]
+];
+
+const MP3_HUFF_QUAD_A_BITS: [u8; 16] = [ 1, 5, 4, 5, 6, 5, 4, 4, 7, 3, 6, 0, 7, 2, 3, 1 ];
+const MP3_HUFF_QUAD_A_LENS: [u8; 16] = [ 1, 4, 4, 5, 4, 6, 5, 6, 4, 5, 5, 6, 5, 6, 6, 6 ];
+
+const MP3_HUFF1_BITS: [u8; 4] = [ 1, 1, 1, 0 ];
+const MP3_HUFF1_LENS: [u8; 4] = [ 1, 3, 2, 3 ];
+const MP3_HUFF2_BITS: [u8; 9] = [ 1, 2, 1, 3, 1, 1, 3, 2, 0 ];
+const MP3_HUFF2_LENS: [u8; 9] = [ 1, 3, 6, 3, 3, 5, 5, 5, 6 ];
+const MP3_HUFF3_BITS: [u8; 9] = [ 3, 2, 1, 1, 1, 1, 3, 2, 0 ];
+const MP3_HUFF3_LENS: [u8; 9] = [ 2, 2, 6, 3, 2, 5, 5, 5, 6 ];
+const MP3_HUFF5_BITS: [u8; 16] = [ 1, 2, 6, 5, 3, 1, 4, 4, 7, 5, 7, 1, 6, 1, 1, 0 ];
+const MP3_HUFF5_LENS: [u8; 16] = [ 1, 3, 6, 7, 3, 3, 6, 7, 6, 6, 7, 8, 7, 6, 7, 8 ];
+const MP3_HUFF6_BITS: [u8; 16] = [ 7, 3, 5, 1, 6, 2, 3, 2, 5, 4, 4, 1, 3, 3, 2, 0 ];
+const MP3_HUFF6_LENS: [u8; 16] = [ 3, 3, 5, 7, 3, 2, 4, 5, 4, 4, 5, 6, 6, 5, 6, 7 ];
+const MP3_HUFF7_BITS: [u8; 36] = [
+ 0x01, 0x02, 0x0A, 0x13, 0x10, 0x0A, 0x03, 0x03,
+ 0x07, 0x0A, 0x05, 0x03, 0x0B, 0x04, 0x0D, 0x11,
+ 0x08, 0x04, 0x0C, 0x0B, 0x12, 0x0F, 0x0B, 0x02,
+ 0x07, 0x06, 0x09, 0x0E, 0x03, 0x01, 0x06, 0x04,
+ 0x05, 0x03, 0x02, 0x00
+];
+const MP3_HUFF7_LENS: [u8; 36] = [
+ 1, 3, 6, 8, 8, 9, 3, 4, 6, 7, 7, 8, 6, 5, 7, 8,
+ 8, 9, 7, 7, 8, 9, 9, 9, 7, 7, 8, 9, 9, 10, 8, 8,
+ 9, 10, 10, 10
+];
+const MP3_HUFF8_BITS: [u8; 36] = [
+ 0x03, 0x04, 0x06, 0x12, 0x0C, 0x05, 0x05, 0x01,
+ 0x02, 0x10, 0x09, 0x03, 0x07, 0x03, 0x05, 0x0E,
+ 0x07, 0x03, 0x13, 0x11, 0x0F, 0x0D, 0x0A, 0x04,
+ 0x0D, 0x05, 0x08, 0x0B, 0x05, 0x01, 0x0C, 0x04,
+ 0x04, 0x01, 0x01, 0x00
+];
+const MP3_HUFF8_LENS: [u8; 36] = [
+ 2, 3, 6, 8, 8, 9, 3, 2, 4, 8, 8, 8, 6, 4, 6, 8,
+ 8, 9, 8, 8, 8, 9, 9, 10, 8, 7, 8, 9, 10, 10, 9, 8,
+ 9, 9, 11, 11
+];
+const MP3_HUFF9_BITS: [u8; 36] = [
+ 0x07, 0x05, 0x09, 0x0E, 0x0F, 0x07, 0x06, 0x04,
+ 0x05, 0x05, 0x06, 0x07, 0x07, 0x06, 0x08, 0x08,
+ 0x08, 0x05, 0x0F, 0x06, 0x09, 0x0A, 0x05, 0x01,
+ 0x0B, 0x07, 0x09, 0x06, 0x04, 0x01, 0x0E, 0x04,
+ 0x06, 0x02, 0x06, 0x00
+];
+const MP3_HUFF9_LENS: [u8; 36] = [
+ 3, 3, 5, 6, 8, 9, 3, 3, 4, 5, 6, 8, 4, 4, 5, 6,
+ 7, 8, 6, 5, 6, 7, 7, 8, 7, 6, 7, 7, 8, 9, 8, 7,
+ 8, 8, 9, 9
+];
+const MP3_HUFF10_BITS: [u8; 64] = [
+ 0x01, 0x02, 0x0A, 0x17, 0x23, 0x1E, 0x0C, 0x11,
+ 0x03, 0x03, 0x08, 0x0C, 0x12, 0x15, 0x0C, 0x07,
+ 0x0B, 0x09, 0x0F, 0x15, 0x20, 0x28, 0x13, 0x06,
+ 0x0E, 0x0D, 0x16, 0x22, 0x2E, 0x17, 0x12, 0x07,
+ 0x14, 0x13, 0x21, 0x2F, 0x1B, 0x16, 0x09, 0x03,
+ 0x1F, 0x16, 0x29, 0x1A, 0x15, 0x14, 0x05, 0x03,
+ 0x0E, 0x0D, 0x0A, 0x0B, 0x10, 0x06, 0x05, 0x01,
+ 0x09, 0x08, 0x07, 0x08, 0x04, 0x04, 0x02, 0x00
+];
+const MP3_HUFF10_LENS: [u8; 64] = [
+ 1, 3, 6, 8, 9, 9, 9, 10, 3, 4, 6, 7, 8, 9, 8, 8,
+ 6, 6, 7, 8, 9, 10, 9, 9, 7, 7, 8, 9, 10, 10, 9, 10,
+ 8, 8, 9, 10, 10, 10, 10, 10, 9, 9, 10, 10, 11, 11, 10, 11,
+ 8, 8, 9, 10, 10, 10, 11, 11, 9, 8, 9, 10, 10, 11, 11, 11
+];
+const MP3_HUFF11_BITS: [u8; 64] = [
+ 0x03, 0x04, 0x0A, 0x18, 0x22, 0x21, 0x15, 0x0F,
+ 0x05, 0x03, 0x04, 0x0A, 0x20, 0x11, 0x0B, 0x0A,
+ 0x0B, 0x07, 0x0D, 0x12, 0x1E, 0x1F, 0x14, 0x05,
+ 0x19, 0x0B, 0x13, 0x3B, 0x1B, 0x12, 0x0C, 0x05,
+ 0x23, 0x21, 0x1F, 0x3A, 0x1E, 0x10, 0x07, 0x05,
+ 0x1C, 0x1A, 0x20, 0x13, 0x11, 0x0F, 0x08, 0x0E,
+ 0x0E, 0x0C, 0x09, 0x0D, 0x0E, 0x09, 0x04, 0x01,
+ 0x0B, 0x04, 0x06, 0x06, 0x06, 0x03, 0x02, 0x00
+];
+const MP3_HUFF11_LENS: [u8; 64] = [
+ 2, 3, 5, 7, 8, 9, 8, 9, 3, 3, 4, 6, 8, 8, 7, 8,
+ 5, 5, 6, 7, 8, 9, 8, 8, 7, 6, 7, 9, 8, 10, 8, 9,
+ 8, 8, 8, 9, 9, 10, 9, 10, 8, 8, 9, 10, 10, 11, 10, 11,
+ 8, 7, 7, 8, 9, 10, 10, 10, 8, 7, 8, 9, 10, 10, 10, 10
+];
+const MP3_HUFF12_BITS: [u8; 64] = [
+ 0x09, 0x06, 0x10, 0x21, 0x29, 0x27, 0x26, 0x1A,
+ 0x07, 0x05, 0x06, 0x09, 0x17, 0x10, 0x1A, 0x0B,
+ 0x11, 0x07, 0x0B, 0x0E, 0x15, 0x1E, 0x0A, 0x07,
+ 0x11, 0x0A, 0x0F, 0x0C, 0x12, 0x1C, 0x0E, 0x05,
+ 0x20, 0x0D, 0x16, 0x13, 0x12, 0x10, 0x09, 0x05,
+ 0x28, 0x11, 0x1F, 0x1D, 0x11, 0x0D, 0x04, 0x02,
+ 0x1B, 0x0C, 0x0B, 0x0F, 0x0A, 0x07, 0x04, 0x01,
+ 0x1B, 0x0C, 0x08, 0x0C, 0x06, 0x03, 0x01, 0x00
+];
+const MP3_HUFF12_LENS: [u8; 64] = [
+ 4, 3, 5, 7, 8, 9, 9, 9, 3, 3, 4, 5, 7, 7, 8, 8,
+ 5, 4, 5, 6, 7, 8, 7, 8, 6, 5, 6, 6, 7, 8, 8, 8,
+ 7, 6, 7, 7, 8, 8, 8, 9, 8, 7, 8, 8, 8, 9, 8, 9,
+ 8, 7, 7, 8, 8, 9, 9, 10, 9, 8, 8, 9, 9, 9, 9, 10
+];
+const MP3_HUFF13_BITS: [u8; 256] = [
+ 0x01, 0x05, 0x0E, 0x15, 0x22, 0x33, 0x2E, 0x47,
+ 0x2A, 0x34, 0x44, 0x34, 0x43, 0x2C, 0x2B, 0x13,
+ 0x03, 0x04, 0x0C, 0x13, 0x1F, 0x1A, 0x2C, 0x21,
+ 0x1F, 0x18, 0x20, 0x18, 0x1F, 0x23, 0x16, 0x0E,
+ 0x0F, 0x0D, 0x17, 0x24, 0x3B, 0x31, 0x4D, 0x41,
+ 0x1D, 0x28, 0x1E, 0x28, 0x1B, 0x21, 0x2A, 0x10,
+ 0x16, 0x14, 0x25, 0x3D, 0x38, 0x4F, 0x49, 0x40,
+ 0x2B, 0x4C, 0x38, 0x25, 0x1A, 0x1F, 0x19, 0x0E,
+ 0x23, 0x10, 0x3C, 0x39, 0x61, 0x4B, 0x72, 0x5B,
+ 0x36, 0x49, 0x37, 0x29, 0x30, 0x35, 0x17, 0x18,
+ 0x3A, 0x1B, 0x32, 0x60, 0x4C, 0x46, 0x5D, 0x54,
+ 0x4D, 0x3A, 0x4F, 0x1D, 0x4A, 0x31, 0x29, 0x11,
+ 0x2F, 0x2D, 0x4E, 0x4A, 0x73, 0x5E, 0x5A, 0x4F,
+ 0x45, 0x53, 0x47, 0x32, 0x3B, 0x26, 0x24, 0x0F,
+ 0x48, 0x22, 0x38, 0x5F, 0x5C, 0x55, 0x5B, 0x5A,
+ 0x56, 0x49, 0x4D, 0x41, 0x33, 0x2C, 0x2B, 0x2A,
+ 0x2B, 0x14, 0x1E, 0x2C, 0x37, 0x4E, 0x48, 0x57,
+ 0x4E, 0x3D, 0x2E, 0x36, 0x25, 0x1E, 0x14, 0x10,
+ 0x35, 0x19, 0x29, 0x25, 0x2C, 0x3B, 0x36, 0x51,
+ 0x42, 0x4C, 0x39, 0x36, 0x25, 0x12, 0x27, 0x0B,
+ 0x23, 0x21, 0x1F, 0x39, 0x2A, 0x52, 0x48, 0x50,
+ 0x2F, 0x3A, 0x37, 0x15, 0x16, 0x1A, 0x26, 0x16,
+ 0x35, 0x19, 0x17, 0x26, 0x46, 0x3C, 0x33, 0x24,
+ 0x37, 0x1A, 0x22, 0x17, 0x1B, 0x0E, 0x09, 0x07,
+ 0x22, 0x20, 0x1C, 0x27, 0x31, 0x4B, 0x1E, 0x34,
+ 0x30, 0x28, 0x34, 0x1C, 0x12, 0x11, 0x09, 0x05,
+ 0x2D, 0x15, 0x22, 0x40, 0x38, 0x32, 0x31, 0x2D,
+ 0x1F, 0x13, 0x0C, 0x0F, 0x0A, 0x07, 0x06, 0x03,
+ 0x30, 0x17, 0x14, 0x27, 0x24, 0x23, 0x35, 0x15,
+ 0x10, 0x17, 0x0D, 0x0A, 0x06, 0x01, 0x04, 0x02,
+ 0x10, 0x0F, 0x11, 0x1B, 0x19, 0x14, 0x1D, 0x0B,
+ 0x11, 0x0C, 0x10, 0x08, 0x01, 0x01, 0x00, 0x01
+];
+const MP3_HUFF13_LENS: [u8; 256] = [
+ 1, 4, 6, 7, 8, 9, 9, 10, 9, 10, 11, 11, 12, 12, 13, 13,
+ 3, 4, 6, 7, 8, 8, 9, 9, 9, 9, 10, 10, 11, 12, 12, 12,
+ 6, 6, 7, 8, 9, 9, 10, 10, 9, 10, 10, 11, 11, 12, 13, 13,
+ 7, 7, 8, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, 13, 13,
+ 8, 7, 9, 9, 10, 10, 11, 11, 10, 11, 11, 12, 12, 13, 13, 14,
+ 9, 8, 9, 10, 10, 10, 11, 11, 11, 11, 12, 11, 13, 13, 14, 14,
+ 9, 9, 10, 10, 11, 11, 11, 11, 11, 12, 12, 12, 13, 13, 14, 14,
+ 10, 9, 10, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 14, 16, 16,
+ 9, 8, 9, 10, 10, 11, 11, 12, 12, 12, 12, 13, 13, 14, 15, 15,
+ 10, 9, 10, 10, 11, 11, 11, 13, 12, 13, 13, 14, 14, 14, 16, 15,
+ 10, 10, 10, 11, 11, 12, 12, 13, 12, 13, 14, 13, 14, 15, 16, 17,
+ 11, 10, 10, 11, 12, 12, 12, 12, 13, 13, 13, 14, 15, 15, 15, 16,
+ 11, 11, 11, 12, 12, 13, 12, 13, 14, 14, 15, 15, 15, 16, 16, 16,
+ 12, 11, 12, 13, 13, 13, 14, 14, 14, 14, 14, 15, 16, 15, 16, 16,
+ 13, 12, 12, 13, 13, 13, 15, 14, 14, 17, 15, 15, 15, 17, 16, 16,
+ 12, 12, 13, 14, 14, 14, 15, 14, 15, 15, 16, 16, 19, 18, 19, 16
+];
+const MP3_HUFF15_BITS: [u8; 256] = [
+ 0x07, 0x0C, 0x12, 0x35, 0x2F, 0x4C, 0x7C, 0x6C,
+ 0x59, 0x7B, 0x6C, 0x77, 0x6B, 0x51, 0x7A, 0x3F,
+ 0x0D, 0x05, 0x10, 0x1B, 0x2E, 0x24, 0x3D, 0x33,
+ 0x2A, 0x46, 0x34, 0x53, 0x41, 0x29, 0x3B, 0x24,
+ 0x13, 0x11, 0x0F, 0x18, 0x29, 0x22, 0x3B, 0x30,
+ 0x28, 0x40, 0x32, 0x4E, 0x3E, 0x50, 0x38, 0x21,
+ 0x1D, 0x1C, 0x19, 0x2B, 0x27, 0x3F, 0x37, 0x5D,
+ 0x4C, 0x3B, 0x5D, 0x48, 0x36, 0x4B, 0x32, 0x1D,
+ 0x34, 0x16, 0x2A, 0x28, 0x43, 0x39, 0x5F, 0x4F,
+ 0x48, 0x39, 0x59, 0x45, 0x31, 0x42, 0x2E, 0x1B,
+ 0x4D, 0x25, 0x23, 0x42, 0x3A, 0x34, 0x5B, 0x4A,
+ 0x3E, 0x30, 0x4F, 0x3F, 0x5A, 0x3E, 0x28, 0x26,
+ 0x7D, 0x20, 0x3C, 0x38, 0x32, 0x5C, 0x4E, 0x41,
+ 0x37, 0x57, 0x47, 0x33, 0x49, 0x33, 0x46, 0x1E,
+ 0x6D, 0x35, 0x31, 0x5E, 0x58, 0x4B, 0x42, 0x7A,
+ 0x5B, 0x49, 0x38, 0x2A, 0x40, 0x2C, 0x15, 0x19,
+ 0x5A, 0x2B, 0x29, 0x4D, 0x49, 0x3F, 0x38, 0x5C,
+ 0x4D, 0x42, 0x2F, 0x43, 0x30, 0x35, 0x24, 0x14,
+ 0x47, 0x22, 0x43, 0x3C, 0x3A, 0x31, 0x58, 0x4C,
+ 0x43, 0x6A, 0x47, 0x36, 0x26, 0x27, 0x17, 0x0F,
+ 0x6D, 0x35, 0x33, 0x2F, 0x5A, 0x52, 0x3A, 0x39,
+ 0x30, 0x48, 0x39, 0x29, 0x17, 0x1B, 0x3E, 0x09,
+ 0x56, 0x2A, 0x28, 0x25, 0x46, 0x40, 0x34, 0x2B,
+ 0x46, 0x37, 0x2A, 0x19, 0x1D, 0x12, 0x0B, 0x0B,
+ 0x76, 0x44, 0x1E, 0x37, 0x32, 0x2E, 0x4A, 0x41,
+ 0x31, 0x27, 0x18, 0x10, 0x16, 0x0D, 0x0E, 0x07,
+ 0x5B, 0x2C, 0x27, 0x26, 0x22, 0x3F, 0x34, 0x2D,
+ 0x1F, 0x34, 0x1C, 0x13, 0x0E, 0x08, 0x09, 0x03,
+ 0x7B, 0x3C, 0x3A, 0x35, 0x2F, 0x2B, 0x20, 0x16,
+ 0x25, 0x18, 0x11, 0x0C, 0x0F, 0x0A, 0x02, 0x01,
+ 0x47, 0x25, 0x22, 0x1E, 0x1C, 0x14, 0x11, 0x1A,
+ 0x15, 0x10, 0x0A, 0x06, 0x08, 0x06, 0x02, 0x00
+];
+const MP3_HUFF15_LENS: [u8; 256] = [
+ 3, 4, 5, 7, 7, 8, 9, 9, 9, 10, 10, 11, 11, 11, 12, 13,
+ 4, 3, 5, 6, 7, 7, 8, 8, 8, 9, 9, 10, 10, 10, 11, 11,
+ 5, 5, 5, 6, 7, 7, 8, 8, 8, 9, 9, 10, 10, 11, 11, 11,
+ 6, 6, 6, 7, 7, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11,
+ 7, 6, 7, 7, 8, 8, 9, 9, 9, 9, 10, 10, 10, 11, 11, 11,
+ 8, 7, 7, 8, 8, 8, 9, 9, 9, 9, 10, 10, 11, 11, 11, 12,
+ 9, 7, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 11, 11, 12, 12,
+ 9, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 10, 11, 11, 11, 12,
+ 9, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 12, 12, 12,
+ 9, 8, 9, 9, 9, 9, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12,
+ 10, 9, 9, 9, 10, 10, 10, 10, 10, 11, 11, 11, 11, 12, 13, 12,
+ 10, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 13,
+ 11, 10, 9, 10, 10, 10, 11, 11, 11, 11, 11, 11, 12, 12, 13, 13,
+ 11, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13,
+ 12, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 12, 13,
+ 12, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13
+];
+const MP3_HUFF16_BITS: [u16; 256] = [
+ 0x001, 0x005, 0x00E, 0x02C, 0x04A, 0x03F, 0x06E, 0x05D,
+ 0x0AC, 0x095, 0x08A, 0x0F2, 0x0E1, 0x0C3, 0x178, 0x011,
+ 0x003, 0x004, 0x00C, 0x014, 0x023, 0x03E, 0x035, 0x02F,
+ 0x053, 0x04B, 0x044, 0x077, 0x0C9, 0x06B, 0x0CF, 0x009,
+ 0x00F, 0x00D, 0x017, 0x026, 0x043, 0x03A, 0x067, 0x05A,
+ 0x0A1, 0x048, 0x07F, 0x075, 0x06E, 0x0D1, 0x0CE, 0x010,
+ 0x02D, 0x015, 0x027, 0x045, 0x040, 0x072, 0x063, 0x057,
+ 0x09E, 0x08C, 0x0FC, 0x0D4, 0x0C7, 0x183, 0x16D, 0x01A,
+ 0x04B, 0x024, 0x044, 0x041, 0x073, 0x065, 0x0B3, 0x0A4,
+ 0x09B, 0x108, 0x0F6, 0x0E2, 0x18B, 0x17E, 0x16A, 0x009,
+ 0x042, 0x01E, 0x03B, 0x038, 0x066, 0x0B9, 0x0AD, 0x109,
+ 0x08E, 0x0FD, 0x0E8, 0x190, 0x184, 0x17A, 0x1BD, 0x010,
+ 0x06F, 0x036, 0x034, 0x064, 0x0B8, 0x0B2, 0x0A0, 0x085,
+ 0x101, 0x0F4, 0x0E4, 0x0D9, 0x181, 0x16E, 0x2CB, 0x00A,
+ 0x062, 0x030, 0x05B, 0x058, 0x0A5, 0x09D, 0x094, 0x105,
+ 0x0F8, 0x197, 0x18D, 0x174, 0x17C, 0x379, 0x374, 0x008,
+ 0x055, 0x054, 0x051, 0x09F, 0x09C, 0x08F, 0x104, 0x0F9,
+ 0x1AB, 0x191, 0x188, 0x17F, 0x2D7, 0x2C9, 0x2C4, 0x007,
+ 0x09A, 0x04C, 0x049, 0x08D, 0x083, 0x100, 0x0F5, 0x1AA,
+ 0x196, 0x18A, 0x180, 0x2DF, 0x167, 0x2C6, 0x160, 0x00B,
+ 0x08B, 0x081, 0x043, 0x07D, 0x0F7, 0x0E9, 0x0E5, 0x0DB,
+ 0x189, 0x2E7, 0x2E1, 0x2D0, 0x375, 0x372, 0x1B7, 0x004,
+ 0x0F3, 0x078, 0x076, 0x073, 0x0E3, 0x0DF, 0x18C, 0x2EA,
+ 0x2E6, 0x2E0, 0x2D1, 0x2C8, 0x2C2, 0x0DF, 0x1B4, 0x006,
+ 0x0CA, 0x0E0, 0x0DE, 0x0DA, 0x0D8, 0x185, 0x182, 0x17D,
+ 0x16C, 0x378, 0x1BB, 0x2C3, 0x1B8, 0x1B5, 0x6C0, 0x004,
+ 0x2EB, 0x0D3, 0x0D2, 0x0D0, 0x172, 0x17B, 0x2DE, 0x2D3,
+ 0x2CA, 0x6C7, 0x373, 0x36D, 0x36C, 0xD83, 0x361, 0x002,
+ 0x179, 0x171, 0x066, 0x0BB, 0x2D6, 0x2D2, 0x166, 0x2C7,
+ 0x2C5, 0x362, 0x6C6, 0x367, 0xD82, 0x366, 0x1B2, 0x000,
+ 0x00C, 0x00A, 0x007, 0x00B, 0x00A, 0x011, 0x00B, 0x009,
+ 0x00D, 0x00C, 0x00A, 0x007, 0x005, 0x003, 0x001, 0x003
+];
+const MP3_HUFF16_LENS: [u8; 256] = [
+ 1, 4, 6, 8, 9, 9, 10, 10, 11, 11, 11, 12, 12, 12, 13, 9,
+ 3, 4, 6, 7, 8, 9, 9, 9, 10, 10, 10, 11, 12, 11, 12, 8,
+ 6, 6, 7, 8, 9, 9, 10, 10, 11, 10, 11, 11, 11, 12, 12, 9,
+ 8, 7, 8, 9, 9, 10, 10, 10, 11, 11, 12, 12, 12, 13, 13, 10,
+ 9, 8, 9, 9, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 9,
+ 9, 8, 9, 9, 10, 11, 11, 12, 11, 12, 12, 13, 13, 13, 14, 10,
+ 10, 9, 9, 10, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 14, 10,
+ 10, 9, 10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 13, 15, 15, 10,
+ 10, 10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 13, 14, 14, 14, 10,
+ 11, 10, 10, 11, 11, 12, 12, 13, 13, 13, 13, 14, 13, 14, 13, 11,
+ 11, 11, 10, 11, 12, 12, 12, 12, 13, 14, 14, 14, 15, 15, 14, 10,
+ 12, 11, 11, 11, 12, 12, 13, 14, 14, 14, 14, 14, 14, 13, 14, 11,
+ 12, 12, 12, 12, 12, 13, 13, 13, 13, 15, 14, 14, 14, 14, 16, 11,
+ 14, 12, 12, 12, 13, 13, 14, 14, 14, 16, 15, 15, 15, 17, 15, 11,
+ 13, 13, 11, 12, 14, 14, 13, 14, 14, 15, 16, 15, 17, 15, 14, 11,
+ 9, 8, 8, 9, 9, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 8
+];
+const MP3_HUFF24_BITS: [u16; 256] = [
+ 0x00F, 0x00D, 0x02E, 0x050, 0x092, 0x106, 0x0F8, 0x1B2,
+ 0x1AA, 0x29D, 0x28D, 0x289, 0x26D, 0x205, 0x408, 0x058,
+ 0x00E, 0x00C, 0x015, 0x026, 0x047, 0x082, 0x07A, 0x0D8,
+ 0x0D1, 0x0C6, 0x147, 0x159, 0x13F, 0x129, 0x117, 0x02A,
+ 0x02F, 0x016, 0x029, 0x04A, 0x044, 0x080, 0x078, 0x0DD,
+ 0x0CF, 0x0C2, 0x0B6, 0x154, 0x13B, 0x127, 0x21D, 0x012,
+ 0x051, 0x027, 0x04B, 0x046, 0x086, 0x07D, 0x074, 0x0DC,
+ 0x0CC, 0x0BE, 0x0B2, 0x145, 0x137, 0x125, 0x10F, 0x010,
+ 0x093, 0x048, 0x045, 0x087, 0x07F, 0x076, 0x070, 0x0D2,
+ 0x0C8, 0x0BC, 0x160, 0x143, 0x132, 0x11D, 0x21C, 0x00E,
+ 0x107, 0x042, 0x081, 0x07E, 0x077, 0x072, 0x0D6, 0x0CA,
+ 0x0C0, 0x0B4, 0x155, 0x13D, 0x12D, 0x119, 0x106, 0x00C,
+ 0x0F9, 0x07B, 0x079, 0x075, 0x071, 0x0D7, 0x0CE, 0x0C3,
+ 0x0B9, 0x15B, 0x14A, 0x134, 0x123, 0x110, 0x208, 0x00A,
+ 0x1B3, 0x073, 0x06F, 0x06D, 0x0D3, 0x0CB, 0x0C4, 0x0BB,
+ 0x161, 0x14C, 0x139, 0x12A, 0x11B, 0x213, 0x17D, 0x011,
+ 0x1AB, 0x0D4, 0x0D0, 0x0CD, 0x0C9, 0x0C1, 0x0BA, 0x0B1,
+ 0x0A9, 0x140, 0x12F, 0x11E, 0x10C, 0x202, 0x179, 0x010,
+ 0x14F, 0x0C7, 0x0C5, 0x0BF, 0x0BD, 0x0B5, 0x0AE, 0x14D,
+ 0x141, 0x131, 0x121, 0x113, 0x209, 0x17B, 0x173, 0x00B,
+ 0x29C, 0x0B8, 0x0B7, 0x0B3, 0x0AF, 0x158, 0x14B, 0x13A,
+ 0x130, 0x122, 0x115, 0x212, 0x17F, 0x175, 0x16E, 0x00A,
+ 0x28C, 0x15A, 0x0AB, 0x0A8, 0x0A4, 0x13E, 0x135, 0x12B,
+ 0x11F, 0x114, 0x107, 0x201, 0x177, 0x170, 0x16A, 0x006,
+ 0x288, 0x142, 0x13C, 0x138, 0x133, 0x12E, 0x124, 0x11C,
+ 0x10D, 0x105, 0x200, 0x178, 0x172, 0x16C, 0x167, 0x004,
+ 0x26C, 0x12C, 0x128, 0x126, 0x120, 0x11A, 0x111, 0x10A,
+ 0x203, 0x17C, 0x176, 0x171, 0x16D, 0x169, 0x165, 0x002,
+ 0x409, 0x118, 0x116, 0x112, 0x10B, 0x108, 0x103, 0x17E,
+ 0x17A, 0x174, 0x16F, 0x16B, 0x168, 0x166, 0x164, 0x000,
+ 0x02B, 0x014, 0x013, 0x011, 0x00F, 0x00D, 0x00B, 0x009,
+ 0x007, 0x006, 0x004, 0x007, 0x005, 0x003, 0x001, 0x003
+];
+const MP3_HUFF24_LENS: [u8; 256] = [
+ 4, 4, 6, 7, 8, 9, 9, 10, 10, 11, 11, 11, 11, 11, 12, 9,
+ 4, 4, 5, 6, 7, 8, 8, 9, 9, 9, 10, 10, 10, 10, 10, 8,
+ 6, 5, 6, 7, 7, 8, 8, 9, 9, 9, 9, 10, 10, 10, 11, 7,
+ 7, 6, 7, 7, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 7,
+ 8, 7, 7, 8, 8, 8, 8, 9, 9, 9, 10, 10, 10, 10, 11, 7,
+ 9, 7, 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 10, 7,
+ 9, 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 10, 11, 7,
+ 10, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 10, 11, 11, 8,
+ 10, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 8,
+ 10, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 11, 11, 11, 8,
+ 11, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 8,
+ 11, 10, 9, 9, 9, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 8,
+ 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 8,
+ 11, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 8,
+ 12, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 8,
+ 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 4
+];
+
+const MP3_HUFF_SYMS2: [u8; 4] = [ 0x00, 0x01, 0x10, 0x11 ];
+const MP3_HUFF_SYMS3: [u8; 9] = [ 0x00, 0x01, 0x02, 0x10, 0x11, 0x12, 0x20, 0x21, 0x22 ];
+const MP3_HUFF_SYMS4: [u8; 16] = [
+ 0x00, 0x01, 0x02, 0x03,
+ 0x10, 0x11, 0x12, 0x13,
+ 0x20, 0x21, 0x22, 0x23,
+ 0x30, 0x31, 0x32, 0x33
+];
+const MP3_HUFF_SYMS6: [u8; 36] = [
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55
+];
+const MP3_HUFF_SYMS8: [u8; 64] = [
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77
+];
+
+pub struct MP3Codebooks {
+ pub quad_cb: Codebook<u8>,
+ pub cb: [Codebook<u8>; 15],
+}
+
+fn map_cb2(idx: usize) -> u8 { MP3_HUFF_SYMS2[idx] }
+fn map_cb3(idx: usize) -> u8 { MP3_HUFF_SYMS3[idx] }
+fn map_cb4(idx: usize) -> u8 { MP3_HUFF_SYMS4[idx] }
+fn map_cb6(idx: usize) -> u8 { MP3_HUFF_SYMS6[idx] }
+fn map_cb8(idx: usize) -> u8 { MP3_HUFF_SYMS8[idx] }
+fn map_cb16(idx: usize) -> u8 { idx as u8 }
+
+macro_rules! init_cb {
+ ($bits: ident, $lens: ident, $map_cb: ident) => ({
+ let mut cbr = TableCodebookDescReader::new(&$bits, &$lens, $map_cb);
+ Codebook::new(&mut cbr, CodebookMode::MSB).unwrap()
+ })
+}
+
+impl MP3Codebooks {
+ pub fn new() -> Self {
+ let quad_cb = init_cb!(MP3_HUFF_QUAD_A_BITS, MP3_HUFF_QUAD_A_LENS, map_cb16);
+ let cb = [
+ init_cb!(MP3_HUFF1_BITS, MP3_HUFF1_LENS, map_cb2),
+ init_cb!(MP3_HUFF2_BITS, MP3_HUFF2_LENS, map_cb3),
+ init_cb!(MP3_HUFF3_BITS, MP3_HUFF3_LENS, map_cb3),
+ init_cb!(MP3_HUFF5_BITS, MP3_HUFF5_LENS, map_cb4),
+ init_cb!(MP3_HUFF6_BITS, MP3_HUFF6_LENS, map_cb4),
+ init_cb!(MP3_HUFF7_BITS, MP3_HUFF7_LENS, map_cb6),
+ init_cb!(MP3_HUFF8_BITS, MP3_HUFF8_LENS, map_cb6),
+ init_cb!(MP3_HUFF9_BITS, MP3_HUFF9_LENS, map_cb6),
+ init_cb!(MP3_HUFF10_BITS, MP3_HUFF10_LENS, map_cb8),
+ init_cb!(MP3_HUFF11_BITS, MP3_HUFF11_LENS, map_cb8),
+ init_cb!(MP3_HUFF12_BITS, MP3_HUFF12_LENS, map_cb8),
+ init_cb!(MP3_HUFF13_BITS, MP3_HUFF13_LENS, map_cb16),
+ init_cb!(MP3_HUFF15_BITS, MP3_HUFF15_LENS, map_cb16),
+ init_cb!(MP3_HUFF16_BITS, MP3_HUFF16_LENS, map_cb16),
+ init_cb!(MP3_HUFF24_BITS, MP3_HUFF24_LENS, map_cb16)
+ ];
+
+ Self { quad_cb, cb }
+ }
+ pub fn get_cb(&self, cb_id: u8) -> Option<(&Codebook<u8>, u8)> {
+ match cb_id {
+ 0 => None,
+ 1 => Some((&self.cb[0], 0)),
+ 2 => Some((&self.cb[1], 0)),
+ 3 => Some((&self.cb[2], 0)),
+ 5 => Some((&self.cb[3], 0)),
+ 6 => Some((&self.cb[4], 0)),
+ 7 => Some((&self.cb[5], 0)),
+ 8 => Some((&self.cb[6], 0)),
+ 9 => Some((&self.cb[7], 0)),
+ 10 => Some((&self.cb[8], 0)),
+ 11 => Some((&self.cb[9], 0)),
+ 12 => Some((&self.cb[10], 0)),
+ 13 => Some((&self.cb[11], 0)),
+ 15 => Some((&self.cb[12], 0)),
+ 16 => Some((&self.cb[13], 1)),
+ 17 => Some((&self.cb[13], 2)),
+ 18 => Some((&self.cb[13], 3)),
+ 19 => Some((&self.cb[13], 4)),
+ 20 => Some((&self.cb[13], 6)),
+ 21 => Some((&self.cb[13], 8)),
+ 22 => Some((&self.cb[13], 10)),
+ 23 => Some((&self.cb[13], 13)),
+ 24 => Some((&self.cb[14], 4)),
+ 25 => Some((&self.cb[14], 5)),
+ 26 => Some((&self.cb[14], 6)),
+ 27 => Some((&self.cb[14], 7)),
+ 28 => Some((&self.cb[14], 8)),
+ 29 => Some((&self.cb[14], 9)),
+ 30 => Some((&self.cb[14], 11)),
+ 31 => Some((&self.cb[14], 13)),
+ _ => unreachable!(),
+ }
+ }
+}