view atrac3.c @ 6624:2dc587201e38 libavcodec

Change k limiting code, i think the code was buggy. If you have ALAC files TEST them! Mine produce the same md5 but the new code is not identical if limiting does happen.
author michael
date Thu, 17 Apr 2008 03:00:08 +0000
parents d155d4915e1c
children a4104482ceef
line wrap: on
line source

/*
 * Atrac 3 compatible decoder
 * Copyright (c) 2006-2007 Maxim Poliakovski
 * Copyright (c) 2006-2007 Benjamin Larsson
 *
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * FFmpeg is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with FFmpeg; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

/**
 * @file atrac3.c
 * Atrac 3 compatible decoder.
 * This decoder handles RealNetworks, RealAudio atrc data.
 * Atrac 3 is identified by the codec name atrc in RealMedia files.
 *
 * To use this decoder, a calling application must supply the extradata
 * bytes provided from the RealMedia container: 10 bytes or 14 bytes
 * from the WAV container.
 */

#include <math.h>
#include <stddef.h>
#include <stdio.h>

#include "avcodec.h"
#include "bitstream.h"
#include "dsputil.h"
#include "bytestream.h"

#include "atrac3data.h"

#define JOINT_STEREO    0x12
#define STEREO          0x2


/* These structures are needed to store the parsed gain control data. */
typedef struct {
    int   num_gain_data;
    int   levcode[8];
    int   loccode[8];
} gain_info;

typedef struct {
    gain_info   gBlock[4];
} gain_block;

typedef struct {
    int     pos;
    int     numCoefs;
    float   coef[8];
} tonal_component;

typedef struct {
    int               bandsCoded;
    int               numComponents;
    tonal_component   components[64];
    float             prevFrame[1024];
    int               gcBlkSwitch;
    gain_block        gainBlock[2];

    DECLARE_ALIGNED_16(float, spectrum[1024]);
    DECLARE_ALIGNED_16(float, IMDCT_buf[1024]);

    float             delayBuf1[46]; ///<qmf delay buffers
    float             delayBuf2[46];
    float             delayBuf3[46];
} channel_unit;

typedef struct {
    GetBitContext       gb;
    //@{
    /** stream data */
    int                 channels;
    int                 codingMode;
    int                 bit_rate;
    int                 sample_rate;
    int                 samples_per_channel;
    int                 samples_per_frame;

    int                 bits_per_frame;
    int                 bytes_per_frame;
    int                 pBs;
    channel_unit*       pUnits;
    //@}
    //@{
    /** joint-stereo related variables */
    int                 matrix_coeff_index_prev[4];
    int                 matrix_coeff_index_now[4];
    int                 matrix_coeff_index_next[4];
    int                 weighting_delay[6];
    //@}
    //@{
    /** data buffers */
    float               outSamples[2048];
    uint8_t*            decoded_bytes_buffer;
    float               tempBuf[1070];
    DECLARE_ALIGNED_16(float,mdct_tmp[512]);
    //@}
    //@{
    /** extradata */
    int                 atrac3version;
    int                 delay;
    int                 scrambled_stream;
    int                 frame_factor;
    //@}
} ATRAC3Context;

static DECLARE_ALIGNED_16(float,mdct_window[512]);
static float            qmf_window[48];
static VLC              spectral_coeff_tab[7];
static float            SFTable[64];
static float            gain_tab1[16];
static float            gain_tab2[31];
static MDCTContext      mdct_ctx;
static DSPContext       dsp;


/* quadrature mirror synthesis filter */

/**
 * Quadrature mirror synthesis filter.
 *
 * @param inlo      lower part of spectrum
 * @param inhi      higher part of spectrum
 * @param nIn       size of spectrum buffer
 * @param pOut      out buffer
 * @param delayBuf  delayBuf buffer
 * @param temp      temp buffer
 */


static void iqmf (float *inlo, float *inhi, unsigned int nIn, float *pOut, float *delayBuf, float *temp)
{
    int   i, j;
    float   *p1, *p3;

    memcpy(temp, delayBuf, 46*sizeof(float));

    p3 = temp + 46;

    /* loop1 */
    for(i=0; i<nIn; i+=2){
        p3[2*i+0] = inlo[i  ] + inhi[i  ];
        p3[2*i+1] = inlo[i  ] - inhi[i  ];
        p3[2*i+2] = inlo[i+1] + inhi[i+1];
        p3[2*i+3] = inlo[i+1] - inhi[i+1];
    }

    /* loop2 */
    p1 = temp;
    for (j = nIn; j != 0; j--) {
        float s1 = 0.0;
        float s2 = 0.0;

        for (i = 0; i < 48; i += 2) {
            s1 += p1[i] * qmf_window[i];
            s2 += p1[i+1] * qmf_window[i+1];
        }

        pOut[0] = s2;
        pOut[1] = s1;

        p1 += 2;
        pOut += 2;
    }

    /* Update the delay buffer. */
    memcpy(delayBuf, temp + nIn*2, 46*sizeof(float));
}

