[FFmpeg-devel] [PATCH] QCELP decoder

Vitor Sessak vitor1001
Thu Oct 30 22:07:45 CET 2008


Michael Niedermayer wrote:
> 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

Commited

>> +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

Should I add a qcelpdec.c file and commit this?

>> +
>> +/**
>> + * 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

Commited.

>> 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 ?

Oops, commited by error, should I revert?

> 
>> 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

Commited.

-Vitor




More information about the ffmpeg-devel mailing list