/* ** ** Function: Calc_Exc_Rand() ** ** Description: Computation of random excitation for inactive frames: ** Adaptive codebook entry selected randomly ** Higher rate innovation pattern selected randomly ** Computes innovation gain to match curGain ** ** Links to text: ** ** Arguments: ** ** Word16 curGain current average gain to match ** Word16 *PrevExc previous/current excitation (updated) ** Word16 *DataEXc current frame excitation ** Word16 *nRandom random generator status (input/output) ** ** Outputs: ** ** Word16 *PrevExc ** Word16 *DataExc ** Word16 *nRandom ** ** Return value: None ** */ void Calc_Exc_Rand(Word16 curGain, Word16 *PrevExc, Word16 *DataExc, Word16 *nRandom, LINEDEF *Line) { int i, i_subfr, iblk; Word16 temp, temp2; Word16 j; Word16 TabPos[2*NbPulsBlk], TabSign[2*NbPulsBlk]; Word16 *ptr_TabPos, *ptr_TabSign; Word16 *ptr1, *curExc; Word16 sh1, x1, x2, inter_exc, delta, b0; Word32 L_acc, L_c, L_temp; Word16 tmp[SubFrLen/Sgrid]; Word16 offset[SubFrames]; Word16 tempExc[SubFrLenD]; /* * generate LTP codes */ Line->Olp[0] = random_number(21, nRandom) + (Word16)123; Line->Olp[1] = random_number(21, nRandom) + (Word16)123; for(i_subfr=0; i_subfr<SubFrames; i_subfr++) { /* in [1, NbFilt] */ Line->Sfs[i_subfr].AcGn = random_number(NbFilt, nRandom) + (Word16)1; } Line->Sfs[0].AcLg = 1; Line->Sfs[1].AcLg = 0; Line->Sfs[2].AcLg = 1; Line->Sfs[3].AcLg = 3; /* * Random innovation : * Selection of the grids, signs and pulse positions */ /* Signs and Grids */ ptr_TabSign = TabSign; ptr1 = offset; for(iblk=0; iblk<SubFrames/2; iblk++) { temp = random_number((1 << (NbPulsBlk+2)), nRandom); *ptr1++ = temp & (Word16)0x0001; temp = shr(temp, 1); *ptr1++ = add( (Word16) SubFrLen, (Word16) (temp & 0x0001) ); for(i=0; i<NbPulsBlk; i++) { *ptr_TabSign++= shl(sub((temp & (Word16)0x0002), 1), 14); temp = shr(temp, 1); } } /* Positions */ ptr_TabPos = TabPos; for(i_subfr=0; i_subfr<SubFrames; i_subfr++) { for(i=0; i<(SubFrLen/Sgrid); i++) tmp[i] = (Word16)i; temp = (SubFrLen/Sgrid); for(i=0; i<Nb_puls[i_subfr]; i++) { j = random_number(temp, nRandom); *ptr_TabPos++ = add(shl(tmp[(int)j],1), offset[i_subfr]); temp = sub(temp, 1); tmp[(int)j] = tmp[(int)temp]; } } /* * Compute fixed codebook gains */ ptr_TabPos = TabPos; ptr_TabSign = TabSign; curExc = DataExc; i_subfr = 0; for(iblk=0; iblk<SubFrames/2; iblk++) { /* decode LTP only */ Decod_Acbk(curExc, &PrevExc[0], Line->Olp[iblk], Line->Sfs[i_subfr].AcLg, Line->Sfs[i_subfr].AcGn); Decod_Acbk(&curExc[SubFrLen], &PrevExc[SubFrLen], Line->Olp[iblk], Line->Sfs[i_subfr+1].AcLg, Line->Sfs[i_subfr+1].AcGn); temp2 = 0; for(i=0; i<SubFrLenD; i++) { temp = abs_s(curExc[i]); if(temp > temp2) temp2 = temp; } if(temp2 == 0) sh1 = 0; else { sh1 = sub(4,norm_s(temp2)); /* 4 bits of margin */ if(sh1 < -2) sh1 = -2; } L_temp = 0L; for(i=0; i<SubFrLenD; i++) { temp = shr(curExc[i], sh1); /* left if sh1 < 0 */ L_temp = L_mac(L_temp, temp, temp); tempExc[i] = temp; } /* ener_ltp x 2**(-2sh1+1) */ L_acc = 0L; for(i=0; i<NbPulsBlk; i++) { L_acc = L_mac(L_acc, tempExc[(int)ptr_TabPos[i]], ptr_TabSign[i]); } inter_exc = extract_h(L_shl(L_acc, 1)); /* inter_exc x 2-sh1 */ /* compute SubFrLenD x curGain**2 x 2**(-2sh1+1) */ /* curGain input = 2**5 curGain */ // L_acc = L_mult(curGain, SubFrLen); L_MULT(curGain, SubFrLen, L_acc); L_acc = L_shr(L_acc, 6); temp = extract_l(L_acc); /* SubFrLen x curGain : avoids overflows */ // L_acc = L_mult(temp, curGain); L_MULT(temp, curGain, L_acc); temp = shl(sh1, 1); temp = add(temp, 4); L_acc = L_shr(L_acc, temp); /* SubFrLenD x curGain**2 x 2**(-2sh1+1) */ /* c = (ener_ltp - SubFrLenD x curGain**2)/nb_pulses_blk */ /* compute L_c = c >> 2sh1-1 */ L_acc = L_sub(L_temp, L_acc); /* x 1/nb_pulses_blk */ L_c = L_mls(L_acc, InvNbPulsBlk); /* * Solve EQ(X) = X**2 + 2 b0 X + c */ /* delta = b0 x b0 - c */ b0 = mult_r(inter_exc, InvNbPulsBlk); /* b0 >> sh1 */ L_acc = L_msu(L_c, b0, b0); /* (c - b0**2) >> 2sh1-1 */ L_acc = L_negate(L_acc); /* delta x 2**(-2sh1+1) */ /* Case delta <= 0 */ if(L_acc <= 0) { /* delta <= 0 */ x1 = negate(b0); /* sh1 */ } /* Case delta > 0 */ else { delta = Sqrt_lbc(L_acc); /* >> sh1 */ x1 = sub(delta, b0); /* x1 >> sh1 */ x2 = add(b0, delta); /* (-x2) >> sh1 */ if(abs_s(x2) < abs_s(x1)) { x1 = negate(x2); } } /* Update DataExc */ sh1 = add(sh1, 1); temp = shl(x1, sh1); if(temp > (2*Gexc_Max)) temp = (2*Gexc_Max); if(temp < -(2*Gexc_Max)) temp = -(2*Gexc_Max); for(i=0; i<NbPulsBlk; i++) { j = *ptr_TabPos++; curExc[(int)j] = add(curExc[(int)j], mult(temp, (*ptr_TabSign++)) ); } /* update PrevExc */ ptr1 = PrevExc; for(i=SubFrLenD; i<PitchMax; i++) *ptr1++ = PrevExc[i]; for(i=0; i<SubFrLenD; i++) *ptr1++ = curExc[i]; curExc += SubFrLenD; i_subfr += 2; } /* end of loop on LTP blocks */ return; }
/* ** ** Function: Qua_SidGain() ** ** Description: Quantization of Sid gain ** Pseudo-log quantizer in 3 segments ** 1st segment : length = 16, resolution = 2 ** 2nd segment : length = 16, resolution = 4 ** 3rd segment : length = 32, resolution = 8 ** quantizes a sum of energies ** ** Links to text: ** ** Arguments: ** ** Word16 *Ener table of the energies ** Word16 *shEner corresponding scaling factors ** Word16 nq if nq >= 1 : quantization of nq energies ** for SID gain calculation in function Cod_Cng() ** if nq = 0 : in function Comp_Info(), ** quantization of saved estimated excitation energy ** ** Outputs: None ** ** ** Return value: index of quantized energy ** */ Word16 Qua_SidGain(Word16 *Ener, Word16 *shEner, Word16 nq) { Word16 temp, iseg, iseg_p1; Word16 j, j2, k, exp; Word32 L_x, L_y; Word16 sh1; Word32 L_acc; int i; if(nq == 0) { /* Quantize energy saved for frame erasure case */ /* L_x = 2 x average_ener */ temp = shl(*shEner, 1); temp = sub(16, temp); L_acc = L_deposit_l(*Ener); L_acc = L_shl(L_acc, temp); /* may overflow, and >> if temp < 0 */ L_x = L_mls(L_acc, fact[0]); } else { /* * Compute weighted average of energies * Ener[i] = enerR[i] x 2**(shEner[i]-14) * L_x = k[nq] x SUM(i=0->nq-1) enerR[i] * with k[nq] = 2 x fact_mul x fact_mul / nq x Frame */ sh1 = shEner[0]; for(i=1; i<nq; i++) { if(shEner[i] < sh1) sh1 = shEner[i]; } for(i=0, L_x=0L; i<nq; i++) { temp = sub(shEner[i], sh1); temp = shr(Ener[i], temp); temp = mult_r(fact[nq], temp); L_x = L_add(L_x, L_deposit_l(temp)); } temp = sub(15, sh1); L_x = L_shl(L_x, temp); } /* Quantize L_x */ if(L_x >= L_bseg[2]) return(63); /* Compute segment number iseg */ if(L_x >= L_bseg[1]) { iseg = 2; exp = 4; } else { exp = 3; if(L_x >= L_bseg[0]) iseg = 1; else iseg = 0; } iseg_p1 = add(iseg,1); j = shl(1, exp); k = shr(j,1); /* Binary search in segment iseg */ for(i=0; i<exp; i++) { temp = add(base[iseg], shl(j, iseg_p1)); // L_y = L_mult(temp, temp); L_MULT(temp, temp, L_y); if(L_x >= L_y) j = add(j, k); else j = sub(j, k); k = shr(k, 1); } temp = add(base[iseg], shl(j, iseg_p1)); L_y = L_mult(temp, temp); L_y = L_sub(L_y, L_x); if(L_y <= 0L) { j2 = add(j, 1); temp = add(base[iseg], shl(j2, iseg_p1)); L_acc = L_mult(temp, temp); L_acc = L_sub(L_x, L_acc); if(L_y > L_acc) temp = add(shl(iseg,4), j); else temp = add(shl(iseg,4), j2); } else { j2 = sub(j, 1); temp = add(base[iseg], shl(j2, iseg_p1)); L_acc = L_mult(temp, temp); L_acc = L_sub(L_x, L_acc); if(L_y < L_acc) temp = add(shl(iseg,4), j); else temp = add(shl(iseg,4), j2); } return(temp); }
void dec_10i40_35bits ( INT16 index[], /* (i) : index of 10 pulses (sign+position) */ INT16 cod[] /* (o) : algebraic (fixed) codebook excitation */ ) { static const INT16 dgray[8] = {0, 1, 3, 2, 5, 6, 4, 7}; INT16 i, j, pos1, pos2, sign, tmp; VPP_EFR_PROFILE_FUNCTION_ENTER(dec_10i40_35bits); for (i = 0; i < L_CODE; i++) { cod[i] = 0; } /* decode the positions and signs of pulses and build the codeword */ for (j = 0; j < NB_TRACK; j++) { /* compute index i */ tmp = index[j]; i = tmp & 7; i = dgray[i]; //i = extract_l (L_shr (L_mult (i, 5), 1)); i = EXTRACT_L (L_SHR_D(L_MULT (i, 5), 1)); //pos1 = add(i, j); /* position of pulse "j" */ pos1 = ADD(i, j); //i = shr (tmp, 3) & 1; i = SHR_D(tmp, 3) & 1; if (i == 0) { sign = 4096; } else { sign = -4096; } cod[pos1] = sign; /* compute index i */ //i = index[add(j, 5)] & 7; i = index[ADD(j, 5)] & 7; i = dgray[i]; //i = extract_l (L_shr (L_mult (i, 5), 1)); i = EXTRACT_L (L_SHR_D(L_MULT(i, 5), 1)); //pos2 = add(i, j); /* position of pulse "j+5" */ pos2 = ADD(i, j); //if (sub (pos2, pos1) < 0) if (SUB (pos2, pos1) < 0) { // sign = negate (sign); sign = NEGATE(sign); } //cod[pos2] = add(cod[pos2], sign); cod[pos2] = ADD(cod[pos2], sign); } VPP_EFR_PROFILE_FUNCTION_EXIT(dec_10i40_35bits); return; }
void Az_lsp ( INT16 a[], /* (i) : predictor coefficients */ INT16 lsp[], /* (o) : line spectral pairs */ INT16 old_lsp[] /* (i) : old lsp[] (in case not found 10 roots) */ ) { INT16 i, j, nf, ip; INT16 xlow, ylow, xhigh, yhigh, xmid, ymid, xint; INT16 x, y, sign, exp; INT16 *coef; INT16 f1[M / 2 + 1], f2[M / 2 + 1]; INT32 t0=0; VPP_EFR_PROFILE_FUNCTION_ENTER(Az_lsp); /*-------------------------------------------------------------* * find the sum and diff. pol. F1(z) and F2(z) * * F1(z) <--- F1(z)/(1+z**-1) & F2(z) <--- F2(z)/(1-z**-1) * * * * f1[0] = 1.0; * * f2[0] = 1.0; * * * * for (i = 0; i< NC; i++) * * { * * f1[i+1] = a[i+1] + a[M-i] - f1[i] ; * * f2[i+1] = a[i+1] - a[M-i] + f2[i] ; * * } * *-------------------------------------------------------------*/ f1[0] = 1024; /* f1[0] = 1.0 */ f2[0] = 1024; /* f2[0] = 1.0 */ for (i = 0; i < NC; i++) { //VPP_MLX16 (t0_hi,t0_lo,a[i + 1], 8192); //VPP_MLA16 ( t0_hi, t0_lo, a[M - i], 8192); //t0 = VPP_SCALE64_TO_16( t0_hi, t0_lo); //x = EXTRACT_H(t0); t0 = (INT32) a[i + 1] + (INT32)a[M - i]; x = (INT16)(L_SHR_D(t0,2)); /* f1[i+1] = a[i+1] + a[M-i] - f1[i] */ f1[i + 1] = SUB (x, f1[i]); //VPP_MLX16(t0_hi, t0_lo, a[i + 1], 8192); //VPP_MLA16(t0_hi, t0_lo, a[M - i], -8192); //x = EXTRACT_H(VPP_SCALE64_TO_16(t0_hi, t0_lo)); t0 = (INT32) a[i + 1] - (INT32)a[M - i]; x = (INT16)(L_SHR_D(t0,2)); //f2[i + 1] = add (x, f2[i]); f2[i + 1] = ADD(x, f2[i]); } /*-------------------------------------------------------------* * find the LSPs using the Chebychev pol. evaluation * *-------------------------------------------------------------*/ nf = 0; /* number of found frequencies */ ip = 0; /* indicator for f1 or f2 */ coef = f1; xlow = grid[0]; ylow = Chebps (xlow, coef, NC); j = 0; /* while ( (nf < M) && (j < grid_points) ) */ //while ((sub (nf, M) < 0) && (sub (j, grid_points) < 0)) while ((SUB (nf, M) < 0) && (SUB (j, grid_points) < 0)) { j++; xhigh = xlow; yhigh = ylow; xlow = grid[j]; ylow = Chebps (xlow, coef, NC); //if (L_mult (ylow, yhigh) <= (INT32) 0L) if (L_MULT(ylow, yhigh) <= (INT32) 0L) { /* divide 4 times the interval */ for (i = 0; i < 4; i++) { /* xmid = (xlow + xhigh)/2 */ // xmid = add (shr (xlow, 1), shr (xhigh, 1)); xmid = ADD ((SHR_D(xlow, 1)),(SHR_D(xhigh, 1))); ymid = Chebps (xmid, coef, NC); //if (L_mult (ylow, ymid) <= (INT32) 0L) if (L_MULT(ylow, ymid) <= (INT32) 0L) { yhigh = ymid; xhigh = xmid; } else { ylow = ymid; xlow = xmid; } } /*-------------------------------------------------------------* * Linear interpolation * * xint = xlow - ylow*(xhigh-xlow)/(yhigh-ylow); * *-------------------------------------------------------------*/ //x = sub (xhigh, xlow); x = SUB (xhigh, xlow); //y = sub (yhigh, ylow); y = SUB (yhigh, ylow); if (y == 0) { xint = xlow; } else { sign = y; //y = abs_s (y); y = ABS_S(y); exp = norm_s (y); //y = shl (y, exp); y = SHL(y, exp); y = div_s ((INT16) 16383, y); //t0 = L_mult (x, y); t0 = L_MULT(x, y); //t0 = L_shr (t0, sub (20, exp)); t0 = L_SHR_V(t0, SUB (20, exp)); //y = extract_l (t0); /* y= (xhigh-xlow)/(yhigh-ylow) */ y = EXTRACT_L(t0); if (sign < 0) { //y = negate (y); y = NEGATE(y); } //t0 = L_mult (ylow, y); t0 = L_MULT(ylow, y); //t0 = L_shr (t0, 11); t0 = L_SHR_D(t0, 11); //xint = sub (xlow, extract_l (t0)); /* xint = xlow - ylow*y */ xint = SUB (xlow, EXTRACT_L(t0)); } lsp[nf] = xint; xlow = xint; nf++; if (ip == 0) { ip = 1; coef = f2; } else { ip = 0; coef = f1; } ylow = Chebps (xlow, coef, NC); } } /* Check if M roots found */ //if (sub (nf, M) < 0) if (SUB (nf, M) < 0) { for (i = 0; i < M; i++) { lsp[i] = old_lsp[i]; } } VPP_EFR_PROFILE_FUNCTION_EXIT(Az_lsp); return; }
INT16 q_gain_code ( /* Return quantization index */ INT16 code[], /* (i) : fixed codebook excitation */ INT16 lcode, /* (i) : codevector size */ INT16 *gain, /* (i/o) : quantized fixed codebook gain */ INT16 txdtx_ctrl, INT16 i_subfr ) { INT16 i, index=0; INT16 gcode0, err, err_min, exp, frac; INT32 ener, ener_code; register INT32 ener_code_hi=0; register UINT32 ener_code_lo=0; INT16 aver_gain; static INT16 gcode0_CN; VPP_EFR_PROFILE_FUNCTION_ENTER(q_gain_code); if ((txdtx_ctrl & TX_SP_FLAG) != 0) { /*-------------------------------------------------------------------* * energy of code: * * ~~~~~~~~~~~~~~~ * * ener_code(Q17) = 10 * Log10(energy/lcode) / constant * * = 1/2 * Log2(energy/lcode) * * constant = 20*Log10(2) * *-------------------------------------------------------------------*/ /* ener_code = log10(ener_code/lcode) / (20*log10(2)) */ //ener_code = 0; ener_code_lo = 0; for (i = 0; i < lcode; i++) { //ener_code = L_mac (ener_code, code[i], code[i]); //ener_code = L_MAC(ener_code, code[i], code[i]); VPP_MLA16(ener_code_hi,ener_code_lo,code[i], code[i]); } /* ener_code = ener_code / lcode */ ener_code = VPP_SCALE64_TO_16(ener_code_hi,ener_code_lo); //ener_code = L_mult (round(ener_code), 26214); ener_code = L_MULT(ROUND(ener_code), 26214); /* ener_code = 1/2 * Log2(ener_code) */ Log2 (ener_code, &exp, &frac); //ener_code = L_Comp (sub (exp, 30), frac); ener_code = L_Comp (SUB (exp, 30), frac); /* predicted energy */ //ener = MEAN_ENER; ener_code_lo = MEAN_ENER>>1; ener_code_hi =0; for (i = 0; i < 4; i++) { //ener = L_mac (ener, past_qua_en[i], pred[i]); //ener = L_MAC(ener, past_qua_en[i], pred[i]); VPP_MLA16(ener_code_hi,ener_code_lo, past_qua_en[i], pred[i]); } ener = VPP_SCALE64_TO_16(ener_code_hi,ener_code_lo); /*-------------------------------------------------------------------* * predicted codebook gain * * ~~~~~~~~~~~~~~~~~~~~~~~ * * gcode0(Qx) = Pow10( (ener*constant - ener_code*constant) / 20 ) * * = Pow2(ener-ener_code) * * constant = 20*Log10(2) * *-------------------------------------------------------------------*/ //ener = L_shr (L_SUB(ener, ener_code), 1); ener = L_SHR_D(L_SUB(ener, ener_code), 1); L_Extract (ener, &exp, &frac); //gcode0 = extract_l (Pow2 (exp, frac)); /* predicted gain */ gcode0 = EXTRACT_L(Pow2 (exp, frac)); //gcode0 = shl (gcode0, 4); gcode0 = SHL(gcode0, 4); /*-------------------------------------------------------------------* * Search for best quantizer * *-------------------------------------------------------------------*/ //err_min = abs_s (sub (*gain, mult (gcode0, qua_gain_code[0]))); err_min = ABS_S(SUB (*gain, MULT(gcode0, qua_gain_code[0]))); index = 0; for (i = 1; i < NB_QUA_CODE; i++) { //err = abs_s (sub (*gain, mult (gcode0, qua_gain_code[i]))); err = ABS_S(SUB (*gain, MULT (gcode0, qua_gain_code[i]))); //if (sub (err, err_min) < 0) if (SUB (err, err_min) < 0) { err_min = err; index = i; } } //*gain = mult (gcode0, qua_gain_code[index]); *gain = MULT(gcode0, qua_gain_code[index]); /*------------------------------------------------------------------* * update table of past quantized energies * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * past_qua_en(Q12) = 20 * Log10(qua_gain_code) / constant * * = Log2(qua_gain_code) * * constant = 20*Log10(2) * *------------------------------------------------------------------*/ for (i = 3; i > 0; i--) { past_qua_en[i] = past_qua_en[i - 1]; } //Log2 (L_deposit_l (qua_gain_code[index]), &exp, &frac); Log2 (L_DEPOSIT_L(qua_gain_code[index]), &exp, &frac); //past_qua_en[0] = shr (frac, 5); past_qua_en[0] = SHR_D(frac, 5); //past_qua_en[0] = add (past_qua_en[0], shl (sub (exp, 11), 10)); past_qua_en[0] = ADD (past_qua_en[0], SHL(SUB (exp, 11), 10)); update_gain_code_history_tx (*gain, gain_code_old_tx); }