/**
 * Regular 512 points IMDCT without overlapping, with the exception of the swapping of odd bands
 * caused by the reverse spectra of the QMF.
 *
 * @param pInput    float input
 * @param pOutput   float output
 * @param odd_band  1 if the band is an odd band
 * @param mdct_tmp  aligned temporary buffer for the mdct
 */

static void IMLT(float *pInput, float *pOutput, int odd_band, float* mdct_tmp)
{
    int     i;

    if (odd_band) {
        /**
        * Reverse the odd bands before IMDCT, this is an effect of the QMF transform
        * or it gives better compression to do it this way.
        * FIXME: It should be possible to handle this in ff_imdct_calc
        * for that to happen a modification of the prerotation step of
        * all SIMD code and C code is needed.
        * Or fix the functions before so they generate a pre reversed spectrum.
        */

        for (i=0; i<128; i++)
            FFSWAP(float, pInput[i], pInput[255-i]);
    }

    mdct_ctx.fft.imdct_calc(&mdct_ctx,pOutput,pInput,mdct_tmp);

    /* Perform windowing on the output. */
    dsp.vector_fmul(pOutput,mdct_window,512);

}


/**
 * Atrac 3 indata descrambling, only used for data coming from the rm container
 *
 * @param in        pointer to 8 bit array of indata
 * @param bits      amount of bits
 * @param out       pointer to 8 bit array of outdata
 */

static int decode_bytes(const uint8_t* inbuffer, uint8_t* out, int bytes){
    int i, off;
    uint32_t c;
    const uint32_t* buf;
    uint32_t* obuf = (uint32_t*) out;

    off = (int)((long)inbuffer & 3);
    buf = (const uint32_t*) (inbuffer - off);
    c = be2me_32((0x537F6103 >> (off*8)) | (0x537F6103 << (32-(off*8))));
    bytes += 3 + off;
    for (i = 0; i < bytes/4; i++)
        obuf[i] = c ^ buf[i];

    if (off)
        av_log(NULL,AV_LOG_DEBUG,"Offset of %d not handled, post sample on ffmpeg-dev.\n",off);

    return off;
}


static void init_atrac3_transforms(ATRAC3Context *q) {
    float enc_window[256];
    float s;
    int i;

    /* Generate the mdct window, for details see
     * http://wiki.multimedia.cx/index.php?title=RealAudio_atrc#Windows */
    for (i=0 ; i<256; i++)
        enc_window[i] = (sin(((i + 0.5) / 256.0 - 0.5) * M_PI) + 1.0) * 0.5;

    if (!mdct_window[0])
        for (i=0 ; i<256; i++) {
            mdct_window[i] = enc_window[i]/(enc_window[i]*enc_window[i] + enc_window[255-i]*enc_window[255-i]);
            mdct_window[511-i] = mdct_window[i];
        }

    /* Generate the QMF window. */
    for (i=0 ; i<24; i++) {
        s = qmf_48tap_half[i] * 2.0;
        qmf_window[i] = s;
        qmf_window[47 - i] = s;
    }

    /* Initialize the MDCT transform. */
    ff_mdct_init(&mdct_ctx, 9, 1);
}

/**
 * Atrac3 uninit, free all allocated memory
 */

static int atrac3_decode_close(AVCodecContext *avctx)
{
    ATRAC3Context *q = avctx->priv_data;

    av_free(q->pUnits);
    av_free(q->decoded_bytes_buffer);

    return 0;
}

/**
/ * Mantissa decoding
 *
 * @param gb            the GetBit context
 * @param selector      what table is the output values coded with
 * @param codingFlag    constant length coding or variable length coding
 * @param mantissas     mantissa output table
 * @param numCodes      amount of values to get
 */

static void readQuantSpectralCoeffs (GetBitContext *gb, int selector, int codingFlag, int* mantissas, int numCodes)
{
    int   numBits, cnt, code, huffSymb;

    if (selector == 1)
        numCodes /= 2;

    if (codingFlag != 0) {
        /* constant length coding (CLC) */
        //FIXME we don't have any samples coded in CLC mode
        numBits = CLCLengthTab[selector];

        if (selector > 1) {
            for (cnt = 0; cnt < numCodes; cnt++) {
                if (numBits)
                    code = get_sbits(gb, numBits);
                else
                    code = 0;
                mantissas[cnt] = code;
            }
        } else {
            for (cnt = 0; cnt < numCodes; cnt++) {
                if (numBits)
                    code = get_bits(gb, numBits); //numBits is always 4 in this case
                else
                    code = 0;
                mantissas[cnt*2] = seTab_0[code >> 2];
                mantissas[cnt*2+1] = seTab_0[code & 3];
            }
        }
    } else {
        /* variable length coding (VLC) */
        if (selector != 1) {
            for (cnt = 0; cnt < numCodes; cnt++) {
                huffSymb = get_vlc2(gb, spectral_coeff_tab[selector-1].table, spectral_coeff_tab[selector-1].bits, 3);
                huffSymb += 1;
                code = huffSymb >> 1;
                if (huffSymb & 1)
                    code = -code;
                mantissas[cnt] = code;
            }
        } else {
            for (cnt = 0; cnt < numCodes; cnt++) {
                huffSymb = get_vlc2(gb, spectral_coeff_tab[selector-1].table, spectral_coeff_tab[selector-1].bits, 3);
                mantissas[cnt*2] = decTable1[huffSymb*2];
                mantissas[cnt*2+1] = decTable1[huffSymb*2+1];
            }
        }
    }
}

/**
 * Restore the quantized band spectrum coefficients
 *
 * @param gb            the GetBit context
 * @param pOut          decoded band spectrum
 * @return outSubbands   subband counter, fix for broken specification/files
 */

static int decodeSpectrum (GetBitContext *gb, float *pOut)
{
    int   numSubbands, codingMode, cnt, first, last, subbWidth, *pIn;
    int   subband_vlc_index[32], SF_idxs[32];
    int   mantissas[128];
    float SF;

    numSubbands = get_bits(gb, 5); // number of coded subbands
    codingMode = get_bits1(gb); // coding Mode: 0 - VLC/ 1-CLC

    /* Get the VLC selector table for the subbands, 0 means not coded. */
    for (cnt = 0; cnt <= numSubbands; cnt++)
        subband_vlc_index[cnt] = get_bits(gb, 3);

    /* Read the scale factor indexes from the stream. */
    for (cnt = 0; cnt <= numSubbands; cnt++) {
        if (subband_vlc_index[cnt] != 0)
            SF_idxs[cnt] = get_bits(gb, 6);
    }

    for (cnt = 0; cnt <= numSubbands; cnt++) {
        first = subbandTab[cnt];
        last = subbandTab[cnt+1];

        subbWidth = last - first;

        if (subband_vlc_index[cnt] != 0) {
            /* Decode spectral coefficients for this subband. */
            /* TODO: This can be done faster is several blocks share the
             * same VLC selector (subband_vlc_index) */
            readQuantSpectralCoeffs (gb, subband_vlc_index[cnt], codingMode, mantissas, subbWidth);

            /* Decode the scale factor for this subband. */
            SF = SFTable[SF_idxs[cnt]] * iMaxQuant[subband_vlc_index[cnt]];

            /* Inverse quantize the coefficients. */
            for (pIn=mantissas ; first<last; first++, pIn++)
                pOut[first] = *pIn * SF;
        } else {
            /* This subband was not coded, so zero the entire subband. */
            memset(pOut+first, 0, subbWidth*sizeof(float));
        }
    }

    /* Clear the subbands that were not coded. */
    first = subbandTab[cnt];
    memset(pOut+first, 0, (1024 - first) * sizeof(float));
    return numSubbands;
}

/**
 * Restore the quantized tonal components
 *
 * @param gb            the GetBit context
 * @param pComponent    tone component
 * @param numBands      amount of coded bands
 */

