/****************************************************************** iLBC Speech Coder ANSI-C Source Code iLBC_decode.c Copyright (c) 2001, Global IP Sound AB. All rights reserved. ******************************************************************/ #include #include #include "iLBC_define.h" #include "StateConstructW.h" #include "LPCdecode.h" #include "iCBConstruct.h" #include "doCPLC.h" #include "helpfun.h" #include "constants.h" #include "packing.h" #include "iLBC_decode.h" #include "string.h" #include "enhancer.h" #include "hpOutput.h" #include "syntFilter.h" /*----------------------------------------------------------------* * Initiation of decoder instance. *---------------------------------------------------------------*/ short initDecode( /* (o) Number of decoded samples */ iLBC_Dec_Inst_t *iLBCdec_inst, /* (i/o) Decoder instance */ int use_enhancer /* (i) 1 to use enhancer 0 to run without enhancer */ ){ int i; memset((*iLBCdec_inst).syntMem, 0, LPC_FILTERORDER*sizeof(float)); memcpy((*iLBCdec_inst).lsfdeqold, lsfmeanTbl, LPC_FILTERORDER*sizeof(float)); memset((*iLBCdec_inst).old_syntdenum, 0, ((LPC_FILTERORDER + 1)*NSUB)*sizeof(float)); for (i=0; iprev_enh_pl = 0; return (BLOCKL); } /*----------------------------------------------------------------* * frame residual decoder function (subrutine to iLBC_decode) *---------------------------------------------------------------*/ static void Decode( float *decresidual, /* (o) decoded residual frame */ int start, /* (i) location of start state */ int idxForMax, /* (i) codebook index for the maximum value */ int *idxVec, /* (i) codebook indexes for the samples in the start state */ float *syntdenum, /* (i) the decoded synthesis filter coefficients */ int *cb_index, /* (i) the indexes for the adaptive codebook */ int *gain_index, /* (i) the indexes for the corresponding gains */ int *extra_cb_index,/* (i) the indexes for the adaptive codebook part of start state */ int *extra_gain_index, /* (i) the indexes for the corresponding gains */ int state_first /* (i) 1 if non adaptive part of start state comes first 0 if that part comes last */ ){ float reverseDecresidual[BLOCKL], mem[CB_MEML]; int k, meml_gotten, Nfor, Nback, i; int diff, start_pos; int subcount, subframe; diff = STATE_LEN - STATE_SHORT_LEN; if (state_first == 1) { start_pos = (start-1)*SUBL; } else { start_pos = (start-1)*SUBL + diff; } /* decode scalar part of start state */ StateConstructW(idxForMax, idxVec, &syntdenum[(start-1)*(LPC_FILTERORDER+1)], &decresidual[start_pos], STATE_SHORT_LEN); if (state_first) { /* put adaptive part in the end */ /* setup memory */ memset(mem, 0, (CB_MEML-STATE_SHORT_LEN)*sizeof(float)); memcpy(mem+CB_MEML-STATE_SHORT_LEN, decresidual+start_pos, STATE_SHORT_LEN*sizeof(float)); /* construct decoded vector */ iCBConstruct(&decresidual[start_pos+STATE_SHORT_LEN], extra_cb_index, extra_gain_index, mem+CB_MEML-stMemLTbl, stMemLTbl, diff, CB_NSTAGES); } else {/* put adaptive part in the beginning */ /* create reversed vectors for prediction */ for(k=0; k 0 ){ /* setup memory */ memset(mem, 0, (CB_MEML-STATE_LEN)*sizeof(float)); memcpy(mem+CB_MEML-STATE_LEN, decresidual+(start-1)*SUBL, STATE_LEN*sizeof(float)); /* loop over subframes to encode */ for (subframe=0; subframe 0 ){ /* setup memory */ meml_gotten = SUBL*(NSUB+1-start); if( meml_gotten > CB_MEML ) { meml_gotten=CB_MEML; } for( k=0; k0) { /* the data are good */ /* decode data */ pbytes=bytes; pos=0; /* Set everything to zero before decoding */ for (k=0;k<6;k++) { lsf_i[k]=0; } start=0; state_first=0; idxForMax=0; for (k=0; k5) ) 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); check=LSF_check(lsfdeq, LPC_FILTERORDER, LPC_N); DecoderInterpolateLSF(syntdenum, weightdenum, lsfdeq, LPC_FILTERORDER, iLBCdec_inst); Decode(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)*(NSUB - 1), (*iLBCdec_inst).last_lag, iLBCdec_inst); memcpy(decresidual, PLCresidual, BLOCKL*sizeof(float)); } } if (mode == 0) { /* the data is bad (either a PLC call * was made or a bit error was detected) */ /* packet loss conceal */ memset(zeros, 0, BLOCKL*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, BLOCKL*sizeof(float)); order_plus_one = LPC_FILTERORDER + 1; for (i = 0; i < 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 */ for (i=0; i < 2; i++) { syntFilter(data + i*SUBL, (*iLBCdec_inst).old_syntdenum + (i+4)*(LPC_FILTERORDER+1), SUBL, (*iLBCdec_inst).syntMem); } for (i=2; i < 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-ENH_BLOCKL], &decresidual[BLOCKL-ENH_BLOCKL-lag], ENH_BLOCKL); for (ilag=21; ilag<120; ilag++) { cc = xCorrCoef(&decresidual[BLOCKL-ENH_BLOCKL], &decresidual[BLOCKL-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, BLOCKL*sizeof(float)); for (i=0; i < 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, BLOCKL, decblock, (*iLBCdec_inst).hpomem);*/ memcpy(decblock,data,BLOCKL*sizeof(float)); memcpy((*iLBCdec_inst).old_syntdenum, syntdenum, NSUB*(LPC_FILTERORDER+1)*sizeof(float)); iLBCdec_inst->prev_enh_pl=0; if (mode==0) { /* PLC was used */ iLBCdec_inst->prev_enh_pl=1; } }