/****************************************************************** | |
iLBC Speech Coder ANSI-C Source Code | |
iLBC_decode.c | |
Copyright (C) The Internet Society (2004). | |
All Rights Reserved. | |
******************************************************************/ | |
#include <math.h> | |
#include <stdlib.h> | |
#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 "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 mode, /* (i) frame size mode */ | |
int use_enhancer /* (i) 1 to use enhancer | |
0 to run without | |
enhancer */ | |
){ | |
int i; | |
iLBCdec_inst->mode = mode; | |
if (mode==30) { | |
iLBCdec_inst->blockl = BLOCKL_30MS; | |
iLBCdec_inst->nsub = NSUB_30MS; | |
iLBCdec_inst->nasub = NASUB_30MS; | |
iLBCdec_inst->lpc_n = LPC_N_30MS; | |
iLBCdec_inst->no_of_bytes = NO_OF_BYTES_30MS; | |
iLBCdec_inst->no_of_words = NO_OF_WORDS_30MS; | |
iLBCdec_inst->state_short_len=STATE_SHORT_LEN_30MS; | |
/* ULP init */ | |
iLBCdec_inst->ULP_inst=&ULP_30msTbl; | |
} | |
else if (mode==20) { | |
iLBCdec_inst->blockl = BLOCKL_20MS; | |
iLBCdec_inst->nsub = NSUB_20MS; | |
iLBCdec_inst->nasub = NASUB_20MS; | |
iLBCdec_inst->lpc_n = LPC_N_20MS; | |
iLBCdec_inst->no_of_bytes = NO_OF_BYTES_20MS; | |
iLBCdec_inst->no_of_words = NO_OF_WORDS_20MS; | |
iLBCdec_inst->state_short_len=STATE_SHORT_LEN_20MS; | |
/* ULP init */ | |
iLBCdec_inst->ULP_inst=&ULP_20msTbl; | |
} | |
else { | |
exit(2); | |
} | |
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_MAX)*sizeof(float)); | |
for (i=0; i<NSUB_MAX; i++) | |
iLBCdec_inst->old_syntdenum[i*(LPC_FILTERORDER+1)]=1.0; | |
iLBCdec_inst->last_lag = 20; | |
iLBCdec_inst->prevLag = 120; | |
iLBCdec_inst->per = 0.0; | |
iLBCdec_inst->consPLICount = 0; | |
iLBCdec_inst->prevPLI = 0; | |
iLBCdec_inst->prevLpc[0] = 1.0; | |
memset(iLBCdec_inst->prevLpc+1,0, | |
LPC_FILTERORDER*sizeof(float)); | |
memset(iLBCdec_inst->prevResidual, 0, BLOCKL_MAX*sizeof(float)); | |
iLBCdec_inst->seed=777; | |
memset(iLBCdec_inst->hpomem, 0, 4*sizeof(float)); | |
iLBCdec_inst->use_enhancer = use_enhancer; | |
memset(iLBCdec_inst->enh_buf, 0, ENH_BUFL*sizeof(float)); | |
for (i=0;i<ENH_NBLOCKS_TOT;i++) | |
iLBCdec_inst->enh_period[i]=(float)40.0; | |
iLBCdec_inst->prev_enh_pl = 0; | |
return (short)(iLBCdec_inst->blockl); | |
} | |
/*----------------------------------------------------------------* | |
* frame residual decoder function (subrutine to iLBC_decode) | |
*---------------------------------------------------------------*/ | |
void Decode( | |
iLBC_Dec_Inst_t *iLBCdec_inst, /* (i/o) the decoder state | |
structure */ | |
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_MAX], mem[CB_MEML]; | |
int k, meml_gotten, Nfor, Nback, i; | |
int diff, start_pos; | |
int subcount, subframe; | |
diff = STATE_LEN - iLBCdec_inst->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], iLBCdec_inst->state_short_len); | |
if (state_first) { /* put adaptive part in the end */ | |
/* setup memory */ | |
memset(mem, 0, | |
(CB_MEML-iLBCdec_inst->state_short_len)*sizeof(float)); | |
memcpy(mem+CB_MEML-iLBCdec_inst->state_short_len, | |
decresidual+start_pos, | |
iLBCdec_inst->state_short_len*sizeof(float)); | |
/* construct decoded vector */ | |
iCBConstruct( | |
&decresidual[start_pos+iLBCdec_inst->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<diff; k++) { | |
reverseDecresidual[k] = | |
decresidual[(start+1)*SUBL-1- | |
(k+iLBCdec_inst->state_short_len)]; | |
} | |
/* setup memory */ | |
meml_gotten = iLBCdec_inst->state_short_len; | |
for (k=0; k<meml_gotten; k++){ | |
mem[CB_MEML-1-k] = decresidual[start_pos + k]; | |
} | |
memset(mem, 0, (CB_MEML-k)*sizeof(float)); | |
/* construct decoded vector */ | |
iCBConstruct(reverseDecresidual, extra_cb_index, | |
extra_gain_index, mem+CB_MEML-stMemLTbl, stMemLTbl, | |
diff, CB_NSTAGES); | |
/* get decoded residual from reversed vector */ | |
for (k=0; k<diff; k++) { | |
decresidual[start_pos-1-k] = reverseDecresidual[k]; | |
} | |
} | |
/* counter for predicted sub-frames */ | |
subcount=0; | |
/* forward prediction of sub-frames */ | |
Nfor = iLBCdec_inst->nsub-start-1; | |
if ( Nfor > 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 sub-frames to encode */ | |
for (subframe=0; subframe<Nfor; subframe++) { | |
/* construct decoded vector */ | |
iCBConstruct(&decresidual[(start+1+subframe)*SUBL], | |
cb_index+subcount*CB_NSTAGES, | |
gain_index+subcount*CB_NSTAGES, | |
mem+CB_MEML-memLfTbl[subcount], | |
memLfTbl[subcount], SUBL, CB_NSTAGES); | |
/* update memory */ | |
memcpy(mem, mem+SUBL, (CB_MEML-SUBL)*sizeof(float)); | |
memcpy(mem+CB_MEML-SUBL, | |
&decresidual[(start+1+subframe)*SUBL], | |
SUBL*sizeof(float)); | |
subcount++; | |
} | |
} | |
/* backward prediction of sub-frames */ | |
Nback = start-1; | |
if ( Nback > 0 ) { | |
/* setup memory */ | |
meml_gotten = SUBL*(iLBCdec_inst->nsub+1-start); | |
if ( meml_gotten > CB_MEML ) { | |
meml_gotten=CB_MEML; | |
} | |
for (k=0; k<meml_gotten; k++) { | |
mem[CB_MEML-1-k] = decresidual[(start-1)*SUBL + k]; | |
} | |
memset(mem, 0, (CB_MEML-k)*sizeof(float)); | |
/* loop over subframes to decode */ | |
for (subframe=0; subframe<Nback; subframe++) { | |
/* construct decoded vector */ | |
iCBConstruct(&reverseDecresidual[subframe*SUBL], | |
cb_index+subcount*CB_NSTAGES, | |
gain_index+subcount*CB_NSTAGES, | |
mem+CB_MEML-memLfTbl[subcount], memLfTbl[subcount], | |
SUBL, CB_NSTAGES); | |
/* update memory */ | |
memcpy(mem, mem+SUBL, (CB_MEML-SUBL)*sizeof(float)); | |
memcpy(mem+CB_MEML-SUBL, | |
&reverseDecresidual[subframe*SUBL], | |
SUBL*sizeof(float)); | |
subcount++; | |
} | |
/* get decoded residual from reversed vector */ | |
for (i=0; i<SUBL*Nback; i++) | |
decresidual[SUBL*Nback - i - 1] = | |
reverseDecresidual[i]; | |
} | |
} | |
/*----------------------------------------------------------------* | |
* main decoder function | |
*---------------------------------------------------------------*/ | |
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 check; | |
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); | |
check=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; | |
} | |
} | |