
/******************************************************************

    iLBC Speech Coder ANSI-C Source Code

    getCBvec.c 

    Copyright (C) The Internet Society (2004). 
    All Rights Reserved.

******************************************************************/

#include "iLBC_define.h"
#include "getCBvec.h"
#include "constants.h"
#include <string.h>

/*----------------------------------------------------------------*
 *  Construct codebook vector for given index.
 *---------------------------------------------------------------*/

void getCBvec(
    float *cbvec,   /* (o) Constructed codebook vector */
    float *mem,     /* (i) Codebook buffer */
    int index,      /* (i) Codebook index */
    int lMem,       /* (i) Length of codebook buffer */
    int cbveclen/* (i) Codebook vector length */
){
    int j, k, n, memInd, sFilt;
    float tmpbuf[CB_MEML];
    int base_size;
    int ilow, ihigh;
    float alfa, alfa1;

    /* Determine size of codebook sections */

    base_size=lMem-cbveclen+1;
    
    if (cbveclen==SUBL) {
        base_size+=cbveclen/2;
    }

    /* No filter -> First codebook section */


    
    if (index<lMem-cbveclen+1) {

        /* first non-interpolated vectors */

        k=index+cbveclen;
        /* get vector */
        memcpy(cbvec, mem+lMem-k, cbveclen*sizeof(float));

    } else if (index < base_size) {

        k=2*(index-(lMem-cbveclen+1))+cbveclen;
    
        ihigh=k/2;
        ilow=ihigh-5;

        /* Copy first noninterpolated part */

        memcpy(cbvec, mem+lMem-k/2, ilow*sizeof(float));

        /* interpolation */

        alfa1=(float)0.2;
        alfa=0.0;
        for (j=ilow; j<ihigh; j++) {
            cbvec[j]=((float)1.0-alfa)*mem[lMem-k/2+j]+
                alfa*mem[lMem-k+j];
            alfa+=alfa1;
        }

        /* Copy second noninterpolated part */

        memcpy(cbvec+ihigh, mem+lMem-k+ihigh, 
            (cbveclen-ihigh)*sizeof(float));

    }

    /* Higher codebbok section based on filtering */

    else {

        /* first non-interpolated vectors */

        if (index-base_size<lMem-cbveclen+1) {
            float tempbuff2[CB_MEML+CB_FILTERLEN+1];
            float *pos;
            float *pp, *pp1;

            memset(tempbuff2, 0,
                CB_HALFFILTERLEN*sizeof(float));
            memcpy(&tempbuff2[CB_HALFFILTERLEN], mem,
                lMem*sizeof(float));
            memset(&tempbuff2[lMem+CB_HALFFILTERLEN], 0,
                (CB_HALFFILTERLEN+1)*sizeof(float));



            k=index-base_size+cbveclen;
            sFilt=lMem-k;
            memInd=sFilt+1-CB_HALFFILTERLEN;

            /* do filtering */
            pos=cbvec;
            memset(pos, 0, cbveclen*sizeof(float));
            for (n=0; n<cbveclen; n++) {
                pp=&tempbuff2[memInd+n+CB_HALFFILTERLEN];
                pp1=&cbfiltersTbl[CB_FILTERLEN-1];
                for (j=0; j<CB_FILTERLEN; j++) {
                    (*pos)+=(*pp++)*(*pp1--);
                }
                pos++;
            }
        }

        /* interpolated vectors */

        else {
            float tempbuff2[CB_MEML+CB_FILTERLEN+1];

            float *pos;
            float *pp, *pp1;
            int i;

            memset(tempbuff2, 0,
                CB_HALFFILTERLEN*sizeof(float));
            memcpy(&tempbuff2[CB_HALFFILTERLEN], mem,
                lMem*sizeof(float));
            memset(&tempbuff2[lMem+CB_HALFFILTERLEN], 0,
                (CB_HALFFILTERLEN+1)*sizeof(float));

            k=2*(index-base_size-
                (lMem-cbveclen+1))+cbveclen;
            sFilt=lMem-k;
            memInd=sFilt+1-CB_HALFFILTERLEN;

            /* do filtering */
            pos=&tmpbuf[sFilt];
            memset(pos, 0, k*sizeof(float));
            for (i=0; i<k; i++) {
                pp=&tempbuff2[memInd+i+CB_HALFFILTERLEN];
                pp1=&cbfiltersTbl[CB_FILTERLEN-1];
                for (j=0; j<CB_FILTERLEN; j++) {
                    (*pos)+=(*pp++)*(*pp1--);
                }
                pos++;
            }

            ihigh=k/2;
            ilow=ihigh-5;



            /* Copy first noninterpolated part */

            memcpy(cbvec, tmpbuf+lMem-k/2, 
                ilow*sizeof(float));

            /* interpolation */

            alfa1=(float)0.2;
            alfa=0.0;
            for (j=ilow; j<ihigh; j++) {
                cbvec[j]=((float)1.0-alfa)*
                    tmpbuf[lMem-k/2+j]+alfa*tmpbuf[lMem-k+j];
                alfa+=alfa1;
            }

            /* Copy second noninterpolated part */

            memcpy(cbvec+ihigh, tmpbuf+lMem-k+ihigh, 
                (cbveclen-ihigh)*sizeof(float));
        }
    }
}


