]> git.nihav.org Git - nihav.git/commitdiff
ATRAC3 decoder
authorKostya Shishkov <kostya.shishkov@gmail.com>
Thu, 18 Oct 2018 16:52:40 +0000 (18:52 +0200)
committerKostya Shishkov <kostya.shishkov@gmail.com>
Fri, 19 Oct 2018 15:20:39 +0000 (17:20 +0200)
Cargo.toml
src/codecs/atrac3.rs [new file with mode: 0644]
src/codecs/mod.rs

index 66f7f270d3bfb8209c532a9760d9a32f5778d498..d1fbd67bdbb87e600ba4d85b4a559a72891ff540 100644 (file)
@@ -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 (file)
index 0000000..ac3964d
--- /dev/null
@@ -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<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
+];
index b9b6f91a90b50cfc4af7fb3aaa62ba7ddc18583c..057542a06392609c2619321691e6b9b1d48825d7 100644 (file)
@@ -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 },
 ];