static int decodeTonalComponents (GetBitContext *gb, tonal_component *pComponent, int numBands)
{
    int i,j,k,cnt;
    int   components, coding_mode_selector, coding_mode, coded_values_per_component;
    int   sfIndx, coded_values, max_coded_values, quant_step_index, coded_components;
    int   band_flags[4], mantissa[8];
    float  *pCoef;
    float  scalefactor;
    int   component_count = 0;

    components = get_bits(gb,5);

    /* no tonal components */
    if (components == 0)
        return 0;

    coding_mode_selector = get_bits(gb,2);
    if (coding_mode_selector == 2)
        return -1;

    coding_mode = coding_mode_selector & 1;

    for (i = 0; i < components; i++) {
        for (cnt = 0; cnt <= numBands; cnt++)
            band_flags[cnt] = get_bits1(gb);

        coded_values_per_component = get_bits(gb,3);

        quant_step_index = get_bits(gb,3);
        if (quant_step_index <= 1)
            return -1;

        if (coding_mode_selector == 3)
            coding_mode = get_bits1(gb);

        for (j = 0; j < (numBands + 1) * 4; j++) {
            if (band_flags[j >> 2] == 0)
                continue;

            coded_components = get_bits(gb,3);

            for (k=0; k<coded_components; k++) {
                sfIndx = get_bits(gb,6);
                pComponent[component_count].pos = j * 64 + (get_bits(gb,6));
                max_coded_values = 1024 - pComponent[component_count].pos;
                coded_values = coded_values_per_component + 1;
                coded_values = FFMIN(max_coded_values,coded_values);

                scalefactor = SFTable[sfIndx] * iMaxQuant[quant_step_index];

                readQuantSpectralCoeffs(gb, quant_step_index, coding_mode, mantissa, coded_values);

                pComponent[component_count].numCoefs = coded_values;

                /* inverse quant */
                pCoef = pComponent[k].coef;
                for (cnt = 0; cnt < coded_values; cnt++)
                    pCoef[cnt] = mantissa[cnt] * scalefactor;

                component_count++;
            }
        }
    }

    return component_count;
}

/**
 * Decode gain parameters for the coded bands
 *
 * @param gb            the GetBit context
 * @param pGb           the gainblock for the current band
 * @param numBands      amount of coded bands
 */

static int decodeGainControl (GetBitContext *gb, gain_block *pGb, int numBands)
{
    int   i, cf, numData;
    int   *pLevel, *pLoc;

    gain_info   *pGain = pGb->gBlock;

    for (i=0 ; i<=numBands; i++)
    {
        numData = get_bits(gb,3);
        pGain[i].num_gain_data = numData;
        pLevel = pGain[i].levcode;
        pLoc = pGain[i].loccode;

        for (cf = 0; cf < numData; cf++){
            pLevel[cf]= get_bits(gb,4);
            pLoc  [cf]= get_bits(gb,5);
            if(cf && pLoc[cf] <= pLoc[cf-1])
                return -1;
        }
    }

    /* Clear the unused blocks. */
    for (; i<4 ; i++)
        pGain[i].num_gain_data = 0;

    return 0;
}

/**
 * Apply gain parameters and perform the MDCT overlapping part
 *
 * @param pIn           input float buffer
 * @param pPrev         previous float buffer to perform overlap against
 * @param pOut          output float buffer
 * @param pGain1        current band gain info
 * @param pGain2        next band gain info
 */

static void gainCompensateAndOverlap (float *pIn, float *pPrev, float *pOut, gain_info *pGain1, gain_info *pGain2)
{
    /* gain compensation function */
    float  gain1, gain2, gain_inc;
    int   cnt, numdata, nsample, startLoc, endLoc;


    if (pGain2->num_gain_data == 0)
        gain1 = 1.0;
    else
        gain1 = gain_tab1[pGain2->levcode[0]];

    if (pGain1->num_gain_data == 0) {
        for (cnt = 0; cnt < 256; cnt++)
            pOut[cnt] = pIn[cnt] * gain1 + pPrev[cnt];
    } else {
        numdata = pGain1->num_gain_data;
        pGain1->loccode[numdata] = 32;
        pGain1->levcode[numdata] = 4;

        nsample = 0; // current sample = 0

        for (cnt = 0; cnt < numdata; cnt++) {
            startLoc = pGain1->loccode[cnt] * 8;
            endLoc = startLoc + 8;

            gain2 = gain_tab1[pGain1->levcode[cnt]];
            gain_inc = gain_tab2[(pGain1->levcode[cnt+1] - pGain1->levcode[cnt])+15];

            /* interpolate */
            for (; nsample < startLoc; nsample++)
                pOut[nsample] = (pIn[nsample] * gain1 + pPrev[nsample]) * gain2;

            /* interpolation is done over eight samples */
            for (; nsample < endLoc; nsample++) {
                pOut[nsample] = (pIn[nsample] * gain1 + pPrev[nsample]) * gain2;
                gain2 *= gain_inc;
            }
        }

        for (; nsample < 256; nsample++)
            pOut[nsample] = (pIn[nsample] * gain1) + pPrev[nsample];
    }

    /* Delay for the overlapping part. */
    memcpy(pPrev, &pIn[256], 256*sizeof(float));
}

/**
 * Combine the tonal band spectrum and regular band spectrum
 *
 * @param pSpectrum     output spectrum buffer
 * @param numComponents amount of tonal components
 * @param pComponent    tonal components for this band
 */

