651 lines
20 KiB
C
651 lines
20 KiB
C
|
|
/******************************************************************
|
|
|
|
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 (iLBCdec_inst->blockl);
|
|
}
|
|
|
|
/*----------------------------------------------------------------*
|
|
* frame residual decoder function (subroutine 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 */
|
|
|
|
memmove(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 */
|
|
|
|
memmove(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 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;
|
|
}
|
|
}
|