[FFmpeg-devel] [PATCH] atrac decoder

Benjamin Larsson banan
Tue Jun 9 11:00:38 CEST 2009


Michael Niedermayer wrote:
>
>> +/* idwl to wordlen translation table */
>> +static const uint8_t idwl2wordlen[16]= {0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
>>     
>
> doxy
>   

OK.

>
> [...]
>   
>> +static DSPContext       dsp;
>>     
>
> hmmm, if my memory doesnt fail then dsp cant be saftely used like this
>   

I'll just move it to the context then.

>
> [...]
>   
>> +static void at1_imdct_transform(ATRAC1Context *q, float *spec, float *out, int nbits, int reverse_spectrum)
>> +{
>> +    float* window;
>> +    MDCTContext* mdct_context;
>> +    int transf_size = 1 << nbits;
>> +
>> +    switch(nbits) {
>> +        case 5:
>> +            window = short_window;
>> +            mdct_context = &q->mdct_ctx[0];
>> +            break;
>> +        case 7:
>> +            window = mid_window;
>> +            mdct_context = &q->mdct_ctx[1];
>> +            break;
>> +        case 8:
>> +        default:
>> +            window = long_window;
>> +            mdct_context = &q->mdct_ctx[2];
>> +    }
>> +
>>     
>
>   
>> +    if (reverse_spectrum) {
>> +        int i;
>> +        for (i=0; i<transf_size/2; i++)
>> +            FFSWAP(float, spec[i], spec[transf_size-1-i]);
>> +    }
>>     
>
> i think that can be avoided by decong in reverse order ...
>   

OK, I'll see what I can do.

>
>   
>> +
>> +    ff_imdct_calc(mdct_context,out,spec);
>>     
>
> cant imdct_half be used?
>   

If you/someone explain what imdct_half does. I need the complete output 
from the imdct per my understanding.

>
> [...]
>   
>> +static int at1_parse_block_size_mode(GetBitContext* gb, int bsm[AT1_QMF_BANDS])
>> +{
>> +    int bsm_tmp;
>> +
>> +    /* low band */
>> +    bsm_tmp = get_bits(gb, 2);
>> +    if (bsm_tmp != 0 && bsm_tmp != 2)
>> +        return -1;
>> +    bsm[IDX_LOW_BAND] = 2 - bsm_tmp;
>> +
>> +    /* middle band */
>> +    bsm_tmp = get_bits(gb, 2);
>>     
>
>   
>> +    if (bsm_tmp != 0 && bsm_tmp != 2)
>> +        return -1;
>>     
>
> bsm_tmp&1
>   

OK

>> +
>> +static int at1_unpack_dequant(GetBitContext* gb, AT1SUContext* su, float spec[AT1_SU_SAMPLES])
>> +{
>> +    int bits_used, band_num, bfu_num, i;
>> +
>> +    /* parse the info byte (2nd byte) telling how much BFUs were coded */
>> +    su->num_bfus = bfu_amount_tab1[get_bits(gb, 3)];
>> +
>> +    /* calc number of consumed bits:
>> +        num_BFUs * (idwl(4bits) + idsf(6bits)) + bsm(8bits) + info_byte(8bits)
>> +        + info_byte_copy(8bits) + bsm_copy(8bits) */
>> +    bits_used = su->num_bfus * 10 + 32 +
>> +                bfu_amount_tab2[get_bits(gb, 2)] * 4 +
>> +                bfu_amount_tab3[get_bits(gb, 3)] * 6;
>> +
>> +    /* get word length index (idwl) for each BFU */
>> +    for (i=0 ; i<su->num_bfus ; i++)
>> +        su->idwls[i] = get_bits(gb, 4);
>> +
>> +    /* get scalefactor index (idsf) for each BFU */
>> +    for (i=0 ; i<su->num_bfus ; i++)
>> +        su->idsfs[i] = get_bits(gb, 6);
>> +
>> +    /* zero idwl/idsf for empty BFUs */
>> +    for (i = su->num_bfus; i < AT1_MAX_BFU; i++)
>> +        su->idwls[i] = su->idsfs[i] = 0;
>> +
>> +    /* read in the spectral data and reconstruct MDCT spectrum of this channel */
>> +    for (band_num=0 ; band_num<AT1_QMF_BANDS ; band_num++) {
>> +        for (bfu_num=bfu_bands_t[band_num] ; bfu_num<bfu_bands_t[band_num+1] ; bfu_num++) {
>> +            int         pos;
>> +
>> +            int num_specs = specs_per_bfu[bfu_num];
>>     
>
>   
>> +            int word_len = idwl2wordlen[su->idwls[bfu_num]];
>>     
>
> that remaping could be done outside the loops
>   

OK

>> +
>> +static int atrac1_decode_frame(AVCodecContext *avctx,
>> +            void *data, int *data_size,
>> +            AVPacket *avpkt)
>> +{
>> +    const uint8_t *buf = avpkt->data;
>> +    int buf_size = avpkt->size;
>> +    ATRAC1Context *q = avctx->priv_data;
>> +    int ch, ret, i;
>> +    int16_t* samples = data;
>> +
>> +//    if ((buf_size<212 && q->channels==1) || (buf_size<424 && q->channels==2))
>> +//        return -1;
>> +
>> +    for (ch=0 ; ch<avctx->channels ; ch++) {
>> +        AT1SUContext* su = &q->SUs[ch];
>> +
>> +        init_get_bits(&q->gb, &buf[212*ch], 212*8);
>> +
>> +        /* parse block_size_mode, 1st byte */
>> +        ret = at1_parse_block_size_mode(&q->gb, su->bsm);
>> +        if(ret)
>> +            return ret;
>> +
>> +        ret = at1_unpack_dequant(&q->gb, su, q->spec);
>> +        if(ret)
>> +            return ret;
>> +
>> +        ret = at1_imdct(su, q);
>> +        if(ret)
>> +            return ret;
>> +        at1_subband_synthesis(q, su, q->out_samples[ch]);
>> +    }
>> +
>> +    /* round, convert to 16bit and interleave */
>> +    if (q->channels == 1) {
>> +        /* mono */
>> +        for (i = 0; i<AT1_SU_SAMPLES; i++)
>> +            samples[i] = av_clip_int16(round(q->out_samples[0][i]));
>> +        *data_size = AT1_SU_SAMPLES * sizeof(int16_t);
>> +    } else {
>> +        /* stereo */
>> +        for (i = 0; i < AT1_SU_SAMPLES; i++) {
>> +            samples[i*2] = av_clip_int16(round(q->out_samples[0][i]));
>> +            samples[i*2+1] = av_clip_int16(round(q->out_samples[1][i]));
>> +        }
>> +        *data_size = 2 * AT1_SU_SAMPLES * sizeof(int16_t);
>> +    }
>>     
>
> maybe this should retutn float instead of converting to 16bit?
>   

OK.

>
>   
>> +
>> +    return avctx->block_align;
>> +}
>> +
>> +static av_cold void init_mdct_windows()
>> +{
>> +    int i;
>> +    /* Generate the short window */
>> +    ff_sine_window_init(short_window,32);
>> +    for (i=0 ; i<32; i++)
>> +        short_window[63-i] = short_window[i];
>> +
>> +    /** The mid and long windows uses the same sine window splitted
>> +     *  in the middle and wrapped into zero/one regions as follows:
>> +     *
>> +     *                   region of "ones"
>> +     *               ---------------------------
>> +     *              /                           \
>> +     *             / 1st half                    \ 2nd half
>> +     *            / of the sine                   \ of the sine window
>> +     *           /  window                         \
>> +     * ---------/                                   \----------------
>> +     * zero region                                      zero region
>> +     */
>> +
>> +    /* Generate the mid window */
>> +    memset(mid_window, 0, sizeof(mid_window));
>> +    memcpy(&mid_window[48], short_window, sizeof(float) * 32);
>> +    for (i = 0; i < 96; i++)
>> +        mid_window[80 + i] = 1.0f;
>> +    memcpy(&mid_window[176], &short_window[32], sizeof(float) * 32);
>> +
>> +    /* Generate the long window */
>> +    memset(long_window, 0, sizeof(long_window));
>> +    memcpy(&long_window[112], short_window, sizeof(float) * 32);
>> +    for (i = 0; i < 224; i++)
>> +        long_window[144 + i] = 1.0f;
>>     
>
> please dont multiply by 1 or 0, its a waste of time
>   

So you want me to change one line of windowing

dsp.vector_fmul(out, window, transf_size << 1);

to 3 cases depending on the block size and replace it with
memset, vector_fmul and vector_fmul_rev ?


I thought about it but scrapped the idea as I wanted the code to be 
clear and simple. But if you want it I'll change the code.

>
> [...]
>   
>> +    /* Generate the QMF window. */
>> +    for (i=0 ; i<24; i++) {
>> +        float s;
>> +        s = qmf_48tap_half[i] * 2.0;
>> +        qmf_window[i] = s;
>> +        qmf_window[47 - i] = s;
>> +    }
>>     
>
> the intermediate s is useless
>   
OK, this is part of the code that will be split out, I missed to note that.

MvH
Benjamin Larsson





More information about the ffmpeg-devel mailing list