static void addTonalComponents (float *pSpectrum, int numComponents, tonal_component *pComponent)
{
    int   cnt, i;
    float   *pIn, *pOut;

    for (cnt = 0; cnt < numComponents; cnt++){
        pIn = pComponent[cnt].coef;
        pOut = &(pSpectrum[pComponent[cnt].pos]);

        for (i=0 ; i<pComponent[cnt].numCoefs ; i++)
            pOut[i] += pIn[i];
    }
}


#define INTERPOLATE(old,new,nsample) ((old) + (nsample)*0.125*((new)-(old)))

static void reverseMatrixing(float *su1, float *su2, int *pPrevCode, int *pCurrCode)
{
    int    i, band, nsample, s1, s2;
    float    c1, c2;
    float    mc1_l, mc1_r, mc2_l, mc2_r;

    for (i=0,band = 0; band < 4*256; band+=256,i++) {
        s1 = pPrevCode[i];
        s2 = pCurrCode[i];
        nsample = 0;

        if (s1 != s2) {
            /* Selector value changed, interpolation needed. */
            mc1_l = matrixCoeffs[s1*2];
            mc1_r = matrixCoeffs[s1*2+1];
            mc2_l = matrixCoeffs[s2*2];
            mc2_r = matrixCoeffs[s2*2+1];

            /* Interpolation is done over the first eight samples. */
            for(; nsample < 8; nsample++) {
                c1 = su1[band+nsample];
                c2 = su2[band+nsample];
                c2 = c1 * INTERPOLATE(mc1_l,mc2_l,nsample) + c2 * INTERPOLATE(mc1_r,mc2_r,nsample);
                su1[band+nsample] = c2;
                su2[band+nsample] = c1 * 2.0 - c2;
            }
        }

        /* Apply the matrix without interpolation. */
        switch (s2) {
            case 0:     /* M/S decoding */
                for (; nsample < 256; nsample++) {
                    c1 = su1[band+nsample];
                    c2 = su2[band+nsample];
                    su1[band+nsample] = c2 * 2.0;
                    su2[band+nsample] = (c1 - c2) * 2.0;
                }
                break;

            case 1:
                for (; nsample < 256; nsample++) {
                    c1 = su1[band+nsample];
                    c2 = su2[band+nsample];
                    su1[band+nsample] = (c1 + c2) * 2.0;
                    su2[band+nsample] = c2 * -2.0;
                }
                break;
            case 2:
            case 3:
                for (; nsample < 256; nsample++) {
                    c1 = su1[band+nsample];
                    c2 = su2[band+nsample];
                    su1[band+nsample] = c1 + c2;
                    su2[band+nsample] = c1 - c2;
                }
                break;
            default:
                assert(0);
        }
    }
}

static void getChannelWeights (int indx, int flag, float ch[2]){

    if (indx == 7) {
        ch[0] = 1.0;
        ch[1] = 1.0;
    } else {
        ch[0] = (float)(indx & 7) / 7.0;
        ch[1] = sqrt(2 - ch[0]*ch[0]);
        if(flag)
            FFSWAP(float, ch[0], ch[1]);
    }
}

static void channelWeighting (float *su1, float *su2, int *p3)
{
    int   band, nsample;
    /* w[x][y] y=0 is left y=1 is right */
    float w[2][2];

    if (p3[1] != 7 || p3[3] != 7){
        getChannelWeights(p3[1], p3[0], w[0]);
        getChannelWeights(p3[3], p3[2], w[1]);

        for(band = 1; band < 4; band++) {
            /* scale the channels by the weights */
            for(nsample = 0; nsample < 8; nsample++) {
                su1[band*256+nsample] *= INTERPOLATE(w[0][0], w[0][1], nsample);
                su2[band*256+nsample] *= INTERPOLATE(w[1][0], w[1][1], nsample);
            }

            for(; nsample < 256; nsample++) {
                su1[band*256+nsample] *= w[1][0];
                su2[band*256+nsample] *= w[1][1];
            }
        }
    }
}


/**
 * Decode a Sound Unit
 *
 * @param gb            the GetBit context
 * @param pSnd          the channel unit to be used
 * @param pOut          the decoded samples before IQMF in float representation
 * @param channelNum    channel number
 * @param codingMode    the coding mode (JOINT_STEREO or regular stereo/mono)
 */


