/*---------------------------------------------------------------------------- ; 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; }
/* ------------------------------------------------------------------------------ FUNCTION NAME: ec_gain_code ------------------------------------------------------------------------------ INPUT AND OUTPUT DEFINITIONS Inputs: st = pointer to a pointer to a structure containing code state data of stucture type ec_gain_codeState pred_state = pointer to MA predictor state of type gc_predState state = state of the state machine of type Word16 gain_code = pointer to decoded innovation gain of type Word16 pOverflow = pointer to overflow indicator of type Flag Outputs: st = pointer to a pointer to a structure containing code state data of stucture type ec_gain_codeState pred_state = pointer to MA predictor state of type gc_predState pOverflow = 1 if there is an overflow else it is zero. Returns: None. Global Variables Used: None. Local Variables Needed: None. ------------------------------------------------------------------------------ FUNCTION DESCRIPTION This function does error concealment using the codebook. Call this function only in BFI (instead of normal gain decoding function). ------------------------------------------------------------------------------ REQUIREMENTS None. ------------------------------------------------------------------------------ REFERENCES ec_gain.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001 ------------------------------------------------------------------------------ PSEUDO-CODE static const Word16 cdown[7] = { 32767, 32112, 32112, 32112, 32112, 32112, 22937 }; Word16 tmp; Word16 qua_ener_MR122; Word16 qua_ener; // calculate median of last five gain values tmp = gmed_n (st->gbuf,5); // new gain = minimum(median, past_gain) * cdown[state] if (sub (tmp, st->past_gain_code) > 0) { tmp = st->past_gain_code; } tmp = mult (tmp, cdown[state]); *gain_code = tmp; // update table of past quantized energies with average of // current values gc_pred_average_limited(pred_state, &qua_ener_MR122, &qua_ener); gc_pred_update(pred_state, qua_ener_MR122, qua_ener); } ------------------------------------------------------------------------------ CAUTION [optional] [State any special notes, constraints or cautions for users of this function] ------------------------------------------------------------------------------ */ void ec_gain_code( ec_gain_codeState *st, /* i/o : State struct */ gc_predState *pred_state, /* i/o : MA predictor state */ Word16 state, /* i : state of the state machine */ Word16 *gain_code, /* o : decoded innovation gain */ Flag *pOverflow ) { static const Word16 cdown[7] = { 32767, 32112, 32112, 32112, 32112, 32112, 22937 }; Word16 tmp; Word16 qua_ener_MR122; Word16 qua_ener; /* calculate median of last five gain values */ tmp = gmed_n(st->gbuf, 5); /* new gain = minimum(median, past_gain) * cdown[state] */ if (sub(tmp, st->past_gain_code, pOverflow) > 0) { tmp = st->past_gain_code; } tmp = mult(tmp, cdown[state], pOverflow); *gain_code = tmp; /* update table of past quantized energies with average of * current values */ gc_pred_average_limited(pred_state, &qua_ener_MR122, &qua_ener, pOverflow); gc_pred_update(pred_state, qua_ener_MR122, qua_ener); }
/* ******************************************************************************** * 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); }
/************************************************************************* * * FUNCTION: Dec_gain() * * PURPOSE: Decode the pitch and codebook gains * ************************************************************************/ void Dec_gain( gc_predState *pred_state, /* i/o: MA predictor state */ enum Mode mode, /* i : AMR mode */ Word16 index, /* i : index of quantization. */ Word16 code[], /* i : Innovative vector. */ Word16 evenSubfr, /* i : Flag for even subframes */ Word16 * gain_pit, /* o : Pitch gain. */ Word16 * gain_cod /* o : Code gain. */ ) { const Word16 *p; Word16 frac, gcode0, exp, qua_ener, qua_ener_MR122; Word16 g_code; Word32 L_tmp; /* Read the quantized gains (table depends on mode) */ index = shl (index, 2); test(); test(); test(); if ( sub (mode, MR102) == 0 || sub (mode, MR74) == 0 || sub (mode, MR67) == 0) { p = &table_gain_highrates[index]; move16 (); *gain_pit = *p++; move16 (); g_code = *p++; move16 (); qua_ener_MR122 = *p++; move16 (); qua_ener = *p; move16 (); } else { test(); if (sub (mode, MR475) == 0) { index = add (index, shl(sub(1, evenSubfr), 1)); p = &table_gain_MR475[index]; move16 (); *gain_pit = *p++; move16 (); g_code = *p++; move16 (); /*---------------------------------------------------------* * calculate predictor update values (not stored in 4.75 * * quantizer table to save space): * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * * * qua_ener = log2(g) * * qua_ener_MR122 = 20*log10(g) * *---------------------------------------------------------*/ /* Log2(x Q12) = log2(x) + 12 */ Log2 (L_deposit_l (g_code), &exp, &frac); exp = sub(exp, 12); qua_ener_MR122 = add (shr_r (frac, 5), shl (exp, 10)); /* 24660 Q12 ~= 6.0206 = 20*log10(2) */ L_tmp = Mpy_32_16(exp, frac, 24660); qua_ener = round (L_shl (L_tmp, 13)); /* Q12 * Q0 = Q13 -> Q10 */ } else { p = &table_gain_lowrates[index]; move16 (); *gain_pit = *p++; move16 (); g_code = *p++; move16 (); qua_ener_MR122 = *p++; move16 (); qua_ener = *p; move16 (); } } /*-------------------------------------------------------------------* * predict codebook gain * * ~~~~~~~~~~~~~~~~~~~~~ * * gc0 = Pow2(int(d)+frac(d)) * * = 2^exp + 2^frac * * * * gcode0 (Q14) = 2^14*2^frac = gc0 * 2^(14-exp) * *-------------------------------------------------------------------*/ gc_pred(pred_state, mode, code, &exp, &frac, NULL, NULL); gcode0 = extract_l(Pow2(14, frac)); /*------------------------------------------------------------------* * read quantized gains, update table of past quantized energies * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * st->past_qua_en(Q10) = 20 * Log10(g_fac) / constant * * = Log2(g_fac) * * = qua_ener * * constant = 20*Log10(2) * *------------------------------------------------------------------*/ L_tmp = L_mult(g_code, gcode0); L_tmp = L_shr(L_tmp, sub(10, exp)); *gain_cod = extract_h(L_tmp); /* update table of past quantized energies */ gc_pred_update(pred_state, qua_ener_MR122, qua_ener); return; }
//============================================================================= //函数名称:Dec_gain //函数功能:解码的音调和码书增益 //============================================================================= void Dec_gain( gc_predState *pred_state, /* i/o: MA predictor state */ enum Mode mode, /* i : AMR mode */ Word16 index, /* i : index of quantization. */ Word16 code[], /* i : Innovative vector. */ Word16 evenSubfr, /* i : Flag for even subframes */ Word16 * gain_pit, /* o : Pitch gain. */ Word16 * gain_cod, /* o : Code gain. */ Flag * pOverflow ) { const Word16 *p; Word16 frac; Word16 gcode0; Word16 exp; Word16 qua_ener; Word16 qua_ener_MR122; Word16 g_code; Word32 L_tmp; Word16 temp1; Word16 temp2; /* Read the quantized gains (table depends on mode) */ //阅读量化收益(表取决于模式) index = shl(index, 2, pOverflow); if (mode == MR102 || mode == MR74 || mode == MR67) { p = &table_gain_highrates[index]; *gain_pit = *p++; g_code = *p++; qua_ener_MR122 = *p++; qua_ener = *p; } else { if (mode == MR475) { index += (1 ^ evenSubfr) << 1; /* evenSubfr is 0 or 1 */ if (index > (MR475_VQ_SIZE*4 - 2)) { index = (MR475_VQ_SIZE * 4 - 2); /* avoid possible buffer overflow */ } p = &table_gain_MR475[index]; *gain_pit = *p++; g_code = *p++; /*---------------------------------------------------------* * calculate predictor update values (not stored in 4.75 * * quantizer table to save space): * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * * * qua_ener = log2(g) * * qua_ener_MR122 = 20*log10(g) * *---------------------------------------------------------*/ //计算预测更新值(不存储在4.75量化表,以节省空间) /* Log2(x Q12) = log2(x) + 12 */ temp1 = (Word16) L_deposit_l(g_code); Log2(temp1, &exp, &frac, pOverflow); exp = sub(exp, 12, pOverflow); temp1 = shr_r(frac, 5, pOverflow); temp2 = shl(exp, 10, pOverflow); qua_ener_MR122 = add(temp1, temp2, pOverflow); /* 24660 Q12 ~= 6.0206 = 20*log10(2) */ L_tmp = Mpy_32_16(exp, frac, 24660, pOverflow); L_tmp = L_shl(L_tmp, 13, pOverflow); qua_ener = pv_round(L_tmp, pOverflow); /* Q12 * Q0 = Q13 -> Q10 */ } else { p = &table_gain_lowrates[index]; *gain_pit = *p++; g_code = *p++; qua_ener_MR122 = *p++; qua_ener = *p; } } /*-------------------------------------------------------------------* * predict codebook gain * * ~~~~~~~~~~~~~~~~~~~~~ * * gc0 = Pow2(int(d)+frac(d)) * * = 2^exp + 2^frac * * * * gcode0 (Q14) = 2^14*2^frac = gc0 * 2^(14-exp) * *-------------------------------------------------------------------*/ gc_pred(pred_state, mode, code, &exp, &frac, NULL, NULL, pOverflow); gcode0 = (Word16) Pow2(14, frac, pOverflow); /*------------------------------------------------------------------* * read quantized gains, update table of past quantized energies * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * st->past_qua_en(Q10) = 20 * Log10(g_fac) / constant * * = Log2(g_fac) * * = qua_ener * * constant = 20*Log10(2) * *------------------------------------------------------------------*/ L_tmp = L_mult(g_code, gcode0, pOverflow); temp1 = sub(10, exp, pOverflow); L_tmp = L_shr(L_tmp, temp1, pOverflow); *gain_cod = extract_h(L_tmp); /* update table of past quantized energies */ //过去的量化能量表更新 gc_pred_update(pred_state, qua_ener_MR122, qua_ener); return; }
int gainQuant( gainQuantState *st, /* i/o : State struct */ enum Mode mode, /* i : coder mode */ Word16 res[], /* i : LP residual, Q0 */ Word16 exc[], /* i : LTP excitation (unfiltered), Q0 */ Word16 code[], /* i : CB innovation (unfiltered), Q13 */ /* (unsharpened for MR475) */ Word16 xn[], /* i : Target vector. */ Word16 xn2[], /* i : Target vector. */ Word16 y1[], /* i : Adaptive codebook. */ Word16 Y2[], /* i : Filtered innovative vector. */ Word16 g_coeff[], /* i : Correlations <xn y1> <y1 y1> */ /* Compute in G_pitch(). */ Word16 even_subframe, /* i : even subframe indicator flag */ Word16 gp_limit, /* i : pitch gain limit */ Word16 *sf0_gain_pit, /* o : Pitch gain sf 0. MR475 */ Word16 *sf0_gain_cod, /* o : Code gain sf 0. MR475 */ Word16 *gain_pit, /* i/o : Pitch gain. */ Word16 *gain_cod, /* o : Code gain. */ /* MR475: gain_* unquantized in even */ /* subframes, quantized otherwise */ Word16 **anap /* o : Index of quantization */ ) { Word16 exp_gcode0; Word16 frac_gcode0; Word16 qua_ener_MR122; Word16 qua_ener; Word16 frac_coeff[5]; Word16 exp_coeff[5]; Word16 exp_en, frac_en; Word16 cod_gain_exp, cod_gain_frac; test (); if (sub (mode, MR475) == 0) { test (); if (even_subframe != 0) { /* save position in output parameter stream and current state of codebook gain predictor */ st->gain_idx_ptr = (*anap)++; gc_pred_copy(st->gc_predSt, st->gc_predUnqSt); /* predict codebook gain (using "unquantized" predictor)*/ /* (note that code[] is unsharpened in MR475) */ gc_pred(st->gc_predUnqSt, mode, code, &st->sf0_exp_gcode0, &st->sf0_frac_gcode0, &exp_en, &frac_en); /* calculate energy coefficients for quantization and store them in state structure (will be used in next subframe when real quantizer is run) */ calc_filt_energies(mode, xn, xn2, y1, Y2, g_coeff, st->sf0_frac_coeff, st->sf0_exp_coeff, &cod_gain_frac, &cod_gain_exp); /* store optimum codebook gain (Q1) */ *gain_cod = shl (cod_gain_frac, add (cod_gain_exp, 1)); move16 (); calc_target_energy(xn, &st->sf0_exp_target_en, &st->sf0_frac_target_en); /* calculate optimum codebook gain and update "unquantized" predictor */ MR475_update_unq_pred(st->gc_predUnqSt, st->sf0_exp_gcode0, st->sf0_frac_gcode0, cod_gain_exp, cod_gain_frac); /* the real quantizer is not run here... */ } else { /* predict codebook gain (using "unquantized" predictor) */ /* (note that code[] is unsharpened in MR475) */ gc_pred(st->gc_predUnqSt, mode, code, &exp_gcode0, &frac_gcode0, &exp_en, &frac_en); /* calculate energy coefficients for quantization */ calc_filt_energies(mode, xn, xn2, y1, Y2, g_coeff, frac_coeff, exp_coeff, &cod_gain_frac, &cod_gain_exp); calc_target_energy(xn, &exp_en, &frac_en); /* run real (4-dim) quantizer and update real gain predictor */ *st->gain_idx_ptr = MR475_gain_quant( st->gc_predSt, st->sf0_exp_gcode0, st->sf0_frac_gcode0, st->sf0_exp_coeff, st->sf0_frac_coeff, st->sf0_exp_target_en, st->sf0_frac_target_en, code, exp_gcode0, frac_gcode0, exp_coeff, frac_coeff, exp_en, frac_en, gp_limit, sf0_gain_pit, sf0_gain_cod, gain_pit, gain_cod); } } else { /*-------------------------------------------------------------------* * predict codebook gain and quantize * * (also compute normalized CB innovation energy for MR795) * *-------------------------------------------------------------------*/ gc_pred(st->gc_predSt, mode, code, &exp_gcode0, &frac_gcode0, &exp_en, &frac_en); test (); if (sub(mode, MR122) == 0) { *gain_cod = G_code (xn2, Y2); move16 (); *(*anap)++ = q_gain_code (mode, exp_gcode0, frac_gcode0, gain_cod, &qua_ener_MR122, &qua_ener); move16 (); } else { /* calculate energy coefficients for quantization */ calc_filt_energies(mode, xn, xn2, y1, Y2, g_coeff, frac_coeff, exp_coeff, &cod_gain_frac, &cod_gain_exp); test (); if (sub (mode, MR795) == 0) { MR795_gain_quant(st->adaptSt, res, exc, code, frac_coeff, exp_coeff, exp_en, frac_en, exp_gcode0, frac_gcode0, L_SUBFR, cod_gain_frac, cod_gain_exp, gp_limit, gain_pit, gain_cod, &qua_ener_MR122, &qua_ener, anap); } else { *(*anap)++ = Qua_gain(mode, exp_gcode0, frac_gcode0, frac_coeff, exp_coeff, gp_limit, gain_pit, gain_cod, &qua_ener_MR122, &qua_ener); move16 (); } } /*------------------------------------------------------------------* * update table of past quantized energies * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * st->past_qua_en(Q10) = 20 * Log10(qua_gain_code) / constant * * = Log2(qua_gain_code) * * = qua_ener * * constant = 20*Log10(2) * *------------------------------------------------------------------*/ gc_pred_update(st->gc_predSt, qua_ener_MR122, qua_ener); } return 0; }