[FFmpeg-devel] [PATCH] QCELP decoder postfilter & final gain control

Kenan Gillet kenan.gillet
Thu Apr 16 00:42:58 CEST 2009


Hi Reynaldo,

On Wed, Apr 15, 2009 at 12:24 PM, Reynaldo H. Verdejo Pinochet
<reynaldo at opendot.cl> wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Hi
>
> Kenan Gillet wrote:
>>
>> I benchmarked ff_celp_lp_synthesis_filterf both with and without the trick
>> (patch attached), on a Core Duo 2Ghz, gcc 4.2.1, and did not find any
>> noticeable difference.
>
> Applied in r18528.


thanks and sorry for the delay but here is the updated version of the patches

Kenan
-------------- next part --------------
Index: libavcodec/celp_filters.c
===================================================================
--- libavcodec/celp_filters.c	(revision 18530)
+++ libavcodec/celp_filters.c	(working copy)
@@ -103,3 +103,23 @@
             out[n] -= filter_coeffs[i-1] * out[n-i];
     }
 }
+
+void ff_celp_lp_zero_synthesis_filterf(
+        float *out,
+        const float* filter_coeffs,
+        const float* in,
+        int buffer_length,
+        int filter_length)
+{
+    int i,n;
+
+    // Avoids a +1 in the inner loop.
+    filter_length++;
+
+    for(n=0; n<buffer_length; n++)
+    {
+        out[n] = in[n];
+        for(i=1; i<filter_length; i++)
+            out[n] -= filter_coeffs[i-1] * in[n-i];
+    }
+}
Index: libavcodec/celp_filters.h
===================================================================
--- libavcodec/celp_filters.h	(revision 18530)
+++ libavcodec/celp_filters.h	(working copy)
@@ -91,4 +91,26 @@
         int buffer_length,
         int filter_length);
 
+/**
+ * LP zero synthesis filter.
+ * @param out [out] pointer to output buffer
+ * @param filter_coeffs filter coefficients.
+ * @param in input signal
+ *        - the array in[-filter_length, -1] must
+ *        contain the previous input of this filter
+ * @param buffer_length amount of data to process
+ * @param filter_length filter length (10 for 10th order LP filter)
+ *
+ * @note Output buffer must contain filter_length samples of past
+ *       speech data before pointer.
+ *
+ * Routine applies A(z) filter to given speech data.
+ */
+void ff_celp_lp_zero_synthesis_filterf(
+        float *out,
+        const float* filter_coeffs,
+        const float* in,
+        int buffer_length,
+        int filter_length);
+
 #endif /* AVCODEC_CELP_FILTERS_H */
-------------- next part --------------
Index: libavcodec/qcelpdec.c
===================================================================
--- libavcodec/qcelpdec.c	(revision 18353)
+++ libavcodec/qcelpdec.c	(working copy)
@@ -66,6 +66,8 @@
     float    pitch_pre_filter_mem[303];
     float    rnd_fir_filter_mem[180];
     float    formant_mem[170];
+    float    postfilter_pole_mem[170];
+    float    prev_anti_tilt_filter_mem;
     float    last_codebook_gain;
     int      prev_g1[2];
     int      prev_bitrate;
@@ -656,6 +658,48 @@
         lspf2lpc(q->prev_lspf, lpc);
 }
 