static int decodeChannelSoundUnit (ATRAC3Context *q, GetBitContext *gb, channel_unit *pSnd, float *pOut, int channelNum, int codingMode)
{
    int   band, result=0, numSubbands, numBands;

    if (codingMode == JOINT_STEREO && channelNum == 1) {
        if (get_bits(gb,2) != 3) {
            av_log(NULL,AV_LOG_ERROR,"JS mono Sound Unit id != 3.\n");
            return -1;
        }
    } else {
        if (get_bits(gb,6) != 0x28) {
            av_log(NULL,AV_LOG_ERROR,"Sound Unit id != 0x28.\n");
            return -1;
        }
    }

    /* number of coded QMF bands */
    pSnd->bandsCoded = get_bits(gb,2);

    result = decodeGainControl (gb, &(pSnd->gainBlock[pSnd->gcBlkSwitch]), pSnd->bandsCoded);
    if (result) return result;

    pSnd->numComponents = decodeTonalComponents (gb, pSnd->components, pSnd->bandsCoded);
    if (pSnd->numComponents == -1) return -1;

    numSubbands = decodeSpectrum (gb, pSnd->spectrum);

    /* Merge the decoded spectrum and tonal components. */
    addTonalComponents (pSnd->spectrum, pSnd->numComponents, pSnd->components);


    /* Convert number of subbands into number of MLT/QMF bands */
    numBands = (subbandTab[numSubbands] - 1) >> 8;


    /* Reconstruct time domain samples. */
    for (band=0; band<4; band++) {
        /* Perform the IMDCT step without overlapping. */
        if (band <= numBands) {
            IMLT(&(pSnd->spectrum[band*256]), pSnd->IMDCT_buf, band&1,q->mdct_tmp);
        } else
            memset(pSnd->IMDCT_buf, 0, 512 * sizeof(float));

        /* gain compensation and overlapping */
        gainCompensateAndOverlap (pSnd->IMDCT_buf, &(pSnd->prevFrame[band*256]), &(pOut[band*256]),
                                    &((pSnd->gainBlock[1 - (pSnd->gcBlkSwitch)]).gBlock[band]),
                                    &((pSnd->gainBlock[pSnd->gcBlkSwitch]).gBlock[band]));
    }

    /* Swap the gain control buffers for the next frame. */
    pSnd->gcBlkSwitch ^= 1;

    return 0;
}

/**
 * Frame handling
 *
 * @param q             Atrac3 private context
 * @param databuf       the input data
 */

static int decodeFrame(ATRAC3Context *q, uint8_t* databuf)
{
    int   result, i;
    float   *p1, *p2, *p3, *p4;
    uint8_t    *ptr1, *ptr2;

    if (q->codingMode == JOINT_STEREO) {

        /* channel coupling mode */
        /* decode Sound Unit 1 */
        init_get_bits(&q->gb,databuf,q->bits_per_frame);

        result = decodeChannelSoundUnit(q,&q->gb, q->pUnits, q->outSamples, 0, JOINT_STEREO);
        if (result != 0)
            return (result);

        /* Framedata of the su2 in the joint-stereo mode is encoded in
         * reverse byte order so we need to swap it first. */
        ptr1 = databuf;
        ptr2 = databuf+q->bytes_per_frame-1;
        for (i = 0; i < (q->bytes_per_frame/2); i++, ptr1++, ptr2--) {
            FFSWAP(uint8_t,*ptr1,*ptr2);
        }

        /* Skip the sync codes (0xF8). */
        ptr1 = databuf;
        for (i = 4; *ptr1 == 0xF8; i++, ptr1++) {
            if (i >= q->bytes_per_frame)
                return -1;
        }


        /* set the bitstream reader at the start of the second Sound Unit*/
        init_get_bits(&q->gb,ptr1,q->bits_per_frame);

        /* Fill the Weighting coeffs delay buffer */
        memmove(q->weighting_delay,&(q->weighting_delay[2]),4*sizeof(int));
        q->weighting_delay[4] = get_bits1(&q->gb);
        q->weighting_delay[5] = get_bits(&q->gb,3);

        for (i = 0; i < 4; i++) {
            q->matrix_coeff_index_prev[i] = q->matrix_coeff_index_now[i];
            q->matrix_coeff_index_now[i] = q->matrix_coeff_index_next[i];
            q->matrix_coeff_index_next[i] = get_bits(&q->gb,2);
        }

        /* Decode Sound Unit 2. */
        result = decodeChannelSoundUnit(q,&q->gb, &q->pUnits[1], &q->outSamples[1024], 1, JOINT_STEREO);
        if (result != 0)
            return (result);

        /* Reconstruct the channel coefficients. */
        reverseMatrixing(q->outSamples, &q->outSamples[1024], q->matrix_coeff_index_prev, q->matrix_coeff_index_now);

        channelWeighting(q->outSamples, &q->outSamples[1024], q->weighting_delay);

    } else {
        /* normal stereo mode or mono */
        /* Decode the channel sound units. */
        for (i=0 ; i<q->channels ; i++) {

            /* Set the bitstream reader at the start of a channel sound unit. */
            init_get_bits(&q->gb, databuf+((i*q->bytes_per_frame)/q->channels), (q->bits_per_frame)/q->channels);

            result = decodeChannelSoundUnit(q,&q->gb, &q->pUnits[i], &q->outSamples[i*1024], i, q->codingMode);
            if (result != 0)
                return (result);
        }
    }

    /* Apply the iQMF synthesis filter. */
    p1= q->outSamples;
    for (i=0 ; i<q->channels ; i++) {
        p2= p1+256;
        p3= p2+256;
        p4= p3+256;
        iqmf (p1, p2, 256, p1, q->pUnits[i].delayBuf1, q->tempBuf);
        iqmf (p4, p3, 256, p3, q->pUnits[i].delayBuf2, q->tempBuf);
        iqmf (p1, p3, 512, p1, q->pUnits[i].delayBuf3, q->tempBuf);
        p1 +=1024;
    }

    return 0;
}


