[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