--- /dev/null
+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<u8>; 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<u8>; 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<u8>, 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<u8>, 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<NACodecInfo>,
+ channels: usize,
+ chmap: NAChannelMap,
+ samples: usize,
+ mode: Mode,
+ scrambled: bool,
+
+ codebooks: [Codebook<u8>; 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<u8>,
+}
+
+struct Atrac3CodebookReader {
+ bits: &'static [u8],
+ codes: &'static [u8],
+}
+impl CodebookDescReader<u8> 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<NACodecInfo>) -> 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<NAFrameRef> {
+ 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<NADecoder> {
+ 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
+];