?? encoder.cpp
字號:
//#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 + -