[FFmpeg-devel] [PATCH] QCELP decoder

Michael Niedermayer michaelni
Thu Oct 30 14:16:10 CET 2008


On Tue, Oct 28, 2008 at 04:47:02PM -0700, Kenan Gillet wrote:
> On Tue, Oct 28, 2008 at 4:43 PM, Kenan Gillet <kenan.gillet at gmail.com> wrote:
> > thanks Diego and Michael for your reviewing.
> >
> > And here is an updated set of patches with a few changes too.
> >
> > round 7 summary:
> > - qcelp-round7-doc-glue.patch.txt has already been oked
> > - grammar / spelling / cosmetics
> > - generalize convolve function used in qcelp_lspf2lpc
> > - remove some multiplication and division in compute_svector
> > - frame unpacking rework
> > - most of the previous comments
> >
> 
> forgot one patch in previous mail :(
[..]

> +/**
> + * pre-calculated table for hammsinc function
> + * Only half of the tables is needed because of symetry.
> + *
> + * TIA/EIA/IS-733 2.4.5.2-2/3
> + */
> +static const float qcelp_hammsinc_table[4] = { -0.006822,  0.041249, -0.143459,  0.588863};
> +
> +typedef struct {
> +    uint8_t index;  /*!< index into the QCELPContext structure */
> +    uint8_t bitpos; /*!< position of the lowet bit in the value's byte */
> +    uint8_t bitlen; /*!< number of bits to read */
> +} QCELPBitmap;
> +
> +#define QCELP_OF(variable, bit, len) {offsetof(QCELPContext, variable), bit, len}
> +
> +/**
> + * bitmap unpacking tables for RATE_FULL
> + *
> + * TIA/EIA/IS-733 Table 2.4.7.1-1
> + */
> +static const QCELPBitmap qcelp_rate_full_bitmap[] = {
> +                                // start on bit
> +    QCELP_OF(lspv  [ 2], 0, 3), // 265
> +    QCELP_OF(lspv  [ 1], 0, 7), // 262
> +    QCELP_OF(lspv  [ 0], 0, 6), // 255
> +    QCELP_OF(lspv  [ 4], 0, 6), // 249
> +    QCELP_OF(lspv  [ 3], 0, 6), // 243
> +    QCELP_OF(lspv  [ 2], 3, 4), // 237
> +    QCELP_OF(cbsign[ 0], 0, 1), // 233
> +    QCELP_OF(cbgain[ 0], 0, 4), // 232
> +    QCELP_OF(pfrac [ 0], 0, 1), // 228
> +    QCELP_OF(plag  [ 0], 0, 7), // 227
> +    QCELP_OF(pgain [ 0], 0, 3), // 220
> +    QCELP_OF(cindex[ 1], 0, 4), // 217
> +    QCELP_OF(cbsign[ 1], 0, 1), // 213
> +    QCELP_OF(cbgain[ 1], 0, 4), // 212
> +    QCELP_OF(cindex[ 0], 0, 7), // 208
> +    QCELP_OF(cbgain[ 3], 0, 1), // 201
> +    QCELP_OF(cindex[ 2], 0, 7), // 200
> +    QCELP_OF(cbsign[ 2], 0, 1), // 193
> +    QCELP_OF(cbgain[ 2], 0, 4), // 192
> +    QCELP_OF(cindex[ 1], 4, 3), // 188
> +    QCELP_OF(plag  [ 1], 0, 3), // 185
> +    QCELP_OF(pgain [ 1], 0, 3), // 182
> +    QCELP_OF(cindex[ 3], 0, 7), // 179
> +    QCELP_OF(cbsign[ 3], 0, 1), // 172
> +    QCELP_OF(cbgain[ 3], 1, 2), // 171
> +    QCELP_OF(cindex[ 4], 0, 6), // 169
> +    QCELP_OF(cbsign[ 4], 0, 1), // 163
> +    QCELP_OF(cbgain[ 4], 0, 4), // 162
> +    QCELP_OF(pfrac [ 1], 0, 1), // 158
> +    QCELP_OF(plag  [ 1], 3, 4), // 157
> +    QCELP_OF(cbgain[ 6], 0, 3), // 153
> +    QCELP_OF(cindex[ 5], 0, 7), // 150
> +    QCELP_OF(cbsign[ 5], 0, 1), // 143
> +    QCELP_OF(cbgain[ 5], 0, 4), // 142
> +    QCELP_OF(cindex[ 4], 6, 1), // 138
> +    QCELP_OF(cindex[ 7], 0, 3), // 137
> +    QCELP_OF(cbsign[ 7], 0, 1), // 134
> +    QCELP_OF(cbgain[ 7], 0, 3), // 133
> +    QCELP_OF(cindex[ 6], 0, 7), // 130
> +    QCELP_OF(cbsign[ 6], 0, 1), // 123
> +    QCELP_OF(cbgain[ 6], 3, 1), // 122
> +    QCELP_OF(cbgain[ 8], 0, 1), // 121
> +    QCELP_OF(pfrac [ 2], 0, 1), // 120
> +    QCELP_OF(plag  [ 2], 0, 7), // 119
> +    QCELP_OF(pgain [ 2], 0, 3), // 112
> +    QCELP_OF(cindex[ 7], 3, 4), // 109
> +    QCELP_OF(cbsign[ 9], 0, 1), // 105
> +    QCELP_OF(cbgain[ 9], 0, 4), // 104
> +    QCELP_OF(cindex[ 8], 0, 7), // 100
> +    QCELP_OF(cbsign[ 8], 0, 1), //  93
> +    QCELP_OF(cbgain[ 8], 1, 3), //  92
> +    QCELP_OF(cindex[10], 0, 4), //  89
> +    QCELP_OF(cbsign[10], 0, 1), //  85
> +    QCELP_OF(cbgain[10], 0, 4), //  84
> +    QCELP_OF(cindex[ 9], 0, 7), //  80
> +    QCELP_OF(pgain [ 3], 0, 2), //  73
> +    QCELP_OF(cindex[11], 0, 7), //  71
> +    QCELP_OF(cbsign[11], 0, 1), //  64
> +    QCELP_OF(cbgain[11], 0, 3), //  63
> +    QCELP_OF(cindex[10], 4, 3), //  60
> +    QCELP_OF(cindex[12], 0, 2), //  57
> +    QCELP_OF(cbsign[12], 0, 1), //  55
> +    QCELP_OF(cbgain[12], 0, 4), //  54
> +    QCELP_OF(pfrac [ 3], 0, 1), //  50
> +    QCELP_OF(plag  [ 3], 0, 7), //  49
> +    QCELP_OF(pgain [ 3], 2, 1), //  42
> +    QCELP_OF(cindex[13], 0, 6), //  41
> +    QCELP_OF(cbsign[13], 0, 1), //  35
> +    QCELP_OF(cbgain[13], 0, 4), //  34
> +    QCELP_OF(cindex[12], 2, 5), //  30
> +    QCELP_OF(cbgain[15], 0, 3), //  25
> +    QCELP_OF(cindex[14], 0, 7), //  22
> +    QCELP_OF(cbsign[14], 0, 1), //  15
> +    QCELP_OF(cbgain[14], 0, 4), //  14
> +    QCELP_OF(cindex[13], 6, 1), //  10
> +    QCELP_OF(reserved,   0, 2), //   9
> +    QCELP_OF(cindex[15], 0, 7), //   7
> +    QCELP_OF(cbsign[15], 0, 1)  //   0
> +};
> +
> +/**
> + * bitmap unpacking tables for RATE_HALF
> + *
> + * TIA/EIA/IS-733 Table 2.4.7.2-1
> + */
> +static const QCELPBitmap qcelp_rate_half_bitmap[] = {
> +                               // start on bit
> +    QCELP_OF(lspv  [2], 0, 3), // 123
> +    QCELP_OF(lspv  [1], 0, 7), // 120
> +    QCELP_OF(lspv  [0], 0, 6), // 113
> +    QCELP_OF(lspv  [4], 0, 6), // 107
> +    QCELP_OF(lspv  [3], 0, 6), // 101
> +    QCELP_OF(lspv  [2], 3, 4), //  95
> +    QCELP_OF(cbsign[0], 0, 1), //  91
> +    QCELP_OF(cbgain[0], 0, 4), //  90
> +    QCELP_OF(pfrac [0], 0, 1), //  86
> +    QCELP_OF(plag  [0], 0, 7), //  85
> +    QCELP_OF(pgain [0], 0, 3), //  78
> +    QCELP_OF(plag  [1], 0, 6), //  75
> +    QCELP_OF(pgain [1], 0, 3), //  69
> +    QCELP_OF(cindex[0], 0, 7), //  66
> +    QCELP_OF(pgain [2], 0, 2), //  59
> +    QCELP_OF(cindex[1], 0, 7), //  57
> +    QCELP_OF(cbsign[1], 0, 1), //  50
> +    QCELP_OF(cbgain[1], 0, 4), //  49
> +    QCELP_OF(pfrac [1], 0, 1), //  45
> +    QCELP_OF(plag  [1], 6, 1), //  44
> +    QCELP_OF(cindex[2], 0, 2), //  43
> +    QCELP_OF(cbsign[2], 0, 1), //  41
> +    QCELP_OF(cbgain[2], 0, 4), //  40
> +    QCELP_OF(pfrac [2], 0, 1), //  36
> +    QCELP_OF(plag  [2], 0, 7), //  35
> +    QCELP_OF(pgain [2], 2, 1), //  28
> +    QCELP_OF(pfrac [3], 0, 1), //  27
> +    QCELP_OF(plag  [3], 0, 7), //  26
> +    QCELP_OF(pgain [3], 0, 3), //  19
> +    QCELP_OF(cindex[2], 2, 5), //  16
> +    QCELP_OF(cindex[3], 0, 7), //  11
> +    QCELP_OF(cbsign[3], 0, 1), //   4
> +    QCELP_OF(cbgain[3], 0, 4)  //   3
> +};
> +
> +/**
> + * bitmap unpacking tables for RATE_QUARTER
> + *
> + * TIA/EIA/IS-733 Table 2.4.7.3-1
> + */
> +static const QCELPBitmap qcelp_rate_quarter_bitmap[] = {
> +                               // start on bit
> +    QCELP_OF(lspv  [2], 0, 3), // 53
> +    QCELP_OF(lspv  [1], 0, 7), // 50
> +    QCELP_OF(lspv  [0], 0, 6), // 43
> +    QCELP_OF(lspv  [4], 0, 6), // 37
> +    QCELP_OF(lspv  [3], 0, 6), // 31
> +    QCELP_OF(lspv  [2], 3, 4), // 25
> +    QCELP_OF(cbgain[3], 0, 4), // 21
> +    QCELP_OF(cbgain[2], 0, 4), // 17
> +    QCELP_OF(cbgain[1], 0, 4), // 13
> +    QCELP_OF(cbgain[0], 0, 4), //  9
> +    QCELP_OF(reserved,  0, 2), //  5
> +    QCELP_OF(cbgain[4], 0, 4)  //  3
> +};
> +
> +/**
> + * bitmap unpacking tables for RATE_OCTAVE
> + *
> + * trick: CBSEED is written into QCELPContext.cbsign[15],
> + * which is not used for RATE_OCTAVE.
> + * CBSEED is only used to ensure the occurrence of random bit
> + * patterns in the 16 first bits that are used as the seed.
> + *
> + * TIA/EIA/IS-733 Table 2.4.7.4-1
> + */
> +static const QCELPBitmap qcelp_rate_octave_bitmap[] = {
> +                                // start on bit
> +    QCELP_OF(cbsign[15], 3, 1), // 19
> +    QCELP_OF(lspv   [0], 0, 1), // 18
> +    QCELP_OF(lspv   [1], 0, 1), // 17
> +    QCELP_OF(lspv   [2], 0, 1), // 16
> +    QCELP_OF(cbsign[15], 2, 1), // 15
> +    QCELP_OF(lspv   [3], 0, 1), // 14
> +    QCELP_OF(lspv   [4], 0, 1), // 13
> +    QCELP_OF(lspv   [5], 0, 1), // 12
> +    QCELP_OF(cbsign[15], 1, 1), // 11
> +    QCELP_OF(lspv   [6], 0, 1), // 10
> +    QCELP_OF(lspv   [7], 0, 1), //  9
> +    QCELP_OF(lspv   [8], 0, 1), //  8
> +    QCELP_OF(cbsign[15], 0, 1), //  7
> +    QCELP_OF(lspv   [9], 0, 1), //  6
> +    QCELP_OF(cbgain [0], 0, 2), //  7
> +    QCELP_OF(reserved,   0, 4)  //  3
> +};
> +
> +/**
> + * position of the bitmapping data for each packet type in
> + * the QCELPContext
> + */
> +static const QCELPBitmap * const qcelp_unpacking_bitmaps_per_rate[5] = {
> +    NULL,                     ///!< for SILENCE rate
> +    qcelp_rate_octave_bitmap,
> +    qcelp_rate_quarter_bitmap,
> +    qcelp_rate_half_bitmap,
> +    qcelp_rate_full_bitmap,
> +};
> +
> +static const uint16_t qcelp_bits_per_rate[5] = {
> +    0, ///!< for SILENCE rate
> +    FF_ARRAY_ELEMS(qcelp_rate_octave_bitmap),
> +    FF_ARRAY_ELEMS(qcelp_rate_quarter_bitmap),
> +    FF_ARRAY_ELEMS(qcelp_rate_half_bitmap),
> +    FF_ARRAY_ELEMS(qcelp_rate_full_bitmap),
> +};

ok

[...]
> +static void interpolate_lspf(float *interpolated_lspf,
> +                             const float curr_weight,
> +                             const float *curr_lspf,
> +                             const float *prev_lspf) {
> +    int   i;
> +
> +    for (i = 0; i < 10; i++)
> +        interpolated_lspf[i] = (1.0 - curr_weight) * prev_lspf[i]
> +                             +        curr_weight  * curr_lspf[i];
> +}

iam ok with the code but the names have to be changed
both fixed point (ff_acelp_weighted_vector_sum) and this should have
similar names
now imho *celp and lsp dont belong in the names as the code is not specific
for that.


[...]
> +/**
> + * Computes the scaled codebook vector Cdn From INDEX and GAIN
> + * for all rates.
> + *
> + * The specification lacks some information here.
> + *
> + * TIA/EIA/IS-733 has an omission on the codebook index determination
> + * formula for RATE_FULL and RATE_HALF frames at section 2.4.8.1.1. It says
> + * you have to subtract the decoded index parameter from the given scaled
> + * codebook vector index 'n' to get the desired circular codebook index, but
> + * it does not mention that you have to clamp 'n' to [0-9] in order to get
> + * RI-compliant results.
> + *
> + * The reason for this mistake seems to be the fact they forgot to mention you
> + * have to do these calculations per codebook subframe and adjust given
> + * equation values accordingly.
> + *
> + * @param q the context
> + * @param gain array holding the 4 pitch subframe gain values
> + * other than RATE_FULL or RATE_HALF
> + * @param cdn_vector array for the generated scaled codebook vector
> + */
> +static void compute_svector(const QCELPContext *q,
> +                            float *gain,
> +                            float *cdn_vector) {
> +    int      i, j, k;
> +    uint16_t cbseed, cindex;
> +    float    rnd[160];
> +
> +    switch (q->framerate) {
> +    case RATE_FULL:
> +        for (i = 0; i < 16; i++) {
> +            gain[i] *= QCELP_RATE_FULL_CODEBOOK_RATIO;
> +            cindex = -q->cindex[i];
> +            for (j = 0; j < 10; j++)
> +                *cdn_vector++ = gain[i] * qcelp_rate_full_codebook[cindex++ & 127];

the & 127 can be avoided by making the qcelp_rate_full_codebook table 10
entries larger. (of course only if this matters in terms of overall decoder
speed)


> +        }
> +        break;
> +    case RATE_HALF:
> +        for (i = 0; i < 4; i++) {
> +            gain[i] *= QCELP_RATE_HALF_CODEBOOK_RATIO;
> +            cindex = -q->cindex[i];
> +            for (j = 0; j < 40; j++)
> +                *cdn_vector++ = gain[i] * qcelp_rate_half_codebook[cindex++ & 127];

same, but 40 entries


> +        }
> +        break;
> +    case RATE_QUARTER:
> +        cbseed = (0x0003 & q->lspv[4])<<14 |
> +                 (0x003F & q->lspv[3])<< 8 |
> +                 (0x0060 & q->lspv[2])<< 1 |
> +                 (0x0007 & q->lspv[1])<< 3 |
> +                 (0x0038 & q->lspv[0])>> 3 ;
> +        cindex = 0;

> +        for (i = 0; i < 8; i++) {
> +            gain[i] *= QCELP_SQRT1887 / 32768.0;
> +            for (k = 0; k < 20; k++) {
> +                cbseed = 521 * cbseed + 259;
> +                rnd[cindex] = (int16_t)cbseed;
> +
> +                // FIR filter
> +                *cdn_vector = qcelp_rnd_fir_coefs[1] * rnd[cindex];
> +                for (j = 1; j < 22 && !(cindex-j+1); j++)
> +                    *cdn_vector += qcelp_rnd_fir_coefs[j] * rnd[cindex-j];

the !(cindex-j+1) check can be removed when rnd is made larger, which imho
is a good idea anyway even if theres no meassureable speed gain.

also isnt this doing the same as convolve() ?


[...]
> +/**
> + * Apply generic gain control.
> + *
> + * @param v_out output vector
> + * @param v_in vector to control gain of
> + * @param v_gain gain-controlled vector
> + *
> + * TIA/EIA/IS-733 2.4.8.3-2/3/4/5, 2.4.8.6
> + */
> +static void apply_gain_ctrl(float *v_out,
> +                            const float *v_in,
> +                            const float *v_gain) {
> +    int   i, j, len;
> +    float scalefactor;
> +
> +    for (i = 0, j = 0; i < 4; i++) {
> +        scalefactor = ff_dot_productf(v_gain + j, v_gain + j, 40);
> +        if (scalefactor) {
> +            scalefactor = sqrt(ff_dot_productf(v_in + j, v_in + j, 40) / scalefactor);
> +            for (len = j + 40; j < len; j++)
> +                v_out[j] = scalefactor * v_gain[j];
> +        }
> +    }
> +}

is it intdended that j is not increased when scalefactor == 0 ?


> +
> +/**
> + * Apply filter in pitch-subframe steps.
> + *
> + * @param memory buffer for the previous state of the filter
> + *        - must be able to contain 303 elements
> + *        - the 143 first elements are from the previous state
> + *        - the next 160 are for output
> + * @param v_in input filter vector
> + * @param gain per-subframe gain array, each element is between 0.0 and 2.0
> + * @param lag per-subframe lag array, each element is
> + *        - between 16 and 143 if its corresponding pfrac is 0,
> + *        - between 16 and 139 otherwise
> + * @param pfrac per-subframe boolean array, 1 if the lag is fractional, 0 otherwise
> + *
> + * @return filter output vector
> + */
> +static const float *do_pitchfilter(float memory[303],
> +                                   const float v_in[160],
> +                                   const float gain[4],
> +                                   const uint8_t *lag,
> +                                   const uint8_t pfrac[4]) {
> +    int         i, j;
> +    float       *v_lag, *v_out;
> +    const float *v_len;
> +
> +    v_out = memory + 143; // Output vector starts at memory[143].
> +
> +    for (i = 0; i < 4; i++)
> +        if (gain[i]) {
> +            v_lag = memory + 143 + 40 * i - lag[i];
> +            for (v_len = v_in + 40; v_in < v_len; v_in++) {
> +                if (pfrac[i]) { // If it is a fractional lag...
> +                    for (j = 0, *v_out = 0.; j < 4; j++)
> +                        *v_out += qcelp_hammsinc_table[j] * (v_lag[j-4] + v_lag[3-j]);
> +                } else
> +                    *v_out = *v_lag;
> +
> +                *v_out = *v_in + gain[i] * *v_out;
> +
> +                v_lag++;
> +                v_out++;
> +            }
> +        } else {
> +            memcpy(v_out, v_in, 40 * sizeof(float));
> +            v_in  += 40;
> +            v_out += 40;
> +        }
> +
> +    memmove(memory, memory + 160, 143 * sizeof(float));
> +    return memory + 143;
> +}

ok


> +
> +/**
> + * Apply pitch synthesis filter and pitch prefilter to the scaled codebook vector.
> + * TIA/EIA/IS-733 2.4.5.2
> + *
> + * @param q the context
> + * @param cdn_vector the scaled codebook vector
> + *
> + * @return 0 if everything goes well, -1 if frame should be erased
> + */
> +static int apply_pitch_filters(QCELPContext *q,
> +                               float *cdn_vector) {
> +    int         i;
> +    float       gain[4];
> +    const float *v_synthesis_filtered, *v_pre_filtered;
> +
> +    if (q->framerate >= RATE_HALF ||
> +       (q->framerate == I_F_Q && (q->prev_framerate >= RATE_HALF))) {
> +
> +        if (q->framerate >= RATE_HALF) {
> +
> +            // Compute gain & lag for the whole frame.
> +            for (i = 0; i < 4; i++) {
> +                gain[i] = q->plag[i] ? (q->pgain[i] + 1) / 4.0 : 0.0;
> +
> +                q->plag[i] += 16;
> +
> +                if (q->pfrac[i] && q->plag[i] >= 140)
> +                    return -1;
> +            }
> +            memcpy(q->prev_pitch_lag, q->plag, 4 * sizeof(*q->plag));
> +        } else {
> +            gain[3] = q->erasure_count < 3 ? 0.9 - 0.3 * (q->erasure_count - 1)
> +                                           : 0.0;
> +            for (i = 0; i < 4; i++)
> +                gain[i] = FFMIN(q->prev_pitch_gain[i], gain[3]);
> +
> +            memset(q->pfrac, 0, 4 *sizeof(*q->pfrac));
> +            memcpy(q->plag, q->prev_pitch_lag, 4 * sizeof(*q->plag));
> +        }
> +
> +        // pitch synthesis filter
> +        v_synthesis_filtered = do_pitchfilter(q->pitch_synthesis_filter_mem, cdn_vector,
> +                                              gain, q->plag, q->pfrac);
> +
> +        // pitch prefilter update
> +        for (i = 0; i < 4; i++)
> +            gain[i] = 0.5 * FFMIN(gain[i], 1.0);
> +
> +        v_pre_filtered = do_pitchfilter(q->pitch_pre_filter_mem, v_synthesis_filtered,
> +                                        gain, q->plag, q->pfrac);
> +
> +        apply_gain_ctrl(cdn_vector, v_synthesis_filtered, v_pre_filtered);
> +
> +        memcpy(q->prev_pitch_gain, gain, sizeof(q->prev_pitch_gain));
> +
> +    } else {
> +        memcpy(q->pitch_synthesis_filter_mem, cdn_vector + 17, 143 * sizeof(float));
> +        memcpy(q->pitch_pre_filter_mem,       cdn_vector + 17, 143 * sizeof(float));
> +        memset(q->prev_pitch_gain, 0, sizeof(q->prev_pitch_gain));
> +        memset(q->prev_pitch_lag,  0, 4 * sizeof(*q->plag));
> +    }

> +    q->prev_framerate = q->framerate;

Is setting this here correct? i mean its possible that this function is
called twice ...


> +
> +    return 0;
> +}
> +
> +/**
> + * Interpolates LSP frequencies and computes LPC coefficients
> + * for a given framerate & pitch subframe.
> + *
> + * TIA/EIA/IS-733 2.4.3.3.4
> + *
> + * @param q the context
> + * @param curr_lspf LSP frequencies vector of the current frame
> + * @param lpc float vector for the resulting LPC
> + * @param subframe_num frame number in decoded stream
> + */
> +void interpolate_lpc(QCELPContext *q,
> +                     const float *curr_lspf,
> +                     float *lpc,
> +                     const int subframe_num) {
> +    float interpolated_lspf[10];
> +
> +    if (q->framerate >= RATE_QUARTER) {
> +        interpolate_lspf(interpolated_lspf, 0.25 * (subframe_num + 1),
> +                         curr_lspf, q->prev_lspf);
> +        lspf2lpc(q, interpolated_lspf, lpc);
> +    } else if (q->framerate == RATE_OCTAVE) {
> +        if (!subframe_num) {
> +            interpolate_lspf(interpolated_lspf, 0.625, curr_lspf, q->prev_lspf);
> +            lspf2lpc(q, interpolated_lspf, lpc);
> +        }
> +    } else {
> +        assert(q->framerate == I_F_Q);
> +
> +        if (!subframe_num)
> +            lspf2lpc(q, curr_lspf, lpc);
> +    }

some code like
if/else/switch/whatever weight=

if(weight==1.0){
    lspf2lpc(q, curr_lspf, lpc);
}else if(weight){
    interpolate_lspf(interpolated_lspf, weight, curr_lspf, q->prev_lspf);
    lspf2lpc(q, interpolated_lspf, lpc);
}

might be cleaner, it also would skip the interpolate_lspf for >= RATE_QUARTER
in the last subframe


> +}
> +
> +/*
> + * Determine the framerate from the frame size and/or the first byte of the frame.
> + *
> + * @return 0 on success, negative error number otherwise.
> + */
> +static int determine_framerate(AVCodecContext *avctx,
> +                               QCELPContext *q,
> +                               const int buf_size,
> +                               uint8_t **buf) {
> +    int claimed_rate = -1;
> +
> +    switch (buf_size) {
> +    case 35: claimed_rate = RATE_FULL;
> +    case 34: q->framerate = RATE_FULL;
> +             break;
> +
> +    case 17: claimed_rate = RATE_HALF;
> +    case 16: q->framerate = RATE_HALF;
> +             break;
> +
> +    case  8: claimed_rate = RATE_QUARTER;
> +    case  7: q->framerate = RATE_QUARTER;
> +             break;
> +
> +    case  4: claimed_rate = RATE_OCTAVE;
> +    case  3: q->framerate = RATE_OCTAVE;
> +             break;
> +
> +    case  1: claimed_rate = SILENCE;
> +    case  0: q->framerate = SILENCE;
> +             break;
> +
> +    default:
> +        return -1;
> +    }
> +
> +    if (claimed_rate >= 0) {
> +        q->framerate = *(*buf)++;
> +
> +        if (claimed_rate != q->framerate)
> +            av_log(avctx, AV_LOG_WARNING, "Claimed framerate and buffer size mismatch.\n");
> +    } else
> +        av_log(avctx, AV_LOG_WARNING,
> +               "Framerate byte is missing, guessing the framerate from packet size.\n");
> +

putting a switch for 34,16,7,3,0 in a seperate function the following could
be used:

q->framerate= foo(buf_size);
if(q->framerate < 0){
    q->framerate = *(*buf)++;

    if (foo(buf_size+1) != q->framerate)
        av_log(avctx, AV_LOG_WARNING, "Claimed framerate and buffer size mismatch.\n");
}else{
 ...



[...]

> +static void warn_insufficient_frame_quality(AVCodecContext *avctx,
> +                                            const char *message) {
> +    av_log(avctx, AV_LOG_WARNING, "Frame #%d, IFQ: %s\n", avctx->frame_number, message);
> +}

ok


> +
> +/**
> + * Decodes the scaled codebook vector Cdn.
> + *
> + * @param q the context
> + * @param cdn_vector array for the generated scaled codebook vector
> + * @return 0  on success, -1 if the frame must be erased
> + */
> +static int decode_scaled_codebook_vector(QCELPContext *q,
> +                                         float cdn_vector[160]) {
> +    float gain[16];
> +
> +    if (decode_gain_and_index(q, gain) < 0)
> +        return -1;
> +    compute_svector(q, gain, cdn_vector);
> +    return 0;
> +}

i was wondering if this wraper function that is used 2x around 2 functions
is worth it
no strong oppinion here, just wondering ...


[...]



> Index: libavcodec/celp_filters.c
> ===================================================================
> --- libavcodec/celp_filters.c	(revision 15692)
> +++ libavcodec/celp_filters.c	(working copy)
> @@ -84,3 +84,24 @@
>  
>      return 0;
>  }
> +
> +void ff_celp_lp_synthesis_filterf(
> +        float *out,
> +        const float* filter_coeffs,
> +        const float* in,
> +        int buffer_length,
> +        int filter_length)
> +{
> +    int i,n;
> +
> +    // These two lines are to avoid a -1 subtraction in the main loop
> +    filter_length++;
> +    filter_coeffs--;
> +
> +    for(n=0; n<buffer_length; n++)
> +    {
> +        out[n] = in[n];
> +        for(i=1; i<filter_length; i++)
> +            out[n] += filter_coeffs[i] * out[n-i];
> +    }
> +}

ok


> Index: libavcodec/celp_filters.h
> ===================================================================
> --- libavcodec/celp_filters.h	(revision 15692)
> +++ libavcodec/celp_filters.h	(working copy)
> @@ -69,4 +69,28 @@
>          int stop_on_overflow,
>          int rounder);
>  
> +/**
> + * LP synthesis filter.
> + * @param out [out] pointer to output buffer
> + *        - the array out[-filter_length, -1] must
> + *        contain the previous result of this filter
> + * @param filter_coeffs filter coefficients.
> + * @param in input signal
> + * @param buffer_length amount of data to process
> + * @param filter_length filter length (10 for 10th order LP filter)
> + *
> + * @return 1 if overflow occurred, 0 - otherwise

hmm void == 1 || 0 ?

[...]


> Index: libavcodec/celp_math.c
> ===================================================================
> --- libavcodec/celp_math.c	(revision 15692)
> +++ libavcodec/celp_math.c	(working copy)
> @@ -195,3 +195,14 @@
>  
>      return (power_int << 15) + value;
>  }
> +
> +float ff_dot_productf(const float* a, const float* b, int length)
> +{
> +    float sum = 0;
> +    int i;
> +
> +    for(i=0; i<length; i++)
> +        sum += a[i] * b[i];
> +
> +    return sum;
> +}
> Index: libavcodec/celp_math.h
> ===================================================================
> --- libavcodec/celp_math.h	(revision 15692)
> +++ libavcodec/celp_math.h	(working copy)
> @@ -83,4 +83,14 @@
>      else           return value <<  offset;
>  }
>  
> +/**
> + * returns the dot product.
> + * @param a input data array
> + * @param b input data array
> + * @param length number of elements
> + *
> + * @return dot product = sum of elementwise products
> + */
> +extern float ff_dot_productf(const float* a, const float* b, int length);
> +
>  #endif /* AVCODEC_CELP_MATH_H */

ok

[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

When the tyrant has disposed of foreign enemies by conquest or treaty, and
there is nothing more to fear from them, then he is always stirring up
some war or other, in order that the people may require a leader. -- Plato
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20081030/15928cca/attachment.pgp>



More information about the ffmpeg-devel mailing list