/**
 * Atrac frame decoding
 *
 * @param avctx     pointer to the AVCodecContext
 */

static int atrac3_decode_frame(AVCodecContext *avctx,
            void *data, int *data_size,
            const uint8_t *buf, int buf_size) {
    ATRAC3Context *q = avctx->priv_data;
    int result = 0, i;
    uint8_t* databuf;
    int16_t* samples = data;

    if (buf_size < avctx->block_align)
        return buf_size;

    /* Check if we need to descramble and what buffer to pass on. */
    if (q->scrambled_stream) {
        decode_bytes(buf, q->decoded_bytes_buffer, avctx->block_align);
        databuf = q->decoded_bytes_buffer;
    } else {
        databuf = buf;
    }

    result = decodeFrame(q, databuf);

    if (result != 0) {
        av_log(NULL,AV_LOG_ERROR,"Frame decoding error!\n");
        return -1;
    }

    if (q->channels == 1) {
        /* mono */
        for (i = 0; i<1024; i++)
            samples[i] = av_clip_int16(round(q->outSamples[i]));
        *data_size = 1024 * sizeof(int16_t);
    } else {
        /* stereo */
        for (i = 0; i < 1024; i++) {
            samples[i*2] = av_clip_int16(round(q->outSamples[i]));
            samples[i*2+1] = av_clip_int16(round(q->outSamples[1024+i]));
        }
        *data_size = 2048 * sizeof(int16_t);
    }

    return avctx->block_align;
}


/**
 * Atrac3 initialization
 *
 * @param avctx     pointer to the AVCodecContext
 */

