www.pudn.com > source.rar > POSTFIL.C
/* ITU-T G.729 Software Package Release 2 (November 2006) */
/*
ITU-T G.729 Annex C - Reference C code for floating point
implementation of G.729
Version 1.01 of 15.September.98
*/
/*
----------------------------------------------------------------------
COPYRIGHT NOTICE
----------------------------------------------------------------------
ITU-T G.729 Annex C ANSI C source code
Copyright (C) 1998, AT&T, France Telecom, NTT, University of
Sherbrooke. All rights reserved.
----------------------------------------------------------------------
*/
/*
File : POSTFIL.C
Used for the floating point version of G.729 main body
(not for G.729A)
*/
/************************************************************************/
/* Post - filtering : short term + long term */
/* Floating point computation */
/************************************************************************/
#include
#include "typedef.h"
#include "ld8k.h"
#include "tab_ld8k.h"
/* Prototypes for local functions */
static void pst_ltp(int t0, FLOAT *ptr_sig_in, FLOAT *ptr_sig_pst0, int *vo);
static void search_del(int t0, FLOAT *ptr_sig_in, int *ltpdel, int *phase,
FLOAT *num_gltp, FLOAT *den_gltp, FLOAT *y_up, int *off_yup);
static void filt_plt( FLOAT *s_in, FLOAT *s_ltp, FLOAT *s_out, FLOAT gain_plt);
static void compute_ltp_l(FLOAT *s_in, int ltpdel, int phase, FLOAT *y_up,
FLOAT *num, FLOAT *den);
static int select_ltp( FLOAT num1, FLOAT den1, FLOAT num2, FLOAT den2);
static void calc_st_filt(FLOAT *apond2, FLOAT *apond1, FLOAT *parcor0,
FLOAT *signal_ltp0_ptr);
static void filt_mu(FLOAT *sig_in, FLOAT *sig_out, FLOAT parcor0);
static void calc_rc0_h(FLOAT *h, FLOAT *rc0);
static void scale_st(FLOAT *sig_in, FLOAT *sig_out, FLOAT *gain_prec);
/* Static arrays and variables */
static FLOAT apond2[LONG_H_ST]; /* s.t. numerator coeff. */
static FLOAT mem_stp[M]; /* s.t. postfilter memory */
static FLOAT mem_zero[M]; /* null memory to compute h_st */
static FLOAT res2[SIZ_RES2]; /* A(gamma2) residual */
/* Static pointers */
static FLOAT *res2_ptr;
static FLOAT *ptr_mem_stp;
/* Variables */
static FLOAT gain_prec; /* for gain adjustment */
/**** Short term postfilter : *****/
/* Hst(z) = Hst0(z) Hst1(z) */
/* Hst0(z) = 1/g0 A(gamma2)(z) / A(gamma1)(z) */
/* if {hi} = i.r. filter A(gamma2)/A(gamma1) (truncated) */
/* g0 = SUM(|hi|) if > 1 */
/* g0 = 1. else */
/* Hst1(z) = 1/(1+ |mu|) (1 + mu z-1) */
/* with mu = 1st parcor calculated on {hi} */
/**** Long term postfilter : *****/
/* harmonic postfilter : H0(z) = gl * (1 + b * z-p) */
/* b = gamma_g * gain_ltp */
/* gl = 1 / 1 + b */
/* copmuation of delay on A(gamma2)(z) s(z) */
/* sub optimal research */
/* 1. search best integer delay */
/* 2. search around integer sub multiples (3 val. / sub mult) */
/* 3. search around integer with fractionnal delays (1/8) */
/************************************************************************/
/*----------------------------------------------------------------------------
* init_pst - Initialize postfilter functions
*----------------------------------------------------------------------------
*/
void init_post_filter(
void
)
{
int i;
/* Initialize arrays and pointers */
/* A(gamma2) residual */
for(i=0; iLONG_H_ST-1] with zeroes */
for(i=MP1; i 0 delay */
)
{
FLOAT apond1[MP1]; /* s.t. denominator coeff. */
FLOAT sig_ltp[L_SUBFRP1]; /* H0 output signal */
FLOAT *sig_ltp_ptr;
FLOAT parcor0;
/* Compute weighted LPC coefficients */
weight_az(coeff, GAMMA1_PST, M, apond1);
weight_az(coeff, GAMMA2_PST, M, apond2);
/* Compute A(gamma2) residual */
residu(apond2, signal_ptr, res2_ptr, L_SUBFR);
/* Harmonic filtering */
sig_ltp_ptr = sig_ltp + 1;
pst_ltp(t0, res2_ptr, sig_ltp_ptr, vo);
/* Save last output of 1/A(gamma1) */
/* (from preceding subframe) */
sig_ltp[0] = *ptr_mem_stp;
/* Control short term pst filter gain and compute parcor0 */
calc_st_filt(apond2, apond1, &parcor0, sig_ltp_ptr);
/* 1/A(gamma1) filtering, mem_stp is updated */
syn_filt(apond1, sig_ltp_ptr, sig_ltp_ptr, L_SUBFR, mem_stp, 1);
/* (1 + mu z-1) tilt filtering */
filt_mu(sig_ltp, sig_out, parcor0);
/* gain control */
scale_st(signal_ptr, sig_out, &gain_prec);
/**** Update for next frame */
copy(&res2[L_SUBFR], &res2[0], MEM_RES2);
return;
}
/*----------------------------------------------------------------------------
* pst_ltp - harmonic postfilter
*----------------------------------------------------------------------------
*/
static void pst_ltp(
int t0, /* input : pitch delay given by coder */
FLOAT *ptr_sig_in, /* input : postfilter input filter (residu2) */
FLOAT *ptr_sig_pst0, /* output: harmonic postfilter output */
int *vo /* output: voicing decision 0 = uv, > 0 delay */
)
{
/**** Declare variables */
int ltpdel, phase;
FLOAT num_gltp, den_gltp;
FLOAT num2_gltp, den2_gltp;
FLOAT gain_plt;
FLOAT y_up[SIZ_Y_UP];
FLOAT *ptr_y_up;
int off_yup;
/* Sub optimal delay search */
search_del(t0, ptr_sig_in, <pdel, &phase, &num_gltp, &den_gltp,
y_up, &off_yup);
*vo = ltpdel;
if(num_gltp == (F)0.) {
copy(ptr_sig_in, ptr_sig_pst0, L_SUBFR);
}
else {
if(phase == 0) {
ptr_y_up = ptr_sig_in - ltpdel;
}
else {
/* Filtering with long filter */
compute_ltp_l(ptr_sig_in, ltpdel, phase, ptr_sig_pst0,
&num2_gltp, &den2_gltp);
if(select_ltp(num_gltp, den_gltp, num2_gltp, den2_gltp) == 1) {
/* select short filter */
ptr_y_up = y_up + ((phase-1) * L_SUBFRP1 + off_yup);
}
else {
/* select long filter */
num_gltp = num2_gltp;
den_gltp = den2_gltp;
ptr_y_up = ptr_sig_pst0;
}
}
if(num_gltp > den_gltp) {
/* beta bounded to 1 */
gain_plt = MIN_GPLT;
}
else {
gain_plt = den_gltp / (den_gltp + GAMMA_G * num_gltp);
}
/** filtering by H0(z) (harmonic filter) **/
filt_plt(ptr_sig_in, ptr_y_up, ptr_sig_pst0, gain_plt);
}
return;
}
/*----------------------------------------------------------------------------
* search_del: computes best (shortest) integer LTP delay + fine search
*----------------------------------------------------------------------------
*/
static void search_del(
int t0, /* input : pitch delay given by coder */
FLOAT *ptr_sig_in, /* input : input signal (with delay line) */
int *ltpdel, /* output: delay = *ltpdel - *phase / f_up */
int *phase, /* output: phase */
FLOAT *num_gltp, /* output: numerator of LTP gain */
FLOAT *den_gltp, /* output: denominator of LTP gain */
FLOAT *y_up, /* : */
int *off_yup /* : */
)
{
/* pointers on tables of constants */
FLOAT *ptr_h;
/* Variables and local arrays */
FLOAT tab_den0[F_UP_PST-1], tab_den1[F_UP_PST-1];
FLOAT *ptr_den0, *ptr_den1;
FLOAT *ptr_sig_past, *ptr_sig_past0;
FLOAT *ptr1;
int i, n, ioff, i_max;
FLOAT ener, num, numsq, den0, den1;
FLOAT den_int, num_int;
FLOAT den_max, num_max, numsq_max;
int phi_max;
int lambda, phi;
FLOAT temp0, temp1;
FLOAT *ptr_y_up;
/*****************************************/
/* Compute current signal energy */
/*****************************************/
ener = (F)0.;
for(i=0; i num_int) {
i_max = i;
num_int = num;
}
ptr_sig_past--;
}
if(num_int <= (F)0.) {
*num_gltp = (F)0.;
*den_gltp = (F)1.;
*ltpdel = 0;
*phase = 0;
return;
}
/* Calculates denominator for lambda_max */
lambda += i_max;
ptr_sig_past = ptr_sig_in - lambda;
den_int=(F)0.;
for(n=0; nfabs(ptr_y_up[L_SUBFR])) {
if(den0 > den_max) {
den_max = den0;
}
}
else {
if(den1 > den_max) {
den_max = den1;
}
}
ptr_y_up += L_SUBFRP1;
ptr_h += LH2_S;
}
if(den_max < (F)0.1 ) {
*num_gltp = (F)0.;
*den_gltp = (F)1.;
*ltpdel = 0;
*phase = 0;
return;
}
/* Computation of the numerators */
/* and selection of best num*num/den */
/* for non null phases */
/* Initialize with null phase */
num_max = num_int;
den_max = den_int;
numsq_max = num_max * num_max;
phi_max = 0;
ioff = 1;
ptr_den0 = tab_den0;
ptr_den1 = tab_den1;
ptr_y_up = y_up;
/* if den_max = 0 : will be selected and declared unvoiced */
/* if num!=0 & den=0 : will be selected and declared unvoiced */
/* degenerated seldom cases, switch off LT is OK */
/* Loop on phase */
for(phi=1; phi temp1) {
num_max = num;
numsq_max = numsq;
den_max = den0;
ioff = 0;
phi_max = phi;
}
/* computes num for lambda_max - phi/F_UP_PST */
ptr_y_up++;
num = (F)0.;
for(n = 0; n temp1) {
num_max = num;
numsq_max = numsq;
den_max = den1;
ioff = 1;
phi_max = phi;
}
ptr_y_up += L_SUBFR;
}
/***************************************************/
/*** test if normalised crit0[iopt] > THRESCRIT ***/
/***************************************************/
if((num_max == (F)0.) || (den_max <= (F)0.1)) {
*num_gltp = (F)0.;
*den_gltp = (F)1.;
*ltpdel = 0;
*phase = 0;
return;
}
/* comparison num * num */
/* with ener * den x THRESCRIT */
temp1 = den_max * ener * THRESCRIT;
if(numsq_max >= temp1) {
*ltpdel = lambda + 1 - ioff;
*off_yup = ioff;
*phase = phi_max;
*num_gltp = num_max;
*den_gltp = den_max;
}
else {
*num_gltp = (F)0.;
*den_gltp = (F)1.;
*ltpdel = 0;
*phase = 0;
}
return;
}
/*----------------------------------------------------------------------------
* filt_plt - ltp postfilter
*----------------------------------------------------------------------------
*/
void filt_plt(
FLOAT *s_in, /* input : input signal with past*/
FLOAT *s_ltp, /* input : filtered signal with gain 1 */
FLOAT *s_out, /* output: output signal */
FLOAT gain_plt /* input : filter gain */
)
{
/* Local variables */
int n;
FLOAT temp;
FLOAT gain_plt_1;
gain_plt_1 = (F)1. - gain_plt;
for(n=0; n num1 * num1 * den2) {
return(2);
}
else {
return(1);
}
}
/*----------------------------------------------------------------------------
* calc_st_filt - computes impulse response of A(gamma2) / A(gamma1)
* controls gain : computation of energy impulse response as
* SUMn (abs (h[n])) and computes parcor0
*----------------------------------------------------------------------------
*/
static void calc_st_filt(
FLOAT *apond2, /* input : coefficients of numerator */
FLOAT *apond1, /* input : coefficients of denominator */
FLOAT *parcor0, /* output: 1st parcor calcul. on composed filter */
FLOAT *sig_ltp_ptr /* in/out: input of 1/A(gamma1) : scaled by 1/g0 */
)
{
FLOAT h[LONG_H_ST];
FLOAT g0, temp;
int i;
/* computes impulse response of apond1 / apond2 */
syn_filt(apond1, apond2, h, LONG_H_ST, mem_zero, 0);
/* computes 1st parcor */
calc_rc0_h(h, parcor0);
/* computes gain g0 */
g0 = (F)0.;
for(i=0; i (F)1.) {
temp = (F)1./g0;
for(i=0; i (F)0.) {
mu = parcor0 * GAMMA3_PLUS;
}
else {
mu = parcor0 * GAMMA3_MINUS;
}
ga = (F)1. / ((F)1. - (FLOAT)fabs(mu));
ptrs = sig_in; /* points on sig_in(-1) */
for(n=0; n