mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 02:37:10 +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