📄 cod_cng.c
字号:
/***** File: "cod_cng.c"**** Description: Comfort noise generation** performed at the encoder part**** Functions: Init_Cod_Cng()** Cod_Cng()** Update_Cng()**** Local functions:** ComputePastAvFilter()** CalcRC()** LpcDiff()*****//* ITU-T G.723 Speech Coder ANSI-C Source Code Version 5.00 copyright (c) 1995, AudioCodes, DSP Group, France Telecom, Universite de Sherbrooke. All rights reserved.*/#include <stdio.h>#include <stdlib.h>#include "typedef.h"#include "cst_lbc.h"#include "tab_lbc.h"#include "util_lbc.h"#include "basop.h"#include "lsp.h"#include "lpc.h"#include "util_cng.h"#include "coder_pc.h"/* Declaration of local functions */static void ComputePastAvFilter(Word16 *Coeff);static void CalcRC(Word16 *Coeff, Word16 *RC, Word16 *shRC);static Flag LpcDiff(Word16 *RC, Word16 shRC, Word16 *Acf, Word16 alpha);/* Global Variables */CODCNGDEF CodCng;/***** Function: Init_Cod_Cng()**** Description: Initialize Cod_Cng static variables**** Links to text:**** Arguments: None**** Outputs: None**** Return value: None***/void Init_Cod_Cng(void){ int i; CodCng.CurGain = 0; for(i=0; i< SizAcf; i++) CodCng.Acf[i] = 0; for(i=0; i <= NbAvAcf; i++) CodCng.ShAcf[i] = 40; for(i=0; i < LpcOrder; i++) CodCng.SidLpc[i] = 0; CodCng.PastFtyp = 1; CodCng.RandSeed = 12345; return;}/***** Function: Cod_Cng()**** Description: Computes Ftyp for inactive frames** 0 : for untransmitted frames** 2 : for SID frames** Computes current frame excitation** Computes current frame LSPs** Computes the coded parameters of SID frames**** Links to text:**** Arguments:**** Word16 *DataExc Current frame synthetic excitation** Word16 *Ftyp Characterizes the frame type for CNG** LINEDEF *Line Quantized parameters (used for SID frames)** Word16 *QntLpc Interpolated frame LPC coefficients**** Outputs:**** Word16 *DataExc** Word16 *Ftyp** LINEDEF *Line** Word16 *QntLpc**** Return value: None***/void Cod_Cng(Word16 *DataExc, Word16 *Ftyp, LINEDEF *Line, Word16 *QntLpc){ Word16 curCoeff[LpcOrder]; Word16 curQGain; Word16 temp; int i; /* * Update Ener */ for(i=NbAvGain-1; i>=1; i--) { CodCng.Ener[i] = CodCng.Ener[i-1]; } /* * Compute LPC filter of present frame */ CodCng.Ener[0] = Durbin(curCoeff, &CodCng.Acf[1], CodCng.Acf[0], &temp); /* * if first frame of silence => SID frame */ if(CodCng.PastFtyp == 1) { *Ftyp = 2; CodCng.NbEner = 1; curQGain = Qua_SidGain(CodCng.Ener, CodCng.ShAcf, CodCng.NbEner); } else { CodCng.NbEner++; if(CodCng.NbEner > NbAvGain) CodCng.NbEner = NbAvGain; curQGain = Qua_SidGain(CodCng.Ener, CodCng.ShAcf, CodCng.NbEner); /* * Compute stationarity of current filter * versus reference filter */ if(LpcDiff(CodCng.RC, CodCng.ShRC, CodCng.Acf, *CodCng.Ener) == 0) { /* transmit SID frame */ *Ftyp = 2; } else { temp = abs_s(sub(curQGain, CodCng.IRef)); if(temp > ThreshGain) { *Ftyp = 2; } else { /* no transmission */ *Ftyp = 0; } } } /* * If SID frame : Compute SID filter */ if(*Ftyp == 2) { /* * Evaluates local stationnarity : * Computes difference between current filter and past average filter * if signal not locally stationary SID filter = current filter * else SID filter = past average filter */ /* Compute past average filter */ ComputePastAvFilter(CodCng.SidLpc) ; /* If adaptation enabled, fill noise filter */ if ( !VadStat.Aen ) { for(i=0; i<LpcOrder; i++) VadStat.NLpc[i] = CodCng.SidLpc[i]; } /* Compute autocorr. of past average filter coefficients */ CalcRC(CodCng.SidLpc , CodCng.RC, &CodCng.ShRC); if(LpcDiff(CodCng.RC, CodCng.ShRC, CodCng.Acf, *CodCng.Ener) == 0){ for(i=0; i<LpcOrder; i++) { CodCng.SidLpc[i] = curCoeff[i]; } CalcRC(curCoeff, CodCng.RC, &CodCng.ShRC); } /* * Compute SID frame codes */ /* Compute LspSid */ AtoLsp(CodCng.LspSid, CodCng.SidLpc, CodStat.PrevLsp); Line->LspId = Lsp_Qnt(CodCng.LspSid, CodStat.PrevLsp); Lsp_Inq(CodCng.LspSid, CodStat.PrevLsp, Line->LspId, 0); Line->Sfs[0].Mamp = curQGain; CodCng.IRef = curQGain; CodCng.SidGain = Dec_SidGain(CodCng.IRef); } /* end of Ftyp=2 case (SID frame) */ /* * Compute new excitation */ if(CodCng.PastFtyp == 1) { CodCng.CurGain = CodCng.SidGain; } else { CodCng.CurGain = extract_h(L_add( L_mult(CodCng.CurGain,0x7000), L_mult(CodCng.SidGain,0x1000) ) ) ; } Calc_Exc_Rand(CodCng.CurGain, CodStat.PrevExc, DataExc, &CodCng.RandSeed, Line); /* * Interpolate LSPs and update PrevLsp */ Lsp_Int(QntLpc, CodCng.LspSid, CodStat.PrevLsp); for (i=0; i < LpcOrder ; i++) { CodStat.PrevLsp[i] = CodCng.LspSid[i]; } /* * Output & save frame type info */ CodCng.PastFtyp = *Ftyp; return;}/***** Function: Update_Acf()**** Description: Computes & Stores sums of subframe-acfs**** Links to text:**** Arguments:**** Word16 *Acf_sf sets of subframes Acfs of current frame** Word16 *ShAcf_sf corresponding scaling factors**** Output : None**** Return value: None***/void Update_Acf(Word16 *Acf_sf, Word16 *ShAcf_sf){ int i, i_subfr; Word16 *ptr1, *ptr2; Word32 L_temp[LpcOrderP1]; Word16 sh1, temp; Word32 L_acc0; /* Update Acf and ShAcf */ ptr2 = CodCng.Acf + SizAcf; ptr1 = ptr2 - LpcOrderP1; for(i=LpcOrderP1; i<SizAcf; i++) *(--ptr2) = *(--ptr1); for(i=NbAvAcf; i>=1; i--) CodCng.ShAcf[i] = CodCng.ShAcf[i-1]; /* Search ShAcf_sf min for current frame */ sh1 = ShAcf_sf[0]; for(i_subfr=1; i_subfr<SubFrames; i_subfr++) { if(ShAcf_sf[i_subfr] < sh1) sh1 = ShAcf_sf[i_subfr]; } sh1 = add(sh1, 14); /* 2 bits of margin */ /* Compute current sum of acfs */ for(i=0; i<= LpcOrder; i++) L_temp[i] = 0; ptr2 = Acf_sf; for(i_subfr=0; i_subfr<SubFrames; i_subfr++) { temp = sub(sh1, ShAcf_sf[i_subfr]); for(i=0; i <= LpcOrder; i++) { L_acc0 = L_deposit_l(*ptr2++); L_acc0 = L_shl(L_acc0, temp); /* shift right if temp<0 */ L_temp[i] = L_add(L_temp[i], L_acc0); } } /* Normalize */ temp = norm_l(L_temp[0]); temp = sub(16, temp); if(temp < 0) temp = 0; for(i=0; i <= LpcOrder; i++) { CodCng.Acf[i] = extract_l(L_shr(L_temp[i],temp)); } CodCng.ShAcf[0] = sub(sh1, temp); return;}/***** Function: ComputePastAvFilter()**** Description: Computes past average filter**** Links to text:**** Argument:**** Word16 *Coeff set of LPC coefficients**** Output:**** Word16 *Coeff**** Return value: None***/void ComputePastAvFilter(Word16 *Coeff){ int i, j; Word16 *ptr_Acf; Word32 L_sumAcf[LpcOrderP1]; Word16 Corr[LpcOrder], Err; Word16 sh1, temp; Word32 L_acc0; /* Search ShAcf min */ sh1 = CodCng.ShAcf[1]; for(i=2; i <= NbAvAcf; i ++) { temp = CodCng.ShAcf[i]; if(temp < sh1) sh1 = temp; } sh1 = add(sh1, 14); /* 2 bits of margin : NbAvAcf <= 4 */ /* Compute sum of NbAvAcf frame-Acfs */ for(j=0; j <= LpcOrder; j++) L_sumAcf[j] = 0; ptr_Acf = CodCng.Acf + LpcOrderP1; for(i=1; i <= NbAvAcf; i ++) { temp = sub(sh1, CodCng.ShAcf[i]); for(j=0; j <= LpcOrder; j++) { L_acc0 = L_deposit_l(*ptr_Acf++); L_acc0 = L_shl(L_acc0, temp); /* shift right if temp<0 */ L_sumAcf[j] = L_add(L_sumAcf[j], L_acc0); } } /* Normalize */ temp = norm_l(L_sumAcf[0]); temp = sub(16, temp); if(temp < 0) temp = 0; Err = extract_l(L_shr(L_sumAcf[0],temp)); for(i=1; i<LpcOrderP1; i++) { Corr[i-1] = extract_l(L_shr(L_sumAcf[i],temp)); } Durbin(Coeff, Corr, Err, &temp); return;}/***** Function: CalcRC()**** Description: Computes function derived from** the autocorrelation of LPC coefficients** used for Itakura distance**** Links to text:**** Arguments :**** Word16 *Coeff set of LPC coefficients** Word16 *RC derived from LPC coefficients autocorrelation** Word16 *ShRC corresponding scaling factor**** Outputs :**** Word16 *RC** Word16 *ShRC**** Return value: None***/void CalcRC(Word16 *Coeff, Word16 *RC, Word16 *ShRC){ int i, j; Word16 sh1; Word32 L_acc; L_acc = 0L; for(j=0; j<LpcOrder; j++) { L_acc = L_mac(L_acc, Coeff[j], Coeff[j]); } L_acc = L_shr(L_acc, 1); L_acc = L_add(L_acc, 0x04000000L); /* 1 << 2 * Lpc_justif. */ sh1 = norm_l(L_acc) - (Word16)2; /* 1 bit because of x2 in RC[i], i> 0*/ /* & 1 bit margin for Itakura distance */ L_acc = L_shl(L_acc, sh1); /* shift right if < 0 */ RC[0] = round(L_acc); for(i=1; i<=LpcOrder; i++) { L_acc = L_mult( (Word16) 0xE000, Coeff[i-1]); /* - (1 << Lpc_justif.) */ for(j=0; j<LpcOrder-i; j++) { L_acc = L_mac(L_acc, Coeff[j], Coeff[j+i]); } L_acc = L_shl(L_acc, sh1); RC[i] = round(L_acc); } *ShRC = sh1; return;}/***** Function: LpcDiff()**** Description: Comparison of two filters** using Itakura distance** 1st filter : defined by *ptrAcf** 2nd filter : defined by *RC** the autocorrelation of LPC coefficients** used for Itakura distance**** Links to text:**** Arguments :**** Word16 *RC derived from LPC coefficients autocorrelation** Word16 ShRC corresponding scaling factor** Word16 *ptrAcf pointer on signal autocorrelation function** Word16 alpha residual energy in LPC analysis using *ptrAcf**** Output: None**** Return value: flag = 1 if similar filters** flag = 0 if different filters***/Flag LpcDiff(Word16 *RC, Word16 ShRC, Word16 *ptrAcf, Word16 alpha){ Word32 L_temp0, L_temp1; Word16 temp; int i; Flag diff; L_temp0 = 0L; for(i=0; i<=LpcOrder; i++) { temp = shr(ptrAcf[i], 2); /* + 2 margin bits */ L_temp0 = L_mac(L_temp0, RC[i], temp); } temp = mult_r(alpha, FracThresh); L_temp1 = L_add((Word32)temp, (Word32)alpha); temp = add(ShRC, 9); /* 9 = Lpc_justif. * 2 - 15 - 2 */ L_temp1 = L_shl(L_temp1, temp); if(L_temp0 < L_temp1) diff = 1; else diff = 0; return(diff);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -