📄 g729ev_g729b_calcexc.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 "stl.h"#include "G729EV_MAIN_OPER_32B.h"#include "G729EV_MAIN_DSPFUNC.h"#include "G729EV_G729_defines.h"#include "G729EV_G729_ld8k.h"#include "G729EV_G729B_defines.h"/* Local functions */static Word16 Gauss(Word16 * seed);static Word16 Sqrt(Word32 Num);/*-----------------------------------------------------------* * procedure Calc_exc_rand * * ~~~~~~~~~~~~~ * * Computes comfort noise excitation * * for SID and not-transmitted frames * *-----------------------------------------------------------*/void Calc_exc_rand(G729EV_G729_DECSTAT * pDecStat, Word16 cur_gain, /* (i) : target sample gain */ Word16 * exc, /* (i/o) : excitation array */ Word16 * seed, /* (i) : current Vad decision */ Flag flag_cod /* (i) : encoder/decoder flag */ ){ Word16 i, j, i_subfr; Word16 temp1, temp2, tmp16; Word16 pos[4]; Word16 sign[4]; Word16 t0, frac; Word16 *cur_exc; Word16 g, Gp, Gp2; Word16 excg[G729EV_G729_L_SUBFR], excs[G729EV_G729_L_SUBFR]; Word32 L_acc, L_ener, L_k; Word16 max, hi, lo, inter_exc; Word16 sh; Word16 x1, x2; IF(cur_gain == 0) { FOR(i = 0; i < G729EV_G729_L_FRAME; i++) { exc[i] = 0;#if(WMOPS) move16();#endif } return; } /* Loop on subframes */ cur_exc = exc; FOR(i_subfr = 0; i_subfr < G729EV_G729_L_FRAME; i_subfr = add(i_subfr, G729EV_G729_L_SUBFR)) { /* generate random adaptive codebook & fixed codebook parameters */ /*****************************************************************/ temp1 = G729EV_G729_Random(seed); frac = sub(s_and(temp1, (Word16) 0x0003), 1); if (sub(frac, 2) == 0) { frac = 0;#if(WMOPS) move16();#endif } temp1 = shr(temp1, 2); t0 = add(s_and(temp1, (Word16) 0x003F), 40); temp1 = shr(temp1, 6); temp2 = s_and(temp1, (Word16) 0x0007); pos[0] = add(shl(temp2, 2), temp2); /* 5 * temp2 */#if(WMOPS) move16();#endif temp1 = shr(temp1, 3); sign[0] = s_and(temp1, (Word16) 0x0001); temp1 = shr(temp1, 1); temp2 = s_and(temp1, (Word16) 0x0007); temp2 = add(shl(temp2, 2), temp2); pos[1] = add(temp2, 1); /* 5 * x + 1 */#if(WMOPS) move16();#endif temp1 = shr(temp1, 3); sign[1] = s_and(temp1, (Word16) 0x0001);#if(WMOPS) move16();#endif temp1 = G729EV_G729_Random(seed); temp2 = s_and(temp1, (Word16) 0x0007); temp2 = add(shl(temp2, 2), temp2); pos[2] = add(temp2, 2); /* 5 * x + 2 */#if(WMOPS) move16();#endif temp1 = shr(temp1, 3); sign[2] = s_and(temp1, (Word16) 0x0001); temp1 = shr(temp1, 1); temp2 = s_and(temp1, (Word16) 0x000F); pos[3] = add(s_and(temp2, (Word16) 1), 3); /* j+3 */#if(WMOPS) move16();#endif temp2 = s_and(shr(temp2, 1), (Word16) 7); temp2 = add(shl(temp2, 2), temp2); /* 5i */ pos[3] = add(pos[3], temp2);#if(WMOPS) move16();#endif temp1 = shr(temp1, 4); sign[3] = s_and(temp1, (Word16) 0x0001);#if(WMOPS) move16();#endif Gp = s_and(G729EV_G729_Random(seed), (Word16) 0x1FFF); /* < 0.5 Q14 */ Gp2 = shl(Gp, 1); /* Q15 */ /* Generate gaussian excitation */ /********************************/ L_acc = 0L; FOR(i = 0; i < G729EV_G729_L_SUBFR; i++) { temp1 = Gauss(seed); L_acc = L_mac(L_acc, temp1, temp1); excg[i] = temp1;#if(WMOPS) move16();#endif }/* Compute fact = alpha x cur_gain * sqrt(L_SUBFR / Eg) with Eg = SUM(i=0->39) excg[i]^2 and alpha = 0.5 alpha x sqrt(L_SUBFR)/2 = 1 + FRAC1*/ L_acc = Inv_sqrt(L_shr(L_acc, 1)); /* Q30 */ L_Extract(L_acc, &hi, &lo); /* cur_gain = cur_gainR << 3 */ temp1 = mult_r(cur_gain, FRAC1); temp1 = add(cur_gain, temp1); /* <=> alpha x cur_gainR x 2^2 x sqrt(L_SUBFR) */ L_acc = Mpy_32_16(hi, lo, temp1); /* fact << 17 */ sh = norm_l(L_acc); temp1 = extract_h(L_shl(L_acc, sh)); /* fact << (sh+1) */ sh = sub(sh, 14); FOR(i = 0; i < G729EV_G729_L_SUBFR; i++) { temp2 = mult_r(excg[i], temp1); temp2 = shr_r(temp2, sh); /* shl if sh < 0 */ excg[i] = temp2;#if(WMOPS) move16();#endif } /* generate random adaptive excitation */ /****************************************/ G729EV_G729_Pred_lt_3(cur_exc, t0, frac, G729EV_G729_L_SUBFR); FOR(i = 0; i < G729EV_G729_L_SUBFR; i++) { cur_exc[i] = shr(cur_exc[i], 1);#if(WMOPS) move16();#endif } /* compute adaptive + gaussian exc -> cur_exc */ /**********************************************/ max = 0;#if(WMOPS) move16();#endif FOR(i = 0; i < G729EV_G729_L_SUBFR; i++) { temp1 = mult_r(cur_exc[i], Gp2); temp1 = add(temp1, excg[i]); /* may overflow */ cur_exc[i] = temp1;#if(WMOPS) move16();#endif temp1 = abs_s(temp1); if (sub(temp1, max) > 0) { max = temp1;#if(WMOPS) move16();#endif } } /* rescale cur_exc -> excs */ IF(max == 0) { sh = 0;#if(WMOPS) move16();#endif } ELSE { sh = sub(3, norm_s(max)); if (sh <= 0) { sh = 0;#if(WMOPS) move16();#endif } } FOR(i = 0; i < G729EV_G729_L_SUBFR; i++) { excs[i] = shr(cur_exc[i], sh);#if(WMOPS) move16();#endif } /* Compute fixed code gain */ /***************************/ /**********************************************************/ /*** Solve EQ(X) = 4 X**2 + 2 b X + c */ /**********************************************************/ L_ener = 0L;#if(WMOPS) move32();#endif FOR(i = 0; i < G729EV_G729_L_SUBFR; i++) { L_ener = L_mac(L_ener, excs[i], excs[i]); } /* ener x 2^(-2sh + 1) */ /* inter_exc = b >> sh */ inter_exc = 0;#if(WMOPS) move16();#endif FOR(i = 0; i < 4; i++) { j = pos[i];#if(WMOPS) move16();#endif IF(sign[i] == 0) { inter_exc = sub(inter_exc, excs[j]); } ELSE { inter_exc = add(inter_exc, excs[j]); } } /* Compute k = cur_gainR x cur_gainR x L_SUBFR */ L_acc = L_mult(cur_gain, G729EV_G729_L_SUBFR); L_acc = L_shr(L_acc, 6); temp1 = extract_l(L_acc); /* cur_gainR x L_SUBFR x 2^(-2) */ L_k = L_mult(cur_gain, temp1); /* k << 2 */ temp1 = add(1, shl(sh, 1)); L_acc = L_shr(L_k, temp1); /* k x 2^(-2sh+1) */ /* Compute delta = b^2 - 4 c */ L_acc = L_sub(L_acc, L_ener); /* - 4 c x 2^(-2sh-1) */ inter_exc = shr(inter_exc, 1); L_acc = L_mac(L_acc, inter_exc, inter_exc); /* 2^(-2sh-1) */ sh = add(sh, 1); /* inter_exc = b x 2^(-sh) */ /* L_acc = delta x 2^(-2sh+1) */ IF(L_acc < 0) { /* adaptive excitation = 0 */ G729EV_G729_Copy(excg, cur_exc, G729EV_G729_L_SUBFR); temp1 = s_or(abs_s(excg[(int) pos[0]]), abs_s(excg[(int) pos[1]])); temp2 = s_or(abs_s(excg[(int) pos[2]]), abs_s(excg[(int) pos[3]])); temp1 = s_or(temp1, temp2); IF(s_and(temp1, (Word16) 0x4000) == 0) sh = (Word16) 1; ELSE sh = (Word16) 2; inter_exc = 0;#if(WMOPS) move16(); move16();#endif FOR(i = 0; i < 4; i++) { temp1 = shr(excg[(int) pos[i]], sh); IF(sign[i] == 0) { inter_exc = sub(inter_exc, temp1); } ELSE { inter_exc = add(inter_exc, temp1); } } /* inter_exc = b >> sh */ L_Extract(L_k, &hi, &lo); L_acc = Mpy_32_16(hi, lo, K0); /* k x (1- alpha^2) << 2 */ temp1 = sub(shl(sh, 1), 1); /* temp1 > 0 */ L_acc = L_shr(L_acc, temp1); /* 4k x (1 - alpha^2) << (-2sh+1) */ L_acc = L_mac(L_acc, inter_exc, inter_exc); /* delta << (-2sh+1) */ Gp = 0;#if(WMOPS) move16();#endif } temp2 = Sqrt(L_acc); /* >> sh */ x1 = sub(temp2, inter_exc); x2 = negate(add(inter_exc, temp2)); /* x 2^(-sh+2) */ if (sub(abs_s(x2), abs_s(x1)) < 0) { x1 = x2;#if(WMOPS) move16();#endif } temp1 = sub(2, sh); g = shr_r(x1, temp1); /* shl if temp1 < 0 */ IF(g >= 0) { if (sub(g, G_MAX) > 0) { g = G_MAX;#if(WMOPS) move16();#endif } } ELSE { if (add(g, G_MAX) < 0) { g = negate(G_MAX);#if(WMOPS) move16();#endif } } /* Update cur_exc with ACELP excitation */ FOR(i = 0; i < 4; i++) { j = pos[i];#if(WMOPS) move16();#endif IF(sign[i] != 0) { cur_exc[j] = add(cur_exc[j], g); } ELSE { cur_exc[j] = sub(cur_exc[j], g); }#if(WMOPS) move16();#endif } FOR(i = 0; i < G729EV_G729_L_SUBFR; i++) { cur_exc[i] = shl(cur_exc[i], 1);#if(WMOPS) move16();#endif } tmp16 = add(pDecStat->i_subfr_cnt, 1); tmp16 = i_mult(tmp16, 3277); pDecStat->lp_gainp = add(pDecStat->lp_gainp, mult_r(tmp16, Gp)); pDecStat->lp_gainc = add(pDecStat->lp_gainc, mult_r(tmp16, shl(g, 3))); pDecStat->tilt_code = extract_l(L_shr(L_add(-29491, 32767), 2)); pDecStat->i_subfr_cnt = add(pDecStat->i_subfr_cnt, 1); cur_exc += G729EV_G729_L_SUBFR; } /* end of loop on subframes */ return;}/*-----------------------------------------------------------* * Local procedures * * ~~~~~~~~~~~~~~~~ * *-----------------------------------------------------------*//* Gaussian generation *//***********************/static Word16 Gauss(Word16 * seed){/**** Xi = uniform v.a. in [-32768, 32767] ****//**** Z = SUM(i=1->12) Xi / 2 x 32768 is N(0,1) ****//**** output : Z x 512 < 2^12 ****/ Word16 i; Word16 temp; Word32 L_acc; L_acc = 0L;#if(WMOPS) move32();#endif FOR(i = 0; i < 12; i++) { L_acc = L_add(L_acc, L_deposit_l(G729EV_G729_Random(seed))); } L_acc = L_shr(L_acc, 7); temp = extract_l(L_acc); return (temp);}/* Square root function : returns sqrt(Num/2) *//**********************************************/static Word16 Sqrt(Word32 Num){ Word16 i; Word16 Rez = (Word16) 0; Word16 Exp = (Word16) 0x4000; Word32 Acc, L_temp; FOR(i = 0; i < 14; i++) { Acc = L_mult(add(Rez, Exp), add(Rez, Exp)); L_temp = L_sub(Num, Acc); if (L_temp >= 0L) Rez = add(Rez, Exp); Exp = shr(Exp, (Word16) 1); } return Rez;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -