[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