📄 g729ev_fec_clasdec.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 <stdio.h>#include <stdlib.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"/*---------------------------------------------------------------------** - Prototypes*---------------------------------------------------------------------*/static Word16 G729EV_FEC_frame_energy(const Word16 * pitch, const Word16 * speech, const Word16 lp_speech, Word16 * frame_ener, Word16 Q_syn);static void Corre(Word16 * x, Word16 * y, Word16 l, Word16 * gain);/*---------------------------------------------------------------------* * Signal classification at the decoder for FER concealment * Function used only at 8kbps. When bit rate >= 12kbps, the classification * is sent by the encoder. *---------------------------------------------------------------------*/void G729EV_FEC_clas_dec(Word16 * clas, /* i/o: frame classification */ const Word16 * pitch, /* i: pitch values for each subframe Q5 */ const Word16 last_good,/* i: type of the last correctly received fr. */ Word16 * frame_synth, /* i/o: synthesis buffer */ Word16 * st_old_synth, /* i/o: synthesis memory */ Word16 * lp_speech /* i/o: long term active speech energy average Q1 */ ){ Word16 i, j, pos; Word16 *pt1, *pt2, zc_frame, frame_ener, tmp_scale; Word16 tiltn, corn, zcn, pcn, fmerit1, enern, ener, tilt; Word16 voicing, cor_max[3], *synth, tmp16, exp1, exp2; Word32 Ltmp, Ltmp1, s1, s2; Word16 tmpS, zc[4], T0, pc, tmp_e, max, tmp_x, tmp_y; Word16 old_synth[G729EV_G729_PIT_MAX + G729EV_MAIN_L_FRAME2]; Word16 Q_syn; cor_max[0] = (Word16) 0; cor_max[1] = (Word16) 0; cor_max[2] = (Word16) 0; Q_syn = (Word16) - 1;#if(WMOPS) move16(); move16(); move16(); move16(); move16();#endif synth = old_synth + G729EV_G729_PIT_MAX; /* Pointer to the current frame */ /* Scaling synth to remove overflow results */ max = (Word16) 0; FOR(i = 0; i < G729EV_G729_PIT_MAX; i++) { tmp_e = abs_s(st_old_synth[i]); if (sub(tmp_e, max) > 0) { max = tmp_e;#if(WMOPS) move16();#endif } } FOR(i = 0; i < G729EV_MAIN_L_FRAME2; i++) { tmp_e = abs_s(frame_synth[i]); if (sub(tmp_e, max) > 0) { max = tmp_e;#if(WMOPS) move16();#endif } } tmp_scale = sub(norm_s(max), 3); if (sub(tmp_scale, 6) > 0) { tmp_scale = (Word16) 6;#if(WMOPS) move16();#endif } FOR(i = 0; i < G729EV_G729_PIT_MAX; i++) { old_synth[i] = shl(st_old_synth[i], tmp_scale);#if(WMOPS) move16();#endif } FOR(i = 0; i < G729EV_MAIN_L_FRAME2; i++) { old_synth[i + G729EV_G729_PIT_MAX] = shl(frame_synth[i], tmp_scale);#if(WMOPS) move16();#endif } Q_syn = add(Q_syn, tmp_scale); /*-----------------------------------------------------------------* - Compute the zero crossing rate for all subframes *-----------------------------------------------------------------*/ pt1 = (Word16 *) synth; pt2 = (Word16 *) synth - 1; FOR(i = 0; i < 4; i++) { tmpS = 0; FOR(j = 0; j < G729EV_G729_L_SUBFR; j++) {#if(WMOPS) test();#endif IF((*pt1 <= 0.0f) && (*pt2 > 0.0f)) { tmpS = add(tmpS, 1);; } pt1++; pt2++; } zc[i] = tmpS;#if(WMOPS) move16(); move16();#endif } zc_frame = add(zc[0], add(zc[1], add(zc[2], zc[3]))); /*-----------------------------------------------------------------* Compute the normalized correlation pitch-synch. at the end of the frame *-----------------------------------------------------------------*/ T0 = shr(pitch[3], G729EV_FEC_SQPIT); IF(sub(T0, 3 * (G729EV_G729_L_SUBFR / 2)) > 0) { T0 = shr(add(shr(add(pitch[2], pitch[3]), 1), G729EV_FEC_QPIT2), G729EV_FEC_SQPIT); }#if(WMOPS) move16(); move16();#endif pos = G729EV_MAIN_L_FRAME2; j = (Word16) 0; pt1 = synth; WHILE(sub(pos, 3 * G729EV_G729_L_SUBFR) > 0) { pos = sub(pos, T0); Corre(&pt1[pos], &pt1[pos - T0], T0, &cor_max[j]); IF(sub(sub(pos, T0), 3 * G729EV_G729_L_SUBFR) < 0) { T0 = shr(add(shr(add(pitch[2], pitch[3]), 1), G729EV_FEC_QPIT2), G729EV_FEC_SQPIT); } j = add(j, 1); } Ltmp = L_deposit_l(cor_max[0]); FOR(i = 1; i < j; i++) { Ltmp = L_add(Ltmp, cor_max[i]); } IF(sub(j, 3) == 0) { voicing = extract_l(L_mls(Ltmp, 10923)); } ELSE if (sub(j, 2) == 0) { voicing = extract_l(L_shr(Ltmp, 1)); } ELSE { voicing = extract_l(Ltmp); } pc = shr(abs_s(sub(add(pitch[3], sub(pitch[2], pitch[1])), pitch[0])), G729EV_FEC_SQPIT); /*-----------------------------------------------------------------* Compute spectral tilt *-----------------------------------------------------------------*/#if(WMOPS) move32(); move32();#endif Ltmp = (Word32) 0; Ltmp1 = (Word32) 0; pt1 = (Word16 *) synth + G729EV_G729_L_SUBFR; pt2 = (Word16 *) synth + G729EV_G729_L_SUBFR - 1; FOR(i = 0; i <= 2; i++) {#if(WMOPS) move32(); move32();#endif s1 = (Word32) 0; s2 = (Word32) 0; FOR(j = 0; j < G729EV_G729_L_SUBFR; j++) { s1 = L_mac(s1, *pt1, *pt1); s2 = L_mac(s2, *pt1, *pt2); pt1++; pt2++; } Ltmp = L_add(s1, L_shr(Ltmp, 1)); Ltmp1 = L_add(s2, L_shr(Ltmp1, 1)); } tmp16 = (Word16) - 1; IF(Ltmp1 < 0) { tmp16 = negate(tmp16); Ltmp1 = L_abs(Ltmp1); }#if(WMOPS) move16();#endif if (Ltmp == 0) { Ltmp = (Word32) 1;#if(WMOPS) move32();#endif } exp1 = norm_l(Ltmp1); tmp_y = extract_h(L_shl(Ltmp1, exp1)); exp1 = sub(31 - 1 + 3, exp1); exp2 = norm_l(Ltmp); tmp_x = extract_h(L_shl(Ltmp, exp2)); exp2 = sub(31 - 1 + 3, exp2); IF(sub(tmp_y, tmp_x) > 0) { tmp_y = shr(tmp_y, 1); exp1 = add(exp1, 1); } tilt = div_s(tmp_y, tmp_x); tilt = shl(tilt, sub(exp1, exp2)); /* sature to 1.0 */ if (tmp16 > 0) { tilt = negate(tilt); } /*-----------------------------------------------------------------* Compute pitch-synchronous energy at the frame end *-----------------------------------------------------------------*/ ener = G729EV_FEC_frame_energy(pitch, synth, *lp_speech, &frame_ener, Q_syn); /*-----------------------------------------------------------------* * transform parameters between 0 & 1 * find unique merit function *-----------------------------------------------------------------*/ enern = mac_r(G729EV_FEC_C_ENR, G729EV_FEC_K_ENR, ener); /*Q8 */ tiltn = extract_h(L_shr(L_mac(G729EV_FEC_C_TILT, G729EV_FEC_K_TILT, tilt), 6)); /*Q14 -> Q8 */ corn = extract_h(L_shr(L_mac(G729EV_FEC_C_COR, G729EV_FEC_K_COR, voicing), 5)); /*Q13 -> Q8 */ zcn = extract_h(L_shl(L_mac(G729EV_FEC_C_ZC_DEC, G729EV_FEC_K_ZC_DEC, zc_frame), 8)); /*Q0 -> Q8 */ pcn = extract_h(L_shl(L_mac(G729EV_FEC_C_PC_DEC, G729EV_FEC_K_PC_DEC, pc), 8)); /*Q0 -> Q8 */#if(WMOPS) move16();#endif IF(sub(pcn, 256) > 0) { pcn = (Word16) 256; } ELSE if (pcn < 0) { pcn = (Word16) 0; } /*fmerit1 = (1.0f/6.0f) * (tiltn + 2.0f*corn + zcn + pcn + enern); */ Ltmp = L_mult(tiltn, G729EV_FEC_UNS6); IF(corn > 0) { Ltmp = L_mac(Ltmp, corn, 4 * G729EV_FEC_UNS6); } ELSE { Ltmp = L_mac(Ltmp, corn, 2 * G729EV_FEC_UNS6); } Ltmp = L_mac(Ltmp, zcn, G729EV_FEC_UNS6); Ltmp = L_mac(Ltmp, pcn, G729EV_FEC_UNS6); Ltmp = L_mac(Ltmp, enern, G729EV_FEC_UNS6); fmerit1 = round(L_shl(Ltmp, 15 - 8)); /*Q15 can saturate to 1,0 */ /*-----------------------------------------------------------------* * frame classification *-----------------------------------------------------------------*/#if(WMOPS) move16();#endif SWITCH(last_good) {case G729EV_FEC_VOICED:case G729EV_FEC_ONSET:case G729EV_FEC_SIN_ONSET:case G729EV_FEC_V_TRANSITION: IF(sub(fmerit1, 12780) < 0) { *clas = G729EV_FEC_UNVOICED; } ELSE if (sub(fmerit1, 20644) < 0) { *clas = G729EV_FEC_V_TRANSITION; } ELSE { *clas = G729EV_FEC_VOICED; } BREAK;case G729EV_FEC_UNVOICED:case G729EV_FEC_UV_TRANSITION: IF(sub(fmerit1, 18350) > 0) { *clas = G729EV_FEC_ONSET; } ELSE if (sub(fmerit1, 14746) > 0) { *clas = G729EV_FEC_UV_TRANSITION; } ELSE { *clas = G729EV_FEC_UNVOICED; } BREAK;default: *clas = G729EV_FEC_UNVOICED; BREAK; } /*-----------------------------------------------------------------* * Measure average energy on good, active G729EV_FEC_VOICED frames for FER * concealment classification *-----------------------------------------------------------------*/ IF(sub(*clas, G729EV_FEC_VOICED) == 0) { Ltmp = L_mult(328, frame_ener); *lp_speech = mac_r(Ltmp, 32441, *lp_speech); /* lp_speech update */#if(WMOPS) move16();#endif } /*-----------------------------------------------------------------* * Update synthesized speech memory *-----------------------------------------------------------------*/ FOR(i = 0; i < G729EV_G729_PIT_MAX; i++) { st_old_synth[i] = shr(old_synth[i + G729EV_MAIN_L_FRAME2], tmp_scale);#if(WMOPS) move16();#endif } return;}/*---------------------------------------------------------------------* * Compute pitch-synchronous energy at the frame end*---------------------------------------------------------------------*/static Word16 G729EV_FEC_frame_energy( /* o: Pitch synchronus energy Q8 */ const Word16 * pitch, /* i: pitch values for each subframe Q5 */ const Word16 * speech, /* i: pointer to speech signal for E computation */ const Word16 lp_speech,/* i: long term active speech energy average Q8 */ Word16 * frame_ener, /* o: pitch-synchronous energy at frame end Q8 */ Word16 Q_syn /* i: Scaling of syntesis */ ){ Word32 Ltmp; Word16 *pt1, tmp16, exp1, frac1, tmp1, tmp2; Word16 len, enern; /*len = (short)( 0.5f * (pitch[2]/64.0 + pitch[3]/64.0) + 0.5f ); */ len = shr(add(shr(add(pitch[2], pitch[3]), 1), G729EV_FEC_QPIT2), G729EV_FEC_SQPIT); if (sub(len, G729EV_G729_L_SUBFR) < 0) { len = shl(len, 1); } pt1 = (Word16 *) speech + sub(G729EV_MAIN_L_FRAME2, len); /**frame_ener = 10.0f * log10(dot_product(pt1, pt1, len) / (float)len );*/ tmp1 = norm_s(len); tmp2 = shl(len, tmp1); tmp1 = sub(15, tmp1); tmp16 = extract_h(G729EV_Dot_product12(pt1, pt1, len, &exp1)); IF(sub(tmp16, tmp2) > 0) { tmp16 = shr(tmp16, 1); exp1 = add(exp1, 1); } tmp16 = div_s(tmp16, tmp2); exp1 = sub(exp1, tmp1); Log2(L_deposit_h(tmp16), &tmp16, &frac1); exp1 = sub(add(exp1, 31 + 1 - 3), add(tmp16, shl(Q_syn, 1))); frac1 = mult_r(frac1, tmp2); Ltmp = Mpy_32_16(exp1, frac1, G729EV_FEC_LG10); /*enern = *frame_ener - lp_speech; */ *frame_ener = extract_l(L_shr(Ltmp, 14 - 8)); enern = sub(*frame_ener, lp_speech);#if(WMOPS) move16();#endif return enern;}/*-----------------------------------------------------------------* * function Corre() * ~~~~~~~~ * Correlation function. Signal x is compared to target signal y * Information about the similarity between vectors is returned in *gain *-----------------------------------------------------------------*/static void Corre(Word16 * x, /* i: vector 1 Q12 */ Word16 * y, /* i: vector 2 Q12 */ Word16 l, /* i: length of vectors */ Word16 * gain /* o: normalized correlation gain Q15 */ ){ Word16 cor, cor_exp; Word16 den, den_exp; Word16 den2, den2_exp; Word32 tmp; Word16 tmp_exp; /* keep Q15 normalized result */ cor = extract_h(G729EV_Dot_product12(x, y, l, &cor_exp)); den = extract_h(G729EV_Dot_product12(y, y, l, &den_exp)); den2 = extract_h(G729EV_Dot_product12(x, x, l, &den2_exp)); /* keep Q31 normalized result */ tmp = L_mult(den, den2); tmp_exp = norm_l(tmp); tmp = L_shl(tmp, tmp_exp); tmp_exp = sub(add(den_exp, den2_exp), tmp_exp); Isqrt_n(&tmp, &tmp_exp); /* keep Q15 result */ gain[0] = shl(mult_r(cor, extract_h(tmp)), add(cor_exp, tmp_exp));#if(WMOPS) move16(); move16(); move16();#endif}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -