/*-----------------------------------------------------------* * procedure Dec_cng: * * ~~~~~~~~ * * Receives frame type * * 0 : for untransmitted frames * * 2 : for SID frames * * Decodes SID frames * * Computes current frame excitation * * Computes current frame LSPs *-----------------------------------------------------------*/ void Dec_cng( Word16 past_ftyp, /* (i) : past frame type */ Word16 sid_sav, /* (i) : energy to recover SID gain */ Word16 sh_sid_sav, /* (i) : corresponding scaling factor */ Word16 *parm, /* (i) : coded SID parameters */ Word16 *exc, /* (i/o) : excitation array */ Word16 *lsp_old, /* (i/o) : previous lsp */ Word16 *A_t, /* (o) : set of interpolated LPC coefficients */ Word16 *seed, /* (i/o) : random generator seed */ Word16 freq_prev[MA_NP][M] /* (i/o) : previous LPS for quantization */ ) { Word16 temp, ind; Word16 dif; dif = sub(past_ftyp, 1); /* SID Frame */ /*************/ if(parm[0] != 0) { sid_gain = tab_Sidgain[(int)parm[4]]; /* Inverse quantization of the LSP */ sid_lsfq_decode(&parm[1], lspSid, freq_prev); } /* non SID Frame */ /*****************/ else { /* Case of 1st SID frame erased : quantize-decode */ /* energy estimate stored in sid_gain */ if(dif > 0) { Qua_Sidgain(&sid_sav, &sh_sid_sav, 0, &temp, &ind); sid_gain = tab_Sidgain[(int)ind]; } } if(dif > 0) { cur_gain = sid_gain; } else { cur_gain = mult_r(cur_gain, A_GAIN0); cur_gain = add(cur_gain, mult_r(sid_gain, A_GAIN1)); } Calc_exc_rand(cur_gain, exc, seed, FLAG_DEC); /* Interpolate the Lsp vectors */ Int_qlpc(lsp_old, lspSid, A_t); Copy(lspSid, lsp_old, M); return; }
/*-----------------------------------------------------------* * procedure Cod_cng: * * ~~~~~~~~ * * computes DTX decision * * encodes SID frames * * computes CNG excitation for encoder update * *-----------------------------------------------------------*/ void Cod_cng( DtxStatus *handle, Word16 *exc, /* (i/o) : excitation array */ Word16 pastVad, /* (i) : previous VAD decision */ Word16 *lsp_old_q, /* (i/o) : previous quantized lsp */ Word16 *Aq, /* (o) : set of interpolated LPC coefficients */ Word16 *ana, /* (o) : coded SID parameters */ Word16 freq_prev[MA_NP][M], /* (i/o) : previous LPS for quantization */ Word16 *seed /* (i/o) : random generator seed */ ) { Word16 i; Word16 curAcf[MP1]; Word16 bid[M], zero[MP1]; Word16 curCoeff[MP1]; Word16 lsp_new[M]; Word16 *lpcCoeff; Word16 cur_igain; Word16 energyq, temp; /* Update Ener and sh_ener */ for(i = NB_GAIN-1; i>=1; i--) { handle->ener[i] = handle->ener[i-1]; handle->sh_ener[i] = handle->sh_ener[i-1]; } /* Compute current Acfs */ Calc_sum_acf(handle->Acf, handle->sh_Acf, curAcf, &(handle->sh_ener[0]), NB_CURACF); /* Compute LPC coefficients and residual energy */ if(curAcf[0] == 0) { handle->ener[0] = 0; /* should not happen */ } else { Set_zero(zero, MP1); Levinson(handle, curAcf, zero, curCoeff, bid, &(handle->ener[0])); } /* if first frame of silence => SID frame */ if(pastVad != 0) { ana[0] = 2; handle->count_fr0 = 0; handle->nb_ener = 1; Qua_Sidgain(handle->ener, handle->sh_ener, handle->nb_ener, &energyq, &cur_igain); } else { handle->nb_ener = add(handle->nb_ener, 1); if(sub(handle->nb_ener, NB_GAIN) > 0) handle->nb_ener = NB_GAIN; Qua_Sidgain(handle->ener, handle->sh_ener, handle->nb_ener, &energyq, &cur_igain); /* Compute stationarity of current filter */ /* versus reference filter */ if(Cmp_filt(handle->RCoeff, handle->sh_RCoeff, curAcf, handle->ener[0], FRAC_THRESH1) != 0) { handle->flag_chang = 1; } /* compare energy difference between current frame and last frame */ temp = abs_s(sub(handle->prev_energy, energyq)); temp = sub(temp, 2); if (temp > 0) handle->flag_chang = 1; handle->count_fr0 = add(handle->count_fr0, 1); if(sub(handle->count_fr0, FR_SID_MIN) < 0) { ana[0] = 0; /* no transmission */ } else { if(handle->flag_chang != 0) { ana[0] = 2; /* transmit SID frame */ } else{ ana[0] = 0; } handle->count_fr0 = FR_SID_MIN; /* to avoid overflow */ } } if(sub(ana[0], 2) == 0) { /* Reset frame count and change flag */ handle->count_fr0 = 0; handle->flag_chang = 0; /* Compute past average filter */ Calc_pastfilt(handle, handle->pastCoeff); Calc_RCoeff(handle->pastCoeff, handle->RCoeff, &(handle->sh_RCoeff)); /* Compute stationarity of current filter */ /* versus past average filter */ /* if stationary */ /* transmit average filter => new ref. filter */ if(Cmp_filt(handle->RCoeff, handle->sh_RCoeff, curAcf, handle->ener[0], FRAC_THRESH2) == 0) { lpcCoeff = handle->pastCoeff; } /* else */ /* transmit current filter => new ref. filter */ else { lpcCoeff = curCoeff; Calc_RCoeff(curCoeff, handle->RCoeff, &(handle->sh_RCoeff)); } /* Compute SID frame codes */ Az_lsp(lpcCoeff, lsp_new, lsp_old_q); /* From A(z) to lsp */ /* LSP quantization */ lsfq_noise(lsp_new, handle->lspSid_q, freq_prev, &ana[1]); handle->prev_energy = energyq; ana[4] = cur_igain; handle->sid_gain = tab_Sidgain[cur_igain]; } /* end of SID frame case */ /* Compute new excitation */ if(pastVad != 0) { handle->cur_gain = handle->sid_gain; } else { handle->cur_gain = mult_r(handle->cur_gain, A_GAIN0); handle->cur_gain = add(handle->cur_gain, mult_r(handle->sid_gain, A_GAIN1)); } Calc_exc_rand(handle->L_exc_err, handle->cur_gain, exc, seed, FLAG_COD); Int_qlpc(lsp_old_q, handle->lspSid_q, Aq); for(i=0; i<M; i++) { lsp_old_q[i] = handle->lspSid_q[i]; } /* Update sumAcf if fr_cur = 0 */ if(handle->fr_cur == 0) { Update_sumAcf(handle); } return; }