From f6107ad865e959e910f89198848cca721bf8ed0b Mon Sep 17 00:00:00 2001 From: "Vasily i. Redkin" Date: Wed, 2 Feb 2011 10:35:38 +0300 Subject: [PATCH] Importing original source yate-g72x.tar.bz2 from yate.hosting.lv --- aux_fnxs.h | 323 +++++++ aux_tbls.c | 95 +++ build.sh | 57 ++ decg723.c | 325 +++++++ decg729fp.c | 1132 +++++++++++++++++++++++++ encg723.c | 721 ++++++++++++++++ encg729fp.c | 1475 ++++++++++++++++++++++++++++++++ g723api.h | 112 +++ g723codec.cpp | 249 ++++++ g723ipp.h | 36 + g729codec.cpp | 229 +++++ g729fpapi.h | 109 +++ owng723.c | 1405 +++++++++++++++++++++++++++++++ owng723.h | 195 +++++ owng729fp.c | 2247 +++++++++++++++++++++++++++++++++++++++++++++++++ owng729fp.h | 580 +++++++++++++ scratchmem.h | 170 ++++ vadg723.c | 187 ++++ vadg723.h | 56 ++ vadg729fp.c | 314 +++++++ vadg729fp.h | 68 ++ 21 files changed, 10085 insertions(+) create mode 100644 aux_fnxs.h create mode 100644 aux_tbls.c create mode 100755 build.sh create mode 100644 decg723.c create mode 100644 decg729fp.c create mode 100644 encg723.c create mode 100644 encg729fp.c create mode 100644 g723api.h create mode 100644 g723codec.cpp create mode 100644 g723ipp.h create mode 100644 g729codec.cpp create mode 100644 g729fpapi.h create mode 100644 owng723.c create mode 100644 owng723.h create mode 100644 owng729fp.c create mode 100644 owng729fp.h create mode 100644 scratchmem.h create mode 100644 vadg723.c create mode 100644 vadg723.h create mode 100644 vadg729fp.c create mode 100644 vadg729fp.h 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__*/