aboutsummaryrefslogtreecommitdiffstats
path: root/codecs/ilbc/iLBC_encode.c
diff options
context:
space:
mode:
authormarkster <markster@f38db490-d61c-443f-a65b-d21fe96a405b>2003-04-15 04:36:52 +0000
committermarkster <markster@f38db490-d61c-443f-a65b-d21fe96a405b>2003-04-15 04:36:52 +0000
commit9fa1f6563a431a73d7eb0c8a284e4cf419cbc2fa (patch)
tree468bcd1944564d1b84b5a9d46b2eb437fe3c73a3 /codecs/ilbc/iLBC_encode.c
parent0cc1bf692bcfc7f3f9ffef9d62c6621cd9ab9f4a (diff)
Add iLBC codec
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@852 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'codecs/ilbc/iLBC_encode.c')
-rwxr-xr-xcodecs/ilbc/iLBC_encode.c446
1 files changed, 446 insertions, 0 deletions
diff --git a/codecs/ilbc/iLBC_encode.c b/codecs/ilbc/iLBC_encode.c
new file mode 100755
index 000000000..6d8e04345
--- /dev/null
+++ b/codecs/ilbc/iLBC_encode.c
@@ -0,0 +1,446 @@
+
+/******************************************************************
+
+ iLBC Speech Coder ANSI-C Source Code
+
+ iLBC_encode.c
+
+ Copyright (c) 2001,
+ Global IP Sound AB.
+ All rights reserved.
+
+******************************************************************/
+
+#include <math.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 */
+){
+ 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*sizeof(float));
+ memset((*iLBCenc_inst).hpimem, 0, 4*sizeof(float));
+
+ return (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];
+ float residual[BLOCKL], reverseResidual[BLOCKL];
+
+ int start, idxForMax, idxVec[STATE_LEN];
+ float reverseDecresidual[BLOCKL], mem[CB_MEML];
+ int n, k, meml_gotten, Nfor, Nback, i, pos;
+ int gain_index[CB_NSTAGES*NASUB], extra_gain_index[CB_NSTAGES];
+ int cb_index[CB_NSTAGES*NASUB],extra_cb_index[CB_NSTAGES];
+ int lsf_i[LSF_NSPLIT*LPC_N];
+ 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*(LPC_FILTERORDER+1)];
+ float weightdenum[NSUB*(LPC_FILTERORDER+1)];
+ float decresidual[BLOCKL];
+
+ /* high pass filtering of input signal if such is not done
+ prior to calling this function */
+
+ /*hpInput(block, BLOCKL, data, (*iLBCenc_inst).hpimem);*/
+
+ /* otherwise simply copy */
+
+ memcpy(data,block,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<NSUB; n++ ) {
+ anaFilter(&data[n*SUBL], &syntdenum[n*(LPC_FILTERORDER+1)],
+ SUBL, &residual[n*SUBL], (*iLBCenc_inst).anaMem);
+ }
+
+ /* find state location */
+
+ start = FrameClassify(residual);
+
+ /* check if state should be in first or last part of the
+ two subframes */
+
+ diff = STATE_LEN - STATE_SHORT_LEN;
+ en1 = 0;
+ index = (start-1)*SUBL;
+ for (i = 0; i < STATE_SHORT_LEN; i++) {
+ en1 += residual[index+i]*residual[index+i];
+ }
+ en2 = 0;
+ index = (start-1)*SUBL+diff;
+ for (i = 0; i < 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(&residual[start_pos],
+ &syntdenum[(start-1)*(LPC_FILTERORDER+1)],
+ &weightdenum[(start-1)*(LPC_FILTERORDER+1)], &idxForMax,
+ idxVec, STATE_SHORT_LEN, state_first);
+
+ StateConstructW(idxForMax, idxVec,
+ &syntdenum[(start-1)*(LPC_FILTERORDER+1)],
+ &decresidual[start_pos], STATE_SHORT_LEN);
+
+ /* predictive quantization in state */
+
+ 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));
+ memset(weightState, 0, LPC_FILTERORDER*sizeof(float));
+
+ /* encode subframes */
+
+ iCBSearch(extra_cb_index, extra_gain_index,
+ &residual[start_pos+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+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+STATE_SHORT_LEN)];
+ }
+
+ /* setup memory */
+
+ meml_gotten = 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 subframes */
+
+ iCBSearch(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 subframes */
+
+ subcount=0;
+
+ /* forward prediction of subframes */
+
+ Nfor = 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 subframes to encode */
+
+ for (subframe=0; subframe<Nfor; subframe++) {
+
+ /* encode subframe */
+
+ iCBSearch(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 subframes */
+
+ 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*(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 subframes to encode */
+
+ for (subframe=0; subframe<Nback; subframe++) {
+
+ /* encode subframe */
+
+ iCBSearch(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<6;k++) {
+ packsplit(&lsf_i[k], &firstpart, &lsf_i[k],
+ ulp_lsf_bitsTbl[k][ulp],
+ ulp_lsf_bitsTbl[k][ulp]+
+ ulp_lsf_bitsTbl[k][ulp+1]+
+ ulp_lsf_bitsTbl[k][ulp+2]);
+ dopack( &pbytes, firstpart,
+ ulp_lsf_bitsTbl[k][ulp], &pos);
+ }
+
+ /* Start block info */
+
+ packsplit(&start, &firstpart, &start,
+ ulp_start_bitsTbl[ulp],
+ ulp_start_bitsTbl[ulp]+
+ ulp_start_bitsTbl[ulp+1]+
+ ulp_start_bitsTbl[ulp+2]);
+ dopack( &pbytes, firstpart,
+ ulp_start_bitsTbl[ulp], &pos);
+
+ packsplit(&state_first, &firstpart, &state_first,
+ ulp_startfirst_bitsTbl[ulp],
+ ulp_startfirst_bitsTbl[ulp]+
+ ulp_startfirst_bitsTbl[ulp+1]+
+ ulp_startfirst_bitsTbl[ulp+2]);
+ dopack( &pbytes, firstpart,
+ ulp_startfirst_bitsTbl[ulp], &pos);
+
+ packsplit(&idxForMax, &firstpart, &idxForMax,
+ ulp_scale_bitsTbl[ulp], ulp_scale_bitsTbl[ulp]+
+ ulp_scale_bitsTbl[ulp+1]+ulp_scale_bitsTbl[ulp+2]);
+ dopack( &pbytes, firstpart,
+ ulp_scale_bitsTbl[ulp], &pos);
+
+ for (k=0; k<STATE_SHORT_LEN; k++) {
+ packsplit(idxVec+k, &firstpart, idxVec+k,
+ ulp_state_bitsTbl[ulp],
+ ulp_state_bitsTbl[ulp]+
+ ulp_state_bitsTbl[ulp+1]+
+ ulp_state_bitsTbl[ulp+2]);
+ dopack( &pbytes, firstpart,
+ ulp_state_bitsTbl[ulp], &pos);
+ }
+
+ /* 22 sample block */
+
+ for (k=0;k<CB_NSTAGES;k++) {
+ packsplit(extra_cb_index+k, &firstpart,
+ extra_cb_index+k,
+ ulp_extra_cb_indexTbl[k][ulp],
+ ulp_extra_cb_indexTbl[k][ulp]+
+ ulp_extra_cb_indexTbl[k][ulp+1]+
+ ulp_extra_cb_indexTbl[k][ulp+2]);
+ dopack( &pbytes, firstpart,
+ ulp_extra_cb_indexTbl[k][ulp], &pos);
+ }
+ for (k=0;k<CB_NSTAGES;k++) {
+ packsplit(extra_gain_index+k, &firstpart,
+ extra_gain_index+k,
+ ulp_extra_cb_gainTbl[k][ulp],
+ ulp_extra_cb_gainTbl[k][ulp]+
+ ulp_extra_cb_gainTbl[k][ulp+1]+
+ ulp_extra_cb_gainTbl[k][ulp+2]);
+ dopack( &pbytes, firstpart,
+ ulp_extra_cb_gainTbl[k][ulp], &pos);
+ }
+
+ /* The four 40 sample sub blocks */
+
+ for (i=0; i<NASUB; i++) {
+ for (k=0; k<CB_NSTAGES; k++) {
+ packsplit(cb_index+i*CB_NSTAGES+k, &firstpart,
+ cb_index+i*CB_NSTAGES+k,
+ ulp_cb_indexTbl[i][k][ulp],
+ ulp_cb_indexTbl[i][k][ulp]+
+ ulp_cb_indexTbl[i][k][ulp+1]+
+ ulp_cb_indexTbl[i][k][ulp+2]);
+ dopack( &pbytes, firstpart,
+ ulp_cb_indexTbl[i][k][ulp], &pos);
+ }
+ }
+
+ for (i=0; i<NASUB; i++) {
+ for (k=0; k<CB_NSTAGES; k++) {
+ packsplit(gain_index+i*CB_NSTAGES+k, &firstpart,
+ gain_index+i*CB_NSTAGES+k,
+ ulp_cb_gainTbl[i][k][ulp],
+ ulp_cb_gainTbl[i][k][ulp]+
+ ulp_cb_gainTbl[i][k][ulp+1]+
+ ulp_cb_gainTbl[i][k][ulp+2]);
+ dopack( &pbytes, firstpart,
+ ulp_cb_gainTbl[i][k][ulp], &pos);
+ }
+ }
+ }
+
+ /* set the last unused bit to zero */
+ dopack( &pbytes, 0, 1, &pos);
+}
+
+