+/**
+ * Apply postfilter in subframe steps.
+ *
+ * @param q the context
+ * @param outbuffer the ouput buffer,
+ *        it must be at least 40 float large
+ * @param lpc linear predictive coding coefficients
+ * @param formant_mem the formant filter memory,
+ *        it must contain 40 samples and 10 previous samples
+ * @param pole_mem the postfilter pole filter memory,
+ *        it must contain 40 samples and 10 previous samples
+ *
+ * TIA/EIA/IS-733 2.4.8.6
+ */
+static void do_postfilter(QCELPContext *q, float *outbuffer, const float *lpc,
+                          const float *formant_mem, float *pole_mem)
+{
+    float weighted_lpc[10];
+    float weight = -0.625;
+    int i;
+
+    for(i=0; i<10; i++)
+    {
+        weighted_lpc[i] = lpc[i] * weight;
+        weight *= 0.625;
+    }
+    ff_celp_lp_zero_synthesis_filterf(outbuffer, weighted_lpc, formant_mem, 40, 10);
+
+    weight = 0.775;
+    for(i=0; i<10; i++)
+    {
+        weighted_lpc[i] = lpc[i] * weight;
+        weight *= 0.775;
+    }
+    ff_celp_lp_synthesis_filterf(pole_mem, weighted_lpc, outbuffer, 40, 10);
+
+    outbuffer[0] = pole_mem[0] - 0.3 * q->prev_anti_tilt_filter_mem;
+    for(i=1; i<40; i++)
+        outbuffer[i] = pole_mem[i] - 0.3 * outbuffer[i-1];
+    q->prev_anti_tilt_filter_mem = outbuffer[39];
+}
+
 static qcelp_packet_rate buf_size2bitrate(const int buf_size)
 {
     switch(buf_size)
@@ -823,16 +867,19 @@
         interpolate_lpc(q, quantized_lspf, lpc, i);
         ff_celp_lp_synthesis_filterf(formant_mem, lpc, outbuffer + i * 40, 40,
                                      10);
+        do_postfilter(q, outbuffer + i * 40, lpc, formant_mem,
+                      q->postfilter_pole_mem + 10 + i * 40);
         formant_mem += 40;
     }
     memcpy(q->formant_mem, q->formant_mem + 160, 10 * sizeof(float));
+    memcpy(q->postfilter_pole_mem,  q->postfilter_pole_mem  + 160, 10 * sizeof(float));
 
-    // FIXME: postfilter and final gain control should be here.
+    // FIXME: final gain control should be here.
     // TIA/EIA/IS-733 2.4.8.6
 
     formant_mem = q->formant_mem + 10;
     for(i=0; i<160; i++)
-        *outbuffer++ = av_clipf(*formant_mem++, QCELP_CLIP_LOWER_BOUND,
+        outbuffer[i] = av_clipf(outbuffer[i], QCELP_CLIP_LOWER_BOUND,
                                 QCELP_CLIP_UPPER_BOUND);
 
     memcpy(q->prev_lspf, quantized_lspf, sizeof(q->prev_lspf));
-------------- next part --------------
--- libavcodec/qcelpdec.c	2009-04-08 20:51:06.000000000 -0700
+++ libavcodec/qcelpdec-w-postfilter.c	2009-04-08 21:00:31.000000000 -0700
@@ -68,6 +68,7 @@ typedef struct
     float    formant_mem[170];
     float    postfilter_pole_mem[170];
     float    prev_anti_tilt_filter_mem;
+    float    final_gain;
     float    last_codebook_gain;
     int      prev_g1[2];
     int      prev_bitrate;
@@ -99,6 +100,8 @@ static av_cold int qcelp_decode_init(AVC
     for(i=0; i<10; i++)
         q->prev_lspf[i] = (i+1)/11.;
 
+    q->final_gain = 1.;
+
     return 0;
 }
 
@@ -779,7 +782,7 @@ static int qcelp_decode_frame(AVCodecCon
     int buf_size = avpkt->size;
     QCELPContext *q = avctx->priv_data;
     float *outbuffer = data;
-    int   i;
+    int   i, j;
     float quantized_lspf[10], lpc[10];
     float gain[16];
     float *formant_mem;
@@ -874,13 +877,16 @@ erasure:
     memcpy(q->formant_mem, q->formant_mem + 160, 10 * sizeof(float));
     memcpy(q->postfilter_pole_mem,  q->postfilter_pole_mem  + 160, 10 * sizeof(float));
 
-    // FIXME: final gain control should be here.
-    // TIA/EIA/IS-733 2.4.8.6
-
     formant_mem = q->formant_mem + 10;
-    for(i=0; i<160; i++)
-        outbuffer[i] = av_clipf(outbuffer[i], QCELP_CLIP_LOWER_BOUND,
-                                QCELP_CLIP_UPPER_BOUND);
+    for(i=0; i<4; i++)
+    {
+        q->final_gain = 0.9375 * q->final_gain
+                      + 0.0625 * compute_gain_ctrl(formant_mem + i * 40, outbuffer + i * 40, 40);
+
+        for(j=0; j<40; j++)
+            outbuffer[j + i*40] = av_clipf(q->final_gain * outbuffer[j + i*40],
+                                           QCELP_CLIP_LOWER_BOUND, QCELP_CLIP_UPPER_BOUND);
+    }
 
     memcpy(q->prev_lspf, quantized_lspf, sizeof(q->prev_lspf));
     q->prev_bitrate = q->bitrate;



More information about the ffmpeg-devel mailing list