| @@ -145,6 +145,7 @@ typedef struct { | |||
| int16_t onset; ///< detected onset level (0-2) | |||
| int16_t was_periodic; ///< whether previous frame was declared as periodic or not (4.4) | |||
| int16_t ht_prev_data; ///< previous data for 4.2.3, equation 86 | |||
| int gain_coeff; ///< (1.14) gain coefficient (4.2.4) | |||
| uint16_t rand_value; ///< random number generator value (4.4.4) | |||
| int ma_predictor_prev; ///< switched MA predictor of LSP quantizer from last good frame | |||
| @@ -348,6 +349,8 @@ static av_cold int decoder_init(AVCodecContext * avctx) | |||
| /* Both 8kbit/s and 6.4kbit/s modes uses two subframes per frame. */ | |||
| avctx->frame_size = SUBFRAME_SIZE << 1; | |||
| ctx->gain_coeff = 16384; // 1.0 in (1.14) | |||
| for (k = 0; k < MA_NP + 1; k++) { | |||
| ctx->past_quantizer_outputs[k] = ctx->past_quantizer_output_buf[k]; | |||
| for (i = 1; i < 11; i++) | |||
| @@ -397,6 +400,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, | |||
| int16_t fc[SUBFRAME_SIZE]; // fixed-codebook vector | |||
| int16_t synth[SUBFRAME_SIZE+10]; // fixed-codebook vector | |||
| int j; | |||
| int gain_before, gain_after; | |||
| int is_periodic = 0; // whether one of the subframes is declared as periodic or not | |||
| if (*data_size < SUBFRAME_SIZE << 2) { | |||
| @@ -637,6 +641,11 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, | |||
| /* Save data (without postfilter) for use in next subframe. */ | |||
| memcpy(ctx->syn_filter_data, synth+SUBFRAME_SIZE, 10 * sizeof(int16_t)); | |||
| /* Calculate gain of unfiltered signal for use in AGC. */ | |||
| gain_before = 0; | |||
| for (j = 0; j < SUBFRAME_SIZE; j++) | |||
| gain_before += FFABS(synth[j+10]); | |||
| /* Call postfilter and also update voicing decision for use in next frame. */ | |||
| g729_postfilter( | |||
| &ctx->dsp, | |||
| @@ -650,6 +659,18 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, | |||
| synth+10, | |||
| SUBFRAME_SIZE); | |||
| /* Calculate gain of filtered signal for use in AGC. */ | |||
| gain_after = 0; | |||
| for(j=0; j<SUBFRAME_SIZE; j++) | |||
| gain_after += FFABS(synth[j+10]); | |||
| ctx->gain_coeff = g729_adaptive_gain_control( | |||
| gain_before, | |||
| gain_after, | |||
| synth+10, | |||
| SUBFRAME_SIZE, | |||
| ctx->gain_coeff); | |||
| if (frame_erasure) | |||
| ctx->pitch_delay_int_prev = FFMIN(ctx->pitch_delay_int_prev + 1, PITCH_DELAY_MAX); | |||
| else | |||
| @@ -560,3 +560,51 @@ void g729_postfilter(DSPContext *dsp, int16_t* ht_prev_data, int16_t* voicing, | |||
| *ht_prev_data = apply_tilt_comp(speech, pos_filter_data + 10, tilt_comp_coeff, | |||
| subframe_size, *ht_prev_data); | |||
| } | |||
| /** | |||
| * \brief Adaptive gain control (4.2.4) | |||
| * \param gain_before gain of speech before applying postfilters | |||
| * \param gain_after gain of speech after applying postfilters | |||
| * \param speech [in/out] signal buffer | |||
| * \param subframe_size length of subframe | |||
| * \param gain_prev (3.12) previous value of gain coefficient | |||
| * | |||
| * \return (3.12) last value of gain coefficient | |||
| */ | |||
| int16_t g729_adaptive_gain_control(int gain_before, int gain_after, int16_t *speech, | |||
| int subframe_size, int16_t gain_prev) | |||
| { | |||
| int gain; // (3.12) | |||
| int n; | |||
| int exp_before, exp_after; | |||
| if(!gain_after && gain_before) | |||
| return 0; | |||
| if (gain_before) { | |||
| exp_before = 14 - av_log2(gain_before); | |||
| gain_before = bidir_sal(gain_before, exp_before); | |||
| exp_after = 14 - av_log2(gain_after); | |||
| gain_after = bidir_sal(gain_after, exp_after); | |||
| if (gain_before < gain_after) { | |||
| gain = (gain_before << 15) / gain_after; | |||
| gain = bidir_sal(gain, exp_after - exp_before - 1); | |||
| } else { | |||
| gain = ((gain_before - gain_after) << 14) / gain_after + 0x4000; | |||
| gain = bidir_sal(gain, exp_after - exp_before); | |||
| } | |||
| gain = (gain * G729_AGC_FAC1 + 0x4000) >> 15; // gain * (1-0.9875) | |||
| } else | |||
| gain = 0; | |||
| for (n = 0; n < subframe_size; n++) { | |||
| // gain_prev = gain + 0.9875 * gain_prev | |||
| gain_prev = (G729_AGC_FACTOR * gain_prev + 0x4000) >> 15; | |||
| gain_prev = av_clip_int16(gain + gain_prev); | |||
| speech[n] = av_clip_int16((speech[n] * gain_prev + 0x2000) >> 14); | |||
| } | |||
| return gain_prev; | |||
| } | |||
| @@ -39,6 +39,13 @@ | |||
| #define FORMANT_PP_FACTOR_NUM 18022 //0.55 in Q15 | |||
| #define FORMANT_PP_FACTOR_DEN 22938 //0.70 in Q15 | |||
| /** | |||
| * gain adjustment factor (G.729, 4.2.4) | |||
| * 0.9875 in Q15 | |||
| */ | |||
| #define G729_AGC_FACTOR 32358 | |||
| #define G729_AGC_FAC1 (32768-G729_AGC_FACTOR) | |||
| /** | |||
| * 1.0 / (1.0 + 0.5) in Q15 | |||
| * where 0.5 is the minimum value of | |||
| @@ -92,4 +99,17 @@ void g729_postfilter(DSPContext *dsp, int16_t* ht_prev_data, int16_t* voicing, | |||
| int16_t* pos_filter_data, int16_t *speech, | |||
| int subframe_size); | |||
| /** | |||
| * \brief Adaptive gain control (4.2.4) | |||
| * \param gain_before (Q0) gain of speech before applying postfilters | |||
| * \param gain_after (Q0) gain of speech after applying postfilters | |||
| * \param speech [in/out] (Q0) signal buffer | |||
| * \param subframe_size length of subframe | |||
| * \param gain_prev (Q12) previous value of gain coefficient | |||
| * | |||
| * \return (Q12) last value of gain coefficient | |||
| */ | |||
| int16_t g729_adaptive_gain_control(int gain_before, int gain_after, int16_t *speech, | |||
| int subframe_size, int16_t gain_prev); | |||
| #endif // FFMPEG_G729POSTFILTER_H | |||