# HG changeset patch # User vitor # Date 1227292756 0 # Node ID cc1e8c59f1e8097f43acfc0bae14614af39279d8 # Parent e596efd84d270b84c14a0e76676390cb0e9f6970 More OKed parts of the QCELP decoder patch by Kenan Gillet, kenan.gillet gmail com diff -r e596efd84d27 -r cc1e8c59f1e8 qcelpdata.h --- a/qcelpdata.h Fri Nov 21 17:38:14 2008 +0000 +++ b/qcelpdata.h Fri Nov 21 18:39:16 2008 +0000 @@ -391,6 +391,16 @@ #define QCELP_SCALE 8192. /** + * the upper boundary of the clipping, depends on QCELP_SCALE + */ +#define QCELP_CLIP_UPPER_BOUND (8191.75/8192.) + +/** + * the lower boundary of the clipping, depends on QCELP_SCALE + */ +#define QCELP_CLIP_LOWER_BOUND -1. + +/** * table for computing Ga (decoded linear codebook gain magnitude) * * @note The table could fit in int16_t in x*8 form, but it seems @@ -470,7 +480,7 @@ /** * sqrt(1.887) is the maximum of the pseudorandom * white sequence used to generate the scaled codebook - * vector for framerate 1/4. + * vector for bitrate 1/4. * * TIA/EIA/IS-733 2.4.8.1.2 */ @@ -478,7 +488,7 @@ /** * table for impulse response of BPF used to filter - * the white excitation for framerate 1/4 synthesis + * the white excitation for bitrate 1/4 synthesis * * Only half the tables are needed because of symmetry. * @@ -490,4 +500,20 @@ -9.918777e-2, 3.749518e-2, 8.985137e-1 }; +/** + * This spread factor is used, for bitrate 1/8 and I_F_Q, + * to force the LSP frequencies to be at least 80 Hz apart. + * + * TIA/EIA/IS-733 2.4.3.3.2 + */ +#define QCELP_LSP_SPREAD_FACTOR 0.02 + +/** + * predictor coefficient for the conversion of LSP codes + * to LSP frequencies for 1/8 and I_F_Q + * + * TIA/EIA/IS-733 2.4.3.2.7-2 + */ +#define QCELP_LSP_OCTAVE_PREDICTOR 29.0/32 + #endif /* AVCODEC_QCELPDATA_H */ diff -r e596efd84d27 -r cc1e8c59f1e8 qcelpdec.c --- a/qcelpdec.c Fri Nov 21 17:38:14 2008 +0000 +++ b/qcelpdec.c Fri Nov 21 18:39:16 2008 +0000 @@ -69,6 +69,116 @@ } /** + * Decodes the 10 quantized LSP frequencies from the LSPV/LSP + * transmission codes of any bitrate and checks for badly received packets. + * + * @param q the context + * @param lspf line spectral pair frequencies + * + * @return 0 on success, -1 if the packet is badly received + * + * TIA/EIA/IS-733 2.4.3.2.6.2-2, 2.4.8.7.3 + */ +static int decode_lspf(QCELPContext *q, + float *lspf) { + int i; + float tmp_lspf; + + if (q->bitrate == RATE_OCTAVE || + q->bitrate == I_F_Q) { + float smooth; + const float *predictors = (q->prev_bitrate != RATE_OCTAVE && + q->prev_bitrate != I_F_Q ? q->prev_lspf + : q->predictor_lspf); + + if (q->bitrate == RATE_OCTAVE) { + q->octave_count++; + + for (i = 0; i < 10; i++) { + q->predictor_lspf[i] = + lspf[i] = (q->lspv[i] ? QCELP_LSP_SPREAD_FACTOR + : -QCELP_LSP_SPREAD_FACTOR) + + predictors[i] * QCELP_LSP_OCTAVE_PREDICTOR + + (i + 1) * ((1 - QCELP_LSP_OCTAVE_PREDICTOR)/11); + } + smooth = (q->octave_count < 10 ? .875 : 0.1); + } else { + float erasure_coeff = QCELP_LSP_OCTAVE_PREDICTOR; + + assert(q->bitrate == I_F_Q); + + if (q->erasure_count > 1) + erasure_coeff *= (q->erasure_count < 4 ? 0.9 : 0.7); + + for (i = 0; i < 10; i++) { + q->predictor_lspf[i] = + lspf[i] = (i + 1) * ( 1 - erasure_coeff)/11 + + erasure_coeff * predictors[i]; + } + smooth = 0.125; + } + + // Check the stability of the LSP frequencies. + lspf[0] = FFMAX(lspf[0], QCELP_LSP_SPREAD_FACTOR); + for (i = 1; i < 10; i++) + lspf[i] = FFMAX(lspf[i], (lspf[i-1] + QCELP_LSP_SPREAD_FACTOR)); + + lspf[9] = FFMIN(lspf[9], (1.0 - QCELP_LSP_SPREAD_FACTOR)); + for (i = 9; i > 0; i--) + lspf[i-1] = FFMIN(lspf[i-1], (lspf[i] - QCELP_LSP_SPREAD_FACTOR)); + + // Low-pass filter the LSP frequencies. + weighted_vector_sumf(lspf, lspf, q->prev_lspf, smooth, 1.0 - smooth, 10); + } else { + q->octave_count = 0; + + tmp_lspf = 0.; + for (i = 0; i < 5 ; i++) { + lspf[2*i+0] = tmp_lspf += qcelp_lspvq[i][q->lspv[i]][0] * 0.0001; + lspf[2*i+1] = tmp_lspf += qcelp_lspvq[i][q->lspv[i]][1] * 0.0001; + } + + // Check for badly received packets. + if (q->bitrate == RATE_QUARTER) { + if (lspf[9] <= .70 || lspf[9] >= .97) + return -1; + for (i = 3; i < 10; i++) + if (fabs(lspf[i] - lspf[i-2]) < .08) + return -1; + } else { + if (lspf[9] <= .66 || lspf[9] >= .985) + return -1; + for (i = 4; i < 10; i++) + if (fabs(lspf[i] - lspf[i-4]) < .0931) + return -1; + } + } + return 0; +} + +/** + * If the received packet is Rate 1/4 a further sanity check is made of the codebook gain. + * + * @param cbgain the unpacked cbgain array + * @return -1 if the sanity check fails, 0 otherwise + * + * TIA/EIA/IS-733 2.4.8.7.3 + */ +static int codebook_sanity_check_for_rate_quarter(const uint8_t *cbgain) { + int i, prev_diff=0; + + for (i = 1; i < 5; i++) { + int diff = cbgain[i] - cbgain[i-1]; + if (FFABS(diff) > 10) + return -1; + else if (FFABS(diff - prev_diff) > 12) + return -1; + prev_diff = diff; + } + return 0; +} + +/** * Computes the scaled codebook vector Cdn From INDEX and GAIN * for all rates. * @@ -96,7 +206,7 @@ uint16_t cbseed, cindex; float *rnd, tmp_gain, fir_filter_value; - switch (q->framerate) { + switch (q->bitrate) { case RATE_FULL: for (i = 0; i < 16; i++) { tmp_gain = gain[i] * QCELP_RATE_FULL_CODEBOOK_RATIO; @@ -248,7 +358,7 @@ /** * Interpolates LSP frequencies and computes LPC coefficients - * for a given framerate & pitch subframe. + * for a given bitrate & pitch subframe. * * TIA/EIA/IS-733 2.4.3.3.4 * @@ -263,9 +373,9 @@ float interpolated_lspf[10]; float weight; - if(q->framerate >= RATE_QUARTER) + if(q->bitrate >= RATE_QUARTER) weight = 0.25 * (subframe_num + 1); - else if(q->framerate == RATE_OCTAVE && !subframe_num) + else if(q->bitrate == RATE_OCTAVE && !subframe_num) weight = 0.625; else weight = 1.0; @@ -275,11 +385,11 @@ weighted_vector_sumf(interpolated_lspf, curr_lspf, q->prev_lspf, weight, 1.0 - weight, 10); qcelp_lspf2lpc(interpolated_lspf, lpc); - }else if(q->framerate >= RATE_QUARTER || (q->framerate == I_F_Q && !subframe_num)) + }else if(q->bitrate >= RATE_QUARTER || (q->bitrate == I_F_Q && !subframe_num)) qcelp_lspf2lpc(curr_lspf, lpc); } -static int buf_size2framerate(const int buf_size) +static int buf_size2bitrate(const int buf_size) { switch(buf_size) {