www.pudn.com > g729.rar > postfilt.c
/*
ITU-T G.729A Speech Coder ANSI-C Source Code
Version 1.1 Last modified: September 1996
Copyright (c) 1996,
AT&T, France Telecom, NTT, Universite de Sherbrooke
All rights reserved.
*/
/*------------------------------------------------------------------------*
* POSTFILTER.C *
*------------------------------------------------------------------------*
* Performs adaptive postfiltering on the synthesis speech *
* This file contains all functions related to the post filter. *
*------------------------------------------------------------------------*/
#include "typedef.h"
#include "basic_op.h"
#include "ld8a.h"
#include "oper_32b.h"
/*---------------------------------------------------------------*
* Postfilter constant parameters (defined in "ld8a.h") *
*---------------------------------------------------------------*
* L_FRAME : Frame size. *
* L_SUBFR : Sub-frame size. *
* M : LPC order. *
* MP1 : LPC order+1 *
* PIT_MAX : Maximum pitch lag. *
* GAMMA2_PST : Formant postfiltering factor (numerator) *
* GAMMA1_PST : Formant postfiltering factor (denominator) *
* GAMMAP : Harmonic postfiltering factor *
* MU : Factor for tilt compensation filter *
* AGC_FAC : Factor for automatic gain control *
*---------------------------------------------------------------*/
/*------------------------------------------------------------*
* static vectors *
*------------------------------------------------------------*/
/* inverse filtered synthesis (with A(z/GAMMA2_PST)) */
static Word16 res2_buf[PIT_MAX+L_SUBFR];
static Word16 *res2;
static Word16 scal_res2_buf[PIT_MAX+L_SUBFR];
static Word16 *scal_res2;
/* memory of filter 1/A(z/GAMMA1_PST) */
static Word16 mem_syn_pst[M];
/*---------------------------------------------------------------*
* Procedure Init_Post_Filter: *
* ~~~~~~~~~~~~~~~~ *
* Initializes the postfilter parameters: *
*---------------------------------------------------------------*/
void Init_Post_Filter(void)
{
res2 = res2_buf + PIT_MAX;
scal_res2 = scal_res2_buf + PIT_MAX;
Set_zero(mem_syn_pst, M);
Set_zero(res2_buf, PIT_MAX+L_SUBFR);
Set_zero(scal_res2_buf, PIT_MAX+L_SUBFR);
return;
}
/*------------------------------------------------------------------------*
* Procedure Post_Filter: *
* ~~~~~~~~~~~ *
*------------------------------------------------------------------------*
* The postfiltering process is described as follows: *
* *
* - inverse filtering of syn[] through A(z/GAMMA2_PST) to get res2[] *
* - use res2[] to compute pitch parameters *
* - perform pitch postfiltering *
* - tilt compensation filtering; 1 - MU*k*z^-1 *
* - synthesis filtering through 1/A(z/GAMMA1_PST) *
* - adaptive gain control *
*------------------------------------------------------------------------*/
void Post_Filter(
Word16 *syn, /* in/out: synthesis speech (postfiltered is output) */
Word16 *Az_4, /* input : interpolated LPC parameters in all subframes */
Word16 *T /* input : decoded pitch lags in all subframes */
)
{
/*-------------------------------------------------------------------*
* Declaration of parameters *
*-------------------------------------------------------------------*/
Word16 res2_pst[L_SUBFR]; /* res2[] after pitch postfiltering */
Word16 syn_pst[L_FRAME]; /* post filtered synthesis speech */
Word16 Ap3[MP1], Ap4[MP1]; /* bandwidth expanded LP parameters */
Word16 *Az; /* pointer to Az_4: */
/* LPC parameters in each subframe */
Word16 t0_max, t0_min; /* closed-loop pitch search range */
Word16 i_subfr; /* index for beginning of subframe */
Word16 h[L_H];
Word16 i, j;
Word16 temp1, temp2;
Word32 L_tmp;
/*-----------------------------------------------------*
* Post filtering *
*-----------------------------------------------------*/
Az = Az_4;
for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
{
/* Find pitch range t0_min - t0_max */
t0_min = sub(*T++, 3);
t0_max = add(t0_min, 6);
if (sub(t0_max, PIT_MAX) > 0) {
t0_max = PIT_MAX;
t0_min = sub(t0_max, 6);
}
/* Find weighted filter coefficients Ap3[] and ap[4] */
Weight_Az(Az, GAMMA2_PST, M, Ap3);
Weight_Az(Az, GAMMA1_PST, M, Ap4);
/* filtering of synthesis speech by A(z/GAMMA2_PST) to find res2[] */
Residu(Ap3, &syn[i_subfr], res2, L_SUBFR);
/* scaling of "res2[]" to avoid energy overflow */
for (j=0; j (Word32)0)
{
cor_max = corr;
t0 = i;
}
deb_sig--;
}
/* Compute the energy of the signal delayed by t0 */
ener = 1;
p = scal_sig - t0;
for ( i=0; i temp)
{
temp = ener;
}
if (ener0 > temp)
{
temp = ener0;
}
j = norm_l(temp);
cmax = round(L_shl(cor_max, j));
en = round(L_shl(ener, j));
en0 = round(L_shl(ener0, j));
/* prediction gain (dB)= -10 log(1-cor_max*cor_max/(ener*ener0)) */
/* temp = (cor_max * cor_max) - (0.5 * ener * ener0) */
temp = L_mult(cmax, cmax);
temp = L_sub(temp, L_shr(L_mult(en, en0), 1));
if (temp < (Word32)0) /* if prediction gain < 3 dB */
{ /* switch off pitch postfilter */
for (i = 0; i < L_subfr; i++)
signal_pst[i] = signal[i];
return;
}
if (sub(cmax, en) > 0) /* if pitch gain > 1 */
{
g0 = INV_GAMMAP;
gain = GAMMAP_2;
}
else {
cmax = shr(mult(cmax, GAMMAP), 1); /* cmax(Q14) = cmax(Q15) * GAMMAP */
en = shr(en, 1); /* Q14 */
i = add(cmax, en);
if(i > 0)
{
gain = div_s(cmax, i); /* gain(Q15) = cor_max/(cor_max+ener) */
g0 = sub(32767, gain); /* g0(Q15) = 1 - gain */
}
else
{
g0 = 32767;
gain = 0;
}
}
for (i = 0; i < L_subfr; i++)
{
/* signal_pst[i] = g0*signal[i] + gain*signal[i-t0]; */
signal_pst[i] = add(mult(g0, signal[i]), mult(gain, signal[i-t0]));
}
return;
}
/*---------------------------------------------------------------------*
* routine preemphasis() *
* ~~~~~~~~~~~~~~~~~~~~~ *
* Preemphasis: filtering through 1 - g z^-1 *
*---------------------------------------------------------------------*/
void preemphasis(
Word16 *signal, /* (i/o) : input signal overwritten by the output */
Word16 g, /* (i) Q15 : preemphasis coefficient */
Word16 L /* (i) : size of filtering */
)
{
static Word16 mem_pre = 0;
Word16 *p1, *p2, temp, i;
p1 = signal + L - 1;
p2 = p1 - 1;
temp = *p1;
for (i = 0; i <= L-2; i++)
{
*p1-- = sub(*p1, mult(g, *p2--));
}
*p1 = sub(*p1, mult(g, mem_pre));
mem_pre = temp;
return;
}
/*----------------------------------------------------------------------*
* routine agc() *
* ~~~~~~~~~~~~~ *
* Scale the postfilter output on a subframe basis by automatic control *
* of the subframe gain. *
* gain[n] = AGC_FAC * gain[n-1] + (1 - AGC_FAC) g_in/g_out *
*----------------------------------------------------------------------*/
void agc(
Word16 *sig_in, /* (i) : postfilter input signal */
Word16 *sig_out, /* (i/o) : postfilter output signal */
Word16 l_trm /* (i) : subframe size */
)
{
static Word16 past_gain=4096; /* past_gain = 1.0 (Q12) */
Word16 i, exp;
Word16 gain_in, gain_out, g0, gain; /* Q12 */
Word32 s;
Word16 signal[L_SUBFR];
/* calculate gain_out with exponent */
for(i=0; i