void WebRtcG729fix_Log2( int32_t L_x, /* (i) Q0 : input value */ int16_t *exponent, /* (o) Q0 : Integer part of Log2. (range: 0<=val<=30) */ int16_t *fraction /* (o) Q15: Fractional part of Log2. (range: 0<=val<1) */ ) { int16_t exp, i, a, tmp; int32_t L_y; if( L_x <= (int32_t)0 ) { *exponent = 0; *fraction = 0; return; } exp = WebRtcSpl_NormW32(L_x); L_x = L_shl(L_x, exp ); /* L_x is normalized */ *exponent = WebRtcSpl_SubSatW16(30, exp); L_x = L_shr(L_x, 9); i = extract_h(L_x); /* Extract b25-b31 */ L_x = L_shr(L_x, 1); a = extract_l(L_x); /* Extract b10-b24 of fraction */ a = a & (int16_t)0x7fff; i = WebRtcSpl_SubSatW16(i, 32); L_y = L_deposit_h(WebRtcG729fix_tablog[i]); /* tablog[i] << 16 */ tmp = WebRtcSpl_SubSatW16(WebRtcG729fix_tablog[i], WebRtcG729fix_tablog[i+1]); /* tablog[i] - tablog[i+1] */ L_y = L_msu(L_y, tmp, a); /* L_y -= tmp*a*2 */ *fraction = extract_h( L_y); }
/* extract elementary LSP from composed LSP with previous LSP */ void Lsp_prev_extract( Word16 lsp[M], /* (i) Q13 : unquantized LSP parameters */ Word16 lsp_ele[M], /* (o) Q13 : target vector */ Word16 fg[MA_NP][M], /* (i) Q15 : MA prediction coef. */ Word16 freq_prev[MA_NP][M], /* (i) Q13 : previous LSP vector */ Word16 fg_sum_inv[M] /* (i) Q12 : inverse previous LSP vector */ ) { Word16 j, k; Word32 L_temp; /* Q19 */ Word16 temp; /* Q13 */ for ( j = 0 ; j < M ; j++ ) { L_temp = L_deposit_h(lsp[j]); for ( k = 0 ; k < MA_NP ; k++ ) L_temp = L_msu( L_temp, freq_prev[k][j], fg[k][j] ); temp = extract_h(L_temp); L_temp = L_mult( temp, fg_sum_inv[j] ); lsp_ele[j] = extract_h( L_shl( L_temp, 3 ) ); } return; }
void Get_wegt( Word16 flsp[], /* (i) Q13 : M LSP parameters */ Word16 wegt[] /* (o) Q11->norm : M weighting coefficients */ ) { Word16 i; Word16 tmp; Word32 L_acc; Word16 sft; Word16 buf[M]; /* in Q13 */ buf[0] = sub( flsp[1], (PI04+8192) ); /* 8192:1.0(Q13) */ for ( i = 1 ; i < M-1 ; i++ ) { tmp = sub( flsp[i+1], flsp[i-1] ); buf[i] = sub( tmp, 8192 ); } buf[M-1] = sub( (PI92-8192), flsp[M-2] ); /* */ for ( i = 0 ; i < M ; i++ ) { if ( buf[i] > 0 ){ wegt[i] = 2048; /* 2048:1.0(Q11) */ } else { L_acc = L_mult( buf[i], buf[i] ); /* L_acc in Q27 */ tmp = extract_h( L_shl( L_acc, 2 ) ); /* tmp in Q13 */ L_acc = L_mult( tmp, CONST10 ); /* L_acc in Q25 */ tmp = extract_h( L_shl( L_acc, 2 ) ); /* tmp in Q11 */ wegt[i] = add( tmp, 2048 ); /* wegt in Q11 */ } } /* */ L_acc = L_mult( wegt[4], CONST12 ); /* L_acc in Q26 */ wegt[4] = extract_h( L_shl( L_acc, 1 ) ); /* wegt in Q11 */ L_acc = L_mult( wegt[5], CONST12 ); /* L_acc in Q26 */ wegt[5] = extract_h( L_shl( L_acc, 1 ) ); /* wegt in Q11 */ /* wegt: Q11 -> normalized */ tmp = 0; for ( i = 0; i < M; i++ ) { if ( sub(wegt[i], tmp) > 0 ) { tmp = wegt[i]; } } sft = norm_s(tmp); for ( i = 0; i < M; i++ ) { wegt[i] = shl(wegt[i], sft); /* wegt in Q(11+sft) */ } return; }
/*-------------------------------------------------------------------* * Function set_sign() * * ~~~~~~~~~~~~~~~~~~~~ * * Set the sign of each pulse position. * *-------------------------------------------------------------------*/ static void set_sign( Word16 fac_cn, /* (i) Q15: residual weight for sign determination */ Word16 cn[], /* (i) Q0 : residual after long term prediction */ Word16 dn[], /* (i) Q0 : correlation between target and h[] */ Word16 sign[], /* (o) Q15: sign vector (sign of each position) */ Word16 inv_sign[], /* (o) Q15: inverse of sign[] */ Word16 pos_max[], /* (o) : pos of max of correlation */ Word32 corr[] /* (o) : correlation of each track */ ) { Word16 i, k, pos, k_cn, k_dn, val; Word32 s, max; /* calculate energy for normalization of cn[] and dn[] */ s = 0; for (i=0; i<L_SUBFR; i++) s = L_mac(s, cn[i], cn[i]); if (s < 512) s = 512; s = Inv_sqrt(s); k_cn = extract_h(L_shl(s, 5)); /* k_cn = 11..23170 */ k_cn = mult(k_cn, fac_cn); s = 0; for (i=0; i<L_SUBFR; i++) s = L_mac(s, dn[i], dn[i]); if (s < 512) s = 512; s = Inv_sqrt(s); k_dn = extract_h(L_shl(s, 5)); /* k_dn = 11..23170 */ /* set sign according to en[] = k_cn*cn[] + k_dn*dn[] */ /* find position of maximum of correlation in each track */ for (k=0; k<NB_TRACK; k++) { max = -1; for (i=k; i<L_SUBFR; i+=STEP) { val = dn[i]; s = L_mac(L_mult(k_cn, cn[i]), k_dn, val); if (s >= 0) { sign[i] = 32767L; /* sign = +1 (Q15) */ inv_sign[i] = -32768L; } else { sign[i] = -32768L; /* sign = -1 (Q15) */ inv_sign[i] = 32767L; val = negate(val); } dn[i] = val; /* modify dn[] according to the fixed sign */ s = L_abs(s); if (s > max) { max = s; pos = i; } } pos_max[k] = pos; corr[k] = max; } return; }
/***************************************************************************** * * Function Name : Mpy_32_32_ss * * Purpose : * * Multiplies the 2 signed values L_var1 and L_var2 with saturation control * on 64-bit. The operation is performed in fractional mode : * - L_var1 and L_var2 are supposed to be in 1Q31 format. * - The result is produced in 1Q63 format : L_varout_h points to the * 32 MSBits while L_varout_l points to the 32 LSBits. * * Complexity weight : 4 * * Inputs : * * L_var1 32 bit long signed integer (Word32) whose value falls in the * range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. * * L_var2 32 bit long signed integer (Word32) whose value falls in the * range : 0x8000 0000 <= L_var2 <= 0x7fff ffff. * * Outputs : * * *L_varout_h 32 bit long signed integer (Word32) whose value falls in * the range : 0x8000 0000 <= L_varout_h <= 0x7fff ffff. * * *L_varout_l 32 bit short unsigned integer (UWord32) whose value falls in * the range : 0x0000 0000 <= L_varout_l <= 0xffff ffff. * * * Return Value : * * none * *****************************************************************************/ void Mpy_32_32_ss( Word32 L_var1, Word32 L_var2, Word32 *L_varout_h, UWord32 *L_varout_l) { UWord16 uvar1_l, uvar2_l; Word16 var1_h, var2_h; Word40 L40_var1; if( (L_var1 == ( Word32)0x80000000) && (L_var2 == ( Word32)0x80000000)) { *L_varout_h = 0x7fffffff; *L_varout_l = ( UWord32)0xffffffff; } else { uvar1_l = extract_l( L_var1); var1_h = extract_h( L_var1); uvar2_l = extract_l( L_var2); var2_h = extract_h( L_var2); /* Below line can not overflow, so we can use << instead of L40_shl. */ L40_var1 = (( Word40) (( UWord32) uvar2_l * ( UWord32) uvar1_l)) << 1; *L_varout_l = 0x0000ffff & L_Extract40( L40_var1); L40_var1 = L40_shr( L40_var1, 16); L40_var1 = L40_add( L40_var1, (( Word40) (( Word32) var2_h * ( Word32) uvar1_l)) << 1); L40_var1 = L40_add( L40_var1, (( Word40) (( Word32) var1_h * ( Word32) uvar2_l)) << 1); *L_varout_l |= (L_Extract40( L40_var1)) << 16; L40_var1 = L40_shr( L40_var1, 16); L40_var1 = L40_mac( L40_var1, var1_h, var2_h); *L_varout_h = L_Extract40( L40_var1); #if (WMOPS) multiCounter[currCounter].extract_l-=2; multiCounter[currCounter].extract_h-=2; multiCounter[currCounter].L_Extract40-=3; multiCounter[currCounter].L40_shr-=2; multiCounter[currCounter].L40_add-=2; multiCounter[currCounter].L40_mac--; #endif /* if WMOPS */ } #if (WMOPS) multiCounter[currCounter].Mpy_32_32_ss++; #endif /* if WMOPS */ return; }
Word32 L_divide(Word32 L_num, Word32 L_denom) { Word16 approx; Word32 L_div; if (L_num < 0 || L_denom < 0 || L_num > L_denom) { printf("ERROR: Invalid input into L_divide!\n"); return (0); } /* First approximation: 1 / L_denom = 1/extract_h(L_denom) */ approx = divide_s((Word16) 0x3fff, extract_h(L_denom)); /* 1/L_denom = approx * (2.0 - L_denom * approx) */ L_div = L_mpy_ls(L_denom, approx); L_div = L_sub((Word32) 0x7fffffffL, L_div); L_div = L_mpy_ls(L_div, approx); /* L_num * (1/L_denom) */ L_div = L_mpy_ll(L_num, L_div); L_div = L_shl(L_div, 2); return (L_div); }
void Log2( Word32 x, /* (i) input */ Word16 *int_comp, /* Q0 integer part */ Word16 *frac_comp /* Q15 fractional part */ ) { Word16 exp, idx_man, sub_man, sub_tab; Word32 a0; if(x <= 0){ *int_comp = 0; *frac_comp = 0; } else{ exp = norm_l(x); // normalization a0 = L_shl(x, exp); // Q30 mantissa, i.e. 1.xxx Q30 /* use table look-up of man in [1.0, 2.0[ Q30 */ a0 = L_shr(L_sub(a0, (Word32)0x40000000), 8); // Q16 index into table - note zero'ing of leading 1 idx_man = extract_h(a0); // Q0 index into table sub_man = extract_l(L_shr((a0 & 0xFFFF), 1)); // Q15 fractional sub_man a0 = L_deposit_h(tablog[idx_man]); // Q31 sub_tab = sub(tablog[idx_man+1], tablog[idx_man]); // Q15 a0 = L_mac(a0, sub_man, sub_tab); // Q31 *frac_comp = intround(a0); // Q15 *int_comp = sub(30, exp); // Q0 } return; }
/*---------------------------------------------------------------------------* * Function Gain_update * * ~~~~~~~~~~~~~~~~~~~~~~ * * update table of past quantized energies * *---------------------------------------------------------------------------*/ void Gain_update( Word16 past_qua_en[], /* (io) Q10 :Past quantized energies */ Word32 L_gbk12 /* (i) Q13 : gbk1[indice1][1]+gbk2[indice2][1] */ ) { Word16 i, tmp; Word16 exp, frac; Word32 L_acc; for(i=3; i>0; i--){ past_qua_en[i] = past_qua_en[i-1]; /* Q10 */ } /*----------------------------------------------------------------------* * -- past_qua_en[0] = 20*log10(gbk1[index1][1]+gbk2[index2][1]); -- * * 2 * 10 log10( gbk1[index1][1]+gbk2[index2][1] ) * * = 2 * 3.0103 log2( gbk1[index1][1]+gbk2[index2][1] ) * * = 2 * 3.0103 log2( gbk1[index1][1]+gbk2[index2][1] ) * * 24660:Q12(6.0205) * *----------------------------------------------------------------------*/ Log2( L_gbk12, &exp, &frac ); /* L_gbk12:Q13 */ L_acc = L_Comp( sub(exp,13), frac); /* L_acc:Q16 */ tmp = extract_h( L_shl( L_acc,13 ) ); /* tmp:Q13 */ past_qua_en[0] = mult( tmp, 24660 ); /* past_qua_en[]:Q10 */ }
Word32 Inv_sqrt( /* (o) Q30 : output value (range: 0<=val<1) */ Word32 L_x /* (i) Q0 : input value (range: 0<=val<=7fffffff) */ ) { Word16 exp, i, a, tmp; Word32 L_y; if( L_x <= (Word32)0) return ( (Word32)0x3fffffffL); exp = norm_l(L_x); L_x = L_shl(L_x, exp ); /* L_x is normalize */ exp = sub(30, exp); if( (exp & 1) == 0 ) /* If exponent even -> shift right */ L_x = L_shr(L_x, 1); exp = shr(exp, 1); exp = add(exp, 1); L_x = L_shr(L_x, 9); i = extract_h(L_x); /* Extract b25-b31 */ L_x = L_shr(L_x, 1); a = extract_l(L_x); /* Extract b10-b24 */ a = a & (Word16)0x7fff; i = sub(i, 16); L_y = L_deposit_h(tabsqr[i]); /* tabsqr[i] << 16 */ tmp = sub(tabsqr[i], tabsqr[i+1]); /* tabsqr[i] - tabsqr[i+1]) */ L_y = L_msu(L_y, tmp, a); /* L_y -= tmp*a*2 */ L_y = L_shr(L_y, exp); /* denormalization */ return(L_y); }
static void Cor_h( Word16 *H, /* (i) Q12 :Impulse response of filters */ Word16 *rr /* (o) :Correlations of H[] */ ) { Word16 *rri0i0, *rri1i1, *rri2i2, *rri3i3, *rri4i4; Word16 *rri0i1, *rri0i2, *rri0i3, *rri0i4; Word16 *rri1i2, *rri1i3, *rri1i4; Word16 *rri2i3, *rri2i4; Word16 *p0, *p1, *p2, *p3, *p4; Word16 *ptr_hd, *ptr_hf, *ptr_h1, *ptr_h2; Word32 cor; Word16 i, k, ldec, l_fin_sup, l_fin_inf; Word16 h[L_SUBFR]; /* Scaling h[] for maximum precision */ cor = 0; for(i=0; i<L_SUBFR; i++) cor += H[i] * H[i]; cor <<= 1; if(extract_h(cor) > 32000) { for(i=0; i<L_SUBFR; i++) h[i] >>= 1; } else {
void Scale_sig( Word16 x[], /* (i/o) : signal to scale */ Word16 lg, /* (i) : size of x[] */ Word16 exp /* (i) : exponent: x = round(x << exp) */ ) { Word32 i; Word32 L_tmp; if(exp > 0) { for (i = lg - 1 ; i >= 0; i--) { L_tmp = L_shl2(x[i], 16 + exp); x[i] = extract_h(L_add(L_tmp, 0x8000)); } } else { exp = -exp; for (i = lg - 1; i >= 0; i--) { L_tmp = x[i] << 16; L_tmp >>= exp; x[i] = (L_tmp + 0x8000)>>16; } } return; }
void Lsp_get_tdist( Word16 wegt[], /* (i) norm: weight coef. */ Word16 buf[], /* (i) Q13 : candidate LSP vector */ Word32 *L_tdist, /* (o) Q27 : distortion */ Word16 rbuf[], /* (i) Q13 : target vector */ Word16 fg_sum[] /* (i) Q15 : present MA prediction coef. */ ) { Word16 j; Word16 tmp, tmp2; /* Q13 */ Word32 L_acc; /* Q25 */ *L_tdist = 0; for ( j = 0 ; j < M ; j++ ) { /* tmp = (buf - rbuf)*fg_sum */ tmp = sub( buf[j], rbuf[j] ); tmp = mult( tmp, fg_sum[j] ); /* *L_tdist += wegt * tmp * tmp */ L_acc = L_mult( wegt[j], tmp ); tmp2 = extract_h( L_shl( L_acc, 4 ) ); *L_tdist = L_mac( *L_tdist, tmp2, tmp ); } return; }
void Gp_clip_test_isf( Word16 isf[], /* (i) : isf values (in frequency domain) */ Word16 mem[] /* (i/o) : memory of gain of pitch clipping algorithm */ ) { Word16 dist, dist_min; Word32 i; dist_min = vo_sub(isf[1], isf[0]); for (i = 2; i < M - 1; i++) { dist = vo_sub(isf[i], isf[i - 1]); if(dist < dist_min) { dist_min = dist; } } dist = extract_h(L_mac(vo_L_mult(26214, mem[0]), 6554, dist_min)); if (dist > DIST_ISF_MAX) { dist = DIST_ISF_MAX; } mem[0] = dist; return; }
int32_t WebRtcG729fix_Inv_sqrt( /* (o) Q30 : output value (range: 0<=val<1) */ int32_t L_x /* (i) Q0 : input value (range: 0<=val<=7fffffff) */ ) { int16_t exp, i, a, tmp; int32_t L_y; if( L_x <= (int32_t)0) return ( (int32_t)0x3fffffffL); exp = WebRtcSpl_NormW32(L_x); L_x = L_shl(L_x, exp ); /* L_x is normalize */ exp = WebRtcSpl_SubSatW16(30, exp); if( (exp & 1) == 0 ) /* If exponent even -> shift right */ L_x = L_shr(L_x, 1); exp = shr(exp, 1); exp = WebRtcSpl_AddSatW16(exp, 1); L_x = L_shr(L_x, 9); i = extract_h(L_x); /* Extract b25-b31 */ L_x = L_shr(L_x, 1); a = extract_l(L_x); /* Extract b10-b24 */ a = a & (int16_t)0x7fff; i = WebRtcSpl_SubSatW16(i, 16); L_y = L_deposit_h(WebRtcG729fix_tabsqr[i]); /* tabsqr[i] << 16 */ tmp = WebRtcSpl_SubSatW16(WebRtcG729fix_tabsqr[i], WebRtcG729fix_tabsqr[i+1]); /* tabsqr[i] - tabsqr[i+1]) */ L_y = L_msu(L_y, tmp, a); /* L_y -= tmp*a*2 */ L_y = L_shr(L_y, exp); /* denormalization */ return(L_y); }
/*---------------------------------------------------------------------------- ; FUNCTION CODE ----------------------------------------------------------------------------*/ void d_gain_code( gc_predState *pred_state, /* i/o : MA predictor state */ enum Mode mode, /* i : AMR mode (MR795 or MR122) */ Word16 index, /* i : received quantization index */ Word16 code[], /* i : innovation codevector */ Word16 *gain_code, /* o : decoded innovation gain */ Flag *pOverflow ) { Word16 gcode0, exp, frac; const Word16 *p; Word16 qua_ener_MR122, qua_ener; Word16 exp_inn_en; Word16 frac_inn_en; Word32 L_tmp; Word16 tbl_tmp; Word16 temp; /*-------------- Decode codebook gain ---------------*/ /*-------------------------------------------------------------------* * predict codebook gain * * ~~~~~~~~~~~~~~~~~~~~~ * * gc0 = Pow2(int(d)+frac(d)) * * = 2^exp + 2^frac * * * *-------------------------------------------------------------------*/ gc_pred(pred_state, mode, code, &exp, &frac, &exp_inn_en, &frac_inn_en, pOverflow); tbl_tmp = add(add(index, index, pOverflow), index, pOverflow); p = &qua_gain_code[tbl_tmp]; /* Different scalings between MR122 and the other modes */ temp = sub((Word16)mode, (Word16)MR122, pOverflow); if (temp == 0) { gcode0 = (Word16)(Pow2(exp, frac, pOverflow)); /* predicted gain */ gcode0 = shl(gcode0, 4, pOverflow); *gain_code = shl(mult(gcode0, *p++, pOverflow), 1, pOverflow); } else { gcode0 = (Word16)(Pow2(14, frac, pOverflow)); L_tmp = L_mult(*p++, gcode0, pOverflow); L_tmp = L_shr(L_tmp, sub(9, exp, pOverflow), pOverflow); *gain_code = extract_h(L_tmp); /* Q1 */ } /*-------------------------------------------------------------------* * update table of past quantized energies * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * *-------------------------------------------------------------------*/ qua_ener_MR122 = *p++; qua_ener = *p++; gc_pred_update(pred_state, qua_ener_MR122, qua_ener); return; }
void energy_computation ( Word16 r_h[], Word16 scal_acf, Word16 rvad[], Word16 scal_rvad, Pfloat * acf0, Pfloat * pvad ) { Word16 i, temp, norm_prod; Word32 L_temp; /* r[0] is always greater than zero (no need to test for r[0] == 0) */ /* Computation of acf0 (exponent and mantissa) */ acf0->e = sub (32, scal_acf); acf0->m = r_h[0] & 0x7ff8; /* Computation of pvad (exponent and mantissa) */ pvad->e = add (acf0->e, 14); pvad->e = sub (pvad->e, scal_rvad); L_temp = 0L; for (i = 1; i <= 8; i++) { temp = shr (r_h[i], 3); L_temp = L_mac (L_temp, temp, rvad[i]); } temp = shr (r_h[0], 3); L_temp = L_add (L_temp, L_shr (L_mult (temp, rvad[0]), 1)); if (L_temp <= 0L) { L_temp = 1L; } norm_prod = norm_l (L_temp); pvad->e = sub (pvad->e, norm_prod); if(norm_prod<=0) pvad->m = extract_h (L_shr (L_temp, -norm_prod)); else pvad->m = extract_h (L_shl (L_temp, norm_prod)); return; }
/***************************************************************************** * * function name: count5_6_7_8_9_10_11 * description: counts tables 5-11 * returns: * input: quantized spectrum * output: bitCount for tables 5-11 * *****************************************************************************/ static void count5_6_7_8_9_10_11(const Word16 *values, const Word16 width, Word16 *bitCount) { Word32 t0,t1,i; Word32 bc5_6,bc7_8,bc9_10; Word16 bc11,sc; bc5_6=0; bc7_8=0; bc9_10=0; bc11=0; sc=0; for(i=0;i<width;i+=2){ t0 = values[i+0]; t1 = values[i+1]; bc5_6 = bc5_6 + EXPAND(huff_ltab5_6[t0+4][t1+4]); t0=ABS(t0); t1=ABS(t1); bc7_8 = bc7_8 + EXPAND(huff_ltab7_8[t0][t1]); bc9_10 = bc9_10 + EXPAND(huff_ltab9_10[t0][t1]); bc11 = bc11 + huff_ltab11[t0][t1]; sc = sc + (t0>0) + (t1>0); } bitCount[1]=INVALID_BITCOUNT; bitCount[2]=INVALID_BITCOUNT; bitCount[3]=INVALID_BITCOUNT; bitCount[4]=INVALID_BITCOUNT; bitCount[5]=extract_h(bc5_6); bitCount[6]=extract_l(bc5_6); bitCount[7]=extract_h(bc7_8) + sc; bitCount[8]=extract_l(bc7_8) + sc; bitCount[9]=extract_h(bc9_10) + sc; bitCount[10]=extract_l(bc9_10) + sc; bitCount[11]=bc11 + sc; }
Word16 voice_factor( /* (o) Q15 : factor (-1=unvoiced to 1=voiced) */ Word16 exc[], /* (i) Q_exc : pitch excitation */ Word16 Q_exc, /* (i) : exc format */ Word16 gain_pit, /* (i) Q14 : gain of pitch */ Word16 code[], /* (i) Q9 : Fixed codebook excitation */ Word16 gain_code, /* (i) Q0 : gain of code */ Word16 L_subfr /* (i) : subframe length */ ) { Word16 tmp, exp, ener1, exp1, ener2, exp2; Word32 i, L_tmp; #ifdef ASM_OPT /* asm optimization branch */ ener1 = extract_h(Dot_product12_asm(exc, exc, L_subfr, &exp1)); #else ener1 = extract_h(Dot_product12(exc, exc, L_subfr, &exp1)); #endif exp1 = exp1 - (Q_exc + Q_exc); L_tmp = vo_L_mult(gain_pit, gain_pit); exp = norm_l(L_tmp); tmp = extract_h(L_tmp << exp); ener1 = vo_mult(ener1, tmp); exp1 = exp1 - exp - 10; /* 10 -> gain_pit Q14 to Q9 */ #ifdef ASM_OPT /* asm optimization branch */ ener2 = extract_h(Dot_product12_asm(code, code, L_subfr, &exp2)); #else ener2 = extract_h(Dot_product12(code, code, L_subfr, &exp2)); #endif exp = norm_s(gain_code); tmp = gain_code << exp; tmp = vo_mult(tmp, tmp); ener2 = vo_mult(ener2, tmp); exp2 = exp2 - (exp + exp); i = exp1 - exp2; if (i >= 0) { ener1 = ener1 >> 1; ener2 = ener2 >> (i + 1); } else
short ran0(short *seed0) { long Ltemp; Ltemp = 0.0; Ltemp = L_mac(27698, 25173, *seed0); Ltemp = L_shr(Ltemp, 1); Ltemp = Ltemp & 0x0000ffffL; *seed0 = extract_l(Ltemp); return (extract_h(L_shl(Ltemp,15))); }
void step_up ( Word16 np, Word16 vpar[], Word16 aav1[] ) { Word32 L_coef[9], L_work[9]; Word16 temp; Word16 i, m; /*** Initialization of the step-up recursion ***/ L_coef[0] = 0x20000000L; L_coef[1] = L_shl (L_deposit_l (vpar[0]), 14); /*** Loop on the LPC analysis order: ***/ for (m = 2; m <= np; m++) { for (i = 1; i < m; i++) { temp = extract_h (L_coef[m - i]); L_work[i] = L_mac (L_coef[i], vpar[m - 1], temp); } for (i = 1; i < m; i++) { L_coef[i] = L_work[i]; } L_coef[m] = L_shl (L_deposit_l (vpar[m - 1]), 14); } /*** Keep the aav1[0..np] in 15 bits ***/ for (i = 0; i <= np; i++) { aav1[i] = extract_h (L_shr (L_coef[i], 3)); } return; }
/*---------------------------------------------------------------------------- * calc_rc0_h - computes 1st parcor from composed filter impulse response *---------------------------------------------------------------------------- */ static void calc_rc0_he( Word16 *h, /* input : impulse response of composed filter */ Word16 *rc0, /* output: 1st parcor */ Word16 long_h_st /*input : impulse response length */ ) { Word16 acf0, acf1; Word32 L_acc; Word16 temp, sh_acf; Word16 *ptrs; Word16 i; /* computation of the autocorrelation function acf */ L_acc = 0L; for(i=0; i<long_h_st; i++) L_acc = L_mac(L_acc, h[i], h[i]); sh_acf = norm_l(L_acc); L_acc = L_shl(L_acc, sh_acf); acf0 = extract_h(L_acc); L_acc = 0L; ptrs = h; for(i=0; i<long_h_st-1; i++){ temp = *ptrs++; L_acc = L_mac(L_acc, temp, *ptrs); } L_acc = L_shl(L_acc, sh_acf); acf1 = extract_h(L_acc); /* Compute 1st parcor */ /**********************/ if( sub(acf0, abs_s(acf1))<0) { *rc0 = 0; return; } *rc0 = div_s(abs_s(acf1), acf0); if(acf1 > 0) { *rc0 = negate(*rc0); } return; }
/* ** ** Function: Dec_Cng() ** ** Description: Receives Ftyp ** 0 : for untransmitted frames ** 2 : for SID frames ** Decodes SID frames ** Computes current frame excitation ** Computes current frame LSPs ** ** Links to text: ** ** Arguments: ** ** Word16 Ftyp Type of silence frame ** LINEDEF *Line Coded parameters ** Word16 *DataExc Current frame excitation ** Word16 *QntLpc Interpolated frame LPC coefficients ** ** Outputs: ** ** Word16 *DataExc ** Word16 *QntLpc ** ** Return value: None ** */ void Dec_Cng(Word16 Ftyp, LINEDEF *Line, Word16 *DataExc, Word16 *QntLpc) { Word16 temp; int i; if(Ftyp == 2) { /* * SID Frame decoding */ DecCng->SidGain = Dec_SidGain(Line->Sfs[0].Mamp); /* Inverse quantization of the LSP */ Lsp_Inq( DecCng->LspSid, DecStat->PrevLsp, Line->LspId, 0) ; } else { /* * non SID Frame */ if(DecCng->PastFtyp == 1) { /* * Case of 1st SID frame erased : quantize-decode * energy estimate stored in DecCng->SidGain * scaling factor in DecCng->CurGain */ temp = Qua_SidGain(&DecCng->SidGain, &DecCng->CurGain, 0); DecCng->SidGain = Dec_SidGain(temp); } } if(DecCng->PastFtyp == 1) { DecCng->CurGain = DecCng->SidGain; } else { DecCng->CurGain = extract_h(L_add( L_mult(DecCng->CurGain,0x7000), L_mult(DecCng->SidGain,0x1000) ) ) ; } Calc_Exc_Rand(DecCng->CurGain, DecStat->PrevExc, DataExc, &DecCng->RandSeed, Line); /* Interpolate the Lsp vectors */ Lsp_Int( QntLpc, DecCng->LspSid, DecStat->PrevLsp ) ; /* Copy the LSP vector for the next frame */ for ( i = 0 ; i < LpcOrder ; i ++ ) DecStat->PrevLsp[i] = DecCng->LspSid[i] ; return; }
void compute_rav1 ( Word16 aav1[], Word16 rav1[], Word16 *scal_rav1 ) { Word32 L_work[9]; Word16 i, k; /*** Computation of the rav1[0..8] ***/ for (i = 0; i <= 8; i++) { L_work[i] = 0L; for (k = 0; k <= 8 - i; k++) { L_work[i] = L_mac (L_work[i], aav1[k], aav1[k + i]); } } if (L_work[0] == 0L) { *scal_rav1 = 0; } else { *scal_rav1 = norm_l (L_work[0]); } for (i = 0; i <= 8; i++) { if((*scal_rav1)<=0) rav1[i] = extract_h (L_shr (L_work[i], -(*scal_rav1))); else rav1[i] = extract_h (L_shl (L_work[i], *scal_rav1)); } return; }
Word32 fnLog2(Word32 L_Input) { static Word16 swC0 = -0x2b2a, swC1 = 0x7fc5, swC2 = -0x54d0; Word16 siShiftCnt, swInSqrd, swIn; Word32 LwIn; /*_________________________________________________________________________ | | | Executable Code | |_________________________________________________________________________| */ /* normalize input and store shifts required */ /* ----------------------------------------- */ siShiftCnt = norm_l(L_Input); LwIn = L_shl(L_Input, siShiftCnt); siShiftCnt = add(siShiftCnt, 1); siShiftCnt = negate(siShiftCnt); /* calculate x*x*c0 */ /* ---------------- */ swIn = extract_h(LwIn); swInSqrd = mult_r(swIn, swIn); LwIn = L_mult(swInSqrd, swC0); /* add x*c1 */ /* --------- */ LwIn = L_mac(LwIn, swIn, swC1); /* add c2 */ /* ------ */ LwIn = L_add(LwIn, L_deposit_h(swC2)); /* apply *(4/32) */ /* ------------- */ LwIn = L_shr(LwIn, 3); LwIn = LwIn & 0x03ffffff; siShiftCnt = shl(siShiftCnt, 10); LwIn = L_add(LwIn, L_deposit_h(siShiftCnt)); /* return log2 */ /* ----------- */ return (LwIn); }
//========================================================================== //函数功能:初始化滤波器50高通 //函数参数:“signal[]”表示输入输出信号,既是输入参数又是输出参数;“lg”表 // 示信号长度,作为输入参数;“mem[]”滤波器内存,作为输入参数 //========================================================================== void HP50_12k8( Word16 signal[], /* input/output signal */ Word16 lg, /* lenght of signal */ Word16 mem[] /* filter memory [6] */ ) { Word16 x2; Word16 y2_hi, y2_lo, y1_hi, y1_lo, x0, x1; Word32 L_tmp; Word32 num; y2_hi = *mem++; y2_lo = *mem++; y1_hi = *mem++; y1_lo = *mem++; x0 = *mem++; x1 = *mem; num = (Word32)lg; do { x2 = x1; x1 = x0; x0 = *signal; /* y[i] = b[0]*x[i] + b[1]*x[i-1] + b140[2]*x[i-2] */ /* + a[1]*y[i-1] + a[2] * y[i-2]; */ //以最大限度地提高精度舍入 L_tmp = 8192 ; /* rounding to maximise precision */ L_tmp += y1_lo * a[1]; L_tmp += y2_lo * a[2]; L_tmp = L_tmp >> 14; L_tmp += (y1_hi * a[1] + y2_hi * a[2] + (x0 + x2) * b[0] + x1 * b[1]) << 1; //多项式系数 L_tmp <<= 2; /* coeff Q12 --> Q13 */ y2_hi = y1_hi; y2_lo = y1_lo; y1_hi = (Word16)(L_tmp>>16); y1_lo = (Word16)((L_tmp & 0xffff)>>1); *signal++ = extract_h((L_add((L_tmp<<1), 0x8000))); }while(--num !=0); *mem-- = x1; *mem-- = x0; *mem-- = y1_lo; *mem-- = y1_hi; *mem-- = y2_lo; *mem-- = y2_hi; return; }
/* ******************************************************************************** * PRIVATE PROGRAM CODE ******************************************************************************** */ void MR475_quant_store_results( gc_predState *pred_st, /* i/o: gain predictor state struct */ const Word16 *p, /* i : pointer to selected quantizer table entry */ Word16 gcode0, /* i : predicted CB gain, Q(14 - exp_gcode0) */ Word16 exp_gcode0, /* i : exponent of predicted CB gain, Q0 */ Word16 *gain_pit, /* o : Pitch gain, Q14 */ Word16 *gain_cod /* o : Code gain, Q1 */ ) { Word16 g_code, exp, frac, tmp; Word32 L_tmp; Word16 qua_ener_MR122; /* o : quantized energy error, MR122 version Q10 */ Word16 qua_ener; /* o : quantized energy error, Q10 */ /* Read the quantized gains */ *gain_pit = *p++; g_code = *p++; /*------------------------------------------------------------------* * calculate final fixed codebook gain: * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * * * gc = gc0 * g * *------------------------------------------------------------------*/ L_tmp = L_mult(g_code, gcode0); L_tmp = L_shr(L_tmp, sub(10, exp_gcode0)); *gain_cod = extract_h(L_tmp); /*------------------------------------------------------------------* * calculate predictor update values and update gain predictor: * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * * * qua_ener = log2(g) * * qua_ener_MR122 = 20*log10(g) * *------------------------------------------------------------------*/ Log2 (L_deposit_l (g_code), &exp, &frac); /* Log2(x Q12) = log2(x) + 12 */ exp = sub(exp, 12); tmp = shr_r (frac, 5); qua_ener_MR122 = add (tmp, shl (exp, 10)); L_tmp = Mpy_32_16(exp, frac, 24660); /* 24660 Q12 ~= 6.0206 = 20*log10(2) */ qua_ener = round (L_shl (L_tmp, 13)); /* Q12 * Q0 = Q13 -> Q10 */ gc_pred_update(pred_st, qua_ener_MR122, qua_ener); }
void Log2( Word32 L_x, /* (i) Q0 : input value */ Word16 *exponent, /* (o) Q0 : Integer part of Log2. (range: 0<=val<=30) */ Word16 *fraction /* (o) Q15: Fractional part of Log2. (range: 0<=val<1) */ ) { Word16 exp, i, a, tmp; Word32 L_y; if( L_x <= (Word32)0 ) { *exponent = 0; *fraction = 0; return; } exp = norm_l(L_x); L_x = L_shl(L_x, exp ); /* L_x is normalized */ *exponent = sub(30, exp); L_x = L_shr(L_x, 9); i = extract_h(L_x); /* Extract b25-b31 */ L_x = L_shr(L_x, 1); a = extract_l(L_x); /* Extract b10-b24 of fraction */ a = a & (Word16)0x7fff; i = sub(i, 32); L_y = L_deposit_h(tablog[i]); /* tablog[i] << 16 */ tmp = sub(tablog[i], tablog[i+1]); /* tablog[i] - tablog[i+1] */ L_y = L_msu(L_y, tmp, a); /* L_y -= tmp*a*2 */ *fraction = extract_h( L_y); return; }
//============================================================================ //函数功能:找到语音因子 //函数参数:"exc[]"表示因子,作为输入参数;"Q_exc"表示激励,表示输入参数;"gain_pit" // 表示增益音高,作为输入参数;"code[]"表示固定码本激励,作为输入参数; // "gain_code"表示编码增益,作为输入参数;"L_subfr"表示子帧长度 //============================================================================ int16 voice_factor( /* (o) Q15 : factor (-1=unvoiced to 1=voiced) */ int16 exc[], /* (i) Q_exc : pitch excitation */ int16 Q_exc, /* (i) : exc format */ int16 gain_pit, /* (i) Q14 : gain of pitch */ int16 code[], /* (i) Q9 : Fixed codebook excitation */ int16 gain_code, /* (i) Q0 : gain of code */ int16 L_subfr /* (i) : subframe length */ ) { int16 i, tmp, exp, ener1, exp1, ener2, exp2; int32 L_tmp; ener1 = extract_h(Dot_product12(exc, exc, L_subfr, &exp1)); exp1 = sub_int16(exp1, Q_exc << 1); L_tmp = mul_16by16_to_int32(gain_pit, gain_pit); exp = normalize_amr_wb(L_tmp); tmp = (int16)((L_tmp << exp) >> 16); ener1 = mult_int16(ener1, tmp); exp1 -= (exp + 10); /* 10 -> gain_pit Q14 to Q9 */ ener2 = extract_h(Dot_product12(code, code, L_subfr, &exp2)); exp = norm_s(gain_code); tmp = shl_int16(gain_code, exp); tmp = mult_int16(tmp, tmp); ener2 = mult_int16(ener2, tmp); exp2 -= (exp << 1); i = exp1 - exp2; if (i >= 0) { ener1 >>= 1; ener2 >>= (i + 1); }
/*---------------------------------------------------------------------------* * Function Init_lsfq_noise * * ~~~~~~~~~~~~~~~~~~~~~~~~~ * * * * -> Initialization of variables for the lsf quantization in the SID * * * *---------------------------------------------------------------------------*/ void Init_lsfq_noise(void) { Word16 i, j; Word32 acc0; /* initialize the noise_fg */ for (i=0; i<4; i++) Copy(fg[0][i], noise_fg[0][i], M); for (i=0; i<4; i++) for (j=0; j<M; j++){ acc0 = L_mult(fg[0][i][j], 19660); acc0 = L_mac(acc0, fg[1][i][j], 13107); noise_fg[1][i][j] = extract_h(acc0); } }
void Gp_clip_test_gain_pit( Word16 gain_pit, /* (i) Q14 : gain of quantized pitch */ Word16 mem[] /* (i/o) : memory of gain of pitch clipping algorithm */ ) { Word16 gain; Word32 L_tmp; L_tmp = (29491 * mem[1])<<1; L_tmp += (3277 * gain_pit)<<1; gain = extract_h(L_tmp); if(gain < GAIN_PIT_MIN) { gain = GAIN_PIT_MIN; } mem[1] = gain; return; }