/* ITU-T G.729A Speech Coder ANSI-C Source Code Version 1.1 Last modified: September 1996 Copyright (c) 1996, AT&T, France Telecom, NTT, Universite de Sherbrooke All rights reserved. */ #include "typedef.h" #include "basic_op.h" #include "oper_32b.h" #include "ld8a.h" #include "tab_ld8a.h" #include "taming.h" void Gbk_presel (Word16 best_gain[], /* (i) [0] Q9 : unquantized pitch gain */ /* (i) [1] Q2 : unquantized code gain */ Word16 * cand1, /* (o) : index of best 1st stage vector */ Word16 * cand2, /* (o) : index of best 2nd stage vector */ Word16 gcode0 /* (i) Q4 : presearch for gain codebook */ ); /*---------------------------------------------------------------------------* * Function Qua_gain * * ~~~~~~~~~~~~~~~~~~ * * Inputs: * * code[] :Innovative codebook. * * g_coeff[] :Correlations compute for pitch. * * L_subfr :Subframe length. * * * * Outputs: * * gain_pit :Quantized pitch gain. * * gain_cod :Quantized code gain. * * * * Return: * * Index of quantization. * * * *--------------------------------------------------------------------------*/ Word16 Qua_gain (CodState *coder, Word16 code[], /* (i) Q13 :Innovative vector. */ Word16 g_coeff[], /* (i) :Correlations -2 */ /* , -2, 2 */ Word16 exp_coeff[], /* (i) :Q-Format g_coeff[] */ Word16 L_subfr, /* (i) :Subframe length. */ Word16 * gain_pit, /* (o) Q14 :Pitch gain. */ Word16 * gain_cod, /* (o) Q1 :Code gain. */ Word16 tameflag /* (i) : set to 1 if taming is needed */ ) { Word16 i, j, index1, index2; Word16 cand1, cand2; Word16 exp, gcode0, exp_gcode0, gcode0_org, e_min; Word16 nume, denom, inv_denom; Word16 exp1, exp2, exp_nume, exp_denom, exp_inv_denom, sft, tmp; Word16 g_pitch, g2_pitch, g_code, g2_code, g_pit_cod; Word16 coeff[5], coeff_lsf[5]; Word16 exp_min[5]; Word32 L_gbk12; Word32 L_tmp, L_dist_min, L_temp, L_tmp1, L_tmp2, L_acc, L_accb; Word16 best_gain[2]; /* Gain predictor, Past quantized energies = -14.0 in Q10 */ /*---------------------------------------------------* *- energy due to innovation -* *- predicted energy -* *- predicted codebook gain => gcode0[exp_gcode0] -* *---------------------------------------------------*/ Gain_predict (coder->past_qua_en, code, L_subfr, &gcode0, &exp_gcode0); /*-----------------------------------------------------------------* * pre-selection * *-----------------------------------------------------------------*/ /*-----------------------------------------------------------------* * calculate best gain * * * * tmp = -1./(4.*coeff[0]*coeff[2]-coeff[4]*coeff[4]) ; * * best_gain[0] = (2.*coeff[2]*coeff[1]-coeff[3]*coeff[4])*tmp ; * * best_gain[1] = (2.*coeff[0]*coeff[3]-coeff[1]*coeff[4])*tmp ; * * gbk_presel(best_gain,&cand1,&cand2,gcode0) ; * * * *-----------------------------------------------------------------*/ /*-----------------------------------------------------------------* * tmp = -1./(4.*coeff[0]*coeff[2]-coeff[4]*coeff[4]) ; * *-----------------------------------------------------------------*/ L_tmp1 = L_mult (g_coeff[0], g_coeff[2]); exp1 = add (add (exp_coeff[0], exp_coeff[2]), 1 - 2); L_tmp2 = L_mult (g_coeff[4], g_coeff[4]); exp2 = add (add (exp_coeff[4], exp_coeff[4]), 1); if (sub (exp1, exp2) > 0) { L_tmp = L_sub (L_shr (L_tmp1, sub (exp1, exp2)), L_tmp2); exp = exp2; } else { L_tmp = L_sub (L_tmp1, L_shr (L_tmp2, sub (exp2, exp1))); exp = exp1; } sft = norm_l (L_tmp); denom = extract_h (L_shl (L_tmp, sft)); exp_denom = sub (add (exp, sft), 16); inv_denom = div_s (16384, denom); inv_denom = negate (inv_denom); exp_inv_denom = sub (14 + 15, exp_denom); /*-----------------------------------------------------------------* * best_gain[0] = (2.*coeff[2]*coeff[1]-coeff[3]*coeff[4])*tmp ; * *-----------------------------------------------------------------*/ L_tmp1 = L_mult (g_coeff[2], g_coeff[1]); exp1 = add (exp_coeff[2], exp_coeff[1]); L_tmp2 = L_mult (g_coeff[3], g_coeff[4]); exp2 = add (add (exp_coeff[3], exp_coeff[4]), 1); if (sub (exp1, exp2) > 0) { L_tmp = L_sub (L_shr (L_tmp1, add (sub (exp1, exp2), 1)), L_shr (L_tmp2, 1)); exp = sub (exp2, 1); } else { L_tmp = L_sub (L_shr (L_tmp1, 1), L_shr (L_tmp2, add (sub (exp2, exp1), 1))); exp = sub (exp1, 1); } sft = norm_l (L_tmp); nume = extract_h (L_shl (L_tmp, sft)); exp_nume = sub (add (exp, sft), 16); sft = sub (add (exp_nume, exp_inv_denom), (9 + 16 - 1)); L_acc = L_shr (L_mult (nume, inv_denom), sft); best_gain[0] = extract_h (L_acc); /*-- best_gain[0]:Q9 --*/ if (tameflag == 1) { if (sub (best_gain[0], GPCLIP2) > 0) best_gain[0] = GPCLIP2; } /*-----------------------------------------------------------------* * best_gain[1] = (2.*coeff[0]*coeff[3]-coeff[1]*coeff[4])*tmp ; * *-----------------------------------------------------------------*/ L_tmp1 = L_mult (g_coeff[0], g_coeff[3]); exp1 = add (exp_coeff[0], exp_coeff[3]); L_tmp2 = L_mult (g_coeff[1], g_coeff[4]); exp2 = add (add (exp_coeff[1], exp_coeff[4]), 1); if (sub (exp1, exp2) > 0) { L_tmp = L_sub (L_shr (L_tmp1, add (sub (exp1, exp2), 1)), L_shr (L_tmp2, 1)); exp = sub (exp2, 1); } else { L_tmp = L_sub (L_shr (L_tmp1, 1), L_shr (L_tmp2, add (sub (exp2, exp1), 1))); exp = sub (exp1, 1); } sft = norm_l (L_tmp); nume = extract_h (L_shl (L_tmp, sft)); exp_nume = sub (add (exp, sft), 16); sft = sub (add (exp_nume, exp_inv_denom), (2 + 16 - 1)); L_acc = L_shr (L_mult (nume, inv_denom), sft); best_gain[1] = extract_h (L_acc); /*-- best_gain[1]:Q2 --*/ /*--- Change Q-format of gcode0 ( Q[exp_gcode0] -> Q4 ) ---*/ if (sub (exp_gcode0, 4) >= 0) { gcode0_org = shr (gcode0, sub (exp_gcode0, 4)); } else { L_acc = L_deposit_l (gcode0); L_acc = L_shl (L_acc, sub ((4 + 16), exp_gcode0)); gcode0_org = extract_h (L_acc); /*-- gcode0_org:Q4 --*/ } /*----------------------------------------------* * - presearch for gain codebook - * *----------------------------------------------*/ Gbk_presel (best_gain, &cand1, &cand2, gcode0_org); /*---------------------------------------------------------------------------* * * * Find the best quantizer. * * * * dist_min = MAX_32; * * for ( i=0 ; ipast_qua_en, L_gbk12); return (add (map1[index1] * (Word16) NCODE2, map2[index2])); } /*---------------------------------------------------------------------------* * Function Gbk_presel * * ~~~~~~~~~~~~~~~~~~~ * * - presearch for gain codebook - * *---------------------------------------------------------------------------*/ void Gbk_presel (Word16 best_gain[], /* (i) [0] Q9 : unquantized pitch gain */ /* (i) [1] Q2 : unquantized code gain */ Word16 * cand1, /* (o) : index of best 1st stage vector */ Word16 * cand2, /* (o) : index of best 2nd stage vector */ Word16 gcode0 /* (i) Q4 : presearch for gain codebook */ ) { Word16 acc_h; Word16 sft_x, sft_y; Word32 L_acc, L_preg, L_cfbg, L_tmp, L_tmp_x, L_tmp_y; Word32 L_temp; /*--------------------------------------------------------------------------* x = (best_gain[1]-(coef[0][0]*best_gain[0]+coef[1][1])*gcode0) * inv_coef; *--------------------------------------------------------------------------*/ L_cfbg = L_mult (coef[0][0], best_gain[0]); /* L_cfbg:Q20 -> !!y */ L_acc = L_shr (L_coef[1][1], 15); /* L_acc:Q20 */ L_acc = L_add (L_cfbg, L_acc); acc_h = extract_h (L_acc); /* acc_h:Q4 */ L_preg = L_mult (acc_h, gcode0); /* L_preg:Q9 */ L_acc = L_shl (L_deposit_l (best_gain[1]), 7); /* L_acc:Q9 */ L_acc = L_sub (L_acc, L_preg); acc_h = extract_h (L_shl (L_acc, 2)); /* L_acc_h:Q[-5] */ L_tmp_x = L_mult (acc_h, INV_COEF); /* L_tmp_x:Q15 */ /*--------------------------------------------------------------------------* y = (coef[1][0]*(-coef[0][1]+best_gain[0]*coef[0][0])*gcode0 -coef[0][0]*best_gain[1]) * inv_coef; *--------------------------------------------------------------------------*/ L_acc = L_shr (L_coef[0][1], 10); /* L_acc:Q20 */ L_acc = L_sub (L_cfbg, L_acc); /* !!x -> L_cfbg:Q20 */ acc_h = extract_h (L_acc); /* acc_h:Q4 */ acc_h = mult (acc_h, gcode0); /* acc_h:Q[-7] */ L_tmp = L_mult (acc_h, coef[1][0]); /* L_tmp:Q10 */ L_preg = L_mult (coef[0][0], best_gain[1]); /* L_preg:Q13 */ L_acc = L_sub (L_tmp, L_shr (L_preg, 3)); /* L_acc:Q10 */ acc_h = extract_h (L_shl (L_acc, 2)); /* acc_h:Q[-4] */ L_tmp_y = L_mult (acc_h, INV_COEF); /* L_tmp_y:Q16 */ sft_y = (14 + 4 + 1) - 16; /* (Q[thr1]+Q[gcode0]+1)-Q[L_tmp_y] */ sft_x = (15 + 4 + 1) - 15; /* (Q[thr2]+Q[gcode0]+1)-Q[L_tmp_x] */ if (gcode0 > 0) { /*-- pre select codebook #1 --*/ *cand1 = 0; do { L_temp = L_sub (L_tmp_y, L_shr (L_mult (thr1[*cand1], gcode0), sft_y)); if (L_temp > 0L) { (*cand1) = add (*cand1, 1); } else break; } while (sub ((*cand1), (NCODE1 - NCAN1)) < 0); /*-- pre select codebook #2 --*/ *cand2 = 0; do { L_temp = L_sub (L_tmp_x, L_shr (L_mult (thr2[*cand2], gcode0), sft_x)); if (L_temp > 0L) { (*cand2) = add (*cand2, 1); } else break; } while (sub ((*cand2), (NCODE2 - NCAN2)) < 0); } else { /*-- pre select codebook #1 --*/ *cand1 = 0; do { L_temp = L_sub (L_tmp_y, L_shr (L_mult (thr1[*cand1], gcode0), sft_y)); if (L_temp < 0L) { (*cand1) = add (*cand1, 1); } else break; } while (sub ((*cand1), (NCODE1 - NCAN1))); /*-- pre select codebook #2 --*/ *cand2 = 0; do { L_temp = L_sub (L_tmp_x, L_shr (L_mult (thr2[*cand2], gcode0), sft_x)); if (L_temp < 0L) { (*cand2) = add (*cand2, 1); } else break; } while (sub ((*cand2), (NCODE2 - NCAN2))); } return; }