Mercurial > hg > audiostuff
diff intercom/ilbc/iLBC_decode.c @ 2:13be24d74cd2
import intercom-0.4.1
author | Peter Meerwald <pmeerw@cosy.sbg.ac.at> |
---|---|
date | Fri, 25 Jun 2010 09:57:52 +0200 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/intercom/ilbc/iLBC_decode.c Fri Jun 25 09:57:52 2010 +0200 @@ -0,0 +1,619 @@ + + /****************************************************************** + + 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 (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; + } +}