?? encoder.cpp
字號:
for (j = 0; j < i; j++)
//DotProd10 *lPnt++ = DotProd(FltBuf[i], FltBuf[j], SubFrLen);
*lPnt++ = DotProd10(FltBuf[i], FltBuf[j], SubFrLen);
}
/* Test potential error */
Lag1 = Olp - Pstep;
Lag2 = Olp - Pstep + Hb - 1;
off_filt = Test_Err(Lag1, Lag2);
Bound[0] = NbFilt085_min + (off_filt << 2);
if (Bound[0] > NbFilt085)
Bound[0] = NbFilt085;
Bound[1] = NbFilt170_min + (off_filt << 3);
if (Bound[1] > NbFilt170)
Bound[1] = NbFilt170;
Max = (float)0.0;
for (k=0; k < Hb; k++)
{
/* Select Quantization table */
l = 0;
if (WrkRate == Rate63)
{
if ((Sfc & 1) == 0)
{
if (Olp-Pstep+k >= SubFrLen-2)
l = 1;
}
else
{
if (Olp >= SubFrLen-2)
l = 1;
}
}
else
l = 1;
/* Search for maximum */
sPnt = AcbkGainTablePtr[l]+20;
for (i=1; i < Bound[l]; i+=2)
{
//DotProd20s Acc0 = DotProd(&CorVct[k*20],sPnt,20);
Acc0 = DotProd20s(&CorVct[k*20],sPnt);
sPnt += 40;
if (Acc0 > Max)
{
Max = Acc0;
Gid = i;
Lid = k;
}
}
}
/* Modify Olp for even sub frames */
if ((Sfc & 1) == 0)
{
Olp = Olp - Pstep + Lid;
Lid = Pstep;
}
/* Save Lag, Gain and Olp */
(*Line).Sfs[Sfc].AcLg = Lid;
(*Line).Sfs[Sfc].AcGn = Gid;
(*Line).Olp[Sfc>>1] = Olp;
/* Decode the Acbk contribution and subtract it */
Decod_Acbk(RezBuf, PrevExc, Olp, Lid, Gid);
for (i=0; i < SubFrLen; i++)
{
Acc0 = Tv[i]-RezBuf[i];
for (j=0; j < i; j++)
Acc0 -= RezBuf[j]*ImpResp[i-j];
Tv[i] = Acc0;
}
}
/*
**
** Function: Decod_Acbk()
**
** Description: Computes the adaptive codebook contribution from the previous
** excitation vector.
** With the gain index, the closed loop pitch lag, the jitter
** which when added to this pitch lag gives the actual closed
** loop value, and after having selected the proper codebook,
** the pitch contribution is reconstructed using the previous
** excitation buffer.
**
** Links to text: Sections 2.14, 2.18 & 3.4
**
** Arguments:
**
** float *Tv Reconstructed excitation vector
** float *PrevExc Previous excitation vector
** int Olp closed-loop pitch period
** int Lid Jitter around pitch period
** int Gid Gain vector index in 5- dimensional
** adaptive gain vector codebook
**
** Outputs:
**
** float *Tv Reconstructed excitation vector
**
** Return value: None
**
*/
void CLanAudioEncoder::Decod_Acbk(float *Tv, float *PrevExc, int Olp, int Lid, int Gid)
{
int i;
float RezBuf[SubFrLen+ClPitchOrd-1];
float *sPnt;
Get_Rez(RezBuf, PrevExc, (Olp + Lid) - Pstep);
i = 0;
if (WrkRate == Rate63)
{
if (Olp >= (SubFrLen-2))
i++;
}
else
i=1;
sPnt = AcbkGainTablePtr[i] + Gid*20;
/* Compute output vector */
for (i=0; i < SubFrLen; i++)
//DotProd5s Tv[i] = DotProd(&RezBuf[i], sPnt, ClPitchOrd);
Tv[i] = DotProd5s(&RezBuf[i], sPnt);
}
/*
**
** Function: Calc_Exc_Rand()
**
** Description: Computation of random excitation for inactive frames:
** Adaptive codebook entry selected randomly
** Higher rate innovation pattern selected randomly
** Computes innovation gain to match curGain
**
** Links to text:
**
** Arguments:
**
** float curGain current average gain to match
** float *PrevExc previous/current excitation (updated)
** float *DataExc current frame excitation
** short *nRandom random generator status (input/output)
** LINEDEF *Line
**
** Outputs:
**
** float *PrevExc
** float *DataExc
** short *nRandom
** LINEDEF *Line
**
** Return value: None
**
*/
void CLanAudioEncoder::Calc_Exc_Rand(float curGain, float *PrevExc, float *DataExc,
short *nRandom, LINEDEF *Line)
{
int i, i_subfr, iblk;
short temp16;
short j;
short TabPos[2*NbPulsBlk], *ptr_TabPos;
float TabSign[2*NbPulsBlk], *ptr_TabSign;
short *ptr1;
float *curExc;
float x1, x2, ener_ltp, inter_exc, delta, b0, c;
short tmp[SubFrLen/Sgrid];
short offset[SubFrames];
/*
* generate LTP codes
*/
Line->Olp[0] = random_number(21, nRandom) + 123;
Line->Olp[1] = random_number(21, nRandom) + 123;
for (i_subfr=0; i_subfr<SubFrames; i_subfr++) { /* in [1, NbFilt] */
Line->Sfs[i_subfr].AcGn = random_number(NbFilt, nRandom) + (short)1;
}
Line->Sfs[0].AcLg = 1;
Line->Sfs[1].AcLg = 0;
Line->Sfs[2].AcLg = 1;
Line->Sfs[3].AcLg = 3;
/*
* Random innovation :
* Selection of the grids, signs and pulse positions
*/
/* Signs and Grids */
ptr_TabSign = TabSign;
ptr1 = offset;
for (iblk=0; iblk<SubFrames/2; iblk++) {
temp16 = random_number((short) (1 << (NbPulsBlk+2)), nRandom);
*ptr1++ = (short) (temp16 & 0x0001);
temp16 >>= 1;
*ptr1++ = (short) (SubFrLen + (temp16 & 0x0001));
for (i=0; i<NbPulsBlk; i++) {
temp16 >>= 1;
*ptr_TabSign++= (float) 2. * (float)(temp16 & 0x0001) - (float) 1.;
}
}
/* Positions */
ptr_TabPos = TabPos;
for (i_subfr=0; i_subfr<SubFrames; i_subfr++) {
for (i=0; i<(SubFrLen/Sgrid); i++)
tmp[i] = (short) i;
temp16 = (SubFrLen/Sgrid);
for (i=0; i<Nb_puls[i_subfr]; i++) {
j = random_number(temp16, nRandom);
*ptr_TabPos++ = (short) (2 * tmp[(int)j] + offset[i_subfr]);
temp16--;
tmp[(int)j] = tmp[(int)temp16];
}
}
/*
* Compute fixed codebook gains
*/
ptr_TabPos = TabPos;
ptr_TabSign = TabSign;
curExc = DataExc;
i_subfr = 0;
for (iblk=0; iblk<SubFrames/2; iblk++) {
/* decode LTP only */
Decod_Acbk(curExc, &PrevExc[0], Line->Olp[iblk],
Line->Sfs[i_subfr].AcLg, Line->Sfs[i_subfr].AcGn);
Decod_Acbk(&curExc[SubFrLen], &PrevExc[SubFrLen], Line->Olp[iblk],
Line->Sfs[i_subfr+1].AcLg, Line->Sfs[i_subfr+1].AcGn);
// ener_ltp = DotProd(curExc, curExc, SubFrLenD);
ener_ltp = DotProd10(curExc, curExc, SubFrLenD);
inter_exc = (float) 0.;
for (i=0; i<NbPulsBlk; i++) {
inter_exc += curExc[(int)ptr_TabPos[i]] * ptr_TabSign[i];
}
c = (ener_ltp - curGain * curGain * (float)SubFrLenD) * InvNbPulsBlk;
/*
* Solve EQ(X) = X**2 + 2 b0 X + c
*/
b0 = inter_exc * InvNbPulsBlk;
delta = b0 * b0 - c;
/* Case delta <= 0 */
if (delta <= (float) 0.) {
x1 = - b0;
}
/* Case delta > 0 */
else {
delta = (float) sqrt(delta);
x1 = - b0 + delta;
x2 = b0 + delta;
if (fabs(x2) < fabs(x1))
x1 = - x2;
}
/* Update DataExc */
if (x1 > Gexc_Max)
x1 = Gexc_Max;
if (x1 < -Gexc_Max)
x1 = -Gexc_Max;
for (i=0; i<NbPulsBlk; i++) {
j = *ptr_TabPos++;
curExc[(int)j] += (x1 * (*ptr_TabSign++));
}
for (i=0; i<SubFrLenD; i++) {
if (curExc[i] > (float) 32766.5)
curExc[i] = (float) 32767.0;
else if (curExc[i] < (float) -32767.5)
curExc[i] = (float) -32768.0;
}
/* update PrevExc */
for (i=SubFrLenD; i<PitchMax; i++)
PrevExc[i-SubFrLenD] = PrevExc[i];
for (i=0; i<SubFrLenD; i++)
PrevExc[i+PitchMax-SubFrLenD] = curExc[i];
curExc += SubFrLenD;
i_subfr += 2;
} /* end of loop on LTP blocks */
return;
}
/*
**
** Function: Comp_Lpc()
**
** Description: Computes the tenth-order LPC filters for an
** entire frame. For each subframe, a
** Hamming-windowed block of 180 samples,
** centered around the subframe, is used to
** compute eleven autocorrelation coefficients.
** The Levinson-Durbin algorithm then generates
** the LPC coefficients. This function requires
** a look-ahead of one subframe, and hence
** introduces a 7.5 ms encoding delay.
**
** Links to text: Section 2.4
**
** Arguments:
**
** float *UnqLpc Empty Buffer
** float PrevDat[] Previous 2 subframes of samples (120 words)
** float DataBuff[] Current frame of samples (240 words)
**
** Outputs:
**
**
** float UnqLpc[] LPC coefficients for entire frame (40 words)
**
** Return value: None
**
*/
void CLanAudioEncoder::Comp_Lpc(float *UnqLpc, float *PrevDat, float *DataBuff)
{
int i,j,k;
float Dpnt[Frame+LpcFrame-SubFrLen];
float Vect[LpcFrame];
float Acf_sf[LpcOrderP1*SubFrames];
float *curAcf;
float Pk2;
/*
* Generate a buffer of 360 samples. This consists of 120 samples
* from the previous frame and 240 samples from the current frame.
*/
for (i=0; i < LpcFrame-SubFrLen; i++)
Dpnt[i] = PrevDat[i];
for (i=0; i < Frame; i++)
Dpnt[i+LpcFrame-SubFrLen] = DataBuff[i];
/*
* Repeat for all subframes
*/
curAcf = Acf_sf;
for (k=0; k < SubFrames; k++)
{
/* Apply the Hamming window */
for (i = 0; i < LpcFrame; i++)
Vect[i] = Dpnt[k*SubFrLen+i]*HammingWindowTable[i];
/* Compute the autocorrelation coefficients */
// curAcf[0] = DotProd(Vect, Vect, LpcFrame)/(LpcFrame*LpcFrame);
curAcf[0] = DotProd10(Vect, Vect, LpcFrame)/(LpcFrame*LpcFrame);
/* Do Ridge regression */
curAcf[0] *= ((float)1025.0/(float)1024.0);
if (curAcf[0] == (float)0.0) {
for (i = 1; i <= LpcOrder; i++)
curAcf[i] = (float) 0.0;
}
else {
for (i = 1; i <= LpcOrder; i++)
curAcf[i] = DotProd(Vect, &Vect[i], LpcFrame-i)
/ (LpcFrame*LpcFrame) * BinomialWindowTable[i-1];
}
/*
* Apply the Levinson-Durbin algorithm to generate the LPC
* coefficients
*/
Durbin(&UnqLpc[k*LpcOrder], &curAcf[1], curAcf[0], &Pk2);
CodStat.SinDet <<= 1;
if (Pk2 > (float) 0.95) {
CodStat.SinDet++;
}
curAcf += LpcOrderP1;
}
/* Update sine detector */
CodStat.SinDet &= 0x7fff ;
j = CodStat.SinDet ;
k = 0 ;
for ( i = 0 ; i < 15 ; i ++ ) {
k += j & 1 ;
j >>= 1 ;
}
if ( k >= 14 )
CodStat.SinDet |= 0x8000 ;
Update_Acf(Acf_sf);
}
/*
**
** Function: Error_Wght()
**
** Description: Implements the formant perceptual weighting
** filter for a frame. This filter effectively
** deemphasizes the formant frequencies in the
** error signal.
**
** Links to text: Section 2.8
**
** Arguments:
**
** float Dpnt[] Highpass filtered speech x[n] (240 words)
** float PerLpc[] Filter coefficients (80 words)
**
** Inputs:
**
** CodStat.WghtFirDl[] FIR filter memory from previous frame (10 words)
** CodStat.WghtIirDl[] IIR filter memory from previous frame (10 words)
**
**
** Outputs:
**
** float Dpnt[] Weighted speech f[n] (240 words)
**
** Return value: None
**
*/
void CLanAudioEncoder::Error_Wght(float *Dpnt, float *PerLpc)
{
int i,j,k;
float Acc0;
for (k=0; k < SubFrames; k++)
{
for (i=0; i < SubFrLen; i++)
{
/* FIR part */
// Acc0 = *Dpnt - DotProd(PerLpc,CodStat.WghtFirDl,LpcOrder);
Acc0 = *Dpnt - DotProd10s(PerLpc,CodStat.WghtFirDl);
for (j=LpcOrder-1; j > 0; j --)
CodStat.WghtFirDl[j] = CodStat.WghtFirDl[j-1];
CodStat.WghtFirDl[0] = *Dpnt;
/* IIR part */
// Acc0 += DotProd(&PerLpc[LpcOrder],CodStat.WghtIirDl,LpcOrder);
Acc0 += DotProd10s(&PerLpc[LpcOrder],CodStat.WghtIirDl);
for (j = LpcOrder-1; j > 0; j --)
CodStat.WghtIirDl[j] = CodStat.WghtIirDl[j-1];
*Dpnt++ = CodStat.WghtIirDl[0] = Acc0;
}
PerLpc += 2*LpcOrder;
}
}
/*
**
** Function: Sub_Ring()
**
** Description: Computes the zero-input response of the
** combined formant perceptual weighting filter,
** harmonic noise shaping filter, and synthesis
** filter for a subframe. Subtracts the
** zero-input response from the harmonic noise
** weighted speech vector to produce the target
** speech vector.
**
** Links to text: Section 2.13
*
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -