[FFmpeg-soc] [PATCH] AMR-WB Decoder

Rob robert.swain at gmail.com
Mon Aug 30 15:00:44 CEST 2010


On 30 August 2010 14:31, Vitor Sessak <vitor1001 at gmail.com> wrote:
> On 08/27/2010 11:13 PM, Marcelo Galvão Póvoa wrote:
>> On 26 August 2010 18:55, Vitor Sessak<vitor1001 at gmail.com>  wrote:
>>> Marcelo Galvão Póvoa wrote:

[...]

>>>> +/**
>>>> + * Generate the high-band excitation with the same energy from the
>>>> lower
>>>> + * one and scaled by the given gain
>>>> + *
>>>> + * @param[in] ctx                  The context
>>>> + * @param[out] hb_exc              Buffer for the excitation
>>>> + * @param[in] synth_exc            Low-band excitation used for
>>>> synthesis
>>>> + * @param[in] hb_gain              Wanted excitation gain
>>>> + */
>>>> +static void scaled_hb_excitation(AMRWBContext *ctx, float *hb_exc,
>>>> +                                 const float *synth_exc, float hb_gain)
>>>> +{
>>>> +    int i;
>>>> +    float energy = ff_dot_productf(synth_exc, synth_exc,
>>>> AMRWB_SFR_SIZE);
>>>> +
>>>> +    /* Generate a white-noise excitation */
>>>> +    for (i = 0; i<  AMRWB_SFR_SIZE_16k; i++)
>>>> +        hb_exc[i] = 32768.0 - (uint16_t) av_lfg_get(&ctx->prng);
>>>> +
>>>> +    ff_scale_vector_to_given_sum_of_squares(hb_exc, hb_exc, energy,
>>>> +                                            AMRWB_SFR_SIZE_16k);
>>>> +
>>>> +    for (i = 0; i<  AMRWB_SFR_SIZE_16k; i++)
>>>> +        hb_exc[i] *= hb_gain;
>>>> +}
>>>
>>> Why are you scaling it twice?
>>
>> The first scaling is to match the energy with the lower band part. The
>> second is the high_band gain itself. This can be done in only one loop
>> using ff_scale_vector_to_given_sum_of_squares() ?
>
> I think you will be obliged to duplicate a little of
>  ff_scale_vector_to_given_sum_of_squares(), but it will make your code
> faster...

The point is to avoid iterating over the subframe to multiply by some
value twice by merging the two beforehand and then applying to the
vector. Looking at the code:

void ff_scale_vector_to_given_sum_of_squares(float *out, const float *in,
                                             float sum_of_squares, const int n)
{
    int i;
    float scalefactor = ff_dot_productf(in, in, n);
    if (scalefactor)
        scalefactor = sqrt(sum_of_squares / scalefactor);
    for (i = 0; i < n; i++)
        out[i] = in[i] * scalefactor;
}

We want:
scalefactor * hb_gain =
sqrt(sum_of_squares / ff_dot_productf(in, in, n)) * hb_gain =
sqrt(sum_of_squares * hb_gain * hb_gain / ff_dot_productf())
hb_gain is [0.1, 1.0] according to find_hb_gain() so there's no sign
issue

So you should just be able to pass in energy * hb_gain * hb_gain I
think. Or duplicate the code.

Best regards,
Rob


More information about the FFmpeg-soc mailing list