X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fqcelpdec.c;h=0df30daf34c5eceb19c4387f3351f9dad12eae1f;hb=643fc8f1076bce3c971b09400019397be98065de;hp=9546bec3231e65e8a93e6fe094f429c81455e410;hpb=b12c76277bdb2e8637a3ddbbcdf0625152557f7d;p=ffmpeg diff --git a/libavcodec/qcelpdec.c b/libavcodec/qcelpdec.c index 9546bec3231..0df30daf34c 100644 --- a/libavcodec/qcelpdec.c +++ b/libavcodec/qcelpdec.c @@ -20,21 +20,25 @@ */ /** - * @file qcelpdec.c + * @file libavcodec/qcelpdec.c * QCELP decoder * @author Reynaldo H. Verdejo Pinochet * @remark FFmpeg merging spearheaded by Kenan Gillet + * @remark Development mentored by Benjamin Larson */ #include #include "avcodec.h" -#include "bitstream.h" +#include "internal.h" +#include "get_bits.h" #include "qcelpdata.h" #include "celp_math.h" #include "celp_filters.h" +#include "acelp_vectors.h" +#include "lsp.h" #undef NDEBUG #include @@ -69,26 +73,9 @@ typedef struct float pitch_gain[4]; uint8_t pitch_lag[4]; uint16_t first16bits; + uint8_t warned_buf_mismatch_bitrate; } QCELPContext; -/** - * Reconstructs LPC coefficients from the line spectral pair frequencies. - * - * TIA/EIA/IS-733 2.4.3.3.5 - */ -void ff_qcelp_lspf2lpc(const float *lspf, float *lpc); - -static void weighted_vector_sumf(float *out, const float *in_a, - const float *in_b, float weight_coeff_a, - float weight_coeff_b, int length) -{ - int i; - - for(i=0; iprev_lspf, smooth, 1.0-smooth, 10); + ff_weighted_vector_sumf(lspf, lspf, q->prev_lspf, smooth, 1.0-smooth, 10); }else { q->octave_count = 0; @@ -256,7 +243,7 @@ static void decode_gain_and_index(QCELPContext *q, gain[2] = gain[1]; gain[1] = 0.6*gain[0] + 0.4*gain[1]; } - }else + }else if (q->bitrate != SILENCE) { if(q->bitrate == RATE_OCTAVE) { @@ -412,22 +399,46 @@ static void compute_svector(QCELPContext *q, const float *gain, *cdn_vector++ = tmp_gain * qcelp_rate_full_codebook[cbseed++ & 127]; } break; + case SILENCE: + memset(cdn_vector, 0, 160 * sizeof(float)); + break; } } /** - * Apply generic gain control. + * Compute the gain control * - * @param v_out output vector * @param v_in gain-controlled vector * @param v_ref vector to control gain of * + * @return gain control + * * FIXME: If v_ref is a zero vector, it energy is zero * and the behavior of the gain control is * undefined in the specs. * * TIA/EIA/IS-733 2.4.8.3-2/3/4/5, 2.4.8.6 */ +static float compute_gain_ctrl(const float *v_ref, const float *v_in, const int len) +{ + float scalefactor = ff_dot_productf(v_in, v_in, len); + + if(scalefactor) + scalefactor = sqrt(ff_dot_productf(v_ref, v_ref, len) / scalefactor); + else + av_log_missing_feature(NULL, "Zero energy for gain control", 1); + return scalefactor; +} + +/** + * Apply generic gain control. + * + * @param v_out output vector + * @param v_in gain-controlled vector + * @param v_ref vector to control gain of + * + * TIA/EIA/IS-733 2.4.8.3, 2.4.8.6 + */ static void apply_gain_ctrl(float *v_out, const float *v_ref, const float *v_in) { @@ -436,12 +447,7 @@ static void apply_gain_ctrl(float *v_out, const float *v_ref, for(i=0, j=0; i<4; i++) { - scalefactor = ff_dot_productf(v_in + j, v_in + j, 40); - if(scalefactor) - scalefactor = sqrt(ff_dot_productf(v_ref + j, v_ref + j, 40) - / scalefactor); - else - av_log_missing_feature(NULL, "Zero energy for gain control", 1); + scalefactor = compute_gain_ctrl(v_ref + j, v_in + j, 40); for(len=j+40; jbitrate >= RATE_HALF || + q->bitrate == SILENCE || (q->bitrate == I_F_Q && (q->prev_bitrate >= RATE_HALF))) { @@ -533,7 +540,19 @@ static void apply_pitch_filters(QCELPContext *q, float *cdn_vector) } }else { - float max_pitch_gain = q->erasure_count < 3 ? 0.9 - 0.3 * (q->erasure_count - 1) : 0.0; + float max_pitch_gain; + + if (q->bitrate == I_F_Q) + { + if (q->erasure_count < 3) + max_pitch_gain = 0.9 - 0.3 * (q->erasure_count - 1); + else + max_pitch_gain = 0.0; + }else + { + assert(q->bitrate == SILENCE); + max_pitch_gain = 1.0; + } for(i=0; i<4; i++) q->pitch_gain[i] = FFMIN(q->pitch_gain[i], max_pitch_gain); @@ -565,11 +584,41 @@ static void apply_pitch_filters(QCELPContext *q, float *cdn_vector) } } +/** + * Reconstructs LPC coefficients from the line spectral pair frequencies + * and performs bandwidth expansion. + * + * @param lspf line spectral pair frequencies + * @param lpc linear predictive coding coefficients + * + * @note: bandwidth_expansion_coeff could be precalculated into a table + * but it seems to be slower on x86 + * + * TIA/EIA/IS-733 2.4.3.3.5 + */ +static void lspf2lpc(const float *lspf, float *lpc) +{ + double lsp[10]; + double bandwidth_expansion_coeff = QCELP_BANDWIDTH_EXPANSION_COEFF; + int i; + + for (i=0; i<10; i++) + lsp[i] = cos(M_PI * lspf[i]); + + ff_acelp_lspd2lpc(lsp, lpc); + + for (i=0; i<10; i++) + { + lpc[i] *= bandwidth_expansion_coeff; + bandwidth_expansion_coeff *= QCELP_BANDWIDTH_EXPANSION_COEFF; + } +} + /** * Interpolates LSP frequencies and computes LPC coefficients * for a given bitrate & pitch subframe. * - * TIA/EIA/IS-733 2.4.3.3.4 + * TIA/EIA/IS-733 2.4.3.3.4, 2.4.8.7.2 * * @param q the context * @param curr_lspf LSP frequencies vector of the current frame @@ -591,15 +640,17 @@ void interpolate_lpc(QCELPContext *q, const float *curr_lspf, float *lpc, if(weight != 1.0) { - weighted_vector_sumf(interpolated_lspf, curr_lspf, q->prev_lspf, - weight, 1.0 - weight, 10); - ff_qcelp_lspf2lpc(interpolated_lspf, lpc); + ff_weighted_vector_sumf(interpolated_lspf, curr_lspf, q->prev_lspf, + weight, 1.0 - weight, 10); + lspf2lpc(interpolated_lspf, lpc); }else if(q->bitrate >= RATE_QUARTER || (q->bitrate == I_F_Q && !subframe_num)) - ff_qcelp_lspf2lpc(curr_lspf, lpc); + lspf2lpc(curr_lspf, lpc); + else if(q->bitrate == SILENCE && !subframe_num) + lspf2lpc(q->prev_lspf, lpc); } -static int buf_size2bitrate(const int buf_size) +static qcelp_packet_rate buf_size2bitrate(const int buf_size) { switch(buf_size) { @@ -610,7 +661,7 @@ static int buf_size2bitrate(const int buf_size) case 1: return SILENCE; } - return -1; + return I_F_Q; } /** @@ -625,8 +676,8 @@ static int buf_size2bitrate(const int buf_size) * * TIA/EIA/IS-733 2.4.8.7.1 */ -static int determine_bitrate(AVCodecContext *avctx, const int buf_size, - uint8_t **buf) +static qcelp_packet_rate determine_bitrate(AVCodecContext *avctx, const int buf_size, + const uint8_t **buf) { qcelp_packet_rate bitrate; @@ -634,8 +685,13 @@ static int determine_bitrate(AVCodecContext *avctx, const int buf_size, { if(bitrate > **buf) { + QCELPContext *q = avctx->priv_data; + if (!q->warned_buf_mismatch_bitrate) + { av_log(avctx, AV_LOG_WARNING, "Claimed bitrate and buffer size mismatch.\n"); + q->warned_buf_mismatch_bitrate = 1; + } bitrate = **buf; }else if(bitrate < **buf) { @@ -653,9 +709,8 @@ static int determine_bitrate(AVCodecContext *avctx, const int buf_size, if(bitrate == SILENCE) { - // FIXME: the decoder should not handle SILENCE frames as I_F_Q frames - av_log_missing_feature(avctx, "Blank frame", 1); - bitrate = I_F_Q; + //FIXME: Remove experimental warning when tested with samples. + av_log_ask_for_sample(avctx, "'Blank frame handling is experimental."); } return bitrate; } @@ -668,8 +723,10 @@ static void warn_insufficient_frame_quality(AVCodecContext *avctx, } static int qcelp_decode_frame(AVCodecContext *avctx, void *data, int *data_size, - uint8_t *buf, const int buf_size) + AVPacket *avpkt) { + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; QCELPContext *q = avctx->priv_data; float *outbuffer = data; int i;