static int atrac3_decode_init(AVCodecContext *avctx)
{
    int i;
    const uint8_t *edata_ptr = avctx->extradata;
    ATRAC3Context *q = avctx->priv_data;

    /* Take data from the AVCodecContext (RM container). */
    q->sample_rate = avctx->sample_rate;
    q->channels = avctx->channels;
    q->bit_rate = avctx->bit_rate;
    q->bits_per_frame = avctx->block_align * 8;
    q->bytes_per_frame = avctx->block_align;

    /* Take care of the codec-specific extradata. */
    if (avctx->extradata_size == 14) {
        /* Parse the extradata, WAV format */
        av_log(avctx,AV_LOG_DEBUG,"[0-1] %d\n",bytestream_get_le16(&edata_ptr));  //Unknown value always 1
        q->samples_per_channel = bytestream_get_le32(&edata_ptr);
        q->codingMode = bytestream_get_le16(&edata_ptr);
        av_log(avctx,AV_LOG_DEBUG,"[8-9] %d\n",bytestream_get_le16(&edata_ptr));  //Dupe of coding mode
        q->frame_factor = bytestream_get_le16(&edata_ptr);  //Unknown always 1
        av_log(avctx,AV_LOG_DEBUG,"[12-13] %d\n",bytestream_get_le16(&edata_ptr));  //Unknown always 0

        /* setup */
        q->samples_per_frame = 1024 * q->channels;
        q->atrac3version = 4;
        q->delay = 0x88E;
        if (q->codingMode)
            q->codingMode = JOINT_STEREO;
        else
            q->codingMode = STEREO;

        q->scrambled_stream = 0;

        if ((q->bytes_per_frame == 96*q->channels*q->frame_factor) || (q->bytes_per_frame == 152*q->channels*q->frame_factor) || (q->bytes_per_frame == 192*q->channels*q->frame_factor)) {
        } else {
            av_log(avctx,AV_LOG_ERROR,"Unknown frame/channel/frame_factor configuration %d/%d/%d\n", q->bytes_per_frame, q->channels, q->frame_factor);
            return -1;
        }

    } else if (avctx->extradata_size == 10) {
        /* Parse the extradata, RM format. */
        q->atrac3version = bytestream_get_be32(&edata_ptr);
        q->samples_per_frame = bytestream_get_be16(&edata_ptr);
        q->delay = bytestream_get_be16(&edata_ptr);
        q->codingMode = bytestream_get_be16(&edata_ptr);

        q->samples_per_channel = q->samples_per_frame / q->channels;
        q->scrambled_stream = 1;

    } else {
        av_log(NULL,AV_LOG_ERROR,"Unknown extradata size %d.\n",avctx->extradata_size);
    }
    /* Check the extradata. */

    if (q->atrac3version != 4) {
        av_log(avctx,AV_LOG_ERROR,"Version %d != 4.\n",q->atrac3version);
        return -1;
    }

    if (q->samples_per_frame != 1024 && q->samples_per_frame != 2048) {
        av_log(avctx,AV_LOG_ERROR,"Unknown amount of samples per frame %d.\n",q->samples_per_frame);
        return -1;
    }

    if (q->delay != 0x88E) {
        av_log(avctx,AV_LOG_ERROR,"Unknown amount of delay %x != 0x88E.\n",q->delay);
        return -1;
    }

    if (q->codingMode == STEREO) {
        av_log(avctx,AV_LOG_DEBUG,"Normal stereo detected.\n");
    } else if (q->codingMode == JOINT_STEREO) {
        av_log(avctx,AV_LOG_DEBUG,"Joint stereo detected.\n");
    } else {
        av_log(avctx,AV_LOG_ERROR,"Unknown channel coding mode %x!\n",q->codingMode);
        return -1;
    }

    if (avctx->channels <= 0 || avctx->channels > 2 /*|| ((avctx->channels * 1024) != q->samples_per_frame)*/) {
        av_log(avctx,AV_LOG_ERROR,"Channel configuration error!\n");
        return -1;
    }


    if(avctx->block_align >= UINT_MAX/2)
        return -1;

    /* Pad the data buffer with FF_INPUT_BUFFER_PADDING_SIZE,
     * this is for the bitstream reader. */
    if ((q->decoded_bytes_buffer = av_mallocz((avctx->block_align+(4-avctx->block_align%4) + FF_INPUT_BUFFER_PADDING_SIZE)))  == NULL)
        return AVERROR(ENOMEM);


    /* Initialize the VLC tables. */
    for (i=0 ; i<7 ; i++) {
        init_vlc (&spectral_coeff_tab[i], 9, huff_tab_sizes[i],
            huff_bits[i], 1, 1,
            huff_codes[i], 1, 1, INIT_VLC_USE_STATIC);
    }

    init_atrac3_transforms(q);

    /* Generate the scale factors. */
    for (i=0 ; i<64 ; i++)
        SFTable[i] = pow(2.0, (i - 15) / 3.0);

    /* Generate gain tables. */
    for (i=0 ; i<16 ; i++)
        gain_tab1[i] = powf (2.0, (4 - i));

    for (i=-15 ; i<16 ; i++)
        gain_tab2[i+15] = powf (2.0, i * -0.125);

    /* init the joint-stereo decoding data */
    q->weighting_delay[0] = 0;
    q->weighting_delay[1] = 7;
    q->weighting_delay[2] = 0;
    q->weighting_delay[3] = 7;
    q->weighting_delay[4] = 0;
    q->weighting_delay[5] = 7;

    for (i=0; i<4; i++) {
        q->matrix_coeff_index_prev[i] = 3;
        q->matrix_coeff_index_now[i] = 3;
        q->matrix_coeff_index_next[i] = 3;
    }

    dsputil_init(&dsp, avctx);

    q->pUnits = av_mallocz(sizeof(channel_unit)*q->channels);
    if (!q->pUnits) {
        av_free(q->decoded_bytes_buffer);
        return AVERROR(ENOMEM);
    }

    return 0;
}


AVCodec atrac3_decoder =
{
    .name = "atrac 3",
    .type = CODEC_TYPE_AUDIO,
    .id = CODEC_ID_ATRAC3,
    .priv_data_size = sizeof(ATRAC3Context),
    .init = atrac3_decode_init,
    .close = atrac3_decode_close,
    .decode = atrac3_decode_frame,
};