mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
Adaptive gain control
This commit is contained in:
parent
aca516cd67
commit
682337672c
@ -145,6 +145,7 @@ typedef struct {
|
|||||||
int16_t onset; ///< detected onset level (0-2)
|
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 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
|
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)
|
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
|
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. */
|
/* Both 8kbit/s and 6.4kbit/s modes uses two subframes per frame. */
|
||||||
avctx->frame_size = SUBFRAME_SIZE << 1;
|
avctx->frame_size = SUBFRAME_SIZE << 1;
|
||||||
|
|
||||||
|
ctx->gain_coeff = 16384; // 1.0 in (1.14)
|
||||||
|
|
||||||
for (k = 0; k < MA_NP + 1; k++) {
|
for (k = 0; k < MA_NP + 1; k++) {
|
||||||
ctx->past_quantizer_outputs[k] = ctx->past_quantizer_output_buf[k];
|
ctx->past_quantizer_outputs[k] = ctx->past_quantizer_output_buf[k];
|
||||||
for (i = 1; i < 11; i++)
|
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 fc[SUBFRAME_SIZE]; // fixed-codebook vector
|
||||||
int16_t synth[SUBFRAME_SIZE+10]; // fixed-codebook vector
|
int16_t synth[SUBFRAME_SIZE+10]; // fixed-codebook vector
|
||||||
int j;
|
int j;
|
||||||
|
int gain_before, gain_after;
|
||||||
int is_periodic = 0; // whether one of the subframes is declared as periodic or not
|
int is_periodic = 0; // whether one of the subframes is declared as periodic or not
|
||||||
|
|
||||||
if (*data_size < SUBFRAME_SIZE << 2) {
|
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. */
|
/* Save data (without postfilter) for use in next subframe. */
|
||||||
memcpy(ctx->syn_filter_data, synth+SUBFRAME_SIZE, 10 * sizeof(int16_t));
|
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. */
|
/* Call postfilter and also update voicing decision for use in next frame. */
|
||||||
g729_postfilter(
|
g729_postfilter(
|
||||||
&ctx->dsp,
|
&ctx->dsp,
|
||||||
@ -650,6 +659,18 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size,
|
|||||||
synth+10,
|
synth+10,
|
||||||
SUBFRAME_SIZE);
|
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)
|
if (frame_erasure)
|
||||||
ctx->pitch_delay_int_prev = FFMIN(ctx->pitch_delay_int_prev + 1, PITCH_DELAY_MAX);
|
ctx->pitch_delay_int_prev = FFMIN(ctx->pitch_delay_int_prev + 1, PITCH_DELAY_MAX);
|
||||||
else
|
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,
|
*ht_prev_data = apply_tilt_comp(speech, pos_filter_data + 10, tilt_comp_coeff,
|
||||||
subframe_size, *ht_prev_data);
|
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_NUM 18022 //0.55 in Q15
|
||||||
#define FORMANT_PP_FACTOR_DEN 22938 //0.70 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
|
* 1.0 / (1.0 + 0.5) in Q15
|
||||||
* where 0.5 is the minimum value of
|
* 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,
|
int16_t* pos_filter_data, int16_t *speech,
|
||||||
int subframe_size);
|
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
|
#endif // FFMPEG_G729POSTFILTER_H
|
||||||
|
Loading…
Reference in New Issue
Block a user