diff --git a/aux_fnxs.h b/aux_fnxs.h new file mode 100644 index 0000000..cf539e4 --- /dev/null +++ b/aux_fnxs.h @@ -0,0 +1,323 @@ +/*///////////////////////////////////////////////////////////////////////////// +// +// 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-2008 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 ippEULA.rtf or ippEULA.txt located in the root directory of your Intel(R) IPP +// product installation for more information. +// +// Purpose: USC: auxiliary functions. +// +*/ + +#ifndef __AUX_FNXS__ +#define __AUX_FNXS__ + +#if defined( _WIN32_WCE) +#pragma warning( disable : 4505 ) +#endif + +#include +#include "scratchmem.h" + +/******************************************************** +* auxiliary inline functions declarations +*********************************************************/ + +/* Random generator */ +__INLINE Ipp16s Rand_16s(Ipp16s *seed) +{ + *seed = (Ipp16s)(*seed * 31821 + 13849); + + return(*seed); +} + +__INLINE Ipp16s Rand2_16s( Ipp16s *pSeed ) +{ + *pSeed = (Ipp16s)(*pSeed * 521 + 259); + return *pSeed ; +} + +__INLINE Ipp16s NormRand_16s(Ipp16s N, Ipp16s *nRandom) +{ + Ipp16s sTmp; + + sTmp = (Ipp16s)(Rand2_16s(nRandom) & 0x7FFF); + sTmp = (Ipp16s)((sTmp * N)>>15); + return sTmp; +} + +__INLINE Ipp16s Abs_16s(Ipp16s x){ + if(x<0){ + if(IPP_MIN_16S == x) return IPP_MAX_16S; + x = (Ipp16s)-x; + } + return x; +} + +__INLINE Ipp32s Abs_32s(Ipp32s x){ + if(x<0){ + if(IPP_MIN_32S == x) return IPP_MAX_32S; + x = -x; + } + return x; +} + +__INLINE Ipp32s Add_32s(Ipp32s x, Ipp32s y) { + Ipp64s z = (Ipp64s)x + y; + if (z>IPP_MAX_32S) return IPP_MAX_32S; + else if(z>8)==0) + return ExpPosNormTbl2[x]; + else { + return ExpPosNormTbl[(x>>8)]; + } +} + +__INLINE Ipp16s Exp_16s(Ipp16s x){ + if (x == -1) return 15; + if (x == 0) return 0; + if (x < 0) x = (Ipp16s)(~x); + return Exp_16s_Pos(x); +} + +//__INLINE Ipp16s Exp_32s_Pos(Ipp32s x){ +// Ipp16s i; +// if (x == 0) return 0; +// for(i = 0; x < (Ipp32s)0x40000000; i++) x <<= 1; +// return i; +//} +__INLINE short Exp_32s_Pos(unsigned int x){ + if (x == 0) return 0; + if((x>>16)==0) return (short)(16+Exp_16s_Pos((unsigned short) x)); + return Exp_16s_Pos((unsigned short)(x>>16)); +} + +__INLINE Ipp16s Exp_32s(Ipp32s x){ + if (x == 0) return 0; + if (x == -1) return 31; + if (x < 0) x = ~x; + return Exp_32s_Pos(x); +} + +__INLINE Ipp16s Norm_32s_I(Ipp32s *x){ + Ipp16s i; + if (*x == 0) return 0; + if (*x < 0){ + for(i = 0; *x >= (Ipp32s)0xC0000000; i++) *x <<= 1; + }else + for(i = 0; *x < (Ipp32s)0x40000000; i++) *x <<= 1; + return i; +} + +__INLINE Ipp16s Norm_32s_Pos_I(Ipp32s *x){ + Ipp16s i; + if (*x == 0) return 0; + for(i = 0; *x < (Ipp32s)0x40000000; i++) *x <<= 1; + return i; +} + +__INLINE Ipp16s Cnvrt_32s16s(Ipp32s x){ + if (IPP_MAX_16S < x) return IPP_MAX_16S; + else if (IPP_MIN_16S > x) return IPP_MIN_16S; + return (Ipp16s)(x); +} + +__INLINE Ipp16s Cnvrt_NR_32s16s(Ipp32s x) { + Ipp16s s = IPP_MAX_16S; + if(x<(Ipp32s)0x7fff8000) s = (Ipp16s)((x+0x8000)>>16); + return s; +} + +__INLINE Ipp32s Cnvrt_64s32s(__INT64 z) { + if(IPP_MAX_32S < z) return IPP_MAX_32S; + else if(IPP_MIN_32S > z) return IPP_MIN_32S; + return (Ipp32s)z; +} + +__INLINE Ipp16s MulHR_16s(Ipp16s x, Ipp16s y) { + return (Ipp16s)( ((((Ipp32s)x * (Ipp32s)y)) + 0x4000) >> 15 ); +} +__INLINE Ipp16s Negate_16s(Ipp16s x) { + if(IPP_MIN_16S == x) + return IPP_MAX_16S; + return (Ipp16s)-x; +} +__INLINE Ipp32s Negate_32s(Ipp32s x) { + if(IPP_MIN_32S == x) + return IPP_MAX_32S; + return (Ipp32s)-x; +} +__INLINE Ipp16s Mul2_16s(Ipp16s x) { + if(x > IPP_MAX_16S/2) return IPP_MAX_16S; + else if( x < IPP_MIN_16S/2) return IPP_MIN_16S; + x = (Ipp16s)(x << 1); + return x; +} +__INLINE Ipp32s Mul2_32s(Ipp32s x) { + if(x > IPP_MAX_32S/2) return IPP_MAX_32S; + else if( x < IPP_MIN_32S/2) return IPP_MIN_32S; + return x <<= 1; +} + +__INLINE Ipp32s Mul16_32s(Ipp32s x) { + if(x > (Ipp32s) 0x07ffffffL) return IPP_MAX_32S; + else if( x < (Ipp32s) 0xf8000000L) return IPP_MIN_32S; + return (x <<= 4); +} + +__INLINE Ipp32s MulC_32s(Ipp16s val, Ipp32s x) { + Ipp32s z ; + Ipp32s xh, xl; + xh = x >> 16; + xl = x & 0xffff; + z = 2*val*xh; + z = Add_32s(z,(xl*val)>>15); + + return( z ); +} + +__INLINE Ipp32s ShiftL_32s(Ipp32s x, Ipp16u n) +{ + Ipp32s max = IPP_MAX_32S >> n; + Ipp32s min = IPP_MIN_32S >> n; + if(x > max) return IPP_MAX_32S; + else if(x < min) return IPP_MIN_32S; + return (x<> x); + Ipp16s min = (Ipp16s)(IPP_MIN_16S >> x); + if(n > max) return IPP_MAX_16S; + else if(n < min) return IPP_MIN_16S; + return (Ipp16s)(n<>n); +} + +__INLINE Ipp16s ExtractHigh(Ipp32s x){ + return ((Ipp16s)(x >> 16)); +} + +__INLINE void Unpack_32s (Ipp32s number, Ipp16s *hi, Ipp16s *lo) +{ + *hi = (Ipp16s)(number >> 16); + *lo = (Ipp16s)((number>>1)&0x7fff); + return; +} +__INLINE Ipp32s Pack_16s32s(Ipp16s hi, Ipp16s lo) +{ + return ( ((Ipp32s)hi<<16) + ((Ipp32s)lo<<1) ); + ; +} +__INLINE Ipp32s Mpy_32_16 (Ipp16s hi, Ipp16s lo, Ipp16s n) +{ + return (2 * (hi * n) + 2 * ((lo * n) >> 15)); +} + +__INLINE Ipp16s Mul_16s_Sfs(Ipp16s x, Ipp16s y, Ipp32s scaleFactor) { + return (Ipp16s)((x * y) >> scaleFactor); +} + +__INLINE Ipp32s Mul_32s(Ipp32s x,Ipp32s y) { + Ipp32s z,z1,z2; + Ipp16s xh, xl, yh, yl; + xh = (Ipp16s)(x >> 15); + yh = (Ipp16s)(y >> 15); + xl = (Ipp16s)(x & 0x7fff); + yl = (Ipp16s)(y & 0x7fff); + z1 = Mul_16s_Sfs(xh,yl,15); + z2 = Mul_16s_Sfs(xl,yh,15); + z = xh * yh; + z += z1; + z += z2; + return (z<<1); +} + +__INLINE Ipp16s Add_16s(Ipp16s x, Ipp16s y) { + return Cnvrt_32s16s((Ipp32s)x + (Ipp32s)y); +} +__INLINE Ipp16s Sub_16s(Ipp16s x, Ipp16s y) { + return Cnvrt_32s16s((Ipp32s)x - (Ipp32s)y); +} + +__INLINE Ipp32s Sub_32s(Ipp32s x,Ipp32s y){ + return Cnvrt_64s32s((__INT64)x - y); +} + +__INLINE Ipp32s ownSqrt_32s( Ipp32s n ) +{ + Ipp32s i ; + + Ipp16s x = 0 ; + Ipp16s y = 0x4000 ; + + Ipp32s z ; + + for ( i = 0 ; i < 14 ; i ++ ) { + z = (x + y) * (x + y ) ; + if ( n >= z ) + x = (Ipp16s)(x + y); + y >>= 1 ; + } + return x; +} + +__INLINE Ipp32s Exp_64s_Pos(Ipp64u x) +{ + if (x == 0) return 0; + if((x>>32)==0) return (Ipp32s)(32+Exp_32s_Pos((Ipp32u) x)); + return (Ipp32s)Exp_32s_Pos((Ipp32u)(x>>32)); +} + + +__INLINE Ipp32s Norm_64s(Ipp64s x){ + Ipp32s i; + if (x == 0) return 0; + if (x == -1) return 63; + if (x < 0) x = ~x; + i = (Ipp32s)Exp_64s_Pos((Ipp64u)x); + return i; +} +__INLINE Ipp32s Norm_32s(Ipp32s x){ + Ipp32s i; + if (x == 0) return 0; + if (x == -1) return 31; + if (x < 0) x = ~x; + i = (Ipp32s)Exp_32s_Pos((Ipp32u)x); + return i; +} + +__INLINE Ipp16s Div_16s(Ipp16s num, Ipp16s den) +{ + if ((num < den) && (num > 0) && (den > 0)) { + return (Ipp16s)( (((Ipp32s)num)<<15) / den); + } else if ((den != 0) && (num == den)) { + return IPP_MAX_16S; + } + return 0; +} + +#endif /* __AUX_FNXS__ */ diff --git a/aux_tbls.c b/aux_tbls.c new file mode 100644 index 0000000..ab6c467 --- /dev/null +++ b/aux_tbls.c @@ -0,0 +1,95 @@ +/*///////////////////////////////////////////////////////////////////////////// +// +// 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-2007 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 ippEULA.rtf or ippEULA.txt located in the root directory of your Intel(R) IPP +// product installation for more information. +// +// Purpose: USC: auxiliary tables. +// +*/ + +#include "aux_fnxs.h" + +__ALIGN32 CONST Ipp16s ExpPosNormTbl[256] = +{ + 7,6,5,5,4,4,4,4, + 3,3,3,3,3,3,3,3, + 2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2, + 1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + -1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1 +}; + +__ALIGN32 CONST Ipp16s ExpPosNormTbl2[256] = +{ + 15,14,13,13,12,12,12,12, + 11,11,11,11,11,11,11,11, + 10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10, + 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7 +}; diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..5513d24 --- /dev/null +++ b/build.sh @@ -0,0 +1,57 @@ +src3="g723codec.cpp decg723.c encg723.c owng723.c vadg723.c aux_tbls.c" +src9="g729codec.cpp decg729fp.c encg729fp.c owng729fp.c vadg729fp.c" + +cc=gcc +o="-O3 -fomit-frame-pointer" +#inc=/home/arkadi/opt/yate2/include/yate +inc=/home/arkadi/opt/yate21/include/yate +#inc=/home/arkadi/opt/yate-svn/include/yate +# uncomment if you have Yate 2.1 or SVN r2745 or later +r2745=-DYATE_G72X_POST_R2745 + +function build() +{ + "$cc" -shared -Xlinker -x -o $1 \ + $r2745 -I$inc -I"$ipproot"/include $ippstatic_include \ + $opt $o \ + -fPIC -fno-check-new -fno-exceptions \ + $src \ + -L"$ipproot"/lib $ipplibs +} + +# 32-bit +opt=-march=pentium4 +ipproot=/opt/intel/ipp/6.0/ia32 +ipplibs="-lippscmerged -lippsrmerged -lippsmerged -lippcore" +ippcore=w7 # pentium4 sse2 +#ipproot=/opt/intel/ipp/5.3/ia32 +#ippcore=a6 # pentium3 sse +ippstatic_include="-include $ipproot/tools/staticlib/ipp_$ippcore.h" +src="$src3" build g723.yate +src="$src9" build g729.yate + +# 64-bit +cc=x86_64-unknown-linux-gnu-gcc-4.3.2 +opt=-march=nocona +ipproot=/opt/intel/ipp/6.0/em64t +ipplibs="-lippscmergedem64t -lippsrmergedem64t -lippsmergedem64t -lippcoreem64t" +ippcore=m7 # pentium4 sse3 em64t +ippstatic_include="-include $ipproot/tools/staticlib/ipp_$ippcore.h" +src="$src3" build g723_x64.yate +src="$src9" build g729_x64.yate + +# IPP cores are: +# 32-bit +# px - pentium mmx +# a6 - pentium3 sse (removed in IPP 6.0) +# w7 - pentium4 sse2 +# t7 - pentium4 prescott sse3 +# v8 - core2 ssse3 +# p8 - core2 penryn, core i7 nehalem sse4.1 +# s8 - atom +# 64-bit +# mx - older amd64 w/o sse3? +# m7 - pentium4 sse3 em64t +# u8 - core2 ssse3 +# y8 - core2 penryn, core i7 nehalem sse4.1 +# n8 - atom diff --git a/decg723.c b/decg723.c new file mode 100644 index 0000000..bf5a040 --- /dev/null +++ b/decg723.c @@ -0,0 +1,325 @@ +/*///////////////////////////////////////////////////////////////////////////// +// +// 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-2007 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 ippEULA.rtf or ippEULA.txt 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: decode API functions. +// +*/ + +#include "owng723.h" + +static Ipp32s DecoderObjSize(void){ + return sizeof(G723Decoder_Obj); +} + + +G723_CODECFUN( APIG723_Status, apiG723Decoder_Alloc, (Ipp32s *pCodecSize)) +{ + *pCodecSize = DecoderObjSize(); + return APIG723_StsNoErr; +} + +G723_CODECFUN( APIG723_Status, apiG723Decoder_Init, + (G723Decoder_Obj* decoderObj, Ipp32u mode)) +{ + Ipp8s* oldMemBuff; + + if(NULL==decoderObj) + return APIG723_StsBadArgErr; + + oldMemBuff = decoderObj->Mem.base; /* if Reinit */ + + ippsZero_16s((Ipp16s*)decoderObj,sizeof(G723Decoder_Obj)>>1) ; /* non-initialized data, bug in debug mode AK27.08.01 */ + decoderObj->objPrm.objSize = DecoderObjSize(); + decoderObj->objPrm.mode = mode; + decoderObj->objPrm.key = G723_DEC_KEY; + decoderObj->objPrm.rat = 0; /* default 6.3 KBit/s*/ + + ippsCopy_16s(LPCDCTbl,decoderObj->PrevLPC,G723_LPC_ORDER); + + decoderObj->PstFltGain = (Ipp16s) 0x1000 ; + /* Initialize the CNG */ + decoderObj->PastFrameType = G723_ActiveFrm; + decoderObj->sSidGain = 0; + decoderObj->CNGSeed = 12345; + decoderObj->CasheCounter = 0; + ippsCopy_16s(LPCDCTbl,decoderObj->SIDLSP,G723_LPC_ORDER); + + apiG723Decoder_InitBuff(decoderObj,oldMemBuff); + + return APIG723_StsNoErr; +} + +G723_CODECFUN( APIG723_Status, apiG723Decoder_ControlMode, + (G723Decoder_Obj* decoderObj, Ipp32u mode)) +{ + decoderObj->objPrm.mode = mode; + return APIG723_StsNoErr; +} + +G723_CODECFUN( APIG723_Status, apiG723Decoder_InitBuff, + (G723Decoder_Obj* decoderObj, Ipp8s *buff)) +{ + + if(NULL==decoderObj) return APIG723_StsBadArgErr; + if(NULL==buff) return APIG723_StsBadArgErr; + + if(buff) decoderObj->Mem.base = buff; // otherwise reinit + else if (decoderObj->Mem.base == NULL) return APIG723_StsNotInitialized; + decoderObj->Mem.CurPtr = decoderObj->Mem.base; + decoderObj->Mem.VecPtr = (Ipp32s *)(decoderObj->Mem.base+G723_ENCODER_SCRATCH_MEMORY_SIZE); + + return APIG723_StsNoErr; +} + +void DecoderCNG_G723(G723Decoder_Obj* decoderObj, ParamStream_G723 *CurrentParams, Ipp16s *pExcitation, Ipp16s *pDstLPC) +{ + Ipp32s i; + + if(CurrentParams->FrameType == G723_SIDFrm) { /* SID Frame */ + LOCAL_ARRAY(Ipp16s, qIndex,3, decoderObj); + + DecodeSIDGain_G723_16s(CurrentParams->sAmpIndex[0],&decoderObj->sSidGain); + + /* LSP inverse quantization */ + qIndex[2] = (Ipp16s)(CurrentParams->lLSPIdx & 0xff); + qIndex[1] = (Ipp16s)((CurrentParams->lLSPIdx>>8) & 0xff); + qIndex[0] = (Ipp16s)((CurrentParams->lLSPIdx>>16) & 0xff); + if(ippsLSFDecode_G723_16s(qIndex, decoderObj->PrevLPC, 0, decoderObj->SIDLSP) != ippStsNoErr) + ippsCopy_16s(decoderObj->PrevLPC,decoderObj->SIDLSP,G723_LPC_ORDER); + + LOCAL_ARRAY_FREE(Ipp16s, qIndex,3, decoderObj); + } else { /* non SID Frame */ + if(decoderObj->PastFrameType == G723_ActiveFrm) { /* Case of 1st SID frame erased */ + QuantSIDGain_G723_16s(&decoderObj->sSidGain, &decoderObj->CurrGain, 0, &i); + DecodeSIDGain_G723_16s(i,&decoderObj->sSidGain); + } + } + + if(decoderObj->PastFrameType == G723_ActiveFrm) { + decoderObj->CurrGain = decoderObj->sSidGain; + } else { /* update gain */ + decoderObj->CurrGain = (Ipp16s)(( 7*decoderObj->CurrGain + decoderObj->sSidGain) >> 3) ; + } + { + + LOCAL_ARRAY(Ipp8s, buff,ComfortNoiseExcitation_G723_16s_Buff_Size, decoderObj); + + ComfortNoiseExcitation_G723_16s(decoderObj->CurrGain, decoderObj->PrevExcitation, pExcitation, + &decoderObj->CNGSeed, CurrentParams->PitchLag,CurrentParams->AdCdbkLag,CurrentParams->AdCdbkGain, CurrentParams->currRate, buff, &decoderObj->CasheCounter); + LOCAL_ARRAY_FREE(Ipp8s, buff,ComfortNoiseExcitation_G723_16s_Buff_Size, decoderObj); + } + + + /* LSP interpolation */ + LSPInterpolation(decoderObj->SIDLSP, decoderObj->PrevLPC, pDstLPC) ; + ippsCopy_16s(decoderObj->SIDLSP,decoderObj->PrevLPC,G723_LPC_ORDER); + + return; +} + +G723_CODECFUN( APIG723_Status, apiG723Decode, + (G723Decoder_Obj* decoderObj, const Ipp8s* src, Ipp16s badFrameIndicator, Ipp16s* dst)) +{ + Ipp32s i,j,k ; + Ipp16s *pData ; + + LOCAL_ALIGN_ARRAY(32, Ipp16s, SubZeroLPC,G723_LPC_ORDER+1, decoderObj); + LOCAL_ARRAY(Ipp16s, CurrLPC,4*(G723_LPC_ORDER+1), decoderObj); + LOCAL_ARRAY(Ipp16s, AdaptiveVector,G723_SBFR_LEN, decoderObj); + LOCAL_ARRAY(Ipp16s, CurrLSF,G723_LPC_ORDER, decoderObj); + LOCAL_ARRAY(Ipp16s, TemporaryVector,G723_MAX_PITCH+G723_FRM_LEN, decoderObj); + LOCAL_ARRAY(GainInfo_G723, GainInfo,4, decoderObj); + ParamStream_G723 CurrentParams; + + if(NULL==decoderObj || NULL==src || NULL ==dst) + return APIG723_StsBadArgErr; + if(decoderObj->objPrm.objSize <= 0) + return APIG723_StsNotInitialized; + if(G723_DEC_KEY != decoderObj->objPrm.key) + return APIG723_StsBadCodecType; + + CurrentParams.FrameType = G723_UntransmittedFrm; + CurrentParams.lLSPIdx = 0; + CurrentParams.sAmpIndex[0] = 0; + CurrentParams.sAmpIndex[1] = 0; + CurrentParams.sAmpIndex[2] = 0; + CurrentParams.sAmpIndex[3] = 0; + CurrentParams.PitchLag[0] = 0; + CurrentParams.PitchLag[1] = 0; + CurrentParams.currRate = (G723_Rate)decoderObj->objPrm.rat; + CurrentParams.isBadFrame = badFrameIndicator; + + if(badFrameIndicator == 0) { + GetParamFromBitstream( src, &CurrentParams); /* Unpack the bitstream */ + if( CurrentParams.FrameType == G723_ActiveFrm) decoderObj->objPrm.rat = CurrentParams.currRate; + } + if ( CurrentParams.isBadFrame != 0 ) { + if(decoderObj->PastFrameType == G723_ActiveFrm) CurrentParams.FrameType = G723_ActiveFrm; /* active */ + else CurrentParams.FrameType = G723_UntransmittedFrm; /* untransmitted */ + } + + if(CurrentParams.FrameType != G723_ActiveFrm) { /* non active frame */ + + /* noise generation */ + DecoderCNG_G723(decoderObj, &CurrentParams, dst, CurrLPC); + } else { + /* Update erasure count. Section 3.10*/ + + if ( 0 != CurrentParams.isBadFrame ) + decoderObj->ErasedFramesCounter++; + else + decoderObj->ErasedFramesCounter = 0 ; + + if ( decoderObj->ErasedFramesCounter > 3 ) + decoderObj->ErasedFramesCounter = 3 ; + + { + LOCAL_ARRAY(Ipp16s, qIndex,3, decoderObj); + /* Decode the LSP vector for subframe 3. Section 3.2 */ + qIndex[2] = (Ipp16s)(CurrentParams.lLSPIdx & 0xff); + qIndex[1] = (Ipp16s)((CurrentParams.lLSPIdx>>8) & 0xff); + qIndex[0] = (Ipp16s)((CurrentParams.lLSPIdx>>16) & 0xff); + if(ippsLSFDecode_G723_16s(qIndex, decoderObj->PrevLPC, CurrentParams.isBadFrame, CurrLSF) != ippStsNoErr) + ippsCopy_16s(decoderObj->PrevLPC,CurrLSF,G723_LPC_ORDER); + + LOCAL_ARRAY_FREE(Ipp16s, qIndex,3, decoderObj); + } + + /* LSP interpolation. Section 3.3 */ + LSPInterpolation(CurrLSF, decoderObj->PrevLPC, CurrLPC) ; + ippsCopy_16s(CurrLSF,decoderObj->PrevLPC,G723_LPC_ORDER); + + /* Generate the excitation for the frame */ + ippsCopy_16s(decoderObj->PrevExcitation,TemporaryVector,G723_MAX_PITCH); + + pData = &TemporaryVector[G723_MAX_PITCH] ; + + if ( 0 == decoderObj->ErasedFramesCounter ) { + /*update the interpolation gain memory.*/ + decoderObj->InterpolatedGain = (Ipp16s)(-GainDBLvls[(CurrentParams.sAmpIndex[2]+CurrentParams.sAmpIndex[3])>>1]); + + for ( i = 0 ; i < 4 ; i ++ ) { + Ipp32s lLag; + Ipp16s sGain; + + /* Fixed codebook excitation. Section 3.5 */ + FixedCodebookVector_G723_16s(CurrentParams.sPosition[i], CurrentParams.sAmplitude[i], + CurrentParams.sAmpIndex[i], CurrentParams.sGrid[i], CurrentParams.AdCdbkGain[i], + i, CurrentParams.currRate, pData, &lLag, &sGain ) ; + if ( G723_Rate63 == CurrentParams.currRate ){ + if(1 == CurrentParams.sTrainDirac[i] ){ + Ipp16s Tmp[G723_SBFR_LEN] ; + ippsCopy_16s(pData,Tmp,G723_SBFR_LEN); + /* Generation of a Dirac train. Section 2.15 */ + for ( j = CurrentParams.PitchLag[i>>1]; j < G723_SBFR_LEN ; j += CurrentParams.PitchLag[i>>1] ) { + ippsAdd_16s_I(Tmp,&pData[j],G723_SBFR_LEN-j); + } + } + }else{ /*rate53*/ + lLag += CurrentParams.PitchLag[i>>1]-1+CurrentParams.AdCdbkLag[i]; + if(lLag < G723_SBFR_LEN-2) { + ippsHarmonicFilter_16s_I(sGain,lLag,&pData[lLag],G723_SBFR_LEN-lLag); + } + } + + /* Adaptive codebook excitation. Section 3.4 */ + + ippsDecodeAdaptiveVector_G723_16s(CurrentParams.PitchLag[i>>1],CurrentParams.AdCdbkLag[i],CurrentParams.AdCdbkGain[i], + &TemporaryVector[G723_SBFR_LEN*i], AdaptiveVector, SA_Rate[CurrentParams.currRate]); + + /* Codebook contributions to excitation. */ + ippsLShiftC_16s_I(1,pData,G723_SBFR_LEN); + ippsAdd_16s_I(AdaptiveVector,pData,G723_SBFR_LEN); + pData += G723_SBFR_LEN ; + } + + ippsCopy_16s(&TemporaryVector[G723_MAX_PITCH],dst,G723_FRM_LEN); + + /* Interpolation index calculation. Section 3.10 */ + InterpolationIndex_G723_16s( TemporaryVector, CurrentParams.PitchLag[1], + &decoderObj->sSidGain, &decoderObj->CurrGain, &decoderObj->InterpolationIdx ); + + /* Pitch post filter coefficients calculation. Section 3.6 */ + if ( decoderObj->objPrm.mode&G723Decode_PF_Enabled ) + for ( i = 0 ; i < 4 ; i ++ ) + ippsPitchPostFilter_G723_16s(CurrentParams.PitchLag[i>>1], &TemporaryVector[G723_MAX_PITCH], &GainInfo[i].sDelay, + &GainInfo[i].sGain, &GainInfo[i].sScalingGain, (Ipp16s)i, SA_Rate[CurrentParams.currRate]); + + + ippsCopy_16s(decoderObj->PrevExcitation,TemporaryVector,G723_MAX_PITCH); + ippsCopy_16s(dst,&TemporaryVector[G723_MAX_PITCH],G723_FRM_LEN); + + /* Pitch post filtering. Section 3.6 */ + if ( decoderObj->objPrm.mode&G723Decode_PF_Enabled ) + for ( i = 0 ; i < 4 ; i ++ ){ + ippsInterpolateC_NR_G729_16s_Sfs( + &TemporaryVector[G723_MAX_PITCH+i*G723_SBFR_LEN], GainInfo[i].sScalingGain, + &TemporaryVector[G723_MAX_PITCH+i*G723_SBFR_LEN+GainInfo[i].sDelay], GainInfo[i].sGain, + &dst[i*G723_SBFR_LEN],G723_SBFR_LEN,15); + } + + ippsCopy_16s(decoderObj->PrevLPC,decoderObj->SIDLSP,G723_LPC_ORDER); + } else { + /* Frame erasure. Section 3.10 */ + /*compute the interpolation gain.*/ + decoderObj->InterpolatedGain = (Ipp16s)((3 * decoderObj->InterpolatedGain + 2 ) >> 2) ; + if ( decoderObj->ErasedFramesCounter >= 3 ) { /* Test for clearing */ + ippsZero_16s(dst,G723_FRM_LEN); + ippsZero_16s(TemporaryVector,G723_FRM_LEN+G723_MAX_PITCH); + }else{ + ResidualInterpolation_G723_16s_I(TemporaryVector, dst, decoderObj->InterpolationIdx, + decoderObj->InterpolatedGain, &decoderObj->ResIntSeed ) ; + } + } + + ippsCopy_16s(&TemporaryVector[G723_FRM_LEN],decoderObj->PrevExcitation,G723_MAX_PITCH); + decoderObj->CNGSeed = 12345; + decoderObj->CasheCounter = 0; + } + + decoderObj->PastFrameType = CurrentParams.FrameType; + + /* Speech synthesis. Section 3.7 */ + pData = dst ; + for ( i = 0 ; i < 4 ; i ++ ) { + + SubZeroLPC[0] = CurrLPC[i*(G723_LPC_ORDER+1)]; + for(k=1; kSyntFltIIRMem); + ippsCopy_16s(&pData[G723_SBFR_LEN-G723_LPC_ORDER], decoderObj->SyntFltIIRMem, G723_LPC_ORDER); + + if ( decoderObj->objPrm.mode&G723Decode_PF_Enabled ) { + + /* Formant post filter. Section 3.8 */ + PostFilter(decoderObj, pData, &CurrLPC[i*(G723_LPC_ORDER+1)+1] ) ; + }else{ + ippsMulC_16s_I(2,pData,G723_SBFR_LEN); + } + pData += G723_SBFR_LEN ; + } + + CLEAR_SCRATCH_MEMORY(decoderObj); + + return APIG723_StsNoErr; +} diff --git a/decg729fp.c b/decg729fp.c new file mode 100644 index 0000000..2607178 --- /dev/null +++ b/decg729fp.c @@ -0,0 +1,1132 @@ +/*///////////////////////////////////////////////////////////////////////////// +// +// 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) 2004-2007 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 ippEULA.rtf or ippEULA.txt 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.729 floating-point speech codec: decode API functions. +// +*/ +#include +#include "owng729fp.h" + +static void post_filter_I(G729FPDecoder_Obj* decoderObj, Ipp32f *pSynth, Ipp32f *pLPC, Ipp32s pitchDelay, Ipp32s dominant, + Ipp32s Vad, Ipp32s pstLPCOrder, Ipp32f *dst,Ipp32s rate); +static void Post_G729A(G729FPDecoder_Obj *decoderObj, Ipp32f *pSrcDstSynthSpeech, Ipp32f *pSrcLPC, + Ipp32s *pSrcDecodedPitch, Ipp32s Vad); + +/* filter coefficients (fc = 100 Hz ) */ + +static __ALIGN32 CONST Ipp32f b100[3] = {0.93980581E+00f, -0.18795834E+01f, 0.93980581E+00f}; +static __ALIGN32 CONST Ipp32f a100[3] = {1.00000000E+00f, 0.19330735E+01f, -0.93589199E+00f}; +/* tables of positions for each track */ +static __ALIGN32 CONST Ipp16s trackTbl0[32] = { + 1, 3, 8, 6, 18, 16, 11, 13, 38, 36, 31, 33, 21, 23, 28, 26, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + +static __ALIGN32 CONST Ipp16s trackTbl1[32] = { +0, 2, 5, 4, 12, 10, 7, 9, 25, 24, 20, 22, 14, 15, 19, 17, +36, 31, 21, 26, 1, 6, 16, 11, 27, 29, 32, 30, 39, 37, 34, 35}; + +static Ipp32s ownDecoderSize(G729Codec_Type codecType) +{ + Ipp32s codecSize, fltsize; + + codecSize = sizeof(G729FPDecoder_Obj); + ippsIIRGetStateSize_32f(2,&fltsize); + codecSize += fltsize; + PHDGetSize(&fltsize); + codecSize += fltsize; + ippsWinHybridGetStateSize_G729E_32f(&fltsize); + codecSize += fltsize; + if(codecType!=G729A_CODEC) { + PSTGetSize(&fltsize); + codecSize += fltsize; + } + + return codecSize; +} + +G729_CODECFUN( APIG729_Status, apiG729FPDecoder_Alloc, + (G729Codec_Type codecType, Ipp32s *pCodecSize)) +{ + if ((codecType != G729_CODEC)&&(codecType != G729A_CODEC) + &&(codecType != G729D_CODEC)&&(codecType != G729E_CODEC)&&(codecType != G729I_CODEC)){ + return APIG729_StsBadCodecType; + } + + *pCodecSize = ownDecoderSize(codecType); + + return APIG729_StsNoErr; + +} + + + +G729_CODECFUN( APIG729_Status, apiG729FPDecoder_Init, + (G729FPDecoder_Obj* decoderObj, G729Codec_Type codecType)) +{ + Ipp32s i,fltsize; + void* pBuf; + Ipp32f coeff[6]; + + Ipp8s* oldMemBuff; + + if ((codecType != G729_CODEC)&&(codecType != G729A_CODEC) + &&(codecType != G729D_CODEC)&&(codecType != G729E_CODEC)&&(codecType != G729I_CODEC)){ + return APIG729_StsBadCodecType; + } + + oldMemBuff = decoderObj->Mem.base; /* if Reinit */ + + ippsZero_16s((Ipp16s*)decoderObj,sizeof(G729FPDecoder_Obj)>>1) ; + + decoderObj->objPrm.objSize = ownDecoderSize(codecType); + decoderObj->objPrm.key = DEC_KEY; + decoderObj->objPrm.codecType = codecType; + + coeff[0] = b100[0]; + coeff[1] = b100[1]; + coeff[2] = b100[2]; + coeff[3] = a100[0]; + coeff[4] = -a100[1]; + coeff[5] = -a100[2]; + pBuf = (Ipp8s*)decoderObj + sizeof(G729FPDecoder_Obj); + ippsIIRInit_32f(&decoderObj->iirstate,coeff,2,NULL,pBuf); + + ippsIIRGetStateSize_32f(2,&fltsize); + decoderObj->phdMem = (Ipp8s *)((Ipp8s*)pBuf + fltsize); + PHDGetSize(&fltsize); + decoderObj->pHWState = (IppsWinHybridState_G729E_32f *)((Ipp8s*)decoderObj->phdMem + fltsize); + + ippsZero_32f(decoderObj->OldExcitationBuffer, PITCH_LAG_MAX+INTERPOL_LEN); + decoderObj->fBetaPreFilter = PITCH_SHARPMIN; + decoderObj->prevPitchDelay = 60; + decoderObj->fCodeGain = 0.; + decoderObj->fPitchGain = 0.; + ippsCopy_32f(InitLSP, decoderObj->OldLSP, LPC_ORDER); + + decoderObj->PastQuantEnergy[0]=decoderObj->PastQuantEnergy[1]=decoderObj->PastQuantEnergy[2]=decoderObj->PastQuantEnergy[3]=-14.0; + for(i=0; iPrevFreq[i][0], LPC_ORDER ); + decoderObj->prevMA = 0; + ippsCopy_32f (InitFrequences, decoderObj->prevLSF, LPC_ORDER ); + /* for G.729B */ + decoderObj->sFESeed = 21845; + /* CNG variables */ + decoderObj->prevFrameType = 3; + decoderObj->sCNGSeed = INIT_SEED_VAL; + decoderObj-> SID = 0.f; + decoderObj->fCurrGain = 0.f; + ownCOS_G729_32f((Ipp32f*)InitFrequences, decoderObj->SIDLSP, LPC_ORDER); + decoderObj->fSIDGain = SIDGainTbl[0]; + ippsZero_32f(decoderObj->SynFltMemory, BWD_LPC_ORDER); + PHDInit(decoderObj->phdMem); + if(codecType==G729A_CODEC) { + ippsZero_32f(decoderObj->PstFltMemoryA, LPC_ORDER); + decoderObj->fPastGain = 1.0; + ippsZero_32f(decoderObj->ResidualBufferA, PITCH_LAG_MAX+SUBFR_LEN); + decoderObj->ResidualMemory = decoderObj->ResidualBufferA + PITCH_LAG_MAX; + ippsZero_32f(decoderObj->PstSynMemoryA, LPC_ORDER); + decoderObj->fPreemphMemoryA = 0.f; + } else { + //PHDGetSize(&fltsize); + ippsWinHybridGetStateSize_G729E_32f(&fltsize); + decoderObj->pstMem = (Ipp8s *)((Ipp8s*)decoderObj->pHWState + fltsize); + + ippsZero_32f(decoderObj->SynthBuffer, BWD_ANALISIS_WND_LEN); + decoderObj->prevFracPitchDelay = 0; + ippsWinHybridInit_G729E_32f(decoderObj->pHWState); + ippsZero_32f(decoderObj->BackwardUnqLPC, BWD_LPC_ORDERP1); + decoderObj->BackwardUnqLPC[0] = 1.; + ippsZero_32f(decoderObj->BackwardLPCMemory, BWD_LPC_ORDERP1); + decoderObj->BackwardLPCMemory[0] = 1.; + decoderObj->lPrevVoicing = 0; + decoderObj->lPrevBFI = 0; + decoderObj->prevLPCMode = 0; + decoderObj->fFEInterpolationCoeff = 0.; + decoderObj->fInterpolationCoeff = 1.1f; /* Filter interpolation parameter */ + ippsZero_32f(decoderObj->PrevFlt, BWD_LPC_ORDERP1); + decoderObj->PrevFlt[0] = 1.; + decoderObj->lPrevPitchPT = 30; + decoderObj->lStatPitchPT = 0; + decoderObj->lStatPitch2PT = 0; + decoderObj->lStatFracPT = 0; + ippsZero_32f(decoderObj->OldBackwardLPC, BWD_LPC_ORDERP1); + decoderObj->OldBackwardLPC[0] = 1.; + decoderObj->OldBackwardRC[0] = decoderObj->OldBackwardRC[1] = 0.f; + decoderObj->fPitchGainMemory = 0.; + decoderObj->fCodeGainMemory = 0.; + decoderObj->fGainMuting = 1.; + decoderObj->lBFICounter = 0; + decoderObj->sBWDStatInd = 0; + decoderObj->lVoicing = 60; + decoderObj->g1PST = GAMMA1_POSTFLT_E; + decoderObj->g2PST = GAMMA2_POSTFLT_E; + decoderObj->gHarmPST = GAMMA_HARM_POSTFLT_E; + decoderObj->sBWDFrmCounter = 0; + decoderObj->sFWDFrmCounter = 0; + PSTInit(decoderObj->pstMem); + } + + apiG729FPDecoder_InitBuff(decoderObj,oldMemBuff); + + return APIG729_StsNoErr; +} + +G729_CODECFUN( APIG729_Status, apiG729FPDecoder_InitBuff, + (G729FPDecoder_Obj* decoderObj, Ipp8s *buff)) +{ + if(buff==NULL) return APIG729_StsBadArgErr; + if(decoderObj==NULL) return APIG729_StsBadArgErr; + + if(NULL==decoderObj || NULL==buff) + return APIG729_StsBadArgErr; + + decoderObj->Mem.base = buff; + decoderObj->Mem.CurPtr = decoderObj->Mem.base; + decoderObj->Mem.VecPtr = (Ipp32s *)(decoderObj->Mem.base+G729FP_ENCODER_SCRATCH_MEMORY_SIZE); + + return APIG729_StsNoErr; +} + +G729_CODECFUN( APIG729_Status, apiG729FPDecode, + (G729FPDecoder_Obj* decoderObj,const Ipp8u* src, Ipp32s frametype, Ipp16s* dst)) +{ + LOCAL_ALIGN_ARRAY(32, Ipp32f, backwardLPC, 2*BWD_LPC_ORDERP1, decoderObj); /* LPC Backward filter */ + LOCAL_ALIGN_ARRAY(32, Ipp32f, forwardLPC, 2*LPC_ORDERP1, decoderObj); /* LPC Forward filter */ + LOCAL_ALIGN_ARRAY(32, Ipp32f, backwardReflectCoeff, BWD_LPC_ORDER, decoderObj); /* LPC backward reflection coefficients */ + LOCAL_ALIGN_ARRAY(32, Ipp32f, forwardAutoCorr, BWD_LPC_ORDERP1, decoderObj); /* Autocorrelations (backward) */ + LOCAL_ALIGN_ARRAY(32, Ipp32f, CurrLSP, LPC_ORDER, decoderObj); /* LSPs */ + LOCAL_ALIGN_ARRAY(32, Ipp32f, ACELPCodeVec, SUBFR_LEN, decoderObj); /* ACELP codevector */ + LOCAL_ALIGN_ARRAY(32, Ipp32f, PhaseDispExc, SUBFR_LEN, decoderObj); /* excitation after phase dispersion */ + LOCAL_ALIGN_ARRAY(32, Ipp32f, flDst, FRM_LEN, decoderObj); + LOCAL_ALIGN_ARRAY(32, Ipp32f, TmpAlignVec, WINDOW_LEN,decoderObj); + LOCAL_ARRAY(Ipp32f, tmpLSP, LPC_ORDER, decoderObj); + LOCAL_ARRAY(Ipp32s, decPrm, 20, decoderObj); + LOCAL_ARRAY(Ipp32s, T2, 2, decoderObj); /* Decoded Pitch */ + LOCAL_ARRAY(Ipp32s, delayLine, 2, decoderObj); + + Ipp32f *Excitation,*pSynth; + Ipp32s i, j, NSbfr; + Ipp32s PitchDelay, index; + Ipp32s bfi; /* Bad frame indicator */ + Ipp32s badPitch=0; /* bad pitch indicator */ + Ipp32s LPCMode; /* Backward / Forward mode indication */ + Ipp32f PitchGain, CodeGain; /* fixed and adaptive codebook gain */ + Ipp32f tmp, energy; + Ipp32f *pLPC; + Ipp32s rate, highStatIndicator=0, aqLen, isSaturateAZ; + Ipp32s FrameType, pstLPCOrder, isBWDDominant=0, Vad, parm2; + Ipp32f tmp_lev; + + Ipp32s nsubfr; + IppStatus sts; + Ipp32s *pDecPrm; + const Ipp8u *pParm; + Ipp32f fTmp; + + if(NULL==decoderObj || NULL==src || NULL ==dst) + return APIG729_StsBadArgErr; + if(decoderObj->objPrm.objSize <= 0) + return APIG729_StsNotInitialized; + if(DEC_KEY != decoderObj->objPrm.key) + return APIG729_StsBadCodecType; + + Excitation = decoderObj->OldExcitationBuffer + PITCH_LAG_MAX + INTERPOL_LEN; + pSynth = decoderObj->SynthBuffer + BWD_SYNTH_MEM; + + pParm = src; + + if(frametype == -1){ /* erased*/ + decPrm[1] = 0; /* FrameType =sil ???*/ + decPrm[0] = 1; /* bfi = 1, corrupted*/ + ippsCopy_32f ((Ipp32f*)decoderObj->prevSID, (Ipp32f*)&decPrm[2], 4); + }else if(frametype == 0){ /* untransmitted sil*/ + decPrm[1] = 0; /* FrameType =sil */ + decPrm[0] = 0; /* bfi = 0, */ + ippsCopy_32f ((Ipp32f*)decoderObj->prevSID, (Ipp32f*)&decPrm[2], 4); + }else if(frametype == 1){ /* SID*/ + decPrm[1] = 1; /* FrameType=sid */ + decPrm[0] = 0; /* bfi = 0*/ + i=0; + decPrm[1+1] = ExtractBitsG729FP(&pParm,&i,1); + decPrm[1+2] = ExtractBitsG729FP(&pParm,&i,5); + decPrm[1+3] = ExtractBitsG729FP(&pParm,&i,4); + decPrm[1+4] = ExtractBitsG729FP(&pParm,&i,5); + ippsCopy_32f ((Ipp32f*)&decPrm[2], (Ipp32f*)decoderObj->prevSID, 4); + }else if(frametype == 2){ /* active frame D*/ + + decPrm[0] = 0; /* bfi = 0*/ + decPrm[1] = 2; /* FrameType=voice d */ + i=0; + decPrm[2] = ExtractBitsG729FP(&pParm,&i,1+N_BITS_1ST_STAGE); + decPrm[3] = ExtractBitsG729FP(&pParm,&i,N_BITS_2ND_STAGE*2); + decPrm[4] = ExtractBitsG729FP(&pParm,&i,8); + decPrm[5] = ExtractBitsG729FP(&pParm,&i,9); + decPrm[6] = ExtractBitsG729FP(&pParm,&i,2); + decPrm[7] = ExtractBitsG729FP(&pParm,&i,6); + decPrm[8] = ExtractBitsG729FP(&pParm,&i,4); + decPrm[9] = ExtractBitsG729FP(&pParm,&i,9); + decPrm[10] = ExtractBitsG729FP(&pParm,&i,2); + decPrm[11] = ExtractBitsG729FP(&pParm,&i,6); + + rate = G729E_MODE; + }else if(frametype == 3){ /* active frame */ + i=0; + decPrm[1] = 3; /* FrameType=voice e */ + decPrm[0] = 0; /* bfi = 0*/ + decPrm[1+1] = ExtractBitsG729FP(&pParm,&i,1+N_BITS_1ST_STAGE); + decPrm[1+2] = ExtractBitsG729FP(&pParm,&i,N_BITS_2ND_STAGE*2); + decPrm[1+3] = ExtractBitsG729FP(&pParm,&i,8); + decPrm[1+4] = ExtractBitsG729FP(&pParm,&i,1); + decPrm[1+5] = ExtractBitsG729FP(&pParm,&i,13); + decPrm[1+6] = ExtractBitsG729FP(&pParm,&i,4); + decPrm[1+7] = ExtractBitsG729FP(&pParm,&i,7); + decPrm[1+8] = ExtractBitsG729FP(&pParm,&i,5); + decPrm[1+9] = ExtractBitsG729FP(&pParm,&i,13); + decPrm[1+10] = ExtractBitsG729FP(&pParm,&i,4); + decPrm[1+11] = ExtractBitsG729FP(&pParm,&i,7); + decPrm[1+4] = (Parity(decPrm[1+3])+decPrm[1+4]) & 1; /* parity error (1) */ + rate = G729_BASE; + }else if(frametype == 4){ /* active frame E*/ + i=0; + decPrm[0] = 0; /* bfi = 0*/ + decPrm[1] = 4; /* FrameType */ + if(ExtractBitsG729FP(&pParm,&i,2)==0) { + decPrm[2] = 0; /*LPCMode*/ + + decPrm[3] = ExtractBitsG729FP(&pParm,&i,1+N_BITS_1ST_STAGE); + decPrm[4] = ExtractBitsG729FP(&pParm,&i,N_BITS_2ND_STAGE*2); + decPrm[5] = ExtractBitsG729FP(&pParm,&i,8); + decPrm[6] = ExtractBitsG729FP(&pParm,&i,1); + decPrm[7] = ExtractBitsG729FP(&pParm,&i,7); + decPrm[8] = ExtractBitsG729FP(&pParm,&i,7); + decPrm[9] = ExtractBitsG729FP(&pParm,&i,7); + decPrm[10] = ExtractBitsG729FP(&pParm,&i,7); + decPrm[11] = ExtractBitsG729FP(&pParm,&i,7); + decPrm[12] = ExtractBitsG729FP(&pParm,&i,7); + decPrm[13] = ExtractBitsG729FP(&pParm,&i,5); + decPrm[14] = ExtractBitsG729FP(&pParm,&i,7); + decPrm[15] = ExtractBitsG729FP(&pParm,&i,7); + decPrm[16] = ExtractBitsG729FP(&pParm,&i,7); + decPrm[17] = ExtractBitsG729FP(&pParm,&i,7); + decPrm[18] = ExtractBitsG729FP(&pParm,&i,7); + decPrm[19] = ExtractBitsG729FP(&pParm,&i,7); + + i = decPrm[5]>>1; + i &= 1; + decPrm[6] += i; + decPrm[6] = (Parity(decPrm[5])+decPrm[6]) & 1;/* parm[6] = parity error (1) */ + } else { + decPrm[2] = 1; /*LPCMode*/ + + decPrm[3] = ExtractBitsG729FP(&pParm,&i,8); + decPrm[4] = ExtractBitsG729FP(&pParm,&i,1); + decPrm[5] = ExtractBitsG729FP(&pParm,&i,13); + decPrm[6] = ExtractBitsG729FP(&pParm,&i,10); + decPrm[7] = ExtractBitsG729FP(&pParm,&i,7); + decPrm[8] = ExtractBitsG729FP(&pParm,&i,7); + decPrm[9] = ExtractBitsG729FP(&pParm,&i,7); + decPrm[10] = ExtractBitsG729FP(&pParm,&i,7); + decPrm[11] = ExtractBitsG729FP(&pParm,&i,5); + decPrm[12] = ExtractBitsG729FP(&pParm,&i,13); + decPrm[13] = ExtractBitsG729FP(&pParm,&i,10); + decPrm[14] = ExtractBitsG729FP(&pParm,&i,7); + decPrm[15] = ExtractBitsG729FP(&pParm,&i,7); + decPrm[16] = ExtractBitsG729FP(&pParm,&i,7); + decPrm[17] = ExtractBitsG729FP(&pParm,&i,7); + + i = decPrm[3]>>1; + i &= 1; + decPrm[4] += i; + decPrm[4] = (Parity(decPrm[3])+decPrm[4]) & 1;/* parm[4] = parity error (1) */ + } + rate = G729E_MODE; + } + pDecPrm = &decPrm[0]; + parm2 = pDecPrm[2]; + + bfi = *pDecPrm++; + FrameType = *pDecPrm++; + + if(bfi == 1) { + if(decoderObj->objPrm.codecType!=G729A_CODEC) { + FrameType = decoderObj->prevFrameType; + if(FrameType == 1) FrameType = 0; + } else { + if(decoderObj->prevFrameType == 1) FrameType = 1; + else FrameType = 0; + } + pDecPrm[-1] = FrameType; + } + + Vad = FrameType; + rate = FrameType - 2; + /* Decoding the Backward/Forward LPC mode */ + if( rate != G729E_MODE) LPCMode = 0; + else { + if (bfi != 0) { + LPCMode = decoderObj->prevLPCMode; /* Frame erased => LPCMode = previous LPCMode */ + *pDecPrm++ = LPCMode; + } else { + LPCMode = *pDecPrm++; + } + if(decoderObj->lPrevBFI != 0) decoderObj->lVoicing = decoderObj->lPrevVoicing; + + /* Backward LPC mode */ + ippsWinHybrid_G729E_32f(decoderObj->SynthBuffer, forwardAutoCorr, decoderObj->pHWState); + + /* Lag windowing */ + ippsMul_32f_I(lagBwd, &forwardAutoCorr[1], BWD_LPC_ORDER); + if (forwardAutoCorr[0]<1.0) forwardAutoCorr[0]=1.0; + + sts = ippsLevinsonDurbin_G729_32f(forwardAutoCorr, BWD_LPC_ORDER, &backwardLPC[BWD_LPC_ORDERP1], backwardReflectCoeff, &tmp_lev); + if(sts == ippStsOverflow) { + ippsCopy_32f(decoderObj->OldBackwardLPC,&backwardLPC[BWD_LPC_ORDERP1],BWD_LPC_ORDER+1); + backwardReflectCoeff[0] = decoderObj->OldBackwardRC[0]; + backwardReflectCoeff[1] = decoderObj->OldBackwardRC[1]; + } else { + ippsCopy_32f(&backwardLPC[BWD_LPC_ORDERP1],decoderObj->OldBackwardLPC,BWD_LPC_ORDER+1); + decoderObj->OldBackwardRC[0] = backwardReflectCoeff[0]; + decoderObj->OldBackwardRC[1] = backwardReflectCoeff[1]; + } + + /* Tests saturation of backwardLPC */ + isSaturateAZ = 0; + for (i=BWD_LPC_ORDERP1; i<2*BWD_LPC_ORDERP1; i++) if (backwardLPC[i] >= 8.) {isSaturateAZ = 1;break;} + if (isSaturateAZ == 1) ippsCopy_32f(decoderObj->BackwardLPCMemory, &backwardLPC[BWD_LPC_ORDERP1], BWD_LPC_ORDERP1); + else ippsCopy_32f(&backwardLPC[BWD_LPC_ORDERP1], decoderObj->BackwardLPCMemory, BWD_LPC_ORDERP1); + + /* Additional bandwidth expansion on backward filter */ + WeightLPCCoeff_G729(&backwardLPC[BWD_LPC_ORDERP1], BWD_GAMMA, BWD_LPC_ORDER, &backwardLPC[BWD_LPC_ORDERP1]); + + if(LPCMode == 1) { + if (!isVarZero(decoderObj->fFEInterpolationCoeff)) { + /* Interpolation of the backward filter after a bad frame */ + tmp = 1.f - decoderObj->fFEInterpolationCoeff; + pLPC = backwardLPC + BWD_LPC_ORDERP1; + ippsInterpolateC_G729_32f(pLPC, tmp, decoderObj->BackwardUnqLPC, decoderObj->fFEInterpolationCoeff, pLPC, BWD_LPC_ORDERP1); + } + } + } + if( bfi == 0) { + decoderObj->fGainMuting = 1.; + decoderObj->lBFICounter = 0; + } else if((decoderObj->lPrevBFI == 0) && (decoderObj->prevFrameType >3)) { + /* store the last good backward filter when the frame is erased */ + ippsCopy_32f(&backwardLPC[BWD_LPC_ORDERP1], decoderObj->BackwardUnqLPC, BWD_LPC_ORDERP1); + } + /* Update next frame synthesis signal */ + ippsCopy_32f(&decoderObj->SynthBuffer[FRM_LEN], &decoderObj->SynthBuffer[0], BWD_SYNTH_MEM); + + if(FrameType < 2) { + /* SID or Untr or Erased Frame */ + if(pDecPrm[-1] != 0) { + decoderObj->fSIDGain = SIDGainTbl[pDecPrm[3]]; + + /* Inverse quantization of the LSP */ + ippsLSFDecode_G729B_32f(&pDecPrm[0], (Ipp32f*)decoderObj->PrevFreq, decoderObj->SIDLSP); + } else { + /* non SID Frame + Case of 1st SID frame erased : quantize-decode + energy estimate stored in fSIDGain */ + if(decoderObj->prevFrameType > 1) { + QuantSIDGain_G729B(&decoderObj->SID, 0, &fTmp, &i); + decoderObj->fSIDGain = SIDGainTbl[i]; + } + } + if(decoderObj->prevFrameType > 1) { + decoderObj->fCurrGain = decoderObj->fSIDGain; + } else { + decoderObj->fCurrGain *= GAIN_INT_FACTOR; + decoderObj->fCurrGain += INV_GAIN_INT_FACTOR * decoderObj->fSIDGain; + } + + if(isVarZero(decoderObj->fCurrGain)) { + ippsZero_32f(Excitation,FRM_LEN); + PhaseDispersionUpdate_G729D(0.f,decoderObj->fCurrGain,decoderObj->phdMem); + PhaseDispersionUpdate_G729D(0.f,decoderObj->fCurrGain,decoderObj->phdMem); + } else { + ComfortNoiseExcitation_G729(decoderObj->fCurrGain, Excitation, &decoderObj->sCNGSeed, DECODER,NULL,decoderObj->phdMem,(Ipp8s *)TmpAlignVec); + } + + /* Interpolate the Lsp vectors */ + ippsInterpolateC_G729_32f(decoderObj->OldLSP, 0.5, decoderObj->SIDLSP, 0.5, tmpLSP, LPC_ORDER); + + ippsLSPToLPC_G729_32f(tmpLSP, forwardLPC); + ippsLSPToLPC_G729_32f(decoderObj->SIDLSP, &forwardLPC[LPC_ORDER+1]); + ippsCopy_32f(decoderObj->SIDLSP, decoderObj->OldLSP, LPC_ORDER); + + pLPC = forwardLPC; + if(decoderObj->objPrm.codecType!=G729A_CODEC) { + for (NSbfr = 0; NSbfr < FRM_LEN; NSbfr += SUBFR_LEN) { + ippsSynthesisFilter_G729_32f(pLPC, LPC_ORDER, &Excitation[NSbfr], &pSynth[NSbfr], SUBFR_LEN, &decoderObj->SynFltMemory[BWD_LPC_ORDER-LPC_ORDER]); + ippsMove_32f(&pSynth[NSbfr+SUBFR_LEN-BWD_LPC_ORDER], decoderObj->SynFltMemory, BWD_LPC_ORDER); + + T2[0] = decoderObj->prevPitchDelay; + pLPC += LPC_ORDERP1; + } + } else { + for (NSbfr = 0,i=0; NSbfr < FRM_LEN; NSbfr += SUBFR_LEN,i++) { + ippsSynthesisFilter_G729_32f(pLPC, LPC_ORDER, &Excitation[NSbfr], &flDst[NSbfr], SUBFR_LEN, decoderObj->SynFltMemory); + ippsCopy_32f(&flDst[NSbfr+SUBFR_LEN-LPC_ORDER], decoderObj->SynFltMemory, LPC_ORDER); + + T2[i] = decoderObj->prevPitchDelay; + pLPC += LPC_ORDERP1; + } + } + decoderObj->fBetaPreFilter = PITCH_SHARPMIN; + decoderObj->fInterpolationCoeff = 1.1f; + /* Reset for gain decoding in case of frame erasure */ + decoderObj->sBWDStatInd = 0; + highStatIndicator = 0; + /* Reset for pitch tracking in case of frame erasure */ + decoderObj->lStatPitchPT = 0; + /* Update the previous filter for the next frame */ + ippsCopy_32f(&forwardLPC[LPC_ORDERP1], decoderObj->PrevFlt, LPC_ORDERP1); + for(i=LPC_ORDERP1; iPrevFlt[i] = 0.; + } else { + /* Active frame */ + decoderObj->sCNGSeed = INIT_SEED_VAL; + /* Forward mode */ + if (LPCMode == 0) { + + /* Decode the LSFs to CurrLSP */ + if(bfi){ + ippsCopy_32f(decoderObj->prevLSF, CurrLSP, LPC_ORDER ); + ippsLSFDecodeErased_G729_32f(decoderObj->prevMA, (Ipp32f*)decoderObj->PrevFreq, decoderObj->prevLSF); + }else{ + Ipp32s indexes[4]; + indexes[0] = (pDecPrm[0] >> N_BITS_1ST_STAGE) & 1; + indexes[1] = pDecPrm[0] & (Ipp16s)(N_ELEM_1ST_STAGE - 1); + indexes[2] = (pDecPrm[1] >> N_BITS_2ND_STAGE) & (Ipp16s)(N_ELEM_2ND_STAGE - 1); + indexes[3] = pDecPrm[1] & (Ipp16s)(N_ELEM_2ND_STAGE - 1); + + decoderObj->prevMA = indexes[0]; + ippsLSFDecode_G729_32f(indexes, (Ipp32f*)decoderObj->PrevFreq, CurrLSP); + + ippsCopy_32f(CurrLSP, decoderObj->prevLSF, LPC_ORDER ); + + } + + /* Convert to LSPs */ + ownCOS_G729_32f(CurrLSP, CurrLSP, LPC_ORDER); + + pDecPrm += 2; + if( decoderObj->prevLPCMode == 0) { /* Interpolation of LPC for the 2 subframes */ + ippsInterpolateC_G729_32f(decoderObj->OldLSP, 0.5, CurrLSP, 0.5, tmpLSP, LPC_ORDER); + + ippsLSPToLPC_G729_32f(tmpLSP, forwardLPC); + ippsLSPToLPC_G729_32f(CurrLSP, &forwardLPC[LPC_ORDER+1]); + } else { + /* no interpolation */ + ippsLSPToLPC_G729_32f(CurrLSP, forwardLPC); /* Subframe 1*/ + ippsCopy_32f(forwardLPC, &forwardLPC[LPC_ORDERP1], LPC_ORDERP1); /* Subframe 2 */ + } + + /* update the LSFs for the next frame */ + ippsCopy_32f(CurrLSP, decoderObj->OldLSP, LPC_ORDER); + + decoderObj->fInterpolationCoeff = 1.1f; + pLPC = forwardLPC; + aqLen = LPC_ORDER; + /* update the previous filter for the next frame */ + ippsCopy_32f(&forwardLPC[LPC_ORDERP1], decoderObj->PrevFlt, LPC_ORDERP1); + for(i=LPC_ORDERP1; iPrevFlt[i] = 0.; + } else { + InterpolatedBackwardFilter_G729(backwardLPC, decoderObj->PrevFlt, &decoderObj->fInterpolationCoeff); + pLPC = backwardLPC; + aqLen = BWD_LPC_ORDER; + /* update the previous filter for the next frame */ + ippsCopy_32f(&backwardLPC[BWD_LPC_ORDERP1], decoderObj->PrevFlt, BWD_LPC_ORDERP1); + } + + for (NSbfr = 0,nsubfr=0; NSbfr < FRM_LEN; NSbfr += SUBFR_LEN,nsubfr++) { + index = *pDecPrm++; /* pitch index */ + + if(NSbfr == 0) { + if (rate == G729D_MODE) i = 0; /* no pitch parity at 6.4 kb/s */ + else i = *pDecPrm++; /* get parity check result */ + badPitch = bfi + i; + } + + DecodeAdaptCodebookDelays(&decoderObj->prevPitchDelay, + &decoderObj->prevFracPitchDelay,delayLine,NSbfr, + badPitch,index,(G729Codec_Type)rate); + PitchDelay = delayLine[0]; + T2[nsubfr] = PitchDelay; + /* adaptive codebook decode */ + ippsDecodeAdaptiveVector_G729_32f_I(delayLine, &Excitation[NSbfr]); + if(decoderObj->objPrm.codecType!=G729A_CODEC) { + /* Pitch tracking*/ + if( rate == G729E_MODE) { + PitchTracking_G729FPE(&decoderObj->prevPitchDelay, &decoderObj->prevFracPitchDelay, &decoderObj->lPrevPitchPT, &decoderObj->lStatPitchPT, + &decoderObj->lStatPitch2PT, &decoderObj->lStatFracPT); + } else { + i = decoderObj->prevPitchDelay; + j = decoderObj->prevFracPitchDelay; + PitchTracking_G729FPE(&i, &j, &decoderObj->lPrevPitchPT, &decoderObj->lStatPitchPT, + &decoderObj->lStatPitch2PT, &decoderObj->lStatFracPT); + } + } + /* Fixed codebook decode*/ + ippsZero_32f(ACELPCodeVec,SUBFR_LEN); + if (rate == G729_BASE) { + /* case base mode or annex A*/ + LOCAL_ARRAY(Ipp32s, Position, 4, decoderObj); + Ipp32s lTmpIndex, sign; + + if(bfi != 0) /* Bad frame */ + { + lTmpIndex = (Ipp32s)Rand_16s(&decoderObj->sFESeed) & (Ipp16s)0x1fff; /* 13 bits random */ + sign = (Ipp32s)Rand_16s(&decoderObj->sFESeed) & (Ipp16s)0x000f; /* 4 bits random */ + }else{ + lTmpIndex = pDecPrm[0]; + sign = pDecPrm[1]; + } + + /* First pulse's positions*/ + Position[0] = (lTmpIndex&7)*5; + + /* Second pulse's positions*/ + lTmpIndex >>= 3; + Position[1] = (lTmpIndex&7)*5 + 1; + /* Third pulse's positions*/ + lTmpIndex >>= 3; + Position[2] = (lTmpIndex&7)*5 + 2; + + /* Forth pulse's positions*/ + lTmpIndex >>= 3; + j = lTmpIndex; + lTmpIndex >>= 1; + Position[3] = (lTmpIndex&7)*5 + 3 + (j&1); + + /* Decode signs of 4 pulse and compose the algebraic codeword */ + for (j=0; j<4; j++) { + if (((sign>>j) & 1) != 0) { + ACELPCodeVec[Position[j]] = 1.0; + } else { + ACELPCodeVec[Position[j]] = -1.0; + } + } + pDecPrm += 2; + /* for gain decoding in case of frame erasure */ + decoderObj->sBWDStatInd = 0; + highStatIndicator = 0; + LOCAL_ARRAY_FREE(Ipp32s, Position, 4, decoderObj); + } else if (rate == G729D_MODE) { + /* case annex D*/ + LOCAL_ARRAY(Ipp32s, Position, 2, decoderObj); + Ipp32s lTmpIndex, sign; + + if(bfi != 0) /* Bad frame */ + { + lTmpIndex = (Ipp32s)Rand_16s(&decoderObj->sFESeed) & (Ipp16s)0x1fff; /* 13 bits random */ + sign = (Ipp32s)Rand_16s(&decoderObj->sFESeed) & (Ipp16s)0x000f; /* 4 bits random */ + }else{ + lTmpIndex = pDecPrm[0]; + sign = pDecPrm[1]; + } + + /* decode the positions of 4 pulses */ + i = lTmpIndex & 15; + Position[0] = trackTbl0[i]; + + lTmpIndex >>= 4; + i = lTmpIndex & 31; + Position[1] = trackTbl1[i]; + + /* find the algebraic codeword */ + + /* decode the signs of 2 pulses */ + for (j=0; j<2; j++) { + if (((sign>>j) & 1) != 0) { + ACELPCodeVec[Position[j]] += 1.0; + } else { + ACELPCodeVec[Position[j]] -= 1.0; + } + } + pDecPrm += 2; + /* for gain decoding in case of frame erasure */ + decoderObj->sBWDStatInd = 0; + highStatIndicator = 0; + LOCAL_ARRAY_FREE(Ipp32s, Position, 2, decoderObj); + } else if (rate == G729E_MODE) { + /* case annex E*/ + LOCAL_ARRAY(Ipp32s, tmp_parm, 5, decoderObj); + + if(bfi) + { + tmp_parm[0] = (Ipp32s)Rand_16s(&decoderObj->sFESeed); + tmp_parm[1] = (Ipp32s)Rand_16s(&decoderObj->sFESeed); + tmp_parm[2] = (Ipp32s)Rand_16s(&decoderObj->sFESeed); + tmp_parm[3] = (Ipp32s)Rand_16s(&decoderObj->sFESeed); + tmp_parm[4] = (Ipp32s)Rand_16s(&decoderObj->sFESeed); + }else{ + for(i=0;i<5;i++) + tmp_parm[i] = pDecPrm[i]; + } + + if (LPCMode == 0) { + Ipp32s pos1, pos2; + Ipp32f sign; + + /* decode the positions and signs of pulses and build the codeword */ + + pos1 = ((tmp_parm[0] & 7) * 5); + if (((tmp_parm[0]>>3) & 1) == 0) sign = 1.; + else sign = -1.; + ACELPCodeVec[pos1] = sign; + + pos2 = (((tmp_parm[0]>>4) & 7) * 5); + if (pos2 > pos1) sign = -sign; + + ACELPCodeVec[pos2] += sign; + + pos1 = ((tmp_parm[1] & 7) * 5) + 1; + if (((tmp_parm[1]>>3) & 1) == 0) sign = 1.; + else sign = -1.; + ACELPCodeVec[pos1] = sign; + + pos2 = (((tmp_parm[1]>>4) & 7) * 5) + 1; + if (pos2 > pos1) sign = -sign; + + ACELPCodeVec[pos2] += sign; + + pos1 = ((tmp_parm[2] & 7) * 5) + 2; + if (((tmp_parm[2]>>3) & 1) == 0) sign = 1.; + else sign = -1.; + ACELPCodeVec[pos1] = sign; + + pos2 = (((tmp_parm[2]>>4) & 7) * 5) + 2; + if (pos2 > pos1) sign = -sign; + + ACELPCodeVec[pos2] += sign; + + pos1 = ((tmp_parm[3] & 7) * 5) + 3; + if (((tmp_parm[3]>>3) & 1) == 0) sign = 1.; + else sign = -1.; + ACELPCodeVec[pos1] = sign; + + pos2 = (((tmp_parm[3]>>4) & 7) * 5) + 3; + if (pos2 > pos1) sign = -sign; + + ACELPCodeVec[pos2] += sign; + + pos1 = ((tmp_parm[4] & 7) * 5) + 4; + if (((tmp_parm[4]>>3) & 1) == 0) sign = 1.; + else sign = -1.; + ACELPCodeVec[pos1] = sign; + + pos2 = (((tmp_parm[4]>>4) & 7) * 5) + 4; + if (pos2 > pos1) sign = -sign; + + ACELPCodeVec[pos2] += sign; + /* for gain decoding in case of frame erasure */ + decoderObj->sBWDStatInd = 0; + highStatIndicator = 0; + } else { + Ipp32s lIdxCounter, track, pos1, pos2, pos3; + Ipp32f sign; + + /* decode the positions and signs of pulses and build the codeword */ + + track = (tmp_parm[0]>>10) & 7; + CLIP_TO_UPLEVEL(track,NUM_TRACK_ACELP); + + for (lIdxCounter=0; lIdxCounter<2; lIdxCounter++) { + pos1 = ((tmp_parm[lIdxCounter] & 7) * 5) + track; + if (((tmp_parm[lIdxCounter]>>3) & 1) == 0) sign = 1.; + else sign = -1.; + ACELPCodeVec[pos1] = sign; + + pos2 = (((tmp_parm[lIdxCounter]>>4) & 7) * 5) + track; + if (pos2 > pos1) sign = -sign; + + ACELPCodeVec[pos2] += sign; + + pos3 = (((tmp_parm[lIdxCounter]>>7) & 7) * 5) + track; + if (pos3 > pos2) sign = -sign; + + ACELPCodeVec[pos3] += sign; + + track++; + if (track > NUM_TRACK_ACELP) track = 0; + } + + for (lIdxCounter=2; lIdxCounter<5; lIdxCounter++) { + pos1 = ((tmp_parm[lIdxCounter] & 7) * 5) + track; + if (((tmp_parm[lIdxCounter]>>3) & 1) == 0) sign = 1.; + else sign = -1.; + ACELPCodeVec[pos1] = sign; + + pos2 = (((tmp_parm[lIdxCounter]>>4) & 7) * 5) + track; + if (pos2 > pos1) sign = -sign; + + ACELPCodeVec[pos2] += sign; + + track++; + if (track > NUM_TRACK_ACELP) track = 0; + } + /* for gain decoding in case of frame erasure */ + decoderObj->sBWDStatInd++; + if (decoderObj->sBWDStatInd >= 30) { + highStatIndicator = 1; + decoderObj->sBWDStatInd = 30; + } else highStatIndicator = 0; + } + pDecPrm += 5; + LOCAL_ARRAY_FREE(Ipp32s, tmp_parm, 5, decoderObj); + } + ippsHarmonicFilter_32f_I(decoderObj->fBetaPreFilter,PitchDelay,&ACELPCodeVec[PitchDelay],SUBFR_LEN-PitchDelay); + /* Decode pitch and codebook gains. */ + index = *pDecPrm++; /* index of energy VQ */ + if (bfi != 0) { + Ipp32f av_pred_en; + + if(rate == G729E_MODE) { + if (decoderObj->lBFICounter < 2) { + if (highStatIndicator) decoderObj->fPitchGain = 1.; + else decoderObj->fPitchGain = 0.95f; + decoderObj->fCodeGain = decoderObj->fCodeGainMemory; + } else { + decoderObj->fPitchGain = decoderObj->fPitchGainMemory * (decoderObj->fGainMuting); + decoderObj->fCodeGain = decoderObj->fCodeGainMemory * (decoderObj->fGainMuting); + if (highStatIndicator) { + if (decoderObj->lBFICounter > 10) decoderObj->fGainMuting *= 0.995f; + } else decoderObj->fGainMuting *= 0.98f; + } + } else { + decoderObj->fPitchGain *= 0.9f; + if(decoderObj->fPitchGain > 0.9f) decoderObj->fPitchGain=0.9f; + decoderObj->fCodeGain *= 0.98f; + } + + /* Update table of past quantized energies */ + + av_pred_en = 0.0f; + for (i = 0; i < 4; i++) + av_pred_en += decoderObj->PastQuantEnergy[i]; + av_pred_en = av_pred_en*0.25f - 4.0f; + if (av_pred_en < -14.0) av_pred_en = -14.0f; + + for (i = 3; i > 0; i--) + decoderObj->PastQuantEnergy[i] = decoderObj->PastQuantEnergy[i-1]; + decoderObj->PastQuantEnergy[0] = av_pred_en; + } else { + DecodeGain_G729(index, ACELPCodeVec, SUBFR_LEN, &decoderObj->fPitchGain, &decoderObj->fCodeGain, rate, decoderObj->PastQuantEnergy); + } + /* Update previous gains */ + decoderObj->fPitchGainMemory = decoderObj->fPitchGain; + decoderObj->fCodeGainMemory = decoderObj->fCodeGain; + /* - Update pitch sharpening "fBetaPreFilter" with quantized fPitchGain */ + decoderObj->fBetaPreFilter = decoderObj->fPitchGain; + CLIP_TO_UPLEVEL(decoderObj->fBetaPreFilter,PITCH_SHARPMAX); + CLIP_TO_LOWLEVEL(decoderObj->fBetaPreFilter,PITCH_SHARPMIN); + + /* Synthesis of speech corresponding to Excitation[] */ + if(decoderObj->objPrm.codecType!=G729A_CODEC) { + if(bfi != 0) { /* Bad frame */ + decoderObj->lBFICounter++; + if (decoderObj->lVoicing == 0 ) { + PitchGain = 0.; + CodeGain = decoderObj->fCodeGain; + } else { + PitchGain = decoderObj->fPitchGain; + CodeGain = 0.; + } + } else { + PitchGain = decoderObj->fPitchGain; + CodeGain = decoderObj->fCodeGain; + } + ippsInterpolateC_G729_32f(&Excitation[NSbfr], PitchGain, ACELPCodeVec, CodeGain, &Excitation[NSbfr], SUBFR_LEN); + + if (rate == G729D_MODE) { + PhaseDispersion_G729D(&Excitation[NSbfr], PhaseDispExc, decoderObj->fCodeGain, decoderObj->fPitchGain, ACELPCodeVec,decoderObj->phdMem,(Ipp8s *)TmpAlignVec); + ippsSynthesisFilter_G729_32f(pLPC, aqLen, PhaseDispExc, &pSynth[NSbfr], SUBFR_LEN, &decoderObj->SynFltMemory[BWD_LPC_ORDER-aqLen]); + } else { + ippsSynthesisFilter_G729_32f(pLPC, aqLen, &Excitation[NSbfr], &pSynth[NSbfr], SUBFR_LEN, &decoderObj->SynFltMemory[BWD_LPC_ORDER-aqLen]); + + /* Updates state machine for phase dispersion in + 6.4 kbps mode, if running at other rate */ + PhaseDispersionUpdate_G729D(decoderObj->fPitchGain, decoderObj->fCodeGain,decoderObj->phdMem); + } + + ippsCopy_32f(&pSynth[NSbfr+SUBFR_LEN-BWD_LPC_ORDER], decoderObj->SynFltMemory, BWD_LPC_ORDER); + } else { + ippsInterpolateC_G729_32f(&Excitation[NSbfr], decoderObj->fPitchGain, ACELPCodeVec, decoderObj->fCodeGain, &Excitation[NSbfr], SUBFR_LEN); + + ippsSynthesisFilter_G729_32f(pLPC, LPC_ORDER, &Excitation[NSbfr], &flDst[NSbfr], SUBFR_LEN, decoderObj->SynFltMemory); + for (i = 0; i < LPC_ORDER; i++) decoderObj->SynFltMemory[i] =flDst[NSbfr+(SUBFR_LEN-LPC_ORDER)+i]; + } + pLPC += aqLen+1; /* interpolated LPC parameters for next subframe */ + } + } + + if(bfi == 0) { + Ipp64f dTmpVar; + + ippsDotProd_32f64f(Excitation, Excitation, FRM_LEN, &dTmpVar); + decoderObj->SID = (Ipp32f)dTmpVar; + } + decoderObj->prevFrameType = FrameType; + ippsMove_32f(&decoderObj->OldExcitationBuffer[FRM_LEN], &decoderObj->OldExcitationBuffer[0], PITCH_LAG_MAX+INTERPOL_LEN); + + if(decoderObj->objPrm.codecType!=G729A_CODEC) { + energy = CalcEnergy_dB_G729(pSynth, FRM_LEN); + if (energy >= 40.) isBackwardModeDominant_G729(&isBWDDominant, LPCMode, &decoderObj->sBWDFrmCounter,&decoderObj->sFWDFrmCounter); + + decoderObj->lPrevBFI = bfi; + decoderObj->prevLPCMode = LPCMode; + decoderObj->lPrevVoicing = decoderObj->lVoicing; + + if (bfi != 0) decoderObj->fFEInterpolationCoeff = 1.; + else { + if (LPCMode == 0) decoderObj->fFEInterpolationCoeff = 0; + else { + if (isBWDDominant == 1) decoderObj->fFEInterpolationCoeff -= 0.1f; + else decoderObj->fFEInterpolationCoeff -= 0.5f; + if (decoderObj->fFEInterpolationCoeff < 0) decoderObj->fFEInterpolationCoeff= 0; + } + } + } + if(decoderObj->objPrm.codecType!=G729A_CODEC) { + /* Control adaptive parameters for postfiltering */ + if( LPCMode == 0) { + pLPC = forwardLPC; + pstLPCOrder = LPC_ORDER; + } else { + pLPC = backwardLPC; + pstLPCOrder = BWD_LPC_ORDER; + } + post_filter_I(decoderObj, pSynth, pLPC, T2[0], ((parm2 == 1) && (isBWDDominant == 1)), Vad, pstLPCOrder, flDst,rate); + } else { + Post_G729A(decoderObj,flDst, forwardLPC, T2, Vad); + } + /* Highpass filter */ + ippsIIR_32f_I(flDst,FRM_LEN,decoderObj->iirstate); + + /* Round to nearest and convert to Ipp16s*/ + { + for(i=0;i= 0.0) + fTmp += 0.5; + else fTmp -= 0.5; + if (fTmp > 32767.0 ) fTmp = 32767.0; + if (fTmp < -32768.0 ) fTmp = -32768.0; + dst[i] = (Ipp16s) fTmp; + } + } + //ippsConvert_32f16s_Sfs(flDst,dst,FRM_LEN,ippRndNear,0); /*A few difference between original code*/ + + CLEAR_SCRATCH_MEMORY(decoderObj); + + return APIG729_StsNoErr; +} +static void post_filter_I(G729FPDecoder_Obj* decoderObj, Ipp32f *pSynth, Ipp32f *pLPC, Ipp32s pitchDelay, Ipp32s dominant, + Ipp32s Vad, Ipp32s pstLPCOrder, Ipp32f *dst,Ipp32s rate) +{ + Ipp32s i, lSFVoice, len; + + if (rate != G729E_MODE) { + len = SHORTTERM_POSTFLT_LEN; + decoderObj->g1PST = GAMMA1_POSTFLT; + decoderObj->g2PST = GAMMA2_POSTFLT; + decoderObj->gHarmPST = GAMMA_HARM_POSTFLT; + } else { + len = SHORTTERM_POSTFLT_LEN_E; + /* If backward mode is dominant => progressively reduce postfiltering */ + if (dominant) { + decoderObj->gHarmPST -= 0.0125f; + CLIP_TO_LOWLEVEL(decoderObj->gHarmPST,0); + decoderObj->g1PST -= 0.035f; + CLIP_TO_LOWLEVEL(decoderObj->g1PST,0); + decoderObj->g2PST -= 0.0325f; + CLIP_TO_LOWLEVEL(decoderObj->g2PST,0); + } else { + decoderObj->gHarmPST += 0.0125f; + CLIP_TO_UPLEVEL(decoderObj->gHarmPST,GAMMA_HARM_POSTFLT_E); + decoderObj->g1PST += 0.035f; + CLIP_TO_UPLEVEL(decoderObj->g1PST,GAMMA1_POSTFLT_E); + decoderObj->g2PST += 0.0325f; + CLIP_TO_UPLEVEL(decoderObj->g2PST,GAMMA2_POSTFLT_E); + } + } + + decoderObj->lVoicing = 0; + for(i=0; ilVoicing = lSFVoice; + pLPC += pstLPCOrder+1; + } + return; +} + +static void Post_G729A(G729FPDecoder_Obj *decoderObj, Ipp32f *pSrcDstSynthSpeech, Ipp32f *pSrcLPC, + Ipp32s *pSrcDecodedPitch, Ipp32s Vad) +{ + LOCAL_ALIGN_ARRAY(32, Ipp32f, SynthBuffer, (FRM_LEN+LPC_ORDER),decoderObj); /* Synthesis */ + LOCAL_ALIGN_ARRAY(32, Ipp32f, pResidual, SUBFR_LEN,decoderObj); /* ResidualMemory after pitch postfiltering */ + LOCAL_ALIGN_ARRAY(32, Ipp32f, pSynthPST, FRM_LEN,decoderObj); /* post filtered synthesis speech */ + LOCAL_ARRAY(Ipp32f, LPCGama2, LPC_ORDERP1,decoderObj); /* bandwidth expanded LP parameters */ + LOCAL_ARRAY(Ipp32f, LPCGama1, LPC_ORDERP1,decoderObj); + LOCAL_ARRAY(Ipp32f, ImpRespPST, PST_IMPRESP_LEN,decoderObj); + Ipp32f *pLPC; + Ipp32s PitchDelay, pitchMaxBound, pitchMinBound; /* closed-loop pitch search range */ + Ipp32s i, NSbfr; /* index for beginning of subframe */ + Ipp32f fTmp, fTmp1, fTmp2; + Ipp32f *pSynth; + Ipp64f sum, sum1; + Ipp64f dGain,dg0; + Ipp32f fMaxCorr; + Ipp32f gainM1, gain; + Ipp32f fEnergy, fEnergy0; + + pLPC = pSrcLPC; + + pSynth = &SynthBuffer[LPC_ORDER]; + + ippsCopy_32f(decoderObj->PstFltMemoryA,SynthBuffer,LPC_ORDER); + ippsCopy_32f(pSrcDstSynthSpeech,pSynth,FRM_LEN); + + for (NSbfr = 0; NSbfr < FRM_LEN; NSbfr += SUBFR_LEN) { + /* Find pitch range t0_min - t0_max */ + + pitchMinBound = *pSrcDecodedPitch++ - 3; + pitchMaxBound = pitchMinBound+6; + if (pitchMaxBound > PITCH_LAG_MAX) { + pitchMaxBound = PITCH_LAG_MAX; + pitchMinBound = pitchMaxBound-6; + } + + /* Find weighted filter coefficients LPCGama2 and LPCGama1 */ + + WeightLPCCoeff_G729(pLPC, GAMMA2_POSTFLT, LPC_ORDER, LPCGama2); + WeightLPCCoeff_G729(pLPC, GAMMA1_POSTFLT, LPC_ORDER, LPCGama1 ); + + /* filtering of synthesis speech by A(z/GAMMA2_POSTFLT) to find ResidualMemory */ + + ippsConvBiased_32f(LPCGama2,LPC_ORDER+1,&pSynth[NSbfr],SUBFR_LEN+LPC_ORDER,decoderObj->ResidualMemory,SUBFR_LEN,LPC_ORDER); + + /* pitch postfiltering */ + + if (Vad > 1) { + + ippsCrossCorrLagMax_32f64f(decoderObj->ResidualMemory, &decoderObj->ResidualMemory[-pitchMaxBound], SUBFR_LEN, pitchMaxBound-pitchMinBound, &sum, &PitchDelay); + PitchDelay = (pitchMaxBound-pitchMinBound-PitchDelay) + pitchMinBound; + fMaxCorr = (Ipp32f)sum; + + /* Compute the energy of the signal delayed by PitchDelay */ + + ippsDotProd_32f64f(&decoderObj->ResidualMemory[-PitchDelay], &decoderObj->ResidualMemory[-PitchDelay], SUBFR_LEN, &sum); + fEnergy = (Ipp32f)(sum+0.5); + + /* Compute the signal energy in the present subframe */ + + ippsDotProd_32f64f(decoderObj->ResidualMemory, decoderObj->ResidualMemory, SUBFR_LEN, &sum); + fEnergy0 = (Ipp32f)(sum+0.5); + + if (fMaxCorr < 0.0) fMaxCorr = 0.0; + + /* prediction gain (dB)= -10 log(1-fMaxCorr*fMaxCorr/(fEnergy*fEnergy0)) */ + + fTmp = fMaxCorr*fMaxCorr; + if (fTmp < fEnergy*fEnergy0*0.5) { /* if prediction gain < 3 dB */ + ippsCopy_32f(decoderObj->ResidualMemory, pResidual, SUBFR_LEN); + } else { + if (fMaxCorr > fEnergy) { /* if pitch gain > 1 */ + gainM1 = INV_GAMMA_POSTFLT_G729A; + gain = GAMMA2_POSTFLT_G729A; + } else { + fMaxCorr *= GAMMA_POSTFLT_G729A; + gain = 1.0f/(fMaxCorr+fEnergy) * fMaxCorr; + gainM1 = 1.0f - gain; + } + ippsInterpolateC_G729_32f(decoderObj->ResidualMemory, gainM1, &decoderObj->ResidualMemory[-PitchDelay], gain, pResidual, SUBFR_LEN); + } + } else + ippsCopy_32f(decoderObj->ResidualMemory,pResidual,SUBFR_LEN); + + /* impulse response of A(z/GAMMA2_POSTFLT)/A(z/GAMMA1_POSTFLT) */ + + ippsCopy_32f(LPCGama2, ImpRespPST, LPC_ORDERP1); + ippsZero_32f(&ImpRespPST[LPC_ORDERP1],PST_IMPRESP_LEN-LPC_ORDERP1); + ippsSynthesisFilter_G729_32f(LPCGama1, LPC_ORDER, ImpRespPST, ImpRespPST, PST_IMPRESP_LEN, &ImpRespPST[LPC_ORDER+1]); + + /* 1st correlation of impulse response */ + ippsDotProd_32f64f(ImpRespPST, ImpRespPST, PST_IMPRESP_LEN, &sum); + ippsDotProd_32f64f(ImpRespPST, &ImpRespPST[1], PST_IMPRESP_LEN-1, &sum1); + if(sum1 <= 0.0) { + fTmp2 = 0.0; + } else { + fTmp1 = (Ipp32f)sum; + fTmp2 = (Ipp32f)sum1; + fTmp2 = fTmp2*TILT_FLT_FACTOR/fTmp1; + } + ippsPreemphasize_32f_I(fTmp2, pResidual, SUBFR_LEN,&decoderObj->fPreemphMemoryA); + + /* filtering through 1/A(z/GAMMA1_POSTFLT) */ + + ippsSynthesisFilter_G729_32f(LPCGama1, LPC_ORDER, pResidual, &pSynthPST[NSbfr], SUBFR_LEN, decoderObj->PstSynMemoryA); + for (i = 0; i < LPC_ORDER; i++) decoderObj->PstSynMemoryA[i] =pSynthPST[NSbfr+(SUBFR_LEN-LPC_ORDER)+i]; + + + + /* scale output to input */ + ippsDotProd_32f64f(&pSynthPST[NSbfr], &pSynthPST[NSbfr], SUBFR_LEN, &dGain); + if(isVarZero(dGain)) { + decoderObj->fPastGain = 0.f; + } else { + ippsDotProd_32f64f(&pSynth[NSbfr], &pSynth[NSbfr], SUBFR_LEN, &dg0); + if(dg0 > 0) { + dg0 = sqrt(dg0/ dGain); + dg0 *= AGC_FACTOR_1M_G729A; + } + + /* compute gain(n) = AGC_FACTOR gain(n-1) + (1-AGC_FACTOR)gain_in/dGain */ + ippsGainControl_G729_32f_I((Ipp32f)dg0, AGC_FACTOR_G729A, &pSynthPST[NSbfr], &decoderObj->fPastGain); + } + + /* update residual memory */ + + ippsMove_32f(&decoderObj->ResidualMemory[SUBFR_LEN-PITCH_LAG_MAX], &decoderObj->ResidualMemory[-PITCH_LAG_MAX], PITCH_LAG_MAX); + + pLPC += LPC_ORDERP1; + } + + /* update pSynth[] buffer */ + + ippsCopy_32f(&pSynth[FRM_LEN-LPC_ORDER], decoderObj->PstFltMemoryA, LPC_ORDER); + + /* overwrite synthesis speech by postfiltered synthesis speech */ + + ippsCopy_32f(pSynthPST, pSrcDstSynthSpeech, FRM_LEN); + + LOCAL_ARRAY_FREE(Ipp32f, ImpRespPST, PST_IMPRESP_LEN,decoderObj); + LOCAL_ARRAY_FREE(Ipp32f, LPCGama1, LPC_ORDERP1,decoderObj); + LOCAL_ARRAY_FREE(Ipp32f, LPCGama2, LPC_ORDERP1,decoderObj); + LOCAL_ALIGN_ARRAY_FREE(32, Ipp32f, pSynthPST, FRM_LEN,decoderObj); /* post filtered synthesis speech */ + LOCAL_ALIGN_ARRAY_FREE(32, Ipp32f, pResidual, SUBFR_LEN,decoderObj); /* ResidualMemory after pitch postfiltering */ + LOCAL_ALIGN_ARRAY_FREE(32, Ipp32f, SynthBuffer, (FRM_LEN+LPC_ORDER),decoderObj); /* Synthesis */ + + return; +} diff --git a/encg723.c b/encg723.c new file mode 100644 index 0000000..b97fe4e --- /dev/null +++ b/encg723.c @@ -0,0 +1,721 @@ +/*///////////////////////////////////////////////////////////////////////////// +// +// 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-2007 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 ippEULA.rtf or ippEULA.txt 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 "vadg723.h" +#include "owng723.h" + +/* Declaration of local functions */ +static void PastAverageFilter_G723(G723Encoder_Obj* encoderObj); +static void GetReflectionCoeff_G723(Ipp16s *pSrcLPC, Ipp16s *pDstReflectCoeff, Ipp16s *pDstReflectCoeffSFS); +static Ipp32s ItakuraDist_G723(Ipp16s *pSrcReflectCoeff, Ipp16s ReflectCoeffSFS, Ipp16s *pSrcAutoCorrs, Ipp16s energy); + +static Ipp32s EncoderObjSize(void){ + Ipp32s fltSize; + Ipp32s objSize = sizeof(G723Encoder_Obj); + VoiceActivityDetectSize_G723(&fltSize); + objSize += fltSize; /* VAD decision memory size*/ + return objSize; +} + +G723_CODECFUN( APIG723_Status, apiG723Codec_ScratchMemoryAlloc,(Ipp32s *pCodecSize)) { + if(NULL==pCodecSize) + return APIG723_StsBadArgErr; + *pCodecSize = G723_ENCODER_SCRATCH_MEMORY_SIZE; + return APIG723_StsNoErr; +} + +G723_CODECFUN( APIG723_Status, apiG723Encoder_Alloc, (Ipp32s *pCodecSize)) +{ + *pCodecSize = EncoderObjSize(); + return APIG723_StsNoErr; +} +G723_CODECFUN( APIG723_Status, apiG723Encoder_ControlMode, + (G723Encoder_Obj* encoderObj, Ipp32u mode)) +{ + encoderObj->objPrm.mode = mode; + + return APIG723_StsNoErr; +} + +G723_CODECFUN( APIG723_Status, apiG723Encoder_Mode, + (G723Encoder_Obj* encoderObj, Ipp32u 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, Ipp32u mode)) +{ + Ipp32s i; + Ipp8s* oldMemBuff; + + if(NULL==encoderObj) + return APIG723_StsBadArgErr; + + oldMemBuff = encoderObj->Mem.base; /* if Reinit */ + + ippsZero_16s((Ipp16s*)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 = (Ipp8s*)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; + //} + + apiG723Encoder_InitBuff(encoderObj,oldMemBuff); + + return APIG723_StsNoErr; +} + +G723_CODECFUN( APIG723_Status, apiG723Encoder_InitBuff, + (G723Encoder_Obj* encoderObj, Ipp8s *buff)) +{ + if(NULL==encoderObj) return APIG723_StsBadArgErr; + if(NULL==buff) 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 = (Ipp32s *)(encoderObj->Mem.base+G723_ENCODER_SCRATCH_MEMORY_SIZE); + + return APIG723_StsNoErr; +} + +void EncoderCNG_G723(G723Encoder_Obj* encoderObj, ParamStream_G723 *Params, Ipp16s *pExcitation, Ipp16s *pDstLPC) +{ + Ipp16s sQuantGain, sTmp; + Ipp32s i; + + LOCAL_ARRAY(Ipp16s, 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=(Ipp16s)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=(Ipp16s)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 = (Ipp16s)Abs_16s(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(Ipp16s, qIndex,3,encoderObj) ; + + /* Check stationarity */ + + PastAverageFilter_G723(encoderObj); + + + if(!encoderObj->AdaptEnableFlag) /* adaptation enabled */ + for(i=0;iprevSidLpc[i+1] = (Ipp16s)(-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] = (Ipp16s)(Params->lLSPIdx & 0xff); + qIndex[1] = (Ipp16s)((Params->lLSPIdx>>8) & 0xff); + qIndex[0] = (Ipp16s)((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(Ipp16s, qIndex,3,encoderObj) ; + } + + /* Compute new excitation */ + if(encoderObj->PastFrameType == G723_ActiveFrm) { + encoderObj->CurrGain = encoderObj->sSidGain; + } else { + encoderObj->CurrGain = (Ipp16s)(( (encoderObj->CurrGain*0xE000)+ + (encoderObj->sSidGain*0x2000) )>>16) ; + } + { + + LOCAL_ARRAY(Ipp8s, 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(Ipp8s, 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(Ipp16s, curCoeff,G723_LPC_ORDER,encoderObj) ; + return; +} + +void UpdateAutoCorrs_G723(G723Encoder_Obj* encoderObj, const Ipp16s *pSrcAutoCorrs, const Ipp16s *pSrcAutoCorrsSFS) +{ + + Ipp32s i, lNsbfr; + Ipp16s sMinSFS, sTmp; + Ipp16s m1, m2; + + LOCAL_ARRAY(Ipp32s, lSumAutoCorrs,G723_LPC_ORDER+1,encoderObj) ; + + /* Update Acf and ShAcf */ + for(i=0; iAutoCorrs[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 = (Ipp16s)IPP_MIN(pSrcAutoCorrsSFS[0],pSrcAutoCorrsSFS[1]); + m2 = (Ipp16s)IPP_MIN(pSrcAutoCorrsSFS[2],pSrcAutoCorrsSFS[3]); + sMinSFS = (Ipp16s)((IPP_MIN(m1,m2))+14); + + /* Calculate the acfs sum */ + ippsZero_16s((Ipp16s*)lSumAutoCorrs,2*G723_LPC_ORDERP1); + + for(lNsbfr=0; lNsbfr<4; lNsbfr++) { + sTmp = (Ipp16s)(sMinSFS - pSrcAutoCorrsSFS[lNsbfr]); + if(sTmp < 0) { + sTmp = (Ipp16s)(-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]<AutoCorrs[i]=(Ipp16s)(lSumAutoCorrs[i]>>sTmp); + encoderObj->AutoCorrsSFS[0] = (Ipp16s)(sMinSFS - sTmp); + + LOCAL_ARRAY_FREE(Ipp32s, lSumAutoCorrs,G723_LPC_ORDER+1,encoderObj) ; + + return; +} + +void PastAverageFilter_G723(G723Encoder_Obj* encoderObj) +{ + Ipp32s i, j; + Ipp16s sMinSFS, sTmp; + + LOCAL_ARRAY(Ipp32s, lSumAutoCorrs,G723_LPC_ORDER+1,encoderObj) ; + LOCAL_ARRAY(Ipp16s, pCorr,G723_LPC_ORDER+1,encoderObj) ; + + /* Search ShAcf min */ + sMinSFS = (Ipp16s)IPP_MIN(encoderObj->AutoCorrsSFS[1],encoderObj->AutoCorrsSFS[2]); + sMinSFS = (Ipp16s)((IPP_MIN(sMinSFS,encoderObj->AutoCorrsSFS[3]))+14); + + ippsZero_16s((Ipp16s*)lSumAutoCorrs,2*G723_LPC_ORDERP1); + + for(i=1; i <= N_AUTOCORRS_BLOCKS; i ++) { + sTmp = (Ipp16s)(sMinSFS - encoderObj->AutoCorrsSFS[i]); + if(sTmp < 0) { + sTmp=(Ipp16s)(-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); + } + + ippsLevinsonDurbin_G723_16s(pCorr, &sTmp, &sTmp, encoderObj->LPCSID); + + LOCAL_ARRAY_FREE(Ipp16s, pCorr,G723_LPC_ORDER+1,encoderObj) ; + LOCAL_ARRAY_FREE(Ipp32s, lSumAutoCorrs,G723_LPC_ORDER+1,encoderObj) ; + + return; +} + +void GetReflectionCoeff_G723(Ipp16s *pSrcLPC, Ipp16s *pDstReflectCoeff, Ipp16s *pDstReflectCoeffSFS) +{ + Ipp32s i, j; + Ipp16s SFS; + Ipp32s lCorr; + + ippsDotProd_16s32s_Sfs(pSrcLPC,pSrcLPC,G723_LPC_ORDER,&lCorr,-1); + lCorr = lCorr >> 1; + lCorr = lCorr + 0x04000000; + SFS = (Ipp16s)(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>SFS; + pDstReflectCoeff[0] = Cnvrt_NR_32s16s(lCorr); + + for(i=1; i<=G723_LPC_ORDER; i++) { + lCorr = -(pSrcLPC[i-1]<<13); + for(j=0; j>(SFS); + pDstReflectCoeff[i] = Cnvrt_NR_32s16s(lCorr); + } + } + return; +} + + +Ipp32s ItakuraDist_G723(Ipp16s *pSrcReflectCoeff, Ipp16s ReflectCoeffSFS, Ipp16s *pSrcAutoCorrs, Ipp16s energy) +{ + Ipp32s i, lSum, lThresh; + + lSum = 0; + for(i=0; i <= G723_LPC_ORDER; i++) { + lSum += pSrcReflectCoeff[i] * (pSrcAutoCorrs[i]>>2); + } + + lThresh = Cnvrt_32s16s(((energy * 7000)+0x4000)>>15) + energy; + lThresh <<= (ReflectCoeffSFS + 8); + + /* The condition (lSum < lThresh) has been corrected to the new condition (lSum <= lThresh). */ + /* The g723.1 speech codec has worked with digital silence incorrectly by use the old condition. */ + return ((lSum <= lThresh)); +} + +G723_CODECFUN( APIG723_Status, apiG723Encode, + (G723Encoder_Obj* encoderObj,const Ipp16s* src, Ipp16s rat, Ipp8s* pDstBitStream )) +{ + Ipp32s i, lNSbfr; + + LOCAL_ALIGN_ARRAY(16, Ipp16s, HPFltSignal,G723_FRM_LEN, encoderObj); + LOCAL_ALIGN_ARRAY(16, Ipp16s, AlignTmpVec,G723_MAX_PITCH+G723_FRM_LEN, encoderObj); + LOCAL_ALIGN_ARRAY(16, Ipp16s, CurrLPC,4*G723_LPC_ORDER, encoderObj) ; + LOCAL_ALIGN_ARRAY(16, Ipp16s, CurrQLPC,4*(G723_LPC_ORDER+1), encoderObj) ; + LOCAL_ALIGN_ARRAY(16, Ipp16s, WeightedLPC,8*G723_LPC_ORDER, encoderObj) ; + LOCAL_ALIGN_ARRAY(16, Ipp16s, CurrLSF,G723_LPC_ORDER, encoderObj) ; + LOCAL_ARRAY(GainInfo_G723, GainInfo,4, encoderObj) ; + + ParamStream_G723 CurrentParams; + + Ipp16s *pData; + Ipp16s isNotSineWave; + + CurrentParams.FrameType = G723_ActiveFrm; + + if(NULL==encoderObj || NULL==src || NULL ==pDstBitStream) + return APIG723_StsBadArgErr; + if(encoderObj->objPrm.objSize <= 0) + return APIG723_StsNotInitialized; + if(G723_ENC_KEY != encoderObj->objPrm.key) + return APIG723_StsBadCodecType; + + if(rat < 0 || rat > 1) { + rat = (Ipp16s)encoderObj->objPrm.rat; + } else { + encoderObj->objPrm.rat = rat; + } + + CurrentParams.currRate = (G723_Rate)rat; + if ( CurrentParams.currRate == G723_Rate53) encoderObj->sSearchTime = 120; /* reset max time */ + + CurrentParams.isBadFrame = (Ipp16s) 0 ; + + if ( encoderObj->objPrm.mode&G723Encode_HF_Enabled ) { + /* High-pass filtering. Section 2.3 */ + ippsHighPassFilter_G723_16s(src,HPFltSignal,encoderObj->HPFltMem); + } else { + ippsRShiftC_16s(src,1,HPFltSignal,G723_FRM_LEN); + } + + /* Compute the Unquantized Lpc */ + { + + Ipp16s sTmp; + + LOCAL_ALIGN_ARRAY(16, Ipp16s, AutoCorrs,(G723_LPC_ORDER+1)*4,encoderObj) ; + LOCAL_ARRAY(Ipp16s, AutoCorrsSFS,4,encoderObj) ; + + ippsCopy_16s(encoderObj->SignalDelayLine,AlignTmpVec,G723_HALFFRM_LEN); + ippsCopy_16s(HPFltSignal,&AlignTmpVec[G723_HALFFRM_LEN],G723_FRM_LEN); + + ippsAutoCorr_G723_16s(AlignTmpVec,&AutoCorrsSFS[0],AutoCorrs); + ippsAutoCorr_G723_16s(&AlignTmpVec[G723_SBFR_LEN],&AutoCorrsSFS[1],&AutoCorrs[G723_LPC_ORDERP1]); + ippsAutoCorr_G723_16s(&AlignTmpVec[2*G723_SBFR_LEN],&AutoCorrsSFS[2],&AutoCorrs[2*G723_LPC_ORDERP1]); + ippsAutoCorr_G723_16s(&AlignTmpVec[3*G723_SBFR_LEN],&AutoCorrsSFS[3],&AutoCorrs[3*G723_LPC_ORDERP1]); + + /* LPC calculation for all subframes */ + + ippsLevinsonDurbin_G723_16s( AutoCorrs, &encoderObj->SineWaveDetector, &sTmp , CurrLPC); + ippsLevinsonDurbin_G723_16s( &AutoCorrs[G723_LPC_ORDERP1], &encoderObj->SineWaveDetector, &sTmp , &CurrLPC[G723_LPC_ORDER]); + ippsLevinsonDurbin_G723_16s( &AutoCorrs[2*G723_LPC_ORDERP1], &encoderObj->SineWaveDetector, &sTmp , &CurrLPC[2*G723_LPC_ORDER]); + ippsLevinsonDurbin_G723_16s( &AutoCorrs[3*G723_LPC_ORDERP1], &encoderObj->SineWaveDetector, &sTmp , &CurrLPC[3*G723_LPC_ORDER]); + + /* Update sine detector */ + UpdateSineDetector(&encoderObj->SineWaveDetector, &isNotSineWave); + /* Update CNG Acf memories */ + UpdateAutoCorrs_G723(encoderObj, AutoCorrs, AutoCorrsSFS); + + LOCAL_ARRAY_FREE(Ipp16s, AutoCorrsSFS,4,encoderObj) ; + LOCAL_ALIGN_ARRAY_FREE(16, Ipp16s, AutoCorrs,(G723_LPC_ORDER+1)*4,encoderObj) ; + + } + /* Convert to Lsp */ + ippsLPCToLSF_G723_16s(&CurrLPC[G723_LPC_ORDER*3], encoderObj->PrevLPC, CurrLSF); + + /* Compute the Vad */ + CurrentParams.FrameType = G723_ActiveFrm; + if( encoderObj->objPrm.mode&G723Encode_VAD_Enabled){ + VoiceActivityDetect_G723(HPFltSignal, (Ipp16s*)&encoderObj->prevSidLpc,(Ipp16s*)&encoderObj->PrevOpenLoopLags, + isNotSineWave,&i,&encoderObj->AdaptEnableFlag,encoderObj->vadMem,AlignTmpVec); + CurrentParams.FrameType = (G723_FrameType)i; + } + + /* VQ Lsp vector */ + + ippsLSFQuant_G723_16s32s(CurrLSF, encoderObj->PrevLPC, &CurrentParams.lLSPIdx); + + ippsCopy_16s(&encoderObj->SignalDelayLine[G723_SBFR_LEN],AlignTmpVec,G723_SBFR_LEN); + ippsCopy_16s(&HPFltSignal[2*G723_SBFR_LEN],encoderObj->SignalDelayLine,2*G723_SBFR_LEN); + ippsCopy_16s(HPFltSignal,&AlignTmpVec[G723_SBFR_LEN],3*G723_SBFR_LEN); + ippsCopy_16s(AlignTmpVec,HPFltSignal,G723_FRM_LEN); + + /* Compute Perceptual filter Lpc coefficients */ + + for ( i = 0 ; i < 4 ; i ++ ) { + /* Compute the FIR and IIR coefficient of the perceptual weighting filter */ + ippsMul_NR_16s_Sfs(&CurrLPC[i*G723_LPC_ORDER],PerceptualFltCoeffTbl, + &WeightedLPC[2*i*G723_LPC_ORDER],G723_LPC_ORDER,15); + ippsMul_NR_16s_Sfs(&CurrLPC[i*G723_LPC_ORDER],&PerceptualFltCoeffTbl[G723_LPC_ORDER], + &WeightedLPC[(2*i+1)*G723_LPC_ORDER],G723_LPC_ORDER,15); + /* do filtering */ + ippsIIR16s_G723_16s_I(&WeightedLPC[2*i*G723_LPC_ORDER],&HPFltSignal[i*G723_SBFR_LEN],encoderObj->WeightedFltMem); + } + + + /* Compute Open loop pitch estimates */ + + ippsCopy_16s(encoderObj->PrevWeightedSignal,AlignTmpVec,G723_MAX_PITCH); + ippsCopy_16s(HPFltSignal,&AlignTmpVec[G723_MAX_PITCH],G723_FRM_LEN); + + + i=3; + ippsAutoScale_16s_I( AlignTmpVec, G723_MAX_PITCH+G723_FRM_LEN, &i); + + ippsOpenLoopPitchSearch_G723_16s( &AlignTmpVec[G723_MAX_PITCH], &CurrentParams.PitchLag[0]); + ippsOpenLoopPitchSearch_G723_16s( &AlignTmpVec[G723_MAX_PITCH+(2*G723_SBFR_LEN)], &CurrentParams.PitchLag[1]); + + encoderObj->PrevOpenLoopLags[0] = CurrentParams.PitchLag[0]; + encoderObj->PrevOpenLoopLags[1] = CurrentParams.PitchLag[1]; + + if(CurrentParams.FrameType != G723_ActiveFrm) { + + ippsCopy_16s(&HPFltSignal[G723_FRM_LEN-G723_MAX_PITCH],encoderObj->PrevWeightedSignal,G723_MAX_PITCH); + EncoderCNG_G723(encoderObj, &CurrentParams,HPFltSignal, CurrQLPC); + + /* change the ringing delays */ + pData = HPFltSignal; + + for( i = 0 ; i < 4; i++ ) { + + LOCAL_ARRAY(Ipp32s, V_AccS,G723_SBFR_LEN,encoderObj) ; + /* Update exc_err */ + ErrorUpdate_G723(encoderObj->ExcitationError, CurrentParams.PitchLag[i>>1], CurrentParams.AdCdbkLag[i], CurrentParams.AdCdbkGain[i],CurrentParams.currRate); + + /* Shift the harmonic noise shaping filter memory */ + ///>>>_ippsCopy_16s(&encoderObj->FltSignal[G723_SBFR_LEN],encoderObj->FltSignal,G723_MAX_PITCH-G723_SBFR_LEN); + ippsMove_16s(&encoderObj->FltSignal[G723_SBFR_LEN],encoderObj->FltSignal,G723_MAX_PITCH-G723_SBFR_LEN); + /* Combined filtering */ + ippsCopy_16s(encoderObj->RingSynthFltMem,encoderObj->RingWeightedFltMem,G723_LPC_ORDER); + ippsSynthesisFilter_G723_16s32s(&CurrQLPC[i*(G723_LPC_ORDER+1)], + pData,V_AccS,encoderObj->RingSynthFltMem); + + ippsIIR16s_G723_32s16s_Sfs(&WeightedLPC[i*2*G723_LPC_ORDER],V_AccS,0, + &(encoderObj->FltSignal[G723_MAX_PITCH-G723_SBFR_LEN]),encoderObj->RingWeightedFltMem); + + pData += G723_SBFR_LEN; + LOCAL_ARRAY_FREE(Ipp32s, V_AccS,G723_SBFR_LEN,encoderObj) ; + } + } + + else { + + /* Active frame */ + ippsHarmonicSearch_G723_16s(CurrentParams.PitchLag[0], &AlignTmpVec[G723_MAX_PITCH], &GainInfo[0].sDelay, &GainInfo[0].sGain); + ippsHarmonicSearch_G723_16s(CurrentParams.PitchLag[0], &AlignTmpVec[G723_MAX_PITCH+G723_SBFR_LEN], &GainInfo[1].sDelay, &GainInfo[1].sGain); + ippsHarmonicSearch_G723_16s(CurrentParams.PitchLag[1], &AlignTmpVec[G723_MAX_PITCH+2*G723_SBFR_LEN], &GainInfo[2].sDelay, &GainInfo[2].sGain); + ippsHarmonicSearch_G723_16s(CurrentParams.PitchLag[1], &AlignTmpVec[G723_MAX_PITCH+3*G723_SBFR_LEN], &GainInfo[3].sDelay, &GainInfo[3].sGain); + + ippsCopy_16s(encoderObj->PrevWeightedSignal,AlignTmpVec,G723_MAX_PITCH); + ippsCopy_16s(HPFltSignal,&AlignTmpVec[G723_MAX_PITCH],G723_FRM_LEN); + + ippsCopy_16s(&AlignTmpVec[G723_FRM_LEN],encoderObj->PrevWeightedSignal,G723_MAX_PITCH); + + ippsHarmonicFilter_NR_16s((Ipp16s)(-GainInfo[0].sGain),GainInfo[0].sDelay,&AlignTmpVec[G723_MAX_PITCH], + HPFltSignal,G723_SBFR_LEN); + ippsHarmonicFilter_NR_16s((Ipp16s)(-GainInfo[1].sGain),GainInfo[1].sDelay,&AlignTmpVec[G723_MAX_PITCH+G723_SBFR_LEN], + &HPFltSignal[G723_SBFR_LEN],G723_SBFR_LEN); + ippsHarmonicFilter_NR_16s((Ipp16s)(-GainInfo[2].sGain),GainInfo[2].sDelay,&AlignTmpVec[G723_MAX_PITCH+2*G723_SBFR_LEN], + &HPFltSignal[2*G723_SBFR_LEN],G723_SBFR_LEN); + ippsHarmonicFilter_NR_16s((Ipp16s)(-GainInfo[3].sGain),GainInfo[3].sDelay,&AlignTmpVec[G723_MAX_PITCH+3*G723_SBFR_LEN], + &HPFltSignal[3*G723_SBFR_LEN],G723_SBFR_LEN); + + { + LOCAL_ARRAY(Ipp16s, qIndex,3,encoderObj) ; + /* Inverse quantization of the LSP */ + qIndex[2] = (Ipp16s)(CurrentParams.lLSPIdx & 0xff); + qIndex[1] = (Ipp16s)((CurrentParams.lLSPIdx>>8) & 0xff); + qIndex[0] = (Ipp16s)((CurrentParams.lLSPIdx>>16) & 0xff); + if(ippsLSFDecode_G723_16s(qIndex, encoderObj->PrevLPC, CurrentParams.isBadFrame, CurrLSF) != ippStsNoErr) + ippsCopy_16s(encoderObj->PrevLPC,CurrLSF,G723_LPC_ORDER); + LOCAL_ARRAY_FREE(Ipp16s, qIndex,3,encoderObj) ; + } + + /* Interpolate the Lsp vectors */ + LSPInterpolation(CurrLSF, encoderObj->PrevLPC, CurrQLPC) ; + + /* Copy the LSP vector for the next frame */ + ippsCopy_16s(CurrLSF,encoderObj->PrevLPC,G723_LPC_ORDER); + + /* sub frame processing */ + pData = HPFltSignal ; + + for ( lNSbfr = 0 ; lNSbfr < 4 ; lNSbfr ++ ) { + + LOCAL_ALIGN_ARRAY(16, Ipp16s, SynDl,G723_LPC_ORDER,encoderObj) ; /* synthesis filter delay line */ + LOCAL_ALIGN_ARRAY(16, Ipp16s, RingWgtDl,2*G723_LPC_ORDER,encoderObj) ;/* formant perceptual weighting filter delay line */ + LOCAL_ALIGN_ARRAY(16, Ipp32s, V_AccS,G723_SBFR_LEN,encoderObj) ; + LOCAL_ALIGN_ARRAY(16, Ipp16s, ImpResp,G723_SBFR_LEN,encoderObj) ; + + /* Compute full impulse response */ + ippsZero_16s(SynDl,G723_LPC_ORDER); /* synthesis filter zero delay */ + + ippsSynthesisFilter_G723_16s32s(&CurrQLPC[lNSbfr*(G723_LPC_ORDER+1)],encoderObj->UnitImpulseSignal,V_AccS,SynDl); + + { + + LOCAL_ALIGN_ARRAY(16, Ipp16s, Temp,G723_MAX_PITCH+G723_SBFR_LEN,encoderObj) ; + + ippsZero_16s(RingWgtDl,2*G723_LPC_ORDER);/* formant perceptual weighting filter zero delay */ + ippsIIR16s_G723_32s16s_Sfs(&WeightedLPC[lNSbfr*2*G723_LPC_ORDER],V_AccS,1, + &Temp[G723_MAX_PITCH],RingWgtDl); + + ippsZero_16s(Temp,G723_MAX_PITCH);/* harmonic filter zero delay */ + ippsHarmonicFilter_NR_16s((Ipp16s)(-GainInfo[lNSbfr].sGain),GainInfo[lNSbfr].sDelay,&Temp[G723_MAX_PITCH],ImpResp,G723_SBFR_LEN); + + LOCAL_ALIGN_ARRAY_FREE(16, Ipp16s, Temp,G723_MAX_PITCH+G723_SBFR_LEN,encoderObj) ; + } + + /* Subtract the ringing of previous sub-frame */ + ippsCopy_16s(encoderObj->RingSynthFltMem,SynDl,G723_LPC_ORDER); + /* Synthesis filter of zero input */ + ippsSynthesisFilter_G723_16s32s(&CurrQLPC[lNSbfr*(G723_LPC_ORDER+1)],encoderObj->ZeroSignal,V_AccS,SynDl); + + ippsCopy_16s(encoderObj->RingSynthFltMem,RingWgtDl,G723_LPC_ORDER);/* FIR same as for synth filter */ + ippsCopy_16s(&encoderObj->RingWeightedFltMem[G723_LPC_ORDER],&RingWgtDl[G723_LPC_ORDER],G723_LPC_ORDER);/* IIR part*/ + ippsIIR16s_G723_32s16s_Sfs(&WeightedLPC[lNSbfr*2*G723_LPC_ORDER],V_AccS,0, + &(encoderObj->FltSignal[G723_MAX_PITCH]),RingWgtDl); + + /* Do the harmonic noise shaping filter with subtraction the result + from the harmonic noise weighted vector.*/ + ippsHarmonicNoiseSubtract_G723_16s_I((Ipp16s)(-GainInfo[lNSbfr].sGain),GainInfo[lNSbfr].sDelay, + &(encoderObj->FltSignal[G723_MAX_PITCH]),pData); + /* Shift the harmonic noise shaping filter memory */ + ///>>>_ippsCopy_16s(&encoderObj->FltSignal[G723_SBFR_LEN],encoderObj->FltSignal,G723_MAX_PITCH-G723_SBFR_LEN); + ippsMove_16s(&encoderObj->FltSignal[G723_SBFR_LEN],encoderObj->FltSignal,G723_MAX_PITCH-G723_SBFR_LEN); + + /* Adaptive codebook contribution to exitation residual. Section 2.14. */ + { + Ipp16s sCloseLag; + Ipp16s sPitchLag = CurrentParams.PitchLag[lNSbfr>>1] ; + + LOCAL_ALIGN_ARRAY(16, Ipp16s, RezBuf,G723_SBFR_LEN+4,encoderObj) ; + + if ( (lNSbfr & 1 ) == 0 ) { /* For even frames only */ + if ( sPitchLag == G723_MIN_PITCH ) sPitchLag++; + if ( sPitchLag > (G723_MAX_PITCH-5) ) sPitchLag = G723_MAX_PITCH-5 ; + } + + ippsAdaptiveCodebookSearch_G723(sPitchLag, pData, ImpResp, encoderObj->PrevExcitation, encoderObj->ExcitationError, + &sCloseLag, &CurrentParams.AdCdbkGain[lNSbfr], (Ipp16s)lNSbfr, isNotSineWave, SA_Rate[CurrentParams.currRate]); + + /* Modify sPitchLag for even sub frames */ + if ( (lNSbfr & 1 ) == 0 ) { + sPitchLag = (Ipp16s)(sPitchLag - 1 + sCloseLag) ; + sCloseLag = 1 ; + } + CurrentParams.AdCdbkLag[lNSbfr] = sCloseLag ; + CurrentParams.PitchLag[lNSbfr>>1] = sPitchLag ; + + ippsDecodeAdaptiveVector_G723_16s(sPitchLag, sCloseLag, CurrentParams.AdCdbkGain[lNSbfr], encoderObj->PrevExcitation, RezBuf, SA_Rate[CurrentParams.currRate]); + + /* subtract the contribution of the pitch predictor decoded to obtain the residual */ + ExcitationResidual_G723_16s(RezBuf,ImpResp,pData,encoderObj); + + LOCAL_ALIGN_ARRAY_FREE(16, Ipp16s, RezBuf,G723_SBFR_LEN+4,encoderObj) ; + } + /* Compute fixed code book contribution */ + FixedCodebookSearch_G723_16s(encoderObj, &CurrentParams, pData, ImpResp, (Ipp16s) lNSbfr) ; + + ippsDecodeAdaptiveVector_G723_16s(CurrentParams.PitchLag[lNSbfr>>1], CurrentParams.AdCdbkLag[lNSbfr], CurrentParams.AdCdbkGain[lNSbfr], encoderObj->PrevExcitation, + ImpResp, SA_Rate[CurrentParams.currRate]); + + ///>>>_ippsCopy_16s(&encoderObj->PrevExcitation[G723_SBFR_LEN],encoderObj->PrevExcitation,G723_MAX_PITCH-G723_SBFR_LEN); + ippsMove_16s(&encoderObj->PrevExcitation[G723_SBFR_LEN],encoderObj->PrevExcitation,G723_MAX_PITCH-G723_SBFR_LEN); + + for ( i = 0 ; i < G723_SBFR_LEN ; i ++ ) { + pData[i] = Cnvrt_32s16s( Mul2_16s(pData[i])+ImpResp[i]); + } + ippsCopy_16s(pData,&encoderObj->PrevExcitation[G723_MAX_PITCH-G723_SBFR_LEN],G723_SBFR_LEN); + + /* Update exc_err */ + ErrorUpdate_G723(encoderObj->ExcitationError, CurrentParams.PitchLag[lNSbfr>>1], CurrentParams.AdCdbkLag[lNSbfr], CurrentParams.AdCdbkGain[lNSbfr],CurrentParams.currRate); + + /* Update the ringing delays by passing excitation through the combined filter.*/ + for(i=0; iRingWeightedFltMem[i] = encoderObj->RingSynthFltMem[i]; /* FIR same as for synth filter */ + } + ippsSynthesisFilter_G723_16s32s(&CurrQLPC[lNSbfr*(G723_LPC_ORDER+1)], + pData,V_AccS,encoderObj->RingSynthFltMem); + ippsIIR16s_G723_32s16s_Sfs(&WeightedLPC[lNSbfr*2*G723_LPC_ORDER],V_AccS,0, + &(encoderObj->FltSignal[G723_MAX_PITCH-G723_SBFR_LEN]),encoderObj->RingWeightedFltMem); + pData += G723_SBFR_LEN ; + + LOCAL_ALIGN_ARRAY_FREE(16, Ipp16s, ImpResp,G723_SBFR_LEN,encoderObj) ; + LOCAL_ALIGN_ARRAY_FREE(16, Ipp32s, V_AccS,G723_SBFR_LEN,encoderObj) ; + LOCAL_ALIGN_ARRAY_FREE(16, Ipp16s, RingWgtDl,2*G723_LPC_ORDER,encoderObj) ;/* formant perceptual weighting filter delay line */ + LOCAL_ALIGN_ARRAY_FREE(16, Ipp16s, SynDl,G723_LPC_ORDER,encoderObj) ; /* synthesis filter delay line */ + } /* end of subframes loop */ + + encoderObj->PastFrameType = G723_ActiveFrm; + encoderObj->CNGSeed = 12345; + encoderObj->CasheCounter = 0; + + } + + /* Pack to the bitstream */ + SetParam2Bitstream(encoderObj, &CurrentParams, pDstBitStream); + + CLEAR_SCRATCH_MEMORY(encoderObj); + + return APIG723_StsNoErr; + +} diff --git a/encg729fp.c b/encg729fp.c new file mode 100644 index 0000000..dfc1d92 --- /dev/null +++ b/encg729fp.c @@ -0,0 +1,1475 @@ +/*///////////////////////////////////////////////////////////////////////////// +// +// 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) 2004-2007 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 ippEULA.rtf or ippEULA.txt 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.729 floating-point speech codec: encode API functions. +// +*/ +#include +#include "vadg729fp.h" +#include "owng729fp.h" + +__ALIGN32 CONST Ipp32f InitLSP[LPC_ORDER] = + { 0.9595f, 0.8413f, 0.6549f, 0.4154f, 0.1423f, + -0.1423f, -0.4154f, -0.6549f, -0.8413f, -0.9595f +}; +__ALIGN32 CONST Ipp32f InitFrequences[LPC_ORDER] = { /* previous LSP vector(init) */ + 0.285599f, 0.571199f, 0.856798f, 1.142397f, 1.427997f, + 1.713596f, 1.999195f, 2.284795f, 2.570394f, 2.855993f +}; /* IPP_PI*(j+1)/(LPC_ORDER+1) */ + +static __ALIGN32 CONST Ipp32f b140[3] = {0.92727435E+00f, -0.18544941E+01f, 0.92727435E+00f}; +static __ALIGN32 CONST Ipp32f a140[3] = {1.00000000E+00f, 0.19059465E+01f, -0.91140240E+00f}; + +static __ALIGN32 CONST Ipp32f lwindow[LPC_ORDER+2] = { + 0.99879038f, 0.99546894f, 0.98995779f, + 0.98229335f, 0.97252620f, 0.96072035f, + 0.94695264f, 0.93131180f, 0.91389754f, + 0.89481964f, 0.87419660f, 0.85215437f +}; + +__ALIGN32 CONST Ipp32f lagBwd[BWD_LPC_ORDER] = { + 0.999892f, 0.999869f, 0.999831f, 0.999777f, 0.999707f, + 0.999622f, 0.999522f, 0.999407f, 0.999276f, 0.999129f, + 0.998968f, 0.998790f, 0.998598f, 0.998390f, 0.998167f, + 0.997928f, 0.997674f, 0.997405f, 0.997121f, 0.996821f, + 0.996506f, 0.996175f, 0.995830f, 0.995469f, 0.995093f, + 0.994702f, 0.994295f, 0.993874f, 0.993437f, 0.992985f, +}; + +/* Quantization of SID gain */ +__ALIGN32 CONST Ipp32f SIDGainTbl[32] = { + 0.502f, 1.262f, 2.000f, 3.170f, + 5.024f, 7.962f, 12.619f, 15.887f, + 20.000f, 25.179f, 31.698f, 39.905f, + 50.238f, 63.246f, 79.621f, 100.237f, + 126.191f, 158.866f, 200.000f, 251.785f, + 316.979f, 399.052f, 502.377f, 632.456f, + 796.214f, 1002.374f, 1261.915f, 1588.656f, + 2000.000f, 2517.851f, 3169.786f, 3990.525f +}; + +#define AVG(a,b,c,d) (Ipp32s)( ((a)+(b)+(c)+(d))/4.0f + 0.5f) + +static void UpdateVad_I(G729FPEncoder_Obj* encoderObj, Ipp32f *Excitation, Ipp32f *forwardLPC, Ipp32f *WeightedSpeech, + Ipp32f *gamma1, Ipp32f *gamma2, Ipp32f *pSynth, + Ipp32f *pError, Ipp32f *SpeechWnd, Ipp32s* dst,G729Codec_Type codecType); + +static void UpdateVad_A(G729FPEncoder_Obj* encoderObj, Ipp32f *Excitation, + Ipp32f *WeightedSpeech, Ipp32f *SpeechWnd, Ipp32s* dst); + +static void UpdateCNG(Ipp32f *pSrcAutoCorr, Ipp32s Vad, Ipp8s *cngMem); + +static Ipp32s CodecType2Num(G729Codec_Type codecType) +{ + switch(codecType) { + case G729D_CODEC: + return 0; + case G729_CODEC: + return 1; + case G729A_CODEC: + return 1; + case G729E_CODEC: + return 2; + } + return -1; +} + +static Ipp32s ownEncoderObjSize() +{ + Ipp32s codecSize, fltsize; + + codecSize = sizeof(G729FPEncoder_Obj); + ippsIIRGetStateSize_32f(2,&fltsize); + codecSize += fltsize; + VADGetSize(&fltsize); + codecSize += fltsize; + CNGGetSize(&fltsize); + codecSize += fltsize; + MSDGetSize(&fltsize); + codecSize += fltsize; + ippsWinHybridGetStateSize_G729E_32f(&fltsize); + codecSize += fltsize; + + return codecSize; +} + +G729_CODECFUN( APIG729_Status, apiG729FPEncoder_Alloc, + (G729Codec_Type codecType, Ipp32s *pCodecSize)) +{ + if ((codecType != G729_CODEC)&&(codecType != G729A_CODEC) + &&(codecType != G729D_CODEC)&&(codecType != G729E_CODEC)&&(codecType != G729I_CODEC)){ + return APIG729_StsBadCodecType; + } + + *pCodecSize = ownEncoderObjSize(); + + return APIG729_StsNoErr; + +} + +G729_CODECFUN( APIG729_Status, apiG729FPCodec_ScratchMemoryAlloc,(Ipp32s *pCodecSize)) +{ + if(NULL==pCodecSize) + return APIG729_StsBadArgErr; + *pCodecSize = G729FP_ENCODER_SCRATCH_MEMORY_SIZE; + + return APIG729_StsNoErr; +} + +G729_CODECFUN( APIG729_Status, apiG729FPEncoder_Mode, + (G729FPEncoder_Obj* encoderObj, G729Encode_Mode mode)) +{ + if(G729Encode_VAD_Enabled != mode && G729Encode_VAD_Disabled != mode){ + return APIG729_StsBadArgErr; + } + encoderObj->objPrm.mode = mode; + return APIG729_StsNoErr; +} + +G729_CODECFUN( APIG729_Status, apiG729FPEncoder_InitBuff, + (G729FPEncoder_Obj* encoderObj, Ipp8s *buff)) +{ + if(buff==NULL) return APIG729_StsBadArgErr; + if(encoderObj==NULL) return APIG729_StsBadArgErr; + + if(NULL==encoderObj || NULL==buff) + return APIG729_StsBadArgErr; + + encoderObj->Mem.base = buff; + encoderObj->Mem.CurPtr = encoderObj->Mem.base; + encoderObj->Mem.VecPtr = (Ipp32s *)(encoderObj->Mem.base+G729FP_ENCODER_SCRATCH_MEMORY_SIZE); + + return APIG729_StsNoErr; +} + +G729_CODECFUN( APIG729_Status, apiG729FPEncoder_Init, + (G729FPEncoder_Obj* encoderObj, G729Codec_Type codecType, G729Encode_Mode mode)) +{ + + Ipp32s i; + Ipp32s fltsize; + void* pBuf; + Ipp32f coeff[6]; + + Ipp8s* oldMemBuff; + + if(NULL==encoderObj) + return APIG729_StsBadArgErr; + + if ((codecType != G729_CODEC)&&(codecType != G729A_CODEC) + &&(codecType != G729D_CODEC)&&(codecType != G729E_CODEC)&&(codecType != G729I_CODEC)){ + return APIG729_StsBadCodecType; + } + + oldMemBuff = encoderObj->Mem.base; /* if Reinit */ + + ippsZero_16s((Ipp16s*)encoderObj,sizeof(G729FPEncoder_Obj)>>1) ; + + encoderObj->objPrm.objSize = ownEncoderObjSize(); + encoderObj->objPrm.mode = mode; + encoderObj->objPrm.key = ENC_KEY; + encoderObj->objPrm.codecType=codecType; + + coeff[0] = b140[0]; + coeff[1] = b140[1]; + coeff[2] = b140[2]; + coeff[3] = a140[0]; + coeff[4] = -a140[1]; + coeff[5] = -a140[2]; + pBuf = (Ipp8s*)encoderObj + sizeof(G729FPEncoder_Obj); + ippsIIRInit_32f(&encoderObj->iirstate,coeff,2,NULL,pBuf); + ippsIIRGetStateSize_32f(2,&fltsize); + encoderObj->vadMem = (Ipp8s *)((Ipp8s*)pBuf + fltsize); + VADGetSize(&fltsize); + encoderObj->cngMem = (Ipp8s *)((Ipp8s*)encoderObj->vadMem + fltsize); + CNGGetSize(&fltsize); + encoderObj->msdMem = (Ipp8s *)((Ipp8s*)encoderObj->cngMem + fltsize); + MSDGetSize(&fltsize); + encoderObj->pHWState = (IppsWinHybridState_G729E_32f *)((Ipp8s*)encoderObj->msdMem + fltsize); + + /* Static vectors to zero */ + + ippsZero_32f(encoderObj->OldSpeechBuffer, SPEECH_BUFF_LEN); + ippsZero_32f(encoderObj->OldExcitationBuffer, PITCH_LAG_MAX+INTERPOL_LEN); + ippsZero_32f(encoderObj->OldWeightedSpeechBuffer, PITCH_LAG_MAX); + ippsZero_32f(encoderObj->WeightedFilterMemory, BWD_LPC_ORDER); + ippsZero_32f(encoderObj->FltMem, BWD_LPC_ORDER); + encoderObj->fBetaPreFilter = PITCH_SHARPMIN; + ippsCopy_32f(InitLSP, encoderObj->OldLSP, LPC_ORDER); + ippsCopy_32f(InitLSP, encoderObj->OldQuantLSP, LPC_ORDER); + for(i=0; i<4; i++) encoderObj->ExcitationError[i] = 1.f; + + encoderObj->PastQuantEnergy[0]=encoderObj->PastQuantEnergy[1]=encoderObj->PastQuantEnergy[2]=encoderObj->PastQuantEnergy[3]=-14.0; + for(i=0; iPrevFreq[i][0], LPC_ORDER ); + ippsZero_32f(encoderObj->OldForwardLPC, LPC_ORDERP1); + encoderObj->OldForwardLPC[0]= 1.f; + ippsZero_32f(encoderObj->OldForwardRC, 2); + encoderObj->sFrameCounter = 0; + /* For G.729B */ + /* Initialize VAD/DTX parameters */ + //if(mode == G729Encode_VAD_Enabled) { + encoderObj->prevVADDec = 1; + encoderObj->prevPrevVADDec = 1; + encoderObj->sCNGSeed = INIT_SEED_VAL; + VADInit(encoderObj->vadMem); + CNGInit(encoderObj->cngMem); + MSDInit(encoderObj->msdMem); + //} + encoderObj->prevLPCMode = 0; + if(codecType==G729A_CODEC) { + ippsZero_32f(encoderObj->ZeroMemory, LPC_ORDER); + } else { + ippsZero_32f(encoderObj->SynFltMemory, BWD_LPC_ORDER); + ippsZero_32f(encoderObj->ErrFltMemory, BWD_LPC_ORDER); + ippsZero_32f(&encoderObj->UnitImpulse[BWD_LPC_ORDERP1], SUBFR_LEN); + ippsZero_32f(encoderObj->PrevFlt, BWD_LPC_ORDERP1); + encoderObj->PrevFlt[0] = 1.f; + ippsWinHybridInit_G729E_32f(encoderObj->pHWState); + ippsZero_32f(encoderObj->SynthBuffer, BWD_ANALISIS_WND_LEN); + ippsZero_32f(encoderObj->BackwardLPCMemory, BWD_LPC_ORDERP1); + encoderObj->BackwardLPCMemory[0] = 1.f; + encoderObj->isBWDDominant = 0; + encoderObj->fInterpolationCoeff = 1.1f; /* Filter interpolation parameter */ + encoderObj->sGlobalStatInd = 10000; /* Mesure of global stationnarity */ + encoderObj->sBWDStatInd = 0; /* Nbre of consecutive backward frames */ + encoderObj->sValBWDStatInd = 0; /* Value associated with stat_bwd */ + ippsZero_32f(encoderObj->OldBackwardLPC, BWD_LPC_ORDERP1); + encoderObj->OldBackwardLPC[0]= 1.f; + ippsZero_32f(encoderObj->OldBackwardRC, 2); + ippsSet_32s(20,encoderObj->LagBuffer,5); + ippsSet_32f(0.7f,encoderObj->PitchGainBuffer,5); + encoderObj->sBWDFrmCounter = 0; + encoderObj->sFWDFrmCounter = 0; + encoderObj->isSmooth = 1; + encoderObj->LogAreaRatioCoeff[0] = encoderObj->LogAreaRatioCoeff[1] = 0.f; + encoderObj->sSearchTimes = 30; + } + + apiG729FPEncoder_InitBuff(encoderObj,oldMemBuff); + + return APIG729_StsNoErr; +} + +G729_CODECFUN( APIG729_Status, apiG729FPEncode, + (G729FPEncoder_Obj* encoderObj,const Ipp16s* src, Ipp8u *dst,G729Codec_Type codecType, Ipp32s *frametype)) +{ + /* LPC analysis */ + LOCAL_ALIGN_ARRAY(32, Ipp32f, forwardAutoCorr, (LPC_ORDERP2+1),encoderObj); /* Autocorrelations (forward) */ + LOCAL_ALIGN_ARRAY(32, Ipp32f, backwardAutoCorr, BWD_LPC_ORDERP1,encoderObj); /* Autocorrelations (backward) */ + LOCAL_ALIGN_ARRAY(32, Ipp32f, backwardReflectCoeff, BWD_LPC_ORDER,encoderObj); /* Reflection coefficients : backward analysis */ + LOCAL_ALIGN_ARRAY(32, Ipp32f, forwardLPC, LPC_ORDERP1*2,encoderObj); /* A(z) forward unquantized for the 2 subframes */ + LOCAL_ALIGN_ARRAY(32, Ipp32f, forwardQntLPC, LPC_ORDERP1*2,encoderObj); /* A(z) forward quantized for the 2 subframes */ + LOCAL_ALIGN_ARRAY(32, Ipp32f, backwardLPC, 2*BWD_LPC_ORDERP1,encoderObj); /* A(z) backward for the 2 subframes */ + LOCAL_ALIGN_ARRAY(32, Ipp32f, WeightedLPC1, BWD_LPC_ORDERP1,encoderObj); /* A(z) with spectral expansion */ + LOCAL_ALIGN_ARRAY(32, Ipp32f, WeightedLPC2, BWD_LPC_ORDERP1,encoderObj); /* A(z) with spectral expansion */ + LOCAL_ALIGN_ARRAY(32, Ipp32f, CurrLSP, LPC_ORDER,encoderObj); + LOCAL_ALIGN_ARRAY(32, Ipp32f, tmpLSP, LPC_ORDER,encoderObj); + LOCAL_ALIGN_ARRAY(32, Ipp32f, CurrQntLSP, LPC_ORDER,encoderObj); /* LSPs at 2th subframe */ + LOCAL_ALIGN_ARRAY(32, Ipp32f, TmpAlignVec, WINDOW_LEN,encoderObj); + /* Other vectors */ + LOCAL_ALIGN_ARRAY(32, Ipp32f, ImpulseResponse, SUBFR_LEN,encoderObj); /* Impulse response*/ + LOCAL_ALIGN_ARRAY(32, Ipp32f, TargetVector, SUBFR_LEN,encoderObj); /* Target vector for pitch search */ + LOCAL_ALIGN_ARRAY(32, Ipp32f, FltTargetVector, SUBFR_LEN,encoderObj); /* Target vector for codebook search */ + LOCAL_ALIGN_ARRAY(32, Ipp32f, FixedCodebookExc, SUBFR_LEN,encoderObj); /* Fixed codebook excitation */ + LOCAL_ALIGN_ARRAY(32, Ipp32f, FltAdaptExc, SUBFR_LEN,encoderObj); /* Filtered adaptive excitation */ + LOCAL_ALIGN_ARRAY(32, Ipp32f, FltFixedCodebookExc, SUBFR_LEN,encoderObj); /* Filtered fixed codebook excitation */ + LOCAL_ALIGN_ARRAY(32, Ipp32f, PitchPredResidual, SUBFR_LEN,encoderObj); /* Pitch prediction residual */ + + LOCAL_ARRAY(Ipp32f, forwardReflectCoeff, LPC_ORDER,encoderObj); /* Reflection coefficients : forward analysis */ + LOCAL_ARRAY(Ipp32f, InterpolatedLSF, LPC_ORDER,encoderObj); /* Interpolated LSF 1st subframe. */ + LOCAL_ARRAY(Ipp32f, CurrLSF, LPC_ORDER,encoderObj); + LOCAL_ARRAY(Ipp32f, CurrFreq, LPC_ORDER,encoderObj); + LOCAL_ARRAY(Ipp32f, TmpAutoCorr, LPC_ORDERP1,encoderObj); + LOCAL_ARRAY(Ipp32s, EncodedParams, 19,encoderObj); + LOCAL_ARRAY(Ipp32f, g_coeff, 5,encoderObj); /* Correlations between TargetVector, FltAdaptExc, & FltFixedCodebookExc: + , , , ,*/ + LOCAL_ARRAY(Ipp32f, gamma1, 2,encoderObj); /* Weighting factor for the 2 subframes */ + LOCAL_ARRAY(Ipp32f, gamma2, 2,encoderObj); + LOCAL_ARRAY(Ipp32s, code_lsp, 2,encoderObj); + LOCAL_ARRAY(Ipp32s, delayLine, 2,encoderObj); + + Ipp32f *SpeechWnd, *pWindow; + Ipp32f *newSpeech; /* Global variable */ + /* Weighted speech vector */ + Ipp32f *WeightedSpeech; + /* Excitation vector */ + Ipp32f *Excitation; + /* Zero vector */ + Ipp32f *pZero=NULL; + Ipp32f *pError=NULL; + Ipp32f *pSynth=NULL; + Ipp32f *pQLPC; + Ipp32f *pUnQLPC; + Ipp32f *pLPC, *pQntLPC; + + /* Scalars */ + Ipp32s LPCMode; /* LP Backward (1) / Forward (0) Indication mode */ + Ipp32s apLen, aqLen; + Ipp32s i, j, NGamma, NSbfr; + Ipp32s openLoopPitch, pitchDelay, minPitchDelay, maxPitchDelay, fracPartPitchDelay; + Ipp32s index, taming; + Ipp32f pitchGain, codeGain; + Ipp32s VADDecision; + + /* G.729 ANNEXE variables*/ + Ipp32s isSaturateAZ; + Ipp32f EnergydB; + + Ipp32s avg_lag; + Ipp32f tmp_lev; + IppStatus sts; + Ipp32s *anau; + + if(NULL==src || NULL ==dst) + return APIG729_StsBadArgErr; + if ((codecType != G729_CODEC)&&(codecType != G729A_CODEC)&&(codecType != G729D_CODEC)&&(codecType != G729E_CODEC)) + return APIG729_StsBadCodecType; + if(encoderObj->objPrm.objSize <= 0) + return APIG729_StsNotInitialized; + if(ENC_KEY != encoderObj->objPrm.key) + return APIG729_StsBadCodecType; + + ippsZero_32f(WeightedLPC1,BWD_LPC_ORDERP1); + ippsZero_32f(WeightedLPC2,BWD_LPC_ORDERP1); + + anau = &EncodedParams[0]; + + newSpeech = encoderObj->OldSpeechBuffer + SPEECH_BUFF_LEN - FRM_LEN; + SpeechWnd = newSpeech - LOOK_AHEAD_LEN; /* Present frame */ + pWindow = encoderObj->OldSpeechBuffer + SPEECH_BUFF_LEN - WINDOW_LEN; /* For LPC window */ + WeightedSpeech = encoderObj->OldWeightedSpeechBuffer + PITCH_LAG_MAX; + Excitation = encoderObj->OldExcitationBuffer + PITCH_LAG_MAX + INTERPOL_LEN; + + if(codecType!=G729A_CODEC){ + pZero = encoderObj->UnitImpulse + BWD_LPC_ORDERP1; + pError = encoderObj->ErrFltMemory + BWD_LPC_ORDER; + pSynth = encoderObj->SynthBuffer + BWD_SYNTH_MEM; + } + + if (encoderObj->sFrameCounter == 32767) encoderObj->sFrameCounter = 256; + else encoderObj->sFrameCounter++; + + ippsConvert_16s32f(src,newSpeech,FRM_LEN); + ippsIIR_32f_I(newSpeech,FRM_LEN,encoderObj->iirstate); +#ifdef CLIPPING_DENORMAL_MODE + ippsIIRGetDlyLine_32f(encoderObj->iirstate, TmpAlignVec); + CLIP_DENORMAL_I(TmpAlignVec[0]); + CLIP_DENORMAL_I(TmpAlignVec[1]); + ippsIIRSetDlyLine_32f(encoderObj->iirstate, TmpAlignVec); +#endif + ownAutoCorr_G729_32f(pWindow, LPC_ORDERP2, forwardAutoCorr,TmpAlignVec); /* Autocorrelations */ + ippsCopy_32f(forwardAutoCorr, TmpAutoCorr, LPC_ORDERP1); + + /* Lag windowing */ + ippsMul_32f_I(lwindow, &forwardAutoCorr[1], LPC_ORDERP2); + /* Levinson Durbin */ + tmp_lev = 0; + sts = ippsLevinsonDurbin_G729_32f(forwardAutoCorr, LPC_ORDER, &forwardLPC[LPC_ORDERP1], forwardReflectCoeff, &tmp_lev); + if(sts == ippStsOverflow) { + ippsCopy_32f(encoderObj->OldForwardLPC,&forwardLPC[LPC_ORDERP1],LPC_ORDER+1); + forwardReflectCoeff[0] = encoderObj->OldForwardRC[0]; + forwardReflectCoeff[1] = encoderObj->OldForwardRC[1]; + } else { + ippsCopy_32f(&forwardLPC[LPC_ORDERP1],encoderObj->OldForwardLPC,LPC_ORDER+1); + encoderObj->OldForwardRC[0] = forwardReflectCoeff[0]; + encoderObj->OldForwardRC[1] = forwardReflectCoeff[1]; + } + + + /* Convert A(z) to lsp */ + if(codecType==G729A_CODEC){ + ippsLPCToLSP_G729A_32f(&forwardLPC[LPC_ORDERP1], encoderObj->OldLSP, CurrLSP); + } else { + ippsLPCToLSP_G729_32f(&forwardLPC[LPC_ORDERP1], encoderObj->OldLSP, CurrLSP); + } + + if (encoderObj->objPrm.mode == G729Encode_VAD_Enabled) { + ownACOS_G729_32f(CurrLSP, CurrLSF, LPC_ORDER); + VoiceActivityDetect_G729_32f(forwardReflectCoeff[1], CurrLSF, forwardAutoCorr, pWindow, encoderObj->sFrameCounter, + encoderObj->prevVADDec, encoderObj->prevPrevVADDec, &VADDecision, &EnergydB,encoderObj->vadMem,TmpAlignVec); + + if(codecType!=G729A_CODEC){ + MusicDetection_G729E_32f( encoderObj, codecType, forwardAutoCorr[0],forwardReflectCoeff, &VADDecision, EnergydB,encoderObj->msdMem,TmpAlignVec); + } + + UpdateCNG(TmpAutoCorr, VADDecision,encoderObj->cngMem); + } else VADDecision = 1; + + if(VADDecision == 0) { + if(codecType==G729A_CODEC){ + UpdateVad_A(encoderObj, Excitation, WeightedSpeech, SpeechWnd, anau); + } else { + /* Inactive frame */ + ippsCopy_32f(&encoderObj->SynthBuffer[FRM_LEN], &encoderObj->SynthBuffer[0], BWD_SYNTH_MEM); + /* Find interpolated LPC parameters in all subframes unquantized. * + * The interpolated parameters are in array forwardLPC of size (LPC_ORDER+1)*4 */ + if( encoderObj->prevLPCMode == 0) { + ippsInterpolateC_G729_32f(encoderObj->OldLSP, 0.5f, CurrLSP, 0.5f, tmpLSP, LPC_ORDER); + + ippsLSPToLPC_G729_32f(tmpLSP, forwardLPC); + + ownACOS_G729_32f(tmpLSP, InterpolatedLSF, LPC_ORDER); + ownACOS_G729_32f(CurrLSP, CurrLSF, LPC_ORDER); + } else { + /* no interpolation */ + /* unquantized */ + ippsLSPToLPC_G729_32f(CurrLSP, forwardLPC); /* Subframe 1 */ + ownACOS_G729_32f(CurrLSP, CurrLSF, LPC_ORDER); /* transformation from LSP to LSF (freq.domain) */ + ippsCopy_32f(CurrLSF, InterpolatedLSF, LPC_ORDER); /* Subframe 1 */ + } + + if (encoderObj->sGlobalStatInd > 10000) { + encoderObj->sGlobalStatInd -= 2621; + if(encoderObj->sGlobalStatInd < 10000) encoderObj->sGlobalStatInd = 10000 ; + } + encoderObj->isBWDDominant = 0; + encoderObj->fInterpolationCoeff = 1.1f; + + ippsCopy_32f(CurrLSP, encoderObj->OldLSP, LPC_ORDER); + + PWGammaFactor_G729(gamma1, gamma2, InterpolatedLSF, CurrLSF, forwardReflectCoeff,&encoderObj->isSmooth, encoderObj->LogAreaRatioCoeff); + + UpdateVad_I(encoderObj, Excitation, forwardLPC, WeightedSpeech, gamma1, gamma2, pSynth, + pError, SpeechWnd, anau, codecType); + + /* update previous filter for next frame */ + ippsCopy_32f(&forwardQntLPC[LPC_ORDERP1], encoderObj->PrevFlt, LPC_ORDERP1); + for(i=LPC_ORDERP1; i PrevFlt[i] = 0.f; + } + encoderObj->prevLPCMode = 0; + + encoderObj->fBetaPreFilter = PITCH_SHARPMIN; + + /* Update memories for next frames */ + ippsMove_32f(&encoderObj->OldSpeechBuffer[FRM_LEN], &encoderObj->OldSpeechBuffer[0], SPEECH_BUFF_LEN-FRM_LEN); + ippsMove_32f(&encoderObj->OldWeightedSpeechBuffer[FRM_LEN], &encoderObj->OldWeightedSpeechBuffer[0], PITCH_LAG_MAX); + ippsMove_32f(&encoderObj->OldExcitationBuffer[FRM_LEN], &encoderObj->OldExcitationBuffer[0], PITCH_LAG_MAX+INTERPOL_LEN); + + anau = EncodedParams+1; + if(EncodedParams[0] == 0){ /* untransmitted*/ + *frametype=0; + }else{ + *frametype=1; /* SID*/ + dst[0] = (Ipp8u)(((anau[0] & 0x1) << 7) | ((anau[1] & 0x1f) << 2) | ((anau[2] & 0xf)>>2)); /* 1+5+2 */ + dst[1] = (Ipp8u)(((anau[2] & 0x3) << 6) | ((anau[3] & 0x1f) << 1)); /* 2+5+LSB */ + } + CLEAR_SCRATCH_MEMORY(encoderObj); + return APIG729_StsNoErr; + } + + /* Active frame */ + + *anau++ = CodecType2Num(codecType)+2; /* bit rate mode */ + if(encoderObj->objPrm.mode == G729Encode_VAD_Enabled) { + encoderObj->sCNGSeed = INIT_SEED_VAL; + encoderObj->prevPrevVADDec = encoderObj->prevVADDec; + encoderObj->prevVADDec = VADDecision; + } + + + /* LSP quantization */ + + ippsLSPQuant_G729E_32f( CurrLSP, (Ipp32f*)encoderObj->PrevFreq, CurrFreq, CurrQntLSP, code_lsp); + + + if( encoderObj->prevLPCMode == 0) { + if(codecType!=G729A_CODEC){ + ippsInterpolateC_G729_32f(encoderObj->OldLSP, 0.5f, CurrLSP, 0.5f, tmpLSP, LPC_ORDER); + + ippsLSPToLPC_G729_32f(tmpLSP, forwardLPC); + + ownACOS_G729_32f(tmpLSP, InterpolatedLSF, LPC_ORDER); + ownACOS_G729_32f(CurrLSP, CurrLSF, LPC_ORDER); + } + + ippsInterpolateC_G729_32f(encoderObj->OldQuantLSP, 0.5f, CurrQntLSP, 0.5f, tmpLSP, LPC_ORDER); + + ippsLSPToLPC_G729_32f(tmpLSP, forwardQntLPC); + ippsLSPToLPC_G729_32f(CurrQntLSP, &forwardQntLPC[LPC_ORDER+1]); + } else { + /* no interpolation */ + /* unquantized */ + ippsLSPToLPC_G729_32f(CurrLSP, forwardLPC); /* Subframe 1 */ + ownACOS_G729_32f(CurrLSP, CurrLSF, LPC_ORDER); /* transformation from LSP to LSF (freq.domain) */ + ippsCopy_32f(CurrLSF, InterpolatedLSF, LPC_ORDER); /* Subframe 1 */ + ippsLSPToLPC_G729_32f(CurrQntLSP, &forwardQntLPC[LPC_ORDERP1]); /* Subframe 2 */ + ippsCopy_32f(&forwardQntLPC[LPC_ORDERP1], forwardQntLPC, LPC_ORDERP1); /* Subframe 1 */ + } + + /* Decision for the switch Forward / Backward mode */ + if(codecType == G729E_CODEC) { + /* LPC recursive Window as in G728 */ + ippsWinHybrid_G729E_32f(encoderObj->SynthBuffer, backwardAutoCorr, encoderObj->pHWState); + /* Lag windowing */ + ippsMul_32f_I(lagBwd, &backwardAutoCorr[1], BWD_LPC_ORDER); + if (backwardAutoCorr[0] < 1.0f) backwardAutoCorr[0] = 1.0f; + sts = ippsLevinsonDurbin_G729_32f(backwardAutoCorr, BWD_LPC_ORDER, &backwardLPC[BWD_LPC_ORDERP1], backwardReflectCoeff, &tmp_lev); + if(sts == ippStsOverflow) { + ippsCopy_32f(encoderObj->OldBackwardLPC,&backwardLPC[BWD_LPC_ORDERP1],BWD_LPC_ORDER+1); + backwardReflectCoeff[0] = encoderObj->OldBackwardRC[0]; + backwardReflectCoeff[1] = encoderObj->OldBackwardRC[1]; + } else { + ippsCopy_32f(&backwardLPC[BWD_LPC_ORDERP1],encoderObj->OldBackwardLPC,BWD_LPC_ORDER+1); + encoderObj->OldBackwardRC[0] = backwardReflectCoeff[0]; + encoderObj->OldBackwardRC[1] = backwardReflectCoeff[1]; + } + + /* Tests saturation of backwardLPC */ + isSaturateAZ = 0; + for (i=BWD_LPC_ORDERP1; i<2*BWD_LPC_ORDERP1; i++) if (backwardLPC[i] >= 8.f) {isSaturateAZ = 1;break;} + if (isSaturateAZ == 1) ippsCopy_32f(encoderObj->BackwardLPCMemory, &backwardLPC[BWD_LPC_ORDERP1], BWD_LPC_ORDERP1); + else ippsCopy_32f(&backwardLPC[BWD_LPC_ORDERP1], encoderObj->BackwardLPCMemory, BWD_LPC_ORDERP1); + + /* Additional bandwidth expansion on backward filter */ + WeightLPCCoeff_G729(&backwardLPC[BWD_LPC_ORDERP1], BWD_GAMMA, BWD_LPC_ORDER, &backwardLPC[BWD_LPC_ORDERP1]); + + SetLPCMode_G729FPE(encoderObj,SpeechWnd, forwardQntLPC, backwardLPC, &LPCMode, CurrLSP,TmpAlignVec); + *anau++ = LPCMode; + } else { + if (encoderObj->sGlobalStatInd > 10000) { + encoderObj->sGlobalStatInd -= 2621; + if( encoderObj->sGlobalStatInd < 10000) encoderObj->sGlobalStatInd = 10000 ; + } + LPCMode = 0; + encoderObj->isBWDDominant = 0; + encoderObj->fInterpolationCoeff = 1.1f; + } + /* Update synthesis signal for next frame. */ + ippsCopy_32f(&encoderObj->SynthBuffer[FRM_LEN], &encoderObj->SynthBuffer[0], BWD_SYNTH_MEM); + /* Update the LSPs for the next frame */ + ippsCopy_32f(CurrLSP, encoderObj->OldLSP, LPC_ORDER); + if( LPCMode == 0) { + ippsCopy_32f(CurrQntLSP, encoderObj->OldQuantLSP, LPC_ORDER); + ippsMove_32f(encoderObj->PrevFreq[0], encoderObj->PrevFreq[1], 3*LPC_ORDER); + ippsCopy_32f(CurrFreq, encoderObj->PrevFreq[0], LPC_ORDER); + + *anau++ = code_lsp[0]; + *anau++ = code_lsp[1]; + } + + /* Find the weighted input speech w_sp[] for the whole speech frame */ + if(LPCMode == 0) { + apLen = LPC_ORDER; + aqLen = LPC_ORDER; + if (encoderObj->isBWDDominant == 0) pUnQLPC = forwardLPC; + else pUnQLPC = forwardQntLPC; + pQLPC = forwardQntLPC; + if(codecType==G729A_CODEC) { + /* Compute A(z/gamma) */ + WeightLPCCoeff_G729(&forwardQntLPC[0], GAMMA1_G729A, LPC_ORDER, &forwardLPC[0]); + WeightLPCCoeff_G729(&forwardQntLPC[LPC_ORDERP1], GAMMA1_G729A, LPC_ORDER, &forwardLPC[LPC_ORDERP1]); + } else { + PWGammaFactor_G729(gamma1, gamma2, InterpolatedLSF, CurrLSF, forwardReflectCoeff,&encoderObj->isSmooth, encoderObj->LogAreaRatioCoeff); + /* update previous filter for next frame */ + ippsCopy_32f(&pQLPC[LPC_ORDERP1], encoderObj->PrevFlt, LPC_ORDERP1); + for(i=LPC_ORDERP1; i PrevFlt[i] = 0.f; + for(j=LPC_ORDERP1; jUnitImpulse[j] = 0.f; + } + } else { + if (encoderObj->isBWDDominant == 0) { + apLen = LPC_ORDER; + pUnQLPC = forwardLPC; + } else { + apLen = BWD_LPC_ORDER; + pUnQLPC = backwardLPC; + } + aqLen = BWD_LPC_ORDER; + pQLPC = backwardLPC; + /* ADAPTIVE BANDWIDTH EXPANSION FOR THE PERCEPTUAL WEIGHTING FILTER */ + if (encoderObj->isBWDDominant == 0) { + gamma1[0] = 0.9f; + gamma1[1] = 0.9f; + gamma2[0] = 0.4f; + gamma2[1] = 0.4f; + } else { + gamma1[0] = 0.98f; + gamma1[1] = 0.98f; + gamma2[0] = 0.4f; + gamma2[1] = 0.4f; + } + if (encoderObj->isBWDDominant == 0) { + for(j=LPC_ORDERP1; jUnitImpulse[j] = 0.f; + } + /* update previous filter for next frame */ + ippsCopy_32f(&pQLPC[BWD_LPC_ORDERP1], encoderObj->PrevFlt, BWD_LPC_ORDERP1); + } + + /* 3.3 Compute weighted input speech for the whole speech frame. */ + if(codecType!=G729A_CODEC){ + pLPC = pUnQLPC; + for (i=0; i<2; i++) { + WeightLPCCoeff_G729(pLPC, gamma1[i], apLen, WeightedLPC1); + WeightLPCCoeff_G729(pLPC, gamma2[i], apLen, WeightedLPC2); +#ifdef CLIPPING_DENORMAL_MODE + for(j=0; jFltMem[BWD_LPC_ORDER-apLen]); + for(j=0; jFltMem[j] = WeightedSpeech[i*SUBFR_LEN+SUBFR_LEN-BWD_LPC_ORDER+j]; + pLPC += apLen+1; + } + + /* 3.4 Open-loop analysis. */ + OpenLoopPitchSearch_G729_32f(WeightedSpeech, &openLoopPitch); + + for (i= 0; i< 4; i++) + encoderObj->LagBuffer[i] = encoderObj->LagBuffer[i+1]; + + avg_lag = AVG(encoderObj->LagBuffer[0],encoderObj->LagBuffer[1],encoderObj->LagBuffer[2],encoderObj->LagBuffer[3]); + if( abs( (Ipp32s) (openLoopPitch/2.0) - avg_lag)<=2) + encoderObj->LagBuffer[4] = (Ipp32s) (openLoopPitch/2.0); + else if( abs((Ipp32s) (openLoopPitch/3.0) - avg_lag)<=2) + encoderObj->LagBuffer[4] = (Ipp32s) (openLoopPitch/3.0); + else + encoderObj->LagBuffer[4] = openLoopPitch; + } else { + ippsConvBiased_32f(&forwardQntLPC[0],LPC_ORDER+1,SpeechWnd,SUBFR_LEN+LPC_ORDER,Excitation,SUBFR_LEN,LPC_ORDER); + ippsConvBiased_32f(&forwardQntLPC[LPC_ORDERP1],LPC_ORDER+1,&SpeechWnd[SUBFR_LEN],SUBFR_LEN+LPC_ORDER,&Excitation[SUBFR_LEN],SUBFR_LEN,LPC_ORDER); + + + { + + WeightedLPC1[0] = 1.0f; + for(i=1; i<=LPC_ORDER; i++) + WeightedLPC1[i] = forwardLPC[i] - 0.7f * forwardLPC[i-1]; + ippsSynthesisFilter_G729_32f(WeightedLPC1, LPC_ORDER, &Excitation[0], &WeightedSpeech[0], SUBFR_LEN, encoderObj->FltMem); + for (i = 0; i < LPC_ORDER; i++) CLIP_DENORMAL(WeightedSpeech[(SUBFR_LEN-LPC_ORDER)+i],encoderObj->FltMem[i]); + + for(i=1; i<=LPC_ORDER; i++) + WeightedLPC1[i] = forwardLPC[i+LPC_ORDERP1] - 0.7f * forwardLPC[i-1+LPC_ORDERP1]; + ippsSynthesisFilter_G729_32f(WeightedLPC1, LPC_ORDER, &Excitation[SUBFR_LEN], &WeightedSpeech[SUBFR_LEN], SUBFR_LEN, encoderObj->FltMem); + for (i = 0; i < LPC_ORDER; i++) CLIP_DENORMAL(WeightedSpeech[SUBFR_LEN+(SUBFR_LEN-LPC_ORDER)+i],encoderObj->FltMem[i]); + } + + /* Annex A.3.4 Open-loop analysis */ + ippsOpenLoopPitchSearch_G729A_32f(WeightedSpeech, &openLoopPitch); + + } + /* Range for closed loop pitch search in 1st subframe */ + minPitchDelay = openLoopPitch - 3; + if (minPitchDelay < PITCH_LAG_MIN) minPitchDelay = PITCH_LAG_MIN; + maxPitchDelay = minPitchDelay + 6; + if (maxPitchDelay > PITCH_LAG_MAX) { + maxPitchDelay = PITCH_LAG_MAX; + minPitchDelay = maxPitchDelay - 6; + } + + pLPC = pUnQLPC; /* pointer to interpolated "unquantized"LPC parameters */ + pQntLPC = pQLPC; /* pointer to interpolated "quantized" LPC parameters */ + + for (NSbfr = 0, NGamma = 0; NSbfr < FRM_LEN; NSbfr += SUBFR_LEN, NGamma++) { + if(codecType!=G729A_CODEC){ + /* LPC computing: weights of filter */ + WeightLPCCoeff_G729(pLPC, gamma1[NGamma], apLen, WeightedLPC1); + WeightLPCCoeff_G729(pLPC, gamma2[NGamma], apLen, WeightedLPC2); + + /* Clause 3.5 Computation of impulse response */ + for (i = 0; i <=apLen; i++) encoderObj->UnitImpulse[i] = WeightedLPC1[i]; + ippsSynthesisFilter_G729_32f(pQntLPC, aqLen, encoderObj->UnitImpulse, ImpulseResponse, SUBFR_LEN, pZero); + ippsSynthesisFilter_G729_32f(WeightedLPC2, apLen, ImpulseResponse, ImpulseResponse, SUBFR_LEN, pZero); + + /* pass the resudual r(n) through 1/A(z) */ + ippsConvBiased_32f(pQntLPC,aqLen+1,&SpeechWnd[NSbfr],SUBFR_LEN+aqLen,&Excitation[NSbfr],SUBFR_LEN,aqLen); + for (i=0; iErrFltMemory[BWD_LPC_ORDER-aqLen]); + /* then through the weighting filter W(z) where TargetVector is a target signal*/ + ippsConvBiased_32f(WeightedLPC1,aqLen+1,pError,SUBFR_LEN+aqLen,TargetVector,SUBFR_LEN,aqLen); + ippsSynthesisFilter_G729_32f(WeightedLPC2, apLen, TargetVector, TargetVector, SUBFR_LEN, &encoderObj->WeightedFilterMemory[BWD_LPC_ORDER-apLen]); + + pitchDelay = AdaptiveCodebookSearch_G729_32f(&Excitation[NSbfr], TargetVector, ImpulseResponse, SUBFR_LEN, minPitchDelay, maxPitchDelay, + NSbfr, &fracPartPitchDelay, codecType,TmpAlignVec); + } else { + /* Computation of impulse response */ + ImpulseResponse[0] = 1.0f; + ippsZero_32f(&ImpulseResponse[1], SUBFR_LEN-1); + ippsSynthesisFilter_G729_32f(pLPC, LPC_ORDER, ImpulseResponse, ImpulseResponse, SUBFR_LEN, &ImpulseResponse[1]); + /* Annex A.3.6 Computation of target signal */ + ippsSynthesisFilter_G729_32f(pLPC, LPC_ORDER, &Excitation[NSbfr], TargetVector, SUBFR_LEN, encoderObj->WeightedFilterMemory); + /* Annex A.3.7 Adaptive-codebook search */ + pitchDelay = ownAdaptiveCodebookSearch_G729A_32f(&Excitation[NSbfr], TargetVector, ImpulseResponse, minPitchDelay, maxPitchDelay, + NSbfr, &fracPartPitchDelay,TmpAlignVec); + } + + if (NSbfr == 0) { /* if 1st subframe */ + /* encode pitch delay (with fraction) */ + if (pitchDelay <= 85) + index = pitchDelay*3 - 58 + fracPartPitchDelay; + else + index = pitchDelay + 112; + + /* find T0_min and T0_max for second subframe */ + + minPitchDelay = pitchDelay - 5; + if (minPitchDelay < PITCH_LAG_MIN) minPitchDelay = PITCH_LAG_MIN; + maxPitchDelay = minPitchDelay + 9; + if (maxPitchDelay > PITCH_LAG_MAX) { + maxPitchDelay = PITCH_LAG_MAX; + minPitchDelay = maxPitchDelay - 9; + } + } else { /* second subframe */ + if (codecType == G729D_CODEC) { /* 4 bits in 2nd subframe (6.4 kbps) */ + if (pitchDelay < minPitchDelay + 3) + index = pitchDelay - minPitchDelay; + else if (pitchDelay < minPitchDelay + 7) + index = (pitchDelay - (minPitchDelay + 3)) * 3 + fracPartPitchDelay + 3; + else + index = (pitchDelay - (minPitchDelay + 7)) + 13; + } else { + index = pitchDelay - minPitchDelay; + index = index*3 + 2 + fracPartPitchDelay; + } + + } + + *anau++ = index; + + if ( (NSbfr == 0) && (codecType != G729D_CODEC) ) { + *anau = Parity(index); + if( codecType == G729E_CODEC) { + *anau ^= ((index >> 1) & 0x0001); + } + anau++; + } + + if(codecType!=G729A_CODEC){ + delayLine[0] = pitchDelay; + delayLine[1] = fracPartPitchDelay; + ippsDecodeAdaptiveVector_G729_32f_I(delayLine, &Excitation[NSbfr]); + + ippsConvBiased_32f( &Excitation[NSbfr], SUBFR_LEN , ImpulseResponse, SUBFR_LEN , FltAdaptExc, SUBFR_LEN ,0); + } else { + ippsSynthesisFilter_G729_32f(pLPC, LPC_ORDER, &Excitation[NSbfr], FltAdaptExc, SUBFR_LEN, encoderObj->ZeroMemory); + } + /* clause 3.7.3 Computation of the adaptive-codebook gain */ + pitchGain = ownAdaptiveCodebookGainCoeff_G729_32f(TargetVector, FltAdaptExc, g_coeff, SUBFR_LEN); + + /* clip pitch gain if taming is necessary */ + + taming = TestErrorContribution_G729(pitchDelay, fracPartPitchDelay, encoderObj->ExcitationError); + + if( taming == 1){ + CLIP_TO_UPLEVEL(pitchGain,MAX_GAIN_TIMING); + } + /* Annex A3.8.1 */ + /* clause 3.8.1 Equ 50 */ + ippsAdaptiveCodebookContribution_G729_32f(pitchGain, FltAdaptExc, TargetVector, FltTargetVector); + + /* Fixed codebook search. */ + { + LOCAL_ALIGN_ARRAY(32, Ipp32f, dn, SUBFR_LEN,encoderObj); + LOCAL_ALIGN_ARRAY(32, Ipp32f, rr, TOEPLIZ_MATRIX_SIZE,encoderObj); + /* pitch contribution to ImpulseResponse */ + if(pitchDelay < SUBFR_LEN) { + ippsHarmonicFilter_32f_I(encoderObj->fBetaPreFilter,pitchDelay,&ImpulseResponse[pitchDelay],SUBFR_LEN-pitchDelay); + } + + ippsCrossCorr_32f(ImpulseResponse, SUBFR_LEN, FltTargetVector, SUBFR_LEN, dn, SUBFR_LEN, 0); + + switch (codecType) { + case G729_CODEC: /* 8 kbit/s */ + { + ippsToeplizMatrix_G729_32f(ImpulseResponse, rr); + ippsFixedCodebookSearch_G729_32f(dn, rr, FixedCodebookExc, anau, &encoderObj->sSearchTimes, NSbfr); + CodewordImpConv_G729_32f(anau[0],FixedCodebookExc,ImpulseResponse,FltFixedCodebookExc ); + anau += 2; + break; + } + case G729A_CODEC: /* 8 kbit/s */ + { + ippsToeplizMatrix_G729_32f(ImpulseResponse, rr); + ippsFixedCodebookSearch_G729A_32f(dn, rr, FixedCodebookExc, anau); + CodewordImpConv_G729_32f(anau[0],FixedCodebookExc,ImpulseResponse,FltFixedCodebookExc ); + anau += 2; + break; + } + case G729D_CODEC: /* 6.4 kbit/s */ + { + ippsToeplizMatrix_G729D_32f(ImpulseResponse, rr); + for(j=0; jfBetaPreFilter,pitchDelay,&FixedCodebookExc[pitchDelay],SUBFR_LEN-pitchDelay); + } + LOCAL_ALIGN_ARRAY_FREE(32, Ipp32f, rr, TOEPLIZ_MATRIX_SIZE,encoderObj); + LOCAL_ALIGN_ARRAY_FREE(32, Ipp32f, dn, SUBFR_LEN,encoderObj); + } + /* Annex A3.9 Quantization of gains */ + /* + Clause 3.9*/ + AdaptiveCodebookGainCoeff_G729_32f( TargetVector, FltAdaptExc, FltFixedCodebookExc, g_coeff); + + index = GainQuant_G729(FixedCodebookExc, g_coeff, SUBFR_LEN, &pitchGain, &codeGain, taming,encoderObj->PastQuantEnergy,codecType,(Ipp8s *)TmpAlignVec); + *anau++ = index; + + /* Update and bound pre filter factor with quantized adaptive codebook gain */ + for (i= 0; i< 4; i++) + encoderObj->PitchGainBuffer[i] = encoderObj->PitchGainBuffer[i+1]; + encoderObj->PitchGainBuffer[4] = pitchGain; + + encoderObj->fBetaPreFilter = pitchGain; + CLIP_TO_UPLEVEL(encoderObj->fBetaPreFilter,PITCH_SHARPMAX); + CLIP_TO_LOWLEVEL(encoderObj->fBetaPreFilter,PITCH_SHARPMIN); + + /* Find the total excitation. */ + ippsInterpolateC_G729_32f(&Excitation[NSbfr], pitchGain, FixedCodebookExc, codeGain, &Excitation[NSbfr], SUBFR_LEN); + + /* Update error function for taming process. */ + UpdateExcErr_G729(pitchGain, pitchDelay, encoderObj->ExcitationError); + + if(codecType!=G729A_CODEC){ + /* Find synthesis speech corresponding to Excitation. */ + ippsSynthesisFilter_G729_32f(pQntLPC, aqLen, &Excitation[NSbfr], &pSynth[NSbfr], SUBFR_LEN, &encoderObj->SynFltMemory[BWD_LPC_ORDER-aqLen]); + for(j=0; jSynFltMemory[j] = pSynth[NSbfr+SUBFR_LEN-BWD_LPC_ORDER+j]; + + /* Update filters memories. */ + for (i = SUBFR_LEN-BWD_LPC_ORDER, j = 0; i < SUBFR_LEN; i++, j++) { + encoderObj->ErrFltMemory[j] = SpeechWnd[NSbfr+i] - pSynth[NSbfr+i]; + encoderObj->WeightedFilterMemory[j] = TargetVector[i] - pitchGain*FltAdaptExc[i] - codeGain*FltFixedCodebookExc[i]; + } + } else { + /* Update filters memories. */ + for (i = SUBFR_LEN-LPC_ORDER, j = 0; i < SUBFR_LEN; i++, j++) + encoderObj->WeightedFilterMemory[j] = TargetVector[i] - pitchGain*FltAdaptExc[i] - codeGain*FltFixedCodebookExc[i]; + } + + pLPC += apLen+1; + pQntLPC += aqLen+1; + } + + encoderObj->prevLPCMode = LPCMode; + + /* Update signal for next frame. */ + + ippsMove_32f(&encoderObj->OldSpeechBuffer[FRM_LEN], &encoderObj->OldSpeechBuffer[0], SPEECH_BUFF_LEN-FRM_LEN); + ippsMove_32f(&encoderObj->OldWeightedSpeechBuffer[FRM_LEN], &encoderObj->OldWeightedSpeechBuffer[0], PITCH_LAG_MAX); + ippsMove_32f(&encoderObj->OldExcitationBuffer[FRM_LEN], &encoderObj->OldExcitationBuffer[0], PITCH_LAG_MAX+INTERPOL_LEN); + + if((codecType == G729_CODEC)&&(VADDecision != 1)) { + anau = EncodedParams; + } else if(codecType == G729E_CODEC) { + anau = EncodedParams+2; + } else { + anau = EncodedParams+1; + } + if((codecType == G729_CODEC)||(codecType == G729A_CODEC)) { + *frametype=3; + dst[0] = (Ipp8u)(anau[0] & 0xff); + dst[1] = (Ipp8u)((anau[1] & 0x3ff) >> 2); + dst[2] = (Ipp8u)(((anau[1] & 0x3) << 6) | ((anau[2]>>2)&0x3f) ); /* 2 + 6 */ + /* 2 + 1 + 5*/ + dst[3] = (Ipp8u)(((anau[2] & 0x3) << 6) | ((anau[3] & 0x1) << 5) | ((anau[4] & 0x1fff) >> 8) ); + dst[4] = (Ipp8u)(anau[4] & 0xff); /* 8*/ + dst[5] = (Ipp8u)(((anau[5] & 0xf)<<4) | ((anau[6] & 0x7f) >> 3)); /* 4 + 4*/ + dst[6] = (Ipp8u)(((anau[6] & 0x7)<< 5) | (anau[7] & 0x1f)); /* 3 + 5*/ + dst[7] = (Ipp8u)((anau[8] & 0x1fff) >> 5); /* 8*/ + dst[8] = (Ipp8u)(((anau[8] & 0x1f) << 3) | ((anau[9] & 0xf) >> 1)); /* 5 + 3*/ + dst[9] = (Ipp8u)(((anau[9] & 0x1) << 7) | (anau[10] & 0x7f)); /* 1 + 7*/ + } else if(codecType == G729D_CODEC) {/* D */ + *frametype=2; + dst[0] = (Ipp8u)( anau[0] & 0xff); /*8*/ + dst[1] = (Ipp8u)( (anau[1] & 0x3ff) >> 2); /*8*/ + dst[2] = (Ipp8u)( ((anau[1] & 0x3) << 6) | ((anau[2]>>2)&0x3f)); /* 2 + 6 */ + dst[3] = (Ipp8u)( ((anau[2] & 0x3) << 6) | ((anau[3]>>3)&0x3f)); /* 2 + 6 */ + dst[4] = (Ipp8u)( ((anau[3] & 0x7) << 5) | ((anau[4] & 0x3) << 3) | ((anau[5] >> 3)& 0x7)); /* 3 + 2 + 3 */ + dst[5] = (Ipp8u)( ((anau[5] & 0x7) << 5) | ((anau[6] & 0xf) << 1)| ((anau[7] >> 8)& 0x1)); /* 3 + 4 + 1*/ + dst[6] = (Ipp8u)( anau[7] & 0xff); /* 8*/ + dst[7] = (Ipp8u)( (anau[8] & 0x3) << 6 | (anau[9] & 0x3f)); /* 2 + 6*/ + } else if(codecType == G729E_CODEC) {/* E*/ + *frametype=4; + if(LPCMode == 0) { /* Forward*/ + dst[0] = (Ipp8u)( (anau[0] >> 2) & 0x3f); /* 2 + 6 */ + dst[1] = (Ipp8u)( ((anau[0] & 0x3) << 6) | ((anau[1]>>4)&0x3f)); /* 2 + 6 */ + dst[2] = (Ipp8u)( ((anau[1] & 0xf) << 4) | ((anau[2]>>4)&0xf)); /* 4 + 4 */ + dst[3] = (Ipp8u)( ((anau[2] & 0xf) << 4) | ((anau[3]&0x1)<<3) | ((anau[4]>>4)&0x7)); /* 4 + 1 + 3 */ + dst[4] = (Ipp8u)( ((anau[4] & 0xf) << 4) | ((anau[5]>>3)&0xf)); /* 4 + 4 */ + dst[5] = (Ipp8u)( ((anau[5] & 0x7) << 5) | ((anau[6]>>2)&0x1f)); /* 3 + 5 */ + dst[6] = (Ipp8u)( ((anau[6] & 0x3) << 6) | ((anau[7]>>1)&0x3f)); /* 2 + 6 */ + dst[7] = (Ipp8u)( ((anau[7]& 0x1) << 7) | (anau[8]&0x7f)); /* 1 + 7 */ + dst[8] = (Ipp8u)( ((anau[9]& 0x7f) << 1) | ((anau[10]>>4)&0x1)); /* 7 + 1 */ + dst[9] = (Ipp8u)( ((anau[10] & 0xf) << 4) | ((anau[11]>>3)&0xf)); /* 4 + 4 */ + dst[10] = (Ipp8u)( ((anau[11] & 0x7) << 5) | ((anau[12]>>2)&0x1f)); /* 3 + 5 */ + dst[11] = (Ipp8u)( ((anau[12] & 0x3) << 6) | ((anau[13]>>1)&0x3f)); /* 2 + 6 */ + dst[12] = (Ipp8u)( ((anau[13]& 0x1) << 7) | (anau[14]&0x7f)); /* 1 + 7 */ + dst[13] = (Ipp8u)( ((anau[15]& 0x7f) << 1) | ((anau[16]>>6)&0x1)); /* 7 + 1 */ + dst[14] = (Ipp8u)( ((anau[16] & 0x3f) << 2)); + } else { /* Backward*/ + dst[0] = (Ipp8u)((3<<6) | ((anau[0] >> 2) & 0x3f)); + dst[1] = (Ipp8u)(((anau[0] & 0x3) << 6) | ((anau[1]&0x1)<<5) | ((anau[2]>>8)&0x1f)); /* 2 + 1 + 5 */ + dst[2] = (Ipp8u)(anau[2] & 0xff); + dst[3] = (Ipp8u)((anau[3] >> 2) & 0xff); /* 2 + 6 */ + dst[4] = (Ipp8u)(((anau[3] & 0x3) << 6) | ((anau[4]>>1)&0x3f)); /* 2 + 6 */ + dst[5] = (Ipp8u)(((anau[4]& 0x1) << 7) | (anau[5]&0x7f)); /* 1 + 7 */ + dst[6] = (Ipp8u)(((anau[6]& 0x7f) << 1) | ((anau[7]>>6)&0x1)); /* 7 + 1 */ + dst[7] = (Ipp8u)(((anau[7]&0x3f) << 2) | ((anau[8] >>3)&0x3)); + dst[8] = (Ipp8u)(((anau[8] & 0x7) << 5) | ((anau[9]>>8)&0x1f)); /* 3 + 5 */ + dst[9] = (Ipp8u)(anau[9] & 0xff); + dst[10] = (Ipp8u)((anau[10] >> 2) & 0xff); /* 2 + 6 */ + dst[11] = (Ipp8u)(((anau[10] & 0x3) << 6) | ((anau[11]>>1)&0x3f)); /* 2 + 6 */ + dst[12] = (Ipp8u)(((anau[11]& 0x1) << 7) | (anau[12]&0x7f)); /* 1 + 7 */ + dst[13] = (Ipp8u)(((anau[13]& 0x7f) << 1) | ((anau[14]>>6)&0x1)); /* 7 + 1 */ + dst[14] = (Ipp8u)(((anau[14] & 0x3f) << 2)); + } + } + CLEAR_SCRATCH_MEMORY(encoderObj); + return APIG729_StsNoErr; +} + +G729_CODECFUN( APIG729_Status, apiG729FPEncodeVAD, + (G729FPEncoder_Obj* encoderObj,const Ipp16s* src, Ipp16s* dst, G729Codec_Type codecType, Ipp32s *frametype )) +{ + LOCAL_ALIGN_ARRAY(32, Ipp32f, forwardAutoCorr, (LPC_ORDERP2+1),encoderObj); /* Autocorrelations (forward) */ + LOCAL_ALIGN_ARRAY(32, Ipp32f, forwardLPC, LPC_ORDERP1*2,encoderObj); /* A(z) forward unquantized for the 2 subframes */ + LOCAL_ALIGN_ARRAY(32, Ipp32f, forwardQntLPC, LPC_ORDERP1*2,encoderObj); /* A(z) forward quantized for the 2 subframes */ + LOCAL_ALIGN_ARRAY(32, Ipp32f, WeightedLPC1, BWD_LPC_ORDERP1,encoderObj); /* A(z) with spectral expansion */ + LOCAL_ALIGN_ARRAY(32, Ipp32f, WeightedLPC2, BWD_LPC_ORDERP1,encoderObj); /* A(z) with spectral expansion */ + LOCAL_ALIGN_ARRAY(32, Ipp32f, TmpAlignVec, WINDOW_LEN,encoderObj); + LOCAL_ARRAY(Ipp32f, TmpAutoCorr, LPC_ORDERP1,encoderObj); + LOCAL_ARRAY(Ipp32f, forwardReflectCoeff, LPC_ORDER,encoderObj); + LOCAL_ARRAY(Ipp32f, CurrLSP, LPC_ORDER,encoderObj); + LOCAL_ARRAY(Ipp32f, CurrLSF, LPC_ORDER,encoderObj); + LOCAL_ARRAY(Ipp32f, tmpLSP, LPC_ORDER,encoderObj); + LOCAL_ARRAY(Ipp32f, InterpolatedLSF, LPC_ORDER,encoderObj); + LOCAL_ARRAY(Ipp32s, EncodedParams, 5,encoderObj); + LOCAL_ARRAY(Ipp32f, gamma1, 2,encoderObj); + LOCAL_ARRAY(Ipp32f, gamma2, 2,encoderObj); + + Ipp32f *SpeechWnd, *pWindow; + Ipp32f *newSpeech; + /* Weighted speech vector */ + Ipp32f *WeightedSpeech; + /* Excitation vector */ + Ipp32f *Excitation; + Ipp32f *pError=NULL; + Ipp32f *pSynth=NULL; + Ipp32s *anau; + Ipp16s isVAD; + Ipp32f tmp_lev; + Ipp32s VADDecision, i; + Ipp32f EnergydB; + IppStatus sts; + + if(NULL==encoderObj || NULL==src || NULL ==dst) + return APIG729_StsBadArgErr; + if ((codecType != G729_CODEC)&&(codecType != G729A_CODEC) + &&(codecType != G729D_CODEC)&&(codecType != G729E_CODEC)) + return APIG729_StsBadCodecType; + if(encoderObj->objPrm.objSize <= 0) + return APIG729_StsNotInitialized; + if(ENC_KEY != encoderObj->objPrm.key) + return APIG729_StsBadCodecType; + isVAD = (Ipp16s)(encoderObj->objPrm.mode == G729Encode_VAD_Enabled); + + if(!isVAD) return APIG729_StsNoErr; + + ippsZero_32f(WeightedLPC1,BWD_LPC_ORDERP1); + ippsZero_32f(WeightedLPC2,BWD_LPC_ORDERP1); + + anau = &EncodedParams[0]; + + newSpeech = encoderObj->OldSpeechBuffer + SPEECH_BUFF_LEN - FRM_LEN; /* New speech */ + SpeechWnd = newSpeech - LOOK_AHEAD_LEN; /* Present frame */ + pWindow = encoderObj->OldSpeechBuffer + SPEECH_BUFF_LEN - WINDOW_LEN; /* For LPC window */ + WeightedSpeech = encoderObj->OldWeightedSpeechBuffer + PITCH_LAG_MAX; + Excitation = encoderObj->OldExcitationBuffer + PITCH_LAG_MAX + INTERPOL_LEN; + + if(codecType!=G729A_CODEC){ + pError = encoderObj->ErrFltMemory + BWD_LPC_ORDER; + pSynth = encoderObj->SynthBuffer + BWD_SYNTH_MEM; + } + + if (encoderObj->sFrameCounter == 32767) encoderObj->sFrameCounter = 256; + else encoderObj->sFrameCounter++; + + ippsConvert_16s32f(src,newSpeech,FRM_LEN); + + ippsIIR_32f_I(newSpeech,FRM_LEN,encoderObj->iirstate); + + ownAutoCorr_G729_32f(pWindow, LPC_ORDERP2, forwardAutoCorr,TmpAlignVec); /* Autocorrelations */ + ippsCopy_32f(forwardAutoCorr, TmpAutoCorr, LPC_ORDERP1); + + /* Lag windowing */ + ippsMul_32f_I(lwindow, &forwardAutoCorr[1], LPC_ORDERP2); + /* Levinson Durbin */ + tmp_lev = 0; + sts = ippsLevinsonDurbin_G729_32f(forwardAutoCorr, LPC_ORDER, &forwardLPC[LPC_ORDERP1], forwardReflectCoeff, &tmp_lev); + if(sts == ippStsOverflow) { + ippsCopy_32f(encoderObj->OldForwardLPC,&forwardLPC[LPC_ORDERP1],LPC_ORDER+1); + forwardReflectCoeff[0] = encoderObj->OldForwardRC[0]; + forwardReflectCoeff[1] = encoderObj->OldForwardRC[1]; + } else { + ippsCopy_32f(&forwardLPC[LPC_ORDERP1],encoderObj->OldForwardLPC,LPC_ORDER+1); + encoderObj->OldForwardRC[0] = forwardReflectCoeff[0]; + encoderObj->OldForwardRC[1] = forwardReflectCoeff[1]; + } + + + /* Convert A(z) to lsp */ + if(codecType==G729A_CODEC){ + ippsLPCToLSP_G729A_32f(&forwardLPC[LPC_ORDERP1], encoderObj->OldLSP, CurrLSP); + } else { + ippsLPCToLSP_G729_32f(&forwardLPC[LPC_ORDERP1], encoderObj->OldLSP, CurrLSP); + } + + if (encoderObj->objPrm.mode == G729Encode_VAD_Enabled) { + ownACOS_G729_32f(CurrLSP, CurrLSF, LPC_ORDER); + VoiceActivityDetect_G729_32f(forwardReflectCoeff[1], CurrLSF, forwardAutoCorr, pWindow, encoderObj->sFrameCounter, + encoderObj->prevVADDec, encoderObj->prevPrevVADDec, &VADDecision, &EnergydB,encoderObj->vadMem,TmpAlignVec); + + if(codecType!=G729A_CODEC){ + MusicDetection_G729E_32f( encoderObj, codecType, forwardAutoCorr[0],forwardReflectCoeff, &VADDecision, EnergydB,encoderObj->msdMem,TmpAlignVec); + } + + UpdateCNG(TmpAutoCorr, VADDecision,encoderObj->cngMem); + } else VADDecision = 1; + + if(VADDecision == 0) { + if(codecType==G729A_CODEC){ + UpdateVad_A(encoderObj, Excitation, WeightedSpeech, SpeechWnd, anau); + } else { + /* Inactive frame */ + ippsCopy_32f(&encoderObj->SynthBuffer[FRM_LEN], &encoderObj->SynthBuffer[0], BWD_SYNTH_MEM); + /* Find interpolated LPC parameters in all subframes unquantized. * + * The interpolated parameters are in array forwardLPC[] of size (LPC_ORDER+1)*4 */ + if( encoderObj->prevLPCMode == 0) { + ippsInterpolateC_G729_32f(encoderObj->OldLSP, 0.5f, CurrLSP, 0.5f, tmpLSP, LPC_ORDER); + + ippsLSPToLPC_G729_32f(tmpLSP, forwardLPC); + + ownACOS_G729_32f(tmpLSP, InterpolatedLSF, LPC_ORDER); + ownACOS_G729_32f(CurrLSP, CurrLSF, LPC_ORDER); + } else { + /* no interpolation */ + /* unquantized */ + ippsLSPToLPC_G729_32f(CurrLSP, forwardLPC); /* Subframe 1 */ + ownACOS_G729_32f(CurrLSP, CurrLSF, LPC_ORDER); /* transformation from LSP to LSF (freq.domain) */ + ippsCopy_32f(CurrLSF, InterpolatedLSF, LPC_ORDER); /* Subframe 1 */ + } + + if (encoderObj->sGlobalStatInd > 10000) { + encoderObj->sGlobalStatInd -= 2621; + if(encoderObj->sGlobalStatInd < 10000) encoderObj->sGlobalStatInd = 10000 ; + } + encoderObj->isBWDDominant = 0; + encoderObj->fInterpolationCoeff = 1.1f; + + ippsCopy_32f(CurrLSP, encoderObj->OldLSP, LPC_ORDER); + + PWGammaFactor_G729(gamma1, gamma2, InterpolatedLSF, CurrLSF, forwardReflectCoeff,&encoderObj->isSmooth, encoderObj->LogAreaRatioCoeff); + + UpdateVad_I(encoderObj, Excitation, forwardLPC, WeightedSpeech, gamma1, gamma2, pSynth, + pError, SpeechWnd, anau, codecType); + + /* update previous filter for next frame */ + ippsCopy_32f(&forwardQntLPC[LPC_ORDERP1], encoderObj->PrevFlt, LPC_ORDERP1); + for(i=LPC_ORDERP1; i PrevFlt[i] = 0.f; + } + encoderObj->prevLPCMode = 0; + + encoderObj->fBetaPreFilter = PITCH_SHARPMIN; + + /* Update memories for next frames */ + ippsMove_32f(&encoderObj->OldSpeechBuffer[FRM_LEN], &encoderObj->OldSpeechBuffer[0], SPEECH_BUFF_LEN-FRM_LEN); + ippsMove_32f(&encoderObj->OldWeightedSpeechBuffer[FRM_LEN], &encoderObj->OldWeightedSpeechBuffer[0], PITCH_LAG_MAX); + ippsMove_32f(&encoderObj->OldExcitationBuffer[FRM_LEN], &encoderObj->OldExcitationBuffer[0], PITCH_LAG_MAX+INTERPOL_LEN); + + anau = EncodedParams+1; + if(EncodedParams[0] == 0){ /* untransmitted*/ + *frametype=0; + }else{ + *frametype=1; /* SID*/ + dst[0] = (Ipp16s)anau[0]; /* Switched predictor index of LSF quantizer: 1 LSB */ + dst[1] = (Ipp16s)anau[1]; /* 1st stage vector of LSF quantizer: 5 LSB*/ + dst[2] = (Ipp16s)anau[2]; /* 2nd stage vector of LSF quantizer: 4 LSB*/ + dst[3] = (Ipp16s)anau[3]; /* Gain (Energy): 5 LSB */ + } + + CLEAR_SCRATCH_MEMORY(encoderObj); + + return APIG729_StsNoErr; + } + + encoderObj->sCNGSeed = INIT_SEED_VAL; + encoderObj->prevPrevVADDec = encoderObj->prevVADDec; + encoderObj->prevVADDec = VADDecision; + ippsMove_32f(&encoderObj->OldSpeechBuffer[FRM_LEN], &encoderObj->OldSpeechBuffer[0], SPEECH_BUFF_LEN-FRM_LEN); + ippsMove_32f(&encoderObj->OldWeightedSpeechBuffer[FRM_LEN], &encoderObj->OldWeightedSpeechBuffer[0], PITCH_LAG_MAX); + ippsMove_32f(&encoderObj->OldExcitationBuffer[FRM_LEN], &encoderObj->OldExcitationBuffer[0], PITCH_LAG_MAX+INTERPOL_LEN); + + CLEAR_SCRATCH_MEMORY(encoderObj); + + return APIG729_StsNoErr; +} + +static void UpdateCNG(Ipp32f *pSrcAutoCorr, Ipp32s Vad, Ipp8s *cngMem) +{ + Ipp32s i; + CNGmemory *cngState = (CNGmemory *)cngMem; + + /* Update AutoCorrs */ + for(i=0; i<(AUTOCORRS_SIZE-LPC_ORDERP1); i++) { + cngState->AutoCorrs[AUTOCORRS_SIZE - 1 - i] = cngState->AutoCorrs[AUTOCORRS_SIZE - LPC_ORDERP1 - 1 - i]; + } + + /* Save current AutoCorrs */ + ippsCopy_32f(pSrcAutoCorr, cngState->AutoCorrs, LPC_ORDERP1); + + cngState->lAutoCorrsCounter++; + if(cngState->lAutoCorrsCounter == CURRAUTOCORRS_NUM) { + cngState->lAutoCorrsCounter = 0; + if(Vad != 0) { + for(i=0; i<(SUMAUTOCORRS_SIZE-LPC_ORDERP1); i++) { + cngState->SumAutoCorrs[SUMAUTOCORRS_SIZE - 1 -i] = cngState->SumAutoCorrs[SUMAUTOCORRS_SIZE - LPC_ORDERP1 - 1 - i]; + } + /* Compute new SumAutoCorrs */ + for(i=0; iSumAutoCorrs[i] = cngState->AutoCorrs[i]+cngState->AutoCorrs[LPC_ORDERP1+i]; + } + } + } + return; +} + +static void CNG(G729FPEncoder_Obj* encoderObj, Ipp32f *pSrcExc, Ipp32f *pDstIntLPC, Ipp32s *pDstParam, G729Codec_Type mode) +{ + LOCAL_ALIGN_ARRAY(32, Ipp32f, curAcf, LPC_ORDERP1,encoderObj); + LOCAL_ALIGN_ARRAY(32, Ipp32f, curCoeff, LPC_ORDERP1,encoderObj); + LOCAL_ALIGN_ARRAY(32, Ipp32f, pastCoeff, LPC_ORDERP1,encoderObj); + LOCAL_ALIGN_ARRAY(32, Ipp8s, tmpAlignVec, 60*sizeof(Ipp32f)+6*sizeof(Ipp32s),encoderObj); + LOCAL_ARRAY(Ipp32f, bid, LPC_ORDERP1,encoderObj); + LOCAL_ARRAY(Ipp32f, s_sumAcf, LPC_ORDERP1,encoderObj); + LOCAL_ARRAY(Ipp32f, CurrLSP, LPC_ORDER,encoderObj); + LOCAL_ARRAY(Ipp32f, tmpLSP, LPC_ORDER,encoderObj); + Ipp32s i; + Ipp32f *lpcCoeff, *OldQuantLSP, *old_A, *old_rc; + Ipp32s currIgain, prevVADDec; + Ipp32f energyq; + IppStatus sts; + Ipp32f tmp; + + CNGmemory *cngState = (CNGmemory *)encoderObj->cngMem; + prevVADDec = encoderObj->prevVADDec; + OldQuantLSP = encoderObj->OldQuantLSP; + old_A = encoderObj->OldForwardLPC; + old_rc = encoderObj->OldForwardRC; + + /* Update Ener */ + for(i = GAINS_NUM-1; i>=1; i--) { + cngState->Energies[i] = cngState->Energies[i-1]; + } + + /* Compute current Acfs */ + for(i=0; iAutoCorrs[i]+cngState->AutoCorrs[LPC_ORDERP1+i]; + } + + /* Compute LPC coefficients and residual energy */ + if(isVarZero(curAcf[0])) { + cngState->Energies[0] = 0.f; /* should not happen */ + } else { + sts = ippsLevinsonDurbin_G729_32f(curAcf, LPC_ORDER, curCoeff, bid, &cngState->Energies[0]); + if(sts == ippStsOverflow) { + ippsCopy_32f(old_A,curCoeff,LPC_ORDER+1); + bid[0] = old_rc[0]; + bid[1] = old_rc[1]; + } else { + ippsCopy_32f(curCoeff,old_A,LPC_ORDER+1); + old_rc[0] = bid[0]; + old_rc[1] = bid[1]; + } + } + + /* if first frame of silence => SID frame */ + if(prevVADDec != 0) { + pDstParam[0] = 1; + cngState->lFrameCounter0 = 0; + cngState->lNumSavedEnergies = 1; + QuantSIDGain_G729B(cngState->Energies, cngState->lNumSavedEnergies, &energyq, &currIgain); + } else { + cngState->lNumSavedEnergies++; + CLIP_TO_UPLEVEL(cngState->lNumSavedEnergies,GAINS_NUM); + QuantSIDGain_G729B(cngState->Energies, cngState->lNumSavedEnergies, &energyq, &currIgain); + + /* Compute stationarity of current filter versus reference filter.*/ + /* Compute Itakura distance and compare to threshold */ + ippsDotProd_32f(cngState->ReflectCoeffs,curAcf,LPC_ORDER+1,&tmp); + if(tmp > (cngState->Energies[0] * ITAKURATHRESH1)) cngState->lFltChangeFlag = 1; + + /* compare energy difference between current frame and last frame */ + if( (Ipp32f)fabs(cngState->fPrevEnergy - energyq) > 2.0f) cngState->lFltChangeFlag = 1; + + cngState->lFrameCounter0++; + if(cngState->lFrameCounter0 < N_MIN_SIM_RRAMES) { + pDstParam[0] = 0; /* no transmission */ + } else { + if(cngState->lFltChangeFlag != 0) { + pDstParam[0] = 1; /* transmit SID frame */ + } else { + pDstParam[0] = 0; + } + cngState->lFrameCounter0 = N_MIN_SIM_RRAMES; + } + } + + if(pDstParam[0] == 1) { + /* Reset frame count and lFltChangeFlag */ + cngState->lFrameCounter0 = 0; + cngState->lFltChangeFlag = 0; + + /* Compute past average filter */ + s_sumAcf[0] = cngState->SumAutoCorrs[0]+cngState->SumAutoCorrs[LPC_ORDERP1]+cngState->SumAutoCorrs[2*LPC_ORDERP1]; + + if(isVarZero(s_sumAcf[0])) { + ippsZero_32f(pastCoeff,LPC_ORDERP1); + pastCoeff[0] = 1.f; + } else { + for(i=1; iSumAutoCorrs[i]+cngState->SumAutoCorrs[LPC_ORDERP1+i]+cngState->SumAutoCorrs[2*LPC_ORDERP1+i]; + } + sts = ippsLevinsonDurbin_G729_32f(s_sumAcf, LPC_ORDER, pastCoeff, bid, &tmp); + if(sts == ippStsOverflow) { + ippsCopy_32f(old_A,pastCoeff,LPC_ORDER+1); + bid[0] = old_rc[0]; + bid[1] = old_rc[1]; + } else { + ippsCopy_32f(pastCoeff,old_A,LPC_ORDER+1); + old_rc[0] = bid[0]; + old_rc[1] = bid[1]; + } + } + + /* Compute autocorrelation of LPC coefficients used for Itakura distance */ + ippsCrossCorr_32f(pastCoeff, LPC_ORDER+1, pastCoeff, LPC_ORDER+1, cngState->ReflectCoeffs, LPC_ORDER+1, 0); + cngState->ReflectCoeffs[0] = cngState->ReflectCoeffs[0]/2; + + /* Compute stationarity of current filter versus past average filter.*/ + + /* if stationary transmit average filter. */ + /* Compute Itakura distance and compare to threshold */ + ippsDotProd_32f(cngState->ReflectCoeffs,curAcf,LPC_ORDER+1,&tmp); + if(tmp <= (cngState->Energies[0] * ITAKURATHRESH2)) { + /* transmit old filter*/ + lpcCoeff = pastCoeff; + } else { + /* transmit current filter => new ref. filter */ + lpcCoeff = curCoeff; + /* Compute autocorrelation of LPC coefficients used for Itakura distance */ + ippsCrossCorr_32f(curCoeff, LPC_ORDER+1, curCoeff, LPC_ORDER+1, cngState->ReflectCoeffs, LPC_ORDER+1, 0); + cngState->ReflectCoeffs[0] = cngState->ReflectCoeffs[0]/2; + } + + /* Compute SID frame codes */ + if(mode==G729A_CODEC) + ippsLPCToLSP_G729A_32f(lpcCoeff, OldQuantLSP, CurrLSP); /* From A(z) to lsp */ + else + ippsLPCToLSP_G729_32f(lpcCoeff, OldQuantLSP, CurrLSP); /* From A(z) to lsp */ + + /* LSP quantization */ + + { + LOCAL_ARRAY(Ipp32f, fTmpLSF, LPC_ORDER,encoderObj); + + /* convert lsp to lsf */ + ownACOS_G729_32f(CurrLSP, fTmpLSF, LPC_ORDER); + + /* spacing to ~100Hz */ + if (fTmpLSF[0] < LSF_LOW_LIMIT) + fTmpLSF[0] = LSF_LOW_LIMIT; + for (i=0 ; i < LPC_ORDER-1 ; i++) { + if (fTmpLSF[i+1]- fTmpLSF[i] < 2*LSF_DIST) fTmpLSF[i+1] = fTmpLSF[i]+ 2*LSF_DIST; + } + if (fTmpLSF[LPC_ORDER-1] > LSF_HI_LIMIT) + fTmpLSF[LPC_ORDER-1] = LSF_HI_LIMIT; + if (fTmpLSF[LPC_ORDER-1] < fTmpLSF[LPC_ORDER-2]) + fTmpLSF[LPC_ORDER-2] = fTmpLSF[LPC_ORDER-1]- LSF_DIST; + + + ippsLSFQuant_G729B_32f(fTmpLSF, (Ipp32f*)encoderObj->PrevFreq, cngState->SIDQuantLSP, &pDstParam[1]); + + LOCAL_ARRAY_FREE(Ipp32f, fTmpLSF, LPC_ORDER,encoderObj); + } + + + cngState->fPrevEnergy = energyq; + pDstParam[4] = currIgain; + cngState->fSIDGain = SIDGainTbl[currIgain]; + } + + /* Compute new excitation */ + if(prevVADDec != 0) { + cngState->fCurrGain = cngState->fSIDGain; + } else { + cngState->fCurrGain *= GAIN_INT_FACTOR; + cngState->fCurrGain += INV_GAIN_INT_FACTOR * cngState->fSIDGain; + } + + if(isVarZero(cngState->fCurrGain)) { + ippsZero_32f(pSrcExc,FRM_LEN); + UpdateExcErr_G729(0.f, SUBFR_LEN+1,encoderObj->ExcitationError); + UpdateExcErr_G729(0.f, SUBFR_LEN+1,encoderObj->ExcitationError); + } else { + ComfortNoiseExcitation_G729(cngState->fCurrGain, pSrcExc, &encoderObj->sCNGSeed, ENCODER, encoderObj->ExcitationError,NULL,tmpAlignVec); + } + + ippsInterpolateC_G729_32f(OldQuantLSP, 0.5f, cngState->SIDQuantLSP, 0.5f, tmpLSP, LPC_ORDER); + + ippsLSPToLPC_G729_32f(tmpLSP, pDstIntLPC); + ippsLSPToLPC_G729_32f(cngState->SIDQuantLSP, &pDstIntLPC[LPC_ORDER+1]); + + ippsCopy_32f(cngState->SIDQuantLSP, OldQuantLSP, LPC_ORDER); + + /* Update SumAutoCorrs if lAutoCorrsCounter = 0 */ + if(cngState->lAutoCorrsCounter == 0) { + for(i=0; i<(SUMAUTOCORRS_SIZE-LPC_ORDERP1); i++) { + cngState->SumAutoCorrs[SUMAUTOCORRS_SIZE - 1 -i] = cngState->SumAutoCorrs[SUMAUTOCORRS_SIZE - LPC_ORDERP1 - 1 - i]; + } + + /* Compute new SumAutoCorrs */ + for(i=0; iSumAutoCorrs[i] = cngState->AutoCorrs[i]+cngState->AutoCorrs[LPC_ORDERP1+i]; + } + } + LOCAL_ARRAY_FREE(Ipp32f, tmpLSP, LPC_ORDER,encoderObj); + LOCAL_ARRAY_FREE(Ipp32f, CurrLSP, LPC_ORDER,encoderObj); + LOCAL_ARRAY_FREE(Ipp32f, s_sumAcf, LPC_ORDERP1,encoderObj); + LOCAL_ARRAY_FREE(Ipp32f, bid, LPC_ORDERP1,encoderObj); + LOCAL_ALIGN_ARRAY_FREE(32, Ipp32f, pastCoeff, LPC_ORDERP1,encoderObj); + LOCAL_ALIGN_ARRAY_FREE(32, Ipp32f, curCoeff, LPC_ORDERP1,encoderObj); + LOCAL_ALIGN_ARRAY_FREE(32, Ipp32f, curAcf, LPC_ORDERP1,encoderObj); + return; +} +static void UpdateVad_I(G729FPEncoder_Obj* encoderObj, Ipp32f *Excitation, Ipp32f *forwardLPC, Ipp32f *WeightedSpeech, + Ipp32f *gamma1, Ipp32f *gamma2, Ipp32f *pSynth, + Ipp32f *pError, Ipp32f *SpeechWnd, Ipp32s* dst,G729Codec_Type codecType) +{ + LOCAL_ALIGN_ARRAY(32, Ipp32f, WeightedLPC1, BWD_LPC_ORDERP1,encoderObj); /* A(z) with spectral expansion */ + LOCAL_ALIGN_ARRAY(32, Ipp32f, WeightedLPC2, BWD_LPC_ORDERP1,encoderObj); /* A(z) with spectral expansion */ + LOCAL_ALIGN_ARRAY(32, Ipp32f, TargetVector, SUBFR_LEN,encoderObj); + LOCAL_ALIGN_ARRAY(32, Ipp32f, forwardQntLPC, LPC_ORDERP1*2,encoderObj); /* A(z) forward quantized for the 2 subframes */ + Ipp32s i, j, NGamma, NSbfr; + + CNG(encoderObj,Excitation, forwardQntLPC, dst,codecType); + + encoderObj->prevPrevVADDec = encoderObj->prevVADDec; + encoderObj->prevVADDec = 0; + + /* Update filters memory*/ + for(NSbfr=0, NGamma = 0; NSbfr < FRM_LEN; NSbfr += SUBFR_LEN, NGamma++) { + WeightLPCCoeff_G729(forwardLPC, gamma1[NGamma], LPC_ORDER, WeightedLPC1); + WeightLPCCoeff_G729(forwardLPC, gamma2[NGamma], LPC_ORDER, WeightedLPC2); +#ifdef CLIPPING_DENORMAL_MODE + for(j=0; jFltMem[BWD_LPC_ORDER-LPC_ORDER]); + for(j=0; jFltMem[j] = WeightedSpeech[NSbfr+SUBFR_LEN-BWD_LPC_ORDER+j]; + + /* update synthesis filter's memory*/ + ippsSynthesisFilter_G729_32f(forwardQntLPC, LPC_ORDER, &Excitation[NSbfr], &pSynth[NSbfr], SUBFR_LEN, &encoderObj->SynFltMemory[BWD_LPC_ORDER-LPC_ORDER]); + for(j=0; jSynFltMemory[j] = pSynth[NSbfr+SUBFR_LEN-BWD_LPC_ORDER+j]; + + /* update WeightedFilterMemory */ + ippsSub_32f(&pSynth[NSbfr],&SpeechWnd[NSbfr],pError,SUBFR_LEN); + ippsConvBiased_32f(WeightedLPC1,LPC_ORDER+1,pError,SUBFR_LEN+LPC_ORDER,TargetVector,SUBFR_LEN,LPC_ORDER); + ippsSynthesisFilter_G729_32f(WeightedLPC2, LPC_ORDER, TargetVector, TargetVector, SUBFR_LEN, &encoderObj->WeightedFilterMemory[BWD_LPC_ORDER-LPC_ORDER]); + for(j=0; jWeightedFilterMemory[j] = TargetVector[SUBFR_LEN-BWD_LPC_ORDER+j]; + + /* update ErrFltMemory */ + for (i = SUBFR_LEN-BWD_LPC_ORDER, j = 0; i < SUBFR_LEN; i++, j++) + encoderObj->ErrFltMemory[j] = pError[i]; + + for (i= 0; i< 4; i++) + encoderObj->PitchGainBuffer[i] = encoderObj->PitchGainBuffer[i+1]; + encoderObj->PitchGainBuffer[4] = 0.5f; + + forwardLPC += LPC_ORDERP1; + forwardQntLPC += LPC_ORDERP1; + } + + LOCAL_ALIGN_ARRAY_FREE(32, Ipp32f, forwardQntLPC, LPC_ORDERP1*2,encoderObj); /* A(z) forward quantized for the 2 subframes */ + LOCAL_ALIGN_ARRAY_FREE(32, Ipp32f, TargetVector, SUBFR_LEN,encoderObj); + LOCAL_ALIGN_ARRAY_FREE(32, Ipp32f, WeightedLPC2, BWD_LPC_ORDERP1,encoderObj); /* A(z) with spectral expansion */ + LOCAL_ALIGN_ARRAY_FREE(32, Ipp32f, WeightedLPC1, BWD_LPC_ORDERP1,encoderObj); /* A(z) with spectral expansion */ + return; +} + +static void UpdateVad_A(G729FPEncoder_Obj* encoderObj, Ipp32f *Excitation, + Ipp32f *WeightedSpeech, Ipp32f *SpeechWnd, Ipp32s* dst) +{ + LOCAL_ALIGN_ARRAY(32, Ipp32f, forwardLPC, LPC_ORDERP1*2,encoderObj); /* A(z) forward unquantized for the 2 subframes */ + LOCAL_ALIGN_ARRAY(32, Ipp32f, forwardQntLPC, LPC_ORDERP1*2,encoderObj); /* A(z) forward quantized for the 2 subframes */ + LOCAL_ALIGN_ARRAY(32, Ipp32f, TargetVector, SUBFR_LEN,encoderObj); + Ipp32s i, NSbfr; + Ipp32f *pQLPC, *pUnQLPC; + + CNG(encoderObj,Excitation, forwardQntLPC, dst,G729A_CODEC); + + encoderObj->prevPrevVADDec = encoderObj->prevVADDec; + encoderObj->prevVADDec = 0; + /* Update WeightedSpeech, FltMem and WeightedFilterMemory */ + pQLPC = forwardQntLPC; + for(NSbfr=0; NSbfr < FRM_LEN; NSbfr += SUBFR_LEN) { + + /* Residual signal in TargetVector */ + ippsConvBiased_32f(pQLPC,LPC_ORDER+1,&SpeechWnd[NSbfr],SUBFR_LEN+LPC_ORDER,TargetVector,SUBFR_LEN,LPC_ORDER); + + WeightLPCCoeff_G729(pQLPC, GAMMA1_G729A, LPC_ORDER, forwardLPC); + + /* Compute WeightedSpeech and FltMem */ + pUnQLPC = forwardLPC + LPC_ORDERP1; + pUnQLPC[0] = 1.0f; + for(i=1; i<=LPC_ORDER; i++) + pUnQLPC[i] = forwardLPC[i] - 0.7f * forwardLPC[i-1]; + ippsSynthesisFilter_G729_32f(pUnQLPC, LPC_ORDER, TargetVector, &WeightedSpeech[NSbfr], SUBFR_LEN, encoderObj->FltMem); + for (i = 0; i < LPC_ORDER; i++) CLIP_DENORMAL(WeightedSpeech[(SUBFR_LEN-LPC_ORDER)+i],encoderObj->FltMem[i]); + + /* Compute WeightedFilterMemory */ + ippsSub_32f_I(&Excitation[NSbfr],TargetVector,SUBFR_LEN); + + ippsSynthesisFilter_G729_32f(forwardLPC, LPC_ORDER, TargetVector, TargetVector, SUBFR_LEN, encoderObj->WeightedFilterMemory); + for (i = 0; i < LPC_ORDER; i++) CLIP_DENORMAL(TargetVector[i],encoderObj->FltMem[i]); + + pQLPC += LPC_ORDERP1; + } + + LOCAL_ALIGN_ARRAY_FREE(32, Ipp32f, TargetVector, SUBFR_LEN,encoderObj); + LOCAL_ALIGN_ARRAY_FREE(32, Ipp32f, forwardQntLPC, LPC_ORDERP1*2,encoderObj); /* A(z) forward quantized for the 2 subframes */ + LOCAL_ALIGN_ARRAY_FREE(32, Ipp32f, forwardLPC, LPC_ORDERP1*2,encoderObj); /* A(z) forward unquantized for the 2 subframes */ + + return; +} diff --git a/g723api.h b/g723api.h new file mode 100644 index 0000000..7a38094 --- /dev/null +++ b/g723api.h @@ -0,0 +1,112 @@ +/*///////////////////////////////////////////////////////////////////////////// +// +// 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-2007 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 ippEULA.rtf or ippEULA.txt 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: coder API header. +// +*/ + +#ifndef __G723API_H__ +#define __G723API_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define G723_FrameSize 240 +#define G723_BitStreamFrameSizeMax 24 + +#define G723_ENC_KEY 0xecd723 +#define G723_DEC_KEY 0xdec723 + +typedef struct { + Ipp32s objSize; + Ipp32s key; + Ipp32u mode; /* mode's */ + Ipp32u rat: 1; /* encode rate: 0-63, 1-53, other bits reserved.*/ +}G723_Obj_t; + +typedef enum _G723Encode_Mode{ + G723Encode_DefaultMode=0, /* r63 ; HF, VAD disabled; */ + G723Encode_VAD_Enabled=1, + G723Encode_HF_Enabled =2 +}G723Encode_Mode; + +typedef enum _G723Decode_Mode{ + G723Decode_DefaultMode=0, /* r63 ; PF disabled */ + G723Decode_PF_Enabled =1 +}G723Decode_Mode; + +typedef enum{ + APIG723_StsBadCodecType = -5, + APIG723_StsNotInitialized = -4, + APIG723_StsBadArgErr = -3, + APIG723_StsDeactivated = -2, + APIG723_StsErr = -1, + APIG723_StsNoErr = 0 +}APIG723_Status; + +struct _G723VADmemory; +struct _G723Encoder_Obj; +struct _G723Decoder_Obj; + +typedef struct _G723VADmemory G723VADmemory; +typedef struct _G723Encoder_Obj G723Encoder_Obj; +typedef struct _G723Decoder_Obj G723Decoder_Obj; + +#define G723_CODECAPI(type,name,arg) extern type name arg; + +/* + Functions declarations +*/ +G723_CODECAPI( APIG723_Status, apiG723Codec_ScratchMemoryAlloc,(Ipp32s *pCodecSize)) +G723_CODECAPI( APIG723_Status, apiG723Encoder_Alloc, (Ipp32s *pCodecSize)) +G723_CODECAPI( APIG723_Status, apiG723Decoder_Alloc, (Ipp32s *pCodecSize)) +G723_CODECAPI( APIG723_Status, apiG723Encoder_Init, + (G723Encoder_Obj* encoderObj, Ipp32u mode)) +G723_CODECAPI( APIG723_Status, apiG723Decoder_Init, + (G723Decoder_Obj* decoderObj, Ipp32u mode)) +G723_CODECAPI( APIG723_Status, apiG723Encoder_InitBuff, + (G723Encoder_Obj* encoderObj, Ipp8s *buff)) +G723_CODECAPI( APIG723_Status, apiG723Decoder_InitBuff, + (G723Decoder_Obj* decoderObj, Ipp8s *buff)) +G723_CODECAPI( APIG723_Status, apiG723Encode, + (G723Encoder_Obj* encoderObj, const Ipp16s* src, Ipp16s rat, Ipp8s* dst )) +G723_CODECAPI( APIG723_Status, apiG723Decode, + (G723Decoder_Obj* decoderObj, const Ipp8s* src, Ipp16s badFrameIndicator, Ipp16s* dst)) +G723_CODECAPI( APIG723_Status, apiG723Encoder_Mode, + (G723Encoder_Obj* encoderObj, Ipp32u mode)) +G723_CODECAPI( APIG723_Status, apiG723Encoder_ControlMode, + (G723Encoder_Obj* encoderObj, Ipp32u mode)) +G723_CODECAPI( APIG723_Status, apiG723Decoder_ControlMode, + (G723Decoder_Obj* decoderObj, Ipp32u mode)) + +#define G723_ENCODER_SCRATCH_MEMORY_SIZE (5120+40) + +#ifdef __cplusplus +} +#endif + +#endif /* __G723API_H__ */ diff --git a/g723codec.cpp b/g723codec.cpp new file mode 100644 index 0000000..33126bf --- /dev/null +++ b/g723codec.cpp @@ -0,0 +1,249 @@ +/** + * g723codec.cpp + * This file is part of the YATE Project http://YATE.null.ro + * + * G.723.1 codec using Intel IPP + * + * Yet Another Telephony Engine - a fully featured software PBX and IVR + * Copyright (C) 2004, 2005 Null Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include "g723api.h" + +#define L_FRAME 240 +#define L_FRAME_COMPRESSED_63 24 // 6.3k +#define L_FRAME_COMPRESSED_53 20 // 5.3k +#define G723_RATE_63 0 // G723_Rate63 in owng723.h +#define G723_RATE_53 1 // G723_Rate53 + +#define G723_DEFAULT_SEND_RATE G723_RATE_63 + +#if G723_DEFAULT_SEND_RATE == G723_RATE_63 +#define L_FRAME_COMPRESSED L_FRAME_COMPRESSED_63 +#else +#define L_FRAME_COMPRESSED L_FRAME_COMPRESSED_53 +#endif + +typedef short g723_block[L_FRAME]; +typedef unsigned char g723_frame[L_FRAME_COMPRESSED]; + +using namespace TelEngine; + +static TranslatorCaps caps[] = { + { 0, 0 }, + { 0, 0 }, + { 0, 0 } +}; + +class G723Plugin : public Plugin, public TranslatorFactory +{ +public: + G723Plugin(); + ~G723Plugin(); + virtual void initialize() { } + virtual bool isBusy() const; + virtual DataTranslator* create(const DataFormat& sFormat, const DataFormat& dFormat); + virtual const TranslatorCaps* getCapabilities() const; +}; + +class G723Codec : public DataTranslator +{ +public: + G723Codec(const char* sFormat, const char* dFormat, bool encoding); + ~G723Codec(); +#ifndef YATE_G72X_POST_R2745 + virtual void Consume(const DataBlock& data, unsigned long tStamp); +#else + virtual unsigned long Consume(const DataBlock& data, unsigned long tStamp, unsigned long flags); +#endif + static int encoderSize; + static int decoderSize; + static int coderSizeScratch; + volatile static int count; + +private: + int g723_sendrate; + DataBlock m_data; + + G723Decoder_Obj* decoder; + G723Encoder_Obj* encoder; + Ipp8s *coderScratchMem; + + static int G723FrameLength(int frametype); +}; + +int G723Codec::encoderSize; +int G723Codec::decoderSize; +int G723Codec::coderSizeScratch; + +volatile int G723Codec::count = 0; + +G723Codec::G723Codec(const char* sFormat, const char* dFormat, bool encoding) + : DataTranslator(sFormat,dFormat), decoder(0), encoder(0), g723_sendrate(G723_DEFAULT_SEND_RATE) +{ + Debug(DebugAll,"G723Codec::G723Codec(\"%s\",\"%s\",%scoding) [%p]", + sFormat,dFormat, encoder ? "en" : "de", this); + + coderScratchMem = ippsMalloc_8s(coderSizeScratch); + if (encoding) { + encoder = (G723Encoder_Obj*)ippsMalloc_8u(encoderSize); + apiG723Encoder_InitBuff(encoder, coderScratchMem); + apiG723Encoder_Init(encoder, G723Encode_DefaultMode); + } + else { + decoder = (G723Decoder_Obj*)ippsMalloc_8u(decoderSize); + apiG723Decoder_InitBuff(decoder, coderScratchMem); + apiG723Decoder_Init(decoder, G723Decode_DefaultMode); + } + // gcc way to say ++count atomically + __sync_add_and_fetch(&count, 1); +} + +G723Codec::~G723Codec() +{ + Debug(DebugAll,"G723Codec::~G723Codec() [%p]",this); + ippsFree(encoder ? (void*)encoder : (void*)decoder); + ippsFree(coderScratchMem); + // --count; + __sync_add_and_fetch(&count, -1); +} + +int G723Codec::G723FrameLength(int frametype) +{ + switch(frametype) { + case 0: return 24; /* 6.3kbps */ + case 1: return 20; /* 5.3kbps */ + case 2: return 4; /* SID */ + } + return 1; /* XXX untransmitted */ +} + +#ifndef YATE_G72X_POST_R2745 +void G723Codec::Consume(const DataBlock& data, unsigned long tStamp) +#else +unsigned long G723Codec::Consume(const DataBlock& data, unsigned long tStamp, unsigned long flags) +#endif +{ + if (!getTransSource()) +#ifndef YATE_G72X_POST_R2745 + return; +#else + return 0; + if (data.null() && (flags & DataSilent)) + return getTransSource()->Forward(data, tStamp, flags); +#endif + ref(); + m_data += data; + DataBlock outdata; + int frames, consumed; + if (encoder) { + frames = m_data.length() / sizeof(g723_block); + consumed = frames * sizeof(g723_block); + if (frames) { + outdata.assign(0, frames*sizeof(g723_frame)); + for (int i = 0; i < frames; i++) { + short* decompressed_buffer = (short*)(((g723_block *)m_data.data())+i); + Ipp8s* compressed_buffer = (Ipp8s*)(((g723_frame *)outdata.data())+i); + int frametype; + apiG723Encode(encoder, decompressed_buffer, g723_sendrate, compressed_buffer); + } + } + if (!tStamp) + tStamp = timeStamp() + (consumed / 2); + } + else { + frames = 0; + int framesize; + for(consumed = 0; consumed < m_data.length(); consumed += framesize) { + int frametype = *((unsigned char *)m_data.data() + consumed) & (short)0x0003; + framesize = G723FrameLength(frametype); + ++frames; + } + outdata.assign(0, frames * sizeof(g723_block)); + frames = 0; + for(consumed = 0; consumed < m_data.length(); consumed += framesize) { + int frametype = *((unsigned char *)m_data.data() + consumed) & (short)0x0003; + framesize = G723FrameLength(frametype); + const Ipp8s* compressed_buffer = (Ipp8s*)((unsigned char *)m_data.data() + consumed); + short* decompressed_buffer = (short*)((g723_block*)outdata.data() + frames); + int badframe = 0; // normal frame + apiG723Decode(decoder, compressed_buffer, badframe, decompressed_buffer); + ++frames; + } + if (!tStamp) + tStamp = timeStamp() + (frames*sizeof(g723_block) / 2); + } + XDebug("G723Codec",DebugAll,"%scoding %d frames of %d input bytes (consumed %d) in %d output bytes", + encoder ? "en" : "de",frames,m_data.length(),consumed,outdata.length()); +#ifdef YATE_G72X_POST_R2745 + unsigned long len = 0; +#endif + if (frames) { + m_data.cut(-consumed); +#ifndef YATE_G72X_POST_R2745 + getTransSource()->Forward(outdata,tStamp); +#else + len = getTransSource()->Forward(outdata, tStamp, flags); +#endif + } + deref(); +#ifdef YATE_G72X_POST_R2745 + return len; +#endif +} + +G723Plugin::G723Plugin() +{ + Output("Loaded module G.723.1 - based on Intel IPP"); + const FormatInfo* f = FormatRepository::addFormat("g723",L_FRAME_COMPRESSED,L_FRAME*1000/8); + caps[0].src = caps[1].dest = f; + caps[0].dest = caps[1].src = FormatRepository::getFormat("slin"); + caps[0].cost = caps[1].cost = 5; + + apiG723Decoder_Alloc(&G723Codec::decoderSize); + apiG723Encoder_Alloc(&G723Codec::encoderSize); + apiG723Codec_ScratchMemoryAlloc(&G723Codec::coderSizeScratch); +} + +G723Plugin::~G723Plugin() +{ + Output("Unloading module G.723.1"); +} + +bool G723Plugin::isBusy() const +{ + return (G723Codec::count != 0); +} + +DataTranslator* G723Plugin::create(const DataFormat& sFormat, const DataFormat& dFormat) +{ + if (sFormat == "slin" && dFormat == "g723") + return new G723Codec(sFormat,dFormat,true); + else if (sFormat == "g723" && dFormat == "slin") + return new G723Codec(sFormat,dFormat,false); + else return 0; +} + +const TranslatorCaps* G723Plugin::getCapabilities() const +{ + return caps; +} + +INIT_PLUGIN(G723Plugin); diff --git a/g723ipp.h b/g723ipp.h new file mode 100644 index 0000000..954ce92 --- /dev/null +++ b/g723ipp.h @@ -0,0 +1,36 @@ +/*///////////////////////////////////////////////////////////////////////////// +// +// 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-2007 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 ippEULA.rtf or ippEULA.txt 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: IPP header files includer. +// +*/ + +#ifndef __G723IPP_H__ +#define __G723IPP_H__ + +#include +#include + +#endif /* __G723IPP_H__ */ + diff --git a/g729codec.cpp b/g729codec.cpp new file mode 100644 index 0000000..fdecae7 --- /dev/null +++ b/g729codec.cpp @@ -0,0 +1,229 @@ +/** + * g729codec.cpp + * This file is part of the YATE Project http://YATE.null.ro + * + * G.729a codec using Intel IPP + * + * Yet Another Telephony Engine - a fully featured software PBX and IVR + * Copyright (C) 2004, 2005 Null Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include "g729fpapi.h" + +#define G729Encoder_Obj G729FPEncoder_Obj +#define G729Decoder_Obj G729FPDecoder_Obj +#define apiG729Encoder_InitBuff apiG729FPEncoder_InitBuff +#define apiG729Decoder_InitBuff apiG729FPDecoder_InitBuff +#define apiG729Encoder_Init apiG729FPEncoder_Init +#define apiG729Decoder_Init apiG729FPDecoder_Init +#define apiG729Encode apiG729FPEncode +#define apiG729Decode apiG729FPDecode +#define apiG729Encoder_Alloc apiG729FPEncoder_Alloc +#define apiG729Decoder_Alloc apiG729FPDecoder_Alloc +#define apiG729Codec_ScratchMemoryAlloc apiG729FPCodec_ScratchMemoryAlloc + +#define L_FRAME 80 +#define L_FRAME_COMPRESSED 10 +typedef short g729_block[L_FRAME]; +typedef unsigned char g729_frame[L_FRAME_COMPRESSED]; + +using namespace TelEngine; + +static TranslatorCaps caps[] = { + { 0, 0 }, + { 0, 0 }, + { 0, 0 } +}; + +class G729Plugin : public Plugin, public TranslatorFactory +{ +public: + G729Plugin(); + ~G729Plugin(); + virtual void initialize() { } + virtual bool isBusy() const; + virtual DataTranslator* create(const DataFormat& sFormat, const DataFormat& dFormat); + virtual const TranslatorCaps* getCapabilities() const; +}; + +class G729Codec : public DataTranslator +{ +public: + G729Codec(const char* sFormat, const char* dFormat, bool encoding); + ~G729Codec(); +#ifndef YATE_G72X_POST_R2745 + virtual void Consume(const DataBlock& data, unsigned long tStamp); +#else + virtual unsigned long Consume(const DataBlock& data, unsigned long tStamp, unsigned long flags); +#endif + static int encoderSize; + static int decoderSize; + static int coderSizeScratch; + volatile static int count; + +private: + DataBlock m_data; + + G729FPDecoder_Obj* decoder; + G729FPEncoder_Obj* encoder; + Ipp8s *coderScratchMem; +}; + +int G729Codec::encoderSize; +int G729Codec::decoderSize; +int G729Codec::coderSizeScratch; + +volatile int G729Codec::count = 0; + +G729Codec::G729Codec(const char* sFormat, const char* dFormat, bool encoding) + : DataTranslator(sFormat,dFormat), decoder(0), encoder(0) +{ + Debug(DebugAll,"G729Codec::G729Codec(\"%s\",\"%s\",%scoding) [%p]", + sFormat,dFormat, encoder ? "en" : "de", this); + + coderScratchMem = ippsMalloc_8s(coderSizeScratch); + if (encoding) { + encoder = (G729Encoder_Obj*)ippsMalloc_8u(encoderSize); + apiG729Encoder_InitBuff(encoder, coderScratchMem); + apiG729Encoder_Init(encoder, G729A_CODEC, G729Encode_VAD_Disabled); + } + else { + decoder = (G729Decoder_Obj*)ippsMalloc_8u(decoderSize); + apiG729Decoder_InitBuff(decoder, coderScratchMem); + apiG729Decoder_Init(decoder, G729A_CODEC); + } + // gcc way to say ++count atomically + __sync_add_and_fetch(&count, 1); +} + +G729Codec::~G729Codec() +{ + Debug(DebugAll,"G729Codec::~G729Codec() [%p]",this); + ippsFree(encoder ? (void*)encoder : (void*)decoder); + ippsFree(coderScratchMem); + // --count; + __sync_add_and_fetch(&count, -1); +} + +#ifndef YATE_G72X_POST_R2745 +void G729Codec::Consume(const DataBlock& data, unsigned long tStamp) +#else +unsigned long G729Codec::Consume(const DataBlock& data, unsigned long tStamp, unsigned long flags) +#endif +{ + if (!getTransSource()) +#ifndef YATE_G72X_POST_R2745 + return; +#else + return 0; + if (data.null() && (flags & DataSilent)) + return getTransSource()->Forward(data, tStamp, flags); +#endif + ref(); + m_data += data; + DataBlock outdata; + int frames, consumed; + if (encoder) { + frames = m_data.length() / sizeof(g729_block); + consumed = frames * sizeof(g729_block); + if (frames) { + outdata.assign(0, frames*sizeof(g729_frame)); + for (int i = 0; i < frames; i++) { + short* decompressed_buffer = (short*)(((g729_block *)m_data.data())+i); + unsigned char* compressed_buffer = (unsigned char*)(((g729_frame *)outdata.data())+i); + int frametype; + apiG729Encode(encoder, decompressed_buffer, compressed_buffer, G729A_CODEC, &frametype); + } + } + if (!tStamp) + tStamp = timeStamp() + (consumed / 2); + } + else { + frames = m_data.length() / sizeof(g729_frame); + consumed = frames * sizeof(g729_frame); + if (frames) { + outdata.assign(0, frames*sizeof(g729_block)); + for (int i = 0; i < frames; i++) { + unsigned char* compressed_buffer = (unsigned char*)(((g729_frame *)m_data.data())+i); + short* decompressed_buffer = (short*)(((g729_block *)outdata.data())+i); + int frametype = 3; // active frame + apiG729Decode(decoder, compressed_buffer, frametype, decompressed_buffer); + } + } + if (!tStamp) + tStamp = timeStamp() + (frames*sizeof(g729_block) / 2); + } + XDebug("G729Codec",DebugAll,"%scoding %d frames of %d input bytes (consumed %d) in %d output bytes", + encoder ? "en" : "de",frames,m_data.length(),consumed,outdata.length()); +#ifdef YATE_G72X_POST_R2745 + unsigned long len = 0; +#endif + if (frames) { + m_data.cut(-consumed); +#ifndef YATE_G72X_POST_R2745 + getTransSource()->Forward(outdata,tStamp); +#else + len = getTransSource()->Forward(outdata, tStamp, flags); +#endif + } + deref(); +#ifdef YATE_G72X_POST_R2745 + return len; +#endif +} + +G729Plugin::G729Plugin() +{ + Output("Loaded module G.729a - based on Intel IPP"); + const FormatInfo* f = FormatRepository::addFormat("g729",L_FRAME_COMPRESSED,L_FRAME*1000/8); + caps[0].src = caps[1].dest = f; + caps[0].dest = caps[1].src = FormatRepository::getFormat("slin"); + caps[0].cost = caps[1].cost = 5; + + apiG729Decoder_Alloc(G729A_CODEC, &G729Codec::decoderSize); + apiG729Encoder_Alloc(G729A_CODEC, &G729Codec::encoderSize); + apiG729Codec_ScratchMemoryAlloc(&G729Codec::coderSizeScratch); +} + +G729Plugin::~G729Plugin() +{ + Output("Unloading module G.729a"); +} + +bool G729Plugin::isBusy() const +{ + return (G729Codec::count != 0); +} + +DataTranslator* G729Plugin::create(const DataFormat& sFormat, const DataFormat& dFormat) +{ + if (sFormat == "slin" && dFormat == "g729") + return new G729Codec(sFormat,dFormat,true); + else if (sFormat == "g729" && dFormat == "slin") + return new G729Codec(sFormat,dFormat,false); + else return 0; +} + +const TranslatorCaps* G729Plugin::getCapabilities() const +{ + return caps; +} + +INIT_PLUGIN(G729Plugin); diff --git a/g729fpapi.h b/g729fpapi.h new file mode 100644 index 0000000..1b25914 --- /dev/null +++ b/g729fpapi.h @@ -0,0 +1,109 @@ +/*///////////////////////////////////////////////////////////////////////////// +// +// 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) 2004-2007 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 ippEULA.rtf or ippEULA.txt 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.729 floating-point speech codec: API header file. +// +*/ + +#ifndef __G729FPAPI_H__ +#define __G729FPAPI_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum _G729Codec_Type{ + G729_CODEC=0, + G729A_CODEC=1, + G729D_CODEC=2, + G729E_CODEC=3, + G729I_CODEC=4 +}G729Codec_Type; + +typedef enum _G729Encode_Mode{ + G729Encode_VAD_Enabled =1, + G729Encode_VAD_Disabled=0 +}G729Encode_Mode; + +typedef enum _G729Decode_Mode{ + G729Decode_DefaultMode=0 +}G729Decode_Mode; + +typedef enum{ + APIG729_StsBadCodecType = -5, + APIG729_StsNotInitialized = -4, + APIG729_StsBadArgErr = -3, + APIG729_StsDeactivated = -2, + APIG729_StsErr = -1, + APIG729_StsNoErr = 0 +}APIG729_Status; + +struct _G729FPVADmemory_Obj; +struct _G729FPEncoder_Obj; +struct _G729FPDecoder_Obj; +typedef struct _G729FPVADmemory_Obj VADmemory; +typedef struct _G729FPEncoder_Obj G729FPEncoder_Obj; +typedef struct _G729FPDecoder_Obj G729FPDecoder_Obj;__G729FPAPI_H__ + +#if defined( _WIN32 ) || defined ( _WIN64 ) + #define __STDCALL __stdcall + #define __CDECL __cdecl +#else + #define __STDCALL + #define __CDECL +#endif + +#define G729_CODECAPI(type,name,arg) extern type name arg; + +/* + Functions declarations +*/ +G729_CODECAPI( APIG729_Status, apiG729FPEncoder_Alloc, + (G729Codec_Type codecType, Ipp32s *pCodecSize)) +G729_CODECAPI( APIG729_Status, apiG729FPDecoder_Alloc, + (G729Codec_Type codecType, Ipp32s *pCodecSize)) +G729_CODECAPI( APIG729_Status, apiG729FPCodec_ScratchMemoryAlloc, + (Ipp32s *pCodecSize)) +G729_CODECAPI( APIG729_Status, apiG729FPEncoder_Init, + (G729FPEncoder_Obj* encoderObj, G729Codec_Type codecType, G729Encode_Mode mode)) +G729_CODECAPI( APIG729_Status, apiG729FPDecoder_Init, + (G729FPDecoder_Obj* decoderObj, G729Codec_Type codecType)) +G729_CODECAPI( APIG729_Status, apiG729FPEncoder_InitBuff, + (G729FPEncoder_Obj* encoderObj, Ipp8s *buff)) +G729_CODECAPI( APIG729_Status, apiG729FPDecoder_InitBuff, + (G729FPDecoder_Obj* decoderObj, Ipp8s *buff)) +G729_CODECAPI( APIG729_Status, apiG729FPEncode, + (G729FPEncoder_Obj* encoderObj,const Ipp16s* src, Ipp8u* dst, G729Codec_Type codecType, Ipp32s *frametype)) +G729_CODECAPI( APIG729_Status, apiG729FPEncodeVAD, + (G729FPEncoder_Obj* encoderObj,const Ipp16s* src, Ipp16s* dst, G729Codec_Type codecType, Ipp32s *pVAD )) +G729_CODECAPI( APIG729_Status, apiG729FPDecode, + (G729FPDecoder_Obj* decoderObj,const Ipp8u* src, Ipp32s frametype, Ipp16s* dst)) +G729_CODECAPI( APIG729_Status, apiG729FPEncoder_Mode, + (G729FPEncoder_Obj* encoderObj, G729Encode_Mode mode)) + +#ifdef __cplusplus +} +#endif + +#endif /* __G729FPAPI_H__ */ diff --git a/owng723.c b/owng723.c new file mode 100644 index 0000000..8e0af16 --- /dev/null +++ b/owng723.c @@ -0,0 +1,1405 @@ +/*///////////////////////////////////////////////////////////////////////////// +// +// 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-2007 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 ippEULA.rtf or ippEULA.txt 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: internal functions and tables. +// +*/ + +#include "owng723.h" + +typedef enum { + G723_Rate63Frame = 0, + G723_Rate53Frame, + G723_SIDFrame, + G723_UntransmittedFrame +}G723_Info_Bit; + +static Ipp32s ExtractBits( const Ipp8s **pBitStrm, Ipp32s *currBitstrmOffset, Ipp32s numParamBits ) +{ + Ipp32s i ; + Ipp32s unpackedParam = 0 ; + + for ( i = 0 ; i < numParamBits ; i ++ ){ + Ipp32s lTemp; + lTemp = ((*pBitStrm)[(i + *currBitstrmOffset)>>3] >> ((i + *currBitstrmOffset) & 0x7)) & 1; + unpackedParam += lTemp << i ; + } + + *pBitStrm += (numParamBits + *currBitstrmOffset)>>3; + *currBitstrmOffset = (numParamBits + *currBitstrmOffset) & 0x7; + + return unpackedParam ; +} + +void GetParamFromBitstream( const Ipp8s *pSrcBitStream, ParamStream_G723 *Params) +{ + Ipp32s i; + Ipp32s lTmp ; + Ipp16s InfoBit; + Ipp16s Bound_AcGn; + const Ipp8s **pBitStream = &pSrcBitStream; + Ipp32s nBit = 0; + + /* Extract the frame type and rate info */ + InfoBit = (Ipp16s)ExtractBits(pBitStream, &nBit, 2); + if ( InfoBit == G723_UntransmittedFrame ) { + Params->FrameType = G723_UntransmittedFrm; Params->lLSPIdx = 0; + return; + } + if ( InfoBit == G723_SIDFrame ) { /* SID frame*/ + Params->lLSPIdx = ExtractBits(pBitStream, &nBit, 24);/* LspId */ + Params->sAmpIndex[0] = (Ipp16s)ExtractBits(pBitStream, &nBit, 6); /* Gain */ + Params->FrameType = G723_SIDFrm; return; + } + if ( InfoBit == G723_Rate53Frame ) { + Params->FrameType = G723_ActiveFrm; + Params->currRate = G723_Rate53; + Params->lLSPIdx = ExtractBits(pBitStream, &nBit, 24);/* LspId */ + Params->PitchLag[0] = (Ipp16s)ExtractBits(pBitStream, &nBit, 7); + Params->AdCdbkLag[1] = (Ipp16s)ExtractBits(pBitStream, &nBit, 2); + Params->PitchLag[1] = (Ipp16s)ExtractBits(pBitStream, &nBit, 7); + Params->AdCdbkLag[3] = (Ipp16s)ExtractBits(pBitStream, &nBit, 2); + + Params->AdCdbkLag[0] = Params->AdCdbkLag[2] = 1; + + Params->AdCdbkGain[0] = (Ipp16s)ExtractBits(pBitStream, &nBit, 12); + Params->AdCdbkGain[1] = (Ipp16s)ExtractBits(pBitStream, &nBit, 12); + Params->AdCdbkGain[2] = (Ipp16s)ExtractBits(pBitStream, &nBit, 12); + Params->AdCdbkGain[3] = (Ipp16s)ExtractBits(pBitStream, &nBit, 12); + + Params->sGrid[0] = (Ipp16s)ExtractBits(pBitStream, &nBit, 1); + Params->sGrid[1] = (Ipp16s)ExtractBits(pBitStream, &nBit, 1); + Params->sGrid[2] = (Ipp16s)ExtractBits(pBitStream, &nBit, 1); + Params->sGrid[3] = (Ipp16s)ExtractBits(pBitStream, &nBit, 1); + + Params->sPosition[0] = ExtractBits(pBitStream, &nBit, 12); + Params->sPosition[1] = ExtractBits(pBitStream, &nBit, 12); + Params->sPosition[2] = ExtractBits(pBitStream, &nBit, 12); + Params->sPosition[3] = ExtractBits(pBitStream, &nBit, 12); + + Params->sAmplitude[0] = (Ipp16s)ExtractBits(pBitStream, &nBit, 4); + Params->sAmplitude[1] = (Ipp16s)ExtractBits(pBitStream, &nBit, 4); + Params->sAmplitude[2] = (Ipp16s)ExtractBits(pBitStream, &nBit, 4); + Params->sAmplitude[3] = (Ipp16s)ExtractBits(pBitStream, &nBit, 4); + /* Frame erasure concealment and parameters scaling*/ + if( Params->PitchLag[0] <= 123) { + Params->PitchLag[0] += G723_MIN_PITCH ; + } else { + Params->isBadFrame = 1; /* transmission error */ + return; + } + if( Params->PitchLag[1] <= 123) { + Params->PitchLag[1] += G723_MIN_PITCH ; + } else { + Params->isBadFrame = 1; /* transmission error */ + return; + } + + for ( i = 0 ; i < 4 ; i ++ ) { + Params->sTrainDirac[i] = 0 ; + Bound_AcGn = AdCdbkSizeLowRate; + lTmp = Params->AdCdbkGain[i]; + Params->AdCdbkGain[i] = (Ipp16s)(lTmp/N_GAINS) ; + if(Params->AdCdbkGain[i] < Bound_AcGn ) { + Params->sAmpIndex[i] = (Ipp16s)(lTmp % N_GAINS) ; + } else { + Params->isBadFrame = 1; /* transmission error */ + return ; + } + } + return; + } + if (InfoBit == G723_Rate63Frame) { + Params->FrameType = G723_ActiveFrm; + Params->currRate = G723_Rate63; + Params->lLSPIdx = ExtractBits(pBitStream, &nBit, 24);/* LspId */ + + Params->PitchLag[0] = (Ipp16s)ExtractBits(pBitStream, &nBit, 7); + Params->AdCdbkLag[1] = (Ipp16s)ExtractBits(pBitStream, &nBit, 2); + Params->PitchLag[1] = (Ipp16s)ExtractBits(pBitStream, &nBit, 7); + Params->AdCdbkLag[3] = (Ipp16s)ExtractBits(pBitStream, &nBit, 2); + + Params->AdCdbkLag[0] = Params->AdCdbkLag[2] = 1; + + Params->AdCdbkGain[0] = (Ipp16s)ExtractBits(pBitStream, &nBit, 12); + Params->AdCdbkGain[1] = (Ipp16s)ExtractBits(pBitStream, &nBit, 12); + Params->AdCdbkGain[2] = (Ipp16s)ExtractBits(pBitStream, &nBit, 12); + Params->AdCdbkGain[3] = (Ipp16s)ExtractBits(pBitStream, &nBit, 12); + + Params->sGrid[0] = (Ipp16s)ExtractBits(pBitStream, &nBit, 1); + Params->sGrid[1] = (Ipp16s)ExtractBits(pBitStream, &nBit, 1); + Params->sGrid[2] = (Ipp16s)ExtractBits(pBitStream, &nBit, 1); + Params->sGrid[3] = (Ipp16s)ExtractBits(pBitStream, &nBit, 1); + + ExtractBits(pBitStream, &nBit, 1);/* Skip the reserved bit for align pack*/ + + lTmp = ExtractBits(pBitStream, &nBit, 13); /*Exract the position,s MSB*/ + /* lTmp = 810*x0 + 90*x1 + 9*x2 + x3*/ + Params->sPosition[0] = lTmp / 810; + lTmp -= Params->sPosition[0]*810; /* lTmp = 90*x1 + 9*x2 + x3*/ + Params->sPosition[1] = lTmp / 90; + lTmp -= Params->sPosition[1]*90; /* lTmp = 9*x2 + x3*/ + Params->sPosition[2] = lTmp / 9; + Params->sPosition[3] = lTmp - (Params->sPosition[2]*9); + + /* Extract all the pulse positions */ + Params->sPosition[0] = ( Params->sPosition[0] << 16 ) + ExtractBits(pBitStream, &nBit, 16) ; + Params->sPosition[1] = ( Params->sPosition[1] << 14 ) + ExtractBits(pBitStream, &nBit, 14) ; + Params->sPosition[2] = ( Params->sPosition[2] << 16 ) + ExtractBits(pBitStream, &nBit, 16) ; + Params->sPosition[3] = ( Params->sPosition[3] << 14 ) + ExtractBits(pBitStream, &nBit, 14) ; + + /* Extract pulse amplitudes */ + Params->sAmplitude[0] = (Ipp16s)ExtractBits(pBitStream, &nBit, 6); + Params->sAmplitude[1] = (Ipp16s)ExtractBits(pBitStream, &nBit, 5); + Params->sAmplitude[2] = (Ipp16s)ExtractBits(pBitStream, &nBit, 6); + Params->sAmplitude[3] = (Ipp16s)ExtractBits(pBitStream, &nBit, 5); + + /* Frame erasure concealment and parameters scaling*/ + + if( Params->PitchLag[0] <= 123) { + Params->PitchLag[0] += G723_MIN_PITCH ; + } else { + Params->isBadFrame = 1; /* transmission error */ + return; + } + if( Params->PitchLag[1] <= 123) { + Params->PitchLag[1] += G723_MIN_PITCH ; + } else { + Params->isBadFrame = 1; /* transmission error */ + return; + } + for ( i = 0 ; i < 4 ; i ++ ) { + lTmp = Params->AdCdbkGain[i]; + Params->sTrainDirac[i] = 0 ; + Bound_AcGn = AdCdbkSizeLowRate ; + if (Params->PitchLag[i>>1] < (G723_SBFR_LEN-2)) { + Params->sTrainDirac[i] = (Ipp16s)(lTmp >> 11) ; + lTmp &= 0x7ff ; + Bound_AcGn = AdCdbkSizeHighRate ; + } + Params->AdCdbkGain[i] = (Ipp16s)(lTmp/N_GAINS) ; + if(Params->AdCdbkGain[i] < Bound_AcGn ) { + Params->sAmpIndex[i] = (Ipp16s)(lTmp % N_GAINS) ; + } else { + Params->isBadFrame = 1; /* transmission error */ + return ; + } + } + return; + } + return; +} + +static Ipp16s* Parm2Bits( Ipp32s param, Ipp16s *pBitStrm, Ipp32s ParamBitNum ) +{ + Ipp32s i; + for ( i = 0 ; i < ParamBitNum ; i ++ ) { + *pBitStrm ++ = (Ipp16s) (param & 0x1); + param >>= 1; + } + + return pBitStrm; +} +void SetParam2Bitstream(G723Encoder_Obj* encoderObj, ParamStream_G723 *Params, Ipp8s *pDstBitStream) +{ + Ipp32s i; + Ipp16s *pBitStream, *pB; + Ipp32s MSBs; + + LOCAL_ARRAY(Ipp16s, Bits,192,encoderObj); + + pBitStream = Bits; + + switch (Params->FrameType) { + + case 0 : /* untransmitted */ + pBitStream = Parm2Bits( G723_UntransmittedFrame, pBitStream, 2 ); + + pDstBitStream[0] = (Ipp8s)(Bits[0] ^ (Bits[1] << 1)); + + break; + case 2 : /* SID */ + ippsZero_8u((Ipp8u *)pDstBitStream, 4); + pBitStream = Parm2Bits( G723_SIDFrame, pBitStream, 2 ); + + pBitStream = Parm2Bits( Params->lLSPIdx, pBitStream, 24 ); /* 24 bit lLSPIdx */ + pBitStream = Parm2Bits( Params->sAmpIndex[0], pBitStream, 6 );/* Do Sid frame gain */ + + pB = Bits; + for ( i = 0 ; i < 4 ; i ++, pB+=8 ) + pDstBitStream[i]=(Ipp8s)(pB[0]^(pB[1]<<1)^(pB[2]<<2)^(pB[3]<<3)^(pB[4]<<4)^(pB[5]<<5)^(pB[6]<<6)^(pB[7]<<7)); + break; + default : + if ( Params->currRate == G723_Rate63 ){ + ippsZero_8u((Ipp8u *)pDstBitStream, 24); + pBitStream = Parm2Bits( G723_Rate63Frame, pBitStream, 2 ); + + pBitStream = Parm2Bits( Params->lLSPIdx, pBitStream, 24 ) ; /* 24 bit LspId */ + pBitStream = Parm2Bits( Params->PitchLag[0] - G723_MIN_PITCH, pBitStream, 7 ) ; /* Adaptive codebook lags */ + pBitStream = Parm2Bits( Params->AdCdbkLag[1], pBitStream, 2 ) ; + pBitStream = Parm2Bits( Params->PitchLag[1] - G723_MIN_PITCH, pBitStream, 7 ) ; + pBitStream = Parm2Bits( Params->AdCdbkLag[3], pBitStream, 2 ) ; + + /* Write gains indexes of 12 bit */ + for ( i = 0 ; i < 4 ; i ++ ) { + pBitStream = Parm2Bits( Params->AdCdbkGain[i]*N_GAINS + Params->sAmpIndex[i] + (Params->sTrainDirac[i] << 11), pBitStream, 12 ) ; + } + + for ( i = 0 ; i < 4 ; i ++ ) + *pBitStream ++ = Params->sGrid[i] ; /* Write all the Grid indices */ + + *pBitStream ++ = 0 ; /* reserved bit */ + /* Write 13 bit combined position index, pack 4 MSB from each pulse position. */ + MSBs = (Params->sPosition[0] >> 16) * 810 + ( Params->sPosition[1] >> 14)*90 + + (Params->sPosition[2] >> 16) * 9 + ( Params->sPosition[3] >> 14 ); + pBitStream = Parm2Bits(MSBs, pBitStream, 13); + + /* Write all the pulse positions */ + pBitStream = Parm2Bits(Params->sPosition[0] & 0xffff, pBitStream, 16); + pBitStream = Parm2Bits(Params->sPosition[1] & 0x3fff, pBitStream, 14); + pBitStream = Parm2Bits(Params->sPosition[2] & 0xffff, pBitStream, 16); + pBitStream = Parm2Bits(Params->sPosition[3] & 0x3fff, pBitStream, 14); + + /* Write pulse amplitudes */ + pBitStream = Parm2Bits(Params->sAmplitude[0], pBitStream, 6); + pBitStream = Parm2Bits(Params->sAmplitude[1] , pBitStream, 5); + pBitStream = Parm2Bits(Params->sAmplitude[2], pBitStream, 6); + pBitStream = Parm2Bits(Params->sAmplitude[3], pBitStream, 5); + + pB = Bits; + for ( i = 0 ; i < 24 ; i ++, pB+=8 ) + pDstBitStream[i]=(Ipp8s)(pB[0]^(pB[1]<<1)^(pB[2]<<2)^(pB[3]<<3)^(pB[4]<<4)^(pB[5]<<5)^(pB[6]<<6)^(pB[7]<<7)); + }else{ + ippsZero_8u((Ipp8u *)pDstBitStream, 20); + pBitStream = Parm2Bits( G723_Rate53Frame, pBitStream, 2 ); + + pBitStream = Parm2Bits( Params->lLSPIdx, pBitStream, 24 ) ; /* 24 bit lLSPIdx */ + pBitStream = Parm2Bits( Params->PitchLag[0] - G723_MIN_PITCH, pBitStream, 7 ) ; /* Adaptive codebook lags */ + pBitStream = Parm2Bits( Params->AdCdbkLag[1], pBitStream, 2 ) ; + pBitStream = Parm2Bits( Params->PitchLag[1] - G723_MIN_PITCH, pBitStream, 7 ) ; + pBitStream = Parm2Bits( Params->AdCdbkLag[3], pBitStream, 2 ) ; + + /* Write gains indexes of 12 bit */ + for ( i = 0 ; i < 4 ; i ++ ) + pBitStream = Parm2Bits( Params->AdCdbkGain[i]*N_GAINS + Params->sAmpIndex[i], pBitStream, 12 ); + + for ( i = 0 ; i < 4 ; i ++ ) + *pBitStream ++ = Params->sGrid[i] ; /* Write all the Grid indices */ + + /* Write positions */ + for ( i = 0 ; i < 4 ; i ++ ) { + pBitStream = Parm2Bits( Params->sPosition[i], pBitStream, 12 ) ; + } + /* Write Pamps */ + for ( i = 0 ; i < 4 ; i ++ ) { + pBitStream = Parm2Bits( Params->sAmplitude[i], pBitStream, 4 ) ; + } + pB = Bits; + for ( i = 0 ; i < 20 ; i ++, pB+=8 ) + pDstBitStream[i]=(Ipp8s)(pB[0]^(pB[1]<<1)^(pB[2]<<2)^(pB[3]<<3)^(pB[4]<<4)^(pB[5]<<5)^(pB[6]<<6)^(pB[7]<<7)); + } + break; + } + + LOCAL_ARRAY_FREE(Ipp16s, Bits,192,encoderObj); + return; +} + +void UpdateSineDetector(Ipp16s *SineWaveDetector, Ipp16s *isNotSineWave) +{ + Ipp32s i, x, lNumTimes; + + *SineWaveDetector &= 0x7fff ; + *isNotSineWave = 1; + + x= *SineWaveDetector; + lNumTimes = 0; + for ( i = 0 ; i < 15 ; i ++ ) { + lNumTimes += x&1; + x >>= 1; + } + if ( lNumTimes >= 14 ) /* Sine wave is detected*/ + *isNotSineWave = -1; +} +/*Usage GenPostFiltTable(Tbl, 0.65); GenPostFiltTable(Tbl+10, 0.75); +#define SATURATE_fs(dVal,dRez)\ + if (dVal >= 0.0) dVal += 0.5;\ + else dVal -= 0.5;\ + dRez = (Ipp16s)dVal; + +static void GenPostFiltTable(Ipp16s *Tbl, Ipp64f dInit) +{ + Ipp64f dFac,dTmp; + Ipp32s i; + dFac = dInit; + for(i=0;i<10;i++) { + dTmp = dFac*32768.f; + SATURATE_fs(dTmp,Tbl[i]); + dFac = dFac*dInit; + } +}*/ +static __ALIGN32 CONST Ipp16s PostFiltTable[2*G723_LPC_ORDER] = { + 21299 , 13844,8999,5849,3802,2471,1606,1044, 679, 441 , /* Zero part */ + 24576,18432,13824,10368,7776,5832,4374,3281,2460,1845 , /* Pole part */ +}; +void PostFilter(G723Decoder_Obj* decoderObj, Ipp16s *pSrcDstSignal, Ipp16s *pSrcLPC ) +{ + Ipp32s i, lTmp, lSignalEnergy, lSfs; + Ipp16s sTmp; + + LOCAL_ARRAY(Ipp16s, FltCoef,2*G723_LPC_ORDER, decoderObj); + LOCAL_ARRAY(Ipp32s, pFltSignal,G723_LPC_ORDER+G723_SBFR_LEN, decoderObj); + LOCAL_ARRAY(Ipp32s, pAutoCorr,2, decoderObj); + LOCAL_ARRAY(Ipp16s, pTmpVec,G723_SBFR_LEN, decoderObj); + + /* Normalize the input speech vector. */ + lSfs=3; + ippsAutoScale_16s(pSrcDstSignal, pTmpVec, (Ipp16s) G723_SBFR_LEN, &lSfs ) ; + + /* Compute the first two autocorrelation coefficients*/ + ippsDotProd_16s32s_Sfs(pTmpVec,pTmpVec,G723_SBFR_LEN,pAutoCorr,0); + ippsDotProd_16s32s_Sfs(pTmpVec,pTmpVec+1,G723_SBFR_LEN-1,pAutoCorr+1,0); + /* Compute new reflection coefficient.*/ + sTmp = (Ipp16s)(pAutoCorr[0]>>15); + if ( sTmp ) { + sTmp = (Ipp16s)((pAutoCorr[1]>>1)/(sTmp)); + } + + /* Compute interpolated reflection coefficient use the new and previous one.*/ + lTmp = ((decoderObj->ReflectionCoeff << 2) - decoderObj->ReflectionCoeff + sTmp); + decoderObj->ReflectionCoeff = (Ipp16s)((lTmp+0x2)>>2); + + sTmp = (Ipp16s)(((Ipp32s)decoderObj->ReflectionCoeff * (Ipp32s)SmoothCoeff)>>15); + sTmp &= 0xfffc ; + + /* Compute FIR and IIR coefficients. Note the table can be generated using the GenPostFiltTable function */ + ippsMul_NR_16s_Sfs(pSrcLPC,PostFiltTable,FltCoef,G723_LPC_ORDER,15); + ippsMul_NR_16s_Sfs(pSrcLPC,PostFiltTable+G723_LPC_ORDER,FltCoef+G723_LPC_ORDER,G723_LPC_ORDER,15); + + /* 32s output needs for compensate filter */ + for(i=0; iPostFilterMem[G723_LPC_ORDER+i]<<16; + } + ippsIIR16s_G723_16s32s(FltCoef,pSrcDstSignal,&pFltSignal[G723_LPC_ORDER],decoderObj->PostFilterMem); + + /* perform the tilt filtering. */ + ippsTiltCompensation_G723_32s16s(sTmp, &pFltSignal[G723_LPC_ORDER-1], pSrcDstSignal); + + /* Gain scaling. Section 3.9 */ + /* Compute normalized signal energy.*/ + sTmp = (Ipp16s)(2*lSfs + 3); + if (sTmp < 0) { + lSignalEnergy = ShiftL_32s(pAutoCorr[0],(Ipp16u)(-sTmp)); + } else { + lSignalEnergy = pAutoCorr[0]>>sTmp; + } + ippsGainControl_G723_16s_I(lSignalEnergy,pSrcDstSignal,&decoderObj->PstFltGain); + + LOCAL_ARRAY_FREE(Ipp16s, pTmpVec,G723_SBFR_LEN, decoderObj); + LOCAL_ARRAY_FREE(Ipp32s, pAutoCorr,2, decoderObj); + LOCAL_ARRAY_FREE(Ipp32s, pFltSignal,G723_LPC_ORDER+G723_SBFR_LEN, decoderObj); + LOCAL_ARRAY_FREE(Ipp16s, FltCoef,2*G723_LPC_ORDER, decoderObj); + + return; +} + +void LSPInterpolation(const Ipp16s *pSrcLSP, const Ipp16s *pSrcPrevLSP, Ipp16s *pDstLPC) +{ + + pDstLPC[0] = 4096; + ippsInterpolateC_NR_G729_16s_Sfs(pSrcLSP,4096,pSrcPrevLSP,12288,&pDstLPC[1],G723_LPC_ORDER,14); + ippsLSFToLPC_G723_16s(&pDstLPC[1], &pDstLPC[1]); + + pDstLPC[G723_LPC_ORDERP1] = 4096; + ippsInterpolateC_NR_G729_16s_Sfs(pSrcLSP,8192,pSrcPrevLSP,8192,&pDstLPC[1+G723_LPC_ORDERP1],G723_LPC_ORDER,14); + ippsLSFToLPC_G723_16s(&pDstLPC[1+G723_LPC_ORDERP1], &pDstLPC[1+G723_LPC_ORDERP1]); + + pDstLPC[2*G723_LPC_ORDERP1] = 4096; + ippsInterpolateC_NR_G729_16s_Sfs(pSrcLSP,12288,pSrcPrevLSP,4096,&pDstLPC[1+2*G723_LPC_ORDERP1],G723_LPC_ORDER,14); + ippsLSFToLPC_G723_16s(&pDstLPC[1+2*G723_LPC_ORDERP1], &pDstLPC[1+2*G723_LPC_ORDERP1]); + + pDstLPC[3*G723_LPC_ORDERP1] = 4096; + ippsCopy_16s(pSrcLSP,&pDstLPC[1+3*G723_LPC_ORDERP1],G723_LPC_ORDER); + ippsLSFToLPC_G723_16s(&pDstLPC[1+3*G723_LPC_ORDERP1], &pDstLPC[1+3*G723_LPC_ORDERP1]); + + return; +} + +/*static void GetAverScaleTable(Ipp16s *pTbl) +{ + Ipp32s i; + Ipp64f dTmp, dAlphaW=2.70375; + dTmp = 32768.f/((Ipp64f)G723_HALFFRM_LEN); + SATURATE_fs(dTmp,pTbl[0]); + for(i=1;i<4;i++) { + dTmp = 32768.f*dAlphaW*dAlphaW/((Ipp64f)i*(Ipp64f)G723_FRM_LEN); + SATURATE_fs(dTmp,pTbl[i]); + } + return; +}*/ + +static __ALIGN32 CONST Ipp16s AverScaleTbl_G723[4] = {273, 998, + 499, 333}; /*This table can be generateg using GetAverScaleTable function.*/ +static __ALIGN32 CONST Ipp32s LogEnerLevel[3] = {2048, 18432, 231233}; +static __ALIGN32 CONST Ipp16s FirstCode[3] = {0, 32, 96}; + +void QuantSIDGain_G723_16s(const Ipp16s *pSrc, const Ipp16s *pSrcSfs, Ipp32s len, Ipp32s *pIndx) +{ + Ipp16s sTmp, sNseg, sNsegP1; + Ipp16s j, m, k, expBase; + Ipp32s lTmp1, lTmp2, lTmp3; + Ipp16s sfs; + Ipp32s i; + + if(len == 0) { + /* Quantize energy */ + sTmp = (Ipp16s)((*pSrcSfs)<<1); + sTmp = (Ipp16s)(16 - sTmp); + lTmp1 = MulC_32s(AverScaleTbl_G723[0], (*pSrc)<>sTmp); + sTmp = (Ipp16s)(((AverScaleTbl_G723[len]*sTmp)+0x4000)>>15); + lTmp1 += sTmp; + } + sTmp = (Ipp16s)(15 - sfs); + if(sTmp < 0) lTmp1 >>= (-sTmp); + else lTmp1 <<= sTmp; + } + + *pIndx = 63; + if(lTmp1 < LogEnerLevel[2]) { + + /* Compute segment number */ + if(lTmp1 >= LogEnerLevel[1]) { + expBase = 4; sNseg = 2; + } else { + expBase = 3; + sNseg=(Ipp16s)((lTmp1 >= LogEnerLevel[0])?1:0); + } + + sNsegP1 = (Ipp16s)(sNseg + 1); + j = (Ipp16s)(1<>1); + + /* Binary search */ + for(i=0; i= lTmp2) j = (Ipp16s)(j + k); + else j = (Ipp16s)(j - k); + k >>= 1; + } + + sTmp = (Ipp16s)(FirstCode[sNseg] + (j< lTmp3) sTmp = (Ipp16s)((sNseg<<4) + j); + else sTmp = (Ipp16s)((sNseg<<4)+m); + } else { + m = (Ipp16s)(j - 1); + sTmp = (Ipp16s)(FirstCode[sNseg] + (m<>4); + if(sNseg == 3) sNseg = 2; + i = (Ipp16s)(pIndx - (sNseg<<4)); + sTmp = (Ipp16s)(sNseg + 1); + sTmp = (Ipp16s)(i< 0) { + sCorrSFS = Norm_32s_I(&lCorr); + sNormCorr = (Ipp16s)(lCorr>>17); /* Be sure sNormCorr < sNormEnergy */ + + ippsDotProd_16s32s_Sfs(pAlignTmp,pAlignTmp,G723_SBFR_LEN, &lEnergy,0); + + sEnergySFS = Norm_32s_I(&lEnergy); + sNormEnergy = (Ipp16s)(lEnergy>>16); + + /* compute sCurrGain = sNormCorr/sNormEnergy */ + sCurrGain =(Ipp16s)( (sNormEnergy > 0)? ((sNormCorr<<15)/sNormEnergy) : IPP_MAX_16S); + + i = (Ipp16s)(sCorrSFS - sEnergySFS + 5); /* Denormalization of division */ + + if(i < 0) sCurrGain = ShiftL_16s(sCurrGain, (Ipp16u)(-i)); + else + sCurrGain >>= i; + + sBestQntGain = 0; + sMinDist = (Ipp16s)Abs_16s(sCurrGain + GainDBLvls[0]); + for ( i = 1; i > 14); + } + ippsAdd_16s_I(sNormConv,pSrcDst,G723_SBFR_LEN); + + LOCAL_ARRAY_FREE(Ipp16s, sNormConv,G723_SBFR_LEN,encoderObj) ; + LOCAL_ARRAY_FREE(Ipp32s, lConv,G723_SBFR_LEN,encoderObj) ; + +} + +#define COMBTBL_LINE_LEN (G723_SBFR_LEN/GRIDSIZE) +static __ALIGN32 CONST Ipp32s CombTbl[N_PULSES*COMBTBL_LINE_LEN] = +{ + 118755, 98280, 80730, 65780, 53130, 42504, 33649, 26334, 20349, 15504, + 11628, 8568, 6188, 4368, 3003, 2002, 1287, 792, 462, 252, + 126, 56, 21, 6, 1, 0, 0, 0, 0, 0, + 23751, 20475, 17550, 14950, 12650, 10626, 8855, 7315, 5985, 4845, + 3876, 3060, 2380, 1820, 1365, 1001, 715, 495, 330, 210, + 126, 70, 35, 15, 5, 1, 0, 0, 0, 0, + 3654, 3276, 2925, 2600, 2300, 2024, 1771, 1540, 1330, 1140, + 969, 816, 680, 560, 455, 364, 286, 220, 165, 120, + 84, 56, 35, 20, 10, 4, 1, 0, 0, 0, + 406, 378, 351, 325, 300, 276, 253, 231, 210, 190, + 171, 153, 136, 120, 105, 91, 78, 66, 55, 45, + 36, 28, 21, 15, 10, 6, 3, 1, 0, 0, + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, + 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +}; + +static __ALIGN32 CONST Ipp32s MaxPosition[4] = {593775, 142506, 593775, 142506}; + +static __ALIGN32 CONST Ipp16s PitchContrb[2*170] = { + 60, 0, 0, 2489, 60, 0, 0, 5217, 1, 6171, 0, 3953, 0, 10364, 1, 9357, -1, 8843, 1, 9396, + 0, 5794, -1, 10816, 2, 11606, -2, 12072, 0, 8616, 1, 12170, 0, 14440, 0, 7787, -1, 13721, 0, 18205, + 0, 14471, 0, 15807, 1, 15275, 0, 13480, -1, 18375, -1, 0, 1, 11194, -1, 13010, 1, 18836, -2, 20354, + 1, 16233, -1, 0, 60, 0, 0, 12130, 0, 13385, 1, 17834, 1, 20875, 0, 21996, 1, 0, 1, 18277, + -1, 21321, 1, 13738, -1, 19094, -1, 20387, -1, 0, 0, 21008, 60, 0, -2, 22807, 0, 15900, 1, 0, + 0, 17989, -1, 22259, 1, 24395, 1, 23138, 0, 23948, 1, 22997, 2, 22604, -1, 25942, 0, 26246, 1, 25321, + 0, 26423, 0, 24061, 0, 27247, 60, 0, -1, 25572, 1, 23918, 1, 25930, 2, 26408, -1, 19049, 1, 27357, + -1, 24538, 60, 0, -1, 25093, 0, 28549, 1, 0, 0, 22793, -1, 25659, 0, 29377, 0, 30276, 0, 26198, + 1, 22521, -1, 28919, 0, 27384, 1, 30162, -1, 0, 0, 24237, -1, 30062, 0, 21763, 1, 30917, 60, 0, + 0, 31284, 0, 29433, 1, 26821, 1, 28655, 0, 31327, 2, 30799, 1, 31389, 0, 32322, 1, 31760, -2, 31830, + 0, 26936, -1, 31180, 1, 30875, 0, 27873, -1, 30429, 1, 31050, 0, 0, 0, 31912, 1, 31611, 0, 31565, + 0, 25557, 0, 31357, 60, 0, 1, 29536, 1, 28985, -1, 26984, -1, 31587, 2, 30836, -2, 31133, 0, 30243, + -1, 30742, -1, 32090, 60, 0, 2, 30902, 60, 0, 0, 30027, 0, 29042, 60, 0, 0, 31756, 0, 24553, + 0, 25636, -2, 30501, 60, 0, -1, 29617, 0, 30649, 60, 0, 0, 29274, 2, 30415, 0, 27480, 0, 31213, + -1, 28147, 0, 30600, 1, 31652, 2, 29068, 60, 0, 1, 28571, 1, 28730, 1, 31422, 0, 28257, 0, 24797, + 60, 0, 0, 0, 60, 0, 0, 22105, 0, 27852, 60, 0, 60, 0, -1, 24214, 0, 24642, 0, 23305, + 60, 0, 60, 0, 1, 22883, 0, 21601, 60, 0, 2, 25650, 60, 0, -2, 31253, -2, 25144, 0, 17998 +}; + +static __ALIGN32 CONST Ipp16s NPulse[4] = +{6,5, + 6,5}; + +void FixedCodebookVector_G723_16s( Ipp32s lDecPos, Ipp32s lAmplitude, Ipp32s mamp, Ipp32s lGrid, + Ipp32s lGain, Ipp32s lNSbfr, G723_Rate currRate, Ipp16s *pDst, Ipp32s *pLag, Ipp16s *pGain ) + +{ + Ipp32s i, j, lTmp, lOffset, lPos; + Ipp16s sCdbkGain, sCdbkSign, sCdbkShift, sCdbkPos; + + ippsZero_16s(pDst,G723_SBFR_LEN); + + switch(currRate) { + case G723_Rate63: { + if ( lDecPos < MaxPosition[lNSbfr] ){ + /* Decode the amplitudes and positions */ + + j = N_PULSES - NPulse[lNSbfr] ; + lTmp = lDecPos ; + for ( i = 0 ; i < G723_SBFR_LEN/GRIDSIZE ; i ++ ) { + lTmp -= CombTbl[j*COMBTBL_LINE_LEN + i]; + if ( lTmp < 0 ) { + lTmp += CombTbl[(j++)*COMBTBL_LINE_LEN+i]; + if ( (lAmplitude & (1 << (N_PULSES-j) )) != 0 ) + pDst[lGrid + GRIDSIZE*i] = GainDBLvls[mamp] ; + else + pDst[lGrid + GRIDSIZE*i] = (Ipp16s)(-GainDBLvls[mamp]) ; + + if ( j == N_PULSES ) break ; + } + } + } + break; + } + + case G723_Rate53: { + sCdbkGain = (Ipp16s)(-GainDBLvls[mamp]); + sCdbkShift = (Ipp16s)lGrid; + sCdbkSign = (Ipp16s)(lAmplitude<<1); + sCdbkPos = (Ipp16s) lDecPos; + + for(lOffset=0; lOffset<8; lOffset+=2) { + lPos = (sCdbkPos & 0x7) ; + lPos = (lPos<<3) + sCdbkShift + lOffset; + if (lPos < G723_SBFR_LEN) + pDst[lPos] = (Ipp16s)(sCdbkGain * ((sCdbkSign & 2 ) - 1)); + sCdbkPos >>= 3; + sCdbkSign >>= 1; + } + + *pLag = PitchContrb[lGain<<1]; + *pGain = PitchContrb[(lGain<<1) + 1]; + break; + } + } +} + +void ResidualInterpolation_G723_16s_I + (Ipp16s *pSrcDst, Ipp16s *pDst, Ipp32s lag, Ipp16s gain, Ipp16s *pSeed) +{ + Ipp32s i, lenBlk, len_res; + if ( lag ) {/* Voiced case*/ + for ( i = 0 ; i < lag ; i ++ ){ /* attenuation */ + pSrcDst[G723_MAX_PITCH+i-lag] = (Ipp16s)((pSrcDst[G723_MAX_PITCH+i-lag] * 0x6000)>>15); + } + lenBlk = G723_FRM_LEN/lag; + len_res = G723_FRM_LEN - (lenBlk*lag); + for(i=0; i 0) ippsCopy_16s(&pSrcDst[G723_MAX_PITCH-lag], &pSrcDst[G723_MAX_PITCH+i*lag], len_res); + ippsCopy_16s(&pSrcDst[G723_MAX_PITCH],pDst,G723_FRM_LEN); + } else {/* Unvoiced case*/ + for ( i = 0 ; i < G723_FRM_LEN ; i ++ ) + pDst[i] = (Ipp16s)((gain * Rand2_16s(pSeed))>>15); + /* reset memory */ + ippsZero_16s(pSrcDst,G723_FRM_LEN+G723_MAX_PITCH); + } + return; +} + +static __ALIGN32 CONST Ipp16s BetaTbl[2*170] = { + 1024, 1024, 1308, 1591, 1906, 1678, 2291, 1891, 2511, 2120, + 2736, 2399, 3298, 2966, 3489, 3049, 3531, 3185, 3844, 3317, + 4360, 3433, 4541, 3523, 4684, 3729, 4813, 3779, 5069, 3789, + 5528, 4262, 5577, 4450, 5713, 4469, 5923, 4713, 5958, 4944, + 5958, 4950, 6064, 4980, 6132, 5010, 6331, 5032, 6370, 5299, + 6527, 5389, 6533, 5389, 6575, 5389, 6633, 5646, 6671, 5701, + 6832, 5733, 6832, 5765, 6972, 5997, 6996, 5997, 7199, 6150, + 7205, 6211, 7414, 6336, 7529, 6360, 7543, 6415, 7543, 6415, + 7692, 6430, 7758, 6440, 7839, 6461, 7839, 6461, 7869, 6512, + 7992, 6601, 8000, 6787, 8016, 6872, 8055, 6931, 8079, 6972, + 8119, 6984, 8208, 7056, 8250, 7056, 8266, 7105, 8291, 7117, + 8300, 7123, 8325, 7136, 8402, 7161, 8445, 7167, 8605, 7180, + 8623, 7180, 8687, 7262, 8752, 7308, 8837, 7334, 8847, 7334, + 8973, 7387, 9002, 7407, 9012, 7434, 9184, 7441, 9593, 7441, + 9672, 7481, 9752, 7536, 9846, 7564, 9978, 7592, 10139, 7685, + 10202, 7714, 10317, 7758, 10476, 7772, 10598, 7794, 10598, 7802, + 10695, 7817, 11425, 7839, 11670, 7869, 14629, 7885, 15255, 7907, + 0, 7946, 0, 7992, 0, 8039, 0, 8063, 0, 8087, + 0, 8087, 0, 8167, 0, 8184, 0, 8200, 0, 8200, + 0, 8241, 0, 8266, 0, 8283, 0, 8308, 0, 8308, + 0, 8334, 0, 8376, 0, 8402, 0, 8463, 0, 8516, + 0, 8524, 0, 8533, 0, 8641, 0, 8669, 0, 8696, + 0, 8752, 0, 8761, 0, 8799, 0, 8828, 0, 8943, + 0, 9112, 0, 9122, 0, 9133, 0, 9153, 0, 9288, + 0, 9299, 0, 9373, 0, 9384, 0, 9384, 0, 9405, + 0, 9416, 0, 9471, 0, 9503, 0, 9559, 0, 9581, + 0, 9660, 0, 9660, 0, 9718, 0, 9799, 0, 9823, + 0, 9846, 0, 9846, 0, 9930, 0,10039, 0, 10164, + 0, 10227, 0, 10291, 0,10436, 0,10503, 0, 10516, + 0, 10530, 0, 10598, 0,10611, 0,10625, 0, 11040, + 0, 11070, 0, 11100, 0,11115, 0,11315, 0, 11331, + 0, 11804, 0, 12100, 0,12263, 0,12263, 0, 12300, + 0, 12337, 0, 12431, 0,12800, 0,12962, 0, 13065, + 0, 13496, 0, 13815, 0,14100, 0,14198, 0, 18409 +}; + +void ErrorUpdate_G723(Ipp32s *pError, Ipp16s openLoopLag, Ipp16s AdCbbkLag, Ipp16s AdCbbkGain, G723_Rate currRate) +{ + Ipp32s ilag, lag, e0, e1, li0=0,li1=0; + Ipp16s sBeta; + + lag = openLoopLag - 1 + AdCbbkLag; + + AdCbbkGain<<=1; + if ( currRate == G723_Rate63) { + if ( openLoopLag >= (G723_SBFR_LEN-2) ) AdCbbkGain++; + } else { + AdCbbkGain++; + } + sBeta = BetaTbl[AdCbbkGain]; + + if(lag > 30) { + ilag = (lag * 273)>>13; /* x 1/30 */ + if(30*(ilag+1) != lag) { + if(ilag == 1) { + if(pError[0] <= pError[1]){ + li0 = 1; + li1 = 1; + } + }else { + li0 = ilag-2; + li1 = ilag-1; + if(pError[li1] > pError[li0]){ + li0 = li1; + } + if(pError[li1] <= pError[ilag]){ + li1 = ilag; + } + } + } + else { /* lag = 60, 90, 120 */ + li0 = ilag-1; + li1 = ilag; + } + } + e0 = Add_32s(ShiftL_32s(MulC_32s(sBeta,pError[li0]),2),4); + e1 = Add_32s(ShiftL_32s(MulC_32s(sBeta,pError[li1]),2),4); + pError[4] = pError[2]; + pError[3] = pError[1]; + pError[2] = pError[0]; + pError[1] = e1; + pError[0] = e0; + return; +} + +static void CodewordImpConv_G723(Ipp16s *pSrc, Ipp16s *pDst, Ipp16s *pSrcSign, Ipp16s *pPos, Ipp16s* pDstSign, Ipp32s* ComposedIdx) +{ + Ipp32s i; + Ipp16s sImpPos0, sImpPos1, sImpPos2, sImpPos3; + Ipp16s sImpSign0, sImpSign1, sImpSign2, sImpSign3; + + sImpPos0 = pPos[0]; + sImpPos1 = pPos[1]; + sImpPos2 = pPos[2]; + sImpPos3 = pPos[3]; + + sImpSign0 = pSrcSign[0]; + sImpSign1 = pSrcSign[1]; + sImpSign2 = pSrcSign[2]; + sImpSign3 = pSrcSign[3]; + + /* find codebook index; 17-bit address */ + + *pDstSign = 0; + if(sImpSign0 > 0) *pDstSign=1; + if(sImpSign1 > 0) *pDstSign += 2; + if(sImpSign2 > 0) *pDstSign += 4; + if(sImpSign3 > 0) *pDstSign += 8; + + i = sImpPos0 >> 3; + i += sImpPos1 & 0xfff8; + i += (sImpPos2 & 0xfff8) << 3; + i += (sImpPos3 & 0xfff8) << 6; + + *ComposedIdx = i; + + /* Compute the filtered codeword */ + + ippsZero_16s(pDst,G723_SBFR_LEN); + + if (sImpPos0>sImpPos1) {i=(Ipp32s)sImpPos0; sImpPos0=sImpPos1; sImpPos1=(Ipp16s)i; i=(Ipp32s)sImpSign0; sImpSign0=sImpSign1; sImpSign1=(Ipp16s)i;} + if (sImpPos2>sImpPos3) {i=(Ipp32s)sImpPos2; sImpPos2=sImpPos3; sImpPos3=(Ipp16s)i; i=(Ipp32s)sImpSign2; sImpSign2=sImpSign3; sImpSign3=(Ipp16s)i;} + if (sImpPos0>sImpPos2) {i=(Ipp32s)sImpPos0; sImpPos0=sImpPos2; sImpPos2=(Ipp16s)i; i=(Ipp32s)sImpSign0; sImpSign0=sImpSign2; sImpSign2=(Ipp16s)i;} + if (sImpPos1>sImpPos3) {i=(Ipp32s)sImpPos1; sImpPos1=sImpPos3; sImpPos3=(Ipp16s)i; i=(Ipp32s)sImpSign1; sImpSign1=sImpSign3; sImpSign3=(Ipp16s)i;} + if (sImpPos1>sImpPos2) {i=(Ipp32s)sImpPos1; sImpPos1=sImpPos2; sImpPos2=(Ipp16s)i; i=(Ipp32s)sImpSign1; sImpSign1=sImpSign2; sImpSign2=(Ipp16s)i;} + + for (i=0; icurrRate) { + + case G723_Rate63: + { + ippsMPMLQFixedCodebookSearch_G723(Params->PitchLag[sNSbfr>>1], ImpResp, pSrcDst, pSrcDst, + &Params->sGrid[sNSbfr], &Params->sTrainDirac[sNSbfr], &Params->sAmpIndex[sNSbfr], &Params->sAmplitude[sNSbfr], &Params->sPosition[sNSbfr], sNSbfr); + break; + } + + case G723_Rate53: + { + Ipp16s sCurrGrid, sSign, sGainCoeff; + Ipp32s lCdbkIdx, lGainIdx; + + LOCAL_ALIGN_ARRAY(16, Ipp16s, pTargetImpRespCorr, G723_SBFR_LEN+4, encoderObj) ; + LOCAL_ALIGN_ARRAY(16, Ipp16s, pFixedVector, G723_SBFR_LEN+4, encoderObj) ; + LOCAL_ALIGN_ARRAY(16, Ipp16s, pFltFixedVector, G723_SBFR_LEN+4, encoderObj) ; + LOCAL_ALIGN_ARRAY(16, Ipp32s, pToeplizMatrix, G723_TOEPLIZ_MATRIX_SIZE, encoderObj) ; + LOCAL_ALIGN_ARRAY(16, Ipp16s, pAlignBuff, G723_SBFR_LEN, encoderObj) ; + LOCAL_ARRAY(Ipp16s, pDstFixedSign, 4, encoderObj) ; + LOCAL_ARRAY(Ipp16s, pDstFixedPosition,4, encoderObj) ; + + sPitchPeriod = (Ipp16s)(Params->PitchLag[sNSbfr>>1]-1+Params->AdCdbkLag[sNSbfr] + PitchContrb[Params->AdCdbkGain[sNSbfr]<<1]); + sGain = PitchContrb[(Params->AdCdbkGain[sNSbfr]<<1)+1]; + + /* Find correlations of h[] needed for the codebook search. */ + ippsRShiftC_16s_I(1,ImpResp,G723_SBFR_LEN); /* Q13 --> Q12*/ + if (sPitchPeriod < G723_SBFR_LEN-2) { + ippsHarmonicFilter_16s_I(sGain,sPitchPeriod,&ImpResp[sPitchPeriod],G723_SBFR_LEN-sPitchPeriod); + } + /* Compute correlation of target vector with impulse response. */ + + ippsCrossCorr_NormM_16s(ImpResp, pSrcDst, G723_SBFR_LEN, pTargetImpRespCorr); + /* Compute the covariance matrix of the impulse response. */ + ippsToeplizMatrix_G723_16s32s(ImpResp, pToeplizMatrix); + + /* Find innovative codebook (filtered codeword) */ + ippsACELPFixedCodebookSearch_G723_32s16s(pTargetImpRespCorr, pToeplizMatrix, pDstFixedSign, pDstFixedPosition, &sCurrGrid, pFixedVector, &encoderObj->sSearchTime); + + CodewordImpConv_G723(ImpResp, pFltFixedVector, pDstFixedSign, pDstFixedPosition, &sSign, &lCdbkIdx); + /* Compute innovation vector gain */ + FixedCodebookGain_G723_16s(pSrcDst,pFltFixedVector,&sGainCoeff,&lGainIdx,pAlignBuff); + + ippsMulC_16s_Sfs(pFixedVector,sGainCoeff,pSrcDst,G723_SBFR_LEN,0); + if(sPitchPeriod < G723_SBFR_LEN-2) + ippsHarmonicFilter_16s_I(sGain,sPitchPeriod,&pSrcDst[sPitchPeriod],G723_SBFR_LEN-sPitchPeriod); + + Params->sTrainDirac[sNSbfr] = 0; + Params->sAmpIndex[sNSbfr] = (Ipp16s)lGainIdx; + Params->sGrid[sNSbfr] = sCurrGrid; + Params->sAmplitude[sNSbfr] = sSign; + Params->sPosition[sNSbfr] = lCdbkIdx; + + LOCAL_ARRAY_FREE(Ipp16s, pDstFixedPosition,4, encoderObj) ; + LOCAL_ARRAY_FREE(Ipp16s, pDstFixedSign, 4, encoderObj) ; + LOCAL_ALIGN_ARRAY_FREE(16, Ipp16s, pAlignBuff, G723_SBFR_LEN, encoderObj) ; + LOCAL_ALIGN_ARRAY_FREE(16, Ipp32s, pToeplizMatrix, G723_TOEPLIZ_MATRIX_SIZE, encoderObj) ; + LOCAL_ALIGN_ARRAY_FREE(16, Ipp16s, pFltFixedVector, G723_SBFR_LEN+4, encoderObj) ; + LOCAL_ALIGN_ARRAY_FREE(16, Ipp16s, pFixedVector, G723_SBFR_LEN+4, encoderObj) ; + LOCAL_ALIGN_ARRAY_FREE(16, Ipp16s, pTargetImpRespCorr, G723_SBFR_LEN+4, encoderObj) ; + + break; + } + } +} + +void InterpolationIndex_G723_16s( Ipp16s *pDecodedExc, Ipp16s sPitchLag, Ipp16s *pGain, Ipp16s *pGainSFS, Ipp16s *pDstIdx) +{ + Ipp32s lSfs, lIdx, lTmp; + Ipp16s sTargetVecEnergy, sMaxCorr, sBestEnergy; + Ipp16s *pExc; + + /* Normalize the excitation */ + lSfs=3; + ippsAutoScale_16s_I( pDecodedExc, G723_MAX_PITCH+G723_FRM_LEN, &lSfs ); + *pGainSFS = (Ipp16s)lSfs; + + if ( sPitchLag > (Ipp16s) (G723_MAX_PITCH-3) ) + sPitchLag = (Ipp16s) (G723_MAX_PITCH-3); + + lIdx = sPitchLag; + pExc = &pDecodedExc[G723_MAX_PITCH+G723_FRM_LEN-2*G723_SBFR_LEN]; + ippsAutoCorrLagMax_Inv_16s(pExc,2*G723_SBFR_LEN,sPitchLag-3,sPitchLag+3,&lTmp,&lIdx); + + if(lTmp > 0 ) { + sMaxCorr = Cnvrt_NR_32s16s( lTmp ); + /* Compute target energy */ + ippsDotProd_16s32s_Sfs(pExc,pExc,2*G723_SBFR_LEN,&lTmp,0); + lTmp <<=1; + sTargetVecEnergy = Cnvrt_NR_32s16s( lTmp ); + *pGain = sTargetVecEnergy; + + /* Calculate the best energy */ + ippsDotProd_16s32s_Sfs(pExc-lIdx,pExc-lIdx,2*G723_SBFR_LEN,&lTmp,0); + lTmp <<=1; + + sBestEnergy = Cnvrt_NR_32s16s( lTmp ); + + lTmp = sBestEnergy * sTargetVecEnergy; + lTmp >>= 3; + + if ( lTmp < sMaxCorr * sMaxCorr ) *pDstIdx = (Ipp16s)lIdx; + else *pDstIdx = 0; + } else *pDstIdx = 0; + + return; +} + + +static __ALIGN32 CONST Ipp16s StratingPositionTbl[G723_SBFR_LEN/GRIDSIZE] = { + 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58}; + +#define MAX_CACHE_NUM 32 +static __ALIGN32 CONST Ipp16s SeedCacheTbl[MAX_CACHE_NUM] = { + 17547, -15555, 11855, 26561, -20077, -21051, 24151, 9545, + -15205, 24141, 29791, -5935, -605, 21717, -3993, 12889, + -9045, 4445, 21103, -32287, -7757, 5093, 6775, 22377, + -29509, -9107, -14209, 13041, 24003, -5387, -9081, -27527}; + +static __ALIGN32 CONST Ipp16s OlpCache[MAX_CACHE_NUM][2] = { + {129, 137}, {143, 135}, {137, 140}, {133, 136}, + {129, 124}, {139, 140}, {129, 133}, {123, 129}, + {139, 128}, {128, 125}, {140, 132}, {137, 133}, + {136, 127}, {131, 132}, {129, 138}, {133, 127}, + {142, 123}, {127, 141}, {137, 128}, {134, 133}, + {136, 135}, {137, 129}, {143, 125}, {138, 130}, + {139, 143}, {140, 139}, {127, 128}, {124, 138}, + {130, 126}, {136, 129}, {130, 138}, {136, 136}}; + +static __ALIGN32 CONST Ipp16s GainCache[MAX_CACHE_NUM][4] = { + {34, 31, 18, 35}, {38, 16, 47, 22}, { 9, 29, 48, 36}, {16, 44, 4, 15}, + {16, 27, 34, 34}, { 5, 26, 45, 8}, {14, 32, 31, 36}, {12, 18, 25, 8}, + { 7, 50, 46, 49}, {43, 26, 1, 21}, { 3, 37, 35, 27}, { 5, 7, 29, 4}, + { 6, 50, 4, 28}, { 3, 16, 16, 12}, {25, 44, 10, 8}, {43, 10, 17, 2}, + {14, 27, 8, 22}, {33, 46, 40, 30}, {31, 4, 6, 28}, {28, 29, 39, 3}, + {31, 32, 9, 31}, {34, 15, 22, 26}, {20, 17, 23, 38}, { 9, 12, 44, 6}, + { 6, 14, 5, 5}, { 7, 25, 13, 49}, {44, 31, 11, 38}, {36, 10, 33, 11}, + {40, 24, 48, 44}, { 1, 24, 12, 49}, {50, 48, 21, 28}, { 9, 23, 5, 19}}; + +static __ALIGN32 CONST Ipp16s SignCache[MAX_CACHE_NUM][24] = { + { 16384, 16384, -16384, -16384, 16384, 16384, 16384, -16384, + 16384, -16384, 16384, 16384, 16384, -16384, -16384, -16384, + 16384, 16384, 16384, -16384, -16384, -16384, 0, 0}, + {-16384, -16384, -16384, -16384, -16384, -16384, 16384, -16384, + 16384, -16384, -16384, -16384, -16384, -16384, -16384, 16384, + -16384, 16384, -16384, 16384, 16384, -16384, 0, 0}, + {-16384, 16384, -16384, -16384, -16384, -16384, -16384, 16384, + 16384, 16384, 16384, 16384, 16384, -16384, -16384, -16384, + 16384, 16384, 16384, 16384, 16384, 16384, 0, 0}, + {-16384, 16384, -16384, 16384, 16384, -16384, 16384, -16384, + 16384, 16384, 16384, -16384, -16384, 16384, 16384, 16384, + 16384, -16384, 16384, -16384, 16384, 16384, 0, 0}, + {-16384, -16384, -16384, 16384, -16384, 16384, 16384, 16384, + 16384, -16384, 16384, 16384, 16384, -16384, 16384, 16384, + 16384, 16384, 16384, 16384, -16384, 16384, 0, 0}, + {-16384, -16384, 16384, 16384, -16384, -16384, 16384, -16384, + -16384, 16384, 16384, -16384, -16384, -16384, -16384, -16384, + -16384, 16384, 16384, 16384, -16384, -16384, 0, 0}, + {-16384, 16384, 16384, -16384, -16384, 16384, -16384, 16384, + 16384, -16384, -16384, 16384, 16384, -16384, 16384, -16384, + 16384, -16384, -16384, -16384, -16384, 16384, 0, 0}, + {-16384, 16384, 16384, -16384, 16384, -16384, -16384, -16384, + 16384, 16384, 16384, -16384, -16384, 16384, 16384, 16384, + -16384, 16384, -16384, 16384, -16384, 16384, 0, 0}, + {-16384, -16384, 16384, 16384, 16384, 16384, -16384, 16384, + 16384, 16384, -16384, -16384, -16384, 16384, -16384, 16384, + 16384, 16384, -16384, 16384, 16384, -16384, 0, 0}, + { 16384, -16384, -16384, 16384, 16384, 16384, -16384, 16384, + -16384, 16384, -16384, 16384, -16384, -16384, -16384, 16384, + -16384, -16384, 16384, -16384, 16384, -16384, 0, 0}, + { 16384, 16384, -16384, 16384, -16384, 16384, -16384, -16384, + 16384, -16384, 16384, -16384, -16384, 16384, -16384, 16384, + -16384, 16384, 16384, -16384, -16384, 16384, 0, 0}, + { 16384, 16384, -16384, -16384, 16384, 16384, -16384, -16384, + -16384, 16384, -16384, 16384, -16384, 16384, 16384, 16384, + -16384, 16384, -16384, -16384, 16384, -16384, 0, 0}, + { 16384, -16384, -16384, -16384, 16384, 16384, 16384, 16384, + -16384, 16384, 16384, -16384, -16384, 16384, 16384, -16384, + -16384, 16384, -16384, 16384, -16384, -16384, 0, 0}, + { 16384, -16384, 16384, -16384, -16384, -16384, -16384, 16384, + -16384, 16384, 16384, 16384, -16384, -16384, -16384, -16384, + -16384, 16384, 16384, 16384, -16384, 16384, 0, 0}, + { 16384, 16384, 16384, 16384, -16384, -16384, -16384, -16384, + -16384, 16384, -16384, -16384, -16384, 16384, 16384, 16384, + -16384, 16384, 16384, 16384, -16384, -16384, 0, 0}, + { 16384, 16384, 16384, 16384, -16384, 16384, -16384, 16384, + -16384, -16384, -16384, 16384, -16384, 16384, 16384, 16384, + 16384, -16384, 16384, 16384, -16384, 16384, 0, 0}, + { 16384, -16384, 16384, -16384, -16384, -16384, -16384, 16384, + 16384, 16384, 16384, 16384, -16384, 16384, -16384, -16384, + -16384, -16384, 16384, 16384, 16384, 16384, 0, 0}, + {-16384, 16384, -16384, -16384, 16384, 16384, -16384, 16384, + 16384, -16384, -16384, -16384, 16384, -16384, -16384, 16384, + -16384, 16384, -16384, 16384, 16384, -16384, 0, 0}, + {-16384, -16384, 16384, -16384, 16384, -16384, 16384, -16384, + -16384, -16384, -16384, 16384, -16384, 16384, -16384, -16384, + -16384, 16384, -16384, 16384, 16384, -16384, 0, 0}, + {-16384, -16384, 16384, 16384, -16384, -16384, -16384, 16384, + -16384, 16384, -16384, -16384, 16384, 16384, 16384, 16384, + 16384, 16384, -16384, 16384, 16384, 16384, 0, 0}, + {-16384, 16384, -16384, 16384, 16384, 16384, 16384, -16384, + 16384, -16384, 16384, 16384, -16384, 16384, 16384, 16384, + -16384, -16384, -16384, -16384, 16384, 16384, 0, 0}, + {-16384, 16384, 16384, 16384, 16384, 16384, -16384, -16384, + -16384, -16384, 16384, -16384, 16384, -16384, -16384, -16384, + -16384, 16384, -16384, 16384, 16384, -16384, 0, 0}, + {-16384, -16384, -16384, 16384, 16384, 16384, 16384, 16384, + 16384, 16384, 16384, 16384, -16384, 16384, 16384, -16384, + -16384, -16384, -16384, 16384, -16384, -16384, 0, 0}, + {-16384, -16384, -16384, 16384, -16384, -16384, 16384, 16384, + 16384, 16384, 16384, -16384, 16384, 16384, 16384, 16384, + -16384, -16384, 16384, 16384, 16384, 16384, 0, 0}, + {-16384, 16384, 16384, 16384, -16384, -16384, 16384, 16384, + -16384, -16384, -16384, -16384, 16384, 16384, -16384, 16384, + -16384, -16384, -16384, 16384, -16384, 16384, 0, 0}, + { 16384, 16384, -16384, 16384, -16384, 16384, -16384, -16384, + -16384, 16384, 16384, 16384, 16384, -16384, -16384, 16384, + -16384, -16384, 16384, 16384, -16384, 16384, 0, 0}, + { 16384, -16384, 16384, 16384, 16384, 16384, 16384, 16384, + -16384, -16384, -16384, -16384, 16384, 16384, -16384, 16384, + 16384, -16384, -16384, 16384, 16384, -16384, 0, 0}, + { 16384, -16384, 16384, -16384, -16384, 16384, 16384, -16384, + -16384, -16384, -16384, 16384, 16384, 16384, 16384, 16384, + -16384, -16384, -16384, -16384, 16384, 16384, 0, 0}, + { 16384, 16384, -16384, -16384, -16384, -16384, -16384, 16384, + 16384, -16384, -16384, -16384, 16384, 16384, 16384, -16384, + 16384, 16384, -16384, -16384, -16384, 16384, 0, 0}, + { 16384, 16384, 16384, -16384, 16384, 16384, 16384, -16384, + 16384, 16384, 16384, 16384, 16384, -16384, -16384, -16384, + -16384, 16384, -16384, -16384, 16384, -16384, 0, 0}, + { 16384, -16384, -16384, -16384, -16384, 16384, 16384, -16384, + 16384, 16384, -16384, -16384, 16384, 16384, 16384, 16384, + 16384, -16384, 16384, 16384, -16384, -16384, 0, 0}, + { 16384, -16384, -16384, -16384, -16384, 16384, 16384, -16384, + -16384, -16384, 16384, 16384, 16384, 16384, 16384, 16384, + 16384, 16384, 16384, -16384, 16384, -16384, 0, 0} +}; + +static __ALIGN32 CONST Ipp16s PosCache[MAX_CACHE_NUM][24] = { + { 47, 51, 27, 41, 21, 9, 117, 83, + 69, 81, 109, 54, 52, 24, 20, 10, + 58, 72, 66, 68, 104, 86, 0, 0}, + { 46, 28, 50, 38, 22, 36, 114, 64, + 100, 112, 60, 24, 34, 6, 4, 28, + 42, 60, 118, 82, 114, 86, 0, 0}, + { 42, 52, 34, 36, 58, 14, 66, 88, + 68, 100, 74, 19, 35, 9, 53, 3, + 1, 84, 64, 88, 74, 78, 0, 0}, + { 41, 17, 1, 7, 13, 29, 86, 94, + 90, 112, 66, 11, 33, 23, 51, 37, + 5, 104, 100, 60, 62, 102, 0, 0}, + { 37, 43, 11, 19, 3, 5, 94, 72, + 108, 96, 98, 14, 50, 18, 32, 12, + 0, 117, 119, 69, 67, 81, 0, 0}, + { 8, 56, 4, 20, 22, 58, 113, 109, + 99, 95, 61, 30, 40, 12, 20, 14, + 18, 111, 109, 115, 93, 79, 0, 0}, + { 38, 28, 16, 50, 14, 58, 87, 103, + 83, 77, 119, 47, 53, 5, 21, 51, + 31, 117, 113, 71, 83, 99, 0, 0}, + { 17, 37, 15, 31, 11, 33, 75, 113, + 73, 63, 97, 33, 7, 39, 29, 23, + 43, 89, 95, 81, 71, 75, 0, 0}, + { 55, 21, 5, 29, 33, 17, 113, 67, + 115, 103, 97, 6, 44, 30, 26, 18, + 46, 90, 62, 100, 78, 86, 0, 0}, + { 10, 26, 38, 44, 34, 6, 104, 112, + 76, 78, 82, 24, 56, 50, 30, 14, + 28, 104, 64, 78, 112, 98, 0, 0}, + { 30, 24, 36, 12, 10, 0, 118, 90, + 94, 70, 84, 19, 37, 45, 53, 25, + 7, 104, 84, 110, 112, 106, 0, 0}, + { 1, 31, 25, 15, 47, 39, 88, 116, + 62, 94, 72, 15, 23, 1, 33, 49, + 37, 106, 84, 114, 62, 102, 0, 0}, + { 37, 47, 9, 13, 7, 45, 112, 62, + 86, 96, 104, 30, 34, 2, 54, 24, + 14, 111, 75, 107, 87, 119, 0, 0}, + { 54, 0, 38, 4, 2, 32, 93, 75, + 119, 65, 117, 6, 24, 58, 38, 30, + 22, 103, 105, 87, 115, 95, 0, 0}, + { 18, 36, 38, 32, 26, 4, 101, 109, + 119, 79, 63, 51, 47, 19, 41, 27, + 29, 113, 95, 97, 119, 105, 0, 0}, + { 57, 59, 31, 17, 13, 47, 67, 109, + 63, 103, 95, 13, 17, 23, 3, 15, + 41, 99, 71, 111, 89, 81, 0, 0}, + { 43, 3, 23, 25, 29, 37, 91, 61, + 85, 79, 69, 28, 18, 46, 14, 34, + 4, 118, 96, 88, 90, 116, 0, 0}, + { 16, 34, 6, 54, 30, 36, 76, 112, + 90, 106, 86, 38, 2, 50, 40, 8, + 48, 102, 108, 84, 70, 66, 0, 0}, + { 0, 8, 20, 58, 14, 46, 92, 102, + 116, 104, 78, 29, 21, 37, 55, 5, + 47, 76, 86, 116, 80, 92, 0, 0}, + { 3, 57, 31, 35, 13, 7, 70, 90, + 72, 84, 60, 29, 51, 45, 57, 21, + 5, 60, 110, 68, 96, 118, 0, 0}, + { 17, 5, 45, 15, 55, 43, 110, 62, + 106, 114, 94, 58, 0, 50, 8, 46, + 14, 115, 73, 101, 91, 99, 0, 0}, + { 20, 12, 54, 52, 16, 50, 115, 109, + 71, 99, 119, 54, 50, 12, 40, 4, + 10, 105, 81, 71, 65, 69, 0, 0}, + { 38, 54, 42, 24, 22, 30, 95, 69, + 101, 91, 75, 7, 21, 43, 55, 11, + 51, 61, 117, 79, 71, 113, 0, 0}, + { 19, 29, 57, 13, 49, 21, 99, 117, + 93, 119, 75, 3, 9, 15, 55, 17, + 25, 119, 87, 97, 89, 95, 0, 0}, + { 15, 53, 21, 35, 7, 59, 111, 67, + 95, 117, 77, 0, 34, 16, 40, 8, + 44, 98, 114, 86, 84, 64, 0, 0}, + { 4, 52, 14, 32, 10, 24, 88, 64, + 118, 92, 76, 0, 48, 4, 34, 14, + 54, 110, 78, 100, 66, 96, 0, 0}, + { 10, 2, 44, 50, 56, 52, 106, 66, + 94, 114, 118, 49, 45, 37, 5, 47, + 23, 60, 70, 72, 84, 88, 0, 0}, + { 45, 35, 21, 9, 15, 37, 92, 74, + 64, 86, 84, 55, 5, 45, 53, 3, + 57, 86, 116, 118, 62, 80, 0, 0}, + { 39, 31, 7, 29, 15, 1, 90, 74, + 106, 70, 68, 36, 4, 54, 52, 26, + 46, 71, 109, 103, 77, 99, 0, 0}, + { 28, 36, 54, 2, 12, 10, 119, 97, + 87, 89, 105, 54, 56, 26, 24, 40, + 32, 119, 99, 65, 79, 103, 0, 0}, + { 40, 26, 28, 56, 2, 14, 69, 97, + 83, 113, 71, 35, 37, 21, 29, 7, + 53, 79, 63, 71, 67, 97, 0, 0}, + { 23, 13, 9, 21, 15, 5, 113, 79, + 103, 105, 91, 5, 39, 19, 9, 29, + 43, 89, 85, 95, 73, 69, 0, 0} +}; + +void ComfortNoiseExcitation_G723_16s (Ipp16s gain, Ipp16s *pPrevExc, Ipp16s *pExc, + Ipp16s *pSeed, Ipp16s *pOlp, Ipp16s *pLags, + Ipp16s *pGains, G723_Rate currRate, Ipp8s *buff, Ipp16s *CasheCounter) + +{ + Ipp32s i, lNSbfr, lNBlock; + Ipp16s j, sTmp, sTmp1; + Ipp16s *pPosition, *pSign; + Ipp16s *ppPosition; + Ipp16s *pCurrExcitation; + Ipp16s sfs, sX1, sX2, sDiscr, sB, sAbsX2, sAbsX1; + Ipp32s lTmp, lC, lExcEnergy; + Ipp16s *pTmpPos; + Ipp16s *pOff; + Ipp16s *pTmpExcitation; + + pPosition = (Ipp16s *)buff; + pSign = pPosition + 2*NUM_PULSE_IN_BLOCK; + pTmpPos = pSign + 2*NUM_PULSE_IN_BLOCK; + pOff = pTmpPos + G723_SBFR_LEN/GRIDSIZE; + pTmpExcitation = pOff + 4; + + /* generate LTP codes */ + if(*CasheCounter < -1) { + Ipp32s curr = *CasheCounter; + pOlp[0] = OlpCache[curr][0]; + pOlp[1] = OlpCache[curr][1]; + + pGains[0] = GainCache[curr][0]; + pGains[1] = GainCache[curr][1]; + pGains[2] = GainCache[curr][2]; + pGains[3] = GainCache[curr][3]; + + *pSeed = SeedCacheTbl[curr]; + + ippsCopy_16s(SignCache[curr],pSign,2*NUM_PULSE_IN_BLOCK); + ippsCopy_16s(PosCache[curr],pPosition,2*NUM_PULSE_IN_BLOCK); + + *CasheCounter += 1; + } else { + pOlp[0] = (Ipp16s)(NormRand_16s(21, pSeed) + 123); + pOlp[1] = (Ipp16s)(NormRand_16s(19, pSeed) + 123); /* The value 21 has been modified to 19 to correspond with ver. G723.1 April 2006 */ + for(lNSbfr=0; lNSbfr<4; lNSbfr++) { /* in [1, MAX_GAIN] */ + pGains[lNSbfr] = (Ipp16s)(NormRand_16s(MAX_GAIN, pSeed) + 1); + } + + /* Generate signs and grids */ + for(lNBlock=0; lNBlock<4; lNBlock += 2) { + sTmp = NormRand_16s((1 << (NUM_PULSE_IN_BLOCK+2)), pSeed); + pOff[lNBlock] = (Ipp16s)(sTmp & 0x1); + sTmp >>= 1; + pOff[lNBlock+1] = (Ipp16s)(G723_SBFR_LEN + (sTmp & 0x1)); + for(i=0; i>1)] = (Ipp16s)(((sTmp & 0x2) - 1)<<14); + sTmp >>= 1; + } + } + + /* Generate positions */ + ppPosition = pPosition; + for(lNSbfr=0; lNSbfr<4; lNSbfr++) { + ippsCopy_16s(StratingPositionTbl, pTmpPos, G723_SBFR_LEN/GRIDSIZE); + + sTmp=(G723_SBFR_LEN/GRIDSIZE); for(i=0; i sTmp1) sTmp1 = (Ipp16s)(-sTmp); + if(sTmp1 == 0) sfs = 0; + else { + sfs = (Ipp16s)(4 - Exp_16s(sTmp1)); /* 4 bits of margin */ + if(sfs < -2) sfs = -2; + } + if(sfs<0) + ippsLShiftC_16s(pCurrExcitation,-sfs,pTmpExcitation,2*G723_SBFR_LEN); + else + ippsRShiftC_16s(pCurrExcitation,sfs,pTmpExcitation,2*G723_SBFR_LEN); + lTmp = pTmpExcitation[pPosition[0+NUM_PULSE_IN_BLOCK*lNBlock]] * pSign[0+NUM_PULSE_IN_BLOCK*lNBlock]; + for(i=1; i>14); + sB = (Ipp16s)(((sTmp*INV_NUM_PULSE_IN_BLOCK)+0x4000)>>15); + /* excitation energy */ + ippsDotProd_16s32s_Sfs(pTmpExcitation,pTmpExcitation,2*G723_SBFR_LEN,&lExcEnergy,-1); + + /* compute 2*G723_SBFR_LEN x gain**2 x 2**(-2sh1+1) */ + /* gain input = 2**5 gain */ + sTmp = (Ipp16s)((gain * G723_SBFR_LEN)>>5); + lTmp = 2 * sTmp * gain; + sTmp = (Ipp16s)((sfs<<1)+4); + lTmp = lTmp>>sTmp; + lTmp = lExcEnergy - lTmp; + lC = MulC_32s(INV_NUM_PULSE_IN_BLOCK, lTmp); /* * 1/NbPuls */ + + /* Solve EQ(X) = X**2 + 2 sB X + c */ + lTmp = 2* sB * sB - lC; + if(lTmp <= 0) { + sX1 = (Ipp16s)(-sB); + } + else { + sDiscr = (Ipp16s)ownSqrt_32s(lTmp>>1); + sX1 = (Ipp16s)(sDiscr - sB); + sX2 = (Ipp16s)(sDiscr + sB); + sAbsX2 = (Ipp16s)Abs_16s(sX2); + sAbsX1 = (Ipp16s)Abs_16s(sX1); + if (sAbsX2 < sAbsX1) sX1 = (Ipp16s)(-sX2); + } + + /* Update Excitation */ + if(++sfs < 0) sTmp = (Ipp16s)(sX1>>(-sfs)); + else sTmp = (Ipp16s)(sX1< G723_MAX_GAIN) + sTmp = G723_MAX_GAIN; + + if(sTmp < -G723_MAX_GAIN) + sTmp = -G723_MAX_GAIN; + + for(i=0; i>15)); + } + + /* update PrevExcitation */ + ippsCopy_16s(&pPrevExc[2*G723_SBFR_LEN],pPrevExc,G723_MAX_PITCH-2*G723_SBFR_LEN); + ippsCopy_16s(pCurrExcitation,&pPrevExc[G723_MAX_PITCH-2*G723_SBFR_LEN],2*G723_SBFR_LEN); + + pCurrExcitation += 2*G723_SBFR_LEN; + lNSbfr += 2; + } +} + +__ALIGN32 CONST IppSpchBitRate SA_Rate[2] = {IPP_SPCHBR_6300, IPP_SPCHBR_5300}; + +__ALIGN32 CONST Ipp16s LPCDCTbl[G723_LPC_ORDER] = { + 3131,4721,7690,10806,13872,16495,19752,22260,25484,27718}; + + +__ALIGN32 CONST Ipp16s PerceptualFltCoeffTbl[2*G723_LPC_ORDER] = { + 29491,26542,23888,21499,19349,17414,15673,14106,12695,11425,/* Zero part */ + 16384, 8192, 4096, 2048, 1024, 512, 256, 128, 64, 32,/* Pole part */ +}; + +#if defined( _WIN32_WCE) +#pragma warning( disable : 4305 ) +#endif +__ALIGN32 CONST Ipp16s GainDBLvls[N_GAINS] = { + 0xFFFF, 0xFFFE, 0xFFFD, 0xFFFC, 0xFFFA, 0xFFF7, 0xFFF3, 0xFFEE, + 0xFFE6, 0xFFDA, 0xFFC9, 0xFFB0, 0xFF8D, 0xFF5A, 0xFF10, 0xFEA4, + 0xFE0A, 0xFD2A, 0xFBE6, 0xFA13, 0xF76F, 0xF39E, 0xEE1A, 0xE621 +}; + + + diff --git a/owng723.h b/owng723.h new file mode 100644 index 0000000..39fc07b --- /dev/null +++ b/owng723.h @@ -0,0 +1,195 @@ +/*///////////////////////////////////////////////////////////////////////////// +// +// 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-2007 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 ippEULA.rtf or ippEULA.txt 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: main own header file. +// +*/ + +#ifndef __OWNG723_H__ +#define __OWNG723_H__ + +#if defined( _WIN32_WCE) +#pragma warning( disable : 4505 ) +#endif + +#include "g723ipp.h" +#include "g723api.h" +#include "scratchmem.h" + +/* G.723.1 coder global constants */ +#define G723_FRM_LEN 240 +#define G723_SBFR_LEN (G723_FRM_LEN/4) +#define G723_HALFFRM_LEN (G723_FRM_LEN/2) +#define G723_LPC_ORDER 10 /*order of LPC filters */ +#define G723_LPC_ORDERP1 11 /*order of LPC filters plus 1*/ +#define SmoothCoeff (Ipp32s) 0xffffc000 /* -0.25 */ +#define G723_MIN_PITCH 18 +#define AdCdbkSizeHighRate 85 +#define G723_MAX_PITCH ((G723_MIN_PITCH)+127) +#define GRIDSIZE 2 +#define AdCdbkSizeLowRate 170 +#define N_PULSES 6 +#define G723_TOEPLIZ_MATRIX_SIZE 416 +#define N_GAINS 24 +#define N_AUTOCORRS_BLOCKS 3 /* N frames for AutoCorrs averaging */ +#define N_GAIN_AVER_FRMS 3 /* N frames for gain averaging */ +#define NUM_PULSE_IN_BLOCK 11 /* N pulses per block */ +#define INV_NUM_PULSE_IN_BLOCK 2979 /* 1/NUM_PULSE_IN_BLOCK */ +#define MAX_GAIN 50 /* Maximum gain in CNG excitation */ +#define AUOTOCORRS_BUFF_SIZE ((N_AUTOCORRS_BLOCKS+1)*(G723_LPC_ORDER+1)) /* size of AutoCorrs array */ +#define G723_MAX_GAIN 10000 /* Maximum gain for fixed CNG excitation */ + +typedef enum { + G723_Rate63 = 0, + G723_Rate53 +}G723_Rate; + +typedef enum { + G723_UntransmittedFrm = 0, + G723_ActiveFrm, + G723_SIDFrm +}G723_FrameType; + +typedef struct { + Ipp16s isBadFrame; + G723_FrameType FrameType; + G723_Rate currRate; + Ipp32s lLSPIdx ; + Ipp16s PitchLag[2] ; + Ipp16s AdCdbkLag[4]; + Ipp16s AdCdbkGain[4]; + Ipp16s sAmpIndex[4]; + Ipp16s sGrid[4]; + Ipp16s sTrainDirac[4]; + Ipp16s sAmplitude[4]; + Ipp32s sPosition[4]; +} ParamStream_G723; + +typedef struct { + Ipp16s sDelay; + Ipp16s sGain; + Ipp16s sScalingGain; +} GainInfo_G723; + +void DecoderCNG_G723(G723Decoder_Obj* decoderObj, ParamStream_G723 *CurrentParams, Ipp16s *pExcitation, Ipp16s *pDstLPC); + +void FixedCodebookSearch_G723_16s(G723Encoder_Obj *encoderObj, ParamStream_G723 *Params, Ipp16s *pSrcDst, Ipp16s *ImpResp, Ipp16s Sfc); +void InterpolationIndex_G723_16s( Ipp16s *pDecodedExc, Ipp16s sPitchLag, Ipp16s *pGain, Ipp16s *pGainSFS, Ipp16s *pDstIdx); +void ErrorUpdate_G723(Ipp32s *pError, Ipp16s openLoopLag, Ipp16s AdCbbkLag, Ipp16s AdCbbkGain, G723_Rate currRate); +void PostFilter(G723Decoder_Obj* decoderObj, Ipp16s *pSrcDstSignal, Ipp16s *pSrcLPC ); +void LSPInterpolation(const Ipp16s *pSrcLSP, const Ipp16s *pSrcPrevLSP, Ipp16s *pDstLPC); +void SetParam2Bitstream(G723Encoder_Obj* encoderObj, ParamStream_G723 *Params, Ipp8s *pDstBitStream); +void GetParamFromBitstream( const Ipp8s *pSrcBitStream, ParamStream_G723 *Params); +void UpdateSineDetector(Ipp16s *SineWaveDetector, Ipp16s *isNotSineWave); +extern Ipp16s LPCDCTbl[G723_LPC_ORDER] ; +extern Ipp16s PerceptualFltCoeffTbl[2*G723_LPC_ORDER] ; +extern Ipp16s GainDBLvls[N_GAINS] ; +extern IppSpchBitRate SA_Rate[2]; + +void EncoderCNG_G723(G723Encoder_Obj* encoderObj, ParamStream_G723 *Params, Ipp16s *pExcitation, Ipp16s *pDstLPC); +void UpdateAutoCorrs_G723(G723Encoder_Obj* encoderObj, const Ipp16s *pSrcAutoCorrs, const Ipp16s *pSrcAutoCorrsSFS); +void DecodeSIDGain_G723_16s (Ipp32s pIndx, Ipp16s *pGain); + +#define ComfortNoiseExcitation_G723_16s_Buff_Size (2*NUM_PULSE_IN_BLOCK+2*NUM_PULSE_IN_BLOCK+G723_SBFR_LEN/GRIDSIZE+4+2*G723_SBFR_LEN)*sizeof(Ipp16s) + +void ComfortNoiseExcitation_G723_16s (Ipp16s gain, Ipp16s *pPrevExc, Ipp16s *pExc, + Ipp16s *pSeed, Ipp16s *pOlp, Ipp16s *pLags, + Ipp16s *pGains, G723_Rate currRate, Ipp8s *buff, Ipp16s *CasheCounter); +void FixedCodebookGain_G723_16s(const Ipp16s *pSrc1, const Ipp16s *pSrc2, + Ipp16s *pGainCoeff, Ipp32s *pGainIdx, Ipp16s *y); +void ExcitationResidual_G723_16s(const Ipp16s *pSrc1, const Ipp16s *pSrc2, Ipp16s *pSrcDst,G723Encoder_Obj *encoderObj); + +void FixedCodebookVector_G723_16s( Ipp32s lDecPos, Ipp32s lAmplitude, Ipp32s mamp, Ipp32s lGrid, + Ipp32s lGain, Ipp32s lNSbfr, G723_Rate currRate, Ipp16s *pDst, Ipp32s *pLag, Ipp16s *pGain ); + +void QuantSIDGain_G723_16s(const Ipp16s *pSrc, const Ipp16s *pSrcSfs, Ipp32s len, Ipp32s *pIndx); + +void ResidualInterpolation_G723_16s_I + (Ipp16s *pSrcDst, Ipp16s *pDst, Ipp32s lag, Ipp16s gain, Ipp16s *pSeed); + +struct _G723Encoder_Obj{ + G723_Obj_t objPrm; /* must be on top */ + + Ipp16s ZeroSignal[G723_SBFR_LEN]; + Ipp16s UnitImpulseSignal[G723_SBFR_LEN]; + Ipp16s PrevWeightedSignal[G723_MAX_PITCH+3]; /* All pitch operation buffers */ + Ipp16s FltSignal[G723_MAX_PITCH+G723_SBFR_LEN+3]; /* shift 3 - aligning */ + Ipp16s PrevExcitation[G723_MAX_PITCH+3]; + Ipp16s SignalDelayLine[G723_HALFFRM_LEN];/* Required memory for the delay */ + Ipp16s WeightedFltMem[2*G723_LPC_ORDER];/* Used delay lines */ + Ipp16s RingWeightedFltMem[2*G723_LPC_ORDER];/* formant perceptual weighting filter delay line */ + Ipp16s RingSynthFltMem[G723_LPC_ORDER]; /* synthesis filter delay line */ + Ipp16s PrevOpenLoopLags[2]; + Ipp16s PrevLPC[G723_LPC_ORDER];/* Lsp previous vector */ + Ipp16s AverEnerCounter; + Ipp16s PrevQGain; + Ipp16s SIDLSP[G723_LPC_ORDER]; + Ipp16s CNGSeed; + Ipp16s CurrGain; + Ipp16s LPCSID[G723_LPC_ORDER]; + Ipp16s ReflectionCoeffSFS; + Ipp16s sSearchTime; /* for ippsFixedCodebookSearch_G723_16s function*/ + Ipp16s prevSidLpc[G723_LPC_ORDERP1]; + Ipp16s SineWaveDetector;/* Sine wave detector */ + Ipp16s sSidGain; + Ipp16s ReflectionCoeff[G723_LPC_ORDER+1]; + G723_FrameType PastFrameType; + Ipp16s AutoCorrs[AUOTOCORRS_BUFF_SIZE]; + Ipp16s AutoCorrsSFS[N_AUTOCORRS_BLOCKS+1]; + Ipp16s GainAverEnergies[N_GAIN_AVER_FRMS]; + Ipp32s ExcitationError[5];/* Taming procedure errors */ + Ipp32s HPFltMem[2];/* High pass variables */ + Ipp8s *vadMem; /* VAD memory */ + Ipp32s AdaptEnableFlag; + Ipp16s CasheCounter; + ScratchMem_Obj Mem; +}; + +struct _G723Decoder_Obj{ + G723_Obj_t objPrm; /* must be on top */ + + Ipp16s PrevExcitation[G723_MAX_PITCH+3]; /* 3 - shift for aligning */ + Ipp16s PostFilterMem[2*G723_LPC_ORDER]; /* Fir+Iir delays */ + Ipp16s PrevLPC[G723_LPC_ORDER];/* Lsp previous vector */ + Ipp16s ErasedFramesCounter; + Ipp16s InterpolatedGain; + Ipp16s SyntFltIIRMem[G723_LPC_ORDER];/* Used delay lines */ + Ipp16s InterpolationIdx; + Ipp16s ResIntSeed; + Ipp16s SIDLSP[G723_LPC_ORDER]; + Ipp16s ReflectionCoeff; + Ipp16s PstFltGain; + Ipp16s CurrGain; + G723_FrameType PastFrameType; + Ipp16s sSidGain; + Ipp16s CNGSeed; + Ipp16s CasheCounter; + ScratchMem_Obj Mem; +}; + +#define G723_CODECFUN(type,name,arg) extern type name arg + +#include "aux_fnxs.h" + +#endif /* __OWNG723_H__ */ diff --git a/owng729fp.c b/owng729fp.c new file mode 100644 index 0000000..537ca94 --- /dev/null +++ b/owng729fp.c @@ -0,0 +1,2247 @@ +/*///////////////////////////////////////////////////////////////////////////// +// +// 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) 2004-2008 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 ippEULA.rtf or ippEULA.txt 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.729 floating-point speech codec: internal functions. +// +*/ + +#include +#include "vadg729fp.h" +#include "owng729fp.h" + +#define sqr(a) ((a)*(a)) + +/* Hamming_cos window for LPC analysis. */ + +static __ALIGN32 CONST Ipp32f HammingWindow[WINDOW_LEN] = { /* hamming-cosine window */ +0.08000000f, 0.08005703f, 0.08022812f, 0.08051321f, +0.08091225f, 0.08142514f, 0.08205172f, 0.08279188f, +0.08364540f, 0.08461212f, 0.08569173f, 0.08688401f, +0.08818865f, 0.08960532f, 0.09113365f, 0.09277334f, +0.09452391f, 0.09638494f, 0.09835598f, 0.10043652f, +0.10262608f, 0.10492408f, 0.10732999f, 0.10984316f, +0.11246302f, 0.11518890f, 0.11802010f, 0.12095598f, +0.12399574f, 0.12713866f, 0.13038395f, 0.13373083f, +0.13717847f, 0.14072597f, 0.14437246f, 0.14811710f, +0.15195890f, 0.15589692f, 0.15993017f, 0.16405767f, +0.16827843f, 0.17259133f, 0.17699537f, 0.18148938f, +0.18607232f, 0.19074300f, 0.19550033f, 0.20034306f, +0.20527001f, 0.21027996f, 0.21537170f, 0.22054392f, +0.22579536f, 0.23112471f, 0.23653066f, 0.24201185f, +0.24756692f, 0.25319457f, 0.25889328f, 0.26466170f, +0.27049842f, 0.27640197f, 0.28237087f, 0.28840363f, +0.29449883f, 0.30065489f, 0.30687031f, 0.31314352f, +0.31947297f, 0.32585713f, 0.33229437f, 0.33878314f, +0.34532180f, 0.35190874f, 0.35854232f, 0.36522087f, +0.37194279f, 0.37870640f, 0.38550997f, 0.39235184f, +0.39923036f, 0.40614375f, 0.41309035f, 0.42006844f, +0.42707625f, 0.43411207f, 0.44117412f, 0.44826069f, +0.45537004f, 0.46250033f, 0.46964988f, 0.47681686f, +0.48399949f, 0.49119604f, 0.49840465f, 0.50562358f, +0.51285106f, 0.52008528f, 0.52732444f, 0.53456670f, +0.54181033f, 0.54905349f, 0.55629444f, 0.56353134f, +0.57076240f, 0.57798582f, 0.58519983f, 0.59240264f, +0.59959245f, 0.60676748f, 0.61392599f, 0.62106609f, +0.62818617f, 0.63528436f, 0.64235890f, 0.64940804f, +0.65643007f, 0.66342324f, 0.67038584f, 0.67731601f, +0.68421221f, 0.69107264f, 0.69789559f, 0.70467937f, +0.71142232f, 0.71812278f, 0.72477907f, 0.73138952f, +0.73795253f, 0.74446648f, 0.75092971f, 0.75734061f, +0.76369762f, 0.76999915f, 0.77624369f, 0.78242958f, +0.78855544f, 0.79461962f, 0.80062068f, 0.80655706f, +0.81242740f, 0.81823015f, 0.82396388f, 0.82962728f, +0.83521879f, 0.84073710f, 0.84618086f, 0.85154873f, +0.85683930f, 0.86205131f, 0.86718345f, 0.87223446f, +0.87720311f, 0.88208807f, 0.88688827f, 0.89160240f, +0.89622939f, 0.90076804f, 0.90521723f, 0.90957582f, +0.91384280f, 0.91801709f, 0.92209762f, 0.92608339f, +0.92997342f, 0.93376678f, 0.93746245f, 0.94105959f, +0.94455731f, 0.94795465f, 0.95125085f, 0.95444512f, +0.95753652f, 0.96052444f, 0.96340811f, 0.96618676f, +0.96885973f, 0.97142631f, 0.97388595f, 0.97623801f, +0.97848189f, 0.98061699f, 0.98264289f, 0.98455900f, +0.98636484f, 0.98806006f, 0.98964417f, 0.99111670f, +0.99247742f, 0.99372596f, 0.99486196f, 0.99588519f, +0.99679530f, 0.99759221f, 0.99827564f, 0.99884540f, +0.99930143f, 0.99964350f, 0.99987161f, 0.99998569f, +1.00000000f, 0.99921930f, 0.99687845f, 0.99298108f, +0.98753333f, 0.98054361f, 0.97202289f, 0.96198452f, +0.95044410f, 0.93741965f, 0.92293155f, 0.90700239f, +0.88965708f, 0.87092263f, 0.85082841f, 0.82940567f, +0.80668795f, 0.78271067f, 0.75751126f, 0.73112911f, +0.70360541f, 0.67498308f, 0.64530689f, 0.61462307f, +0.58297962f, 0.55042595f, 0.51701277f, 0.48279238f, +0.44781810f, 0.41214463f, 0.37582767f, 0.33892387f, +0.30149087f, 0.26358715f, 0.22527184f, 0.18660481f, +0.14764643f, 0.10845750f, 0.06909923f, 0.02963307f}; + +void ownAutoCorr_G729_32f(Ipp32f *pSrc, Ipp32s len, Ipp32f *pDst, Ipp32f *pExtBuff) +{ + ippsMul_32f(pSrc, HammingWindow, pExtBuff, WINDOW_LEN); + + ippsAutoCorr_32f(pExtBuff, WINDOW_LEN, pDst, len+1); + + if (pDst[0]<(Ipp32f)1.0) pDst[0]=(Ipp32f)1.0; + + return; +} + +void ownACOS_G729_32f(Ipp32f *pSrc, Ipp32f *pDst, Ipp32s len) +{ + + Ipp32s i; + + for (i=0; i 84 do not search fractional pitch */ + + if( (nSbfr == 0) && (pitchPeriod > 84) ) + return pitchPeriod; + + ippsCopy_32f(pSrcExc, pTmpExcitation, SUBFR_LEN); + + /* Fraction -1/3 */ + + delayLine[1] = -1; + + ippsDecodeAdaptiveVector_G729_32f_I(delayLine, pSrcExc); + ippsDotProd_32f64f( pCorr, pSrcExc, SUBFR_LEN, &corr); + if(corr > max){ + max = corr; + *fracPartPitchDelay = -1; + ippsCopy_32f(pSrcExc, pTmpExcitation, SUBFR_LEN); + } + + /* Fraction +1/3 */ + + delayLine[1] = 1; + ippsDecodeAdaptiveVector_G729_32f_I(delayLine, pSrcExc); + ippsDotProd_32f64f( pCorr, pSrcExc, SUBFR_LEN, &corr); + if(corr > max){ + max = corr; + *fracPartPitchDelay = 1; + } + else + ippsCopy_32f(pTmpExcitation, pSrcExc, SUBFR_LEN); + + return pitchPeriod; +} + +Ipp32s ExtractBitsG729FP( const Ipp8u **pBits, Ipp32s *nBit, Ipp32s Count ) +{ + Ipp32s i ; + Ipp32s Rez = 0L ; + + for ( i = 0 ; i < Count ; i ++ ){ + Ipp32s fTmp ; + fTmp = ((*pBits)[(i + *nBit)>>3] >> (7 - ((i + *nBit) & 0x0007)) ) & 1; + Rez <<= 1 ; + Rez += fTmp ; + } + + *pBits += (Count + *nBit)>>3; + *nBit = (Count + *nBit) & 0x0007; + + return Rez ; +} + +void PWGammaFactor_G729(Ipp32f *pGamma1, Ipp32f *pGamma2, Ipp32f *pIntLSF, Ipp32f *CurrLSF, + Ipp32f *ReflectCoeff, Ipp32s *isFlat, Ipp32f *PrevLogAreaRatioCoeff) +{ + Ipp32f logAreaRatioCoeff[4]; + Ipp32f *logAreaRatioCoeffNew; + Ipp32f *lsf; + Ipp32f minDist, fTmp; + Ipp32s i, k; + + logAreaRatioCoeffNew = &logAreaRatioCoeff[2]; + + /* Convert reflection coefficients to the Log Area Ratio coefficient*/ + for (i=0; i<2; i++) + logAreaRatioCoeffNew[i] = (Ipp32f)log10( (Ipp64f)( ( 1.0f + ReflectCoeff[i]) / (1.0f - ReflectCoeff[i]))); + + /* Interpolation of lar for the 1st subframe */ + for (i=0; i<2; i++) { + logAreaRatioCoeff[i] = 0.5f * (logAreaRatioCoeffNew[i] + PrevLogAreaRatioCoeff[i]); + PrevLogAreaRatioCoeff[i] = logAreaRatioCoeffNew[i]; + } + + for (k=0; k<2; k++) { /* LOOP : gamma2 for 1st to 2nd subframes */ + if (*isFlat != 0) { + if ((logAreaRatioCoeff[2*k] LAR_THRESH3)) *isFlat = 0; + } else { + if ((logAreaRatioCoeff[2*k] > LAR_THRESH2)||(logAreaRatioCoeff[2*k+1] < LAR_THRESH4)) *isFlat = 1; + } + + if (*isFlat == 0) { + /* Second criterion based on the minimum distance between two successives lsfs. */ + pGamma1[k] = GAMMA1_TILTED; + if (k == 0) lsf = pIntLSF; + else lsf = CurrLSF; + + minDist = lsf[1] - lsf[0]; + for (i=1; i GAMMA2_TILTED_MAX) pGamma2[k] = GAMMA2_TILTED_MAX; + if (pGamma2[k] < GAMMA2_TILTED_MIN) pGamma2[k] = GAMMA2_TILTED_MIN; + } else { + pGamma1[k] = GAMMA1_FLAT; + pGamma2[k] = GAMMA2_FLAT; + } + } + return; +} + + +void CodewordImpConv_G729_32f(Ipp32s index, const Ipp32f *pSrc1,const Ipp32f *pSrc2,Ipp32f *pDst) +{ + Ipp32s i; + Ipp32s lPos0, lPos1, lPos2, lPos3; /* position*/ + Ipp32s lSign0, lSign1, lSign2, lSign3; /*signs: 1,-1*/ + + lPos0 = index & 0x7; + lPos1 = (index>>3) & 0x7; + lPos2 = (index>>6) & 0x7; + lPos3 = index>>9; + + lPos0 = (lPos0<<2)+lPos0; /* lPos0*5;*/ + lPos1 = (lPos1<<2)+lPos1+1; /* 1+lPos1*5;*/ + lPos2 = (lPos2<<2)+lPos2+2; /* 2+lPos2*5;*/ + lPos3 = ((lPos3>>1)<<2)+(lPos3>>1)+(lPos3&1)+3; /* 3+(lPos3>>1)*5+(lPos3&1);*/ + + if (lPos0>lPos1) {i=lPos0; lPos0=lPos1; lPos1=i; } + if (lPos2>lPos3) {i=lPos2; lPos2=lPos3; lPos3=i; } + if (lPos0>lPos2) {i=lPos0; lPos0=lPos2; lPos2=i; } + if (lPos1>lPos3) {i=lPos1; lPos1=lPos3; lPos3=i; } + if (lPos1>lPos2) {i=lPos1; lPos1=lPos2; lPos2=i; } + + lSign0 = (pSrc1[lPos0] > 0)? 1:-1; + lSign1 = (pSrc1[lPos1] > 0)? 1:-1; + lSign2 = (pSrc1[lPos2] > 0)? 1:-1; + lSign3 = (pSrc1[lPos3] > 0)? 1:-1; + + for (i=0; i>1) ; + ippsZero_32f(msdState->MeanRC,10); + msdState->lMusicCounter=0; + msdState->fMusicCounter=0.0f; + msdState->lZeroMusicCounter=0; + msdState->fMeanPitchGain =0.5f; + msdState->lPFlagCounter=0; + msdState->fMeanPFlagCounter=0.0; + msdState->lConscPFlagCounter=0; + msdState->lRCCounter=0; + msdState->fMeanFullBandEnergy =0.0f; + + return; + +} + +void MusicDetection_G729E_32f(G729FPEncoder_Obj *encoderObj, G729Codec_Type codecType, Ipp32f Energy, + Ipp32f *ReflectCoeff, Ipp32s *VadDecision, Ipp32f LLenergy, Ipp8s *msdMem,Ipp32f *pExtBuff) +{ + + Ipp32s i; + Ipp32f fSum1, fSum2,fStandartDeviation; + Ipp16s VoicingStrenght1, VoicingStrenght2, VoicingStrenght; + Ipp32f fError, fEnergy , fSpectralDifference, *pTmpVec; + Ipp32f fThreshold; + MusDetectMemory *msdState = (MusDetectMemory *)msdMem; + + pTmpVec = &pExtBuff[0]; /*10 elements*/ + + fError = 1.0f; + for (i=0; i< 4; i++) fError *= (1.0f - ReflectCoeff[i]*ReflectCoeff[i]); + ippsSub_32f(msdState->MeanRC, ReflectCoeff, pTmpVec, 10); + ippsDotProd_32f(pTmpVec, pTmpVec, 10, &fSpectralDifference); + + fEnergy = 10.0f*(Ipp32f)log10(fError*Energy/240.0f +IPP_MINABS_32F); + + if( *VadDecision == VAD_NOISE ){ + ippsInterpolateC_G729_32f(msdState->MeanRC, 0.9f, ReflectCoeff, 0.1f, msdState->MeanRC, 10); + msdState->fMeanFullBandEnergy = 0.9f * msdState->fMeanFullBandEnergy + 0.1f * fEnergy; + } + + fSum1 = 0.0f; + fSum2 = 0.0f; + for(i=0; i<5; i++){ + fSum1 += (Ipp32f) encoderObj->LagBuffer[i]; + fSum2 += encoderObj->PitchGainBuffer[i]; + } + + fSum1 = fSum1/5.0f; + fSum2 = fSum2/5.0f; + fStandartDeviation =0.0f; + for(i=0; i<5; i++) fStandartDeviation += sqr(((Ipp32f) encoderObj->LagBuffer[i] - fSum1)); + fStandartDeviation = (Ipp32f)sqrt(fStandartDeviation/4.0f); + + msdState->fMeanPitchGain = 0.8f * msdState->fMeanPitchGain + 0.2f * fSum2; + /* See I.5.1.1 Pitch lag smoothness and voicing strenght indicator.*/ + if ( codecType == G729D_CODEC) + fThreshold = 0.73f; + else + fThreshold = 0.63f; + + if ( msdState->fMeanPitchGain > fThreshold) + VoicingStrenght2 = 1; + else + VoicingStrenght2 = 0; + + if ( fStandartDeviation < 1.30f && msdState->fMeanPitchGain > 0.45f ) + VoicingStrenght1 = 1; + else + VoicingStrenght1 = 0; + + VoicingStrenght= (Ipp16s)( ((Ipp16s)encoderObj->prevVADDec & (Ipp16s)(VoicingStrenght1 | VoicingStrenght2))| (Ipp16s)(VoicingStrenght2)); + + if( ReflectCoeff[1] <= 0.45f && ReflectCoeff[1] >= 0.0f && msdState->fMeanPitchGain < 0.5f) + msdState->lRCCounter++; + else + msdState->lRCCounter =0; + + if( encoderObj->prevLPCMode== 1 && (*VadDecision == VAD_VOICE)) + msdState->lMusicCounter++; + + if ((encoderObj->sFrameCounter%64) == 0 ){ + if( encoderObj->sFrameCounter == 64) + msdState->fMusicCounter = (Ipp32f)msdState->lMusicCounter; + else + msdState->fMusicCounter = 0.9f*msdState->fMusicCounter + 0.1f*(Ipp32f)msdState->lMusicCounter; + } + + if( msdState->lMusicCounter == 0) + msdState->lZeroMusicCounter++; + else + msdState->lZeroMusicCounter = 0; + + if( msdState->lZeroMusicCounter > 500 || msdState->lRCCounter > 150) msdState->fMusicCounter = 0.0f; + + if ((encoderObj->sFrameCounter%64) == 0) + msdState->lMusicCounter = 0; + + if( VoicingStrenght== 1 ) + msdState->lPFlagCounter++; + + if ((encoderObj->sFrameCounter%64) == 0 ){ + if( encoderObj->sFrameCounter == 64) + msdState->fMeanPFlagCounter = (Ipp32f)msdState->lPFlagCounter; + else{ + if( msdState->lPFlagCounter > 25) + msdState->fMeanPFlagCounter = 0.98f * msdState->fMeanPFlagCounter + 0.02f * msdState->lPFlagCounter; + else if( msdState->lPFlagCounter > 20) + msdState->fMeanPFlagCounter = 0.95f * msdState->fMeanPFlagCounter + 0.05f * msdState->lPFlagCounter; + else + msdState->fMeanPFlagCounter = 0.90f * msdState->fMeanPFlagCounter + 0.10f * msdState->lPFlagCounter; + } + } + + if( msdState->lPFlagCounter == 0) + msdState->lConscPFlagCounter++; + else + msdState->lConscPFlagCounter = 0; + + if( msdState->lConscPFlagCounter > 100 || msdState->lRCCounter > 150) msdState->fMeanPFlagCounter = 0.0f; + + if ((encoderObj->sFrameCounter%64) == 0) + msdState->lPFlagCounter = 0; + + if (codecType == G729E_CODEC){ + if( fSpectralDifference > 0.15f && (fEnergy -msdState->fMeanFullBandEnergy)> 4.0f && (LLenergy> 50.0) ) + *VadDecision =VAD_VOICE; + else if( (fSpectralDifference > 0.38f || (fEnergy -msdState->fMeanFullBandEnergy)> 4.0f ) && (LLenergy> 50.0f)) + *VadDecision =VAD_VOICE; + else if( (msdState->fMeanPFlagCounter >= 10.0f || msdState->fMusicCounter >= 5.0f || encoderObj->sFrameCounter < 64)&& (LLenergy> 7.0)) + *VadDecision =VAD_VOICE; + } + return; +} + +void PitchTracking_G729FPE(Ipp32s *pitchDelay, Ipp32s *fracPitchDelay, Ipp32s *prevPitchDelay, Ipp32s *stat_N, + Ipp32s *lStatPitch2PT, Ipp32s *lStatFracPT) +{ + Ipp32s pitchDistance, minDist, lPitchMult; + Ipp32s j, distSign; + + pitchDistance = (*pitchDelay) - (*prevPitchDelay); + if(pitchDistance < 0) { + distSign = 0; + pitchDistance = - pitchDistance; + } else { + distSign = 1; + } + + /* Test pitch stationarity */ + if (pitchDistance < 5) { + (*stat_N)++; + if (*stat_N > 7) *stat_N = 7 ; + *lStatPitch2PT = *pitchDelay; + *lStatFracPT = *fracPitchDelay; + } else { + /* Find multiples or sub-multiples */ + minDist = pitchDistance; + if( distSign == 0) { + lPitchMult = 2 * (*pitchDelay); + for (j=2; j<5; j++) { + pitchDistance = abs(lPitchMult - (*prevPitchDelay)); + if (pitchDistance <= minDist) { + minDist = pitchDistance; + } + lPitchMult += (*pitchDelay); + } + } else { + lPitchMult = 2 * (*prevPitchDelay); + for (j=2; j<5; j++) { + pitchDistance = abs(lPitchMult - (*pitchDelay)); + if (pitchDistance <= minDist) { + minDist = pitchDistance; + } + lPitchMult += (*prevPitchDelay); + } + } + if (minDist < 5) { /* Multiple or sub-multiple detected */ + if (*stat_N > 0) { + *pitchDelay = *lStatPitch2PT; + *fracPitchDelay = *lStatFracPT; + } + *stat_N -= 1; + if (*stat_N < 0) *stat_N = 0 ; + } else { + *stat_N = 0; /* No (sub-)multiple detected => Pitch transition */ + *lStatPitch2PT = *pitchDelay; + *lStatFracPT = *fracPitchDelay; + } + } + + *prevPitchDelay = *pitchDelay; + + return; +} + +void OpenLoopPitchSearch_G729_32f(const Ipp32f *pSrc, Ipp32s* lBestLag) +{ + Ipp32f fTmp; + Ipp64f dTmp; + + Ipp32f fMax1, fMax2, fMax3; + Ipp32s max1Idx, max2Idx, max3Idx; + + /* Find a maximum for three sections and compare the maxima + of each section by favoring small lag. */ + + /* First section: lag delay = PITCH_LAG_MAX to 80 */ + ippsAutoCorrLagMax_32f(pSrc, FRM_LEN, 80,PITCH_LAG_MAX+1, &fMax1, &max1Idx); + /* Second section: lag delay = 79 to 40 */ + ippsAutoCorrLagMax_32f(pSrc, FRM_LEN, 40,80, &fMax2, &max2Idx); + /* Third section: lag delay = 39 to 20 */ + ippsAutoCorrLagMax_32f(pSrc, FRM_LEN, PITCH_LAG_MIN,40, &fMax3, &max3Idx); + + ippsDotProd_32f64f(&pSrc[-max1Idx], &pSrc[-max1Idx], FRM_LEN, &dTmp); + fTmp = (Ipp32f) (1.0f / sqrt(dTmp+0.01f)); + fMax1 = (Ipp32f)(fMax1) * fTmp; /* max/sqrt(energy) */ + + ippsDotProd_32f64f(&pSrc[-max2Idx], &pSrc[-max2Idx], FRM_LEN, &dTmp); + + fTmp = (Ipp32f) (1.0f / sqrt(dTmp+0.01)); + fMax2 = (Ipp32f)(fMax2) * fTmp; /* max/sqrt(energy) */ + + /* Calc energy */ + ippsDotProd_32f64f(&pSrc[-max3Idx], &pSrc[-max3Idx], FRM_LEN, &dTmp); + /* 1/sqrt(energy) */ + fTmp = 1.0f / (Ipp32f)sqrt(dTmp+0.01); + fMax3 = (Ipp32f)(fMax3) * fTmp; /* max/sqrt(energy) */ + + /* Compare the 3 sections maxima and choose the small one. */ + if ( fMax1 * PITCH_THRESH < fMax2 ) { + fMax1 = fMax2; + max1Idx = max2Idx; + } + + if ( fMax1 * PITCH_THRESH < fMax3 ) max1Idx = max3Idx; + + *lBestLag = max1Idx; + + return; +} + +Ipp32s TestErrorContribution_G729(Ipp32s valPitchDelay, Ipp32s valFracPitchDelay, Ipp32f *ExcErr) +{ + + Ipp32s j, lTmp, l1, l2, lTaming; + Ipp32f maxErrExc; + + lTmp = (valFracPitchDelay > 0) ? (valPitchDelay+1) : valPitchDelay; + + j = lTmp - SUBFR_LEN - INTER_PITCH_LEN; + if(j < 0) j = 0; + l1 = (Ipp32s) (j * INV_SUBFR_LEN); + + j = lTmp + INTER_PITCH_LEN - 2; + l2 = (Ipp32s) (j * INV_SUBFR_LEN); + + maxErrExc = -1.f; + lTaming = 0 ; + for(j=l2; j>=l1; j--) { + if(ExcErr[j] > maxErrExc) maxErrExc = ExcErr[j]; + } + if(maxErrExc > THRESH_ERR) { + lTaming = 1; + } + return(lTaming); +} + +void UpdateExcErr_G729(Ipp32f valPitchGain, Ipp32s valPitchDelay, Ipp32f *pExcErr) +{ + Ipp32s i, l1, l2, n; + Ipp32f fMax, fTmp; + + fMax = -1.f; + + n = valPitchDelay- SUBFR_LEN; + if(n < 0) { + fTmp = 1.f + valPitchGain * pExcErr[0]; + if(fTmp > fMax) fMax = fTmp; + fTmp = 1.f + valPitchGain * fTmp; + if(fTmp > fMax) fMax = fTmp; + } else { + l1 = (Ipp32s) (n * INV_SUBFR_LEN); + + i = valPitchDelay - 1; + l2 = (Ipp32s) (i * INV_SUBFR_LEN); + + for(i = l1; i <= l2; i++) { + fTmp = 1.f + valPitchGain * pExcErr[i]; + if(fTmp > fMax) fMax = fTmp; + } + } + + for(i=3; i>=1; i--) pExcErr[i] = pExcErr[i-1]; + pExcErr[0] = fMax; + + return; +} + +void isBackwardModeDominant_G729(Ipp32s *isBackwardModeDominant, Ipp32s LPCMode, Ipp32s *pCounterBackward, Ipp32s *pCounterForward) +{ + + Ipp32s lTmp, lCounter; + + if (LPCMode == 0) (*pCounterForward)++; + else (*pCounterBackward)++; + + lCounter = *pCounterBackward + *pCounterForward; + + if (lCounter == 100) { + lCounter = lCounter >> 1; + *pCounterBackward = (*pCounterBackward) >> 1; + *pCounterForward = (*pCounterForward) >> 1; + } + + *isBackwardModeDominant = 0; + if (lCounter >= 10) { + lTmp = (*pCounterForward) << 2; + if (*pCounterBackward > lTmp) *isBackwardModeDominant = 1; + } + + return; +} + +Ipp32f CalcEnergy_dB_G729(Ipp32f *pSrc, Ipp32s len) +{ + Ipp64f dEnergy; + Ipp32f fEnergydB; + Ipp32s n, k, lTmp; + + ippsDotProd_32f64f(pSrc, pSrc, len, &dEnergy); + dEnergy += 0.0001; + fEnergydB = (Ipp32f)log10(dEnergy); + n = (Ipp32s) (fEnergydB * INVERSE_LOG2); + if(n >= 4) { + if(dEnergy > 2147483647.) dEnergy = 93.1814; + else { + k = (Ipp32s)dEnergy; + lTmp = -(1 << (n-4)); + k &= lTmp; + dEnergy = 10. * log10((Ipp32f)k); + } + } + else dEnergy = 0.005; + + return (Ipp32f)dEnergy; +} + +void InterpolatedBackwardFilter_G729(Ipp32f *pSrcDstLPCBackwardFlt, Ipp32f *pSrcPrevFilter, Ipp32f *pSrcDstIntCoeff) +{ + Ipp32s i; + Ipp32f s1, s2; + Ipp32f *pBwdLPC; + Ipp32f fIntFactor; + + pBwdLPC = pSrcDstLPCBackwardFlt + BWD_LPC_ORDERP1; + + /* Calculate the interpolated filters */ + fIntFactor = *pSrcDstIntCoeff - 0.1f; + if( fIntFactor < 0) fIntFactor = 0; + + for (i=0; igainMem,6); + phdState->prevDispState = 0; + phdState->prevCbGain = 0.; + phdState->onset = 0; +} + +void PhaseDispersionUpdate_G729D(Ipp32f valPitchGain, Ipp32f valCodebookGain, Ipp8s *phdMem) +{ + Ipp32s i; + PHDmemory *phdState = (PHDmemory *)phdMem; + + for (i = 5; i > 0; i--) phdState->gainMem[i] = phdState->gainMem[i-1]; + phdState->gainMem[0] = valPitchGain; + phdState->prevDispState = 2; + phdState->prevCbGain = valCodebookGain; + phdState->onset = 0; + + return; +} + +void PhaseDispersion_G729D(Ipp32f *pSrcExcSignal, Ipp32f *pDstFltExcSignal, Ipp32f valCodebookGain, + Ipp32f valPitchGain, Ipp32f *pSrcDstInnovation, Ipp8s *phdMem,Ipp8s *pExtBuff) +{ + Ipp32s i; + PHDmemory *phdState = (PHDmemory *)phdMem; + + Ipp32f *pScaledLTP; + Ipp32f *pMemory; + Ipp32s *pPos; + Ipp32s numNonZeroElem, nPulse, i1, lPos; + Ipp32s phDispState; + const Ipp32f *pTable=NULL; + + pScaledLTP = (Ipp32f *)pExtBuff; + pMemory = (Ipp32f *)(pExtBuff + SUBFR_LEN*sizeof(Ipp32f)); + pPos = (Ipp32s *)(pMemory + SUBFR_LEN*sizeof(Ipp32f)); + + /* anti-sparseness post-processing */ + ippsAdaptiveCodebookContribution_G729_32f(valCodebookGain, pSrcDstInnovation, pSrcExcSignal, pScaledLTP); + ippsCopy_32f(pSrcDstInnovation,pMemory,SUBFR_LEN); + ippsZero_32f(pSrcDstInnovation,SUBFR_LEN); + + numNonZeroElem=0; + for (i=0; i 0.6f) && (valPitchGain < 0.9f) ) { + phDispState = 1; + } else { + phDispState = 2; + } + + for (i = 5; i > 0; i--) { + phdState->gainMem[i]=phdState->gainMem[i-1]; + } + phdState->gainMem[0] = valPitchGain; + + if (valCodebookGain > 2.0f * phdState->prevCbGain) + phdState->onset = 2; + else { + if (phdState->onset) phdState->onset -= 1; + } + + i1=0; + for (i = 0; i < 6; i++) { + if (phdState->gainMem[i] < 0.6f) i1 += 1; + } + if (i1 > 2 && !phdState->onset) phDispState = 0; + + if (phDispState - phdState->prevDispState > 1 && !phdState->onset) phDispState -= 1; + + if (phdState->onset) { + if (phDispState < 2) phDispState++; + } + + phdState->prevDispState=phDispState; + phdState->prevCbGain = valCodebookGain; + + if (phDispState == 0) { + pTable = ImpLow; + } else if (phDispState == 1) { + pTable = ImpMiddle; + } else if (phDispState == 2) { + pTable = ImpHigh; + } + + for (nPulse=0; nPulsesBWDStatInd)++; + CLIP_TO_UPLEVEL(encoderObj->sBWDStatInd,21); + if(encoderObj->sValBWDStatInd < 32517) encoderObj->sValBWDStatInd += 250; + else encoderObj->sValBWDStatInd = 32767; + + /* after 20 backward frames => increase stat */ + if (encoderObj->sBWDStatInd == 20) { + if(encoderObj->sGlobalStatInd < 30267) encoderObj->sGlobalStatInd += 2500; + else encoderObj->sGlobalStatInd = 32767; + } + else if (encoderObj->sBWDStatInd > 20) encoderObj->sGlobalStatInd += 500; + + } + + else if ((valLPCMode == 0)&&(encoderObj->prevLPCMode == 1)) { /* Backward -> Forward transition */ + + /* Transition occurs after less than 20 backward frames => decrease stat */ + if (encoderObj->sBWDStatInd < 20) { + sTmp = (Ipp16s)(5000 - encoderObj->sValBWDStatInd); + encoderObj->sGlobalStatInd = (Ipp16s)(encoderObj->sGlobalStatInd-sTmp); + } + + /* Reset consecutive backward frames counter */ + encoderObj->sBWDStatInd = 0; + encoderObj->sValBWDStatInd = 0; + + } + + /* Second adaptation based on prediction gains */ + + if (encoderObj->sGlobalStatInd < 13000) { + + if (valBackwardPredGain > valForwardPredGain + TH4) encoderObj->sGlobalStatInd += 3200; + else if (valBackwardPredGain > valForwardPredGain + TH3) encoderObj->sGlobalStatInd += 2400; + else if (valBackwardPredGain > valForwardPredGain + TH2) encoderObj->sGlobalStatInd += 1600; + else if (valBackwardPredGain > valForwardPredGain + TH1) encoderObj->sGlobalStatInd += 800; + else if (valBackwardPredGain > valForwardPredGain) encoderObj->sGlobalStatInd += 400; + + } + + if (valBackwardPredGain < valForwardPredGain - TH5) encoderObj->sGlobalStatInd -= 6400; + else if (valBackwardPredGain < valForwardPredGain - TH4) encoderObj->sGlobalStatInd -= 3200; + else if (valBackwardPredGain < valForwardPredGain - TH3) encoderObj->sGlobalStatInd -= 1600; + else if (valBackwardPredGain < valForwardPredGain - TH2) encoderObj->sGlobalStatInd -= 800; + else if (valBackwardPredGain < valForwardPredGain - TH1) encoderObj->sGlobalStatInd -= 400; + + CLIP_TO_UPLEVEL(encoderObj->sGlobalStatInd,32000); + CLIP_TO_LOWLEVEL(encoderObj->sGlobalStatInd,0); + return; +} + +void SetLPCMode_G729FPE(G729FPEncoder_Obj* encoderObj, Ipp32f *pSrcSignal, Ipp32f *pSrcForwardLPCFilter, + Ipp32f *pSrcBackwardLPCFilter, Ipp32s *pDstLPCMode, Ipp32f *pSrcLSP,Ipp32f *pExtBuff) +{ + + Ipp32s i; + Ipp32f *pLPCFlt, *PPtr; + Ipp32f fGap, forwardPredGain, backwardPredGain, intBackwardPredGain; + Ipp32f LSPThreshold, LSPDist, fTmp; + Ipp32f ener_DB_pSrcSignal; + + PPtr = &pExtBuff[0]; /*FRM_LEN elements*/ + + ener_DB_pSrcSignal = CalcEnergy_dB_G729(pSrcSignal, FRM_LEN); + + pLPCFlt = pSrcBackwardLPCFilter + BWD_LPC_ORDERP1; + /* Calc backward filter prediction gain (without interpolation ) */ + ippsConvBiased_32f(pLPCFlt,BWD_LPC_ORDER+1,pSrcSignal,FRM_LEN+BWD_LPC_ORDER,PPtr,FRM_LEN,BWD_LPC_ORDER); + backwardPredGain = ener_DB_pSrcSignal - CalcEnergy_dB_G729(PPtr, FRM_LEN); + + /* Interpolated backward filter for the first sub-frame */ + InterpolatedBackwardFilter_G729(pSrcBackwardLPCFilter, encoderObj->PrevFlt, &encoderObj->fInterpolationCoeff); + + /* Calc interpolated backward filter prediction gain */ + ippsConvBiased_32f(pSrcBackwardLPCFilter,BWD_LPC_ORDER+1,pSrcSignal,SUBFR_LEN+BWD_LPC_ORDER,PPtr,SUBFR_LEN,BWD_LPC_ORDER); + ippsConvBiased_32f(pLPCFlt,BWD_LPC_ORDER+1,&pSrcSignal[SUBFR_LEN],SUBFR_LEN+BWD_LPC_ORDER,&PPtr[SUBFR_LEN],SUBFR_LEN,BWD_LPC_ORDER); + intBackwardPredGain = ener_DB_pSrcSignal - CalcEnergy_dB_G729(PPtr, FRM_LEN); + + /* Calc forward filter prediction gain */ + ippsConvBiased_32f(pSrcForwardLPCFilter,LPC_ORDER+1,pSrcSignal,SUBFR_LEN+LPC_ORDER,PPtr,SUBFR_LEN,LPC_ORDER); + ippsConvBiased_32f(&pSrcForwardLPCFilter[LPC_ORDERP1],LPC_ORDER+1,&pSrcSignal[SUBFR_LEN],SUBFR_LEN+LPC_ORDER,&PPtr[SUBFR_LEN],SUBFR_LEN,LPC_ORDER); + forwardPredGain = ener_DB_pSrcSignal - CalcEnergy_dB_G729(PPtr, FRM_LEN); + + /* Choose: backward/forward mode.*/ + /* 1st criterion with prediction gains. The global stationarity index + is used to adapt the threshold value " GAP ".*/ + + /* Do the threshold adaptation according to the global stationarity indicator */ + fGap = (Ipp32f)(encoderObj->sGlobalStatInd) * GAP_FACT; + fGap += 1.f; + + if ( (intBackwardPredGain > forwardPredGain - fGap)&& (backwardPredGain > forwardPredGain - fGap)&& + (backwardPredGain > 0.f) && (intBackwardPredGain > 0.f) ) *pDstLPCMode = 1; + else *pDstLPCMode = 0; + + if (encoderObj->sGlobalStatInd < 13000) *pDstLPCMode = 0; /* => Forward mode imposed */ + + /* 2nd criterion with a distance between 2 successive LSP vectors */ + /* Computation of the LPC distance */ + LSPDist = 0; + for(i=0; iOldLSP[i] - pSrcLSP[i]; + LSPDist += fTmp * fTmp; + } + + /* Adaptation of the LSPs thresholds */ + if (encoderObj->sGlobalStatInd < 32000) { + LSPThreshold = 0.f; + } + else { + LSPThreshold = 0.03f; + } + + /* Switching backward -> forward forbidden in case of a LPC stationnary */ + if ((LSPDist < LSPThreshold) &&(*pDstLPCMode == 0)&&(encoderObj->prevLPCMode == 1) + &&(backwardPredGain > 0.f)&&(intBackwardPredGain > 0.f)) { + *pDstLPCMode = 1; + } + + /* Low energy frame => Forward mode chosen */ + + if (ener_DB_pSrcSignal < THRES_ENERGY) { + *pDstLPCMode = 0; + if (encoderObj->sGlobalStatInd > 13000) encoderObj->sGlobalStatInd = 13000; + } + else isBackwardModeDominant_G729(&encoderObj->isBWDDominant, *pDstLPCMode,&encoderObj->sBWDFrmCounter,&encoderObj->sFWDFrmCounter); + + /* Adaptation of the global stationarity indicator */ + if (ener_DB_pSrcSignal >= THRES_ENERGY) GlobalStationnarityAdaptation_G729E(encoderObj,backwardPredGain, forwardPredGain, *pDstLPCMode); + if(*pDstLPCMode == 0) encoderObj->fInterpolationCoeff = 1.1f; + return; +} + +static void NormalizedCorrelation(Ipp32f *pSrcExc, Ipp32f *pSrcTargetVector, Ipp32f *pSrcImpulseResponse, + Ipp32s len, Ipp32s lagMin, Ipp32s lagMax, Ipp32f *pDstCorr, Ipp32f *pTmpFltPastExc) +{ + Ipp32s i, k; + Ipp64f dEnergy, dTmp; + + k = -lagMin; + + ippsConvBiased_32f( &pSrcExc[k], len , pSrcImpulseResponse, len , pTmpFltPastExc, len ,0); + + /* loop for every possible period */ + for (i = lagMin; i < lagMax; i++) { + /* Compute energy of pFltExc[] */ + ippsDotProd_32f64f(pTmpFltPastExc, pTmpFltPastExc, len, &dEnergy); + + /* Compute correlation between pSrcTargetVector[] and pFltExc[] */ + ippsDotProd_32f64f(pSrcTargetVector, pTmpFltPastExc, len, &dTmp); + + /* Normalize correlation = correlation * (1/sqrt(energy)) */ + pDstCorr[i] = (Ipp32f)(dTmp)/((Ipp32f)sqrt(dEnergy+0.01)); + + /* modify the filtered excitation pFltExc[] for the next iteration */ + k--; + ippsFilteredExcitation_G729_32f( pSrcImpulseResponse, pTmpFltPastExc, len, pSrcExc[k]); + } + + /* Compute energy of pFltExc[] */ + ippsDotProd_32f64f(pTmpFltPastExc, pTmpFltPastExc, len, &dEnergy); + + /* Compute correlation between pSrcTargetVector[] and pFltExc[] */ + ippsDotProd_32f64f(pSrcTargetVector, pTmpFltPastExc, len, &dTmp); + + /* Normalize correlation = correlation * (1/sqrt(energy)) */ + pDstCorr[lagMax] = (Ipp32f)(dTmp)/((Ipp32f)sqrt(dEnergy+0.01)); + + return; + +} + +static __ALIGN32 CONST Ipp32f ReorderInter_3[2*3*INTERPOL4_LEN] = { + 0.015738f,-0.047624f, 0.084078f, 0.900839f, + 0.084078f,-0.047624f, 0.015738f, 0.000000f, + 0.000000f, 0.016285f,-0.105570f, 0.760084f, + 0.424082f,-0.121120f, 0.031217f,-0.005925f, +-0.005925f, 0.031217f,-0.121120f, 0.424082f, + 0.760084f,-0.105570f, 0.016285f, 0.000000f +}; + +static Ipp32f Interpolation_3(Ipp32f *pSrc, Ipp32s lFrac) +{ + Ipp32s i; + Ipp32f sum, *x1; + const Ipp32f *c; + + x1 = &pSrc[-(INTERPOL4_LEN-1)]; + if (lFrac < 0) { + x1--; + lFrac += UP_SAMPLING; + } + c = &ReorderInter_3[2*INTERPOL4_LEN*lFrac]; + + sum = 0.0f; + for(i=0; i< 2*INTERPOL4_LEN; i++) + sum+= x1[i] * c[i]; + + return sum; +} + +Ipp32s AdaptiveCodebookSearch_G729_32f(Ipp32f *pSrcExc, Ipp32f *pSrcTargetVector, Ipp32f *pSrcImpulseResponse, Ipp32s len, + Ipp32s minLag, Ipp32s maxLag, Ipp32s valSubframeNum, Ipp32s *pDstFracPitch, G729Codec_Type codecType,Ipp32f *pExtBuff) +{ + Ipp32s i, lFracPart; + Ipp32s lBestLag, lMin, lMax; + Ipp32f max; + Ipp32f fIntCorr; + Ipp32f *pFltExc; /* filtered past excitation */ + Ipp32f *pCorr; + Ipp32s midLag; + + pFltExc = &pExtBuff[0]; + + /* Find interval to compute normalized correlation */ + lMin = minLag - INTERPOL4_LEN; + lMax = maxLag + INTERPOL4_LEN; + + pCorr = &pExtBuff[SUBFR_LEN - lMin]; /*Actually (10+2*INTERPOL4_LEN) from [SUBFR_LEN]. pCorr[lMin:lMax]*/ + + /* Compute normalized correlation between target and filtered excitation */ + NormalizedCorrelation(pSrcExc, pSrcTargetVector, pSrcImpulseResponse, len, lMin, lMax, pCorr,pFltExc); + + /* find integer pitch */ + max = pCorr[minLag]; + lBestLag = minLag; + + for(i= minLag+1; i<=maxLag; i++) { + if( pCorr[i] >= max) { + max = pCorr[i]; + lBestLag = i; + } + } + + /* If first subframe and lBestLag > 84 do not search fractionnal pitch */ + + if( (valSubframeNum == 0) && (lBestLag > 84) ) { + *pDstFracPitch = 0; + return(lBestLag); + } + + /* test the fractions around lBestLag and choose the one which maximizes the interpolated normalized correlation */ + + if (codecType == G729D_CODEC) { /* 6.4 kbps */ + if (valSubframeNum == 0) { + max = Interpolation_3(&pCorr[lBestLag], -2); + lFracPart = -2; + + for (i = -1; i <= 2; i++) { + fIntCorr = Interpolation_3(&pCorr[lBestLag], i); + if(fIntCorr > max) { + max = fIntCorr; + lFracPart = i; + } + } + } else { + midLag = maxLag - 4; + if ((lBestLag == midLag - 1) || lBestLag == midLag) { + max = Interpolation_3(&pCorr[lBestLag], -2); + lFracPart = -2; + + for (i = -1; i <= 2; i++) { + fIntCorr = Interpolation_3(&pCorr[lBestLag], i); + if(fIntCorr > max) { + max = fIntCorr; + lFracPart = i; + } + } + } else if (lBestLag == midLag - 2) { + max = Interpolation_3(&pCorr[lBestLag], 0); + lFracPart = 0; + + for (i = 1; i <= 2; i++) { + fIntCorr = Interpolation_3(&pCorr[lBestLag], i); + if(fIntCorr > max) { + max = fIntCorr; + lFracPart = i; + } + } + } else if (lBestLag == midLag + 1) { + max = Interpolation_3(&pCorr[lBestLag], -2); + lFracPart = -2; + + for (i = -1; i <= 0; i++) { + fIntCorr = Interpolation_3(&pCorr[lBestLag], i); + if(fIntCorr > max) { + max = fIntCorr; + lFracPart = i; + } + } + } else + lFracPart = 0; + } + } else { + max = Interpolation_3(&pCorr[lBestLag], -2); + lFracPart = -2; + + for (i = -1; i <= 2; i++) { + fIntCorr = Interpolation_3(&pCorr[lBestLag], i); + if(fIntCorr > max) { + max = fIntCorr; + lFracPart = i; + } + } + } + + /* limit the fraction value in the interval [-1,0,1] */ + + if (lFracPart == -2) { + lFracPart = 1; + lBestLag -= 1; + } + if (lFracPart == 2) { + lFracPart = -1; + lBestLag += 1; + } + + *pDstFracPitch = lFracPart; + + return lBestLag; +} + +void CNGGetSize(Ipp32s *pDstSize) +{ + *pDstSize = sizeof(CNGmemory); + return; +} + +void CNGInit(Ipp8s *cngMem) +{ + CNGmemory *cngState = (CNGmemory *)cngMem; + ippsZero_16s((Ipp16s*)cngState,sizeof(CNGmemory)>>1) ; + + ippsZero_32f(cngState->SumAutoCorrs,SUMAUTOCORRS_SIZE); + ippsZero_32f(cngState->AutoCorrs,AUTOCORRS_SIZE); + ippsZero_32f(cngState->Energies,GAINS_NUM); + + cngState->fCurrGain = 0.; + cngState->lAutoCorrsCounter = 0; + cngState->lFltChangeFlag = 0; +} + +static Ipp32f gaussGen(Ipp16s *sCNGSeed) +{ + Ipp32s i, lTmp; + + lTmp = 0; + for(i=0; i<12; i++) { + lTmp += Rand_16s(sCNGSeed); + } + lTmp >>= 7; + return((Ipp32f)lTmp * 0.001953125f); +} + +void ComfortNoiseExcitation_G729(Ipp32f fCurrGain, Ipp32f *exc, Ipp16s *sCNGSeed, Ipp32s flag_cod, Ipp32f *ExcitationError, Ipp8s *phdMem, Ipp8s *pExtBuff) +{ + Ipp32f *pGaussianExc; + Ipp32s *pos; + Ipp32f *sign; + Ipp32f *CurrentExcitation; + Ipp32f fgp, fEner, fFact, fInterExc, k, discriminant, x1, x2, absMinRoot; + Ipp32s i, n, pitchDelay, lFrac; + Ipp16s sGp, sTmp1, sTmp2; + Ipp32s *delayLine; + //Ipp64f ener_tmp; + + pGaussianExc = (Ipp32f *)pExtBuff; + pos = (Ipp32s *)(pExtBuff + SUBFR_LEN*sizeof(Ipp32f)); + sign = (Ipp32f *)((Ipp8s *)pos + 4*sizeof(Ipp32s)); + delayLine = (Ipp32s *)((Ipp8s *)sign + 4*sizeof(Ipp32f)); + + /* Loop on subframes */ + CurrentExcitation = exc; + for (n = 0; n < NUN_SUBFRAMES; n++) { + /* Fenerate random adaptive codebook and fixed codebook parameters */ + sTmp1 = Rand_16s(sCNGSeed); + lFrac = (Ipp32s)(sTmp1 & (Ipp16s)0x0003) - 1; + if(lFrac == 2) lFrac = 0; + sTmp1 >>= 2; + pitchDelay = (Ipp32s)(sTmp1 & (Ipp16s)0x003F) + 40; + sTmp1 >>= 6; + sTmp2 = (Ipp16s)(sTmp1 & (Ipp16s)0x0007); + pos[0] = 5 * (Ipp32s)sTmp2; + sTmp1 >>= 3; + sTmp2 = (Ipp16s)(sTmp1 & (Ipp16s)0x0001); + sign[0] = 2.f * (Ipp32f)sTmp2 - 1.f; + sTmp1 >>= 1; + sTmp2 = (Ipp16s)(sTmp1 & (Ipp16s)0x0007); + pos[1] = 5 * (Ipp32s)sTmp2 + 1; + sTmp1 >>= 3; + sTmp2 = (Ipp16s)(sTmp1 & (Ipp16s)0x0001); + sign[1] = 2.f * (Ipp32f)sTmp2 - 1.f; + sTmp1 = Rand_16s(sCNGSeed); + sTmp2 = (Ipp16s)(sTmp1 & (Ipp16s)0x0007); + pos[2] = 5 * (Ipp32s)sTmp2 + 1; + sTmp1 >>= 3; + sTmp2 = (Ipp16s)(sTmp1 & (Ipp16s)0x0001); + sign[2] = 2.f * (Ipp32f)sTmp2 - 1.f; + sTmp1 >>= 1; + sTmp2 = (Ipp16s)(sTmp1 & (Ipp16s)0x000F); + pos[3] = (Ipp32s)(sTmp2 & (Ipp16s)0x0001) + 3; /* j+3*/ + sTmp2 >>= 1; + sTmp2 &= (Ipp16s)0x0007; + pos[3] += 5 * (Ipp32s)sTmp2; + sTmp1 >>= 4; + sTmp2 = (Ipp16s)(sTmp1 & (Ipp16s)0x0001); + sign[3] = 2.f * (Ipp32f)sTmp2 - 1.f; + sGp = (Ipp16s)(Rand_16s(sCNGSeed) & (Ipp16s)0x1FFF); /* < 0.5 */ + fgp = (Ipp32f)sGp / 16384.f; + + /* Generate gaussian excitation */ + /*ippsRandomNoiseExcitation_G729B_16s32f(sCNGSeed, excg, SUBFR_LEN); + ippsDotProd_32f64f(excg, excg, SUBFR_LEN,&ener_tmp);*/ + fEner = 0.f; + for(i=0; i= 0.f) { + CLIP_TO_UPLEVEL(absMinRoot,CNG_MAX_GAIN); + } else { + CLIP_TO_LOWLEVEL(absMinRoot,(-CNG_MAX_GAIN)); + } + + /* Update cur_exc with ACELP excitation */ + for(i=0; i<4; i++) { + CurrentExcitation[pos[i]] += absMinRoot * sign[i]; + } + + if(flag_cod != DECODER) UpdateExcErr_G729(fgp, pitchDelay,ExcitationError); + else { + if(absMinRoot >= 0.f) PhaseDispersionUpdate_G729D(fgp,absMinRoot,phdMem); + else PhaseDispersionUpdate_G729D(fgp,-absMinRoot,phdMem); + } + CurrentExcitation += SUBFR_LEN; + } /* end of loop on subframes */ + + return; +} + + + +static __ALIGN32 CONST Ipp32f fFact[GAINS_NUM+1] = + {(Ipp32f)0.003125, (Ipp32f)0.00078125, (Ipp32f)0.000390625}; + +static Ipp32s quantEnergy(Ipp32f fEner, Ipp32f *pDstQEnergy) +{ + Ipp32f fEnergydB; + Ipp32s index; + + if(fEner <= MIN_ENER) { /* MIN_ENER <=> -8dB */ + *pDstQEnergy = (Ipp32f)-12.; + return(0); + } + + fEnergydB = (Ipp32f)10. * (Ipp32f)log10(fEner); + + if(fEnergydB <= (Ipp32f)-8.) { + *pDstQEnergy = (Ipp32f)-12.; + return(0); + } + + if(fEnergydB >= (Ipp32f)65.) { + *pDstQEnergy = (Ipp32f)66.; + return(31); + } + + if(fEnergydB <= (Ipp32f)14.) { + index = (Ipp32s)((fEnergydB + (Ipp32f)10.) * 0.25); + if (index < 1) index = 1; + *pDstQEnergy = (Ipp32f)4. * (Ipp32f)index - (Ipp32f)8.; + return(index); + } + + index = (Ipp32s)((fEnergydB - (Ipp32f)3.) * 0.5); + if (index < 6) index = 6; + *pDstQEnergy = (Ipp32f)2. * (Ipp32f)index + (Ipp32f)4.; + return(index); +} + +void QuantSIDGain_G729B(Ipp32f *fEner, Ipp32s lNumSavedEnergies, Ipp32f *enerq, Ipp32s *idx) +{ + Ipp32s i; + Ipp32f averageEnergy; + + /* Quantize energy saved for frame erasure case*/ + if(lNumSavedEnergies == 0) { + averageEnergy = (*fEner) * fFact[0]; + } else { + /* Compute weighted average of energies*/ + averageEnergy = (Ipp32f)0.; + for(i=0; i(Ipp32f)0.0){ + /* pre select first index */ + pCand[0] = 0 ; + do{ + if(y>thr1_G729D[pCand[0]]*fGainCode) (pCand[0])++ ; + else break ; + } while((pCand[0])<(SIZECODEBOOK1_ANNEXD-NUM_CAND1_ANNEXD)) ; + /* pre select second index */ + pCand[1] = 0 ; + do{ + if(x>thr2_G729D[pCand[1]]*fGainCode) (pCand[1])++ ; + else break ; + } while((pCand[1])<(SIZECODEBOOK2_ANNEXD-NUM_CAND2_ANNEXD)) ; + } + else{ + /* pre select first index */ + pCand[0] = 0 ; + do{ + if(y(Ipp32f)0.0){ + /* pre select first index */ + pCand[0] = 0 ; + do{ + if(y>thr1_G729[pCand[0]]*fGainCode) (pCand[0])++ ; + else break ; + } while((pCand[0])<(SIZECODEBOOK1-NUM_CAND1)) ; + /* pre select second index */ + pCand[1] = 0 ; + do{ + if(x>thr2_G729[pCand[1]]*fGainCode) (pCand[1])++ ; + else break ; + } while((pCand[1])<(SIZECODEBOOK2-NUM_CAND2)) ; + } + else{ + /* pre select first index */ + pCand[0] = 0 ; + do{ + if(y 0; j--) + pastQntEnergies[j] = pastQntEnergies[j-1]; + pastQntEnergies[0] = (Ipp32f)20.0*(Ipp32f)log10((Ipp64f)fGainCode); + + return; +} + +static void GainPredict_G729_32f(Ipp32f *pastQntEnr, Ipp32f *FixedCodebookExc, Ipp32s len,Ipp32f *fGainCode) +{ + Ipp32f fEnergy, predCodeboookGain; + Ipp32s i; + Ipp64f dTmp; + + predCodeboookGain = MEAN_ENER ; + + /* innovation energy */ + ippsDotProd_32f64f(FixedCodebookExc, FixedCodebookExc, len, &dTmp); + fEnergy = (Ipp32f)dTmp+0.01f; + + fEnergy = (Ipp32f)10.0 * (Ipp32f)log10(fEnergy /(Ipp32f)len); + + predCodeboookGain -= fEnergy; + + /* predicted energy */ + for (i=0; i<4; i++) predCodeboookGain += PredCoeff[i]*pastQntEnr[i]; + + /* predicted codebook gain */ + *fGainCode = predCodeboookGain; + *fGainCode = (Ipp32f)pow((Ipp64f)10.0,(Ipp64f)(*fGainCode/20.0)); /* predicted gain */ + + return; +} + +Ipp32s GainQuant_G729(Ipp32f *FixedCodebookExc, Ipp32f *pGainCoeff, Ipp32s lSbfrLen, Ipp32f *pitchGain, Ipp32f *codeGain, + Ipp32s tamingflag, Ipp32f *PastQuantEnergy, G729Codec_Type codecType,Ipp8s *pExtBuff) +{ + Ipp32s *pCand,*index; + Ipp32f fGainCode ; + Ipp32f *pBestGain,fTmp; + Ipp64f dGainCode; + Ipp32s lQIndex; + + pBestGain = (Ipp32f *)pExtBuff; + pCand = (Ipp32s *)(pExtBuff + 2*sizeof(Ipp32f)); + index = (Ipp32s *)((Ipp8s *)pCand + 2*sizeof(Ipp32s)); + + GainPredict_G729_32f( PastQuantEnergy, FixedCodebookExc, lSbfrLen, &fGainCode); + + /*-- pre-selection --*/ + fTmp = (Ipp32f)-1./((Ipp32f)4.*pGainCoeff[0]*pGainCoeff[2]-pGainCoeff[4]*pGainCoeff[4]) ; + pBestGain[0] = ((Ipp32f)2.*pGainCoeff[2]*pGainCoeff[1]-pGainCoeff[3]*pGainCoeff[4])*fTmp ; + pBestGain[1] = ((Ipp32f)2.*pGainCoeff[0]*pGainCoeff[3]-pGainCoeff[1]*pGainCoeff[4])*fTmp ; + + if (tamingflag == 1){ + CLIP_TO_UPLEVEL(pBestGain[0],MAX_GAIN_TIMING2); + } + /* Presearch for gain codebook */ + if(codecType==G729D_CODEC) { + GainCodebookPreselect_G729D(pBestGain,pCand,fGainCode) ; + + ippsGainCodebookSearch_G729D_32f(pGainCoeff, fGainCode, pCand, index, tamingflag); + + *pitchGain = gbk1_G729D[index[0]][0]+gbk2_G729D[index[1]][0] ; + dGainCode = (Ipp64f)(gbk1_G729D[index[0]][1]+gbk2_G729D[index[1]][1]); + + *codeGain = (Ipp32f)(dGainCode) * fGainCode; + + if(dGainCode < 0.2) dGainCode = 0.2; + + lQIndex = map1_G729D[index[0]]*SIZECODEBOOK2_ANNEXD+map2_G729D[index[1]]; + } else { + GainCodebookPreselect_G729(pBestGain,pCand,fGainCode) ; + + ippsGainCodebookSearch_G729_32f(pGainCoeff, fGainCode, pCand, index, tamingflag); + + *pitchGain = gbk1_G729[index[0]][0]+gbk2_G729[index[1]][0] ; + dGainCode = (Ipp64f)(gbk1_G729[index[0]][1]+gbk2_G729[index[1]][1]); + *codeGain = (Ipp32f)(dGainCode) * fGainCode; + + lQIndex = map1_G729[index[0]]*SIZECODEBOOK2+map2_G729[index[1]]; + } + /* Update table of past quantized energies */ + GainUpdate_G729_32f( PastQuantEnergy, (Ipp32f)dGainCode); + + return lQIndex; +} + +void DecodeGain_G729(Ipp32s index, Ipp32f *FixedCodebookExc, Ipp32s lSbfrLen, Ipp32f *pitchGain, Ipp32f *codeGain, Ipp32s rate, Ipp32f *PastQuantEnergy) +{ + + + Ipp32s idxs[2]; + Ipp32f fGainCode; + Ipp64f dGainCode; + + GainPredict_G729_32f( PastQuantEnergy, FixedCodebookExc, lSbfrLen, &fGainCode); + + /* Decode pitch and codebook gain. */ + + if(rate==G729D_MODE) { + idxs[0] = imap1_G729D[index>>NCODE2_B_ANNEXD] ; + idxs[1] = imap2_G729D[index & (SIZECODEBOOK2_ANNEXD-1)] ; + + *pitchGain = gbk1_G729D[idxs[0]][0]+gbk2_G729D[idxs[1]][0]; + dGainCode = (Ipp64f)gbk1_G729D[idxs[0]][1]+gbk2_G729D[idxs[1]][1]; + + *codeGain = (Ipp32f)(dGainCode) * fGainCode; + + if(dGainCode < 0.2) dGainCode = 0.2; + } else { + idxs[0] = imap1_G729[index>>NCODE2_BITS] ; + idxs[1] = imap2_G729[index & (SIZECODEBOOK2-1)] ; + + *pitchGain = gbk1_G729[idxs[0]][0]+gbk2_G729[idxs[1]][0]; + dGainCode = (Ipp64f)gbk1_G729[idxs[0]][1]+gbk2_G729[idxs[1]][1]; + + *codeGain = (Ipp32f) (dGainCode * fGainCode); + } + + /* Update table of past quantized energies */ + GainUpdate_G729_32f( PastQuantEnergy, (Ipp32f)dGainCode); + + return; +} + +void PSTGetSize(Ipp32s *pDstSize) +{ + *pDstSize = sizeof(PSTmemory); + return; +} + +void PSTInit(Ipp8s *pstMem) +{ + PSTmemory *pstState = (PSTmemory *)pstMem; + + ippsZero_32f(pstState->ResidualMemory,RESISDUAL_MEMORY); + ippsZero_32f(pstState->STPMemory,BWD_LPC_ORDER); + ippsZero_32f(pstState->STPNumCoeff,SHORTTERM_POSTFLT_LEN_E); + ippsZero_32f(pstState->ZeroMemory,BWD_LPC_ORDER); + + pstState->gainPrec = 1.; +} + +static __ALIGN32 CONST Ipp32f STPTbl[SIZE_SHORT_INT_FLT_MEMORY] = { +(Ipp32f) -0.005772, (Ipp32f) 0.087669, (Ipp32f) 0.965882, (Ipp32f) -0.048753, +(Ipp32f) -0.014793, (Ipp32f) 0.214886, (Ipp32f) 0.868791, (Ipp32f) -0.065537, +(Ipp32f) -0.028507, (Ipp32f) 0.374334, (Ipp32f) 0.723418, (Ipp32f) -0.060834, +(Ipp32f) -0.045567, (Ipp32f) 0.550847, (Ipp32f) 0.550847, (Ipp32f) -0.045567, +(Ipp32f) -0.060834, (Ipp32f) 0.723418, (Ipp32f) 0.374334, (Ipp32f) -0.028507, +(Ipp32f) -0.065537, (Ipp32f) 0.868791, (Ipp32f) 0.214886, (Ipp32f) -0.014793, +(Ipp32f) -0.048753, (Ipp32f) 0.965882, (Ipp32f) 0.087669, (Ipp32f) -0.005772}; + +static __ALIGN32 CONST Ipp32f LTPTbl[SIZE_LONG_INT_FLT_MEMORY] = { +(Ipp32f) -0.001246, (Ipp32f) 0.002200, (Ipp32f) -0.004791, (Ipp32f) 0.009621, +(Ipp32f) -0.017685, (Ipp32f) 0.031212, (Ipp32f) -0.057225, (Ipp32f) 0.135470, +(Ipp32f) 0.973955, (Ipp32f) -0.103495, (Ipp32f) 0.048663, (Ipp32f) -0.027090, +(Ipp32f) 0.015280, (Ipp32f) -0.008160, (Ipp32f) 0.003961, (Ipp32f) -0.001827, +(Ipp32f) -0.002388, (Ipp32f) 0.004479, (Ipp32f) -0.009715, (Ipp32f) 0.019261, +(Ipp32f) -0.035118, (Ipp32f) 0.061945, (Ipp32f) -0.115187, (Ipp32f) 0.294161, +(Ipp32f) 0.898322, (Ipp32f) -0.170283, (Ipp32f) 0.083211, (Ipp32f) -0.046645, +(Ipp32f) 0.026210, (Ipp32f) -0.013854, (Ipp32f) 0.006641, (Ipp32f) -0.003099, +(Ipp32f) -0.003277, (Ipp32f) 0.006456, (Ipp32f) -0.013906, (Ipp32f) 0.027229, +(Ipp32f) -0.049283, (Ipp32f) 0.086990, (Ipp32f) -0.164590, (Ipp32f) 0.464041, +(Ipp32f) 0.780309, (Ipp32f) -0.199879, (Ipp32f) 0.100795, (Ipp32f) -0.056792, +(Ipp32f) 0.031761, (Ipp32f) -0.016606, (Ipp32f) 0.007866, (Ipp32f) -0.003740, +(Ipp32f) -0.003770, (Ipp32f) 0.007714, (Ipp32f) -0.016462, (Ipp32f) 0.031849, +(Ipp32f) -0.057272, (Ipp32f) 0.101294, (Ipp32f) -0.195755, (Ipp32f) 0.630993, +(Ipp32f) 0.630993, (Ipp32f) -0.195755, (Ipp32f) 0.101294, (Ipp32f) -0.057272, +(Ipp32f) 0.031849, (Ipp32f) -0.016462, (Ipp32f) 0.007714, (Ipp32f) -0.003770, +(Ipp32f) -0.003740, (Ipp32f) 0.007866, (Ipp32f) -0.016606, (Ipp32f) 0.031761, +(Ipp32f) -0.056792, (Ipp32f) 0.100795, (Ipp32f) -0.199879, (Ipp32f) 0.780309, +(Ipp32f) 0.464041, (Ipp32f) -0.164590, (Ipp32f) 0.086990, (Ipp32f) -0.049283, +(Ipp32f) 0.027229, (Ipp32f) -0.013906, (Ipp32f) 0.006456, (Ipp32f) -0.003277, +(Ipp32f) -0.003099, (Ipp32f) 0.006641, (Ipp32f) -0.013854, (Ipp32f) 0.026210, +(Ipp32f) -0.046645, (Ipp32f) 0.083211, (Ipp32f) -0.170283, (Ipp32f) 0.898322, +(Ipp32f) 0.294161, (Ipp32f) -0.115187, (Ipp32f) 0.061945, (Ipp32f) -0.035118, +(Ipp32f) 0.019261, (Ipp32f) -0.009715, (Ipp32f) 0.004479, (Ipp32f) -0.002388, +(Ipp32f) -0.001827, (Ipp32f) 0.003961, (Ipp32f) -0.008160, (Ipp32f) 0.015280, +(Ipp32f) -0.027090, (Ipp32f) 0.048663, (Ipp32f) -0.103495, (Ipp32f) 0.973955, +(Ipp32f) 0.135470, (Ipp32f) -0.057225, (Ipp32f) 0.031212, (Ipp32f) -0.017685, +(Ipp32f) 0.009621, (Ipp32f) -0.004791, (Ipp32f) 0.002200, (Ipp32f) -0.001246 +}; + +static void HarmonicPostFilter_G729_32f(Ipp32s valPitchDelay, Ipp32f *pSrc, Ipp32f *pDst, + Ipp32s *isVoiced, Ipp32f valHarmonicCoeff, Ipp32f *mem); +static void SearchDelay(Ipp32s valPitchDelay, Ipp32f *pSrcSignal, Ipp32s *LTPDelay, Ipp32s *lPhase, + Ipp32f *LTPGainNumerator, Ipp32f *LTPGainDemerator, Ipp32f *pSignal, Ipp32s *lOffset, Ipp32f *mem); +static void HarmonicFilter_G729_32f(Ipp32f *pSrcSignal, Ipp32f *pSrcFltSignal, Ipp32f *pDstSignal, Ipp32f valFltGain); +static void TiltCompensation_G729_32f(Ipp32f *pSrcSignal, Ipp32f *pDstSignal, Ipp32f val); +static void Calc1stParcor(Ipp32f *pSrcImpulseResponse, Ipp32f *pDstPartialCorrCoeff, Ipp32s len); +static void GainControl_G729(Ipp32f *pSrcSignal, Ipp32f *pDstSignal, Ipp32f *pSrcDstGain, Ipp32f *mem); + +void Post_G729E(G729FPDecoder_Obj *decoderObj, Ipp32s pitchDelay, Ipp32f *pSignal, Ipp32f *pLPC, Ipp32f *pDstFltSignal, Ipp32s *pVoicing, + Ipp32s len, Ipp32s lenLPC, Ipp32s Vad) +{ + LOCAL_ALIGN_ARRAY(32, Ipp32f, STPDenCoeff, BWD_LPC_ORDERP1,decoderObj); + LOCAL_ALIGN_ARRAY(32, Ipp32f, LTPSignal, SUBFR_LENP1,decoderObj); + LOCAL_ALIGN_ARRAY(32, Ipp32f, mem,SIZE_SEARCH_DEL_MEMORY+2*(FRAC_DELAY_RES-1),decoderObj); + Ipp32f *pLTPSignal; + Ipp32f f1stParcor,fG0, fTmp; + Ipp32f *pResidual; + Ipp32f *pSTPMemory; + Ipp32s i; + PSTmemory *pstState = (PSTmemory *)decoderObj->pstMem; + + pResidual = pstState->ResidualMemory + RESISDUAL_MEMORY; + pSTPMemory = pstState->STPMemory + BWD_LPC_ORDER - 1; + + /* Compute weighted LPC coefficients */ + WeightLPCCoeff_G729(pLPC, decoderObj->g1PST, lenLPC, STPDenCoeff); + WeightLPCCoeff_G729(pLPC, decoderObj->g2PST, lenLPC, pstState->STPNumCoeff); + ippsZero_32f(&pstState->STPNumCoeff[lenLPC+1], (BWD_LPC_ORDER-lenLPC)); + /* Compute A(gamma2) residual */ + ippsConvBiased_32f(pstState->STPNumCoeff,lenLPC+1,pSignal,SUBFR_LEN+lenLPC,pResidual,SUBFR_LEN,lenLPC); + + /* Harmonic filtering */ + pLTPSignal = LTPSignal + 1; + + if (Vad > 1) + HarmonicPostFilter_G729_32f(pitchDelay, pResidual, pLTPSignal, pVoicing, decoderObj->gHarmPST,mem); + else { + *pVoicing = 0; + ippsCopy_32f(pResidual, pLTPSignal, SUBFR_LEN); + } + + /* Save last output of 1/A(gamma1) (from preceding subframe) */ + LTPSignal[0] = *pSTPMemory; + + /* Controls Ipp16s term pst filter gain and compute f1stParcor */ + /* compute i.r. of composed filter STPNumCoeff / STPDenCoeff */ + ippsSynthesisFilter_G729_32f(STPDenCoeff, lenLPC, pstState->STPNumCoeff, mem, len, pstState->ZeroMemory); + + /* compute 1st parcor */ + Calc1stParcor(mem, &f1stParcor, len); + + /* compute fG0 */ + fG0 = 0.f; + for(i=0; i (Ipp32f)1.) { + fTmp = (Ipp32f)1./fG0; + ippsMulC_32f_I(fTmp, pLTPSignal, SUBFR_LEN); + } + + /* 1/A(gamma1) filtering, STPMemory is updated */ + ippsSynthesisFilter_G729_32f(STPDenCoeff, lenLPC, pLTPSignal, pLTPSignal, SUBFR_LEN, &pstState->STPMemory[BWD_LPC_ORDER-lenLPC]); + ippsCopy_32f(&pLTPSignal[SUBFR_LEN-BWD_LPC_ORDER], pstState->STPMemory, BWD_LPC_ORDER); + + /* Tilt filtering with : (1 + mu z-1) * (1/1-|mu|)*/ + TiltCompensation_G729_32f(LTPSignal, pDstFltSignal, f1stParcor); + + /* Gain control */ + GainControl_G729(pSignal, pDstFltSignal, &pstState->gainPrec,mem); + + /**** Update for next subframe */ + ippsMove_32f(&pstState->ResidualMemory[SUBFR_LEN], &pstState->ResidualMemory[0], RESISDUAL_MEMORY); + + LOCAL_ALIGN_ARRAY_FREE(32, Ipp32f, mem,SIZE_SEARCH_DEL_MEMORY+2*(FRAC_DELAY_RES-1),decoderObj); + LOCAL_ALIGN_ARRAY_FREE(32, Ipp32f, LTPSignal, SUBFR_LENP1,decoderObj); /* H0 output signal */ + LOCAL_ALIGN_ARRAY_FREE(32, Ipp32f, STPDenCoeff, BWD_LPC_ORDERP1,decoderObj); /* s.t. denominator coeff. */ + + return; +} + +static void HarmonicPostFilter_G729_32f(Ipp32s valPitchDelay, Ipp32f *pSrc, Ipp32f *pDst, + Ipp32s *isVoiced, Ipp32f valHarmonicCoeff, Ipp32f *mem) +{ + Ipp32s LTPDelay, lPhase; + Ipp32f LTPGainNumerator, LTPGainDenominator; + Ipp32f LTPGainNumerator2, LTPGainDenominator2; + Ipp32f harmFltCoeff; + Ipp32f *pDelayedSignal; + Ipp32s lOffset; + Ipp32f *pSignal = &mem[0]; + Ipp32f *searcgDelMem = &mem[SIZE_SEARCH_DEL_MEMORY]; + + /* Sub optimal delay search */ + SearchDelay(valPitchDelay, pSrc, <PDelay, &lPhase, <PGainNumerator, <PGainDenominator, + pSignal, &lOffset,searcgDelMem); + *isVoiced = LTPDelay; + + if(isVarZero(LTPGainNumerator)) { + ippsCopy_32f(pSrc, pDst, SUBFR_LEN); + } else { + if(lPhase == 0) { + pDelayedSignal = pSrc - LTPDelay; + } else { + Ipp64f z; + /* Filtering with long filter*/ + ippsConvBiased_32f((Ipp32f*)<PTbl[(lPhase-1) * LONG_INT_FLT_LEN], LONG_INT_FLT_LEN, + &pSrc[LONG_INT_FLT_LEN_BY2-LTPDelay], SUBFR_LEN+LONG_INT_FLT_LEN, + pDst, SUBFR_LEN, LONG_INT_FLT_LEN); + + /* Compute fNumerator */ + ippsDotProd_32f64f(pDst, pSrc, SUBFR_LEN, &z); + LTPGainNumerator2 = (Ipp32f)z; + if(LTPGainNumerator2 < 0.0f) LTPGainNumerator2 = 0.0f; + + /* Compute den */ + ippsDotProd_32f(pDst, pDst, SUBFR_LEN, <PGainDenominator2); + + if(isVarZero(LTPGainDenominator2)) { + /* select Ipp16s filter */ + pDelayedSignal = pSignal + ((lPhase-1) * SUBFR_LENP1 + lOffset); + } + if(LTPGainNumerator2 * LTPGainNumerator2 * LTPGainDenominator> LTPGainNumerator * LTPGainNumerator * LTPGainDenominator2) { + /* select long filter */ + LTPGainNumerator = LTPGainNumerator2; + LTPGainDenominator = LTPGainDenominator2; + pDelayedSignal = pDst; + } else { + /* select Ipp16s filter */ + pDelayedSignal = pSignal + ((lPhase-1) * SUBFR_LENP1 + lOffset); + } + } + + if(LTPGainNumerator >= LTPGainDenominator) { + harmFltCoeff = 1.f/(1.f+ valHarmonicCoeff); + } else { + harmFltCoeff = LTPGainDenominator / (LTPGainDenominator + valHarmonicCoeff * LTPGainNumerator); + } + + /** filtering by H0(z) = harmonic filter **/ + HarmonicFilter_G729_32f(pSrc, pDelayedSignal, pDst, harmFltCoeff); + } + + return; +} + +static void SearchDelay(Ipp32s valPitchDelay, Ipp32f *pSrcSignal, Ipp32s *LTPDelay, Ipp32s *lPhase, + Ipp32f *LTPGainNumerator, Ipp32f *LTPGainDemerator, Ipp32f *pSignal, Ipp32s *lOffset, Ipp32f *mem) +{ + Ipp32f *pDen0, *pDen1; + Ipp32s iOfset, i, lLambda; + Ipp32f fNumerator, fSqNumerator, fDenominator0, fDenominator1; + Ipp32f fMaxDenominator, maxNumerator, squaredNumeratorMax; + Ipp32s lMaxPhi; + Ipp32f *pDelayedSignal; + Ipp64f dEnergy, dDenominator, dTmp; + Ipp32f fIntNumerator; + + pDen0 = &mem[0]; + pDen1 = &mem[FRAC_DELAY_RES-1]; + + /* Compute current signal energy */ + ippsDotProd_32f64f(pSrcSignal, pSrcSignal, SUBFR_LEN, &dEnergy); + if(dEnergy < 0.1) { + *LTPGainNumerator = 0.f; + *LTPGainDemerator = 1.f; + *lPhase = 0; + *LTPDelay = 0; + return; + } + + /* Selects best of 3 integer delays: Maximum of 3 numerators around valPitchDelay coder LTP delay*/ + + ippsAutoCorrLagMax_32f(pSrcSignal, SUBFR_LEN, valPitchDelay - 1, valPitchDelay + 2, &fIntNumerator, &lLambda); + + if(fIntNumerator <= 0.) { + *LTPGainNumerator = 0.f; + *LTPGainDemerator = 1.f; + *lPhase = 0; + *LTPDelay = 0; + return; + } + + /* Calculates denominator for lambda_max */ + ippsDotProd_32f64f(&pSrcSignal[-lLambda], &pSrcSignal[-lLambda], SUBFR_LEN, &dDenominator); + if(dDenominator < 0.1) { + *LTPGainNumerator = 0.f; + *LTPGainDemerator = 1.f; + *lPhase = 0; + *LTPDelay = 0; + return; + } + + /* Compute pSignal & denominators */ + pDelayedSignal = pSignal; + fMaxDenominator = (Ipp32f)dDenominator; + + /* loop on lPhase to select the best lPhase around lLambda */ + for(i=0; ifabs(pDelayedSignal[SUBFR_LEN])) { + /* Choose left side*/ + if(fDenominator0 > fMaxDenominator) { + fMaxDenominator = fDenominator0; + } + } else { + /* Choose right side*/ + if(fDenominator1 > fMaxDenominator) { + fMaxDenominator = fDenominator1; + } + } + pDelayedSignal += SUBFR_LENP1; + } + if(fMaxDenominator < 0.1f ) { + *LTPGainNumerator = 0.f; + *LTPGainDemerator = 1.f; + *lPhase = 0; + *LTPDelay = 0; + return; + } + /* Initialization */ + maxNumerator = (Ipp32f)fIntNumerator; + fMaxDenominator = (Ipp32f)dDenominator; + squaredNumeratorMax = maxNumerator * maxNumerator; + lMaxPhi = 0; + iOfset = 1; + + pDelayedSignal = pSignal; + + /* if fMaxDenominator = 0 or fNumerator!=0 & den=0: will be selected and declared unvoiced */ + /* Loop on lPhase */ + for(i=0; i<(FRAC_DELAY_RES-1); i++) { + + /* computes fNumerator for lambda_max+1 - i/FRAC_DELAY_RES */ + ippsDotProd_32f64f(pSrcSignal, pDelayedSignal, SUBFR_LEN, &dTmp); + + if(dTmp < 0.) fNumerator = (Ipp32f)0.; + else fNumerator = (Ipp32f)dTmp; + fSqNumerator = fNumerator * fNumerator; + + /* selection if fNumerator/sqrt(fDenominator0) max */ + if((fSqNumerator * fMaxDenominator) > (squaredNumeratorMax * pDen0[i])) { + maxNumerator = fNumerator; + squaredNumeratorMax = fSqNumerator; + fMaxDenominator = pDen0[i]; + iOfset = 0; + lMaxPhi = i+1; + } + + /* computes fNumerator for lambda_max - phi/FRAC_DELAY_RES */ + + ippsDotProd_32f64f(pSrcSignal, &pDelayedSignal[1], SUBFR_LEN, &dTmp); + if(dTmp < 0.) fNumerator = (Ipp32f)0.; + else fNumerator = (Ipp32f)dTmp; + + fSqNumerator = fNumerator * fNumerator; + + /* selection if fNumerator/sqrt(fDenominator1) max */ + if((fSqNumerator * fMaxDenominator) > (squaredNumeratorMax * pDen1[i])) { + maxNumerator = fNumerator; + squaredNumeratorMax = fSqNumerator; + fMaxDenominator = pDen1[i]; + iOfset = 1; + lMaxPhi = i+1; + } + pDelayedSignal += (SUBFR_LEN+1); + } + + if(isVarZero(maxNumerator) || (fMaxDenominator <= 0.1f)) { + *LTPGainNumerator = 0.f; + *LTPGainDemerator = 1.f; + *lPhase = 0; + *LTPDelay = 0; + return; + } + + /* comparison numerator**2 with energy*denominator*Threshold */ + if(squaredNumeratorMax >= (fMaxDenominator * dEnergy * LTPTHRESHOLD)) { + *LTPDelay = lLambda + 1 - iOfset; + *lOffset = iOfset; + *lPhase = lMaxPhi; + *LTPGainNumerator = maxNumerator; + *LTPGainDemerator = fMaxDenominator; + } else { + *LTPGainNumerator = 0.f; + *LTPGainDemerator = 1.f; + *lPhase = 0; + *LTPDelay = 0; + } + return; +} + +static void HarmonicFilter_G729_32f(Ipp32f *pSrcSignal, Ipp32f *pSrcFltSignal, Ipp32f *pDstSignal, Ipp32f valFltGain) +{ + Ipp32f valFltGainNeg; + + valFltGainNeg = 1.f - valFltGain; + + ippsInterpolateC_G729_32f(pSrcSignal, valFltGain, pSrcFltSignal, valFltGainNeg, pDstSignal, SUBFR_LEN); + + return; +} + +static void Calc1stParcor(Ipp32f *pSrcImpulseResponse, Ipp32f *pDstPartialCorrCoeff, Ipp32s len) +{ + Ipp32f firstCorr, secondCorr; + Ipp64f dTmp; + + /* computation of the autocorrelation of the impulse response*/ + ippsDotProd_32f64f(pSrcImpulseResponse, pSrcImpulseResponse, len, &dTmp); + firstCorr = (Ipp32f)dTmp; + + ippsDotProd_32f64f(pSrcImpulseResponse, &pSrcImpulseResponse[1], len-1, &dTmp); + secondCorr = (Ipp32f)dTmp; + + if(isVarZero(firstCorr)) { + *pDstPartialCorrCoeff = 0.f; + return; + } + + /* Compute 1st parcor */ + if(firstCorr < (Ipp32f)fabs(secondCorr) ) { + *pDstPartialCorrCoeff = 0.0f; + return; + } + *pDstPartialCorrCoeff = - secondCorr / firstCorr; + + return; +} + +static void TiltCompensation_G729_32f(Ipp32f *pSrcSignal, Ipp32f *pDstSignal, Ipp32f val) +{ + Ipp32s n; + Ipp32f fMu, fGamma, fTmp; + + if(val > 0.f) { + fMu = val * GAMMA3_POSTFLT_P; + } + else { + fMu = val * GAMMA3_POSTFLT_M; + } + fGamma = 1.f / (1.f - (Ipp32f)fabs(fMu)); + + /* points on pSrcSignal(-1) */ + for(n=0; n +#include +#include "g729fpapi.h" +#include "scratchmem.h" + +#define ENC_KEY 0xecd729 +#define DEC_KEY 0xdec729 + +#define G729FP_ENCODER_SCRATCH_MEMORY_SIZE (2*7168+40) + +#define SPEECH_BUFF_LEN 240 /* Total size of speech buffer */ +#define FRM_LEN 80 /* LPC update frame size */ +#define SUBFR_LEN 40 /* Sub-frame size */ +#define NUN_SUBFRAMES FRM_LEN/SUBFR_LEN + +#define WINDOW_LEN 240 /* LPC analysis window size */ +#define LOOK_AHEAD_LEN 40 /* Samples of next frame needed for LPC ana. */ + +#define LPC_ORDER 10 /* LPC order */ +#define LPC_ORDERP1 (LPC_ORDER+1) /* LPC order+1 */ + +#define MOVING_AVER_ORDER 4 /* MA prediction order for LSP */ +#define N_BITS_1ST_STAGE 7 /* number of bits in first stage for LSP index */ +#define N_ELEM_1ST_STAGE (1<0 */ +#define GAMMA3_POSTFLT_M (Ipp32f)0.9 /* tilt weighting factor when k1<0 */ + +/* long term pst parameters : */ +#define SUBFR_LENP1 (SUBFR_LEN + 1) /* Sub-frame size + 1 */ +#define FRAC_DELAY_RES 8 /* resolution for fractionnal delay */ + +#define SHORT_INT_FLT_LEN 4 /* length of Ipp16s interp. subfilters */ +#define LONG_INT_FLT_LEN 16 /* length of long interp. subfilters */ +#define SHORT_INT_FLT_LEN_BY2 (SHORT_INT_FLT_LEN/2) +#define LONG_INT_FLT_LEN_BY2 (LONG_INT_FLT_LEN/2) + +#define LTPTHRESHOLD (Ipp32f)0.5f /* threshold LT to switch off postfilter */ +#define AGC_FACTOR (Ipp32f)0.9875 /* gain adjustment factor */ + +#define AGC_FACTORM1 ((Ipp32f)1. - AGC_FACTOR) /* gain adjustment factor */ + +/* Array sizes */ +#define RESISDUAL_MEMORY (PITCH_LAG_MAX + 1 + LONG_INT_FLT_LEN_BY2) +#define SIZE_RESISDUAL_MEMORY (RESISDUAL_MEMORY + SUBFR_LEN) +#define SIZE_SEARCH_DEL_MEMORY ((FRAC_DELAY_RES-1) * SUBFR_LENP1) +#define SIZE_LONG_INT_FLT_MEMORY ((FRAC_DELAY_RES-1) * LONG_INT_FLT_LEN) +#define SIZE_SHORT_INT_FLT_MEMORY ((FRAC_DELAY_RES-1) * SHORT_INT_FLT_LEN) + +#define G729D_MODE 0 /* Low rate (6400 bit/s) */ +#define G729_BASE 1 /* Full rate (8000 bit/s) */ +#define G729E_MODE 2 /* High rate (11800 bit/s) */ + +/* backward LPC analysis parameters */ +#define BWD_LPC_ORDER 30 /* Order of Backward LP filter. */ +#define BWD_LPC_ORDERP1 (BWD_LPC_ORDER+1) /* Order of Backward LP filter + 1 */ +#define NON_RECURSIVE_PART 35 +#define BWD_SYNTH_MEM (BWD_LPC_ORDER + NON_RECURSIVE_PART) +#define BWD_ANALISIS_WND_LEN (FRM_LEN + BWD_SYNTH_MEM) +#define BWD_GAMMA 0.98f + +/* Annex E adaptive Ipp16s term postfilter parameters:*/ +#define GAMMA1_POSTFLT_E 0.7f /* denominator weighting factor */ +#define GAMMA2_POSTFLT_E 0.65f /* numerator weighting factor */ +#define SHORTTERM_POSTFLT_LEN_E 32 /* Lenght of the impulse response*/ +#define GAMMA_HARM_POSTFLT_E 0.25f +#define GAMMA_HARM_POSTFLT 0.5f + +/* Constants for backward/forward decision*/ +#define THRES_ENERGY 40.f /*Low energy frame threshold*/ +/* Gains levels */ +#define TH1 1.f +#define TH2 2.f +#define TH3 3.f +#define TH4 4.f +#define TH5 4.7f +#define GAP_FACT (Ipp32f)0.000114375f +#define INVERSE_LOG2 (Ipp32f) (1./log10(2.)) + +/*Constants for gain quantization.*/ +#define MEAN_ENER (Ipp32f)36.0 /* average innovation energy */ +#define NCODE1_BITS 3 /* number of Codebook-bit */ +#define NCODE2_BITS 4 /* number of Codebook-bit */ +#define SIZECODEBOOK1 (1<maxValue) value=maxValue + +#define CLIP_TO_LOWLEVEL(value,minValue)\ + if(value> 1; + sum = 1; + for (nBits = 0; nBits <= 5; nBits++) { + temp = temp >> 1; + bit = temp & 0x00000001; + sum += bit; + } + sum = sum & 0x00000001; + + return sum; +} + +__INLINE Ipp16s Rand_16s(Ipp16s *seed) +{ + *seed = (Ipp16s)(*seed * 31821 + 13849); + return(*seed); +} + +static __ALIGN32 CONST Ipp16s modtab[]={1, 2, 0, 1, 2, 0, 1, 2}; + +__INLINE void DecodeAdaptCodebookDelays(Ipp32s *prevPitchDelay, Ipp32s *prevFracPitchDelay,Ipp32s *delayLine, + Ipp32s NSbfr, Ipp32s badPitch,Ipp32s pitchIndx,G729Codec_Type type){ + Ipp16s minPitchDelay, maxPitchDelay; + + if(badPitch == 0){ + + if (NSbfr == 0) /* if 1st subframe */ + { + if (pitchIndx < 197) + { + delayLine[0] = (pitchIndx+2)/3 + 19; + delayLine[1] = pitchIndx - delayLine[0] * 3 + 58; + } + else + { + delayLine[0] = pitchIndx - 112; + delayLine[1] = 0; + } + + } else {/* second subframe */ + /* find minPitchDelay and maxPitchDelay for 2nd subframe */ + minPitchDelay = (Ipp16s)(delayLine[0] - 5); + CLIP_TO_LOWLEVEL(minPitchDelay,PITCH_LAG_MIN); + + maxPitchDelay = (Ipp16s)(minPitchDelay + 9); + if (maxPitchDelay > PITCH_LAG_MAX) + { + maxPitchDelay = PITCH_LAG_MAX; + minPitchDelay = (Ipp16s)(maxPitchDelay - 9); + } + if (type == G729D_MODE) { + pitchIndx = pitchIndx & 15; + if (pitchIndx <= 3) { + delayLine[0] = minPitchDelay + pitchIndx; + delayLine[1] = 0; + } + else if (pitchIndx < 12) { + /* *T0_frac = index % 3; */ + delayLine[1] = modtab[pitchIndx - 4]; + delayLine[0] = (pitchIndx - delayLine[1])/3 + minPitchDelay + 2; + + if (delayLine[1] == 2) { + delayLine[1] = -1; + delayLine[0] += 1; + } + } + else { + delayLine[0] = minPitchDelay + pitchIndx - 6; + delayLine[1] = 0; + } + + } + else { + delayLine[0] = minPitchDelay + (pitchIndx + 2)/3 - 1; + delayLine[1] = pitchIndx - 2 - 3 * ((pitchIndx + 2)/3 - 1); + } + } + *prevPitchDelay = delayLine[0]; + *prevFracPitchDelay = delayLine[1]; + }else { /* Bad frame, or parity error */ + delayLine[0] = *prevPitchDelay; + if (type == G729E_MODE) { + delayLine[1] = *prevFracPitchDelay; + } + else { + delayLine[1] = 0; + *prevPitchDelay += 1; + CLIP_TO_UPLEVEL(*prevPitchDelay,PITCH_LAG_MAX); + } + } +} + +void CodewordImpConv_G729_32f(Ipp32s index, const Ipp32f *pSrc1,const Ipp32f *pSrc2,Ipp32f *pDst); + +#define isVarZero(var) (fabs(var) < IPP_MINABS_32F) + +#endif /* __OWNG729FP_H__ */ diff --git a/scratchmem.h b/scratchmem.h new file mode 100644 index 0000000..f776fae --- /dev/null +++ b/scratchmem.h @@ -0,0 +1,170 @@ +/***************************************************************************** +// +// 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-2007 Intel Corporation. All Rights Reserved. +// +// Intel(R) Integrated Performance Primitives +// +// USCI - Unified Speech Codec Interface +// +// Purpose: Scratch memory managment header file. +***************************************************************************/ + +#ifndef __SCRATCHMEM_H__ +#define __SCRATCHMEM_H__ + +/* Define NULL pointer value */ +#ifndef NULL +#ifdef __cplusplus +#define NULL 0 +#else +#define NULL ((void *)0) +#endif +#endif + +#if defined(__ICC) || defined( __ICL ) || defined ( __ECL ) + #define __INLINE static __inline +#elif defined( __GNUC__ ) + #define __INLINE static __inline__ +#else + #define __INLINE static +#endif + +#if defined(__ICL ) || defined ( __ECL ) +/* Intel C/C++ compiler bug for __declspec(align(8)) !!! */ + #define __ALIGN(n) __declspec(align(16)) + #define __ALIGN32 __declspec(align(32)) +#else + #define __ALIGN(n) + #define __ALIGN32 +#endif + +#if (defined (_WIN64) || defined(linux64) || defined(linux32e)) && !defined(_WIN32_WCE) +__INLINE +Ipp64s IPP_INT_PTR( const void* ptr ) { + union { + void* Ptr; + Ipp64s Int; + } dd; + dd.Ptr = (void*)ptr; + return dd.Int; +} +__INLINE +Ipp64u IPP_UINT_PTR( const void* ptr ) { + union { + void* Ptr; + Ipp64u Int; + } dd; + dd.Ptr = (void*)ptr; + return dd.Int; +} +#elif (defined(_WIN32) || defined(linux32)) && !defined(_WIN32_WCE) +__INLINE +Ipp32s IPP_INT_PTR( const void* ptr ) { + union { + void* Ptr; + Ipp32s Int; + } dd; + dd.Ptr = (void*)ptr; + return dd.Int; +} + +__INLINE +Ipp32u IPP_UINT_PTR( const void* ptr ) { + union { + void* Ptr; + Ipp32u Int; + } dd; + dd.Ptr = (void*)ptr; + return dd.Int; +} +#else + #define IPP_INT_PTR( ptr ) ( (long)(ptr) ) + #define IPP_UINT_PTR( ptr ) ( (Ipp32u long)(ptr) ) +#endif + +#define IPP_BYTES_TO_ALIGN(ptr, align) ((-(IPP_INT_PTR(ptr)&((align)-1)))&((align)-1)) + +#define IPP_ALIGNED_PTR(ptr, align) (void*)( (Ipp8s*)(ptr) + (IPP_BYTES_TO_ALIGN( ptr, align )) ) + +#define IPP_MALLOC_ALIGNED_BYTES 32 + +#define IPP_MALLOC_ALIGNED_0BYTES 0 +#define IPP_MALLOC_ALIGNED_1BYTES 1 +#define IPP_MALLOC_ALIGNED_8BYTES 8 +#define IPP_MALLOC_ALIGNED_16BYTES 16 +#define IPP_MALLOC_ALIGNED_32BYTES 32 + +#define IPP_ALIGNED_ARRAY(align,arrtype,arrname,arrlength)\ + arrtype arrname##AlignedArrBuff[(arrlength)+IPP_MALLOC_ALIGNED_##align##BYTES/sizeof(arrtype)];\ + arrtype *arrname = (arrtype*)IPP_ALIGNED_PTR(arrname##AlignedArrBuff,align) + +__INLINE void* GetMemory(Ipp32s arrlen, Ipp32s sizeOfElem, Ipp8s **CurPtr) +{ + void *ret; + + ret = (void*)IPP_ALIGNED_PTR(*CurPtr,sizeOfElem); + *CurPtr += (arrlen+1)*sizeOfElem; + + return ret; +} + +__INLINE void* GetAlignMemory(Ipp32s align, Ipp32s arrlen, Ipp32s sizeOfElem, Ipp8s **CurPtr) +{ + void *ret; + + ret = (void*)IPP_ALIGNED_PTR(*CurPtr,align); + *CurPtr += (arrlen+align/sizeOfElem)*sizeOfElem; + + return ret; +} + + +typedef struct _ScratchMem_Obj { + Ipp8s *base; + Ipp8s *CurPtr; + Ipp32s *VecPtr; + Ipp32s offset; +}ScratchMem_Obj; + + #define LOCAL_ALIGN_ARRAY(align,arrtype,arrname,arrlength,obj)\ + arrtype *arrname = (arrtype *)GetAlignMemory(align,arrlength,sizeof(arrtype),&(obj)->Mem.CurPtr) + + #define LOCAL_ARRAY(arrtype,arrname,arrlength,obj)\ + arrtype *arrname = (arrtype *)GetMemory(arrlength,sizeof(arrtype),&(obj)->Mem.CurPtr) + + #define LOCAL_ARRAY_FREE(arrtype,arrname,arrlength,obj)\ + arrname=NULL;\ + (obj)->Mem.CurPtr -= ((arrlength)+1)*sizeof(arrtype) + + #define LOCAL_ALIGN_ARRAY_FREE(align,arrtype,arrname,arrlength,obj)\ + arrname=NULL;\ + (obj)->Mem.CurPtr -= ((arrlength)+IPP_MALLOC_ALIGNED_##align##BYTES/sizeof(arrtype))*sizeof(arrtype) + + #define CLEAR_SCRATCH_MEMORY(obj)\ + (obj)->Mem.CurPtr = (obj)->Mem.base + + #define OPEN_SCRATCH_BLOCK(obj)\ + (obj)->Mem.VecPtr[(obj)->Mem.offset] = IPP_INT_PTR((obj)->Mem.CurPtr);\ + (obj)->Mem.offset++ + + #define CLOSE_SCRATCH_BLOCK(obj)\ + (obj)->Mem.offset--;\ + (obj)->Mem.CurPtr = (Ipp8s *)(obj)->Mem.VecPtr[(obj)->Mem.offset] + + +#ifdef CONST + #undef CONST +#endif + +/*#if (_IPP_ARCH == _IPP_ARCH_XSC) + #define CONST +#else + #define CONST const +#endif*/ +#define CONST + +#endif /* __SCRATCHMEM_H__ */ diff --git a/vadg723.c b/vadg723.c new file mode 100644 index 0000000..df28feb --- /dev/null +++ b/vadg723.c @@ -0,0 +1,187 @@ +/*///////////////////////////////////////////////////////////////////////////// +// +// 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-2008 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 ippEULA.rtf or ippEULA.txt 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: G723 VAD functions. +// +*/ + +#include "vadg723.h" +#include "aux_fnxs.h" + +/* + Name: VoiceActivityDetectSize + + Purpose: VAD decision memory size query + pVADmem pointer to the VAD decision memory +*/ +void VoiceActivityDetectSize_G723(Ipp32s* pVADsize) +{ + + *pVADsize = sizeof(G723VADmemory); + *pVADsize = (*pVADsize+7)&(~7); +} +/* + Name: VoiceActivityDetectInit + + Purpose: VAD decision memory init + pVADmem pointer to the VAD decision memory +*/ + +void VoiceActivityDetectInit_G723(Ipp8s* pVADmem) +{ + G723VADmemory* vadMem = (G723VADmemory*)pVADmem; + + + vadMem->HangoverCounter = 3; + vadMem->VADCounter = 0; + vadMem->PrevEnergy = 0x400; + vadMem->NoiseLevel = 0x400; + + vadMem->AdaptEnableFlag = 0; + + vadMem->OpenLoopDelay[0] = 1; + vadMem->OpenLoopDelay[1] = 1; + +} + +static __ALIGN32 CONST Ipp32s LogAdd_Tbl[11] = { + 300482560, 300482560, 300482560, 300482560,337149952,378273792,424443904,476217344,534315008,599523328,672694272 +}; +static __ALIGN32 CONST Ipp16s LogMul_Tbl[11] = { + 0, 0, 0, 0, 1119, 1255, 1409, 1580, 1773, 1990, 2233 +}; + +void VoiceActivityDetect_G723(const Ipp16s *pSrc, const Ipp16s *pNoiseLPC, + const Ipp16s *pOpenLoopDelay, Ipp32s SineWaveDetector, Ipp32s *pVADDecision, Ipp32s *pAdaptEnableFlag, Ipp8s* pVADmem, Ipp16s *AlignBuff) +{ + G723VADmemory* vadMem = (G723VADmemory*)pVADmem; + Ipp32s i, j, lTmp0, lTmp1; + Ipp16s sTmp0, sTmp1, sNmult, MinOLP; + + Ipp32s VADResult = 1 ; + + vadMem->OpenLoopDelay[2] = pOpenLoopDelay[0] ; + vadMem->OpenLoopDelay[3] = pOpenLoopDelay[1] ; + + /* Find Minimum pitch period */ + MinOLP = G723_MAX_PITCH ; + for ( i = 0 ; i < 4 ; i ++ ) { + if ( MinOLP > vadMem->OpenLoopDelay[i] ) + MinOLP = vadMem->OpenLoopDelay[i] ; + } + + /* How many olps are multiplies of their min */ + sNmult = 0 ; + for ( i = 0 ; i < 4 ; i++ ) { + sTmp1 = MinOLP ; + for ( j = 0 ; j < 8 ; j++ ) { + sTmp0 = (Ipp16s)(sTmp1 - vadMem->OpenLoopDelay[i]); + if(sTmp0 < 0) sTmp0 = (Ipp16s)(-sTmp0); + if ( sTmp0 <= 3 ) sNmult++ ; + sTmp1 = (Ipp16s)(sTmp1 + MinOLP); + } + } + + /* Update adaptation enable counter if not periodic and not sine and clip it.*/ + if ( (sNmult == 4) || (SineWaveDetector == -1) ) + if(vadMem->AdaptEnableFlag > 5) vadMem->AdaptEnableFlag = 6; + else vadMem->AdaptEnableFlag += 2; + else + if ( vadMem->AdaptEnableFlag < 1 ) vadMem->AdaptEnableFlag = 0; + else vadMem->AdaptEnableFlag--; + + /* Inverse filter the data */ + + ippsResidualFilter_AMRWB_16s_Sfs(pNoiseLPC, G723_LPC_ORDER, &pSrc[G723_SBFR_LEN], AlignBuff, G723_FRM_LEN-G723_SBFR_LEN, 14); + ippsDotProd_16s32s_Sfs(AlignBuff,AlignBuff,G723_FRM_LEN-G723_SBFR_LEN,&lTmp1,-1); + + /* Scale the residual energy */ + lTmp1 = MulC_32s(2913, lTmp1 ) ; + /* Clip noise level */ + if ( vadMem->NoiseLevel > vadMem->PrevEnergy ) { + lTmp0 = vadMem->PrevEnergy - (vadMem->PrevEnergy>>2); + vadMem->NoiseLevel = lTmp0 + (vadMem->NoiseLevel>>2); + } + + + /* Update the noise level */ + if ( !vadMem->AdaptEnableFlag ) { + vadMem->NoiseLevel = vadMem->NoiseLevel + (vadMem->NoiseLevel>>5); + } else { /* Decay NoiseLevel */ + vadMem->NoiseLevel = vadMem->NoiseLevel - (vadMem->NoiseLevel>>11); + } + + /* Update previous energy */ + vadMem->PrevEnergy = lTmp1 ; + + /* CLip Noise Level */ + if ( vadMem->NoiseLevel < 0x80 ) + vadMem->NoiseLevel = 0x80 ; + if ( vadMem->NoiseLevel > 0x1ffff ) + vadMem->NoiseLevel = 0x1ffff ; + + /* Compute the threshold */ + lTmp0 = vadMem->NoiseLevel<<13; + sTmp0 = Norm_32s_Pos_I(&lTmp0); + sTmp1 = (Ipp16s)((lTmp0>>15)& 0x7e00); + + lTmp0 = LogAdd_Tbl[sTmp0] - sTmp1 * LogMul_Tbl[sTmp0]; + sTmp1 = (Ipp16s)(lTmp0 >> 15); + + + sTmp0 = (Ipp16s)(vadMem->NoiseLevel>>2); + lTmp0 = sTmp0*sTmp1; + lTmp0 >>= 10; + + /* threshold */ + if ( lTmp0 > lTmp1 ) + VADResult = 0 ; + + /* update counters */ + if ( VADResult ) { + vadMem->VADCounter++ ; + vadMem->HangoverCounter++ ; + } else { + vadMem->VADCounter-- ; + if ( vadMem->VADCounter < 0 ) + vadMem->VADCounter = 0 ; + } + if ( vadMem->VADCounter >= 2 ) { + vadMem->HangoverCounter = 6 ; + if ( vadMem->VADCounter >= 3 ) + vadMem->VADCounter = 3 ; + } + if ( vadMem->HangoverCounter ) { + VADResult = 1 ; + if ( vadMem->VADCounter == 0 ) + vadMem->HangoverCounter -- ; + } + /* Update periodicity detector */ + vadMem->OpenLoopDelay[0] = vadMem->OpenLoopDelay[2] ; + vadMem->OpenLoopDelay[1] = vadMem->OpenLoopDelay[3] ; + + *pAdaptEnableFlag = vadMem->AdaptEnableFlag; /* adaptation enable counter */ + *pVADDecision = VADResult; /* VAD decision : 0 - noise, 1 - voice */ + +} diff --git a/vadg723.h b/vadg723.h new file mode 100644 index 0000000..1bb3d98 --- /dev/null +++ b/vadg723.h @@ -0,0 +1,56 @@ +/*///////////////////////////////////////////////////////////////////////////// +// +// 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-2007 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 ippEULA.rtf or ippEULA.txt 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: USC VAD G723 header file. +// +*/ +#ifndef __VADG723_H__ +#define __VADG723_H__ + +#include +#include "owng723.h" + +struct _G723VADmemory { + Ipp32s PrevEnergy; + Ipp32s NoiseLevel; + Ipp16s HangoverCounter; + Ipp16s VADCounter; + Ipp32s AdaptEnableFlag; + Ipp16s OpenLoopDelay[4]; +/*--------------*/ + G723_Obj_t objPrm; /* must be on top */ + Ipp16s PrevOpenLoopLags[2]; + Ipp16s prevSidLpc[G723_LPC_ORDERP1]; + Ipp16s SineWaveDetector;/* Sine wave detector */ + G723_FrameType PastFrameType; + Ipp32s HPFltMem[2];/* High pass variables */ + ScratchMem_Obj Mem; +}; + +void VoiceActivityDetectSize_G723(Ipp32s* pVADsize); +void VoiceActivityDetectInit_G723(Ipp8s* pVADmem); +void VoiceActivityDetect_G723(const Ipp16s *pSrc, const Ipp16s *pNoiseLPC, + const Ipp16s *pOpenLoopDelay, Ipp32s SineWaveDetector, Ipp32s *pVADDecision, Ipp32s *pAdaptEnableFlag, Ipp8s* pVADmem, Ipp16s *AlignBuff); + +#endif /*__VADG723_H__*/ diff --git a/vadg729fp.c b/vadg729fp.c new file mode 100644 index 0000000..7385d47 --- /dev/null +++ b/vadg729fp.c @@ -0,0 +1,314 @@ +/*///////////////////////////////////////////////////////////////////////////// +// +// 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-2008 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 ippEULA.rtf or ippEULA.txt 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.729 float VAD functions. +// +*/ + +#include +#include +#include "vadg729fp.h" + +static __ALIGN32 CONST Ipp32f a[14] = { + 1.750000e-03f, -4.545455e-03f, -2.500000e+01f, 2.000000e+01f, + 0.000000e+00f, 8.800000e+03f, 0.000000e+00f, 2.5e+01f, + -2.909091e+01f, 0.000000e+00f, 1.400000e+04f, 0.928571f, + -1.500000e+00f, 0.714285f +}; + +static __ALIGN32 CONST Ipp32f b[14] = { + 0.00085f, 0.001159091f, -5.0f, -6.0f, -4.7f, -12.2f, 0.0009f, + -7.0f, -4.8182f, -5.3f, -15.5f, 1.14285f, -9.0f, -2.1428571f +}; + +static Ipp32s MakeDecision(Ipp32f fLowBandEnergyDiff, Ipp32f fFullBandEnergyDiff, Ipp32f fSpectralDistortion, Ipp32f fZeroCrossingDiff) +{ + /* The spectral distortion vs zero-crossing difference */ + if (fSpectralDistortion > a[0]*fZeroCrossingDiff+b[0]) { + return(VAD_VOICE); + } + if (fSpectralDistortion > a[1]*fZeroCrossingDiff+b[1]) { + return(VAD_VOICE); + } + + /* full-band energy difference vs zero-crossing difference */ + + if (fFullBandEnergyDiff < a[2]*fZeroCrossingDiff+b[2]) { + return(VAD_VOICE); + } + if (fFullBandEnergyDiff < a[3]*fZeroCrossingDiff+b[3]) { + return(VAD_VOICE); + } + if (fFullBandEnergyDiff < b[4]) { + return(VAD_VOICE); + } + + /* full-band energy difference vs the spectral distortion */ + if (fFullBandEnergyDiff < a[5]*fSpectralDistortion+b[5]) { + return(VAD_VOICE); + } + if (fSpectralDistortion > b[6]) { + return(VAD_VOICE); + } + + /* full-band energy difference vs zero-crossing difference */ + if (fFullBandEnergyDiff < a[7]*fZeroCrossingDiff+b[7]) { + return(VAD_VOICE); + } + if (fFullBandEnergyDiff < a[8]*fZeroCrossingDiff+b[8]) { + return(VAD_VOICE); + } + if (fFullBandEnergyDiff < b[9]) { + return(VAD_VOICE); + } + + /* low-band energy difference vs the spectral distortion */ + if (fLowBandEnergyDiff < a[10]*fSpectralDistortion+b[10]) { + return(VAD_VOICE); + } + + /* low-band energy difference vs full-band eneggy difference */ + if (fLowBandEnergyDiff > a[11]*fFullBandEnergyDiff+b[11]) { + return(VAD_VOICE); + } + + if (fLowBandEnergyDiff < a[12]*fFullBandEnergyDiff+b[12]) { + return(VAD_VOICE); + } + if (fLowBandEnergyDiff < a[13]*fFullBandEnergyDiff+b[13]) { + return(VAD_VOICE); + } + + return(VAD_NOISE); +} + +void VADInit(Ipp8s *pVADmem) +{ + VADmemory *vadState = (VADmemory *)pVADmem; + ippsZero_16s((Ipp16s*)vadState,sizeof(VADmemory)>>1) ; + + ippsZero_32f(vadState->MeanLSFVec, LPC_ORDER); + vadState->fMeanFullBandEnergy = 0.0f; + vadState->fMeanLowBandEnergy = 0.0f; + vadState->fMeanEnergy = 0.0f; + vadState->fMeanZeroCrossing = 0.0f; + vadState->lSilenceCounter = 0; + vadState->lUpdateCounter = 0; + vadState->lSmoothingCounter = 0; + vadState->lLessEnergyCounter = 0; + vadState->lFVD = 1; + vadState->fMinEnergy = IPP_MAXABS_32F; + return; +} + +void VADGetSize(Ipp32s *pDstSize) +{ + *pDstSize = sizeof(VADmemory); + return; +} + +static __ALIGN32 CONST Ipp32f ToplAutoCorrMtr[LPC_ORDERP2+1]={ + 0.120089698456645f, 0.21398822343783f, 0.14767692339633f, + 0.07018811903116f, 0.00980856433051f, -0.02015934721195f, + -0.02388269958005f, -0.01480076155002f, -0.00503292155509f, + 0.00012141366508f, 0.00119354245231f, 0.00065908718613f, + 0.00015015782285f +}; + +void VoiceActivityDetect_G729_32f(Ipp32f ReflectCoeff, Ipp32f *pLSF, Ipp32f *pAutoCorr, Ipp32f *pSrc, Ipp32s FrameCounter, + Ipp32s prevDecision, Ipp32s prevPrevDecision, Ipp32s *pVad, Ipp32f *pEnergydB,Ipp8s *pVADmem,Ipp32f *pExtBuff) +{ + Ipp32f *pTmp; + Ipp32f fSpectralDistortion, fFullBandEnergyDiff, fLowBandEnergyDiff, lNumZeroCrossing, fZeroCrossingDiff; + Ipp32f fLowBandEnergy; + Ipp32f fFullBandEnergy; + Ipp32f zeroNum; + Ipp32s i; + static __ALIGN32 CONST Ipp32f vadTable[7][6]={ + /* coeff C_coeff coeffZC C_coeffZC coeffSD C_coeffSD */ + { 0.75f, 0.25f, 0.8f, 0.2f, 0.6f, 0.4f}, + { 0.75f, 0.25f, 0.8f, 0.2f, 0.6f, 0.4f}, + { 0.95f, 0.05f, 0.92f, 0.08f, 0.65f, 0.35f}, + { 0.97f, 0.03f, 0.94f, 0.06f, 0.70f, 0.3f}, + { 0.99f, 0.01f, 0.96f, 0.04f, 0.75f, 0.25f}, + {0.995f, 0.005f, 0.99f, 0.01f, 0.75f, 0.25f}, + {0.995f, 0.005f, 0.998f, 0.002f, 0.75f, 0.25f}, + }; + const Ipp32f *pVadTable; + VADmemory *vadState = (VADmemory *)pVADmem; + + pTmp = &pExtBuff[0]; /*10 elements*/ + + /* compute the frame energy, full-band energy */ + fFullBandEnergy = 10.0f * (Ipp32f) log10( pAutoCorr[0]/240.0f + IPP_MINABS_32F); + *pEnergydB = fFullBandEnergy ; + + /* compute the low-band energy (El)*/ + ippsDotProd_32f(pAutoCorr, ToplAutoCorrMtr, LPC_ORDERP2+1, &fLowBandEnergy); + if (fLowBandEnergy < 0.0f) fLowBandEnergy = 0.0f; + fLowBandEnergy= 10.0f * (Ipp32f) log10((Ipp32f) (fLowBandEnergy/120.0f + IPP_MINABS_32F)); + + /* Normalize line spectral frequences */ + for(i=0; iMeanLSFVec, pTmp, LPC_ORDER); + ippsDotProd_32f(pTmp, pTmp, LPC_ORDER, &fSpectralDistortion); + + /* compute # zero crossing */ + ippsSignChangeRate_32f(&pSrc[ZC_START_INDEX], ZC_END_INDEX+1-ZC_START_INDEX, &zeroNum); + lNumZeroCrossing = zeroNum/80; + + /* Initialize and update min energies */ + if( FrameCounter < 129 ) { + if( fFullBandEnergy < vadState->fMinEnergy ){ + vadState->fMinEnergy = fFullBandEnergy; + vadState->fPrevMinEnergy = fFullBandEnergy; + } + if( (FrameCounter % 8) == 0){ + vadState->MinimumBuff[FrameCounter/8 -1] = vadState->fMinEnergy; + vadState->fMinEnergy = IPP_MAXABS_32F; + } + } + if( (FrameCounter % 8) == 0){ + ippsMin_32f(vadState->MinimumBuff,15,&vadState->fPrevMinEnergy); + } + + if( FrameCounter >= 129 ) { + if( (FrameCounter % 8 ) == 1) { + vadState->fMinEnergy = vadState->fPrevMinEnergy; + vadState->fNextMinEnergy = IPP_MAXABS_32F; + } + if( fFullBandEnergy < vadState->fMinEnergy ) + vadState->fMinEnergy = fFullBandEnergy; + if( fFullBandEnergy < vadState->fNextMinEnergy ) + vadState->fNextMinEnergy = fFullBandEnergy; + if( (FrameCounter % 8) == 0){ + for ( i =0; i< 15; i++) + vadState->MinimumBuff[i] = vadState->MinimumBuff[i+1]; + vadState->MinimumBuff[15] = vadState->fNextMinEnergy; + ippsMin_32f(vadState->MinimumBuff,16,&vadState->fPrevMinEnergy); + + } + } + + if (FrameCounter <= END_OF_INIT){ + if( fFullBandEnergy < 21.0f){ + vadState->lLessEnergyCounter++; + *pVad = VAD_NOISE; + } + else{ + *pVad = VAD_VOICE; + vadState->fMeanEnergy = (vadState->fMeanEnergy*( (Ipp32f)(FrameCounter-vadState->lLessEnergyCounter -1)) + + fFullBandEnergy)/(Ipp32f) (FrameCounter-vadState->lLessEnergyCounter); + vadState->fMeanZeroCrossing = (vadState->fMeanZeroCrossing*( (Ipp32f)(FrameCounter-vadState->lLessEnergyCounter -1)) + + lNumZeroCrossing)/(Ipp32f) (FrameCounter-vadState->lLessEnergyCounter); + ippsInterpolateC_G729_32f(vadState->MeanLSFVec, (Ipp32f)(FrameCounter-vadState->lLessEnergyCounter -1), + pLSF, 1.0f, vadState->MeanLSFVec, LPC_ORDER); + ippsMulC_32f_I(1.0f/(Ipp32f) (FrameCounter-vadState->lLessEnergyCounter ), vadState->MeanLSFVec, LPC_ORDER); + } + } + + if (FrameCounter >= END_OF_INIT ){ + if (FrameCounter == END_OF_INIT ){ + vadState->fMeanFullBandEnergy = vadState->fMeanEnergy - 10.0f; + vadState->fMeanLowBandEnergy = vadState->fMeanEnergy - 12.0f; + } + + fFullBandEnergyDiff = vadState->fMeanFullBandEnergy - fFullBandEnergy; + fLowBandEnergyDiff = vadState->fMeanLowBandEnergy - fLowBandEnergy; + fZeroCrossingDiff = vadState->fMeanZeroCrossing - lNumZeroCrossing; + + if( fFullBandEnergy < 21.0f ){ + *pVad = VAD_NOISE; + } + else{ + *pVad =MakeDecision(fLowBandEnergyDiff, fFullBandEnergyDiff, fSpectralDistortion, fZeroCrossingDiff ); + } + + vadState->lVADFlag =VAD_NOISE; + if( (prevDecision == VAD_VOICE) && (*pVad == VAD_NOISE) && + (fFullBandEnergy > vadState->fMeanFullBandEnergy + 2.0f) && ( fFullBandEnergy > 21.0f)){ + *pVad = VAD_VOICE; + vadState->lVADFlag=VAD_VOICE; + } + + if((vadState->lFVD == 1) ){ + if( (prevPrevDecision == VAD_VOICE) && (prevDecision == VAD_VOICE) && + (*pVad == VAD_NOISE) && (fabs(vadState->fPrevEnergy - fFullBandEnergy)<= 3.0f)){ + vadState->lSmoothingCounter++; + *pVad = VAD_VOICE; + vadState->lVADFlag=VAD_VOICE; + if(vadState->lSmoothingCounter <=4) + vadState->lFVD =1; + else{ + vadState->lFVD =0; + vadState->lSmoothingCounter=0; + } + } + } + else + vadState->lFVD =1; + + if(*pVad == VAD_NOISE) + vadState->lSilenceCounter++; + + if((*pVad == VAD_VOICE) && (vadState->lSilenceCounter > 10) && + ((fFullBandEnergy - vadState->fPrevEnergy) <= 3.0f)){ + *pVad = VAD_NOISE; + vadState->lSilenceCounter=0; + } + + + if(*pVad == VAD_VOICE) + vadState->lSilenceCounter=0; + + if ((fFullBandEnergy < vadState->fMeanFullBandEnergy + 3.0f) && ( FrameCounter >128) + &&( !vadState->lVADFlag) && (ReflectCoeff < 0.6f) ) + *pVad = VAD_NOISE; + + if ((fFullBandEnergy < vadState->fMeanFullBandEnergy + 3.0f) && (ReflectCoeff < 0.75f) && ( fSpectralDistortion < 0.002532959f)){ + vadState->lUpdateCounter++; + i = vadState->lUpdateCounter/10; + if(i>6) i=6; + pVadTable = vadTable[i]; + ippsInterpolateC_G729_32f(vadState->MeanLSFVec, pVadTable[4], + pLSF, (pVadTable[5]), vadState->MeanLSFVec, LPC_ORDER); + vadState->fMeanFullBandEnergy = pVadTable[0]*vadState->fMeanFullBandEnergy+(pVadTable[1])*fFullBandEnergy; + vadState->fMeanLowBandEnergy = pVadTable[0]*vadState->fMeanLowBandEnergy+(pVadTable[1])*fLowBandEnergy; + vadState->fMeanZeroCrossing = pVadTable[2]*vadState->fMeanZeroCrossing+(pVadTable[3])*lNumZeroCrossing; + } + + if((FrameCounter > 128) && ( ( vadState->fMeanFullBandEnergy < vadState->fMinEnergy ) + && ( fSpectralDistortion < 0.002532959f)) || ( vadState->fMeanFullBandEnergy > vadState->fMinEnergy + 10.0f )){ + vadState->fMeanFullBandEnergy = vadState->fMinEnergy; + vadState->lUpdateCounter = 0; + } + } + + vadState->fPrevEnergy = fFullBandEnergy; + return; +} + + + diff --git a/vadg729fp.h b/vadg729fp.h new file mode 100644 index 0000000..cef2c95 --- /dev/null +++ b/vadg729fp.h @@ -0,0 +1,68 @@ +/*///////////////////////////////////////////////////////////////////////////// +// +// 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-2007 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 ippEULA.rtf or ippEULA.txt 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: USC VAD G729fp header file. +// +*/ +#ifndef __VADG729FP_H__ +#define __VADG729FP_H__ + +#include +#include "owng729fp.h" + +struct _G729FPVADmemory_Obj{ + Ipp32f MeanLSFVec[LPC_ORDER]; + Ipp32f MinimumBuff[16]; + Ipp32f fMeanEnergy; + Ipp32f fMeanFullBandEnergy; + Ipp32f fMeanLowBandEnergy; + Ipp32f fMeanZeroCrossing; + Ipp32f fPrevMinEnergy; + Ipp32f fNextMinEnergy; + Ipp32f fMinEnergy; + Ipp32f fPrevEnergy; + Ipp32s lVADFlag; + Ipp32s lSilenceCounter; + Ipp32s lUpdateCounter; + Ipp32s lSmoothingCounter; + Ipp32s lFVD; + Ipp32s lLessEnergyCounter; +/*---------------------------*/ + G729CCoder_Obj objPrm; + ScratchMem_Obj Mem; + Ipp32f OldSpeechBuffer[SPEECH_BUFF_LEN]; + Ipp16s sFrameCounter; /* frame counter for VAD*/ + Ipp32s prevVADDec; + Ipp32s prevPrevVADDec; + Ipp32f OldLSP[LPC_ORDER]; + Ipp32f OldForwardLPC[LPC_ORDERP1]; + Ipp32f OldForwardRC[2]; +}; + +void VADInit(Ipp8s *vadMem); +void VADGetSize(Ipp32s *pDstSize); +void VoiceActivityDetect_G729_32f(Ipp32f ReflectCoeff, Ipp32f *pLSF, Ipp32f *pAutoCorr, Ipp32f *pSrc, Ipp32s FrameCounter, + Ipp32s prevDecision, Ipp32s prevPrevDecision, Ipp32s *pVad, Ipp32f *pEnergydB,Ipp8s *pVADmem,Ipp32f *pExtBuff); + +#endif /*__VADG729FP_H__*/