📄 pstcp.c
字号:
/* ITU-T G.729 Annex C+ - Reference C code for floating point implementation of G.729 Annex C+ (integration of Annexes B, D and E) Version 2.1 of October 1999*//* File : PSTCP.C*//************************************************************************//* Post - filtering : short term + long term *//************************************************************************/#include <stdio.h>#include <stdlib.h>#include <math.h>/**** Prototypes */#include "typedef.h"#include "ld8k.h"#include "ld8cp.h"#include "tab_ld8k.h"/* Prototypes for local functions *//**********************************/static void pst_ltpe(int t0, FLOAT *ptr_sig_in, FLOAT *ptr_sig_pst0, int *vo, FLOAT gamma_harm);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_filte(struct postfilt_state_t *state, FLOAT *apond2, FLOAT *apond1, FLOAT *parcor0, FLOAT *signal_ltp0_ptr, int long_h_st, int m_pst);static void filt_mu(FLOAT *sig_in, FLOAT *sig_out, FLOAT parcor0);static void calc_rc0_he(FLOAT *h, FLOAT *rc0, int long_h_st);static void scale_st(FLOAT *sig_in, FLOAT *sig_out, FLOAT *gain_prec);/************************************************************************//**** 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 = k1 * gamma3 *//* k1 = 1st parcor calculated on {hi} *//* gamma3 = gamma3_minus if k1<0, gamma3_plus if k1>0 *//**** Long term postfilter : *****//* harmonic postfilter : H0(z) = gl * (1 + b * z-p) *//* b = gamma_g * gain_ltp *//* gl = 1 / 1 + b *//* computation of delay p on A(gamma2)(z) s(z) *//* sub optimal search *//* 1. search around 1st subframe delay (3 integer values) *//* 2. search around best integer with fract. delays (1/8) *//************************************************************************//*---------------------------------------------------------------------------- * Init_Post_Filter - Initialize postfilter functions *---------------------------------------------------------------------------- */void init_post_filter(struct postfilt_state_t *state){ /* Initialize arrays and pointers */ /* res2 = A(gamma2) residual */ /*for(i=0; i<MEM_RES2; i++) state->res2[i] = (F)0.;*/ set_zero(state->res2, MEM_RES2); state->res2_ptr = state->res2 + MEM_RES2; /* 1/A(gamma1) memory */ /*for(i=0; i<M_BWD; i++) state->mem_stp[i] = (F)0.;*/ set_zero(state->mem_stp, M_BWD); state->ptr_mem_stp = state->mem_stp + M_BWD - 1; /* fill apond2[M+1->long_h_st-1] with zeroes */ /*for(i=MP1; i<LONG_H_ST; i++) state->apond2[i] = (F)0.;*/ set_zero(state->apond2 + MP1, LONG_H_ST - MP1); /* null memory to compute i.r. of A(gamma2)/A(gamma1) */ /*for(i=0; i<M; i++) state->mem_zero[i] = (F)0.;*/ set_zero(state->mem_zero, M); /* for gain adjustment */ state->gain_prec = (F)1.;}/*---------------------------------------------------------------------------- * Post - adaptive postfilter main function *---------------------------------------------------------------------------- */void poste(struct postfilt_state_t *state, int t0, /* input : pitch delay given by coder */ FLOAT *signal_ptr, /* input : input signal (pointer to current subframe */ FLOAT *coeff, /* input : LPC coefficients for current subframe */ FLOAT *sig_out, /* output: postfiltered output */ int *vo, /* output: voicing decision 0 = uv, > 0 delay */ FLOAT gamma1, /* input: short term postfilt. den. weighting factor*/ FLOAT gamma2, /* input: short term postfilt. num. weighting factor*/ FLOAT gamma_harm, /* input: long term postfilter weighting factor*/ int long_h_st, /* input: impulse response length*/ int m_pst, /* input: LPC order */ int Vad /* input : VAD information (frame type) */){ /* Local variables and arrays */ FLOAT apond1[M_BWDP1]; /* 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, m_pst, apond1); weight_az(coeff, gamma2, m_pst, state->apond2); set_zero(&state->apond2[m_pst+1], (M_BWD-m_pst)); /* Compute A(gamma2) residual */ residue(m_pst, state->apond2, signal_ptr, state->res2_ptr, L_SUBFR); /* Harmonic filtering */ sig_ltp_ptr = sig_ltp + 1; if (Vad > 1) pst_ltpe(t0, state->res2_ptr, sig_ltp_ptr, vo, gamma_harm); else { *vo = 0; copy(state->res2_ptr, sig_ltp_ptr, L_SUBFR); } /* Save last output of 1/A(gamma1) */ /* (from preceding subframe) */ sig_ltp[0] = *state->ptr_mem_stp; /* Controls short term pst filter gain and compute parcor0 */ calc_st_filte(state, state->apond2, apond1, &parcor0, sig_ltp_ptr, long_h_st, m_pst); /* 1/A(gamma1) filtering, mem_stp is updated */ syn_filte(m_pst, apond1, sig_ltp_ptr, sig_ltp_ptr, L_SUBFR, &state->mem_stp[M_BWD-m_pst], 0); copy(&sig_ltp_ptr[L_SUBFR-M_BWD], state->mem_stp, M_BWD); /* Tilt filtering */ filt_mu(sig_ltp, sig_out, parcor0); /* Gain control */ scale_st(signal_ptr, sig_out, &state->gain_prec); /**** Update for next subframe */ copy(&state->res2[L_SUBFR], &state->res2[0], MEM_RES2);}/*---------------------------------------------------------------------------- * pst_ltp - harmonic postfilter *---------------------------------------------------------------------------- */static void pst_ltpe( 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 */ FLOAT gamma_harm /* input: harmonic postfilter coefficient */){/**** 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 */ if (gamma_harm == GAMMA_HARM) gain_plt = MIN_GPLT; else gain_plt = (F)1./((F)1.+ gamma_harm); } else { gain_plt = den_gltp / (den_gltp + gamma_harm * num_gltp); } /** filtering by H0(z) = harmonic filter **/ filt_plt(ptr_sig_in, ptr_y_up, ptr_sig_pst0, gain_plt); }}/*---------------------------------------------------------------------------- * 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 */ const 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<L_SUBFR; i++) { ener += ptr_sig_in[i] * ptr_sig_in[i]; } if(ener < (F)0.1) { *num_gltp = (F)0.; *den_gltp = (F)1.; *ltpdel = 0; *phase = 0; return; } /*************************************/ /* Selects best of 3 integer delays */ /* Maximum of 3 numerators around t0 */ /* coder LTP delay */ /*************************************/ lambda = t0 - 1; ptr_sig_past = ptr_sig_in - lambda; num_int = (F)-1.0e30; /* initialization used only to suppress Microsoft Visual C++ warnings */ i_max = 0; for(i=0; i<3; i++) { num=(F)0.; for(n=0; n<L_SUBFR; n++) { num += ptr_sig_in[n]* ptr_sig_past[n]; } if(num > 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; n<L_SUBFR; n++) { den_int += ptr_sig_past[n]* ptr_sig_past[n]; } if(den_int < (F)0.1) { *num_gltp = (F)0.; *den_gltp = (F)1.; *ltpdel = 0; *phase = 0; return; } /***********************************/ /* Select best phase around lambda */ /***********************************/ /* Compute y_up & denominators */ /*******************************/ ptr_y_up = y_up; den_max = den_int; ptr_den0 = tab_den0; ptr_den1 = tab_den1; ptr_h = tab_hup_s; ptr_sig_past0 = ptr_sig_in + LH_UP_S - 1 - lambda; /* points on lambda_max+1 */ /* loop on phase */ for(phi=1; phi<F_UP_PST; phi++) { /* Computes criterion for (lambda_max+1) - phi/F_UP_PST */ /* and lambda_max - phi/F_UP_PST */ ptr_sig_past = ptr_sig_past0; /* computes y_up[n] */ for(n = 0; n<=L_SUBFR; n++) { ptr1 = ptr_sig_past++; temp0 = (F)0.; for(i=0; i<LH2_S; i++) { temp0 += ptr_h[i] * ptr1[-i]; } ptr_y_up[n] = temp0; } /* recursive computation of den0 (lambda_max+1) and den1 (lambda_max) */ /* common part to den0 and den1 */ temp0 = (F)0.; for(n=1; n<L_SUBFR; n++) { temp0 += ptr_y_up[n] * ptr_y_up[n]; } /* den0 */ den0 = temp0 + ptr_y_up[0] * ptr_y_up[0]; *ptr_den0++ = den0; /* den1 */ den1 = temp0 + ptr_y_up[L_SUBFR] * ptr_y_up[L_SUBFR]; *ptr_den1++ = den1; if(fabs(ptr_y_up[0])>fabs(ptr_y_up[L_SUBFR])) { if(den0 > den_max) { den_max = den0; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -