int enhancerInterface( float *out, /* (o) enhanced signal */ float *in, /* (i) unenhanced signal */ iLBC_Dec_Inst_t *iLBCdec_inst /* (i) buffers etc */ ){ float *enh_buf, *enh_period; int iblock, isample; int lag=0, ilag, i, ioffset; float cc, maxcc; float ftmp1, ftmp2; float *inPtr, *enh_bufPtr1, *enh_bufPtr2; float plc_pred[ENH_BLOCKL]; float lpState[6], downsampled[(ENH_NBLOCKS*ENH_BLOCKL+120)/2]; int inLen=ENH_NBLOCKS*ENH_BLOCKL+120; int start, plc_blockl, inlag; enh_buf=iLBCdec_inst->enh_buf; enh_period=iLBCdec_inst->enh_period; memmove(enh_buf, &enh_buf[iLBCdec_inst->blockl], (ENH_BUFL-iLBCdec_inst->blockl)*sizeof(float)); memcpy(&enh_buf[ENH_BUFL-iLBCdec_inst->blockl], in, iLBCdec_inst->blockl*sizeof(float)); if (iLBCdec_inst->mode==30) plc_blockl=ENH_BLOCKL; else plc_blockl=40; /* when 20 ms frame, move processing one block */ ioffset=0; if (iLBCdec_inst->mode==20) ioffset=1; i=3-ioffset; memmove(enh_period, &enh_period[i], (ENH_NBLOCKS_TOT-i)*sizeof(float)); /* Set state information to the 6 samples right before the samples to be downsampled. */ memcpy(lpState, enh_buf+(ENH_NBLOCKS_EXTRA+ioffset)*ENH_BLOCKL-126, 6*sizeof(float)); /* Down sample a factor 2 to save computations */ DownSample(enh_buf+(ENH_NBLOCKS_EXTRA+ioffset)*ENH_BLOCKL-120, lpFilt_coefsTbl, inLen-ioffset*ENH_BLOCKL, lpState, downsampled); /* Estimate the pitch in the down sampled domain. */ for (iblock = 0; iblock<ENH_NBLOCKS-ioffset; iblock++) { lag = 10; maxcc = xCorrCoef(downsampled+60+iblock* ENH_BLOCKL_HALF, downsampled+60+iblock* ENH_BLOCKL_HALF-lag, ENH_BLOCKL_HALF); for (ilag=11; ilag<60; ilag++) { cc = xCorrCoef(downsampled+60+iblock* ENH_BLOCKL_HALF, downsampled+60+iblock* ENH_BLOCKL_HALF-ilag, ENH_BLOCKL_HALF); if (cc > maxcc) { maxcc = cc; lag = ilag; } } /* Store the estimated lag in the non-downsampled domain */ enh_period[iblock+ENH_NBLOCKS_EXTRA+ioffset] = (float)lag*2; } /* PLC was performed on the previous packet */ if (iLBCdec_inst->prev_enh_pl==1) { inlag=(int)enh_period[ENH_NBLOCKS_EXTRA+ioffset]; lag = inlag-1; maxcc = xCorrCoef(in, in+lag, plc_blockl); for (ilag=inlag; ilag<=inlag+1; ilag++) { cc = xCorrCoef(in, in+ilag, plc_blockl); if (cc > maxcc) { maxcc = cc; lag = ilag; } } enh_period[ENH_NBLOCKS_EXTRA+ioffset-1]=(float)lag; /* compute new concealed residual for the old lookahead, mix the forward PLC with a backward PLC from the new frame */ inPtr=&in[lag-1]; enh_bufPtr1=&plc_pred[plc_blockl-1]; if (lag>plc_blockl) { start=plc_blockl; } else { start=lag; } for (isample = start; isample>0; isample--) { *enh_bufPtr1-- = *inPtr--; } enh_bufPtr2=&enh_buf[ENH_BUFL-1-iLBCdec_inst->blockl]; for (isample = (plc_blockl-1-lag); isample>=0; isample--) { *enh_bufPtr1-- = *enh_bufPtr2--; } /* limit energy change */ ftmp2=0.0; ftmp1=0.0; for (i=0;i<plc_blockl;i++) { ftmp2+=enh_buf[ENH_BUFL-1-iLBCdec_inst->blockl-i]* enh_buf[ENH_BUFL-1-iLBCdec_inst->blockl-i]; ftmp1+=plc_pred[i]*plc_pred[i]; } ftmp1=(float)sqrt(ftmp1/(float)plc_blockl); ftmp2=(float)sqrt(ftmp2/(float)plc_blockl); if (ftmp1>(float)2.0*ftmp2 && ftmp1>0.0) { for (i=0;i<plc_blockl-10;i++) { plc_pred[i]*=(float)2.0*ftmp2/ftmp1; } for (i=plc_blockl-10;i<plc_blockl;i++) { plc_pred[i]*=(float)(i-plc_blockl+10)* ((float)1.0-(float)2.0*ftmp2/ftmp1)/(float)(10)+ (float)2.0*ftmp2/ftmp1; } } enh_bufPtr1=&enh_buf[ENH_BUFL-1-iLBCdec_inst->blockl]; for (i=0; i<plc_blockl; i++) { ftmp1 = (float) (i+1) / (float) (plc_blockl+1); *enh_bufPtr1 *= ftmp1; *enh_bufPtr1 += ((float)1.0-ftmp1)* plc_pred[plc_blockl-1-i]; enh_bufPtr1--; } } if (iLBCdec_inst->mode==20) { /* Enhancer with 40 samples delay */ for (iblock = 0; iblock<2; iblock++) { enhancer(out+iblock*ENH_BLOCKL, enh_buf, ENH_BUFL, (5+iblock)*ENH_BLOCKL+40, ENH_ALPHA0, enh_period, enh_plocsTbl, ENH_NBLOCKS_TOT); } } else if (iLBCdec_inst->mode==30) { /* Enhancer with 80 samples delay */ for (iblock = 0; iblock<3; iblock++) { enhancer(out+iblock*ENH_BLOCKL, enh_buf, ENH_BUFL, (4+iblock)*ENH_BLOCKL, ENH_ALPHA0, enh_period, enh_plocsTbl, ENH_NBLOCKS_TOT); } } return (lag*2); }
void iLBC_decode( float *decblock, /* (o) decoded signal block */ unsigned char *bytes, /* (i) encoded signal bits */ iLBC_Dec_Inst_t *iLBCdec_inst, /* (i/o) the decoder state structure */ int mode /* (i) 0: bad packet, PLC, 1: normal */ ){ float data[BLOCKL_MAX]; float lsfdeq[LPC_FILTERORDER*LPC_N_MAX]; float PLCresidual[BLOCKL_MAX], PLClpc[LPC_FILTERORDER + 1]; float zeros[BLOCKL_MAX], one[LPC_FILTERORDER + 1]; int k, i, start, idxForMax, pos, lastpart, ulp; int lag, ilag; float cc, maxcc; int idxVec[STATE_LEN]; int gain_index[NASUB_MAX*CB_NSTAGES], extra_gain_index[CB_NSTAGES]; int cb_index[CB_NSTAGES*NASUB_MAX], extra_cb_index[CB_NSTAGES]; int lsf_i[LSF_NSPLIT*LPC_N_MAX]; int state_first; int last_bit; unsigned char *pbytes; float weightdenum[(LPC_FILTERORDER + 1)*NSUB_MAX]; int order_plus_one; float syntdenum[NSUB_MAX*(LPC_FILTERORDER+1)]; float decresidual[BLOCKL_MAX]; if (mode>0) { /* the data are good */ /* decode data */ pbytes=bytes; pos=0; /* Set everything to zero before decoding */ for (k=0; k<LSF_NSPLIT*LPC_N_MAX; k++) { lsf_i[k]=0; } start=0; state_first=0; idxForMax=0; for (k=0; k<iLBCdec_inst->state_short_len; k++) { idxVec[k]=0; } for (k=0; k<CB_NSTAGES; k++) { extra_cb_index[k]=0; } for (k=0; k<CB_NSTAGES; k++) { extra_gain_index[k]=0; } for (i=0; i<iLBCdec_inst->nasub; i++) { for (k=0; k<CB_NSTAGES; k++) { cb_index[i*CB_NSTAGES+k]=0; } } for (i=0; i<iLBCdec_inst->nasub; i++) { for (k=0; k<CB_NSTAGES; k++) { gain_index[i*CB_NSTAGES+k]=0; } } /* loop over ULP classes */ for (ulp=0; ulp<3; ulp++) { /* LSF */ for (k=0; k<LSF_NSPLIT*iLBCdec_inst->lpc_n; k++){ unpack( &pbytes, &lastpart, iLBCdec_inst->ULP_inst->lsf_bits[k][ulp], &pos); packcombine(&lsf_i[k], lastpart, iLBCdec_inst->ULP_inst->lsf_bits[k][ulp]); } /* Start block info */ unpack( &pbytes, &lastpart, iLBCdec_inst->ULP_inst->start_bits[ulp], &pos); packcombine(&start, lastpart, iLBCdec_inst->ULP_inst->start_bits[ulp]); unpack( &pbytes, &lastpart, iLBCdec_inst->ULP_inst->startfirst_bits[ulp], &pos); packcombine(&state_first, lastpart, iLBCdec_inst->ULP_inst->startfirst_bits[ulp]); unpack( &pbytes, &lastpart, iLBCdec_inst->ULP_inst->scale_bits[ulp], &pos); packcombine(&idxForMax, lastpart, iLBCdec_inst->ULP_inst->scale_bits[ulp]); for (k=0; k<iLBCdec_inst->state_short_len; k++) { unpack( &pbytes, &lastpart, iLBCdec_inst->ULP_inst->state_bits[ulp], &pos); packcombine(idxVec+k, lastpart, iLBCdec_inst->ULP_inst->state_bits[ulp]); } /* 23/22 (20ms/30ms) sample block */ for (k=0; k<CB_NSTAGES; k++) { unpack( &pbytes, &lastpart, iLBCdec_inst->ULP_inst->extra_cb_index[k][ulp], &pos); packcombine(extra_cb_index+k, lastpart, iLBCdec_inst->ULP_inst->extra_cb_index[k][ulp]); } for (k=0; k<CB_NSTAGES; k++) { unpack( &pbytes, &lastpart, iLBCdec_inst->ULP_inst->extra_cb_gain[k][ulp], &pos); packcombine(extra_gain_index+k, lastpart, iLBCdec_inst->ULP_inst->extra_cb_gain[k][ulp]); } /* The two/four (20ms/30ms) 40 sample sub-blocks */ for (i=0; i<iLBCdec_inst->nasub; i++) { for (k=0; k<CB_NSTAGES; k++) { unpack( &pbytes, &lastpart, iLBCdec_inst->ULP_inst->cb_index[i][k][ulp], &pos); packcombine(cb_index+i*CB_NSTAGES+k, lastpart, iLBCdec_inst->ULP_inst->cb_index[i][k][ulp]); } } for (i=0; i<iLBCdec_inst->nasub; i++) { for (k=0; k<CB_NSTAGES; k++) { unpack( &pbytes, &lastpart, iLBCdec_inst->ULP_inst->cb_gain[i][k][ulp], &pos); packcombine(gain_index+i*CB_NSTAGES+k, lastpart, iLBCdec_inst->ULP_inst->cb_gain[i][k][ulp]); } } } /* Extract last bit. If it is 1 this indicates an empty/lost frame */ unpack( &pbytes, &last_bit, 1, &pos); /* Check for bit errors or empty/lost frames */ if (start<1) mode = 0; if (iLBCdec_inst->mode==20 && start>3) mode = 0; if (iLBCdec_inst->mode==30 && start>5) mode = 0; if (last_bit==1) mode = 0; if (mode==1) { /* No bit errors was detected, continue decoding */ /* adjust index */ index_conv_dec(cb_index); /* decode the lsf */ SimplelsfDEQ(lsfdeq, lsf_i, iLBCdec_inst->lpc_n); LSF_check(lsfdeq, LPC_FILTERORDER, iLBCdec_inst->lpc_n); DecoderInterpolateLSF(syntdenum, weightdenum, lsfdeq, LPC_FILTERORDER, iLBCdec_inst); Decode(iLBCdec_inst, decresidual, start, idxForMax, idxVec, syntdenum, cb_index, gain_index, extra_cb_index, extra_gain_index, state_first); /* preparing the plc for a future loss! */ doThePLC(PLCresidual, PLClpc, 0, decresidual, syntdenum + (LPC_FILTERORDER + 1)*(iLBCdec_inst->nsub - 1), (*iLBCdec_inst).last_lag, iLBCdec_inst); memcpy(decresidual, PLCresidual, iLBCdec_inst->blockl*sizeof(float)); } } if (mode == 0) { /* the data is bad (either a PLC call * was made or a severe bit error was detected) */ /* packet loss conceal */ memset(zeros, 0, BLOCKL_MAX*sizeof(float)); one[0] = 1; memset(one+1, 0, LPC_FILTERORDER*sizeof(float)); start=0; doThePLC(PLCresidual, PLClpc, 1, zeros, one, (*iLBCdec_inst).last_lag, iLBCdec_inst); memcpy(decresidual, PLCresidual, iLBCdec_inst->blockl*sizeof(float)); order_plus_one = LPC_FILTERORDER + 1; for (i = 0; i < iLBCdec_inst->nsub; i++) { memcpy(syntdenum+(i*order_plus_one), PLClpc, order_plus_one*sizeof(float)); } } if (iLBCdec_inst->use_enhancer == 1) { /* post filtering */ iLBCdec_inst->last_lag = enhancerInterface(data, decresidual, iLBCdec_inst); /* synthesis filtering */ if (iLBCdec_inst->mode==20) { /* Enhancer has 40 samples delay */ i=0; syntFilter(data + i*SUBL, iLBCdec_inst->old_syntdenum + (i+iLBCdec_inst->nsub-1)*(LPC_FILTERORDER+1), SUBL, iLBCdec_inst->syntMem); for (i=1; i < iLBCdec_inst->nsub; i++) { syntFilter(data + i*SUBL, syntdenum + (i-1)*(LPC_FILTERORDER+1), SUBL, iLBCdec_inst->syntMem); } } else if (iLBCdec_inst->mode==30) { /* Enhancer has 80 samples delay */ for (i=0; i < 2; i++) { syntFilter(data + i*SUBL, iLBCdec_inst->old_syntdenum + (i+iLBCdec_inst->nsub-2)*(LPC_FILTERORDER+1), SUBL, iLBCdec_inst->syntMem); } for (i=2; i < iLBCdec_inst->nsub; i++) { syntFilter(data + i*SUBL, syntdenum + (i-2)*(LPC_FILTERORDER+1), SUBL, iLBCdec_inst->syntMem); } } } else { /* Find last lag */ lag = 20; maxcc = xCorrCoef(&decresidual[BLOCKL_MAX-ENH_BLOCKL], &decresidual[BLOCKL_MAX-ENH_BLOCKL-lag], ENH_BLOCKL); for (ilag=21; ilag<120; ilag++) { cc = xCorrCoef(&decresidual[BLOCKL_MAX-ENH_BLOCKL], &decresidual[BLOCKL_MAX-ENH_BLOCKL-ilag], ENH_BLOCKL); if (cc > maxcc) { maxcc = cc; lag = ilag; } } iLBCdec_inst->last_lag = lag; /* copy data and run synthesis filter */ memcpy(data, decresidual, iLBCdec_inst->blockl*sizeof(float)); for (i=0; i < iLBCdec_inst->nsub; i++) { syntFilter(data + i*SUBL, syntdenum + i*(LPC_FILTERORDER+1), SUBL, iLBCdec_inst->syntMem); } } /* high pass filtering on output if desired, otherwise copy to out */ hpOutput(data, iLBCdec_inst->blockl, decblock,iLBCdec_inst->hpomem); /* memcpy(decblock,data,iLBCdec_inst->blockl*sizeof(float));*/ memcpy(iLBCdec_inst->old_syntdenum, syntdenum, iLBCdec_inst->nsub*(LPC_FILTERORDER+1)*sizeof(float)); iLBCdec_inst->prev_enh_pl=0; if (mode==0) { /* PLC was used */ iLBCdec_inst->prev_enh_pl=1; } }