mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-07-23 20:51:58 +00:00
initial bits of ilbc codec mod.
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@452 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
@@ -0,0 +1,513 @@
|
||||
|
||||
/******************************************************************
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user