📄 g729ev_fec_ferutil.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"/*----------------------------------------------------------------------------------* * G729EV_FEC_energy() * * ~~~~~~~~~~~ * * Estimation of pitch-synchronous (VOICED sounds) or half-frame energy * *----------------------------------------------------------------------------------*/Word16 G729EV_FEC_energy(const Word16 clas, /* i: frame classification */ const Word16 * synth, /* i: synthesized speech */ const Word16 pitch, /* i: pitch period Q0 */ Word32 * enr_q, /* o: pitch-synchronous or half_frame energy Q0 */ const Word16 offset /* i: speech pointer offset (0 or L_FRAME) */ ){ Word16 len, tmpS, exp_enrq, pos; Word16 speech_temp[G729EV_FEC_L_FRAME2_FER]; const Word16 *pt_synth;#if(WMOPS) move16();#endif exp_enrq = (Word16) 0; IF(sub(clas, G729EV_FEC_VOICED) >= 0) /* Voiced current frame */ { len = pitch; /* pitch value at the end of frame */#if(WMOPS) move16();#endif if (sub(len, G729EV_G729_L_SUBFR) < 0) { len = shl(len, 1); /* Take 2 pitch periods if pitch is too short */ }#if(WMOPS) move16();#endif IF(offset == 0) { pt_synth = synth; } ELSE { pt_synth = synth + sub(G729EV_FEC_L_FRAME_FER, len); } tmpS = G729EV_Emaximum2(-1, pt_synth, len, enr_q); /* pitch synchronous E */ exp_enrq = (Word16) 0; } ELSE {#if(WMOPS) move16(); move16(); move16();#endif pos = (Word16) 0; if (offset) { pos = G729EV_FEC_L_FRAME2_FER;#if(WMOPS) move16();#endif } G729EV_G729_Copy((Word16 *) synth + pos, speech_temp, G729EV_FEC_L_FRAME2_FER); /* scale down to be sure there is no overflow */ G729EV_Scale_sig(speech_temp, G729EV_FEC_L_FRAME2_FER, -2); /* enr2 = 1.0f/L_FRAME2 * dot_product( synth, synth, L_FRAME2 ); */ *enr_q = G729EV_Dot_product(speech_temp, speech_temp, G729EV_FEC_L_FRAME2_FER); exp_enrq = -6; /*(-1<<1) + (-2<<1) */ } return exp_enrq;}Word16 G729EV_FEC_Lsf_stab( /* o: LP filter stability */ const Word16 * Lsf, /* i: LSF vector */ const Word16 * Lsfold /* i: old LSF vector */ ){ Word16 i; Word16 tmp; Word32 L_tmp;#if(WMOPS) move32();#endif L_tmp = (Word32) 0; FOR(i = 0; i < G729EV_G729_M; i++) { tmp = sub(Lsf[i], Lsfold[i]); L_tmp = L_mac(L_tmp, tmp, tmp); } /*stab_fac = (float)(1.25f - (tmp/0.14f)); */ tmp = extract_h(L_shl(L_tmp, 2)); /*Q13 */ tmp = mult(tmp, 29257); /* Q10 */ tmp = sub(1250, tmp); /* 1.25 - tmp in Q10 */ tmp = shl(tmp, 5); /* Q10 -> Q15 with saturation */ if (tmp < 0) { tmp = (Word16) 0;#if(WMOPS) move16();#endif } return tmp;}/*----------------------------------------------------------------------------------* * procedure G729EV_FEC_findpulse: * ~~~~~~~~~~ * Find last glottat pulse in the last pitch lag *-----------------------------------------------------------------------------------*/Word16 G729EV_FEC_findpulse( /* o: pulse position */ const Word16 res[], /* i: residual signal */ Word16 T0, /* i: integer pitch */ const Word16 enc /* i: enc = 1 -> encoder side; enc = 0 -> decoder side */ ){ const Word16 *ptr; Word16 val, maxval; Word16 i, maxi, tmp16; Word32 Ltmp; Word16 resf[G729EV_FEC_L_FRAME_FER]; /* Low pass filtered residual */ Word16 sign, sign_in; sign = (Word16) 0; sign_in = (Word16) 0;#if(WMOPS) move16(); move16();#endif /*-----------------------------------------------------------------* * 1. Very simple LP filter *-----------------------------------------------------------------*/ IF(sub(enc, 1) == 0) { /*resf[0] = 0.50f * res[0] + 0.25f * res[1]; */ Ltmp = L_mult(res[0], 16384); resf[0] = mac_r(Ltmp, res[1], 8192); move16(); FOR(i = 1; i < G729EV_FEC_L_FRAME_FER - 1; i++) { /*resf[i] = 0.25f * res[i-1] + 0.5f * res[i] + 0.25f * res[i+1]; */ Ltmp = L_mult(8192, res[i - 1]); Ltmp = L_mac(Ltmp, 16384, res[i]); resf[i] = mac_r(Ltmp, 8192, res[i + 1]); move16(); } /*resf[L_FRAME-1] = 0.25f * res[L_FRAME-2] + 0.50f * res[L_FRAME-1]; */ Ltmp = L_mult(res[G729EV_FEC_L_FRAME_FER - 2], 8192); resf[G729EV_FEC_L_FRAME_FER - 1] = mac_r(Ltmp, 16384, res[G729EV_FEC_L_FRAME_FER - 1]); move16(); /*-----------------------------------------------------------------* * 2. Find "biggest" pitch pulse *-----------------------------------------------------------------*/ /* Find the biggest last pulse from the end of the vector */#if(WMOPS) move16(); move16();#endif ptr = resf + G729EV_FEC_L_FRAME_FER - 1; maxval = *ptr--; maxi = (Word16) 0; FOR(i = 1; i < T0; i++) {#if(WMOPS) move16();#endif val = *ptr--; tmp16 = abs_s(val); IF(sub(tmp16, maxval) > 0) { maxval = tmp16; maxi = i; if (val < 0) { sign = (Word16) 1; } if (val >= 0) { sign = (Word16) 0; }#if(WMOPS) move16(); move16(); move16();#endif } } if (sign) { maxi = add(maxi, 256); } } ELSE { if (T0 < 0) { T0 = negate(T0); sign_in = (Word16) 1;#if(WMOPS) move16();#endif } /*-----------------------------------------------------------------* * 2. Find "biggest" pitch pulse *-----------------------------------------------------------------*/ ptr = res; /*if the decoded maximum pulse position is positive */ IF(sign_in == 0) {#if(WMOPS) move16(); move16();#endif maxval = 0; maxi = (Word16) 0; FOR(i = 1; i <= T0; i++) {#if(WMOPS) move16();#endif val = *ptr++; move16(); if (sub(val, maxval) >= 0) { maxval = val; maxi = i;#if(WMOPS) move16(); move16();#endif } } } ELSE /*if the decoded maximum pulse position is negative */ {#if(WMOPS) move16(); move16();#endif maxval = 0; maxi = 0; FOR(i = 1; i <= T0; i++) {#if(WMOPS) move16();#endif val = *ptr++; if (sub(val, maxval) <= 0) {#if(WMOPS) move16(); move16();#endif maxval = val; maxi = i; } } } } return (maxi);}/*-----------------------------------------------------------------* * Pitch prediction for frame erasure * *-----------------------------------------------------------------*/void G729EV_FEC_pitch_pred(Word16 bfi, /* i: Bad frame ? */ Word16 * T, /* i/o: Pitch */ Word16 * T_fr, /* i/o: fractionnal pitch */ Word16 * pit_mem,/* i/o: Pitch memories */ Word16 * bfi_mem /* i/o: Memory of bad frame indicator */ ){ Word16 pit, a, b, sum0, sum1; Word32 L_tmp; Word16 tmp; Word16 i; /*------------------------------------------------------------*/ IF(bfi != 0) { /* Correct pitch */ IF(*bfi_mem == 0) { FOR(i = 3; i >= 0; i--) { if (sub(abs_s(sub(pit_mem[i], pit_mem[i + 1])), 128) > 0) { pit_mem[i] = pit_mem[i + 1];#if(WMOPS) move16();#endif } } } /* Linear prediction (estimation) of pitch */#if(WMOPS) move16(); move32();#endif sum0 = 0; L_tmp = 0; FOR(i = 0; i < 5; i++) { sum0 = add(sum0, pit_mem[i]); L_tmp = L_mac(L_tmp, i, pit_mem[i]); } sum1 = extract_l(L_shr(L_tmp, 2)); a = sub(mult_r(19661, sum0), mult_r(13107, sum1)); b = sub(sum1, sum0); pit = add(a, b);#if(WMOPS) move16();#endif if (sub(pit, G729EV_FEC_PIT_MAX32) > 0) { pit = G729EV_FEC_PIT_MAX32; } if (sub(pit, G729EV_FEC_PIT_MIN32) < 0) { pit = G729EV_FEC_PIT_MIN32; }#if(WMOPS) move16(); move16();#endif *T = shr(add(pit, 16), 5); tmp = shl(*T, 5); IF(sub(pit, tmp) >= 0) { *T_fr = mult_r(sub(pit, tmp), 3072); } ELSE { *T_fr = negate(mult_r(sub(tmp, pit), 3072)); } } ELSE { pit = add(shl(*T, 5), mult_r(shl(*T_fr, 4), 21845)); } /* Update memory */ FOR(i = 0; i < 4; i++) { pit_mem[i] = pit_mem[i + 1];#if(WMOPS) move16();#endif }#if(WMOPS) move16(); move16();#endif pit_mem[4] = pit; *bfi_mem = bfi; /*------------------------------------------------------------*/ return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -