From: Kostya Shishkov Date: Thu, 18 Oct 2018 16:52:40 +0000 (+0200) Subject: ATRAC3 decoder X-Git-Url: https://git.nihav.org/?p=nihav.git;a=commitdiff_plain;h=aab478c13f6e6c24c4b85f2293c7a58cd683c5a6 ATRAC3 decoder --- diff --git a/Cargo.toml b/Cargo.toml index 66f7f27..d1fbd67 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,9 +38,10 @@ all_audio_decoders = ["decoder_pcm", "decoder_imc", "decoders_real"] decoder_pcm = ["decoders"] decoder_ts102366 = ["decoders", "fft"] decoder_imc = ["decoders", "fft", "dsp_window"] -decoders_real = ["decoder_realaudio144", "decoder_realaudio288", "decoder_sipro", "decoder_ts102366", "decoder_cook", "decoder_ralf"] +decoders_real = ["decoder_realaudio144", "decoder_realaudio288", "decoder_sipro", "decoder_ts102366", "decoder_cook", "decoder_atrac3", "decoder_ralf"] decoder_realaudio144 = ["decoders"] decoder_realaudio288 = ["decoders"] decoder_sipro = ["decoders"] decoder_cook = ["decoders", "fft", "mdct"] +decoder_atrac3 = ["decoders", "mdct"] decoder_ralf = ["decoders"] diff --git a/src/codecs/atrac3.rs b/src/codecs/atrac3.rs new file mode 100644 index 0000000..ac3964d --- /dev/null +++ b/src/codecs/atrac3.rs @@ -0,0 +1,765 @@ +use formats::*; +use frame::*; +use super::*; +use io::bitreader::*; +use io::byteio::*; +use io::codebook::*; +use dsp::fft::FFTMode; +use dsp::mdct::IMDCT; +use std::f32::consts; + +#[derive(Clone,Copy,PartialEq)] +enum Mode { + Mono, + Stereo, + JointStereo, +} + +const ATRAC3_FRAME_SIZE: usize = 1024; + +#[derive(Clone,Copy)] +struct Tone { + pos: usize, + ncoeffs: usize, + coeffs: [f32; 8], +} + +struct GainData { + ngains: [usize; 4], + gain_lev: [[usize; 8]; 4], + gain_loc: [[usize; 8]; 4], +} + +impl GainData { + fn new() -> Self { + Self { + ngains: [0; 4], + gain_lev: [[0; 8]; 4], + gain_loc: [[0; 8]; 4], + } + } + fn read(&mut self, br: &mut BitReader, bands: usize) -> DecoderResult<()> { + self.ngains = [0; 4]; + for band in 0..bands { + self.ngains[band] = br.read(3)? as usize; + for i in 0..self.ngains[band] { + self.gain_lev[band][i] = br.read(4)? as usize; + self.gain_loc[band][i] = br.read(5)? as usize; + } + } + Ok(()) + } +} + +struct Channel { + data: [f32; ATRAC3_FRAME_SIZE], + delay: [f32; ATRAC3_FRAME_SIZE], + qmf_delay: [f32; 64 * 3], + + bands: usize, + block_no: usize, + + gain_data: [GainData; 2], + + subbands: usize, + components: usize, + ntones: usize, + tones: [Tone; 64], +} + +impl Channel { + fn new() -> Self { + Self { + data: [0.0; ATRAC3_FRAME_SIZE], + delay: [0.0; ATRAC3_FRAME_SIZE], + qmf_delay: [0.0; 64 * 3], + + bands: 0, + block_no: 0, + + gain_data: [GainData::new(), GainData::new()], + + subbands: 0, + components: 0, + ntones: 0, + tones: [Tone {pos: 0, ncoeffs: 0, coeffs: [0.0; 8]}; 64], + } + } + fn decode_unit(&mut self, br: &mut BitReader, codebooks: &[Codebook; 7], scalefactors: &[f32; 64]) -> DecoderResult<()> { + self.bands = (br.read(2)? as usize) + 1; + self.gain_data[self.block_no].read(br, self.bands)?; + self.data = [0.0; ATRAC3_FRAME_SIZE]; + + self.ntones = 0; + self.components = br.read(5)? as usize; + if self.components > 0 { + let selector = br.read(2)?; + validate!(selector != 2); + let mut mode0 = (selector & 1) != 0; + + for _ in 0..self.components { + let mut flags: [bool; 4] = [false; 4]; + for band in 0..self.bands { + flags[band] = br.read_bool()?; + } + let nvals = br.read(3)? as usize; + let quant = br.read(3)? as usize; + validate!(quant > 1); + if selector == 3 { + mode0 = br.read_bool()?; + } + for j in 0..self.bands*4 { + if !flags[j >> 2] { continue; } + let count = br.read(3)? as usize; + validate!(self.ntones + count < 64); + for _ in 0..count { + let scale_idx = br.read(6)? as usize; + let tone = &mut self.tones[self.ntones]; + tone.pos = (br.read(6)? as usize) + j * 64; + tone.ncoeffs = (ATRAC3_FRAME_SIZE - tone.pos).min(nvals + 1); + let scale = scalefactors[scale_idx] * ATRAC3_MAX_QUANT[quant]; + read_coeffs(br, codebooks, &mut tone.coeffs[..tone.ncoeffs], quant, scale, mode0)?; + self.ntones += 1; + } + } + } + } + + // spectrum + let mut quants: [usize; 32] = [0; 32]; + let mut scf: [usize; 32] = [0; 32]; + self.subbands = (br.read(5)? as usize) + 1; + let mode0 = br.read_bool()?; + for i in 0..self.subbands { + quants[i] = br.read(3)? as usize; + } + for i in 0..self.subbands { + if quants[i] == 0 { continue; } + scf[i] = br.read(6)? as usize; + } + + self.data = [0.0; ATRAC3_FRAME_SIZE]; + for i in 0..self.subbands { + if quants[i] == 0 { continue; } + let start = ATRAC3_SUBBANDS[i]; + let end = ATRAC3_SUBBANDS[i + 1]; + let scale = scalefactors[scf[i]] * ATRAC3_MAX_QUANT[quants[i]]; + read_coeffs(br, codebooks, &mut self.data[start..end], quants[i], scale, mode0)?; + } + + for i in 0..self.ntones { + let tone = &self.tones[i]; + for j in 0..tone.ncoeffs { + self.data[tone.pos + j] += tone.coeffs[j]; + } + } + Ok(()) + } + fn synth(&mut self, dsp: &mut DSP) { + let mut flag = 0; + let mut band = 0; + for (data, delay) in self.data.chunks_mut(256).zip(self.delay.chunks_mut(256)) { + if (flag & 1) != 0 { + for i in 0..128 { + let t0 = data[i]; + let t1 = data[255 - i]; + data[i] = t1; + data[255 - i] = t0; + } + } + dsp.synth_band(data); + dsp.apply_gains(data, delay, &mut self.gain_data, self.block_no, band); + delay.copy_from_slice(&dsp.tmp[256..512]); + flag ^= 1; + band += 1; + } + self.block_no ^= 1; + } + fn do_qmf(&mut self, dsp: &mut DSP, dst: &mut [f32]) { + let mut qchunks = self.qmf_delay.chunks_mut(64); + let qmf0 = qchunks.next().unwrap(); + let qmf1 = qchunks.next().unwrap(); + let qmf2 = qchunks.next().unwrap(); + { + let mut tchunks = self.data.chunks_mut(512); + let tmp0 = tchunks.next().unwrap(); + let tmp1 = tchunks.next().unwrap(); + dsp.do_qmf(tmp0, qmf0, false); + dsp.do_qmf(tmp1, qmf1, true); + } + dsp.do_qmf_out(dst, &self.data, qmf2); + } +} + +const ATRAC3_DEFAULT_DELAY: usize = 2190; +const ATRAC3_WEIGHTING_DELAYS: [u8; 6] = [ 0, 7, 0, 7, 0, 7 ]; + +fn read_coeffs(br: &mut BitReader, cb: &[Codebook; 7], dst: &mut [f32], quant: usize, scale: f32, mode0: bool) -> DecoderResult<()> { + if mode0 { + read_coeffs_mode0(br, dst, quant, scale) + } else if quant == 1 { + read_coeffs_mode1(br, &cb[0], dst, scale) + } else { + read_coeffs_other(br, &cb[quant - 1], dst, scale) + } +} + +const ATRAC3_MODE0_CB: [f32; 4] = [ 0.0, 1.0, -2.0, -1.0 ]; +const ATRAC3_MODE0_BITS: [u8; 8] = [ 0, 4, 3, 3, 4, 4, 5, 6 ]; + +fn read_coeffs_mode0(br: &mut BitReader, dst: &mut [f32], quant: usize, scale: f32) -> DecoderResult<()> { + let bits = ATRAC3_MODE0_BITS[quant]; + if bits > 0 { + for i in 0..dst.len() { + let val = br.read_s(bits)? as f32; + dst[i] = val * scale; + } + } else { + for i in (0..dst.len()).step_by(2) { + let val = br.read(4)? as usize; + dst[i + 0] = ATRAC3_MODE0_CB[val >> 2] * scale; + dst[i + 1] = ATRAC3_MODE0_CB[val & 3] * scale; + } + } + Ok(()) +} + +const ATRAC3_MODE1_CB: [f32; 9 * 2] = [ + 0.0, 0.0, + 0.0, 1.0, + 0.0, -1.0, + 1.0, 0.0, + -1.0, 0.0, + 1.0, 1.0, + 1.0, -1.0, + -1.0, 1.0, + -1.0, -1.0 +]; + +fn read_coeffs_mode1(br: &mut BitReader, cb: &Codebook, dst: &mut [f32], scale: f32) -> DecoderResult<()> { + for i in (0..dst.len()).step_by(2) { + let val = br.read_cb(cb)? as usize; + dst[i + 0] = ATRAC3_MODE1_CB[val * 2 + 0] * scale; + dst[i + 1] = ATRAC3_MODE1_CB[val * 2 + 1] * scale; + } + Ok(()) +} + +fn read_coeffs_other(br: &mut BitReader, cb: &Codebook, dst: &mut [f32], scale: f32) -> DecoderResult<()> { + for i in 0..dst.len() { + let val = (br.read_cb(cb)? as i8) + 1; + let sign = (val & 1) != 0; + let coef = (if sign { -(val >> 1) } else { val >> 1 }) as f32; + dst[i] = coef * scale; + } + Ok(()) +} + +struct DSP { + imdct: IMDCT, + window: [f32; 512], + gain_tab: [f32; 16], + gain_tab2: [f32; 32], + tmp: [f32; ATRAC3_FRAME_SIZE + 64], +} + +impl DSP { + fn new() -> Self { + let mut gain_tab: [f32; 16] = [0.0; 16]; + let mut gain_tab2: [f32; 32] = [0.0; 32]; + + for i in 0..16 { + gain_tab[i] = 2.0f32.powf(4.0 - (i as f32)); + } + for i in 0..32 { + gain_tab2[i] = 2.0f32.powf(((i as f32) - 15.0) * -0.125); + } + + let mut tmpw: [f32; 256] = [0.0; 256]; + for i in 0..tmpw.len() { + tmpw[i] = (((((i as f32) + 0.5) / 256.0 - 0.5) * consts::PI).sin() + 1.0) * 0.5; + } + + let mut window: [f32; 512] = [0.0; 512]; + for i in 0..tmpw.len() { + let w = tmpw[i] / (tmpw[i] * tmpw[i] + tmpw[255 - i] * tmpw[255 - i]); + window[i] = w; + window[512 - 1 - i] = w; + } + + Self { + imdct: IMDCT::new(FFTMode::SplitRadix, 512), + tmp: [0.0; ATRAC3_FRAME_SIZE + 64], + gain_tab, gain_tab2, window, + } + } + fn synth_band(&mut self, src: &[f32]) { + let dst = &mut self.tmp; + self.imdct.imdct(src, dst); + for i in 0..512 { + dst[i] *= self.window[i]; + } + } + fn apply_gains(&mut self, dst: &mut [f32], delay: &[f32], gain_data: &mut [GainData; 2], block_no: usize, band: usize) { + let prev_ngains = gain_data[block_no ^ 1].ngains[band]; + let gain1 = if gain_data[block_no].ngains[band] > 0 { + self.gain_tab[gain_data[block_no].gain_lev[band][0]] + } else { 1.0 }; + + if prev_ngains == 0 { + for i in 0..256 { + dst[i] = self.tmp[i] * gain1 + delay[i]; + } + return; + } + + gain_data[block_no ^ 1].gain_lev[band][prev_ngains] = 4; + gain_data[block_no ^ 1].gain_loc[band][prev_ngains] = 32; + + let mut off = 0; + for i in 0..prev_ngains { + let start = gain_data[block_no ^ 1].gain_loc[band][i] * 8; + let end = start + 8; + + let mut gain2 = self.gain_tab [gain_data[block_no ^ 1].gain_lev[band][i]]; + let gain_inc = self.gain_tab2[gain_data[block_no ^ 1].gain_lev[band][i + 1] + 15 - + gain_data[block_no ^ 1].gain_lev[band][i]]; + + while off < start { + dst[off] = (self.tmp[off] * gain1 + delay[off]) * gain2; + off += 1; + } + while off < end { + dst[off] = (self.tmp[off] * gain1 + delay[off]) * gain2; + gain2 *= gain_inc; + off += 1; + } + } + for i in off..256 { + dst[i] = self.tmp[i] * gain1 + delay[i]; + } + } + fn qmf_prepare(&mut self, src: &[f32], delay: &[f32], size: usize, swap: bool) { + for i in 0..46 { + self.tmp[i] = delay[i]; + } + let (s0, s1) = if !swap { + (&src[0..], &src[size/2..]) + } else { + (&src[size/2..], &src[0..]) + }; + for i in (0..size).step_by(4) { + self.tmp[46 + i + 0] = s0[i / 2 + 0] + s1[i / 2 + 0]; + self.tmp[46 + i + 1] = s0[i / 2 + 0] - s1[i / 2 + 0]; + self.tmp[46 + i + 2] = s0[i / 2 + 1] + s1[i / 2 + 1]; + self.tmp[46 + i + 3] = s0[i / 2 + 1] - s1[i / 2 + 1]; + } + } + fn qmf_synth(&mut self, dst: &mut [f32], size: usize) { + for i in (0..size).step_by(2) { + let mut acc0 = 0.0; + let mut acc1 = 0.0; + + for j in (0..ATRAC3_QMF_FILTER.len()).step_by(2) { + acc0 += self.tmp[i + j + 0] * ATRAC3_QMF_FILTER[j + 0]; + acc1 += self.tmp[i + j + 1] * ATRAC3_QMF_FILTER[j + 1]; + } + dst[i + 0] = acc1 * consts::SQRT_2 / 256.0; + dst[i + 1] = acc0 * consts::SQRT_2 / 256.0; + } + } + fn do_qmf(&mut self, dst: &mut [f32], delay: &mut [f32], swap: bool) { + self.qmf_prepare(dst, delay, 512, swap); + self.qmf_synth(dst, 512); + for i in 0..46 { + delay[i] = self.tmp[512 + i]; + } + } + fn do_qmf_out(&mut self, dst: &mut [f32], src: &[f32], delay: &mut [f32]) { + self.qmf_prepare(src, delay, 1024, false); + self.qmf_synth(dst, 1024); + for i in 0..46 { + delay[i] = self.tmp[1024 + i]; + } + } +} + +struct Atrac3Decoder { + info: Rc, + channels: usize, + chmap: NAChannelMap, + samples: usize, + mode: Mode, + scrambled: bool, + + codebooks: [Codebook; 7], + dsp: DSP, + ch_data: [Channel; 2], + scalefactors: [f32; 64], + + mci_prev: [usize; 4], + mci_cur: [usize; 4], + mci_next: [usize; 4], + + weighting_delay: [u8; 6], + + pkt_buf: Vec, +} + +struct Atrac3CodebookReader { + bits: &'static [u8], + codes: &'static [u8], +} +impl CodebookDescReader for Atrac3CodebookReader { + fn bits(&mut self, idx: usize) -> u8 { self.bits[idx] } + fn code(&mut self, idx: usize) -> u32 { self.codes[idx] as u32 } + fn sym (&mut self, idx: usize) -> u8 { idx as u8 } + fn len(&mut self) -> usize { self.bits.len() } +} + +impl Atrac3Decoder { + fn new() -> Self { + let mut scalefactors: [f32; 64] = [0.0; 64]; + for i in 0..scalefactors.len() { + scalefactors[i] = 2.0f32.powf(((i as f32) - 15.0) / 3.0); + } + + let mut cb0 = Atrac3CodebookReader { codes: ATRAC3_HUFF_CODES[0], bits: ATRAC3_HUFF_BITS[0] }; + let mut cb1 = Atrac3CodebookReader { codes: ATRAC3_HUFF_CODES[1], bits: ATRAC3_HUFF_BITS[1] }; + let mut cb2 = Atrac3CodebookReader { codes: ATRAC3_HUFF_CODES[2], bits: ATRAC3_HUFF_BITS[2] }; + let mut cb3 = Atrac3CodebookReader { codes: ATRAC3_HUFF_CODES[3], bits: ATRAC3_HUFF_BITS[3] }; + let mut cb4 = Atrac3CodebookReader { codes: ATRAC3_HUFF_CODES[4], bits: ATRAC3_HUFF_BITS[4] }; + let mut cb5 = Atrac3CodebookReader { codes: ATRAC3_HUFF_CODES[5], bits: ATRAC3_HUFF_BITS[5] }; + let mut cb6 = Atrac3CodebookReader { codes: ATRAC3_HUFF_CODES[6], bits: ATRAC3_HUFF_BITS[6] }; + Self { + info: NACodecInfo::new_dummy(), + chmap: NAChannelMap::new(), + channels: 0, + samples: 0, + mode: Mode::Mono, + scrambled: false, + + dsp: DSP::new(), + ch_data: [Channel::new(), Channel::new()], + codebooks: [Codebook::new(&mut cb0, CodebookMode::MSB).unwrap(), + Codebook::new(&mut cb1, CodebookMode::MSB).unwrap(), + Codebook::new(&mut cb2, CodebookMode::MSB).unwrap(), + Codebook::new(&mut cb3, CodebookMode::MSB).unwrap(), + Codebook::new(&mut cb4, CodebookMode::MSB).unwrap(), + Codebook::new(&mut cb5, CodebookMode::MSB).unwrap(), + Codebook::new(&mut cb6, CodebookMode::MSB).unwrap() ], + + mci_prev: [3; 4], + mci_cur: [3; 4], + mci_next: [3; 4], + + weighting_delay: ATRAC3_WEIGHTING_DELAYS, + pkt_buf: Vec::with_capacity(65536), + scalefactors, + } + } + fn rev_matrix(&mut self) { + for i in 0..4 { + let c0 = self.mci_prev[i]; + let c1 = self.mci_cur[i]; + let off; + if c0 != c1 { + let l0 = ATRAC3_MATRIX_COEFFS[c0 * 2 + 0]; + let r0 = ATRAC3_MATRIX_COEFFS[c1 * 2 + 0]; + let l1 = ATRAC3_MATRIX_COEFFS[c0 * 2 + 1]; + let r1 = ATRAC3_MATRIX_COEFFS[c1 * 2 + 1]; + for idx in 0..8 { + let t0 = self.ch_data[0].data[idx + i * 256]; + let t1 = self.ch_data[1].data[idx + i * 256]; + let n1 = t0 * interp(l0, r0, idx) + t1 * interp(l1, r1, idx); + self.ch_data[0].data[idx + i * 256] = n1; + self.ch_data[1].data[idx + i * 256] = t0 * 2.0 - n1; + } + off = i * 256 + 8; + } else { + off = i * 256; + } + match c1 { + 0 => { + for i in off..256 { + let t0 = self.ch_data[0].data[i]; + let t1 = self.ch_data[1].data[i]; + self.ch_data[0].data[i] = t1 * 2.0; + self.ch_data[1].data[i] = (t0 - t1) * 2.0; + } + }, + 1 => { + for i in off..256 { + let t0 = self.ch_data[0].data[i]; + let t1 = self.ch_data[1].data[i]; + self.ch_data[0].data[i] = (t0 + t1) * 2.0; + self.ch_data[1].data[i] = t1 * -2.0; + } + }, + _ => { + for i in off..256 { + let t0 = self.ch_data[0].data[i]; + let t1 = self.ch_data[1].data[i]; + self.ch_data[0].data[i] = t0 + t1; + self.ch_data[1].data[i] = t0 - t1; + } + }, + }; + } + } + fn weigh_channels(&mut self) { + if (self.weighting_delay[1] == 7) && (self.weighting_delay[3] == 7) { return; } + let pw: [f32; 2]; + if self.weighting_delay[1] == 7 { + pw = [1.0; 2]; + } else { + let w = (self.weighting_delay[1] as f32) / 7.0; + let iw = (2.0 - w * w).sqrt(); + if self.weighting_delay[0] == 0 { + pw = [w, iw]; + } else { + pw = [iw, w]; + } + } + let cw: [f32; 2]; + if self.weighting_delay[3] == 7 { + cw = [1.0; 2]; + } else { + let w = (self.weighting_delay[3] as f32) / 7.0; + let iw = (2.0 - w * w).sqrt(); + if self.weighting_delay[2] == 0 { + cw = [w, iw]; + } else { + cw = [iw, w]; + } + } + + for i in 0..4 { + let off = i * 256; + for j in 0..8 { + self.ch_data[0].data[off + j] *= interp(pw[0], pw[1], j); + self.ch_data[1].data[off + j] *= interp(pw[0], pw[1], j); + } + for j in 8..256 { + self.ch_data[0].data[off + j] *= cw[0]; + self.ch_data[1].data[off + j] *= cw[1]; + } + } + } +} + +fn interp(a: f32, b: f32, pos: usize) -> f32 { + a + ((pos as f32) / 8.0) * (b - a) +} + +impl NADecoder for Atrac3Decoder { + fn init(&mut self, info: Rc) -> DecoderResult<()> { + if let NACodecTypeInfo::Audio(ainfo) = info.get_properties() { + self.info = info.clone(); + let edata = info.get_extradata().unwrap(); + validate!(edata.len() >= 4); + + let mut mr = MemoryReader::new_read(&edata); + let mut br = ByteReader::new(&mut mr); + + match edata.len() { + 10 => { + let version = br.read_u32be()?; + validate!(version == 4); + self.samples = br.read_u16be()? as usize; + let delay = br.read_u16be()? as usize; + validate!(delay == ATRAC3_DEFAULT_DELAY); + let mode = br.read_u16be()?; + self.mode = match mode { + 0 => Mode::Mono, + 2 => Mode::Stereo, + 0x12 => Mode::JointStereo, + _ => return Err(DecoderError::InvalidData), + }; + self.channels = if self.mode == Mode::Mono { 1 } else { 2 }; + self.scrambled = true; + }, + 14 | 16 => { + if edata.len() == 16 { br.read_skip(2)?; } + self.samples = br.read_u32be()? as usize; + let mode = br.read_u16be()?; + self.mode = if mode != 0 { Mode::JointStereo } else { Mode::Stereo }; + self.channels = 2; + br.read_skip(2)?; + let ffactor = br.read_u16be()? as usize; + validate!((ffactor > 0) && (ffactor <= 16)); + // calculate block_align / channels / ffactor, validate it's 96/152/192 + }, + _ => { return Err(DecoderError::InvalidData) } + }; + validate!(self.samples == ATRAC3_FRAME_SIZE * self.channels); + if self.mode == Mode::Mono { + self.chmap.add_channel(NAChannelType::C); + } else { + self.chmap.add_channel(NAChannelType::L); + self.chmap.add_channel(NAChannelType::R); + } + let ainfo = NAAudioInfo::new(ainfo.get_sample_rate(), self.channels as u8, + SND_F32P_FORMAT, self.samples); + self.info = info.replace_info(NACodecTypeInfo::Audio(ainfo)); + Ok(()) + } else { + Err(DecoderError::InvalidData) + } + } + fn decode(&mut self, pkt: &NAPacket) -> DecoderResult { + let info = pkt.get_stream().get_info(); + validate!(info.get_properties().is_audio()); + let pktbuf = pkt.get_buffer(); + validate!(pktbuf.len() > 5); + + let frame_size = pktbuf.len(); + self.pkt_buf.resize(frame_size, 0); + if self.scrambled { + for (i, s) in pktbuf.iter().enumerate() { + self.pkt_buf[i] = s ^ ATRAC3_XOR_KEY[i & 3]; + } + } else { + let dst = &mut self.pkt_buf[0..frame_size]; + dst.copy_from_slice(pktbuf.as_slice()); + } + + { + let mut br = BitReader::new(self.pkt_buf.as_slice(), frame_size, BitReaderMode::BE); + let id = br.read(6)?; + validate!(id == 0x28); + self.ch_data[0].decode_unit(&mut br, &self.codebooks, &self.scalefactors)?; + self.ch_data[0].synth(&mut self.dsp); + } + if self.channels == 2 { + let off; + if self.mode == Mode::JointStereo { + for i in 0..frame_size / 2 { + let b0 = self.pkt_buf[i]; + let b1 = self.pkt_buf[frame_size - i - 1]; + self.pkt_buf[i] = b1; + self.pkt_buf[frame_size - i - 1] = b0; + } + let mut i = 0; + while (i < frame_size) && (self.pkt_buf[i] == 0xF8) { i += 1; } + validate!(frame_size - i > 4); + off = i; + } else { + off = frame_size / 2; + } + let mut br = BitReader::new(&self.pkt_buf[off..], frame_size - off, BitReaderMode::BE); + if self.mode == Mode::JointStereo { + let id = br.read(2)?; + validate!(id == 0x3); + } else { + let id = br.read(6)?; + validate!(id == 0x28); + } + if self.mode == Mode::JointStereo { + for i in 0..self.weighting_delay.len() - 2 { + self.weighting_delay[i] = self.weighting_delay[i + 2]; + } + self.weighting_delay[4] = br.read(1)? as u8; + self.weighting_delay[5] = br.read(3)? as u8; + self.mci_prev = self.mci_cur; + self.mci_cur = self.mci_next; + for i in 0..4 { + self.mci_next[i] = br.read(2)? as usize; + } + } + self.ch_data[1].decode_unit(&mut br, &self.codebooks, &self.scalefactors)?; + self.ch_data[1].synth(&mut self.dsp); + } + if self.mode == Mode::JointStereo { + self.rev_matrix(); + self.weigh_channels(); + } + + let ainfo = self.info.get_properties().get_audio_info().unwrap(); + + let mut abuf = alloc_audio_buffer(ainfo, ATRAC3_FRAME_SIZE, self.chmap.clone())?; + let mut adata = abuf.get_abuf_f32().unwrap(); + let mut output = adata.get_data_mut(); + + for ch in 0..self.channels { + let dpos = abuf.get_offset(ch); + self.ch_data[ch].do_qmf(&mut self.dsp, &mut output[dpos..][..ATRAC3_FRAME_SIZE]); + } + + let mut frm = NAFrame::new_from_pkt(pkt, self.info.replace_info(NACodecTypeInfo::Audio(ainfo)), abuf); + frm.set_keyframe(true); + Ok(Rc::new(RefCell::new(frm))) + } +} + +pub fn get_decoder() -> Box { + Box::new(Atrac3Decoder::new()) +} + +#[cfg(test)] +mod test { + use test::dec_video::*; + #[test] + fn test_atrac3() { + let file = "assets/RV/rv30_atrc_384x208_realproducer_plus_8.51.rm"; +// let file = "assets/RV/rv20_svt_atrc_640x352_realproducer_plus_8.51.rm"; + test_decode_audio("realmedia", file, Some(12000), "atrac3"); + } +} + +const ATRAC3_XOR_KEY: [u8; 4] = [ 0x53, 0x7F, 0x61, 0x03 ]; + +const ATRAC3_HUFF_CODES: [&[u8]; 7] = [ + &[ 0x00, 0x04, 0x05, 0x0C, 0x0D, 0x1C, 0x1D, 0x1E, 0x1F ], + &[ 0x00, 0x04, 0x05, 0x06, 0x07 ], + &[ 0x00, 0x04, 0x05, 0x0C, 0x0D, 0x0E, 0x0F ], + &[ 0x00, 0x04, 0x05, 0x0C, 0x0D, 0x1C, 0x1D, 0x1E, 0x1F ], // same as 0 + &[ 0x00, 0x02, 0x03, 0x08, 0x09, 0x0A, 0x0B, 0x1C, 0x1D, 0x3C, 0x3D, 0x3E, 0x3F, 0x0C, 0x0D ], + &[ 0x00, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x14, + 0x15, 0x16, 0x17, 0x18, 0x19, 0x34, 0x35, 0x36, + 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x78, 0x79, 0x7A, + 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x08, 0x09 ], + &[ 0x00, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, + 0x0F, 0x10, 0x11, 0x24, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, + 0x31, 0x32, 0x33, 0x68, 0x69, 0x6A, 0x6B, 0x6C, + 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, + 0x75, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, + 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, + 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 0x02, 0x03 ] +]; +const ATRAC3_HUFF_BITS: [&[u8]; 7] = [ + &[ 1, 3, 3, 4, 4, 5, 5, 5, 5 ], + &[ 1, 3, 3, 3, 3 ], + &[ 1, 3, 3, 4, 4, 4, 4 ], + &[ 1, 3, 3, 4, 4, 5, 5, 5, 5 ], + &[ 2, 3, 3, 4, 4, 4, 4, 5, 5, 6, 6, 6, 6, 4, 4 ], + &[ 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 4, 4 ], + &[ 3, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 4, 4 ], +]; + +const ATRAC3_MAX_QUANT: [f32; 8] = [ 0.0, 1.0/1.5, 1.0/2.5, 1.0/3.5, 1.0/4.5, 1.0/7.5, 1.0/15.5, 1.0/31.5 ]; + +const ATRAC3_SUBBANDS: [usize; 32 + 1] = [ + 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, + 192, 224, 256, 288, 320, 352, 384, 416, 448, 480, 512, 576, 640, 704, 768, 896, + 1024 +]; + +const ATRAC3_MATRIX_COEFFS: [f32; 8] = [ 0.0, 2.0, 2.0, 2.0, 0.0, 0.0, 1.0, 1.0 ]; + +const ATRAC3_QMF_FILTER: [f32; 48] = [ + -0.000029238139, -0.000184109580, -0.000112315138, 0.000602345390, + 0.000484503806, -0.001705877949, -0.001041114796, 0.004068033770, + 0.001566677820, -0.008430772461, -0.001512299757, 0.015680588782, + -0.000122339843, -0.026883240789, 0.004925364163, 0.043472178280, + -0.015603342094, -0.068180441856, 0.037618979812, 0.108652018011, + -0.087192758918, -0.198768734932, 0.264158189297, 0.928483188152, + 0.928483188152, 0.264158189297, -0.198768734932, -0.087192758918, + 0.108652018011, 0.037618979812, -0.068180441856, -0.015603342094, + 0.043472178280, 0.004925364163, -0.026883240789, -0.000122339843, + 0.015680588782, -0.001512299757, -0.008430772461, 0.001566677820, + 0.004068033770, -0.001041114796, -0.001705877949, 0.000484503806, + 0.000602345390, -0.000112315138, -0.000184109580, -0.000029238139 +]; diff --git a/src/codecs/mod.rs b/src/codecs/mod.rs index b9b6f91..057542a 100644 --- a/src/codecs/mod.rs +++ b/src/codecs/mod.rs @@ -249,6 +249,8 @@ mod h263; #[cfg(any(feature="decoder_realvideo3", feature="decoder_realvideo4", feature="decoder_realvideo6", feature="decoder_realaudio144", feature="decoder_realaudio288", feature="decoder_cook", feature="decoder_ralf"))] mod real; +#[cfg(feature="decoder_atrac3")] +mod atrac3; #[cfg(feature="decoder_pcm")] mod pcm; #[cfg(feature="decoder_sipro")] @@ -300,6 +302,8 @@ const DECODERS: &[DecoderInfo] = &[ DecoderInfo { name: "ac3", get_decoder: ts102366::get_decoder }, #[cfg(feature="decoder_cook")] DecoderInfo { name: "cook", get_decoder: real::cook::get_decoder }, +#[cfg(feature="decoder_atrac3")] + DecoderInfo { name: "atrac3", get_decoder: atrac3::get_decoder }, #[cfg(feature="decoder_ralf")] DecoderInfo { name: "ralf", get_decoder: real::ralf::get_decoder }, ];