
/*

This software module was originally developed by

    Masayuki Nishiguchi and Kazuyuki Iijima (Sony Corporation)
    
    and edited by
 
    Akira Inoue (Sony Corporation)

    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 <stdio.h>

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

#define PU_IP  2 

extern int	ipc_encDelayMode;
extern int	ipc_decDelayMode;

static void calc_syn_cont2u_LD(
float   *res,
float   (*alphaip)[11],
float   *syn)
{
    int i, j;
	

    float out2;
    static float mem2[P+1]={0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.};
		    
    float pos[FRM];
   
    for(i = 0; i < FRM; i++)    pos[i] = 0.0;


       for(i = 0; i < FRM/2 - LD_LEN; i++)
       {
   	   out2 = 0.;
	   for(j=P;j>0;j--)
	   {
		   out2 += mem2[j] * alphaip[0][j];
		   mem2[j]=mem2[j-1];
	    }

	    out2 = res[i] - out2;
            mem2[1]= out2;
            pos[i]= out2;
       }


       for(i = FRM/2 - LD_LEN ; i < FRM; i++)
       {
	   out2 = 0.;
	   for(j=P;j>0;j--)
	   {
	       out2 += mem2[j] * alphaip[1][j];
	       mem2[j]=mem2[j-1];
	   }

	   out2 = res[i] - out2;
	   mem2[1]= out2;
	   pos[i]= out2;
       }

       for(i=0;i<FRM;i++)
       {
           syn[i] =  pos[i] ;
       }
}

static void calc_syn_cont2u(
float	*res,
float	(*alphaip)[11],
float	*syn)
{
    int i, j, ii;
    
    float out2,out2old;
    static float mem2[P+1]={0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.};
    float mem2old[P+1];
    
    float pos[FRM];
    float nokori[80];
    static float alphaipold[P+1];
    float window[80];
    
    for(i=0;i<40;i++)
	window[i]=(float)(i)/40.;
    for(i=40;i<80;i++)
	window[i]=1.;
    
    for(i = 0; i < P + 1; i++)	mem2old[i] = 0.0;
    for(i = 0; i < FRM; i++)	pos[i] = 0.0;
    for(i = 0; i < 80; i++)	nokori[i] = 0.0;
    
    
    for(ii=0;ii<2;ii++)
    {
	for(i=0;i<=P;i++)
	    mem2old[i]=mem2[i];
	
	for(i = 0; i < 80; i++)
	{
	    out2 = 0.;
	    out2old = 0.;
	    for(j=P;j>0;j--)
	    {
		out2 += mem2[j] * alphaip[ii][j];
		mem2[j]=mem2[j-1];
		out2old += mem2old[j]*alphaipold[j];
		mem2old[j]=mem2old[j-1];
	    }
	    
	    out2 = res[ii*80+i] - out2;
	    mem2[1]= out2;
	    pos[ii*80+i]= out2;
	    out2old = res[ii*80+i] - out2old;
	    mem2old[1]= out2old;
	    nokori[i]= out2old;
	}
	
	for(i=0;i<80;i++)
	{
	    syn[ii*80+i] =  pos[ii*80+i] ;
	}
	
	for(i=0;i<=P;i++)
	    alphaipold[i]=alphaip[ii][i];
    }
}

static void IpLsp2Lpc(
float	(*qLsp)[10],
float	(*alphaip)[11])     	                  
{
    int		i, j;
    float	ipLsp0[P + 1], ipLsp1[P + 1];
    
    ipLsp0[0] = ipLsp1[0] = 0.0;
    for(i = 0; i < P; i++)
    {
	ipLsp0[i + 1] = qLsp[0][i];
	ipLsp1[i + 1] = qLsp[1][i];
    }
    
    IPC_lsp_lpc(ipLsp0, alphaip[0]);
    IPC_lsp_lpc(ipLsp1, alphaip[1]);
    
    for(j = 0; j < 2; j++)
    {
	alphaip[j][0] = 1.0;
	for(i = 1; i < P + 1; i++)
	{
	    alphaip[j][i] = -alphaip[j][i];
	}
    }
    return;
}    


static void lp_synU(int *vuv, float *synoutu, float *resinu,
		     float (*qLsp)[10])
{
    int i;
    float lsp[2][P];
    float alphaip[2][P+1];
    float res[FRM];
    float syn[FRM];

    for(i=0;i<10;i++){
	lsp[0][i]=qLsp[0][i];
	lsp[1][i]=qLsp[1][i];
    }
    
    IpLsp2Lpc(lsp, alphaip);
    
    for(i = 0; i < 160; i++)
	res[i] = resinu[i];
    
    if(ipc_decDelayMode == DM_SHORT)
    {
	calc_syn_cont2u_LD(res, alphaip, syn);
	IPC_posfil_u_LD(syn,alphaip);
    }
    else
    {
	calc_syn_cont2u(res, alphaip, syn);
	IPC_posfil_u(syn,alphaip);
    }	
    
    for(i = 0; i < 160; i++)
	synoutu[i] = syn[i];
}

void td_synt(
float	*qRes,
int	*VUVs,
float	(*qLsp)[10],
float	*synoutu)
{
	float suv[FRM];

	IPC_uvExt(VUVs,suv,qRes);
	lp_synU(VUVs, synoutu, suv, qLsp);
}
