# HG changeset patch # User vitor # Date 1226429438 0 # Node ID 3b52561535535d48d0df55e60bb6ff87bbc3b6fa # Parent 257459ea9e7b1c51232a156c109476da7486a0fd More OKed parts of the QCELP decoder patch by Kenan Gillet, kenan.gillet gmail com diff -r 257459ea9e7b -r 3b5256153553 qcelpdata.h --- a/qcelpdata.h Tue Nov 11 08:46:29 2008 +0000 +++ b/qcelpdata.h Tue Nov 11 18:50:38 2008 +0000 @@ -379,6 +379,38 @@ }; /** + * the final gain scalefactor before clipping into a usable output float + */ +#define QCELP_SCALE 8192. + +/** + * table for computing Ga (decoded linear codebook gain magnitude) + * + * @note The table could fit in int16_t in x*8 form, but it seems + * to be slower on x86 + * + * TIA/EIA/IS-733 2.4.6.2.1-3 + */ + +static const float qcelp_g12ga[61] = { + 1.000/QCELP_SCALE, 1.125/QCELP_SCALE, 1.250/QCELP_SCALE, 1.375/QCELP_SCALE, + 1.625/QCELP_SCALE, 1.750/QCELP_SCALE, 2.000/QCELP_SCALE, 2.250/QCELP_SCALE, + 2.500/QCELP_SCALE, 2.875/QCELP_SCALE, 3.125/QCELP_SCALE, 3.500/QCELP_SCALE, + 4.000/QCELP_SCALE, 4.500/QCELP_SCALE, 5.000/QCELP_SCALE, 5.625/QCELP_SCALE, + 6.250/QCELP_SCALE, 7.125/QCELP_SCALE, 8.000/QCELP_SCALE, 8.875/QCELP_SCALE, + 10.000/QCELP_SCALE, 11.250/QCELP_SCALE, 12.625/QCELP_SCALE, 14.125/QCELP_SCALE, + 15.875/QCELP_SCALE, 17.750/QCELP_SCALE, 20.000/QCELP_SCALE, 22.375/QCELP_SCALE, + 25.125/QCELP_SCALE, 28.125/QCELP_SCALE, 31.625/QCELP_SCALE, 35.500/QCELP_SCALE, + 39.750/QCELP_SCALE, 44.625/QCELP_SCALE, 50.125/QCELP_SCALE, 56.250/QCELP_SCALE, + 63.125/QCELP_SCALE, 70.750/QCELP_SCALE, 79.375/QCELP_SCALE, 89.125/QCELP_SCALE, + 100.000/QCELP_SCALE, 112.250/QCELP_SCALE, 125.875/QCELP_SCALE, 141.250/QCELP_SCALE, + 158.500/QCELP_SCALE, 177.875/QCELP_SCALE, 199.500/QCELP_SCALE, 223.875/QCELP_SCALE, + 251.250/QCELP_SCALE, 281.875/QCELP_SCALE, 316.250/QCELP_SCALE, 354.875/QCELP_SCALE, + 398.125/QCELP_SCALE, 446.625/QCELP_SCALE, 501.125/QCELP_SCALE, 563.375/QCELP_SCALE, + 631.000/QCELP_SCALE, 708.000/QCELP_SCALE, 794.375/QCELP_SCALE, 891.250/QCELP_SCALE, + 1000.000/QCELP_SCALE}; + +/** * circular codebook for rate 1 frames in x*100 form * * TIA/EIA/IS-733 2.4.6.1-2 @@ -428,4 +460,18 @@ }; #define QCELP_RATE_HALF_CODEBOOK_RATIO 0.5 +/** + * table for impulse response of BPF used to filter + * the white excitation for framerate 1/4 synthesis + * + * Only half the tables are needed because of symetry. + * + * TIA/EIA/IS-733 2.4.8.1.2-1.1 + */ +static const double qcelp_rnd_fir_coefs[11] = { + -1.344519e-1, 1.735384e-2, -6.905826e-2, 2.434368e-2, + -8.210701e-2, 3.041388e-2, -9.251384e-2, 3.501983e-2, + -9.918777e-2, 3.749518e-2, 8.985137e-1 +}; + #endif /* AVCODEC_QCELPDATA_H */ diff -r 257459ea9e7b -r 3b5256153553 qcelpdec.c --- a/qcelpdec.c Tue Nov 11 08:46:29 2008 +0000 +++ b/qcelpdec.c Tue Nov 11 18:50:38 2008 +0000 @@ -103,6 +103,39 @@ return memory + 143; } +/** + * 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]; + float weight; + + if (q->framerate >= RATE_QUARTER) { + weight = 0.25 * (subframe_num + 1); + } else if (q->framerate == RATE_OCTAVE && !subframe_num) { + weight = 0.625; + } else { + weight = 1.0; + } + + if (weight != 1.0) { + weighted_vector_sumf(interpolated_lspf, curr_lspf, q->prev_lspf, weight, 1.0 - weight, 10); + lspf2lpc(q, interpolated_lspf, lpc); + } else if (q->framerate >= RATE_QUARTER || (q->framerate == I_F_Q && !subframe_num)) + lspf2lpc(q, curr_lspf, lpc); +} + static int buf_size2framerate(const int buf_size) { switch (buf_size) { case 35: @@ -123,3 +156,14 @@ const char *message) { av_log(avctx, AV_LOG_WARNING, "Frame #%d, IFQ: %s\n", avctx->frame_number, message); } + +AVCodec qcelp_decoder = +{ + .name = "qcelp", + .type = CODEC_TYPE_AUDIO, + .id = CODEC_ID_QCELP, + .init = qcelp_decode_init, + .decode = qcelp_decode_frame, + .priv_data_size = sizeof(QCELPContext), + .long_name = NULL_IF_CONFIG_SMALL("QCELP / PureVoice"), +};