[FFmpeg-devel] [PATCH] atrac decoder

Benjamin Larsson banan
Tue Aug 11 19:32:30 CEST 2009


Michael Niedermayer wrote:
> On Mon, Aug 10, 2009 at 11:10:40PM +0200, Benjamin Larsson wrote:
>> Michael Niedermayer wrote:
>>> On Mon, Jun 08, 2009 at 09:40:18PM +0200, Benjamin Larsson wrote:
> [...]
>>> [...]
>>>> +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 ...
>>>
>>
>> Would be possible if there where no short blocks. The logic to untangle
>> those are not worth it.
> 
> elabrate please

A subband that is reversed can use short or long mdct sizes. If it is
long then decoding in reverse order would work.

12,11,10,9,8,7,6,5,4,3,2,1

But when the short order is used (to code transients), the blocks are
reversed in groups.

3,2,1,6,5,4,9,8,7,12,11,10

> 
> 
>>>> +
>>>> +    ff_imdct_calc(mdct_context,out,spec);
>>> cant imdct_half be used?
>>>
>> Changed to
>>
>> memset
>> fmul
>> fmul_rev
>> memset
>>
>> It was slightly faster and uses less memory.
> 
> you still use the full imdct

Yes, that has to do with windowing. As I shouldn't multiply with 0 and 1
I have to do it this way. To use imdct_half I need to build the complete
windows again (Use more memory etc).

> 
> 
> [...]
>>> [...]
>>>> +
>>>> +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
>>
>> I think I understood this one time, now I just don't see how that could
>> be done.
> 
> for all bfu_num
>     table[bfu_num] = idwl2wordlen[get_bits()];
> 
> ...
> 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 = table[bfu_num];
> 
> 
> [...]
> 
>> +/* 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. How should the split be done, svn copy or not (complete atrac3.c in
history or not) ?

MvH
Benjamin Larsson



More information about the ffmpeg-devel mailing list