Mercurial > hg > audiostuff
diff intercom/ilbc/iLBC_encode.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_encode.c Fri Jun 25 09:57:52 2010 +0200 @@ -0,0 +1,507 @@ + + /****************************************************************** + + iLBC Speech Coder ANSI-C Source Code + + iLBC_encode.c + + Copyright (C) The Internet Society (2004). + All Rights Reserved. + + ******************************************************************/ + +#include <math.h> +#include <stdlib.h> +#include <string.h> + +#include "iLBC_define.h" +#include "LPCencode.h" +#include "FrameClassify.h" +#include "StateSearchW.h" +#include "StateConstructW.h" +#include "helpfun.h" +#include "constants.h" +#include "packing.h" +#include "iCBSearch.h" +#include "iCBConstruct.h" +#include "hpInput.h" +#include "anaFilter.h" +#include "syntFilter.h" + + /*----------------------------------------------------------------* + * Initiation of encoder instance. + *---------------------------------------------------------------*/ + +short initEncode( /* (o) Number of bytes + encoded */ + iLBC_Enc_Inst_t * iLBCenc_inst, /* (i/o) Encoder instance */ + int mode /* (i) frame size mode */ + ) +{ + iLBCenc_inst->mode = mode; + if (mode == 30) { + iLBCenc_inst->blockl = BLOCKL_30MS; + iLBCenc_inst->nsub = NSUB_30MS; + iLBCenc_inst->nasub = NASUB_30MS; + iLBCenc_inst->lpc_n = LPC_N_30MS; + iLBCenc_inst->no_of_bytes = NO_OF_BYTES_30MS; + iLBCenc_inst->no_of_words = NO_OF_WORDS_30MS; + + + + + + iLBCenc_inst->state_short_len = STATE_SHORT_LEN_30MS; + /* ULP init */ + iLBCenc_inst->ULP_inst = &ULP_30msTbl; + } else if (mode == 20) { + iLBCenc_inst->blockl = BLOCKL_20MS; + iLBCenc_inst->nsub = NSUB_20MS; + iLBCenc_inst->nasub = NASUB_20MS; + iLBCenc_inst->lpc_n = LPC_N_20MS; + iLBCenc_inst->no_of_bytes = NO_OF_BYTES_20MS; + iLBCenc_inst->no_of_words = NO_OF_WORDS_20MS; + iLBCenc_inst->state_short_len = STATE_SHORT_LEN_20MS; + /* ULP init */ + iLBCenc_inst->ULP_inst = &ULP_20msTbl; + } else { + exit(2); + } + + memset((*iLBCenc_inst).anaMem, 0, LPC_FILTERORDER * sizeof(float)); + memcpy((*iLBCenc_inst).lsfold, lsfmeanTbl, + LPC_FILTERORDER * sizeof(float)); + memcpy((*iLBCenc_inst).lsfdeqold, lsfmeanTbl, + LPC_FILTERORDER * sizeof(float)); + memset((*iLBCenc_inst).lpc_buffer, 0, + (LPC_LOOKBACK + BLOCKL_MAX) * sizeof(float)); + memset((*iLBCenc_inst).hpimem, 0, 4 * sizeof(float)); + + return (iLBCenc_inst->no_of_bytes); +} + + /*----------------------------------------------------------------* + * main encoder function + *---------------------------------------------------------------*/ + +void iLBC_encode(unsigned char *bytes, /* (o) encoded data bits iLBC */ + float *block, /* (o) speech vector to + encode */ + iLBC_Enc_Inst_t * iLBCenc_inst /* (i/o) the general encoder + state */ + ) +{ + + float data[BLOCKL_MAX]; + float residual[BLOCKL_MAX], reverseResidual[BLOCKL_MAX]; + + int start, idxForMax, idxVec[STATE_LEN]; + + + + + + float reverseDecresidual[BLOCKL_MAX], mem[CB_MEML]; + int n, k, meml_gotten, Nfor, Nback, i, pos; + int gain_index[CB_NSTAGES * NASUB_MAX], 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]; + unsigned char *pbytes; + int diff, start_pos, state_first; + float en1, en2; + int index, ulp, firstpart; + int subcount, subframe; + float weightState[LPC_FILTERORDER]; + float syntdenum[NSUB_MAX * (LPC_FILTERORDER + 1)]; + float weightdenum[NSUB_MAX * (LPC_FILTERORDER + 1)]; + float decresidual[BLOCKL_MAX]; + + /* high pass filtering of input signal if such is not done + prior to calling this function */ + + hpInput(block, iLBCenc_inst->blockl, data, (*iLBCenc_inst).hpimem); + + /* otherwise simply copy */ + + /*memcpy(data,block,iLBCenc_inst->blockl*sizeof(float)); */ + + /* LPC of hp filtered input data */ + + LPCencode(syntdenum, weightdenum, lsf_i, data, iLBCenc_inst); + + + /* inverse filter to get residual */ + + for (n = 0; n < iLBCenc_inst->nsub; n++) { + anaFilter(&data[n * SUBL], &syntdenum[n * (LPC_FILTERORDER + 1)], + SUBL, &residual[n * SUBL], iLBCenc_inst->anaMem); + } + + /* find state location */ + + start = FrameClassify(iLBCenc_inst, residual); + + /* check if state should be in first or last part of the + two subframes */ + + diff = STATE_LEN - iLBCenc_inst->state_short_len; + en1 = 0; + index = (start - 1) * SUBL; + + + + + + for (i = 0; i < iLBCenc_inst->state_short_len; i++) { + en1 += residual[index + i] * residual[index + i]; + } + en2 = 0; + index = (start - 1) * SUBL + diff; + for (i = 0; i < iLBCenc_inst->state_short_len; i++) { + en2 += residual[index + i] * residual[index + i]; + } + + + if (en1 > en2) { + state_first = 1; + start_pos = (start - 1) * SUBL; + } else { + state_first = 0; + start_pos = (start - 1) * SUBL + diff; + } + + /* scalar quantization of state */ + + StateSearchW(iLBCenc_inst, &residual[start_pos], + &syntdenum[(start - 1) * (LPC_FILTERORDER + 1)], + &weightdenum[(start - 1) * (LPC_FILTERORDER + 1)], &idxForMax, + idxVec, iLBCenc_inst->state_short_len, state_first); + + StateConstructW(idxForMax, idxVec, + &syntdenum[(start - 1) * (LPC_FILTERORDER + 1)], + &decresidual[start_pos], iLBCenc_inst->state_short_len); + + /* predictive quantization in state */ + + if (state_first) { /* put adaptive part in the end */ + + /* setup memory */ + + memset(mem, 0, + (CB_MEML - iLBCenc_inst->state_short_len) * sizeof(float)); + memcpy(mem + CB_MEML - iLBCenc_inst->state_short_len, + decresidual + start_pos, + iLBCenc_inst->state_short_len * sizeof(float)); + memset(weightState, 0, LPC_FILTERORDER * sizeof(float)); + + /* encode sub-frames */ + + iCBSearch(iLBCenc_inst, extra_cb_index, extra_gain_index, + &residual[start_pos + iLBCenc_inst->state_short_len], + mem + CB_MEML - stMemLTbl, + stMemLTbl, diff, CB_NSTAGES, + &weightdenum[start * (LPC_FILTERORDER + 1)], weightState, 0); + + /* construct decoded vector */ + + iCBConstruct(&decresidual[start_pos + + iLBCenc_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++) { + reverseResidual[k] = residual[(start + 1) * SUBL - 1 + - (k + iLBCenc_inst->state_short_len)]; + } + + /* setup memory */ + + meml_gotten = iLBCenc_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)); + memset(weightState, 0, LPC_FILTERORDER * sizeof(float)); + + /* encode sub-frames */ + + iCBSearch(iLBCenc_inst, extra_cb_index, extra_gain_index, + reverseResidual, mem + CB_MEML - stMemLTbl, stMemLTbl, + diff, CB_NSTAGES, + &weightdenum[(start - 1) * (LPC_FILTERORDER + 1)], + weightState, 0); + + /* 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 = iLBCenc_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)); + memset(weightState, 0, LPC_FILTERORDER * sizeof(float)); + + /* loop over sub-frames to encode */ + + for (subframe = 0; subframe < Nfor; subframe++) { + + /* encode sub-frame */ + + iCBSearch(iLBCenc_inst, cb_index + subcount * CB_NSTAGES, + gain_index + subcount * CB_NSTAGES, + &residual[(start + 1 + subframe) * SUBL], + mem + CB_MEML - memLfTbl[subcount], + memLfTbl[subcount], SUBL, CB_NSTAGES, + &weightdenum[(start + 1 + subframe) * + (LPC_FILTERORDER + 1)], weightState, subcount + 1); + + /* 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)); + memset(weightState, 0, LPC_FILTERORDER * sizeof(float)); + + subcount++; + } + } + + + /* backward prediction of sub-frames */ + + Nback = start - 1; + + + if (Nback > 0) { + + /* create reverse order vectors */ + + for (n = 0; n < Nback; n++) { + for (k = 0; k < SUBL; k++) { + reverseResidual[n * SUBL + k] = + residual[(start - 1) * SUBL - 1 - n * SUBL - k]; + reverseDecresidual[n * SUBL + k] = + decresidual[(start - 1) * SUBL - 1 - n * SUBL - k]; + } + } + + /* setup memory */ + + meml_gotten = SUBL * (iLBCenc_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)); + memset(weightState, 0, LPC_FILTERORDER * sizeof(float)); + + /* loop over sub-frames to encode */ + + for (subframe = 0; subframe < Nback; subframe++) { + + /* encode sub-frame */ + + iCBSearch(iLBCenc_inst, cb_index + subcount * CB_NSTAGES, + gain_index + subcount * CB_NSTAGES, + &reverseResidual[subframe * SUBL], + mem + CB_MEML - memLfTbl[subcount], + memLfTbl[subcount], SUBL, CB_NSTAGES, + &weightdenum[(start - 2 - subframe) * + (LPC_FILTERORDER + 1)], weightState, subcount + 1); + + /* 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)); + memset(weightState, 0, LPC_FILTERORDER * sizeof(float)); + + subcount++; + + } + + /* get decoded residual from reversed vector */ + + for (i = 0; i < SUBL * Nback; i++) { + decresidual[SUBL * Nback - i - 1] = reverseDecresidual[i]; + } + } + /* end encoding part */ + + /* adjust index */ + index_conv_enc(cb_index); + + /* pack bytes */ + + pbytes = bytes; + pos = 0; + + /* loop over the 3 ULP classes */ + + for (ulp = 0; ulp < 3; ulp++) { + + + + + + + /* LSF */ + for (k = 0; k < LSF_NSPLIT * iLBCenc_inst->lpc_n; k++) { + packsplit(&lsf_i[k], &firstpart, &lsf_i[k], + iLBCenc_inst->ULP_inst->lsf_bits[k][ulp], + iLBCenc_inst->ULP_inst->lsf_bits[k][ulp] + + iLBCenc_inst->ULP_inst->lsf_bits[k][ulp + 1] + + iLBCenc_inst->ULP_inst->lsf_bits[k][ulp + 2]); + dopack(&pbytes, firstpart, + iLBCenc_inst->ULP_inst->lsf_bits[k][ulp], &pos); + } + + /* Start block info */ + + packsplit(&start, &firstpart, &start, + iLBCenc_inst->ULP_inst->start_bits[ulp], + iLBCenc_inst->ULP_inst->start_bits[ulp] + + iLBCenc_inst->ULP_inst->start_bits[ulp + 1] + + iLBCenc_inst->ULP_inst->start_bits[ulp + 2]); + dopack(&pbytes, firstpart, + iLBCenc_inst->ULP_inst->start_bits[ulp], &pos); + + packsplit(&state_first, &firstpart, &state_first, + iLBCenc_inst->ULP_inst->startfirst_bits[ulp], + iLBCenc_inst->ULP_inst->startfirst_bits[ulp] + + iLBCenc_inst->ULP_inst->startfirst_bits[ulp + 1] + + iLBCenc_inst->ULP_inst->startfirst_bits[ulp + 2]); + dopack(&pbytes, firstpart, + iLBCenc_inst->ULP_inst->startfirst_bits[ulp], &pos); + + packsplit(&idxForMax, &firstpart, &idxForMax, + iLBCenc_inst->ULP_inst->scale_bits[ulp], + iLBCenc_inst->ULP_inst->scale_bits[ulp] + + iLBCenc_inst->ULP_inst->scale_bits[ulp + 1] + + iLBCenc_inst->ULP_inst->scale_bits[ulp + 2]); + dopack(&pbytes, firstpart, + iLBCenc_inst->ULP_inst->scale_bits[ulp], &pos); + + for (k = 0; k < iLBCenc_inst->state_short_len; k++) { + packsplit(idxVec + k, &firstpart, idxVec + k, + iLBCenc_inst->ULP_inst->state_bits[ulp], + iLBCenc_inst->ULP_inst->state_bits[ulp] + + iLBCenc_inst->ULP_inst->state_bits[ulp + 1] + + iLBCenc_inst->ULP_inst->state_bits[ulp + 2]); + dopack(&pbytes, firstpart, + iLBCenc_inst->ULP_inst->state_bits[ulp], &pos); + } + + + + + + + /* 23/22 (20ms/30ms) sample block */ + + for (k = 0; k < CB_NSTAGES; k++) { + packsplit(extra_cb_index + k, &firstpart, + extra_cb_index + k, + iLBCenc_inst->ULP_inst->extra_cb_index[k][ulp], + iLBCenc_inst->ULP_inst->extra_cb_index[k][ulp] + + iLBCenc_inst->ULP_inst->extra_cb_index[k][ulp + 1] + + iLBCenc_inst->ULP_inst->extra_cb_index[k][ulp + 2]); + dopack(&pbytes, firstpart, + iLBCenc_inst->ULP_inst->extra_cb_index[k][ulp], &pos); + } + + for (k = 0; k < CB_NSTAGES; k++) { + packsplit(extra_gain_index + k, &firstpart, + extra_gain_index + k, + iLBCenc_inst->ULP_inst->extra_cb_gain[k][ulp], + iLBCenc_inst->ULP_inst->extra_cb_gain[k][ulp] + + iLBCenc_inst->ULP_inst->extra_cb_gain[k][ulp + 1] + + iLBCenc_inst->ULP_inst->extra_cb_gain[k][ulp + 2]); + dopack(&pbytes, firstpart, + iLBCenc_inst->ULP_inst->extra_cb_gain[k][ulp], &pos); + } + + /* The two/four (20ms/30ms) 40 sample sub-blocks */ + + for (i = 0; i < iLBCenc_inst->nasub; i++) { + for (k = 0; k < CB_NSTAGES; k++) { + packsplit(cb_index + i * CB_NSTAGES + k, &firstpart, + cb_index + i * CB_NSTAGES + k, + iLBCenc_inst->ULP_inst->cb_index[i][k][ulp], + iLBCenc_inst->ULP_inst->cb_index[i][k][ulp] + + iLBCenc_inst->ULP_inst->cb_index[i][k][ulp + 1] + + iLBCenc_inst->ULP_inst->cb_index[i][k][ulp + 2]); + dopack(&pbytes, firstpart, + iLBCenc_inst->ULP_inst->cb_index[i][k][ulp], &pos); + } + } + + for (i = 0; i < iLBCenc_inst->nasub; i++) { + for (k = 0; k < CB_NSTAGES; k++) { + packsplit(gain_index + i * CB_NSTAGES + k, &firstpart, + gain_index + i * CB_NSTAGES + k, + iLBCenc_inst->ULP_inst->cb_gain[i][k][ulp], + iLBCenc_inst->ULP_inst->cb_gain[i][k][ulp] + + iLBCenc_inst->ULP_inst->cb_gain[i][k][ulp + 1] + + iLBCenc_inst->ULP_inst->cb_gain[i][k][ulp + 2]); + dopack(&pbytes, firstpart, + iLBCenc_inst->ULP_inst->cb_gain[i][k][ulp], &pos); + } + } + } + + /* set the last bit to zero (otherwise the decoder + will treat it as a lost frame) */ + dopack(&pbytes, 0, 1, &pos); +}