[FFmpeg-devel] [PATCH] AAC decoder

Robert Swain robert.swain
Wed May 21 16:34:26 CEST 2008


2008/4/2 Michael Niedermayer <michaelni at gmx.at>:
> On Tue, Apr 01, 2008 at 04:56:48PM +0200, Andreas ?man wrote:
>> Andreas ?man wrote:

[...]

>> +/**
>> + * Decode scale_factor_data
>> + * reference: Table 4.47
>> + */
>> +static int scale_factor_data(AACContext * ac, GetBitContext * gb, float mix_gain, unsigned int global_gain, ics_struct * ics, const int cb[][64], float sf[][64]) {
>
> Maybe rename the function to what the comment says
>
>
>> +    int g, i;
>> +    unsigned int intensity = 100; // normalization for intensity_tab lookup table
>> +    int noise = global_gain - 90;
>> +    int noise_flag = 1;
>> +    ics->intensity_present = 0;
>> +    for (g = 0; g < ics->num_window_groups; g++) {
>> +        for (i = 0; i < ics->max_sfb; i++) {
>> +            if (cb[g][i] == ZERO_HCB) {
>> +                sf[g][i] = 0.;
>
>> +            } else if (cb[g][i] == INTENSITY_HCB || cb[g][i] == INTENSITY_HCB2) {
>> +                ics->intensity_present = 1;
>> +                intensity += get_vlc2(gb, ac->mainvlc.table, 7, 3) - 60;
>> +                if(intensity > 255) {
>> +                    av_log(ac->avccontext, AV_LOG_ERROR,
>> +                           "Intensity (%d) out of range", intensity);
>> +                    return -1;
>> +                }
>> +                sf[g][i] = ac->intensity_tab[intensity];
>> +            } else if (cb[g][i] == NOISE_HCB) {
>> +                if (noise_flag) {
>> +                    noise_flag = 0;
>> +                    noise += get_bits(gb, 9) - 256;
>> +                } else {
>> +                    noise += get_vlc2(gb, ac->mainvlc.table, 7, 3) - 60;
>> +                }
>> +                sf[g][i] = pow(2.0, 0.25 * noise) * ac->sf_scale;
>> +            } else {
>> +                global_gain += get_vlc2(gb, ac->mainvlc.table, 7, 3) - 60;
>> +                if(global_gain > 255) {
>> +                    av_log(ac->avccontext, AV_LOG_ERROR,
>> +                           "Global gain (%d) out of range", global_gain);
>> +                    return -1;
>> +                }
>> +                sf[g][i] = ac->pow2sf_tab[global_gain];
>> +            }
>
> The identical code is implemented here 3 times, 2 times with seperate
> LUTs and once by directly calling pow()
> The differenes look like bugs. like forgetting to check validity or
> performing the scaling needed for the float2int16 transform.
>
> if(cb[g][i] == NOISE_HCB && noise_flag-- > 0)
>    gain[index] += get_bits(gb, 9) - 256;
> else
>    gain[index] += get_vlc2(gb, ac->mainvlc.table, 7, 3) - 60;
> if(gain[index] > 255)
>    ...
> sf[g][i] = ac->pow2sf_tab[gain[index]];

I tried this and audibly it sounds fine on a few files I tested. I
want to compare the two tables and pow() * ac->sf_scale call before
submitting a patch though.

[...]

>> +static int coupling_channel_element(AACContext * ac, GetBitContext * gb, int id) {
>
>> +    float cc_scale[] = {
>> +        pow(2, 1/8.), pow(2, 1/4.), pow(2, 0.5), 2.
>> +    };
>
> static const
>
>
>> +    int num_gain = 0;
>> +    int c, g, sfb;
>> +    int sign;
>> +    float scale;
>> +    sce_struct * sce;
>> +    coupling_struct * coup;
>
>> +    if (!ac->che_cc[id]) {
>> +        return -1;
>> +    }
>
> somehow i think all these checks can be factored out.
>
>
>> +    sce = &ac->che_cc[id]->ch;
>> +    sce->mixing_gain = 1.0;
>> +
>> +    coup = &ac->che_cc[id]->coup;
>> +
>> +    coup->ind_sw = get_bits1(gb);
>> +    //if (coup->ind_sw)
>> +    //    av_log(ac->avccontext, AV_LOG_ERROR, "aac: independently switched coupling\n");
>> +    coup->num_coupled = get_bits(gb, 3);
>> +    for (c = 0; c <= coup->num_coupled; c++) {
>> +        num_gain++;
>> +        coup->is_cpe[c] = get_bits1(gb);
>> +        coup->tag_select[c] = get_bits(gb, 4);
>> +        if (coup->is_cpe[c]) {
>> +            coup->l[c] = get_bits1(gb);
>> +            coup->r[c] = get_bits1(gb);
>> +            if (coup->l[c] && coup->r[c])
>> +                num_gain++;
>> +        }
>> +    }
>> +    coup->domain = get_bits1(gb);
>> +    sign = get_bits(gb, 1);
>> +    scale = cc_scale[get_bits(gb, 2)];
>> +
>> +    if (individual_channel_stream(ac, gb, 0, 0, sce))
>> +        return -1;
>> +
>> +    for (c = 0; c < num_gain; c++) {
>> +        int cge = 1;
>> +        int gain = 0;
>> +        float gain_cache = 1.;
>> +        if (c != 0) {
>> +            cge = coup->ind_sw ? 1 : get_bits1(gb);
>> +            gain = cge ? get_vlc2(gb, ac->mainvlc.table, 7, 3) - 60: 0;
>
>> +            gain_cache = pow(scale, (float)gain);
>
> useless cast and cc_scale is useless too

I have two possibilities for this:

20080521-remove_cc_scale-scale_idx.diff
20080521-remove_cc_scale-scale.diff

The latter avoids a division within the loops at the cost of an
additional pow() call. I didn't know which would be preferred (though
I would lean toward the latter at a guess) so I'm submitting both for
review. :)

[...]

>> +static void tns_filter_tool(AACContext * ac, int decode, sce_struct * sce, float * coef) {
>
> bad name ...

The spec calls this function tns_decode_frame. Is that acceptable or
if not, do you have any hints? TNS == Temporal Noise Shaping.

[...]

Rob
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 20080521-remove_cc_scale-scale.diff
Type: text/x-diff
Size: 1706 bytes
Desc: not available
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20080521/d5a17a9c/attachment.diff>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 20080521-remove_cc_scale-scale_idx.diff
Type: text/x-diff
Size: 1844 bytes
Desc: not available
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20080521/d5a17a9c/attachment-0001.diff>



More information about the ffmpeg-devel mailing list