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

📄 encoder.cpp

📁 G711语音压缩源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
//#include "stdafx.h"

#include <memory.h>
#include <math.h>
#include "LanAudio.h"
#include "Global.h"


unsigned char linear2alaw(_int16	pcm_val);
_int16 alaw2linear(unsigned char  a_val);
unsigned char linear2ulaw(_int16	pcm_val);
_int16 ulaw2linear(unsigned char	u_val);
unsigned char alaw2ulaw(unsigned char	aval);
unsigned char ulaw2alaw(unsigned char	uval);

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CLanAudioEncoder::CLanAudioEncoder(int iBitRate, BOOL bHighPassFilter, BOOL bVad,EAudioCodec nCodec)
{
	UseHp = bHighPassFilter;
	UseVx = bVad;
	WrkRate = iBitRate;
	m_nCodec = nCodec;
	m_bMute = FALSE;

    Init_Coder();

    // Init Comfort Noise Functions 
    Init_Vad();
    Init_Cod_Cng();
///	OutputDebugString("Audio Encoder Inited\n");
}

CLanAudioEncoder::~CLanAudioEncoder()
{
}
int CLanAudioEncoder::EncodeG723(const short * iFrame, char * cCode)
{
	int i, iInfo, iSize;

    if (WrkRate == Rate53) reset_max_time();

	for (i = 0; i < Frame; i ++) DataBuff[i] = (float)iFrame[i];

	Coder(DataBuff, cCode);

    iInfo = cCode[0] & 0x0003;

    /* Check frame type and rate information */
    switch (iInfo) 
	{
        case 0x0002 : {  /* SID frame */
            iSize = 4;
            break;
        }

        case 0x0003 : {  /* untransmitted silence frame */
            iSize = 1;
            break;
        }

        case 0x0001 : {  /* active frame, low rate */
            iSize = 20;
            break;
        }

        default : {      /* active frame, high rate */
            iSize = 24;
        }
    }
	return iSize;
}
int CLanAudioEncoder::EncodeG711(const short* input,unsigned char* code)
{
	const short* org_input = input;
	unsigned char * org_code = code;

	if(m_bMute){
		if(m_nCodec==G711_A)
			for(int i = 0; i < G711_Frame; i++){
				*code = linear2alaw((_int16)0);
				code ++;
			}
		else
			for(int i = 0; i < G711_Frame; i++){
				*code = linear2ulaw((_int16)0);
				code ++;
			}
	}
	else {
		if(m_nCodec==G711_A)
			for(int i = 0; i < G711_Frame; i++){
				*code = linear2alaw(*input);
				input ++;
				code ++;
			}
		else
			for(int i = 0; i < G711_Frame; i++){
				*code = linear2ulaw(*input);
				input ++;
				code ++;
			}
	}
	input = org_input;
	code = org_code;

	return G711_Frame;
}
int CLanAudioEncoder::Encode(const short * iFrame, char * cCode)
{
	switch (m_nCodec){
	case G711_A:
	case G711_U:
		return(EncodeG711(iFrame,(unsigned char *)cCode));
		break;
	case G723:
		return(EncodeG723(iFrame,cCode));
		break;
	default:
		return(0);
		break;
	}
}

/*
**
** Function:        Init_Coder()
**
** Description:     Initializes non-zero state variables
**          for the coder.
**
** Links to text:   Section 2.21
**
** Arguments:       None
**
** Outputs:     None
**
** Return value:    None
**
*/
void  CLanAudioEncoder::Init_Coder(void)
{
    int i;

    /* Initialize encoder data structure with zeros */
    ::memset(&CodStat,0,sizeof(CODSTATDEF));

    /* Initialize the previously decoded LSP vector to the DC vector */

    for (i=0; i < LpcOrder; i++)
        CodStat.PrevLsp[i] = LspDcTable[i];

    /* Initialize the taming procedure */
    for(i=0; i<SizErr; i++)
        CodStat.Err[i] = Err0;

    return;
}

void CLanAudioEncoder::Init_Vad(void)
{
    int i ;

    VadStat.Hcnt = 3 ;
    VadStat.Vcnt = 0 ;
    VadStat.Penr = (float) 1024.0;
    VadStat.Nlev = (float) 1024.0;

    VadStat.Aen = 0;

    VadStat.Polp[0] = 1;
    VadStat.Polp[1] = 1;
    VadStat.Polp[2] = SubFrLen;
    VadStat.Polp[3] = SubFrLen;

    for (i=0; i < LpcOrder; i++)
        VadStat.NLpc[i] = (float)0.0;

}

