📄 g729ev_main_envadaption.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 "G729EV_MAIN_defines.h"#include "G729EV_MAIN_EnvAdaption.h"#include "G729EV_MAIN_DSPFUNC.h"#include "G729EV_MAIN_OPER_32B.h"/*--------------------------------------------------------------------------* * Function get_Energy() * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * Compute subframe energy * *--------------------------------------------------------------------------*/void G729EV_MAIN_get_Energy(Word16 * pSample, /* (i) input samples */ Word32 * pELow, /* (o) energy (LSB) */ Word16 * pEHigh /* (o) energy (MSB) */ ){ Word16 i; Overflow = 0;#ifdef WMOPS move16();#endif FOR(i = 0; i < G729EV_MAIN_PRE_SUBFRAME; i++) { *pELow = L_macNs(*pELow, pSample[i], pSample[i]); if (Overflow != 0) *pEHigh = add(*pEHigh, 1); if (Overflow != 0) *pELow = L_and(*pELow, 0x7fffffff); if (Overflow != 0) { Overflow = 0;#ifdef WMOPS move16();#endif } }}/*--------------------------------------------------------------------------* * Function G729EV_MAIN_getV() * * ~~~~~~~~~~~~~~~~~~~~~~~~~~ ~ * * Compute attenuation factor e_num/e_den * *--------------------------------------------------------------------------*/Word16 G729EV_MAIN_getV(Word32 e_num, /* (i) numerator */ Word32 e_den /* (i) denominator */ ){ Word16 v; Word16 n1, n2, d, n; Word32 v32, e_den32; Word16 e_num16; n1 = norm_l(e_num); n2 = norm_l(e_den); e_den32 = L_shl(e_den, sub(n2, 1)); e_num16 = extract_l(L_shl(e_num, sub(n1, 16))); d = div_l(e_den32, e_num16); v32 = Inv_sqrt(d); n = add(sub(n2, n1), 14); v = extract_l(L_shr(v32, sub(23, shr(n, 1)))); /* Q30->Q7 */ IF(L_and(n, 1) != 0) /* (n%2 !=0) */ { v32 = L_mult(v, 0x5a82); /* (REAL)v32*1.41; */ v = shl(extract_h(v32), 1); /* extract_h(v32*4); */ } v = i_mult(v, 0x100); return (v);}/*--------------------------------------------------------------------------* * Function G729EV_MAIN_smooth() * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * Smooth gain * *--------------------------------------------------------------------------*/Word16 G729EV_MAIN_smooth(Word16 lastVal, /* (i) smoothing filter memory */ Word16 newVal /* (i) input gain */ ){ Word32 acc; /* return lastVal*0.85 + newVal*0.15 */ acc = L_mult(lastVal, 0x6ccd); acc = L_mac(acc, newVal, 0x1333); return round(acc);}/*--------------------------------------------------------------------------* * Function G729EV_MAIN_envAdapt() * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * Reduce pre/postecho in lower and higher band * * Add CELP and TDAC synthesis in lower-band * *--------------------------------------------------------------------------*/void G729EV_MAIN_envAdapt(Word16 * sOut_low, /* (o) output samples lowband */ Word16 * sBasic_low, /* (i) 12k layer contribution (lowband) */ Word16 * sTdacAdd_low, /* (i) TDAC layer add-on for lowand */ Word16 * vmlold, /* (i) needed for lowband gain smoothing */ Word16 * sOut_hi, /* (o) output samples highband */ Word16 * sBasic_hi, /* (i) 14k layer contribution (highband) */ Word16 * sTdacInc_hi, /* (i) highband signal TDBWE combinded with TDAC */ Word16 * vmhold, /* (i) needed for highband gain smoothing */ Word16 work, /* (i) if zero ->do not cancel echo (rate<=14000) */ Word16 begin_index_low, /* (i) start index for false alarm zone in lower-band */ Word16 end_index_low, /* (i) stop index for false alarm zone in lower-band */ Word16 begin_index_high,/* (i) start index for false alarm zone in higher-band */ Word16 end_index_high /* (i) stop index for false alarm zone in higher-band */ ){ Word16 i, j; Word16 vl, vh; Word16 vml[G729EV_MAIN_L_FRAME2]; Word16 vmh[G729EV_MAIN_L_FRAME2]; Word16 sBasicLow_tilt[G729EV_MAIN_L_FRAME2]; Word16 sTdacAddLow_tilt[G729EV_MAIN_L_FRAME2]; Word16 *sHelp1; Word16 *sHelp2; Word32 EsBasicLow; Word32 EsTdacAddLow; Word32 EsBasicHi; Word32 EsTdacIncHi; Word16 EsBasicLowHigh; Word16 EsTdacAddLowHigh; Word16 EsBasicHiHigh; Word16 EsTdacIncHiHigh; Word32 EsTdacIncHi081; Word16 *pvl; Word16 *pvh; Word16 Hi, Lo; /* apply tilt on lowband before comparing energies */ sHelp1 = sBasic_low - 1; sHelp2 = sTdacAdd_low - 1;#ifdef WMOPS move16(); move16();#endif FOR(j = 1; j < G729EV_MAIN_L_FRAME2; j++) { sBasicLow_tilt[j] = sub(sBasic_low[j], sHelp1[j]);#ifdef WMOPS move16();#endif sTdacAddLow_tilt[j] = sub(sTdacAdd_low[j], sHelp2[j]);#ifdef WMOPS move16();#endif } sBasicLow_tilt[0] = 0;#ifdef WMOPS move16();#endif sTdacAddLow_tilt[0] = 0;#ifdef WMOPS move16();#endif /* compare energies, get scale factors */ FOR(j = 0; j < G729EV_MAIN_L_FRAME2; j = j + G729EV_MAIN_PRE_SUBFRAME) { IF(work) { /* get energies */ EsBasicLow = 100; EsTdacAddLow = 100; EsBasicHi = 100; EsTdacIncHi = 100;#ifdef WMOPS move32(); move32(); move32(); move32();#endif EsBasicLowHigh = 0; EsTdacAddLowHigh = 0; EsBasicHiHigh = 0; EsTdacIncHiHigh = 0;#ifdef WMOPS move16(); move16(); move16(); move16();#endif Overflow = 0; Carry = 0;#ifdef WMOPS move16(); move16();#endif G729EV_MAIN_get_Energy(&sBasicLow_tilt[j], &EsBasicLow, &EsBasicLowHigh); G729EV_MAIN_get_Energy(&sTdacAddLow_tilt[j], &EsTdacAddLow, &EsTdacAddLowHigh); G729EV_MAIN_get_Energy(&sBasic_hi[j], &EsBasicHi, &EsBasicHiHigh); G729EV_MAIN_get_Energy(&sTdacInc_hi[j], &EsTdacIncHi, &EsTdacIncHiHigh); /* if highpart of energy != zero, normalize */ IF(add(EsBasicLowHigh, EsTdacAddLowHigh) != 0) { Word16 max16, v, i31mv; max16 = s_max(EsBasicLowHigh, EsTdacAddLowHigh); v = norm_l(max16); i31mv = sub(31, v); EsBasicLow = L_add(L_shl(EsBasicLowHigh, v), L_shr((EsBasicLow & 0x7fffffff), i31mv)); EsTdacAddLow = L_add(L_shl(EsTdacAddLowHigh, v), L_shr((EsTdacAddLow & 0x7fffffff), i31mv)); } IF(L_sub(EsBasicLow, EsTdacAddLow) >= 0) /* if EsBasicLow>=EsTdacAddLow */ { vl = 0x7fff; /* vl=1 */#ifdef WMOPS move16();#endif } ELSE { vl = G729EV_MAIN_getV(EsBasicLow, EsTdacAddLow); } /* if highpart of energy != zero, normalize */ IF(add(EsBasicHiHigh, EsTdacIncHiHigh) != 0) { Word16 max16, v, i31mv; max16 = s_max(EsBasicHiHigh, EsTdacIncHiHigh); v = norm_l(max16); i31mv = sub(31, v); EsBasicHi = L_add(L_shl(EsBasicHiHigh, v), L_shr((EsBasicHi & 0x7fffffff), i31mv)); EsTdacIncHi = L_add(L_shl(EsTdacIncHiHigh, v), L_shr((EsTdacIncHi & 0x7fffffff), i31mv)); } /* EsTdacIncHi081=EsTdacIncHi*0.81: */ L_Extract(EsTdacIncHi, &Hi, &Lo); EsTdacIncHi081 = Mpy_32_16(Hi, Lo, 0x67ae); IF(L_sub(EsBasicHi, EsTdacIncHi081) >= 0) { vh = 0x7fff; /* vh=1 */#ifdef WMOPS move16();#endif } ELSE { vh = G729EV_MAIN_getV(EsBasicHi, EsTdacIncHi); } } ELSE { vh = 0x7fff; /* vh=1 */ vl = 0x7fff; /* vl=1 */#ifdef WMOPS move16(); move16();#endif } pvl = &vml[j]; pvh = &vmh[j];#ifdef WMOPS move16(); move16();#endif FOR(i = 0; i < G729EV_MAIN_PRE_SUBFRAME; i++) { pvl[i] = vl; pvh[i] = vh;#ifdef WMOPS move16(); move16();#endif } }/* begin_index_low = 0; end_index_low = 159; no preecho supression */ FOR(i = begin_index_low; i <= end_index_low; i++) { vml[i] = 0x7fff;#ifdef WMOPS move16();#endif } FOR(i = begin_index_high; i <= end_index_high; i++) { vmh[i] = 0x7fff;#ifdef WMOPS move16();#endif } /* EnvAdaption - smoothing of gains */ vmh[0] = G729EV_MAIN_smooth(*vmhold, vmh[0]); vml[0] = G729EV_MAIN_smooth(*vmlold, vml[0]);#ifdef WMOPS move16(); move16();#endif FOR(i = 1; i < (G729EV_MAIN_L_FRAME2); i++) { vmh[i] = G729EV_MAIN_smooth(vmh[i - 1], vmh[i]); vml[i] = G729EV_MAIN_smooth(vml[i - 1], vml[i]);#ifdef WMOPS move16(); move16();#endif } /* update vmh vml memory */ *vmlold = vml[(G729EV_MAIN_L_FRAME2) - 1]; *vmhold = vmh[(G729EV_MAIN_L_FRAME2) - 1];#ifdef WMOPS move16(); move16();#endif FOR(i = 0; i < G729EV_MAIN_L_FRAME2; i++) { sOut_low[i] = add(sBasic_low[i], mult_r(sTdacAdd_low[i], vml[i])); sOut_hi[i] = mult_r(sTdacInc_hi[i], vmh[i]);#ifdef WMOPS move16(); move16();#endif }}/*--------------------------------------------------------------------------* * Function G729EV_MAIN_PreechoFalseAlarm() * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * Determine start/stop indices for false alarm zone in lower- and higher- * * band * *--------------------------------------------------------------------------*/void G729EV_MAIN_PreechoFalseAlarm(Word16 * rec_sig, /* (i) reconstructed signal, output of the imdct transform */ Word16 * imdct_mem, /* (i) memory of the imdct transform, used in the next frame */ Word32 * max_prev, /* (i/o) maximum energy in the previous reconstructed frame */ Word16 * begin_ind, /* (o) starting index of the eventual false alarm zone */ Word16 * end_ind /* (o) ending index of the eventual false alarm zone */ ){ Word16 i, j; Word32 es_tdac[6]; /* 0..3: energy of the 4 subframes, 4..5: energy of the future subframes */ Word32 min_es, max_es, max_rec = 0; Word16 *ptr; /*energy of low bands 4 present and 2 future sub-frames */ FOR(i = 0; i < 6; i++) { es_tdac[i] = 100;#ifdef WMOPS move32();#endif } ptr = rec_sig;#if(WMOPS) move16();#endif FOR(j = 0; j < 4; j++) /*4 present subframes */ { FOR(i = 0; i < G729EV_MAIN_PRE_SUBFRAME; i++) { es_tdac[j] = L_mac0(es_tdac[j], *ptr, *ptr);#ifdef WMOPS move32();#endif ptr++; } } ptr = imdct_mem;#if(WMOPS) move16();#endif FOR(j = 4; j < 6; j++) /*2 future subframes */ { FOR(i = 0; i < G729EV_MAIN_PRE_SUBFRAME; i++) { es_tdac[j] = L_mac(es_tdac[j], *ptr, *ptr); /*including *=2 as the max of the synthesis window is sqrt(2) */#ifdef WMOPS move32();#endif ptr++; } } min_es = es_tdac[0]; /* for memorising the min energy */ max_es = es_tdac[0]; /* for memorising the max energy */ *begin_ind = 0;#if(WMOPS) move32(); move32(); move16();#endif FOR(i = 1; i < 6; i++) { if (L_sub(es_tdac[i], max_es) > 0) { max_es = es_tdac[i]; /* max energy low band, 4 present and 2 future subframes */ *begin_ind = extract_l(L_mult0(i, G729EV_MAIN_PRE_SUBFRAME));#ifdef WMOPS move32();#endif } if (sub(i, 3) == 0) { max_rec = max_es; /*save partial max result for the 4 present subframes */#ifdef WMOPS move32();#endif } } IF(L_sub(L_shr(*max_prev, 5), max_rec) >= 0) /*post-echo situation, preecho false alarm detection desactivated */ { *begin_ind = G729EV_MAIN_L_FRAME2; *end_ind = G729EV_MAIN_L_FRAME2 - 1; /* begin > end --> nothing is done */ *max_prev = max_rec;#ifdef WMOPS move16(); move16(); move32();#endif } ELSE { *max_prev = max_rec;#ifdef WMOPS move32();#endif FOR(i = 1; i < 4; i++) { if (L_sub(es_tdac[i], min_es) < 0) { min_es = es_tdac[i]; /* min energy low band, 4 present subframes only */#ifdef WMOPS move32();#endif } } IF(L_sub(L_shr(max_es, 4), min_es) < 0) /* no big energy change --> no preecho ->false alarm zone:the whole frame */ { *begin_ind = 0; *end_ind = G729EV_MAIN_L_FRAME2 - 1;#ifdef WMOPS move16(); move16();#endif } ELSE { *end_ind = add(*begin_ind, 2 * G729EV_MAIN_PRE_SUBFRAME - 1); /*length of the false alarm zone is 2 subframes */ if (sub(*end_ind, G729EV_MAIN_L_FRAME2 - 1) > 0) { *end_ind = G729EV_MAIN_L_FRAME2 - 1;#ifdef WMOPS move16();#endif } } } return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -