POSTFILT.C
资源名称:G711-729.rar [点击查看]
上传用户:meifeng08
上传日期:2013-06-18
资源大小:5304k
文件大小:14k
源码类别:
语音压缩
开发平台:
C/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<L_SUBFR; j++)
- {
- scal_res2[j] = shr(res2[j], 2);
- }
- /* pitch postfiltering */
- pit_pst_filt(res2, scal_res2, t0_min, t0_max, L_SUBFR, res2_pst);
- /* tilt compensation filter */
- /* impulse response of A(z/GAMMA2_PST)/A(z/GAMMA1_PST) */
- Copy(Ap3, h, M+1);
- Set_zero(&h[M+1], L_H-M-1);
- Syn_filt(Ap4, h, h, L_H, &h[M+1], 0);
- /* 1st correlation of h[] */
- L_tmp = L_mult(h[0], h[0]);
- for (i=1; i<L_H; i++) L_tmp = L_mac(L_tmp, h[i], h[i]);
- temp1 = extract_h(L_tmp);
- L_tmp = L_mult(h[0], h[1]);
- for (i=1; i<L_H-1; i++) L_tmp = L_mac(L_tmp, h[i], h[i+1]);
- temp2 = extract_h(L_tmp);
- if(temp2 <= 0) {
- temp2 = 0;
- }
- else {
- temp2 = mult(temp2, MU);
- temp2 = div_s(temp2, temp1);
- }
- preemphasis(res2_pst, temp2, L_SUBFR);
- /* filtering through 1/A(z/GAMMA1_PST) */
- Syn_filt(Ap4, res2_pst, &syn_pst[i_subfr], L_SUBFR, mem_syn_pst, 1);
- /* scale output to input */
- agc(&syn[i_subfr], &syn_pst[i_subfr], L_SUBFR);
- /* update res2[] buffer; shift by L_SUBFR */
- Copy(&res2[L_SUBFR-PIT_MAX], &res2[-PIT_MAX], PIT_MAX);
- Copy(&scal_res2[L_SUBFR-PIT_MAX], &scal_res2[-PIT_MAX], PIT_MAX);
- Az += MP1;
- }
- /* update syn[] buffer */
- Copy(&syn[L_FRAME-M], &syn[-M], M);
- /* overwrite synthesis speech by postfiltered synthesis speech */
- Copy(syn_pst, syn, L_FRAME);
- return;
- }
- /*---------------------------------------------------------------------------*
- * procedure pitch_pst_filt *
- * ~~~~~~~~~~~~~~~~~~~~~~~~ *
- * Find the pitch period around the transmitted pitch and perform *
- * harmonic postfiltering. *
- * Filtering through (1 + g z^-T) / (1+g) ; g = min(pit_gain*gammap, 1) *
- *--------------------------------------------------------------------------*/
- void pit_pst_filt(
- Word16 *signal, /* (i) : input signal */
- Word16 *scal_sig, /* (i) : input signal (scaled, divided by 4) */
- Word16 t0_min, /* (i) : minimum value in the searched range */
- Word16 t0_max, /* (i) : maximum value in the searched range */
- Word16 L_subfr, /* (i) : size of filtering */
- Word16 *signal_pst /* (o) : harmonically postfiltered signal */
- )
- {
- Word16 i, j, t0;
- Word16 g0, gain, cmax, en, en0;
- Word16 *p, *p1, *deb_sig;
- Word32 corr, cor_max, ener, ener0, temp;
- Word32 L_temp;
- /*---------------------------------------------------------------------------*
- * Compute the correlations for all delays *
- * and select the delay which maximizes the correlation *
- *---------------------------------------------------------------------------*/
- deb_sig = &scal_sig[-t0_min];
- cor_max = MIN_32;
- t0 = t0_min; /* Only to remove warning from some compilers */
- for (i=t0_min; i<=t0_max; i++)
- {
- corr = 0;
- p = scal_sig;
- p1 = deb_sig;
- for (j=0; j<L_subfr; j++)
- corr = L_mac(corr, *p++, *p1++);
- L_temp = L_sub(corr, cor_max);
- if (L_temp > (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<L_subfr ;i++, p++)
- ener = L_mac(ener, *p, *p);
- /* Compute the signal energy in the present subframe */
- ener0 = 1;
- p = scal_sig;
- for ( i=0; i<L_subfr; i++, p++)
- ener0 = L_mac(ener0, *p, *p);
- if (cor_max < 0)
- {
- cor_max = 0;
- }
- /* scale "cor_max", "ener" and "ener0" on 16 bits */
- temp = cor_max;
- if (ener > 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<l_trm; i++)
- signal[i] = shr(sig_out[i], 2);
- s = 0;
- for(i=0; i<l_trm; i++)
- s = L_mac(s, signal[i], signal[i]);
- if (s == 0) {
- past_gain = 0;
- return;
- }
- exp = sub(norm_l(s), 1);
- gain_out = round(L_shl(s, exp));
- /* calculate gain_in with exponent */
- for(i=0; i<l_trm; i++)
- signal[i] = shr(sig_in[i], 2);
- s = 0;
- for(i=0; i<l_trm; i++)
- s = L_mac(s, signal[i], signal[i]);
- if (s == 0) {
- g0 = 0;
- }
- else {
- i = norm_l(s);
- gain_in = round(L_shl(s, i));
- exp = sub(exp, i);
- /*---------------------------------------------------*
- * g0(Q12) = (1-AGC_FAC) * sqrt(gain_in/gain_out); *
- *---------------------------------------------------*/
- s = L_deposit_l(div_s(gain_out,gain_in)); /* Q15 */
- s = L_shl(s, 7); /* s(Q22) = gain_out / gain_in */
- s = L_shr(s, exp); /* Q22, add exponent */
- /* i(Q12) = s(Q19) = 1 / sqrt(s(Q22)) */
- s = Inv_sqrt(s); /* Q19 */
- i = round(L_shl(s,9)); /* Q12 */
- /* g0(Q12) = i(Q12) * (1-AGC_FAC)(Q15) */
- g0 = mult(i, AGC_FAC1); /* Q12 */
- }
- /* compute gain(n) = AGC_FAC gain(n-1) + (1-AGC_FAC)gain_in/gain_out */
- /* sig_out(n) = gain(n) sig_out(n) */
- gain = past_gain;
- for(i=0; i<l_trm; i++) {
- gain = mult(gain, AGC_FAC);
- gain = add(gain, g0);
- sig_out[i] = extract_h(L_shl(L_mult(sig_out[i], gain), 3));
- }
- past_gain = gain;
- return;
- }