📄 encgsmfr.c
字号:
/*/////////////////////////////////////////////////////////////////////////////
//
// INTEL CORPORATION PROPRIETARY INFORMATION
// This software is supplied under the terms of a license agreement or
// nondisclosure agreement with Intel Corporation and may not be copied
// or disclosed except in accordance with the terms of that agreement.
// Copyright(c) 2004-2005 Intel Corporation. All Rights Reserved.
//
// Intel(R) Integrated Performance Primitives
// USC - Unified Speech Codec interface library
//
// By downloading and installing USC codec, you hereby agree that the
// accompanying Materials are being provided to you under the terms and
// conditions of the End User License Agreement for the Intel(R) Integrated
// Performance Primitives product previously accepted by you. Please refer
// to the file ipplic.htm located in the root directory of your Intel(R) IPP
// product installation for more information.
//
// A speech coding standards promoted by ITU, ETSI, 3GPP and other
// organizations. Implementations of these standards, or the standard enabled
// platforms may require licenses from various entities, including
// Intel Corporation.
//
//
// Purpose: GSM FR 06.10: encoder API.
//
*/
#include "ippsc.h"
#include "owngsmfr.h"
static __ALIGN32 CONST short FAC[8] = { 18431, 20479, 22527,
24575, 26623, 28671,
30719, 32767};
static __ALIGN32 CONST short DLB[4] = {6554,16384,
26214,32767};
static __ALIGN32 CONST short swTab[4]={3277,11469,
21299,32767};
static void acfEnComp(GSMFREncoder_Obj *encoderObj,const int *L_ACF);
static void acfEverag(GSMFREncoder_Obj *encoderObj,const int *L_ACF);
static void spectComp(GSMFREncoder_Obj *encoderObj);
static void periodDetect(GSMFREncoder_Obj *encoderObj);
static void threshAdapt(GSMFREncoder_Obj *encoderObj);
static void vadDecision(GSMFREncoder_Obj *encoderObj);
static void vadHangoverAdd(GSMFREncoder_Obj *encoderObj );
static void periodUpdate(GSMFREncoder_Obj *encoderObj,short lags[4]);
static int toneDetect(GSMFREncoder_Obj *encoderObj);
static void saveParm(short *pSrc,short *pDst,int *index,int len);
static void larAverage(short *a,short *LAR,int len);
static void xmaxAverage(short *a,short *xmax);
static int Dtx_Encoder_Count(GSMFREncoder_Obj *encoderObj,short *LAR,short *xmax,uchar *dst);
static void newSIDFrame(short *a,short *b,uchar dst[33]);
GSMFR_CODECFUN( APIGSMFR_Status, apiGSMFREncoder_GetSize,
(GSMFREncoder_Obj* encoderObj, unsigned int *pCodecSize))
{
if(NULL == encoderObj)
return APIGSMFR_StsBadArgErr;
if(NULL == pCodecSize)
return APIGSMFR_StsBadArgErr;
if(encoderObj->objPrm.key != ENC_KEY)
return APIGSMFR_StsNotInitialized;
*pCodecSize = encoderObj->objPrm.objSize;
return APIGSMFR_StsNoErr;
}
static int AutoCorr1(short *pSrcDst, int len, int *pDst,int lenDst, int *pNorm)
{
short tmp, sMaxVal;
ippsMax_16s(pSrcDst,len,&sMaxVal);
ippsMin_16s(pSrcDst,len,&tmp);
if(-tmp > sMaxVal)
sMaxVal = (short)(-tmp);
if(sMaxVal == 0)
*pNorm = 0;
else
*pNorm = 4-Exp_32s_Pos( (int)sMaxVal << 16);
if(*pNorm > 0) {
tmp = (short)(16384 >>(*pNorm-1));
ippsMulC_NR_16s_ISfs( tmp,pSrcDst,len,15 );
}
ippsAutoCorr_16s32s(pSrcDst,len,pDst, lenDst );
return 0;
}
static int AutoCorr0(short *pSrcDst, int len, int *pDst,int lenDst, int *pNorm)
{
AutoCorr1( pSrcDst, len, pDst, lenDst, pNorm);
if(*pNorm > 0)
ippsLShiftC_16s_I(*pNorm,pSrcDst,len);
return 0;
}
static int GsmLPCAnal(GSMFREncoder_Obj *encoderObj, short *pSrcDst, short *pDst)
{
IPP_ALIGNED_ARRAY(16, int, L_ACF, 9);
AutoCorr0(pSrcDst,160,L_ACF, 9,&encoderObj->scalauto);
ippsLShiftC_32s_I(1,L_ACF,9);
if(encoderObj->vadMode == GSMFR_VAD_ON ){
acfEnComp(encoderObj, L_ACF); /* do pvad for threshAdapt() & vadDecision()*/
acfEverag(encoderObj, L_ACF); /* do av1 for ippspredValComp() & av0 for spectComp()*/
}
ippsSchur_GSMFR_32s16s(L_ACF,pDst,8);
Ref2LAR(pDst,8);
QuantCoding(pDst,8);
return 0;
}
static void CutLTPParm(short *dp,const short *d,short *dst1,short *dst2) {
int j, maxL, powerL, resultL, maxInd, minInd;
short pTmp[40], NcVal, bcVal, R, S, sMaxVal, scal, tmp, wtmp;
ippsMaxIndx_16s(d,40,&sMaxVal,&maxInd);
ippsMinIndx_16s(d,40,&tmp,&minInd);
if(-tmp > sMaxVal) {
sMaxVal = (short)(-tmp);
maxInd = minInd;
}
if(sMaxVal == 0) {
tmp = scal = 0;
}
else {
tmp = Exp_32s_Pos( (int)sMaxVal << 16 );
}
if(tmp > 6)
scal = 0;
else
scal = (short)(6 - tmp);
maxL = 0;
NcVal = 40;
wtmp = (short)(d[maxInd] >> scal);
for(j = 40; j <121; j++) {
resultL = (int)wtmp * dp[maxInd - j];
if(resultL > maxL) {
NcVal = (short)(j);
maxL = resultL;
}
}
*dst2 = NcVal;
maxL <<= 1;
maxL = maxL>>(6-scal);
ippsRShiftC_16s(&dp[- NcVal],3,pTmp,40);
ippsDotProd_16s32s_Sfs(pTmp,pTmp,40, &powerL,-1 );
if(maxL <1) {
*dst1 = 0;
return;
}
if(maxL >= powerL) {
*dst1 = 3;
return;
}
tmp = Exp_32s_Pos( powerL );
R = (short)( (maxL<<tmp) >> 16 );
S = (short)( (powerL<<tmp) >> 16 );
for(bcVal = 0; bcVal <3; bcVal++)
if(R <= Mul_16s_Sfs(S, DLB[bcVal],15))
break;
*dst1 = bcVal;
}
static void LTPParm(short *dp,const short *d,short *dst1, short *dst2){
int maxL, powerL, NcVal;
short bcVal, R, S, sMaxVal, scal, tmp, pTmp[40];
ippsMax_16s(d,40,&sMaxVal);
ippsMin_16s(d,40,&tmp);
if(tmp==IPP_MIN_16S) tmp++;
if(tmp<0) tmp =(short)( -tmp);
sMaxVal = (short)(IPP_MAX(sMaxVal,tmp));
if(sMaxVal == 0){
tmp = scal = 0;
} else {
tmp = Exp_32s_Pos( (int)sMaxVal << 16 );
}
if(tmp > 6)
scal = 0;
else
scal = (short)(6 - tmp);
ippsRShiftC_16s(d,scal,pTmp,40);
ippsCrossCorrLagMax_16s(pTmp,dp-120,40,80,&maxL,&NcVal);
*dst2 = (short)(-(NcVal-120));
maxL = maxL<<1;
maxL >>= (6-scal);
ippsRShiftC_16s(&dp[NcVal-120],3,pTmp,40);
ippsDotProd_16s32s_Sfs(pTmp,pTmp,40, &powerL,-1 );
if(maxL <1) {
*dst1 = 0;
return;
}
if(maxL >= powerL) {
*dst1 = 3;
return;
}
tmp = Exp_32s_Pos( powerL );
R = (short)( (maxL<<tmp) >> 16 );
S = (short)( (powerL<<tmp) >> 16 );
for(bcVal = 0; bcVal <3; bcVal++)
if(R <= Mul_16s_Sfs(S, DLB[bcVal],15))
break;
*dst1 = bcVal;
}
static int GsmLTP(GSMFR_LTP_t cutLTPFlag,const short *d,short *dp, short *ep, short *bcVal,
short *NcVal) {
if(!d || !ep || !dp || !NcVal || !bcVal )
return -1;
if( cutLTPFlag == LTP_ON)
CutLTPParm(dp, d, bcVal, NcVal);
else
LTPParm(dp, d, bcVal, NcVal);
Ltaf(dp,d, ep,swTab[*bcVal],*NcVal);
return 0;
}
static void GsmSTAF(short *s,short *LARc,short *pLARj,short *pLARj1,short *pMem)
{
short LARp[32];
DecCodLAR( LARc, pLARj,8 );
Interpolate_GSMFR_16s( pLARj1, pLARj, LARp , 8);
ippsInterpolate_G729_16s( pLARj1, pLARj, LARp+8, 8);
Interpolate_GSMFR_16s( pLARj, pLARj1, LARp+16, 8);
ippsCopy_16s( pLARj, LARp+24 , 8);
LARp2RC( LARp, 32);
ippsShortTermAnalysisFilter_GSMFR_16s_I(LARp , s , 13, pMem );
ippsShortTermAnalysisFilter_GSMFR_16s_I(LARp+8 , s + 13, 14, pMem );
ippsShortTermAnalysisFilter_GSMFR_16s_I(LARp+16, s + 27, 13, pMem );
ippsShortTermAnalysisFilter_GSMFR_16s_I(LARp+24, s + 40,120, pMem );
}
static int GsmRPEEnc(short *ep,short *xMaxC,
short *Mc,
short *xMc) {
short x[40], xM[13], xMp[13], mant, exponent;
ippsWeightingFilter_GSMFR_16s(ep, x, 40);
RPEGrid(x,xM,Mc);
APCMQuant2(xM,xMc,&mant,&exponent,xMaxC);
ippsRPEQuantDecode_GSMFR_16s(xMc,FAC[mant],(short)(6-exponent),xMp );
ippsZero_16s(ep,40);
RPEGridPos( xMp,*Mc, ep);
return 0;
}
static int GSMFREncoder(GSMFREncoder_Obj *pObj, const short *s,short *LARc,short *NcVal,
short *bcVal,short *Mc, short *xMaxC,short *xMc) {
IPP_ALIGNED_ARRAY( 16, short, so,160);
short *dp = pObj->dp0 + 120 ;
int k;
ippsHighPassFilter_GSMFR_16s( s,pObj->sof,GSMFR_EXT_FRAME_LEN,pObj->hpMem);
ippsPreemphasize_GSMFR_16s(pObj->sof,so, GSMFR_EXT_FRAME_LEN, &pObj->mp);
GsmLPCAnal(pObj,so, LARc);
GsmSTAF(so,LARc,pObj->LARpp[ pObj->idx],pObj->LARpp[pObj->idx^1],pObj->u);
pObj->idx^=1;
for(k = 0; k <4; k++) {
GsmLTP(pObj->objPrm.cutLTPFlag,&so[k*40],dp,&pObj->ep[5],&bcVal[k],&NcVal[k]);
GsmRPEEnc(&pObj->ep[5],&xMaxC[k], &Mc[k], &xMc[13*k] );
ippsAdd_16s_I(&pObj->ep[5],dp,40);
dp += 40;
}
ippsCopy_8u((Ipp8u*)(pObj->dp0 + GSMFR_EXT_FRAME_LEN),(Ipp8u*)pObj->dp0,
120 * sizeof(*pObj->dp0));
return 0;
}
GSMFR_CODECFUN( APIGSMFR_Status, apiGSMFREncoder_Alloc,(int *pSizeTab)) {
int allocSize = sizeof(GSMFREncoder_Obj);
*pSizeTab = allocSize;
return APIGSMFR_StsNoErr;
}
static __ALIGN32 CONST short rrvad[3]={24576,-16384,4096};
static __ALIGN32 CONST short hann[160]={
0 ,12 ,51 ,114 ,204 ,318 ,458 ,622 ,811 ,1025 ,1262 ,1523 ,1807 ,2114 ,2444 ,2795 ,3167 ,3560 ,3972 ,4405 ,
4856 ,5325 ,5811 ,6314 ,6832 ,7365 ,7913 ,8473 ,9046 ,9631 ,10226,10831,11444,12065,12693,13326,13964,14607,15251,15898,
16545,17192,17838,18482,19122,19758,20389,21014,21631,22240,22840,23430,24009,24575,25130,25670,26196,26707,27201,27679,
28193,28581,29003,29406,29789,30151,30491,30809,31105,31377,31626,31852,32053,32230,32382,32509,32611,32688,32739,32764
, 32764, 32739, 32688, 32611, 32509, 32382, 32230, 32053, 31852, 31626, 31377, 31105, 30809,
30491, 30151, 29789, 29406, 29003, 28581, 28193, 27679, 27201, 26707, 26196, 25670, 25130,
24575, 24009, 23430, 22840, 22240, 21631, 21014, 20389, 19758, 19122, 18482, 17838, 17192,
16545, 15898, 15251, 14607, 13964, 13326, 12693, 12065, 11444, 10831, 10226, 9631, 9046,
8473, 7913, 7365, 6832, 6314, 5811, 5325, 4856, 4405, 3972, 3560, 3167, 2795, 2444, 2114,
1807, 1523, 1262, 1025, 811, 622, 458, 318, 204, 114, 51, 12, 0
};
GSMFR_CODECFUN( APIGSMFR_Status, apiGSMFREncoder_Init, (GSMFREncoder_Obj* encoderObj,
GSMFR_Params_t *params)) {
if(!encoderObj) return APIGSMFR_StsBadArgErr;
ippsZero_8u((Ipp8u*)encoderObj,sizeof(GSMFREncoder_Obj));
encoderObj->objPrm.objSize = sizeof(GSMFREncoder_Obj);
encoderObj->vadMode = params->vadMode;
encoderObj->vadDirection = params->vadDirection;
encoderObj->objPrm.key = ENC_KEY;
ippsCopy_16s(rrvad,encoderObj->rvad,3);
encoderObj->nextFrameVadMode = params->vadMode;
encoderObj->nextFrameVadDirection = params->vadDirection;
encoderObj->objPrm.cutLTPFlag = params->ltp_f;
encoderObj->normrvad=7;
encoderObj->e_thvad=20;
encoderObj->m_thvad=31250;
encoderObj->hangcount=-1;
encoderObj->oldlag=40;
encoderObj->vad=1;
encoderObj->vvad=1;
encoderObj->myburstcount = DTX_ELAPSED_FRAMES;
return APIGSMFR_StsNoErr;
}
GSMFR_CODECFUN( APIGSMFR_Status, apiGSMFREncoder_Mode, (GSMFREncoder_Obj* encoderObj,
GSMFR_Params_t *params)) {
if(!encoderObj) return APIGSMFR_StsBadArgErr;
encoderObj->vadMode = params->vadMode;
encoderObj->vadDirection = params->vadDirection;
return APIGSMFR_StsNoErr;
}
static void newSIDFrame(short *saveLAR,short *saveXMax,uchar pDst[33])
{
short xMaxAvg, LAR[8];
larAverage(saveLAR,LAR,8);
xmaxAverage(saveXMax,&xMaxAvg);
ippsSet_8u(0,pDst,33);
/* pack to bitstream */
pDst[0] =(uchar)( ((LAR[0] >> 2) & 15));
pDst[1] =(uchar)( ((LAR[0] & 3) << 6) | (LAR[1] & 0x3F));
pDst[2] =(uchar)( ((LAR[2] & 0x1F) << 3)| ((LAR[3] >> 2) & 7));
pDst[3] =(uchar)( ((LAR[3] & 3) << 6) | ((LAR[4] & 15) << 2) | ((LAR[5] >> 2) & 3));
pDst[4] =(uchar)( ((LAR[5] & 3) << 6) | ((LAR[6] & 7) << 3) | (LAR[7] &7));
pDst[6] =(uchar)( ((xMaxAvg >> 1) & 0x1F));
pDst[7] =(uchar)( ((xMaxAvg & 1) << 7));
pDst[13] =(uchar)( ((xMaxAvg >> 1) & 0x1F));
pDst[14] =(uchar)( ((xMaxAvg & 1) << 7));
pDst[20] =(uchar)( ((xMaxAvg >> 1) & 0x1F));
pDst[21] =(uchar)( ((xMaxAvg & 1) << 7));
pDst[27] =(uchar)( ((xMaxAvg >> 1) & 0x1F));
pDst[28] =(uchar)( ((xMaxAvg & 1) << 7));
}
/* return 0 if SID frame ,1 if voice
SID (after hangover) recalculated with every new vad=0 frame
last update period SID = 23
vad=0 frame considered as speech in myburstcount
toneDetect() have to go after threshAdapt()
*/
static int Dtx_Encoder_Count(GSMFREncoder_Obj *encoderObj,short LAR[8],short xmax[4],uchar *dst)
{
if ( encoderObj->vad == 1)
{
++encoderObj->myburstcount;
if(encoderObj->SIDAveragePeriodCount>0 && encoderObj->SIDAveragePeriodCount<2)
{
++encoderObj->myburstcount;
}
encoderObj->SIDAveragePeriodCount=0;
if ( encoderObj->myburstcount >= DTX_ELAPSED_FRAMES )
{
encoderObj->myburstcount = DTX_ELAPSED_FRAMES;
}
}
else
{
++encoderObj->SIDAveragePeriodCount;
if ( encoderObj->myburstcount >= DTX_ELAPSED_FRAMES &&
encoderObj->SIDAveragePeriodCount < DTX_HANG_CONST)
{
saveParm(LAR ,encoderObj->saveLAR,&encoderObj->oldestLAR,8); /* save history for SID forming */
saveParm(xmax ,encoderObj->saveXMax,&encoderObj->oldestxmax,4); /* save history for SID forming */
return 1;
}
if ( encoderObj->SIDAveragePeriodCount >= DTX_HANG_CONST )
{/*form new SID */
encoderObj->myburstcount = 0;
newSIDFrame(encoderObj->saveLAR,encoderObj->saveXMax,dst);
saveParm(LAR ,encoderObj->saveLAR,&encoderObj->oldestLAR,8); /* save history for SID forming */
saveParm(xmax ,encoderObj->saveXMax,&encoderObj->oldestxmax,4); /* save history for SID forming */
ippsCopy_8u(dst,encoderObj->oldSID,33);
encoderObj->SIDAveragePeriodCount = DTX_HANG_CONST;
return 0;
}else
if ( encoderObj->myburstcount < (DTX_ELAPSED_FRAMES+1))
{
ippsCopy_8u(encoderObj->oldSID,dst,33);
saveParm(LAR ,encoderObj->saveLAR,&encoderObj->oldestLAR,8); /* save history for SID forming */
saveParm(xmax ,encoderObj->saveXMax,&encoderObj->oldestxmax,4); /* save history for SID forming */
return 0;
}
saveParm(LAR ,encoderObj->saveLAR,&encoderObj->oldestLAR,8); /* save history for SID forming */
saveParm(xmax ,encoderObj->saveXMax,&encoderObj->oldestxmax,4); /* save history for SID forming */
}
return 1;
}
GSMFR_CODECFUN( APIGSMFR_Status, apiGSMFREncode,(GSMFREncoder_Obj *encoderObj,
const short *source, uchar *wBuf,int *vad,int *frameType)) {
short LAR[8], NcVal[4], Mc[4], bcVal[4], xmax[4], xMc[13*4],vpar[9];
int L_work[9];
if(NULL==encoderObj || NULL==source || NULL ==wBuf )
return APIGSMFR_StsBadArgErr;
if(0 >= encoderObj->objPrm.objSize)
return APIGSMFR_StsNotInitialized;
encoderObj->vadMode = encoderObj->nextFrameVadMode;
encoderObj->vadDirection = encoderObj->nextFrameVadDirection;
if(GSMFREncoder(encoderObj, source, LAR, NcVal, bcVal, Mc, xmax, xMc))
return APIGSMFR_StsBadArgErr;
*frameType=1;
if(encoderObj->vadMode == GSMFR_VAD_ON ){
/*3.3.1 clause, Schur recursion to compute reflection coefficients*/
ippsSchur_GSMFR_32s16s(encoderObj->L_av1,&vpar[1],8);
predValComp(vpar,L_work,9); /* do rav1 for threshAdapt() & spectComp()*/
ippsLShiftC_32s_I(1,L_work,9);
/*Keep the normrav1 for use in subclause 3.4 and 3.6.*/
if ( L_work[0] == 0 )
encoderObj->normrav1 =0;
else
encoderObj->normrav1 = Exp_32s_Pos( L_work[0] );
Shift_32s16s(L_work,encoderObj->rav1,9,16-encoderObj->normrav1);
spectComp(encoderObj); /* do stat for threshAdapt()*/
periodDetect(encoderObj);/* do ptch for threshAdapt()*/
periodUpdate(encoderObj,NcVal);
threshAdapt(encoderObj); /* do rvad for next call acfEnComp(L_ACF) & thvad for vadDecision()*/
vadDecision(encoderObj); /* do vvad for vadHangoverAdd(vad) */
vadHangoverAdd(encoderObj);
if(encoderObj->vadDirection == GSMFR_DOWNLINK)
toneDetect(encoderObj);/* do tone for threshAdapt()*/
/* sid frame encoding */
*vad = encoderObj->vad;
*frameType= Dtx_Encoder_Count(encoderObj,LAR,xmax,wBuf);
}
if(*frameType)
{
/*pack to bitstream*/
wBuf[0] =(uchar)( ((LAR[0] >> 2) & 0xF));
wBuf[8] =(uchar)( ((xMc[2] & 0x3) << 6) | ((xMc[3] & 0x7) << 3) | (xMc[4] & 0x7));
wBuf[1] =(uchar)( ((LAR[0] & 0x3) << 6) | (LAR[1] & 0x3F));
wBuf[9] =(uchar)( ((xMc[5] & 0x7) << 5) | ((xMc[6] & 0x7) << 2) | ((xMc[7] >> 1) & 0x3));
wBuf[2] =(uchar)( ((LAR[2] & 0x1F) << 3)| ((LAR[3] >> 2) & 0x7));
wBuf[10] =(uchar)( ((xMc[7] & 0x1) << 7) | ((xMc[8] & 0x7) << 4) | ((xMc[9] & 0x7) << 1) | ((xMc[10] >> 2) & 0x1));
wBuf[3] =(uchar)( ((LAR[3] & 0x3) << 6) | ((LAR[4] & 0xF) << 2) | ((LAR[5] >> 2) & 0x3));
wBuf[11] =(uchar)( ((xMc[10] & 0x3) << 6)| ((xMc[11] & 0x7) << 3)| (xMc[12] & 0x7));
wBuf[4] =(uchar)( ((LAR[5] & 0x3) << 6) | ((LAR[6] & 0x7) << 3) | (LAR[7] & 0x7));
wBuf[15] =(uchar)( ((xMc[15] & 0x3) << 6)| ((xMc[16] & 0x7) << 3)| (xMc[17] & 0x7));
wBuf[5] =(uchar)( ((NcVal[0] & 0x7F) << 1) | ((bcVal[0] >> 1) & 0x1));
wBuf[16] =(uchar)( ((xMc[18] & 0x7) << 5)| ((xMc[19] & 0x7) << 2)| ((xMc[20] >> 1) & 0x3));
wBuf[12] =(uchar)( ((NcVal[1] & 0x7F) << 1) | ((bcVal[1] >> 1) & 0x1));
wBuf[17] =(uchar)( ((xMc[20] & 0x1) << 7)| ((xMc[21] & 0x7) << 4)| ((xMc[22] & 0x7) << 1) | ((xMc[23] >> 2) & 0x1));
wBuf[19] =(uchar)( ((NcVal[2] & 0x7F) << 1) | ((bcVal[2] >> 1) & 0x1));
wBuf[18] =(uchar)( ((xMc[23] & 0x3) << 6)| ((xMc[24] & 0x7) << 3)| (xMc[25] & 0x7));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -