⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 encoder.cpp

📁 G711语音压缩源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
            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 + -