?? encoder.cpp
字號:
* versus reference filter
*/
if (!LpcDiff(CodCng.RC, CodCng.Acf, *CodCng.Ener)) {
*Ftyp = 2; /* transmit SID frame */
}
else {
i = ::abs((int)(curQGain - CodCng.IRef));
if (i > 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);
if (!LpcDiff(CodCng.RC, CodCng.Acf, *CodCng.Ener)) {
for (i=0; i<LpcOrder; i++) {
CodCng.SidLpc[i] = curCoeff[i];
}
CalcRC(curCoeff, CodCng.RC);
}
/*
* 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 = (float)0.875 * CodCng.CurGain + (float)0.125 * CodCng.SidGain;
}
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;
}
BOOL CLanAudioEncoder::Comp_Vad(float *Dpnt)
{
int i, j, bexp;
float Acc0, Frac, Thresh, Enr;
float Temp;
int Tm1, Tm2;
short Minp;
BOOL VadState = TRUE;
static float ScfTab[11] = {
(float) 9170.0,
(float) 9170.0,
(float) 9170.0,
(float) 9170.0,
(float) 10289.0,
(float) 11544.0,
(float) 12953.0,
(float) 14533.0,
(float) 16306.0,
(float) 18296.0,
(float) 20529.0
};
if ( !UseVx )
return VadState ;
/* Find Minimum pitch period */
Minp = (short) PitchMax ;
for ( i = 0 ; i < 4 ; i ++ ) {
if ( Minp > VadStat.Polp[i] )
Minp = VadStat.Polp[i] ;
}
/* Check that all are multiplies of the minimum */
Tm2 = 0 ;
for ( i = 0 ; i < 4 ; i ++ ) {
Tm1 = Minp ;
for ( j = 0 ; j < 8 ; j ++ ) {
if (abs((int)(Tm1 - VadStat.Polp[i])) <= 3)
Tm2++ ;
Tm1 += Minp;
}
}
/* Update adaptation enable counter if not periodic and not sine */
if ( (Tm2 == 4) || (CodStat.SinDet < 0) )
VadStat.Aen += 2 ;
else
VadStat.Aen -- ;
/* Clip it */
if ( VadStat.Aen > 6 )
VadStat.Aen = 6 ;
if ( VadStat.Aen < 0 )
VadStat.Aen = 0 ;
/* Inverse filter the data */
Enr = (float) 0.0;
for ( i = SubFrLen ; i < Frame ; i ++ ) {
Acc0 = Dpnt[i];
for ( j = 0 ; j < LpcOrder ; j ++ )
Acc0 -= Dpnt[i-j-1] * VadStat.NLpc[j];
Enr += Acc0 * Acc0;
}
/* Scale the rezidual energy.
* Multiplication by 0.5 yields a value approximately equal
* to the corresponding computation in the fixed point code.
* Thus the same bounds, computations and thresholds as in the
* fixed point code can be used below.
*/
Enr = (float)0.5 * (Enr / (float)180.0);
/* Clip noise level in any case */
if ( VadStat.Nlev > VadStat.Penr ) {
VadStat.Nlev = (float)0.25 * VadStat.Nlev + (float)0.75 * VadStat.Penr;
}
/* Update the noise level, if adaptation is enabled */
if ( !VadStat.Aen ) {
VadStat.Nlev *= (float)33.0 / (float)32.0;
}
/* Decay Nlev by small amount */
else {
VadStat.Nlev *= (float)2047.0 / (float)2048.0;
}
/* Update previous energy */
VadStat.Penr = Enr;
/* CLip Noise Level */
if (VadStat.Nlev < (float) 128.0)
VadStat.Nlev = (float) 128.0;
if (VadStat.Nlev > (float) 131071.0)
VadStat.Nlev = (float) 131071.0;
/* Compute the threshold */
Frac = (float) frexp(VadStat.Nlev, &bexp);
/* VadStat.Nlev = Frac x 2**bexp, where Frac = 0.1bbbbbb...., binary.
* Isolate the 6 fractional bits 'b', Temp = 0.bbbbbb.
*/
Temp = ((float)floor(Frac * (float)128.0) / (float)64.0) - (float)1.0;
Temp = ((float)1.0 - Temp) * ScfTab[18 - bexp] + Temp * ScfTab[17 - bexp];
Thresh = (Temp * VadStat.Nlev) / (float)4096.0;
/* Compare with the threshold */
if (Thresh > Enr)
VadState = FALSE ;
/* Do the various counters */
if ( VadState ) {
VadStat.Vcnt ++ ;
VadStat.Hcnt ++ ;
}
else {
VadStat.Vcnt -- ;
if ( VadStat.Vcnt < 0 )
VadStat.Vcnt = 0 ;
}
if ( VadStat.Vcnt >= 2 ) {
VadStat.Hcnt = 6 ;
if (VadStat.Vcnt >= 3)
VadStat.Vcnt = 3;
}
if ( VadStat.Hcnt ) {
VadState = TRUE ;
if ( VadStat.Vcnt == 0 )
VadStat.Hcnt -- ;
}
/* Update Periodicy detector */
VadStat.Polp[0] = VadStat.Polp[2] ;
VadStat.Polp[1] = VadStat.Polp[3] ;
return VadState ;
}
/*
**
** Function: Update_Acf()
**
** Description: Computes & Stores sums of subframe-acfs
**
** Links to text:
**
** Arguments:
**
** float *Acf_sf sets of subframes Acfs of current frame
**
** Output : None
**
** Return value: None
**
*/
void CLanAudioEncoder::Update_Acf(float *Acf_sf)
{
int i, i_subfr;
float *ptr1, *ptr2;
/* Update Acf */
ptr2 = CodCng.Acf + SizAcf;
ptr1 = ptr2 - LpcOrderP1;
for (i=LpcOrderP1; i<SizAcf; i++)
*(--ptr2) = *(--ptr1);
/* Compute current sum of acfs */
for (i=0; i<= LpcOrder; i++)
CodCng.Acf[i] = (float) 0.0;
ptr2 = Acf_sf;
for (i_subfr=0; i_subfr<SubFrames; i_subfr++) {
for (i=0; i <= LpcOrder; i++) {
CodCng.Acf[i] += *ptr2++;
}
}
}
/*
**
** Function: ComputePastAvFilter()
**
** Description: Computes past average filter
**
** Links to text:
**
** Argument:
**
** float *Coeff set of LPC coefficients
**
** Output:
**
** float *Coeff
**
** Return value: None
**
*/
void CLanAudioEncoder::ComputePastAvFilter(float *Coeff)
{
int i, j;
float *ptr_Acf;
float sumAcf[LpcOrderP1];
float temp;
/* Compute sum of NbAvAcf frame-Acfs */
for (j=0; j <= LpcOrder; j++)
sumAcf[j] = (float) 0.0;
ptr_Acf = CodCng.Acf + LpcOrderP1;
for (i=1; i <= NbAvAcf; i++) {
for (j=0; j <= LpcOrder; j++) {
sumAcf[j] += *ptr_Acf++;
}
}
Durbin(Coeff, &sumAcf[1], sumAcf[0], &temp);
return;
}
/*
**
** Function: CalcRC()
**
** Description: Computes function derived from
** the autocorrelation of LPC coefficients
** used for Itakura distance
**
** Links to text:
**
** Arguments :
**
** float *Coeff set of LPC coefficients
** float *RC derived from LPC coefficients autocorrelation
**
** Outputs :
**
** float *RC
**
** Return value: None
**
*/
void CLanAudioEncoder::CalcRC(float *Coeff, float *RC)
{
int i, j;
float temp;
// temp = (float) 1.0 + DotProd(Coeff, Coeff, LpcOrder);
temp = (float) 1.0 + DotProd10s(Coeff, Coeff);
RC[0] = temp;
for (i=1; i<=LpcOrder; i++) {
temp = -Coeff[i-1];
for (j=0; j<LpcOrder-i; j++) {
temp += Coeff[j] * Coeff[j+i];
}
RC[i] = (float)2.0 * temp;
}
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 :
**
** float *RC derived from LPC coefficients autocorrelation
** float *ptrAcf pointer on signal autocorrelation function
** float alpha residual energy in LPC analysis using *ptrAcf
**
** Output: None
**
** Return value: flag = 1 if similar filters
** flag = 0 if different filters
**
*/
BOOL CLanAudioEncoder::LpcDiff(float *RC, float *ptrAcf, float alpha)
{
float temp0, temp1;
BOOL diff;
temp0 = DotProd(RC, ptrAcf, LpcOrderP1);
temp1 = alpha * FracThreshP1;
if (temp0 < temp1)
diff = TRUE;
else
diff = FALSE;
return diff;
}
/*
**
** Function: Rem_Dc()
**
** Description: High-pass filtering
**
** Links to text: Section 2.3
**
** Arguments:
**
** float *Dpnt
**
** Inputs:
**
** CodStat.HpfZdl FIR filter memory from previous frame (1 word)
** CodStat.HpfPdl IIR filter memory from previous frame (1 word)
**
** Outputs:
**
** float *Dpnt
**
** Return value: None
**
*/
void CLanAudioEncoder::Rem_Dc(float *Dpnt)
{
int i;
float acc0;
if (UseHp)
{
for (i=0; i < Frame; i++)
{
acc0 = Dpnt[i] - CodStat.HpfZdl;
CodStat.HpfZdl = Dpnt[i];
Dpnt[i] = CodStat.HpfPdl =
acc0 + CodStat.HpfPdl*((float)127.0/(float)128.0);
}
}
}
/*
**
** Function: Line_Pack()
**
** Description: Packing coded parameters in bitstream of 16-bit words
**
** Links to text: Section 4
**
** Arguments:
**
** LINEDEF *Line Coded parameters for a frame
** char *Vout bitstream chars
** short Ftyp Voice Activity Indicator
**
** Outputs:
**
** short *Vout
**
** Return value: None
**
*/
void CLanAudioEncoder::Line_Pack(LINEDEF *Line, char *Vout, short Ftyp)
{
int i;
int BitCount;
short BitStream[192];
short *Bsp = BitStream;
int Temp;
/* Clear the output vector */
for ( i = 0 ; i < 24 ; i ++ )
Vout[i] = 0 ;
/*
* Add the coder rate info and frame type info to the 2 msb
* of the first word of the frame.
* The signaling is as follows:
* Ftyp WrkRate => X1X0
* 1 Rate63 00 : High Rate
* 1 Rate53 01 : Low Rate
* 2 x 10 : Silence Insertion Descriptor frame
* 0 x 11 : Used only for simulation of
* untransmitted silence frames
*/
switch (Ftyp) {
case 0 : {
Temp = 0x00000003L;
break;
}
case 2 : {
Temp = 0x00000002L;
break;
}
default : {
if ( WrkRate == Rate63 )
Temp = 0x00000000L;
else
Temp = 0x00000001L;
break;
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -