[FFmpeg-devel] AAC decoder round 9

Robert Swain robert.swain
Wed Aug 20 14:39:15 CEST 2008


2008/8/19 Robert Swain <robert.swain at gmail.com>:
> 2008/8/18 Michael Niedermayer <michaelni at gmx.at>:
>> On Mon, Aug 18, 2008 at 08:42:53PM +0100, Robert Swain wrote:
>>> $subj
>>>
>>> Will this be the last...? :)
>>
>> No, not yet :)
>
> It may be, if I fix this bit of apply_tns(), I don't think there's
> much point resubmitting as you'll know what the code looks like. :)
>
>>> Rob
>>
>>> Index: libavcodec/aac.c
>>> ===================================================================
>>> --- libavcodec/aac.c  (revision 14828)
>>> +++ libavcodec/aac.c  (working copy)
>>> @@ -94,6 +94,17 @@
>>>  static VLC vlc_spectral[11];
>>>
>>>
>>> +// TODO: Maybe add to dsputil?!
>>> +#if 0
>>> +static void vector_fmul_add_add_add(DSPContext * dsp, float * dst, const float * src0, const float * src1,
>>> +        const float * src2, const float * src3, float src4, int len) {
>>> +    int i;
>>> +    dsp->vector_fmul_add_add(dst, src0, src1, src2, src4, len, 1);
>>> +    for (i = 0; i < len; i++)
>>> +        dst[i] += src3[i];
>>> +}
>>> +#endif
>>> +
>>>  /**
>>>   * Configure output channel order based on the current program configuration element.
>>>   *
>>
>> ohh well, if you want this #if 0 code so be it
>> ok, but please remove the "// TODO: Maybe add to dsputil?!" we do not want
>> to move this there unless we find out that it is actually needed for these
>> windows ...
>
> I don't mind either way. I'm probably going to rip out the code which
> calls this anyway and it's no problem to grab it from SoC if we ever
> need it. So I won't bother with this one.
>
>>>   * Decode Mid/Side data; reference: table 4.54.
>>>   *
>>>   * @param   ms_present  Indicates mid/side stereo presence. [0] mask is all 0s;
>>> @@ -1067,6 +1116,57 @@
>>>  }
>>>
>>>  /**
>>> + * Decode Temporal Noise Shaping filter coefficients and apply all-pole filters; reference: 4.6.9.3.
>>> + *
>>> + * @param   decode  1 if tool is used normally, 0 if tool is used in LTP.
>>> + * @param   coef    spectral coefficients
>>> + */
>>> +static void apply_tns(float coef[1024], TemporalNoiseShaping * tns, IndividualChannelStream * ics, int decode) {
>>> +    const int mmm = FFMIN(ics->tns_max_bands,  ics->max_sfb);
>>> +    int w, filt, m, i, ib;
>>> +    int bottom, top, order, start, end, size, inc;
>>> +    float tmp;
>>> +    float lpc[TNS_MAX_ORDER + 1], b[TNS_MAX_ORDER + 1];
>>> +
>>> +    for (w = 0; w < ics->num_windows; w++) {
>>> +        bottom = ics->num_swb;
>>> +        for (filt = 0; filt < tns->n_filt[w]; filt++) {
>>> +            top    = bottom;
>>> +            bottom = FFMAX(0, top - tns->length[w][filt]);
>>> +            order  = tns->order[w][filt];
>>> +            if (order == 0)
>>> +                continue;
>>> +
>>
>>> +            // tns_decode_coef
>>> +            lpc[0] = 1;
>>> +            for (m = 1; m <= order; m++) {
>>> +                lpc[m] = tns->coef[w][filt][m - 1];
>>> +                for (i = 1; i < m; i++)
>>> +                    b[i] = lpc[i] + lpc[m] * lpc[m-i];
>>> +                for (i = 1; i < m; i++)
>>> +                    lpc[i] = b[i];
>>> +            }
>>
>> This loop looks oddly similar to the end of compute_lpc_coefs()
>> and eval_lpc_coeffs() can something be factored out here?
>
> Indeed, the 3GPP ref source calls this code the conversion of PARCOR
> (PARtial autoCORrelation, according to a quick google) coefficients to
> LPC coefficients. It doesn't, however, say what algorithm is used.
>
> Short of fully unrolling the Levinson-Durbin algorithm functions you
> mentioned and comparing to the aac.c code, it's not easy to see if
> they're identical or not, nor which should be used. I'll try comparing
> the results of some conversions before I resort to manual unrolling
> with pen and paper. :)

Hrm. I can't get eval_lpc_coeffs() to work with a coef input vector
populated from tns_tmp2_map.

static int eval_lpc_coeffs(const float *in, float *tgt, int n)
{
    int i, j;
    double f0, f1, f2;

    if (in[n] == 0)
        return -1;

    if ((f0 = *in) <= 0)
        return -1;

    in--; // To avoid a -1 subtraction in the inner loop

    for (i=1; i <= n; i++) {
        f1 = in[i+1];

        for (j=0; j < i - 1; j++)
            f1 += in[i-j]*tgt[j];

        tgt[i-1] = f2 = -f1/f0;
        for (j=0; j < i >> 1; j++) {
            float temp = tgt[j] + tgt[i-j-2]*f2;
            tgt[i-j-2] += tgt[j]*f2;
            tgt[j] = temp;
        }
        if ((f0 += f1*f2) < 0)
            return -1;
    }

    return 0;
}

It seems the various conditions on in[] and f0 cause it to exit with
an error with the coef[] vectors I've tried and as they're potentially
valid, that's disconcerting for using this code.

compute_lpc_coefs() accepts a two dimensional lpc array as an
argument. I'm guessing this so that the coefficients are available for
various orders ready for testing to choose which is best or something
like that.

Do you have any advice for how to proceed? I'm going to keep prodding
eval_lpc_coeffs() in the mean time.

Rob




More information about the ffmpeg-devel mailing list