/*
**
** Function:        Init_Cod_Cng()
**
** Description:     Initialize Cod_Cng static variables
**
** Links to text:
**
** Arguments:       None
**
** Outputs:         None
**
** Return value:    None
**
*/
void CLanAudioEncoder::Init_Cod_Cng(void)
{
    int i;

    CodCng.CurGain = (float)0.0;

    for (i=0; i< SizAcf; i++)
        CodCng.Acf[i] = (float)0.0;

    for (i=0; i < LpcOrder; i++)
        CodCng.SidLpc[i] = (float)0.0;

    CodCng.PastFtyp = 1;

    CodCng.RandSeed = 12345;

    return;
}


void CLanAudioEncoder::reset_max_time(void)
{
    extra = 120;
    return;
}

/*
**
** Function:        Coder()
**
** Description:     Implements G.723.1 dual-rate coder for    a frame
**          of speech
**
** Links to text:   Section 2
**
** Arguments:
**
**  float  DataBuff[]   frame (240 samples)
**
** Outputs:
**
**  char   Vout[]       Encoded frame (0/4/20/24 bytes)
**
** Return value:
**
**  BOOL            Always TRUE
**
*/
BOOL  CLanAudioEncoder::Coder(float *DataBuff, char *Vout)
{
    int i,j;

    /*
     *  Local variables
     */
    float   UnqLpc[SubFrames*LpcOrder];
    float   QntLpc[SubFrames*LpcOrder];
    float   PerLpc[2*SubFrames*LpcOrder];

    float   LspVect[LpcOrder];
    LINEDEF Line;
    PWDEF   Pw[SubFrames];

    float   ImpResp[SubFrLen];
    float   *Dpnt;

    short  Ftyp = 1;

    /*  Coder Start  */

    Line.Crc = 0;

    Rem_Dc(DataBuff);

    /* Compute the Unquantized Lpc set for whole frame */
    Comp_Lpc(UnqLpc, CodStat.PrevDat, DataBuff);

    /* Convert to Lsp */
    AtoLsp(LspVect, &UnqLpc[LpcOrder*(SubFrames-1)], CodStat.PrevLsp);

    /* Compute the Vad */
    Ftyp = Comp_Vad(DataBuff) ? 1 : 0;

    /* VQ Lsp vector */
    Line.LspId = Lsp_Qnt(LspVect, CodStat.PrevLsp);

    Mem_Shift(CodStat.PrevDat, DataBuff);

    /* Compute Percetual filter Lpc coefficeints */
    Wght_Lpc(PerLpc, UnqLpc);

    /* Apply the perceptual weighting filter */
    Error_Wght(DataBuff, PerLpc);

    /*  Compute Open loop pitch estimates  */

    //Dpnt = (float *) malloc(sizeof(float)*(PitchMax+Frame));
	Dpnt = new float[PitchMax+Frame];

    /* Construct the buffer */
    for (i=0; i < PitchMax;i++)
        Dpnt[i] = CodStat.PrevWgt[i];

    for (i=0;i < Frame;i++)
        Dpnt[PitchMax+i] = DataBuff[i];

    j = PitchMax;
    for (i=0; i < SubFrames/2; i++) {
        Line.Olp[i] = Estim_Pitch(Dpnt, j);
        VadStat.Polp[i+2] = (short) Line.Olp[i];
        j += 2*SubFrLen;
    }

    if (Ftyp != 1) {

        /*
        // Case of inactive signal
        */
        //free((char *) Dpnt);
		delete Dpnt;

        /* Save PrevWgt */
        for ( i = 0 ; i < PitchMax ; i ++ )
            CodStat.PrevWgt[i] = DataBuff[i+Frame-PitchMax];

        /* CodCng => Ftyp = 0 (untransmitted) or 2 (SID) */
        Cod_Cng(DataBuff, &Ftyp, &Line, QntLpc);

        /* Update the ringing delays */
        Dpnt = DataBuff;
        for ( i = 0 ; i < SubFrames; i++ ) {

            /* Update exc_err */
            Update_Err(Line.Olp[i>>1], Line.Sfs[i].AcLg, Line.Sfs[i].AcGn);

            Upd_Ring( Dpnt, &QntLpc[i*LpcOrder], &PerLpc[i*2*LpcOrder],
                                                        CodStat.PrevErr);
            Dpnt += SubFrLen;
        }
    }
    else {

        /* Compute the Hmw */
        j = PitchMax;
        for (i=0; i < SubFrames; i++) {
            Pw[i] = Comp_Pw(Dpnt, j, Line.Olp[i>>1]);
            j += SubFrLen;
        }

        /* Reload the buffer */
        for (i=0; i < PitchMax; i++)
            Dpnt[i] = CodStat.PrevWgt[i];
        for (i=0; i < Frame; i++)
            Dpnt[PitchMax+i] = DataBuff[i];

        /* Save PrevWgt */
        for (i=0; i < PitchMax; i++)
          CodStat.PrevWgt[i] = Dpnt[Frame+i];

        /* Apply the Harmonic filter */
        j = 0;
        for (i=0; i < SubFrames; i++) {
            Filt_Pw(DataBuff, Dpnt, j , Pw[i]);
            j += SubFrLen;
        }

        //free((char *) Dpnt);
		delete Dpnt;

        /* Inverse quantization of the LSP */
        Lsp_Inq(LspVect, CodStat.PrevLsp, Line.LspId, Line.Crc);

        /* Interpolate the Lsp vectors */
        Lsp_Int(QntLpc, LspVect, CodStat.PrevLsp);

        /* Copy the LSP vector for the next frame */
        for ( i = 0 ; i < LpcOrder ; i ++ )
            CodStat.PrevLsp[i] = LspVect[i];

        /*  Start the sub frame processing loop  */

        Dpnt = DataBuff;

        for (i=0; i < SubFrames; i++) {

            /* Compute full impulse response */
            Comp_Ir(ImpResp, &QntLpc[i*LpcOrder], &PerLpc[i*2*LpcOrder], Pw[i]);

            /* Subtruct the ringing of previos sub-frame */
            Sub_Ring(Dpnt, &QntLpc[i*LpcOrder], &PerLpc[i*2*LpcOrder],
                     CodStat.PrevErr, Pw[i]);

            /* Compute adaptive code book contribution */
            Find_Acbk(Dpnt, ImpResp, CodStat.PrevExc, &Line, i);

            /* Compute fixed code book contribution */
            Find_Fcbk(Dpnt, ImpResp, &Line, i);

            /* Reconstruct the excitation */
            Decod_Acbk(ImpResp, CodStat.PrevExc, Line.Olp[i>>1],
                       Line.Sfs[i].AcLg, Line.Sfs[i].AcGn);

            for (j=SubFrLen; j < PitchMax; j++)
                CodStat.PrevExc[j-SubFrLen] = CodStat.PrevExc[j];

            for (j=0; j < SubFrLen; j++) {
                Dpnt[j] = Dpnt[j] + ImpResp[j];
                CodStat.PrevExc[PitchMax-SubFrLen+j] = Dpnt[j];

                /* Clip the new samples */
                if (CodStat.PrevExc[PitchMax-SubFrLen+j] < (float)-32767.5)
                    CodStat.PrevExc[PitchMax-SubFrLen+j] = (float)-32768.0;
                else if (CodStat.PrevExc[PitchMax-SubFrLen+j] > (float)32766.5)
                    CodStat.PrevExc[PitchMax-SubFrLen+j] = (float)32767.0;
            }

            /* Update exc_err */
            Update_Err(Line.Olp[i>>1], Line.Sfs[i].AcLg, Line.Sfs[i].AcGn);

            /* Update the ringing delays  */
            Upd_Ring(Dpnt, &QntLpc[i*LpcOrder], &PerLpc[i*2*LpcOrder],
                     CodStat.PrevErr);

            Dpnt += SubFrLen;
        }  /* end of subframes loop */

        /*
        // Save Vad information and reset CNG random generator
        */
        CodCng.PastFtyp = 1;
        CodCng.RandSeed = 12345;

    } /* End of active frame case */

    /* Pack the Line structure */
    Line_Pack(&Line, Vout, Ftyp);

    return TRUE;
}


/*
**
** 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:
**
**  float   *DataExc   Current frame synthetic excitation
**  short  *Ftyp      Characterizes the frame type for CNG
**  LINEDEF *Line      Quantized parameters (used for SID frames)
**  float   *QntLpc    Interpolated frame LPC coefficients
**
** Outputs:
**
**  float   *DataExc
**  short  *Ftyp
**  LINEDEF *Line
**  float   *QntLpc
**
** Return value:       None
**
*/
void CLanAudioEncoder::Cod_Cng(float *DataExc, short *Ftyp, LINEDEF *Line, float *QntLpc)
{
    float   curCoeff[LpcOrder];
    short  curQGain;
    float   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.NbEner);
    }

    else {
        CodCng.NbEner++;
        if (CodCng.NbEner > NbAvGain)
            CodCng.NbEner = NbAvGain;
        curQGain = Qua_SidGain(CodCng.Ener, CodCng.NbEner);

        /*
         * Compute stationarity of current filter

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -