📄 dtxamrwb.c
字号:
/*/////////////////////////////////////////////////////////////////////////////
//
// INTEL CORPORATION PROPRIETARY INFORMATION
// This software is supplied under the terms of a license agreement or
// nondisclosure agreement with Intel Corporation and may not be copied
// or disclosed except in accordance with the terms of that agreement.
// Copyright(c) 2005 Intel Corporation. All Rights Reserved.
//
// Intel(R) Integrated Performance Primitives
// USC - Unified Speech Codec interface library
//
// By downloading and installing USC codec, you hereby agree that the
// accompanying Materials are being provided to you under the terms and
// conditions of the End User License Agreement for the Intel(R) Integrated
// Performance Primitives product previously accepted by you. Please refer
// to the file ipplic.htm located in the root directory of your Intel(R) IPP
// product installation for more information.
//
// A speech coding standards promoted by ITU, ETSI, 3GPP and other
// organizations. Implementations of these standards, or the standard enabled
// platforms may require licenses from various entities, including
// Intel Corporation.
//
//
// Purpose: AMRWB speech codec DTX utilities.
//
*/
#include "ownamrwb.h"
static void ownAverageIsfHistory(short *pIsfOldvec, short *pIndices, int *pIsfAvrvec);
static void ownFindFrameIndices(short *pIsfOldvec, short *pIndices, SDtxEncoderState *st);
static short ownDitherCtrl(SDtxEncoderState *st);
static void ownCNDithering(short *pIsfvec, int *valLogIntEnergy, short *pDitherSeed);
short ownDTXEncReset(SDtxEncoderState *st, short *pIsfInit)
{
int i;
if (st == (SDtxEncoderState*)NULL) return -1;
st->siHistPtr = 0;
st->siLogEnerIndex = 0;
for (i = 0; i < DTX_HIST_SIZE; i++)
{
ippsCopy_16s(pIsfInit, &st->asiIsfHistory[i * LP_ORDER], LP_ORDER);
}
st->siCngSeed = RND_INIT;
ippsZero_16s(st->siLogEnerHist, DTX_HIST_SIZE);
st->siHangoverCount = DTX_HANG_CONST;
st->siAnaElapsedCount = 32767;
ippsZero_16s((short*)st->aiDistMatrix, 28*2);
ippsZero_16s((short*)st->aiSumDist, (DTX_HIST_SIZE - 1)*2);
return 1;
}
short ownDTXEnc(SDtxEncoderState *st, short *pIsfvec, short *pExc2vec, unsigned short *pPrmsvec)
{
short valLogEnergy, valGain, valLevelTmp, valExp, valExpTmp, tmp;
short valLogIntPart, valLogFracPart;
int i, valEner, valLevel;
short pIsfOrdervec[3];
short valCNDith;
IPP_ALIGNED_ARRAY(16, int, pIsf32svec, LP_ORDER);
/* VOX mode computation of SID parameters */
ippsZero_16s((short*)pIsf32svec, LP_ORDER*2);
/* average energy and isf */
/* Division by DTX_HIST_SIZE = 8 has been done in dtx_buffer */
ippsSum_16s_Sfs(st->siLogEnerHist, DTX_HIST_SIZE, &valLogEnergy, 0);
ownFindFrameIndices(st->asiIsfHistory, pIsfOrdervec, st);
ownAverageIsfHistory(st->asiIsfHistory, pIsfOrdervec, pIsf32svec);
for (i = 0; i < LP_ORDER; i++)
{
pIsfvec[i] = (short)(pIsf32svec[i] >> 3);
}
/* quantize logarithmic energy to 6 bits (-6 : 66 dB) which corresponds to -2:22 in log2(E) */
valLogEnergy >>= 2;
valLogEnergy += 512;
/* Multiply by 2.625 to get full 6 bit range */
valLogEnergy = Mul_16s_Sfs(valLogEnergy, 21504, 15);
/* Quantize Energy */
st->siLogEnerIndex = valLogEnergy >> 6;
if (st->siLogEnerIndex > 63) st->siLogEnerIndex = 63;
if (st->siLogEnerIndex < 0) st->siLogEnerIndex = 0;
/* Quantize ISFs */
ippsISFQuantDTX_AMRWB_16s(pIsfvec, pIsfvec, (short*)pPrmsvec);
pPrmsvec += 5;
*(pPrmsvec)++ = st->siLogEnerIndex;
valCNDith = ownDitherCtrl(st);
*(pPrmsvec)++ = valCNDith;
/* level = (float)( pow( 2.0f, (float)st->siLogEnerIndex / 2.625 - 2.0 ) ); */
valLogEnergy = (st->siLogEnerIndex << 9);
/* Divide by 2.625; siLogEnergy will be between 0:24 */
valLogEnergy = Mul_16s_Sfs(valLogEnergy, 12483, 15);
valLogIntPart = valLogEnergy >> 10;
valLogFracPart = (short) (valLogEnergy & 0x3ff);
valLogFracPart <<= 5;
valLogIntPart += 15;
valLevel = ownPow2_AMRWB(valLogIntPart, valLogFracPart);
valExpTmp = 15 - Norm_32s_I(&valLevel);
valLevelTmp = (short)(valLevel >> 16);
/* generate white noise vector */
for (i = 0; i < FRAME_SIZE; i++)
{
pExc2vec[i] = Random(&(st->siCngSeed)) >> 4;
}
/* energy of generated excitation */
ippsDotProd_16s32s_Sfs( pExc2vec, pExc2vec,FRAME_SIZE, &valEner, -1);
valEner = Add_32s(valEner, 1);
valExp = (30 - Norm_32s_I(&valEner));
ownInvSqrt_AMRWB_32s16s_I(&valEner, &valExp);
valGain = (short)(valEner >> 16);
valGain = Mul_16s_Sfs(valLevelTmp, valGain, 15);
valExp += valExpTmp;
/* Multiply by sqrt(FRAME_SIZE)=16, i.e. shift left by 4 */
valExp += 4;
for (i = 0; i < FRAME_SIZE; i++)
{
tmp = Mul_16s_Sfs(pExc2vec[i], valGain, 15);
if (valExp > 0)
pExc2vec[i] = Cnvrt_32s16s(tmp << valExp);
else
pExc2vec[i] = (tmp >> (-valExp));
}
return 0;
}
short ownDTXDecReset(SDtxDecoderState * st, short *pIsfInit)
{
int i;
if (st == (SDtxDecoderState*) NULL) return -1;
st->siSidLast = 0;
st->siLogEnergy = 3500;
st->siLogEnergyOld = 3500;
st->siSidPeriodInv = (1 << 13);
/* low level noise for better performance in DTX handover cases */
st->siCngSeed = RND_INIT;
st->siHistPtr = 0;
ippsCopy_16s(pIsfInit, st->asiIsf, LP_ORDER);
ippsCopy_16s(pIsfInit, st->asiIsfOld, LP_ORDER);
ippsSet_16s(st->siLogEnergy, st->siLogEnerHist, DTX_HIST_SIZE);
for (i = 0; i < DTX_HIST_SIZE; i++)
{
ippsCopy_16s(pIsfInit, &st->asiIsfHistory[i * LP_ORDER], LP_ORDER);
}
st->siAnaElapsedCount = 32767;
st->siHangoverCount = DTX_HANG_CONST;
st->siValidData = 0;
st->siSidFrame = 0;
st->siGlobalState = SPEECH;
st->siHangoverAdded = 0;
st->siDitherSeed = RND_INIT;
st->siDataUpdated = 0;
st->siComfortNoiseDith = 0;
return 0;
}
short ownDTXDec(SDtxDecoderState *st, short *pExc2vec, short valDTXState, short *pIsfvec,
const unsigned short *pPrmsvec)
{
short valLogEnergyIndex;
short valIntFac;
short valGain;
short valHistPtr;
short valInterFac;
short tmp, valExp, valExpTmp, valLogIntPart, valLogFracPart, valLevelTmp;
int i, j, valLogIntEnergy, valLevel, valEner;
IPP_ALIGNED_ARRAY(16, int, pIsf32svec, LP_ORDER);
if ((st->siHangoverAdded != 0) && (st->siSidFrame != 0))
{
/* sid_first after dtx hangover period or sid_upd after dtxhangover */
/* consider twice the last frame */
valHistPtr = st->siHistPtr + 1;
if (valHistPtr == DTX_HIST_SIZE) valHistPtr = 0;
ippsCopy_16s(&st->asiIsfHistory[st->siHistPtr * LP_ORDER], &st->asiIsfHistory[valHistPtr * LP_ORDER], LP_ORDER);
st->siLogEnerHist[valHistPtr] = st->siLogEnerHist[st->siHistPtr];
ippsZero_16s((short*)pIsf32svec, LP_ORDER*2);
ippsSum_16s_Sfs(st->siLogEnerHist, DTX_HIST_SIZE, &st->siLogEnergy, 0);
for (i = 0; i < DTX_HIST_SIZE; i++)
{
for (j = 0; j < LP_ORDER; j++)
{
pIsf32svec[j] += (int)(st->asiIsfHistory[i * LP_ORDER + j]);
}
}
st->siLogEnergy >>= 1;
st->siLogEnergy += 1024;
if (st->siLogEnergy < 0) st->siLogEnergy = 0;
for (j = 0; j < LP_ORDER; j++)
{
st->asiIsf[j] = (short)(pIsf32svec[j] >> 3);
}
}
if (st->siSidFrame != 0)
{
ippsCopy_16s(st->asiIsf, st->asiIsfOld, LP_ORDER);
st->siLogEnergyOld = st->siLogEnergy;
if (st->siValidData != 0) /* new data available (no CRC) */
{
valInterFac = st->siSidLast;
if (valInterFac > 32) valInterFac = 32;
if (valInterFac >= 2)
st->siSidPeriodInv = (1 << 15) / valInterFac;
else
st->siSidPeriodInv = (1 << 14);
ippsISFQuantDecodeDTX_AMRWB_16s((short*)pPrmsvec, st->asiIsf);
pPrmsvec += 5;
valLogEnergyIndex = *(pPrmsvec)++;
/* read background noise stationarity information */
st->siComfortNoiseDith = *(pPrmsvec)++;
st->siLogEnergy = valLogEnergyIndex << 9;
st->siLogEnergy = Mul_16s_Sfs(st->siLogEnergy, 12483, 15);
if ((st->siDataUpdated == 0) || (st->siGlobalState == SPEECH))
{
ippsCopy_16s(st->asiIsf, st->asiIsfOld, LP_ORDER);
st->siLogEnergyOld = st->siLogEnergy;
}
}
}
if ((st->siSidFrame != 0) && (st->siValidData != 0))
{
st->siSidLast = 0;
}
/* Interpolate SID info */
valIntFac = st->siSidLast << 10;
valIntFac = Mul_16s_Sfs(valIntFac, st->siSidPeriodInv, 15);
if (valIntFac > 1024) valIntFac = 1024;
valIntFac <<= 4;
valLogIntEnergy = 2 * valIntFac * st->siLogEnergy;
ownMulC_16s_Sfs(st->asiIsf, valIntFac, pIsfvec, LP_ORDER, 15);
valIntFac = 16384 - valIntFac;
valLogIntEnergy += 2 * valIntFac * st->siLogEnergyOld;
for (i = 0; i < LP_ORDER; i++)
{
pIsfvec[i] += Mul_16s_Sfs(valIntFac, st->asiIsfOld[i], 15);
pIsfvec[i] <<= 1;
}
/* If background noise is non-stationary, insert comfort noise dithering */
if (st->siComfortNoiseDith != 0)
{
ownCNDithering(pIsfvec, &valLogIntEnergy, &st->siDitherSeed);
}
valLogIntEnergy >>= 9;
valLogIntPart = (short)(valLogIntEnergy >> 16);
valLogFracPart = (short)((valLogIntEnergy - (int)(valLogIntPart << 16)) >> 1);
valLogIntPart += (16 - 1);
valLevel = ownPow2_AMRWB(valLogIntPart, valLogFracPart);
valExpTmp = 15 - Norm_32s_I(&valLevel);
valLevelTmp = (short)(valLevel >> 16);
/* generate white noise vector */
for (i = 0; i < FRAME_SIZE; i++)
{
pExc2vec[i] = Random(&(st->siCngSeed)) >> 4;
}
/* energy of generated excitation */
ippsDotProd_16s32s_Sfs( pExc2vec, pExc2vec,FRAME_SIZE, &valEner, -1);
valEner = Add_32s(valEner, 1);
valExp = (30 - Norm_32s_I(&valEner));
ownInvSqrt_AMRWB_32s16s_I(&valEner, &valExp);
valGain = (short)(valEner >> 16);
valGain = Mul_16s_Sfs(valLevelTmp, valGain, 15);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -