
/*

This software module was originally developed by

    Kazuyuki Iijima (Sony Corporation)

    and edited by

    Naoya Tanaka (Matsushita Communication Industrial Co., Ltd.)

    in the course of development of the MPEG-4 Audio standard (ISO/IEC 14496-3).
    This software module is an implementation of a part of one or more
    MPEG-4 Audio (ISO/IEC 14496-3) tools as specified by the MPEG-4 Audio
    standard (ISO/IEC 14496-3).
    ISO/IEC gives users of the MPEG-4 Audio standards (ISO/IEC 14496-3)
    free license to this software module or modifications thereof for use
    in hardware or software products claiming conformance to the MPEG-4
    Audio standards (ISO/IEC 14496-3).
    Those intending to use this software module in hardware or software
    products are advised that this use may infringe existing patents.
    The original developer of this software module and his/her company,
    the subsequent editors and their companies, and ISO/IEC have no
    liability for use of this software module or modifications thereof in
    an implementation.
    Copyright is not released for non MPEG-4 Audio (ISO/IEC 14496-3)
    conforming products. The original developer retains full right to use
    the code for his/her own purpose, assign or donate the code to a third
    party and to inhibit third party from using the code for non MPEG-4
    Audio (ISO/IEC 14496-3) conforming products.
    This copyright notice must be included in all copies or derivative works.

    Copyright (c)1996.

*/

#include <math.h>
#include <values.h>
#include <stdio.h>

#include "hvxc.h"
#include "hvxcDec.h"
#include "hvxcCommon.h"

#include "pan_par_const.h"

#define FD_RATE 1.0

extern float	ipc_coef[SAMPLE];

float   ipc_coefLD[SAMPLE];

extern int	ipc_encMode;
extern int	ipc_decMode;

extern int	ipc_encDelayMode;
extern int	ipc_decDelayMode;

extern int	ipc_bitstreamMode;

static void IPC_makeCoefDec(void)
{
    int i;
    float energy;
    float c4;

    energy = 0.;
    for(i=0; i < SAMPLE ; i++){
        ipc_coef[i]=(0.54  - 0.46 * cos( 2*M_PI*i/(SAMPLE-1)));
        energy=energy + ipc_coef[i] * ipc_coef[i] ;
    }
    for(i=0; i < SAMPLE ; i++)
        ipc_coef[i]=ipc_coef[i]/sqrt(energy);

    c4 = 0.;
    for(i=0; i < SAMPLE ; i++)
        c4 = c4 + pow(ipc_coef[i], 4.);
}

static void IPC_makeCoefDecLD(void)
{
      int i;
      float energy;

      for(i=0; i < SAMPLE ; i++)
            ipc_coefLD[i]=(0.54  - 0.46 * cos( 2*M_PI*i/(SAMPLE-1)));
      for(i=0;i<8;i++)
            ipc_coefLD[i]=0.;
      for(i=SAMPLE-8;i<SAMPLE;i++)
            ipc_coefLD[i]=0.;

      energy = 0.;
      for(i=0; i < SAMPLE ; i++)
            energy=energy + ipc_coefLD[i] * ipc_coefLD[i] ;

      for(i=0; i < SAMPLE ; i++)
            ipc_coefLD[i]=ipc_coefLD[i]/sqrt(energy);

}

void IPC_HVXCInitDec(void)
{
    IPC_makeCoefDec();
    IPC_set_const_lpcVM_dec();
    IPC_make_f_coef_dec();
    IPC_make_c_dis();
    IPC_make_w_celp();

    if(ipc_decDelayMode == DM_SHORT)
    {
	IPC_makeCoefDecLD();
    }
}


static void UnpackBitsChar(char *encBitChar, int *ptr, int *param, int nbit)
{
    int     i;
    
    *param = 0;

    for(i = 0; i < nbit; i++)
    {
	if(encBitChar[*ptr] == '1')
	{
	    *param |= 0x01 << (nbit - i - 1);
	}
	else
	{
	    *param |= 0x00;
	}
	(*ptr)++;
    }
}

static void Bit2Prm(
unsigned char	*encBit,
EncPrm		*encPrm)
{
    char	encBitChar[80];
    int		i, j;
    int		ptr = 0;

    for(i = 0; i < 5; i++)
    {
	for(j = 0; j < 8; j++)
	{
	    if(encBit[i] & (0x80 >> j))
	    {
		encBitChar[i * 8 + j] = '1';
	    }
	    else
	    {
		encBitChar[i * 8 + j] = '0';
	    }
	}
    }

    UnpackBitsChar(encBitChar, &ptr, &encPrm->idLsp.nVq[0], 
        PAN_BIT_LSP18_0);
    UnpackBitsChar(encBitChar, &ptr, &encPrm->idLsp.nVq[1], 
        PAN_BIT_LSP18_1);
    UnpackBitsChar(encBitChar, &ptr, &encPrm->idLsp.nVq[2], 
        PAN_BIT_LSP18_2);
    UnpackBitsChar(encBitChar, &ptr, &encPrm->idLsp.nVq[3], 
        PAN_BIT_LSP18_3);
    UnpackBitsChar(encBitChar, &ptr, &encPrm->idLsp.nVq[4], 
        PAN_BIT_LSP18_4);

    UnpackBitsChar(encBitChar, &ptr, &encPrm->vuvFlag, 2);

    if(encPrm->vuvFlag == 0)
    {
	for(i = 0; i < N_SFRM_L0; i++)
	{
	    UnpackBitsChar(encBitChar, &ptr,
			   &encPrm->vuvPrm.idUV.idSL0[i], 6);
	    UnpackBitsChar(encBitChar, &ptr,
			   &encPrm->vuvPrm.idUV.idGL0[i], 4);
	}
    }
    else
    {
	UnpackBitsChar(encBitChar, &ptr, &encPrm->vuvPrm.idV.pchcode, 7);
	UnpackBitsChar(encBitChar, &ptr, &encPrm->vuvPrm.idV.idS0, 4);
	UnpackBitsChar(encBitChar, &ptr, &encPrm->vuvPrm.idV.idS1, 4);
	UnpackBitsChar(encBitChar, &ptr, &encPrm->vuvPrm.idV.idG, 5);
    }
    

    if(ipc_decMode == DEC4K || ipc_decMode == DEC3K)
    {
	for(i = 5; i < 10; i++)
	{
	    for(j = 0; j < 8; j++)
	    {
		if(encBit[i] & (0x80 >> j))
		{
		    encBitChar[i * 8 + j] = '1';
		}
		else
		{
		    encBitChar[i * 8 + j] = '0';
		}
	    }
	}
	
	UnpackBitsChar(encBitChar, &ptr, &encPrm->idLsp.nVq[5], 8);
	
	if(encPrm->vuvFlag == 0)
	{
	    for(i = 0; i < N_SFRM_L1; i++)
	    {
		UnpackBitsChar(encBitChar, &ptr,
			       &encPrm->vuvPrm.idUV.idSL1[i], 5);
		UnpackBitsChar(encBitChar, &ptr,
			       &encPrm->vuvPrm.idUV.idGL1[i], 3);
	    }
	}
	else
	{
	    UnpackBitsChar(encBitChar, &ptr, &encPrm->vuvPrm.idV.id4kS0, 7);
	    UnpackBitsChar(encBitChar, &ptr, &encPrm->vuvPrm.idV.id4kS1, 10);
	    UnpackBitsChar(encBitChar, &ptr, &encPrm->vuvPrm.idV.id4kS2, 9);
	    UnpackBitsChar(encBitChar, &ptr, &encPrm->vuvPrm.idV.id4kS3, 6);
	}
    }
}

static void Bit2PrmVR(
unsigned char   *encBit,
EncPrm          *encPrm)
{
    char        encBitChar[80]; /* for 4kbps one frame */
    int         i, j;
    int         ptr = 0;

    static int  prevVUV = 0;

    for(i = 0; i < 5; i++)
    {
        for(j = 0; j < 8; j++)
        {
            if(encBit[i] & (0x80 >> j))
            {
                encBitChar[i * 8 + j] = '1';
            }
            else
            {
                encBitChar[i * 8 + j] = '0';
            }
        }
    }

    UnpackBitsChar(encBitChar, &ptr, &encPrm->vuvFlag, 2);

    if(encPrm->vuvFlag != 1)
    {
        UnpackBitsChar(encBitChar, &ptr, &encPrm->idLsp.nVq[0],
                       PAN_BIT_LSP18_0);
        UnpackBitsChar(encBitChar, &ptr, &encPrm->idLsp.nVq[1],
                       PAN_BIT_LSP18_1);
        UnpackBitsChar(encBitChar, &ptr, &encPrm->idLsp.nVq[2],
                       PAN_BIT_LSP18_2);
        UnpackBitsChar(encBitChar, &ptr, &encPrm->idLsp.nVq[3],
                       PAN_BIT_LSP18_3);
        UnpackBitsChar(encBitChar, &ptr, &encPrm->idLsp.nVq[4],
                       PAN_BIT_LSP18_4);

        if(encPrm->vuvFlag == 0)
        {
            for(i = 0; i < N_SFRM_L0; i++)
            {
                UnpackBitsChar(encBitChar, &ptr,
                               &encPrm->vuvPrm.idUV.idGL0[i], 4);
            }
        }
        else
        {
            UnpackBitsChar(encBitChar, &ptr, &encPrm->vuvPrm.idV.pchcode, 7);
            UnpackBitsChar(encBitChar, &ptr, &encPrm->vuvPrm.idV.idS0, 4);
            UnpackBitsChar(encBitChar, &ptr, &encPrm->vuvPrm.idV.idS1, 4);
            UnpackBitsChar(encBitChar, &ptr, &encPrm->vuvPrm.idV.idG, 5);
        }


        if(ipc_decMode == DEC4K)
        {
            for(i = 5; i < 10; i++)
            {
                for(j = 0; j < 8; j++)
                {
                    if(encBit[i] & (0x80 >> j))
                    {
                        encBitChar[i * 8 + j] = '1';
                    }
                    else
                    {
                        encBitChar[i * 8 + j] = '0';
                    }
                }
            }

            UnpackBitsChar(encBitChar, &ptr, &encPrm->idLsp.nVq[5], 8);

            if(encPrm->vuvFlag == 0)
            {
                for(i = 0; i < N_SFRM_L1; i++)
                {
                    UnpackBitsChar(encBitChar, &ptr,
                                   &encPrm->vuvPrm.idUV.idSL1[i], 5);
                    UnpackBitsChar(encBitChar, &ptr,
                                   &encPrm->vuvPrm.idUV.idGL1[i], 3);
                }
            }
            else
            {
                UnpackBitsChar(encBitChar, &ptr, &encPrm->vuvPrm.idV.id4kS0, 7);
                UnpackBitsChar(encBitChar, &ptr, &encPrm->vuvPrm.idV.id4kS1, 10);
                UnpackBitsChar(encBitChar, &ptr, &encPrm->vuvPrm.idV.id4kS2, 9);
                UnpackBitsChar(encBitChar, &ptr, &encPrm->vuvPrm.idV.id4kS3, 6);
            }
        }
    }

    if(encPrm->vuvFlag == 1)
    {
        encPrm->vuvFlag = prevVUV;
        encPrm->bgnFlag = 1;
    }
    else
    {
        prevVUV = encPrm->vuvFlag;
        encPrm->bgnFlag = 0;
    }
}





void IPC_UnPackBit2Prm(
unsigned char	*encBit,
IdLsp		*idLsp,
int		*idVUV,
IdCelp		*idCelp,
float		*pitch,
IdAm		*idAm)
{
    static EncPrm	encPrm;
    int			i, pchcode;


    static int	frm = 0;

    Bit2Prm(encBit, &encPrm);
    
    for(i = 0; i < L_VQ - 1; i++)
    {
	idLsp->nVq[i] = encPrm.idLsp.nVq[i];
    }
    
    *idVUV = encPrm.vuvFlag;
    
    if(encPrm.vuvFlag == 0)
    {
	*pitch = 148.0;

	for(i = 0; i < N_SFRM_L0; i++)
	{
	    idCelp->idSL0[i] = encPrm.vuvPrm.idUV.idSL0[i];
	    idCelp->idGL0[i] = encPrm.vuvPrm.idUV.idGL0[i];
	}
    }
    else
    {
	pchcode = encPrm.vuvPrm.idV.pchcode;
	*pitch = pchcode + 20.0;
	idAm->idS0 = encPrm.vuvPrm.idV.idS0;
	idAm->idS1 = encPrm.vuvPrm.idV.idS1;
	idAm->idG = encPrm.vuvPrm.idV.idG;
    }
    
    if(ipc_decMode == DEC4K || ipc_decMode == DEC3K)
    {
	idLsp->nVq[L_VQ - 1] = encPrm.idLsp.nVq[L_VQ - 1];
	    
	if(encPrm.vuvFlag == 0)
	{
	    for(i = 0; i < N_SFRM_L1; i++)
	    {
		idCelp->idSL1[i] = encPrm.vuvPrm.idUV.idSL1[i];
		idCelp->idGL1[i] = encPrm.vuvPrm.idUV.idGL1[i];
	    }
	}
	else
	{
	    idAm->id4kS0 = encPrm.vuvPrm.idV.id4kS0;
	    idAm->id4kS1 = encPrm.vuvPrm.idV.id4kS1;
	    idAm->id4kS2 = encPrm.vuvPrm.idV.id4kS2;
	    idAm->id4kS3 = encPrm.vuvPrm.idV.id4kS3;
	}
    }

    frm++;
}

void IPC_UnPackBit2PrmVR(
unsigned char   *encBit,
IdLsp           *idLsp,
int             *idVUV,
int             *bgnFlag,
IdCelp          *idCelp,
float           *pitch,
IdAm            *idAm)
{
    static EncPrm       encPrm;
    int                 i, pchcode;


    static int  frm = 0;

    Bit2PrmVR(encBit, &encPrm);

    *bgnFlag = encPrm.bgnFlag;
    *idVUV = encPrm.vuvFlag;

    for(i = 0; i < L_VQ - 1; i++)
    {
        idLsp->nVq[i] = encPrm.idLsp.nVq[i];
    }

    if(encPrm.vuvFlag == 0)
    {
        *pitch = 148.0;

        for(i = 0; i < N_SFRM_L0; i++)
        {
            idCelp->idSL0[i] = encPrm.vuvPrm.idUV.idSL0[i];
            idCelp->idGL0[i] = encPrm.vuvPrm.idUV.idGL0[i];
        }
    }
    else
    {
        pchcode = encPrm.vuvPrm.idV.pchcode;
        *pitch = pchcode + 20.0;
        idAm->idS0 = encPrm.vuvPrm.idV.idS0;
        idAm->idS1 = encPrm.vuvPrm.idV.idS1;
        idAm->idG = encPrm.vuvPrm.idV.idG;
    }

    if(ipc_decMode == DEC4K)
    {
        idLsp->nVq[L_VQ - 1] = encPrm.idLsp.nVq[L_VQ - 1];

        if(encPrm.vuvFlag == 0)
        {
            for(i = 0; i < N_SFRM_L1; i++)
            {
                idCelp->idSL1[i] = encPrm.vuvPrm.idUV.idSL1[i];
                idCelp->idGL1[i] = encPrm.vuvPrm.idUV.idGL1[i];
            }
        }
        else
        {
            idAm->id4kS0 = encPrm.vuvPrm.idV.id4kS0;
            idAm->id4kS1 = encPrm.vuvPrm.idV.id4kS1;
            idAm->id4kS2 = encPrm.vuvPrm.idV.id4kS2;
            idAm->id4kS3 = encPrm.vuvPrm.idV.id4kS3;
        }
    }

    frm++;
}

int IPC_DecParams1st(
unsigned char	*encBit,
float		pchmod,
int		*idVUV2,
float		(*qLspQueue)[LPCORDER],
float		*pch2,
float		(*am2)[SAMPLE / 2][3],
IdCelp		*idCelp2)
{
    static IdAm		idAm = {0, 0, 0, 0, 0, 0, 0};

    float	mfdpch;
    float	tmpQLsp[LPCORDER];
    int		i, j, k;
    int		idAmS[2], idAmG;
    int		idAm4k[4];
    float	tmpAm[SAMPLE / 2][3];
    float       *dumLSF = NULL;

    IdLsp	idLsp;
    int		idVUV;
    int		normMode, bitNum;

    static int	frm = 0;

#include "inc_lsp_575.tbl"
    static float min_gap=PAN_MINGAP_PAR;
    static float p_factor=PAN_LSP_AR_R_PAR;

    static float prevQLsp[LPCORDER];

    if(0==frm) {
        for(j=0;j<LPCORDER;j++) {
            prevQLsp[j] = (j+1.)/(float)(LPCORDER+1);
        }
    }

    IPC_UnPackBit2Prm(encBit, &idLsp, &idVUV, &idCelp2[frm % 2], &mfdpch,
		      &idAm);

    pan_lspdec(prevQLsp, tmpQLsp, 
               p_factor, min_gap, LPCORDER, 
               (long *)idLsp.nVq, 
               lsp_tbl, d_tbl, pd_tbl, dim_1, ncd_1, dim_2, ncd_2);

    if(DEC4K==ipc_decMode || DEC3K==ipc_decMode)
    {
	IPC_DecLspEnh(&idLsp, tmpQLsp);
    }

    for(j=0;j<LPCORDER;j++) prevQLsp[j] = tmpQLsp[j];

    for(j=0;j<LPCORDER;j++) tmpQLsp[j] *= .5;
    
    for(j = 0; j < P; j++)
    {
	qLspQueue[(frm + 2) % 4][j] = tmpQLsp[j];
    }

    idVUV2[0] = idVUV2[1];
    idVUV2[1] = idVUV;
    
    pch2[0] = pch2[1];
    pch2[1] = mfdpch;
    
    normMode = 0;
    bitNum = 10;
    
    idAmS[0]=idAm.idS0;
    idAmS[1]=idAm.idS1;
    idAmG=idAm.idG;
    
    if(ipc_decMode == DEC4K || ipc_decMode == DEC3K)
    {
	idAm4k[0]=idAm.id4kS0;
	idAm4k[1]=idAm.id4kS1;
	idAm4k[2]=idAm.id4kS2;
	idAm4k[3]=idAm.id4kS3;
    }

    harm_sew_dec(tmpAm, &pch2[1], dumLSF, normMode, idVUV2[1], idAmS, bitNum,
		 idAmG, 0, pchmod, idAm4k);
    
    for(j = 0; j < SAMPLE / 2; j++)
    {
	for(k = 0; k < 3; k++)
	{
	    am2[0][j][k] = am2[1][j][k];
	}
    }
    for(j = 0; j < SAMPLE / 2; j++)
    {
	for(k = 0; k < 3; k++)
	{
	    am2[1][j][k] = tmpAm[j][k];
	}
    }

    frm++;

    return(0);
}

int IPC_DecParams1stVR(
unsigned char   *encBit,
float           pchmod,
int             *idVUV2,
int             *bgnFlag2,
float           (*qLspQueue)[LPCORDER],
float           *pch2,
float           (*am2)[SAMPLE / 2][3],
IdCelp          *idCelp2)
{
    static IdAm         idAm = {0, 0, 0, 0, 0, 0, 0};

    float       mfdpch;
    float       tmpQLsp[LPCORDER];
    int         i, j, k;
    int         idAmS[2], idAmG;
    int         idAm4k[4];
    float       tmpAm[SAMPLE / 2][3];
    float       *dumLSF = NULL;

    IdLsp       idLsp;
    int         idVUV;
    int         bgnFlag;
    int         normMode, bitNum;

    static int  frm = 0;
    static int  bgnCnt = 0;

    #include "inc_lsp_575.tbl"
    static float min_gap=PAN_MINGAP_PAR;
    static float p_factor=PAN_LSP_AR_R_PAR;

    static float prevQLsp[LPCORDER];

    static float prevQLsp2[LPCORDER];

    static float fadeOut = 1.0;

    static int prevGainId = 0;

    if(0==frm) {
        for(j=0;j<LPCORDER;j++) {
            prevQLsp[j] = (j+1.)/(float)(LPCORDER+1);
        }
    }

    IPC_UnPackBit2PrmVR(encBit, &idLsp, &idVUV, &bgnFlag, &idCelp2[frm % 2],
                      &mfdpch, &idAm);

    pan_lspdec(prevQLsp, tmpQLsp, 
               p_factor, min_gap, LPCORDER, 
               (long *)idLsp.nVq, 
               lsp_tbl, d_tbl, pd_tbl, dim_1, ncd_1, dim_2, ncd_2);

    if(DEC4K==ipc_decMode)
    {
        IPC_DecLspEnh(&idLsp, tmpQLsp);
    }

    if(bgnFlag)
    {
        for(i = 0; i < LPCORDER; i++)
        {
            tmpQLsp[i] = (prevQLsp2[i] * (2.0 * BGN_INTVL - 1.0 - 2.0 * bgnCnt)
                          + prevQLsp[i] * (1.0 + 2.0 * bgnCnt)) /
                              (BGN_INTVL * 2.0);
        }
        bgnCnt++;
    }
    else
    {
        for(i = 0; i < LPCORDER; i++)
        {
            prevQLsp2[i] = prevQLsp[i];
        }

        for(j = 0; j < LPCORDER; j++)
        {
            prevQLsp[j] = tmpQLsp[j];
        }

        /* check gain of excitations */

        if(bgnCnt == BGN_INTVL)
        {
/*
            printf("gain %d\n", idCelp2[frm % 2].idGL0[0]);
            printf("     %d\n", idCelp2[frm % 2].idGL0[1]);
*/
            if(idCelp2[frm % 2].idGL0[0] <= prevGainId + 2)
            {
                for(j = 0; j < LPCORDER; j++)
                {
                    tmpQLsp[j] = prevQLsp2[j];
                }
            }
        }

        bgnCnt = 0;
    }

    prevGainId = idCelp2[frm % 2].idGL0[1];


    for(j=0;j<LPCORDER;j++) tmpQLsp[j] *= .5;

    for(j = 0; j < P; j++)
    {
        qLspQueue[(frm + 2) % 4][j] = tmpQLsp[j];
    }

    idVUV2[0] = idVUV2[1];
    idVUV2[1] = idVUV;

    bgnFlag2[0] = bgnFlag2[1];
    bgnFlag2[1] = bgnFlag;

    pch2[0] = pch2[1];
    pch2[1] = mfdpch;

    normMode = 0;
    bitNum = 10;

    idAmS[0]=idAm.idS0;
    idAmS[1]=idAm.idS1;
    idAmG=idAm.idG;

    if(ipc_decMode == DEC4K)
    {
        idAm4k[0]=idAm.id4kS0;
        idAm4k[1]=idAm.id4kS1;
        idAm4k[2]=idAm.id4kS2;
        idAm4k[3]=idAm.id4kS3;
    }

    harm_sew_dec(tmpAm, &pch2[1], dumLSF, normMode, idVUV2[1], idAmS, bitNum,
                 idAmG, 0, pchmod, idAm4k);
    for(j = 0; j < SAMPLE / 2; j++)
    {
        for(k = 0; k < 3; k++)
        {
            am2[0][j][k] = am2[1][j][k];
        }
    }

    if(bgnCnt > 0)
    {
        fadeOut *= FD_RATE;
    }
    else
    {
        fadeOut = 1.0;
    }

    for(j = 0; j < SAMPLE / 2; j++)
    {
        for(k = 0; k < 3; k++)
        {
            am2[1][j][k] = fadeOut * tmpAm[j][k];
        }
    }

    frm++;

    return(0);
}

void IPC_DecParams2nd(
int	fr0,
int	*idVUV2,
float	(*qLspQueue)[LPCORDER],
IdCelp	*idCelp2,
float	(*qLsp2)[LPCORDER],
float	(*qRes2)[FRM])
{
    int		j;
    int		idCelpSL0[N_SFRM_L0], idCelpGL0[N_SFRM_L0];
    int		idCelpSL1[N_SFRM_L1], idCelpGL1[N_SFRM_L1];

    fr0 += 2;

    for(j = 0; j < P; j++)
    {
	qLsp2[0][j] = qLspQueue[(fr0 + 0) % 4][j];
	qLsp2[1][j] = qLspQueue[(fr0 + 1) % 4][j];
    }
    
    for(j = 0; j < N_SFRM_L0; j++)
    {
	idCelpSL0[j] = idCelp2[fr0 % 2].idSL0[j];
	idCelpGL0[j] = idCelp2[fr0 % 2].idGL0[j];
    }
    
    if(ipc_decMode == DEC4K || ipc_decMode == DEC3K)
    {
	for(j = 0; j < N_SFRM_L1; j++)
	{
	    idCelpSL1[j] = idCelp2[fr0 % 2].idSL1[j];
	    idCelpGL1[j] = idCelp2[fr0 % 2].idGL1[j];
	}
    }
    
    td_decoder(idVUV2[0], idCelpSL0, idCelpGL0, idCelpSL1, idCelpGL1,
	       qRes2[0]);
    
    for(j = 0; j < N_SFRM_L0; j++)
    {
	idCelpSL0[j] = idCelp2[(fr0 + 1) % 2].idSL0[j];
	idCelpGL0[j] = idCelp2[(fr0 + 1) % 2].idGL0[j];
    }
    
    if(ipc_decMode == DEC4K || ipc_decMode == DEC3K)
    {
	for(j = 0; j < N_SFRM_L1; j++)
	{
	    idCelpSL1[j] = idCelp2[(fr0 + 1) % 2].idSL1[j];
	    idCelpGL1[j] = idCelp2[(fr0 + 1) % 2].idGL1[j];
	}
    }
    
    td_decoder(idVUV2[1], idCelpSL0, idCelpGL0, idCelpSL1, idCelpGL1,
	       qRes2[1]);

}

void IPC_DecParams2ndVR(
int     fr0,
int     *idVUV2,
int     *bgnFlag2,
float   (*qLspQueue)[LPCORDER],
IdCelp  *idCelp2,
float   (*qLsp2)[LPCORDER],
float   (*qRes2)[FRM])
{
    int         j;
    int         idCelpSL0[N_SFRM_L0], idCelpGL0[N_SFRM_L0];
    int         idCelpSL1[N_SFRM_L1], idCelpGL1[N_SFRM_L1];

    fr0 += 2;

    for(j = 0; j < P; j++)
    {
        qLsp2[0][j] = qLspQueue[(fr0 + 0) % 4][j];
        qLsp2[1][j] = qLspQueue[(fr0 + 1) % 4][j];
    }

    for(j = 0; j < N_SFRM_L0; j++)
    {
        idCelpSL0[j] = idCelp2[fr0 % 2].idSL0[j];
        idCelpGL0[j] = idCelp2[fr0 % 2].idGL0[j];
    }

    if(ipc_decMode == DEC4K)
    {
        for(j = 0; j < N_SFRM_L1; j++)
        {
            idCelpSL1[j] = idCelp2[fr0 % 2].idSL1[j];
            idCelpGL1[j] = idCelp2[fr0 % 2].idGL1[j];
        }
    }

    td_decoderVR(idVUV2[0], bgnFlag2[0], idCelpSL0, idCelpGL0, idCelpSL1, idCelpGL1,
                 qRes2[0]);

    for(j = 0; j < N_SFRM_L0; j++)
    {
        idCelpSL0[j] = idCelp2[(fr0 + 1) % 2].idSL0[j];
        idCelpGL0[j] = idCelp2[(fr0 + 1) % 2].idGL0[j];
    }

    if(ipc_decMode == DEC4K)
    {
        for(j = 0; j < N_SFRM_L1; j++)
        {
            idCelpSL1[j] = idCelp2[(fr0 + 1) % 2].idSL1[j];
            idCelpGL1[j] = idCelp2[(fr0 + 1) % 2].idGL1[j];
        }
    }

    td_decoderVR(idVUV2[1], bgnFlag2[1], idCelpSL0, idCelpGL0, idCelpSL1, idCelpGL1,
                 qRes2[1]);

}

void IPC_SynthSC(
int	idVUV,
float	*qLsp,
float	mfdpch,
float	(*am)[3],
float	*qRes,
short int	*frmBuf)
{
    static int	frm = 0;
    int		i;
    static int	idVUVs[2] = {0, 0};
    static float	pchs[2];
    static float	qLsps[2][P];
    int		lsUn;
    float	synoutu[SAMPLE-OVERLAP]; 
    float	synoutv[SAMPLE-OVERLAP]; 
    float	bufsf[FRM];
    int tmpIdVUVs[2];

    static int muteflag = 0;

    for(i = 0; i < P; i++)
    {
	qLsps[0][i] = qLsps[1][i];
	qLsps[1][i] = qLsp[i];
    }
    
    if(frm == 0)
    {
	for(i = 0; i < P; i++)
	{
	    qLsps[0][i] = qLsps[1][i] = qLsp[i];
	}

	idVUVs[0] = idVUVs[1] = idVUV;
	pchs[0]= pchs[1]= mfdpch;

	for(i = 0; i < FRM; i++)
	{
	    bufsf[i] = 0.0;
	}
    }
    else
    {
	idVUVs[0] = idVUVs[1];
	idVUVs[1] = idVUV;  
		
	pchs[0]= pchs[1];
	pchs[1]= mfdpch;  

	lsUn=8;

        if(ipc_bitstreamMode == BM_VARIABLE)
        {
            td_synt(qRes,idVUVs,qLsps,synoutu);

            tmpIdVUVs[0] = idVUVs[0];
            tmpIdVUVs[1] = idVUVs[1];

            if(tmpIdVUVs[0] == 1)
            {
                tmpIdVUVs[0] = 0;
            }
            if(tmpIdVUVs[1] == 1)
            {
                tmpIdVUVs[1] = 0;
            }

            harm_srew_synt(am,pchs,tmpIdVUVs,qLsps,lsUn,synoutv);
        }
        else
        {
	    harm_srew_synt(am,pchs,idVUVs,qLsps,lsUn,synoutv);

	    td_synt(qRes,idVUVs,qLsps,synoutu);
        }
		
	if(ipc_decMode == DEC2K)
	{
	    for(i=0;i<FRM;i++)
		bufsf[i]= synoutu[i] + synoutv[i];
	}
	else
	{
	    for(i=0;i<FRM;i++)
		bufsf[i]= synoutu[i] + synoutv[i];
	}	    
		
	IPC_bpf(bufsf);
    }
    if (ipc_decMode == DEC0K) {
	if (muteflag == 0)
	    for (i=0;i<FRM;i++)
		bufsf[i] *= ((float)(FRM-i)/(float)FRM);
            else
		for (i=0;i<FRM;i++) bufsf[i] = 0;
        muteflag = 1;
    } else {
	if (muteflag == 1)
	    for (i=0;i<FRM;i++)
	        bufsf[i] *= ((float)i/(float)FRM);
            muteflag = 0;
    }

    for(i=0;i<FRM;i++)
    {
	if(bufsf[i] > 32767.) bufsf[i]=32767.;
	if(bufsf[i] < -32767.) bufsf[i]= -32767.;
	frmBuf[i] = (short) bufsf[i];
    }

    frm++;
}
