Merge remote-tracking branch 'qatar/master'
[ffmpeg.git] / libavcodec / g729postfilter.c
index 9af6014..fc90374 100644 (file)
@@ -111,7 +111,7 @@ static int16_t long_term_filter(DSPContext *dsp, int pitch_delay_int,
                                 const int16_t* residual, int16_t *residual_filt,
                                 int subframe_size)
 {
-    int i, k, n, tmp, tmp2;
+    int i, k, tmp, tmp2;
     int sum;
     int L_temp0;
     int L_temp1;
@@ -163,7 +163,7 @@ static int16_t long_term_filter(DSPContext *dsp, int pitch_delay_int,
 
     ener = dsp->scalarproduct_int16(sig_scaled + RES_PREV_DATA_SIZE,
                                     sig_scaled + RES_PREV_DATA_SIZE,
-                                    subframe_size, 0);
+                                    subframe_size);
     if (ener) {
         sh_ener = FFMAX(av_log2(ener) - 14, 0);
         ener >>= sh_ener;
@@ -192,7 +192,7 @@ static int16_t long_term_filter(DSPContext *dsp, int pitch_delay_int,
         for (i = pitch_delay_int - 1; i <= pitch_delay_int + 1; i++) {
             sum = dsp->scalarproduct_int16(sig_scaled + RES_PREV_DATA_SIZE,
                                            sig_scaled + RES_PREV_DATA_SIZE - i,
-                                           subframe_size, 0);
+                                           subframe_size);
             if (sum > corr_int_num) {
                 corr_int_num = sum;
                 best_delay_int = i;
@@ -202,7 +202,7 @@ static int16_t long_term_filter(DSPContext *dsp, int pitch_delay_int,
             /* Compute denominator of pseudo-normalized correlation R'(0). */
             corr_int_den = dsp->scalarproduct_int16(sig_scaled - best_delay_int + RES_PREV_DATA_SIZE,
                                                     sig_scaled - best_delay_int + RES_PREV_DATA_SIZE,
-                                                    subframe_size, 0);
+                                                    subframe_size);
 
             /* Compute signals with non-integer delay k (with 1/8 precision),
                where k is in [0;6] range.
@@ -229,7 +229,7 @@ static int16_t long_term_filter(DSPContext *dsp, int pitch_delay_int,
             for (k = 0; k < ANALYZED_FRAC_DELAYS; k++) {
                 sum = dsp->scalarproduct_int16(&delayed_signal[k][1],
                                                &delayed_signal[k][1],
-                                               subframe_size - 1, 0);
+                                               subframe_size - 1);
                 corr_den[k][0] = sum + delayed_signal[k][0            ] * delayed_signal[k][0            ];
                 corr_den[k][1] = sum + delayed_signal[k][subframe_size] * delayed_signal[k][subframe_size];
 
@@ -257,7 +257,7 @@ static int16_t long_term_filter(DSPContext *dsp, int pitch_delay_int,
                            correlation R'(k). */
                         sum = dsp->scalarproduct_int16(&delayed_signal[k][i],
                                                        sig_scaled + RES_PREV_DATA_SIZE,
-                                                       subframe_size, 0);
+                                                       subframe_size);
                         gain_num_short = FFMAX(sum >> sh_gain_num, 0);
 
                         /*
@@ -314,7 +314,7 @@ static int16_t long_term_filter(DSPContext *dsp, int pitch_delay_int,
         /* Compute R'(k) correlation's numerator. */
         sum = dsp->scalarproduct_int16(residual_filt,
                                        sig_scaled + RES_PREV_DATA_SIZE,
-                                       subframe_size, 0);
+                                       subframe_size);
 
         if (sum < 0) {
             gain_long_num = 0;
@@ -327,7 +327,7 @@ static int16_t long_term_filter(DSPContext *dsp, int pitch_delay_int,
         }
 
         /* Compute R'(k) correlation's denominator. */
-        sum = dsp->scalarproduct_int16(residual_filt, residual_filt, subframe_size, 0);
+        sum = dsp->scalarproduct_int16(residual_filt, residual_filt, subframe_size);
 
         tmp = FFMAX(av_log2(sum) - 14, 0);
         sum >>= tmp;
@@ -433,12 +433,12 @@ static int16_t get_tilt_comp(DSPContext *dsp, int16_t *lp_gn,
     lp_gn[10] = 4096; //1.0 in (3.12)
 
     /* Apply 1/A(z/FORMANT_PP_FACTOR_DEN) filter to hf. */
-    ff_celp_lp_synthesis_filter(lp_gn + 11, lp_gd + 1, lp_gn + 11, 22, 10, 0, 0x800);
+    ff_celp_lp_synthesis_filter(lp_gn + 11, lp_gd + 1, lp_gn + 11, 22, 10, 0, 0, 0x800);
     /* Now lp_gn (starting with 10) contains impulse response
        of A(z/FORMANT_PP_FACTOR_NUM)/A(z/FORMANT_PP_FACTOR_DEN) filter. */
 
-    rh0 = dsp->scalarproduct_int16(lp_gn + 10, lp_gn + 10, 20, 0);
-    rh1 = dsp->scalarproduct_int16(lp_gn + 10, lp_gn + 11, 20, 0);
+    rh0 = dsp->scalarproduct_int16(lp_gn + 10, lp_gn + 10, 20);
+    rh1 = dsp->scalarproduct_int16(lp_gn + 10, lp_gn + 11, 20);
 
     /* downscale to avoid overflow */
     temp = av_log2(rh0) - 14;
@@ -511,12 +511,12 @@ static int16_t apply_tilt_comp(int16_t* out, int16_t* res_pst, int refl_coeff,
     return tmp;
 }
 
-void g729_postfilter(DSPContext *dsp, int16_t* ht_prev_data, int16_t* voicing,
+void ff_g729_postfilter(DSPContext *dsp, int16_t* ht_prev_data, int* voicing,
                      const int16_t *lp_filter_coeffs, int pitch_delay_int,
                      int16_t* residual, int16_t* res_filter_data,
                      int16_t* pos_filter_data, int16_t *speech, int subframe_size)
 {
-    int16_t residual_filt_buf[SUBFRAME_SIZE+10];
+    int16_t residual_filt_buf[SUBFRAME_SIZE+11];
     int16_t lp_gn[33]; // (3.12)
     int16_t lp_gd[11]; // (3.12)
     int tilt_comp_coeff;
@@ -554,9 +554,57 @@ void g729_postfilter(DSPContext *dsp, int16_t* ht_prev_data, int16_t* voicing,
     /* Apply second half of short-term postfilter: 1/A(z/FORMANT_PP_FACTOR_DEN) */
     ff_celp_lp_synthesis_filter(pos_filter_data + 10, lp_gd + 1,
                                 residual_filt_buf + 10,
-                                subframe_size, 10, 0, 0x800);
+                                subframe_size, 10, 0, 0, 0x800);
     memcpy(pos_filter_data, pos_filter_data + subframe_size, 10 * sizeof(int16_t));
 
     *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 ff_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;
+}