📄 encg723.c
字号:
/*/////////////////////////////////////////////////////////////////////////////
//
// INTEL CORPORATION PROPRIETARY INFORMATION
// This software is supplied under the terms of a license agreement or
// nondisclosure agreement with Intel Corporation and may not be copied
// or disclosed except in accordance with the terms of that agreement.
// Copyright(c) 2005 Intel Corporation. All Rights Reserved.
//
// Intel(R) Integrated Performance Primitives
// USC - Unified Speech Codec interface library
//
// By downloading and installing USC codec, you hereby agree that the
// accompanying Materials are being provided to you under the terms and
// conditions of the End User License Agreement for the Intel(R) Integrated
// Performance Primitives product previously accepted by you. Please refer
// to the file ipplic.htm located in the root directory of your Intel(R) IPP
// product installation for more information.
//
// A speech coding standards promoted by ITU, ETSI, 3GPP and other
// organizations. Implementations of these standards, or the standard enabled
// platforms may require licenses from various entities, including
// Intel Corporation.
//
//
// Purpose: G.723.1 speech codec: encode API functions.
//
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "owng723.h"
/* Declaration of local functions */
static void PastAverageFilter_G723(G723Encoder_Obj* encoderObj);
static void GetReflectionCoeff_G723(short *pSrcLPC, short *pDstReflectCoeff, short *pDstReflectCoeffSFS);
static int ItakuraDist_G723(short *pSrcReflectCoeff, short ReflectCoeffSFS, short *pSrcAutoCorrs, short energy);
static int EncoderObjSize(void){
int fltSize;
int objSize = sizeof(G723Encoder_Obj);
VoiceActivityDetectSize_G723(&fltSize);
objSize += fltSize; /* VAD decision memory size*/
return objSize;
}
G723_CODECFUN( APIG723_Status, apiG723Encoder_Alloc, (int *pCodecSize))
{
*pCodecSize = EncoderObjSize();
return APIG723_StsNoErr;
}
G723_CODECFUN( APIG723_Status, apiG723Encoder_ControlMode,
(G723Encoder_Obj* encoderObj, unsigned int mode))
{
encoderObj->objPrm.mode = mode;
return APIG723_StsNoErr;
}
G723_CODECFUN( APIG723_Status, apiG723Encoder_Mode,
(G723Encoder_Obj* encoderObj, unsigned int mode))
{
if (G723Encode_VAD_Enabled == mode)
encoderObj->objPrm.mode |= G723Encode_VAD_Enabled;
else{
encoderObj->objPrm.mode |= G723Encode_VAD_Enabled;
encoderObj->objPrm.mode ^= G723Encode_VAD_Enabled;
}
return APIG723_StsNoErr;
}
G723_CODECFUN( APIG723_Status, apiG723Encoder_Init,
(G723Encoder_Obj* encoderObj, unsigned int mode))
{
int i;
ippsZero_16s((short*)encoderObj,sizeof(G723Encoder_Obj)>>1) ;
encoderObj->objPrm.objSize = EncoderObjSize();
encoderObj->objPrm.mode = mode;
encoderObj->objPrm.key = G723_ENC_KEY;
encoderObj->objPrm.rat = 0; /* default 6.3 KBit/s*/
encoderObj->vadMem = (char*)encoderObj + sizeof(G723Encoder_Obj);
/* Initialize encoder data structure with zeros */
ippsZero_16s(encoderObj->ZeroSignal, G723_SBFR_LEN);
ippsZero_16s(encoderObj->UnitImpulseSignal, G723_SBFR_LEN); encoderObj->UnitImpulseSignal[0] = 0x2000 ; /* unit impulse */
/* Initialize the previously decoded LSP vector to the DC vector */
ippsCopy_16s(LPCDCTbl,encoderObj->PrevLPC,G723_LPC_ORDER);
/* Initialize the taming procedure */
for(i=0; i<5; i++) encoderObj->ExcitationError[i] = 4;
encoderObj->sSearchTime = 120; /* reset max time */
/* Initialize the VAD */
//if(encoderObj->objPrm.mode & G723Encode_VAD_Enabled){
VoiceActivityDetectInit_G723(encoderObj->vadMem);
/* Initialize the CNG */
encoderObj->CurrGain = 0;
ippsZero_16s(encoderObj->AutoCorrs,AUOTOCORRS_BUFF_SIZE);
for(i=0; i <= N_AUTOCORRS_BLOCKS; i++) encoderObj->AutoCorrsSFS[i] = 40;
encoderObj->PrevOpenLoopLags[0] = G723_SBFR_LEN;
encoderObj->PrevOpenLoopLags[1] = G723_SBFR_LEN;
ippsZero_16s(encoderObj->LPCSID,G723_LPC_ORDER);
ippsZero_16s(encoderObj->SIDLSP,G723_LPC_ORDER);
ippsZero_16s(encoderObj->prevSidLpc,G723_LPC_ORDERP1);
encoderObj->prevSidLpc[0] = 0x2000;
ippsZero_16s(encoderObj->ReflectionCoeff,G723_LPC_ORDER+1);
ippsZero_16s(encoderObj->GainAverEnergies,N_GAIN_AVER_FRMS);
encoderObj->PastFrameType = G723_ActiveFrm;
encoderObj->CNGSeed = 12345;
encoderObj->CasheCounter = 0;
encoderObj->ReflectionCoeffSFS = 0;
encoderObj->AverEnerCounter = 0;
encoderObj->PrevQGain = 0;
encoderObj->sSidGain = 0;
//}
return APIG723_StsNoErr;
}
G723_CODECFUN( APIG723_Status, apiG723Encoder_InitBuff,
(G723Encoder_Obj* encoderObj, char *buff))
{
#if !defined (NO_SCRATCH_MEMORY_USED)
if(NULL==encoderObj)
return APIG723_StsBadArgErr;
if(buff) encoderObj->Mem.base = buff; // otherwise reinit
else if (encoderObj->Mem.base == NULL) return APIG723_StsNotInitialized;
encoderObj->Mem.CurPtr = encoderObj->Mem.base;
encoderObj->Mem.VecPtr = (int *)(encoderObj->Mem.base+G723_ENCODER_SCRATCH_MEMORY_SIZE);
#endif
return APIG723_StsNoErr;
}
void EncoderCNG_G723(G723Encoder_Obj* encoderObj, ParamStream_G723 *Params, short *pExcitation, short *pDstLPC)
{
short sQuantGain, sTmp;
int i;
LOCAL_ARRAY(short, curCoeff,G723_LPC_ORDER,encoderObj) ;
for(i=N_GAIN_AVER_FRMS-1;i>=1;i--) encoderObj->GainAverEnergies[i]=encoderObj->GainAverEnergies[i-1];
/* Calculate the LPC filter */
ippsLevinsonDurbin_G723_16s( encoderObj->AutoCorrs, &sTmp, encoderObj->GainAverEnergies, curCoeff);
/* if the first frame of silence => SID frame */
if(encoderObj->PastFrameType == G723_ActiveFrm) {
Params->FrameType = G723_SIDFrm;
encoderObj->AverEnerCounter = 1;
QuantSIDGain_G723_16s(encoderObj->GainAverEnergies, encoderObj->AutoCorrsSFS, encoderObj->AverEnerCounter,&i);
sQuantGain=i;
} else {
encoderObj->AverEnerCounter++;
if(encoderObj->AverEnerCounter > N_GAIN_AVER_FRMS) encoderObj->AverEnerCounter = N_GAIN_AVER_FRMS;
QuantSIDGain_G723_16s(encoderObj->GainAverEnergies, encoderObj->AutoCorrsSFS, encoderObj->AverEnerCounter,&i);
sQuantGain=i;
/* Compute stationarity of current filter versus reference filter */
if(ItakuraDist_G723(encoderObj->ReflectionCoeff, encoderObj->ReflectionCoeffSFS, encoderObj->AutoCorrs, *encoderObj->GainAverEnergies) == 0) {
Params->FrameType = G723_SIDFrm; /* SID frame */
} else {
sTmp = abs(sQuantGain-encoderObj->PrevQGain);
if(sTmp > 3) {
Params->FrameType = G723_SIDFrm;/* SID frame */
} else {
Params->FrameType = G723_UntransmittedFrm;/* untransmitted */
}
}
}
if(Params->FrameType == G723_SIDFrm) { /* Compute SID filter */
LOCAL_ARRAY(short, qIndex,3,encoderObj) ;
/* Check stationarity */
PastAverageFilter_G723(encoderObj);
if(!encoderObj->AdaptEnableFlag) /* adaptation enabled */
for(i=0;i<G723_LPC_ORDER;i++)
encoderObj->prevSidLpc[i+1] = -encoderObj->LPCSID[i];
GetReflectionCoeff_G723(encoderObj->LPCSID , encoderObj->ReflectionCoeff, &encoderObj->ReflectionCoeffSFS);
if(ItakuraDist_G723(encoderObj->ReflectionCoeff, encoderObj->ReflectionCoeffSFS, encoderObj->AutoCorrs, *encoderObj->GainAverEnergies) == 0){
ippsCopy_16s(curCoeff,encoderObj->LPCSID,G723_LPC_ORDER);
GetReflectionCoeff_G723(curCoeff, encoderObj->ReflectionCoeff, &encoderObj->ReflectionCoeffSFS);
}
/* Compute SID frame codes */
ippsLPCToLSF_G723_16s(encoderObj->LPCSID,encoderObj->PrevLPC,encoderObj->SIDLSP);
ippsLSFQuant_G723_16s32s(encoderObj->SIDLSP, encoderObj->PrevLPC, &Params->lLSPIdx);
qIndex[2] = Params->lLSPIdx & 0xff;
qIndex[1] = (Params->lLSPIdx>>8) & 0xff;
qIndex[0] = (Params->lLSPIdx>>16) & 0xff;
if(ippsLSFDecode_G723_16s(qIndex, encoderObj->PrevLPC, 0, encoderObj->SIDLSP) != ippStsNoErr)
ippsCopy_16s(encoderObj->PrevLPC,encoderObj->SIDLSP,G723_LPC_ORDER);
Params->sAmpIndex[0] = sQuantGain;
encoderObj->PrevQGain = sQuantGain;
DecodeSIDGain_G723_16s(encoderObj->PrevQGain,&encoderObj->sSidGain);
LOCAL_ARRAY_FREE(short, qIndex,3,encoderObj) ;
}
/* Compute new excitation */
if(encoderObj->PastFrameType == G723_ActiveFrm) {
encoderObj->CurrGain = encoderObj->sSidGain;
} else {
encoderObj->CurrGain = ( (encoderObj->CurrGain*0xE000)+
(encoderObj->sSidGain*0x2000) )>>16 ;
}
{
LOCAL_ARRAY(char, buff,ComfortNoiseExcitation_G723_16s_Buff_Size,encoderObj) ;
ComfortNoiseExcitation_G723_16s(encoderObj->CurrGain, encoderObj->PrevExcitation, pExcitation,
&encoderObj->CNGSeed, Params->PitchLag,Params->AdCdbkLag,(Ipp16s*)Params->AdCdbkGain, Params->currRate, buff, &encoderObj->CasheCounter);
LOCAL_ARRAY_FREE(char, buff,ComfortNoiseExcitation_G723_16s_Buff_Size,encoderObj) ;
}
LSPInterpolation(encoderObj->SIDLSP, encoderObj->PrevLPC, pDstLPC);/* Interpolate LSPs */
ippsCopy_16s(encoderObj->SIDLSP,encoderObj->PrevLPC,G723_LPC_ORDER); /* update prev SID LPC */
encoderObj->PastFrameType = Params->FrameType;
LOCAL_ARRAY_FREE(short, curCoeff,G723_LPC_ORDER,encoderObj) ;
return;
}
void UpdateAutoCorrs_G723(G723Encoder_Obj* encoderObj, const short *pSrcAutoCorrs, const short *pSrcAutoCorrsSFS)
{
int i, lNsbfr;
short sMinSFS, sTmp;
short m1, m2;
LOCAL_ARRAY(int, lSumAutoCorrs,G723_LPC_ORDER+1,encoderObj) ;
/* Update Acf and ShAcf */
for(i=0; i<AUOTOCORRS_BUFF_SIZE-G723_LPC_ORDER-1; i++) encoderObj->AutoCorrs[AUOTOCORRS_BUFF_SIZE-1-i] = encoderObj->AutoCorrs[AUOTOCORRS_BUFF_SIZE-G723_LPC_ORDER-2-i];
for(i=N_AUTOCORRS_BLOCKS; i>=1; i--) encoderObj->AutoCorrsSFS[i] = encoderObj->AutoCorrsSFS[i-1];
/* Search the min of pSrcAutoCorrsSFS */
m1 = IPP_MIN(pSrcAutoCorrsSFS[0],pSrcAutoCorrsSFS[1]);
m2 = IPP_MIN(pSrcAutoCorrsSFS[2],pSrcAutoCorrsSFS[3]);
sMinSFS = (IPP_MIN(m1,m2))+14;
/* Calculate the acfs sum */
ippsZero_16s((short*)lSumAutoCorrs,2*G723_LPC_ORDERP1);
for(lNsbfr=0; lNsbfr<4; lNsbfr++) {
sTmp = sMinSFS - pSrcAutoCorrsSFS[lNsbfr];
if(sTmp < 0) {
sTmp = -sTmp;
for(i=0; i <= G723_LPC_ORDER; i++) {
lSumAutoCorrs[i] += (pSrcAutoCorrs[lNsbfr*G723_LPC_ORDERP1+i]>>sTmp);
}
} else {
for(i=0; i <= G723_LPC_ORDER; i++) {
lSumAutoCorrs[i] += (pSrcAutoCorrs[lNsbfr*G723_LPC_ORDERP1+i]<<sTmp);
}
}
}
/* Normalize */
sTmp = Exp_32s_Pos(lSumAutoCorrs[0]);
sTmp = 16 - sTmp; if(sTmp < 0) sTmp = 0;
for(i=0;i<=G723_LPC_ORDER;i++) encoderObj->AutoCorrs[i]=(short)(lSumAutoCorrs[i]>>sTmp);
encoderObj->AutoCorrsSFS[0] = sMinSFS - sTmp;
LOCAL_ARRAY_FREE(int, lSumAutoCorrs,G723_LPC_ORDER+1,encoderObj) ;
return;
}
void PastAverageFilter_G723(G723Encoder_Obj* encoderObj)
{
int i, j;
short sMinSFS, sTmp;
LOCAL_ARRAY(int, lSumAutoCorrs,G723_LPC_ORDER+1,encoderObj) ;
LOCAL_ARRAY(short, pCorr,G723_LPC_ORDER+1,encoderObj) ;
/* Search ShAcf min */
sMinSFS = IPP_MIN(encoderObj->AutoCorrsSFS[1],encoderObj->AutoCorrsSFS[2]);
sMinSFS = (IPP_MIN(sMinSFS,encoderObj->AutoCorrsSFS[3]))+14;
ippsZero_16s((short*)lSumAutoCorrs,2*G723_LPC_ORDERP1);
for(i=1; i <= N_AUTOCORRS_BLOCKS; i ++) {
sTmp = sMinSFS - encoderObj->AutoCorrsSFS[i];
if(sTmp < 0) {
sTmp=-sTmp;
for(j=0; j <= G723_LPC_ORDER; j++) {
lSumAutoCorrs[j] += (encoderObj->AutoCorrs[i*G723_LPC_ORDERP1+j]>>sTmp);
}
} else {
for(j=0; j <= G723_LPC_ORDER; j++) {
lSumAutoCorrs[j] += (encoderObj->AutoCorrs[i*G723_LPC_ORDERP1+j]<<sTmp);
}
}
}
/* Normalize */
sTmp = Exp_32s_Pos(lSumAutoCorrs[0]);
sTmp = 16 - sTmp;
if(sTmp < 0) sTmp = 0;
for(i=0; i<G723_LPC_ORDER+1; i++) {
pCorr[i] = (short)(lSumAutoCorrs[i]>>sTmp);
}
ippsLevinsonDurbin_G723_16s(pCorr, &sTmp, &sTmp, encoderObj->LPCSID);
LOCAL_ARRAY_FREE(short, pCorr,G723_LPC_ORDER+1,encoderObj) ;
LOCAL_ARRAY_FREE(int, lSumAutoCorrs,G723_LPC_ORDER+1,encoderObj) ;
return;
}
void GetReflectionCoeff_G723(short *pSrcLPC, short *pDstReflectCoeff, short *pDstReflectCoeffSFS)
{
int i, j;
short SFS;
int lCorr;
ippsDotProd_16s32s_Sfs(pSrcLPC,pSrcLPC,G723_LPC_ORDER,&lCorr,-1);
lCorr = lCorr >> 1;
lCorr = lCorr + 0x04000000;
SFS = Exp_32s_Pos(lCorr) - 2;
*pDstReflectCoeffSFS = SFS;
if(SFS > 0) {
lCorr = ShiftL_32s(lCorr, SFS);
pDstReflectCoeff[0] = Cnvrt_NR_32s16s(lCorr);
for(i=1; i<=G723_LPC_ORDER; i++) {
lCorr = -(pSrcLPC[i-1]<<13);
for(j=0; j<G723_LPC_ORDER-i; j++) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -