mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-04 03:50:31 +00:00
Add iLBC codec
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@852 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
303
codecs/ilbc/doCPLC.c
Executable file
303
codecs/ilbc/doCPLC.c
Executable file
@@ -0,0 +1,303 @@
|
||||
|
||||
/******************************************************************
|
||||
|
||||
iLBC Speech Coder ANSI-C Source Code
|
||||
|
||||
doCPLC.c
|
||||
|
||||
Copyright (c) 2001,
|
||||
Global IP Sound AB.
|
||||
All rights reserved.
|
||||
|
||||
******************************************************************/
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "iLBC_define.h"
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* Compute cross correlation and pitch gain for pitch prediction
|
||||
* of last subframe at given lag.
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
void compCorr(
|
||||
float *cc, /* (o) cross correlation coefficient */
|
||||
float *gc, /* (o) gain */
|
||||
float *buffer, /* (i) signal buffer */
|
||||
int lag, /* (i) pitch lag */
|
||||
int bLen, /* (i) length of buffer */
|
||||
int sRange /* (i) correlation search length */
|
||||
){
|
||||
int i;
|
||||
float ftmp1, ftmp2;
|
||||
|
||||
ftmp1 = 0.0;
|
||||
ftmp2 = 0.0;
|
||||
for (i=0; i<sRange; i++) {
|
||||
ftmp1 += buffer[bLen-sRange+i] *
|
||||
buffer[bLen-sRange+i-lag];
|
||||
ftmp2 += buffer[bLen-sRange+i-lag] *
|
||||
buffer[bLen-sRange+i-lag];
|
||||
}
|
||||
|
||||
if (ftmp2 > 0.0) {
|
||||
*cc = ftmp1*ftmp1/ftmp2;
|
||||
*gc = (float)fabs(ftmp1/ftmp2);
|
||||
}
|
||||
else {
|
||||
*cc = 0.0;
|
||||
*gc = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------*
|
||||
* Packet loss concealment routine. Conceals a residual signal
|
||||
* and LP parameters. If no packet loss, update state.
|
||||
*---------------------------------------------------------------*/
|
||||
|
||||
void doThePLC(
|
||||
float *PLCresidual, /* (o) concealed residual */
|
||||
float *PLClpc, /* (o) concealed LP parameters */
|
||||
int PLI, /* (i) packet loss indicator
|
||||
0 - no PL, 1 = PL */
|
||||
float *decresidual, /* (i) decoded residual */
|
||||
float *lpc, /* (i) decoded LPC (only used for no PL) */
|
||||
int inlag, /* (i) pitch lag */
|
||||
iLBC_Dec_Inst_t *iLBCdec_inst
|
||||
/* (i/o) decoder instance */
|
||||
){
|
||||
int lag=20, randlag;
|
||||
float gain, maxcc;
|
||||
float gain_comp, maxcc_comp;
|
||||
int i, pick, offset;
|
||||
float ftmp, ftmp1, randvec[BLOCKL], pitchfact;
|
||||
|
||||
/* Packet Loss */
|
||||
|
||||
if (PLI == 1) {
|
||||
|
||||
(*iLBCdec_inst).consPLICount += 1;
|
||||
|
||||
/* if previous frame not lost,
|
||||
determine pitch pred. gain */
|
||||
|
||||
if ((*iLBCdec_inst).prevPLI != 1) {
|
||||
|
||||
/* Search around the previous lag to find the
|
||||
best pitch period */
|
||||
|
||||
lag=inlag-3;
|
||||
compCorr(&maxcc, &gain, (*iLBCdec_inst).prevResidual,
|
||||
lag, BLOCKL, 60);
|
||||
for (i=inlag-2;i<=inlag+3;i++) {
|
||||
compCorr(&maxcc_comp, &gain_comp,
|
||||
(*iLBCdec_inst).prevResidual,
|
||||
i, BLOCKL, 60);
|
||||
|
||||
if (maxcc_comp>maxcc) {
|
||||
maxcc=maxcc_comp;
|
||||
gain=gain_comp;
|
||||
lag=i;
|
||||
}
|
||||
}
|
||||
|
||||
if (gain > 1.0) {
|
||||
gain = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
/* previous frame lost, use recorded lag and gain */
|
||||
|
||||
else {
|
||||
lag=(*iLBCdec_inst).prevLag;
|
||||
gain=(*iLBCdec_inst).prevGain;
|
||||
}
|
||||
|
||||
/* Attenuate signal and scale down pitch pred gain if
|
||||
several frames lost consecutively */
|
||||
|
||||
|
||||
if ((*iLBCdec_inst).consPLICount > 1) {
|
||||
gain *= (float)0.9;
|
||||
}
|
||||
|
||||
/* Compute mixing factor of picth repeatition and noise */
|
||||
|
||||
|
||||
if (gain > PLC_XT_MIX) {
|
||||
pitchfact = PLC_YT_MIX;
|
||||
} else if (gain < PLC_XB_MIX) {
|
||||
pitchfact = PLC_YB_MIX;
|
||||
} else {
|
||||
pitchfact = PLC_YB_MIX + (gain - PLC_XB_MIX) *
|
||||
(PLC_YT_MIX-PLC_YB_MIX)/(PLC_XT_MIX-PLC_XB_MIX);
|
||||
}
|
||||
|
||||
/* compute concealed residual */
|
||||
|
||||
(*iLBCdec_inst).energy = 0.0;
|
||||
for (i=0; i<BLOCKL; i++) {
|
||||
|
||||
/* noise component */
|
||||
|
||||
(*iLBCdec_inst).seed=((*iLBCdec_inst).seed*69069L+1) &
|
||||
(0x80000000L-1);
|
||||
randlag = 50 + ((signed long) (*iLBCdec_inst).seed)%70;
|
||||
pick = i - randlag;
|
||||
|
||||
if (pick < 0) {
|
||||
randvec[i] = gain *
|
||||
(*iLBCdec_inst).prevResidual[BLOCKL+pick];
|
||||
} else {
|
||||
randvec[i] = gain * randvec[pick];
|
||||
}
|
||||
|
||||
/* pitch repeatition component */
|
||||
|
||||
pick = i - lag;
|
||||
|
||||
if (pick < 0) {
|
||||
PLCresidual[i] = gain *
|
||||
(*iLBCdec_inst).prevResidual[BLOCKL+pick];
|
||||
} else {
|
||||
PLCresidual[i] = gain * PLCresidual[pick];
|
||||
}
|
||||
|
||||
/* mix noise and pitch repeatition */
|
||||
|
||||
PLCresidual[i] = (pitchfact * PLCresidual[i] +
|
||||
((float)1.0 - pitchfact) * randvec[i]);
|
||||
|
||||
(*iLBCdec_inst).energy += PLCresidual[i] *
|
||||
PLCresidual[i];
|
||||
}
|
||||
|
||||
/* less than 30 dB, use only noise */
|
||||
|
||||
if (sqrt((*iLBCdec_inst).energy/(float)BLOCKL) < 30.0) {
|
||||
(*iLBCdec_inst).energy = 0.0;
|
||||
gain=0.0;
|
||||
for (i=0; i<BLOCKL; i++) {
|
||||
PLCresidual[i] = randvec[i];
|
||||
(*iLBCdec_inst).energy += PLCresidual[i] *
|
||||
PLCresidual[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* conceal LPC by bandwidth expansion of old LPC */
|
||||
|
||||
ftmp=PLC_BWEXPAND;
|
||||
PLClpc[0]=(float)1.0;
|
||||
for (i=1; i<LPC_FILTERORDER+1; i++) {
|
||||
PLClpc[i] = ftmp * (*iLBCdec_inst).prevLpc[i];
|
||||
ftmp *= PLC_BWEXPAND;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* previous frame lost and this frame OK, mixing in
|
||||
with new frame */
|
||||
|
||||
else if ((*iLBCdec_inst).prevPLI == 1) {
|
||||
|
||||
lag = (*iLBCdec_inst).prevLag;
|
||||
gain = (*iLBCdec_inst).prevGain;
|
||||
|
||||
/* if pitch pred gain high, do overlap-add */
|
||||
|
||||
if (gain >= PLC_GAINTHRESHOLD) {
|
||||
|
||||
/* Compute mixing factor of pitch repeatition
|
||||
and noise */
|
||||
|
||||
if (gain > PLC_XT_MIX) {
|
||||
pitchfact = PLC_YT_MIX;
|
||||
} else if (gain < PLC_XB_MIX) {
|
||||
pitchfact = PLC_YB_MIX;
|
||||
} else {
|
||||
pitchfact = PLC_YB_MIX + (gain - PLC_XB_MIX) *
|
||||
(PLC_YT_MIX-PLC_YB_MIX)/(PLC_XT_MIX-PLC_XB_MIX);
|
||||
}
|
||||
|
||||
/* compute concealed residual for 3 subframes */
|
||||
|
||||
for (i=0; i<3*SUBL; i++) {
|
||||
|
||||
(*iLBCdec_inst).seed=((*iLBCdec_inst).seed*
|
||||
69069L+1) & (0x80000000L-1);
|
||||
randlag = 50 + ((signed long)
|
||||
(*iLBCdec_inst).seed)%70;
|
||||
|
||||
/* noise component */
|
||||
|
||||
pick = i - randlag;
|
||||
|
||||
if (pick < 0) {
|
||||
randvec[i] = gain *
|
||||
(*iLBCdec_inst).prevResidual[BLOCKL+pick];
|
||||
} else {
|
||||
randvec[i] = gain * randvec[pick];
|
||||
}
|
||||
|
||||
/* pitch repeatition component */
|
||||
|
||||
pick = i - lag;
|
||||
|
||||
if (pick < 0) {
|
||||
PLCresidual[i] = gain *
|
||||
(*iLBCdec_inst).prevResidual[BLOCKL+pick];
|
||||
} else {
|
||||
PLCresidual[i] = gain * PLCresidual[pick];
|
||||
}
|
||||
|
||||
/* mix noise and pitch repeatition */
|
||||
|
||||
PLCresidual[i] = (pitchfact * PLCresidual[i] +
|
||||
((float)1.0 - pitchfact) * randvec[i]);
|
||||
}
|
||||
|
||||
/* interpolate concealed residual with actual
|
||||
residual */
|
||||
|
||||
offset = 3*SUBL;
|
||||
for (i=0; i<offset; i++) {
|
||||
ftmp1 = (float) (i+1) / (float) (offset+1);
|
||||
ftmp = (float)1.0 - ftmp1;
|
||||
PLCresidual[i]=PLCresidual[i]*ftmp+
|
||||
decresidual[i]*ftmp1;
|
||||
}
|
||||
|
||||
memcpy(PLCresidual+offset, decresidual+offset,
|
||||
(BLOCKL-offset)*sizeof(float));
|
||||
|
||||
} else {
|
||||
memcpy(PLCresidual, decresidual, BLOCKL*sizeof(float));
|
||||
}
|
||||
|
||||
/* copy LPC */
|
||||
|
||||
memcpy(PLClpc, lpc, (LPC_FILTERORDER+1)*sizeof(float));
|
||||
|
||||
(*iLBCdec_inst).consPLICount = 0;
|
||||
}
|
||||
|
||||
/* no packet loss, copy input */
|
||||
|
||||
else {
|
||||
memcpy(PLCresidual, decresidual, BLOCKL*sizeof(float));
|
||||
memcpy(PLClpc, lpc, (LPC_FILTERORDER+1)*sizeof(float));
|
||||
}
|
||||
|
||||
/* update state */
|
||||
|
||||
(*iLBCdec_inst).prevLag = lag;
|
||||
(*iLBCdec_inst).prevGain = gain;
|
||||
(*iLBCdec_inst).prevPLI = PLI;
|
||||
memcpy((*iLBCdec_inst).prevLpc, PLClpc,
|
||||
(LPC_FILTERORDER+1)*sizeof(float));
|
||||
memcpy((*iLBCdec_inst).prevResidual, PLCresidual,
|
||||
BLOCKL*sizeof(float));
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user