📄 g729ev_fec_decbfi.c
字号:
/* ITU-T G.729EV Optimization/Characterization Candidate *//* Version: 1.0.a *//* Revision Date: June 28, 2006 *//* ITU-T G.729EV Optimization/Characterization Candidate ANSI-C Source Code Copyright (c) 2006 France Telecom, Matsushita Electric, Mindspeed, Siemens AG, ETRI, VoiceAge Corp. All rights reserved*/#include <stdlib.h>#include <stdio.h>#include "G729EV_MAIN_defines.h"#include "G729EV_G729_defines.h"#include "G729EV_FEC_fer.h"#include "G729EV_FEC_tools.h"#include "G729EV_G729_ld8k.h"#include "stl.h"#include "G729EV_MAIN_OPER_32B.h"#include "G729EV_MAIN_DSPFUNC.h"static void G729EV_FEC_synchro_exc(Word16 * exc, Word16 true_puls_pos, Word16 desire_puls_pos, Word16 Old_pitch);static Word16 G729EV_FEC_enr_1_Az( /* o: impulse response energy */ Word16 Aq[], /* i: LP filter coefs */ Word16 len /* i: impulse response length */ );static void G729EV_FEC_syn_bfi(Word16 last_good, Word16 bfi_cnt, const Word16 stab_fac, Word16 * lp_gainp, Word16 * lp_gainc, Word16 * exc_mem, Word16 * exc2, const Word16 T3, const Word16 tilt_code, const Word16 Ts, Word16 * pitch_buf, const Word16 Tcnt, Word16 * Aq, Word16 * synth, Word16 * mem_syn2, Word32 * Lenr_old, Word16 * seed, Word16 * exc, Word16 puls_pos, Word16 new_pit);/******************************************************************************//* G729EV_FEC_dec_bf : Frame erasure concealment *//* Find LPC coefficient, pitch and reconstruct lost synthesis *//******************************************************************************/void G729EV_FEC_dec_bf(Word16 parm[], /* (i) : vector of synthesis parameters */ Word16 synth[], /* (i/o) : synthesis speech */ Word16 Az_dec[], /* (o) : decoded LP filter in 2 subframes */ Word16 bfi, /* (i) : Bad Frame Indicator */ Word16 * last_good, /* (i) : last good frame classification */ Word16 * pitch_buf, /* (i/o) : Pitch memory */ Word16 old_enr, /* (i) : Energy at the end of the last frame */ Word16 * old_exc, /* (i/o) : excitiation memory */ G729EV_G729_DECSTAT * st, /* (i) : Decoder structure */ Word16 new_clas, /* (i) : present frame classification */ Word16 puls_pos /* (i) : Position of the last pulse */ ){ Word16 A[G729EV_MAIN_NB_SUBFR * G729EV_G729_MP1]; Word16 lsp_new[G729EV_G729_M]; Word16 *exc, T3; Word16 exc2[G729EV_MAIN_L_FRAME2 + G729EV_FEC_L_FIR_FER - 1]; Word16 exc_buf[G729EV_MAIN_L_FRAME2 + G729EV_G729_PIT_MAX + G729EV_G729_L_INTERPOL + G729EV_G729_L_SUBFR]; Word16 T0, T0_frac; Word16 t0, t0_frac; Word16 index; T0 = (Word16) 0; T0_frac = (Word16) 0;#if(WMOPS) move16(); move16();#endif exc = exc_buf + G729EV_G729_PIT_MAX + G729EV_G729_L_INTERPOL; G729EV_G729_Copy(old_exc, exc_buf, G729EV_G729_PIT_MAX + G729EV_G729_L_INTERPOL); /* Decode the LSPs */ G729EV_G729_D_lsp(st->freq_prev, st->prev_lsp, &(st->prev_ma), parm, lsp_new, bfi); parm += 2; IF(sub(bfi, G729EV_FEC_SINGLE_FRAME) == 0) { index = *parm++; /* pitch index */#if(WMOPS) move16(); move16();#endif /* decode future pitch */ G729EV_G729_Dec_lag3(index, G729EV_G729_PIT_MIN, G729EV_G729_PIT_MAX, 0, &t0, &t0_frac); G729EV_G729_Int_qlpc_bfi(st->lsp_old, lsp_new, A, interpol_frac2); G729EV_G729_Copy(A, Az_dec, G729EV_MAIN_NB_SUBFR * G729EV_G729_MP1); /* update the LSFs for the next frame */ G729EV_G729_Copy(lsp_new, st->lsp_old, G729EV_G729_M); G729EV_FEC_pitch_pred(1, &T0, &T0_frac, st->pit_mem, &(st->bfi_mem)); T3 = st->pit_mem[3]; /*t0 = true future pitch */ } ELSE { /* Interpolation of LPC for the 4 subframes */ G729EV_G729_Int_qlpc_bfi(st->lsp_old, lsp_new, A, interpol_frac2); G729EV_G729_Copy(A, Az_dec, G729EV_MAIN_NB_SUBFR * G729EV_G729_MP1); /* update the LSFs for the next frame */ G729EV_G729_Copy(lsp_new, st->lsp_old, G729EV_G729_M); G729EV_FEC_pitch_pred(1, &T0, &T0_frac, st->pit_mem, &(st->bfi_mem)); T3 = st->pit_mem[3]; t0 = T0; /* t0 = predicted pitch */#if(WMOPS) move16(); move16();#endif } /*-------------------------------------------------* * Find the excitation and synthesize speech *-------------------------------------------------*/ G729EV_FEC_syn_bfi(*last_good, st->bfi_cnt, st->stab_fac, &st->lp_gainp, &st->lp_gainc, st->old_exc, exc2, T3, st->tilt_code, st->old_fpitch, pitch_buf, st->upd_cnt, A, synth, st->mem_syn, &(st->Lenr_old), &(st->seed_fer), exc, puls_pos, t0); /*------------------------------------------------* Others updates --------------------------------------------------*/ G729EV_G729_Copy(&exc[G729EV_MAIN_L_FRAME2 - G729EV_G729_PIT_MAX - G729EV_G729_L_INTERPOL], st->old_exc, G729EV_G729_PIT_MAX + G729EV_G729_L_INTERPOL); st->upd_cnt = add(st->upd_cnt, 1); /* counter of the age of the last update */ if (sub(st->upd_cnt, G729EV_FEC_MAX_UPD_CNT) > 0) { st->upd_cnt = G729EV_FEC_MAX_UPD_CNT;#if(WMOPS) move16();#endif } /*----------------------------------------------------------------------* * Update for next frame. *----------------------------------------------------------------------*/}/******************************************************************************//* G729EV_FEC_syn_bfi : Reconstruction of erased frame *//* - Find pitch *//* - Estimate damping factor *//* - Construct and synchronize periodic part of excitation *//* - Construct random part of excitation *//* - Apply gain to excitation *//* - Do synthesis filtering to recover lost synthesis *//******************************************************************************/static void G729EV_FEC_syn_bfi(Word16 last_good, /* i: last good frame clas */ Word16 bfi_cnt, /* i: counter of consecutive bfi frames */ const Word16 stab_fac, /* i: ISF stability measure */ Word16 * lp_gainp, /* i/o: damped pitch gain */ Word16 * lp_gainc, /* i/o: damped code gain */ Word16 * exc_mem, /* o: excitation memory (st->old_exc) */ Word16 * exc2, /* o: excitation buffer (for synthesis) */ const Word16 T3, /* i: floating pitch */ const Word16 tilt_code, /* i: spectral tilt */ const Word16 Ts, /* i: previous pitch for hr G729EV_FEC_VOICED */ Word16 * pitch_buf, /* o: floating pitch for every subfr */ const Word16 Tcnt, /* i: counter of the last bfi pitch updt. */ Word16 * Aq, /* i LP filter coefs */ Word16 * synth, /* o synthesized speech at Fs = 16kHz */ Word16 * mem_syn2, /* i/o initial synthesis filter states */ Word32 * Lenr_old, /* o energy update at the end for next frame */ Word16 * seed, /* i/o: random generator seed */ Word16 * exc, /* i/o: pointer to present exc */ Word16 puls_pos, /* i : Pulse position */ Word16 new_pit /* i : Pitch of the first future frame */ ){ Word16 i, i_subfr; Word16 pit_subfr; Word16 nb_pusles, pulse_chosen, Terr; Word16 P0 = 0, pit_search, diff_pit, sign; Word32 L_tmp, L_tmp2, L_step; Word16 hp_filt[5], tmp2, *p_Az, exp_alpha, exp_gain, j; Word16 delta, fT0, pos, total_pit_lag = 0; Word16 *pt_exc, *pt1_exc, alpha, step, gain_inov, gain, tmp16, tmp_Tc, Tc; Word16 dist_Plast, Plast, Tlist[10]; /*------------------------------------------------------------------------------------------* * Find secure pitch estimation for FERs * The new_pit is always known * in single FER, new_pit is the futur pitch else new_pit is predict from past pitch *------------------------------------------------------------------------------------------*/ sign = 0;#if(WMOPS) move16(); move16(); test(); test();#endif IF(((sub(Ts, shl(mult(29491, T3), 1)) < 0) && (sub(Ts, mult(19661, T3)) > 0)) || /* last pitch coherent with the past */ (sub(Tcnt, G729EV_FEC_MAX_UPD_CNT) >= 0)) /* or last update too far in the past */ { tmp_Tc = T3; /*pitch period of the 4th subframe of the last good frame */ } ELSE { tmp_Tc = Ts; /* pitch period of the 4th subframe of the last good STABLE VOICED */ } IF(new_pit > 0) {#if(WMOPS) move16();#endif fT0 = tmp_Tc; delta = shr(sub(shl(new_pit, G729EV_FEC_SQPIT), fT0), 2); /* 4 sub-frames */ FOR(i = 0; i < 4; i++) /* subframe pitch values */ { fT0 = add(fT0, delta); pitch_buf[i] = shl(shr(add(fT0, G729EV_FEC_QPIT2), G729EV_FEC_SQPIT), G729EV_FEC_SQPIT);#if(WMOPS) move16();#endif } } ELSE /* Should never happen in normal processing condition */ { FOR(i = 0; i < 4; i++) { pitch_buf[i] = tmp_Tc;#if(WMOPS) move16();#endif } } /*-------------------------------------------------* * hp filter random part and add to excitation *-------------------------------------------------*/ tmp2 = sub(32767, tilt_code); FOR(i = 0; i < G729EV_FEC_L_FIR_FER; i++) { /*hp_filt[i] = (1.0f - tilt_code) * G729EV_FEC_h_high[i]; */ hp_filt[i] = mult_r(tmp2, G729EV_FEC_h_high[i]);#if(WMOPS) move16();#endif } /*-------------------------------------------------* * Estimate damping factor * *-------------------------------------------------*/#if(WMOPS) move16();#endif IF(sub(last_good, G729EV_FEC_UNVOICED) == 0) { IF(sub(bfi_cnt, 3) > 0) { /* If stable, do not decrease the energy */ /*alpha = (stab_fac * (0.9f - G729EV_FEC_ALPHA_U) + G729EV_FEC_ALPHA_U); */ alpha = G729EV_FEC_ALPHA_VT; } ELSE IF(sub(bfi_cnt, 1) > 0) { /* If stable, do not decrease the energy */ /*alpha = (stab_fac * (0.9f - G729EV_FEC_ALPHA_U) + G729EV_FEC_ALPHA_U); */ alpha = add(mult_r(stab_fac, (32767 - G729EV_FEC_ALPHA_U)), G729EV_FEC_ALPHA_U); } ELSE { alpha = G729EV_FEC_ALPHA_U2; } } ELSE if (sub(last_good, G729EV_FEC_UV_TRANSITION) == 0) { alpha = G729EV_FEC_ALPHA_UT; } ELSE if ((sub(last_good, G729EV_FEC_ONSET) == 0)) { alpha = 26214; /* mild convergence to 0 for the first 3 erased frames */ } ELSE if (((sub(last_good, G729EV_FEC_VOICED) == 0) || (sub(last_good, G729EV_FEC_ONSET) == 0))) { alpha = G729EV_FEC_ALPHA_V; /* constant for the first 3 erased frames */ } ELSE if (sub(last_good, G729EV_FEC_SIN_ONSET) == 0) { alpha = G729EV_FEC_ALPHA_S; } ELSE /* G729EV_FEC_V_TRANSITION */ { IF((sub(bfi_cnt, 2) <= 0)) { alpha = 2 * G729EV_FEC_ALPHA_VT; /* medium convergence to 0 */ } ELSE { alpha = (Word16) 6654; /* very fast convergence to 0 */ } } IF(sub(last_good, G729EV_FEC_VOICED) >= 0) { IF(sub(bfi_cnt, 1) == 0) /* if first erased frame in a block, reset harmonic gain */ { /*gain = (float)sqrt( *lp_gainp ); *//* move pitch gain towards 1 for G729EV_FEC_VOICED to remove energy fluctuations */ if(*lp_gainp == 0) { *lp_gainp = 1; } exp_alpha = norm_s(*lp_gainp); tmp2 = shl(*lp_gainp, exp_alpha); tmp2 = div_s(16384, tmp2); L_tmp = L_deposit_h(tmp2); Isqrt_n(&L_tmp, &exp_alpha); gain = extract_h(L_shl(L_tmp, exp_alpha));#if(WMOPS) move16(); move32();#endif IF(sub(gain, 32113) > 0) /*.98 */ { gain = (Word16) 32113;#if(WMOPS) move16();#endif } ELSE if (sub(gain, 27853) < 0) /*0.85 */ { gain = (Word16) 27853;#if(WMOPS) move16();#endif } alpha = mult_r(alpha, gain); } ELSE IF(bfi_cnt <= 3) { /* in Q15 */ alpha = shl(*lp_gainp, 1); } ELSE { alpha = G729EV_FEC_ALPHA_VT; } } IF(sub(last_good, G729EV_FEC_UV_TRANSITION) >= 0) { /* Tc = (short)(bfi_pitch + 0.5f); */ Tc = shr(add(tmp_Tc, G729EV_FEC_QPIT2), G729EV_FEC_SQPIT);#if(WMOPS) move16();#endif /*-------------------------------------------------* * Construct the periodic part of excitation * *-------------------------------------------------*/ pt_exc = exc; pt1_exc = exc - Tc; pos = (Word16) 0; IF(sub(bfi_cnt, 1) == 0) /* if 1st erased frame after a good frame */ { FOR(i = 0; i < Tc; i++) /* pitch cycle is first low-pass filtered */ { /* *pt_exc++ = ( 0.18f * pt1_exc[-1] + 0.64f * pt1_exc[0] + 0.18f * pt1_exc[1] ); */ L_tmp = L_mult(5898, pt1_exc[-1]); L_tmp = L_mac(L_tmp, 20972, pt1_exc[0]); L_tmp = L_mac(L_tmp, 5898, pt1_exc[1]); *pt_exc = round(L_tmp); pt_exc++; pt1_exc++;#if(WMOPS)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -