📄 qgain795.c
字号:
dist_min = L_tmp < dist_min ? L_tmp : dist_min;
}
/*------------------------------------------------------------------*
* read quantized gains and new values for MA predictor memories *
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
*------------------------------------------------------------------*/
/* Read the quantized gains */
p = &qua_gain_code[index+ index+ index];
g_code = *p++;
*qua_ener_MR122 = *p++;
*qua_ener = *p;
/*------------------------------------------------------------------*
* calculate final fixed codebook gain: *
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
* *
* gc = gc0 * g *
*------------------------------------------------------------------*/
L_tmp = (g_code* gcode0 << 1 );
L_tmp = 9>exp_gcode0 ? L_tmp >> (9-exp_gcode0) : L_tmp << (exp_gcode0 - 9);
*gain_cod = (Word16)(L_tmp >> 16);
return index;
}
/************************************************************************* * * FUNCTION: MR795_gain_quant * * PURPOSE: pitch and codebook quantization for MR795 * *************************************************************************/void MR795_gain_quant( GainAdaptState *adapt_st, Word16 res[], Word16 exc[], Word16 code[],Word16 frac_coeff[],
Word16 exp_coeff[], Word16 exp_code_en, Word16 frac_code_en, Word16 exp_gcode0, Word16 frac_gcode0,
Word16 L_subfr,Word16 cod_gain_frac, Word16 cod_gain_exp,Word16 gp_limit, Word16 *gain_pit,
Word16 *gain_cod, Word16 *qua_ener_MR122, Word16 *qua_ener, Word16 **anap )
{
Word16 frac_en[4]; Word16 exp_en[4]; Word16 ltpg, alpha, gcode0; Word16 g_pitch_cand[3]; /* pitch gain candidates Q14 */ Word16 g_pitch_cind[3]; /* pitch gain indices Q0 */ Word16 gain_pit_index; Word16 gain_cod_index; Word16 exp; Word16 gain_cod_unq; /* code gain (unq.) Q(10-exp_gcode0) */ /* get list of candidate quantized pitch gain values * and corresponding quantization indices */ gain_pit_index = q_gain_pitch (MR795, gp_limit, gain_pit, g_pitch_cand, g_pitch_cind); /*-------------------------------------------------------------------* * predicted codebook gain * * ~~~~~~~~~~~~~~~~~~~~~~~ * * gc0 = 2^exp_gcode0 + 2^frac_gcode0 * * * * gcode0 (Q14) = 2^14*2^frac_gcode0 = gc0 * 2^(14-exp_gcode0) * *-------------------------------------------------------------------*/ gcode0 = (Word16)Pow2(14, frac_gcode0); /* Q14 */ /* pre-quantization of codebook gain * (using three pitch gain candidates); * result: best guess of pitch gain and code gain */ MR795_gain_code_quant3( exp_gcode0, gcode0, g_pitch_cand, g_pitch_cind, frac_coeff, exp_coeff, gain_pit, &gain_pit_index, gain_cod, &gain_cod_index, qua_ener_MR122, qua_ener); /* calculation of energy coefficients and LTP coding gain */ calc_unfilt_energies(res, exc, code, *gain_pit, L_subfr, frac_en, exp_en, <pg); /* run gain adaptor, calculate alpha factor to balance LTP/CB gain * (this includes the gain adaptor update) * Note: ltpg = 0 if frac_en[0] == 0, so the update is OK in that case */ gain_adapt(adapt_st, ltpg, *gain_cod, &alpha); /* if this is a very low energy signal (threshold: see * calc_unfilt_energies) or alpha <= 0 then don't run the modified quantizer */ if (frac_en[0] != 0 && alpha > 0) { /* innovation energy <cod cod> was already computed in gc_pred() */ /* (this overwrites the LtpResEn which is no longer needed) */ frac_en[3] = frac_code_en; exp_en[3] = exp_code_en; /* store optimum codebook gain in Q(10-exp_gcode0) */ exp = cod_gain_exp -exp_gcode0 + 10; gain_cod_unq = exp >0 ? cod_gain_frac<<exp: cod_gain_frac>> -exp; /* run quantization with modified criterion */ gain_cod_index = MR795_gain_code_quant_mod( *gain_pit, exp_gcode0, gcode0, frac_en, exp_en, alpha, gain_cod_unq, gain_cod, qua_ener_MR122, qua_ener); } *(*anap)++ = gain_pit_index; *(*anap)++ = gain_cod_index; }
/************************************************************************* * * Function: gain_adapt() * Purpose: calculate pitch/codebook gain adaptation factor alpha * (and update the adaptor state) * ***************************************************************************/
void gain_adapt(GainAdaptState *st, Word16 ltpg, Word16 gain_cod, Word16 *alpha )
{
Word16 adapt; /* adaptdation status; 0, 1, or 2 */
Word16 result; /* alpha factor, Q13 */
Word16 filt; /* median-filtered LTP coding gain, Q13 */
Word16 tmp, i,temp[5];
GainAdaptState *pst = st;
adapt = (ltpg <= LTP_GAIN_THR1) ? 0 : ((ltpg <= LTP_GAIN_THR2 ) ? 1 : 2);
tmp = (gain_cod>>1)+(gain_cod&0x1);
pst->onset = ((tmp > pst->prev_gc ) &&(gain_cod> 200) ) ? 8 : pst->onset - (pst->onset != 0);
/** // if onset, increase adaptor state
* if (onset && (gainAdapt < 2)) gainAdapt++;*/
adapt = adapt + ((pst->onset != 0) && (adapt < 2));
pst->ltpg_mem[0] = ltpg;
temp[0] = pst->ltpg_mem[0];temp[1] = pst->ltpg_mem[1];temp[2] = pst->ltpg_mem[2];
temp[3] = pst->ltpg_mem[3];temp[4] = pst->ltpg_mem[4];
if(temp[0] < temp[1]) { i = temp[0]; temp[0] = temp[1]; temp[1] = i; };
if(temp[0] < temp[2]) { i = temp[0]; temp[0] = temp[2]; temp[2] = i; };
if(temp[0] < temp[3]) { i = temp[0]; temp[0] = temp[3]; temp[3] = i; };
if(temp[0] < temp[4]) { i = temp[0]; temp[0] = temp[4]; temp[4] = i; };
if(temp[1] < temp[2]) { i = temp[1]; temp[1] = temp[2]; temp[2] = i; };
if(temp[1] < temp[3]) { i = temp[1]; temp[1] = temp[3]; temp[3] = i; };
if(temp[1] < temp[4]) { i = temp[1]; temp[1] = temp[4]; temp[4] = i; };
if(temp[2] < temp[3]) { i = temp[2]; temp[2] = temp[3]; temp[3] = i; };
if(temp[2] < temp[4]) { i = temp[2]; temp[2] = temp[4]; temp[4] = i; };
filt = temp[2];
if (adapt == 0)
{
if ( filt >5443) /* 5443 Q13 = 0.66443... */ { result = 0; } else { result = filt < 0 ? 16384 :16384-(24660*(filt<<2)>>15 );
} } else { result = 0; } /* * if (prevAlpha == 0.0) result = 0.5 * (result + prevAlpha); */ result >>= (pst->prev_alpha == 0);
/* store the result */ *alpha = result; /* update adapter state memory */ pst->prev_alpha = result;
pst->prev_gc = gain_cod;
pst->ltpg_mem[4] = pst->ltpg_mem[3];
pst->ltpg_mem[3] = pst->ltpg_mem[2];
pst->ltpg_mem[2] = pst->ltpg_mem[1];
pst->ltpg_mem[1] = pst->ltpg_mem[0];
}
Word16 q_gain_pitch ( Mode mode, Word16 gp_limit, Word16 *gain,Word16 gain_cand[], Word16 gain_cind[] )
{
Word16 i, index, err, err_min;
Word16 *pgain = gain, *pgain_cind = gain_cind, *pgain_cand = gain_cand;
const Word16 *pqua_gain_pitch = qua_gain_pitch;
err_min = abs(*pgain - pqua_gain_pitch[0]);
index = 0;
for (i = 1; i < NB_QUA_PITCH; i++) { if ( pqua_gain_pitch[i] <= gp_limit)
{ err = abs (*pgain- pqua_gain_pitch[i]);
index = err < err_min ? i :index;
err_min = err<err_min ? err : err_min;
}
} if (mode == MR795) { /* in MR795 mode, compute three gain_pit candidates around the index
* found in the quantization loop: the index found and the two direct
* neighbours, except for the extreme cases (i=0 or i=NB_QUA_PITCH-1),
* where the direct neighbour and the neighbour to that is used.
*/
Word16 ii;
ii = index == 0 ? index : ((index == NB_QUA_PITCH-1)|| (pqua_gain_pitch[index+1]> gp_limit) ? index-2 : index-1);
/* store candidate indices and values */
pgain_cind[0] = ii;
pgain_cand[0] = pqua_gain_pitch[ii];
ii ++;
pgain_cind[1] = ii;
pgain_cand[1] = pqua_gain_pitch[ii];
ii ++;
pgain_cind[2] = ii;
pgain_cand[2] = pqua_gain_pitch[ii];
ii ++;
*pgain = pqua_gain_pitch[index];
} else {
*pgain = ( mode == MR122) ? pqua_gain_pitch[index] & 0xFFFC : pqua_gain_pitch[index];
} return index;
}
/************************************************************************* * * FUNCTION: calc_unfilt_energies * * PURPOSE: calculation of several energy coefficients for unfiltered * excitation signals and the LTP coding gain * * frac_en[0]*2^exp_en[0] = <res res> // LP residual energy * frac_en[1]*2^exp_en[1] = <exc exc> // LTP residual energy * frac_en[2]*2^exp_en[2] = <exc code> // LTP/CB innovation dot product * frac_en[3]*2^exp_en[3] = <lres lres> // LTP residual energy * // (lres = res - gain_pit*exc) * ltpg = log2(LP_res_en / LTP_res_en) * *************************************************************************/void calc_unfilt_energies(Word16 res[], Word16 exc[], Word16 code[], Word16 gain_pit,Word16 L_subfr, Word16 frac_en[],Word16 exp_en[], Word16 *ltpg )
{ Word32 s, s1,s2, L_temp;
Word16 i, exp,exp1,exp2, tmp,tmp1,tmp2,tmp3;
Word16 ltp_res_en, pred_gain;
Word16 ltpg_exp, ltpg_frac;
Word16 *pres = res,*pfrac_en = frac_en, *pexp_en = exp_en,*pexc = exc,*pcode = code ;
/* Compute residual energy */
s =0;
for (i = 0; i < L_subfr; i++)
{
s += pres[i]*pres[i]<<1;
if(s<0)
{
s = MAX_32; break;
}
}
/* ResEn := 0 if ResEn < 200.0 (= 400 Q1) */
tmp = s<400L;
exp = tmp ? 0 : norm_l(s);
pfrac_en[0] = (Word16)(tmp ? 0 : ((s<<exp)>>16));
pexp_en[0] = tmp ? -15 : (15 - exp);
/* Compute ltp excitation energy */
s = 0;
s1 = s2 = 0;
for (i = 0; i < L_subfr; i+=4 )
{
s += (pexc[i]*pexc[i] + pexc[i+1]*pexc[i+1]+ pexc[i+2]*pexc[i+2] + pexc[i+3]*pexc[i+3]) <<1;
s1 += (pexc[i]*pcode[i] + pexc[i+1]*pcode[i+1] + pexc[i+2]*pcode[i+2] +pexc[i+3]*pcode[i+3])<<1;
tmp = pres[i] -(((pexc[i]*gain_pit<<2) +0x00008000)>>16); /* LTP residual, Q0 */
tmp1 = pres[i+1] -(((pexc[i+1]*gain_pit<<2) +0x00008000)>>16);
tmp2 = pres[i+2] -(((pexc[i+2]*gain_pit<<2) +0x00008000)>>16);
tmp3 = pres[i+3] -(((pexc[i+3]*gain_pit<<2) +0x00008000)>>16);
s2 += (tmp*tmp + tmp1*tmp1 + tmp2*tmp2 + tmp3*tmp3) <<1;
}
exp = norm_l(s);
exp1 = norm_l(s1);
exp2 = norm_l(s2);
pfrac_en[1] = (Word16)((s<< exp)>>16);
pexp_en[1] = 15- exp;
pfrac_en[2] = (Word16)((s1<<exp1)>>16);
pexp_en[2] = 2- exp1;
ltp_res_en =(Word16)((s2<<exp2)>>16);
exp2 = 15 -exp2;
pfrac_en[3] = ltp_res_en;
pexp_en[3] = exp2;
/* calculate LTP coding gain, i.e. energy reduction LP res -> LTP res */
if (ltp_res_en > 0 && pfrac_en[0] != 0)
{
/* gain = ResEn / LTPResEn */
pred_gain = div_s ((pfrac_en[0]>>1), ltp_res_en);
exp2 -= pexp_en[0];
/* L_temp = ltpGain * 2^(30 + exp) */
L_temp = (pred_gain<<16);
L_temp = (exp2 + 3) > 0 ? L_temp>>(exp2+3):(L_temp > (MAX_32 >> (-exp2-3)) ? MAX_32: L_temp << -(exp2+3) );
/* Log2 = log2() + 27 */
Log2(L_temp, <pg_exp, <pg_frac);
L_temp = ((ltpg_exp -27)<<16) + (ltpg_frac<<1);
L_temp = L_temp << 13;
*ltpg = (L_temp > 0)&&(L_temp+0x00008000)<0 ? MAX_16: (L_temp+0x00008000)>>16;
}
else
{
*ltpg = 0;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -