
//#ifdef HAVE_CONFIG_H
#include "config.h"
//#endif

#include "audio.h"
#include "ssc_generic.h"

#ifndef VC_PROJ
#include <xtensa/tie/xt_hifi2.h>
extern ae_int32 AE_MUL16S(ae_int16 b, ae_int16 c);
extern ae_int64 AE_MUL32_HH(ae_int32x2 d0, ae_int32x2 d1);
#endif

#ifndef KHW_23BIT_WINDOW_SQUARE
short win_square[108] = 
{
	0, 0, 0, 0, 1, 3, 6, 11, 18, 29, 43, 62, 86, 116, 155, 201, 257, 323, 402, 493, 598, 718, 855, 
	1010, 1182, 1375, 1589, 1823, 2081, 2362, 2667, 2997, 3353, 3733, 4140, 4572, 5031, 5514, 6025, 
	6559, 7117, 7699, 8304, 8929, 9574, 10239, 10920, 11617, 12326, 13048, 13779, 14517, 15261, 16009, 
	16758, 17506, 18249, 18988, 19719, 20441, 21150, 21847, 22528, 23193, 23838, 24463, 25068, 25649, 
	26207, 26743, 27252, 27737, 28195, 28627, 29034, 29414, 29769, 30100, 30406, 30686, 30944, 31179, 
	31392, 31584, 31757, 31911, 32049, 32168, 32273, 32365, 32444, 32510, 32566, 32612, 32650, 32682, 
	32706, 32724, 32738, 32750, 32756, 32762, 32764, 32766, 32766, 32766, 32766, 32766
};
#else
int win_square[108] =
{
	0, 2, 18, 69, 189, 422, 822, 1454, 2392,
	3723, 5540, 7945, 11050, 14974, 19842, 25786, 32944, 41457,
	51472, 63136, 76599, 92009, 109517, 129267, 151402, 176061, 203373,
	233464, 266446, 302424, 341488, 383717, 429175, 477910, 529952, 585315,
	643994, 705965, 771182, 839581, 911077, 985565, 1062919, 1142994, 1225626,
	1310633, 1397813, 1486954, 1577823, 1670179, 1763767, 1858321, 1953574, 2049245,
	2145058, 2240731, 2335982, 2430537, 2524125, 2616480, 2707350, 2796490, 2883672,
	2968679, 3051310, 3131386, 3208739, 3283227, 3354723, 3423122, 3488339, 3550310,
	3608989, 3664351, 3716395, 3765129, 3810586, 3852817, 3891881, 3927858, 3960840,
	3990931, 4018243, 4042902, 4065038, 4084788, 4102294, 4117705, 4131167, 4142831,
	4152847, 4161361, 4168518, 4174464, 4179331, 4183253, 4186360, 4188764, 4190581,
	4191912, 4192850, 4193482, 4193882, 4194114, 4194234, 4194286, 4194302, 4194302,
};
#endif


#if 1

#ifdef FOR_VISUAL_C_NO_ASSM
static void comb_filter_const(int *y, short T, int N,
      short g10, short g11, short g12)
{
	int i;
//#if 0
#ifdef VC_PROJ
	long long Ltmp;
#else
	ae_int64 Ltmp;
#endif
	for (i=0; i<N; i++)
	{
//#if 0
#ifdef VC_PROJ
		Ltmp = SSC_MULT16x32(g10,y[i-T]) + SSC_MULT16x32(g11, SSC_ADD32(y[i-T+1],y[i-T-1])) + SSC_MULT16x32(g12, SSC_ADD32(y[i-T+2],y[i-T-2]));
#else
	//	Ltmp = SSC_MULT16x32(g10,y[i-T]);
		Ltmp = AE_MUL32_HH(g10,y[i-T]);
		AE_MULA32_HH(Ltmp, g11,SSC_ADD32(y[i-T+1],y[i-T-1]));
		AE_MULA32_HH(Ltmp, g12,SSC_ADD32(y[i-T+2],y[i-T-2]));
#endif
		y[i] += (int)((long long)Ltmp>>15);
	}
}

#endif



void comb_filter(int *y,short T0, short T1, int N,
	short g0, short g1,int overlap)

{
//	int i;
	short g00, g01, g02, g10, g11, g12;
#ifndef KHW_23BIT_WINDOW	
	short w2;
#else
	int w2;
#endif
//#if 0
#ifdef VC_PROJ
	long long Ltmp;
#else
	ae_int64 Ltmp;
#endif

#ifndef KHW_23BIT_WINDOW_SQUARE
	short *win = win_square;
#else
	int *win = win_square;
#endif
	int i;
	
	if (g0==0 && g1==0) return;
	if (g0==g1 && T0==T1) overlap=0;
	
	g00 = SSC_MULT16x16_Q15(g0, 10048);
	g01 = SSC_MULT16x16_Q15(g0, 7112);
	g02 = SSC_MULT16x16_Q15(g0, 4248);
	g10 = SSC_MULT16x16_Q15(g1, 10048);
	g11 = SSC_MULT16x16_Q15(g1, 7112);
	g12 = SSC_MULT16x16_Q15(g1, 4248);

	if(g0==0)
	{
		i = overlap;
		do
		{
			w2 = *win++;
#ifndef KHW_23BIT_WINDOW_SQUARE
#ifdef VC_PROJ
			Ltmp = SSC_MULT16x32(SSC_MULT16x16_Q15(w2,g10),y[-T1])
				+ SSC_MULT16x32(SSC_MULT16x16_Q15(w2,g11),SSC_ADD32(y[-T1+1],y[-T1-1]))
				+ SSC_MULT16x32(SSC_MULT16x16_Q15(w2,g12),SSC_ADD32(y[-T1+2],y[-T1-2]));
#else
			Ltmp = SSC_MULT16x32(SSC_MULT16x16_Q15(w2,g10),y[-T1]);
			AE_MULA32_HH(Ltmp, SSC_MULT16x16_Q15(w2,g11),SSC_ADD32(y[-T1+1],y[-T1-1]));
			AE_MULA32_HH(Ltmp, SSC_MULT16x16_Q15(w2,g12),SSC_ADD32(y[-T1+2],y[-T1-2]));
#endif
			*y += (int)((long long)Ltmp >> 15);
#else
#ifdef VC_PROJ
			Ltmp = SSC_MULT16x32(SSC_MULT16x32_Q15(g10, w2), y[-T1])
				+ SSC_MULT16x32(SSC_MULT16x32_Q15(g11, w2), SSC_ADD32(y[-T1 + 1], y[-T1 - 1]))
				+ SSC_MULT16x32(SSC_MULT16x32_Q15(g12, w2), SSC_ADD32(y[-T1 + 2], y[-T1 - 2]));
#else

			Ltmp = AE_MUL32_HH((int)((long long)AE_SRAI64(AE_MUL32_HH(g10, w2), 15))   , y[-T1]);
			AE_MULA32_HH(Ltmp, (int)((long long)AE_SRAI64(AE_MUL32_HH(g11, w2), 15)), SSC_ADD32(y[-T1 + 1], y[-T1 - 1]));
			AE_MULA32_HH(Ltmp, (int)((long long)AE_SRAI64(AE_MUL32_HH(g12, w2), 15)), SSC_ADD32(y[-T1 + 2], y[-T1 - 2]));
#endif
			*y += (int)((long long)Ltmp >> 22);
#endif
			
			y++;
		}
		while(--i);

	}
	else if(g1==0)
	{
		i = overlap;
		do				
		{
			w2 = *win++;
#ifndef KHW_23BIT_WINDOW_SQUARE
#ifdef VC_PROJ
			Ltmp = SSC_MULT16x32(SSC_MULT16x16_Q15((Q15ONE-w2),g00),y[-T0])
				+ SSC_MULT16x32(SSC_MULT16x16_Q15((Q15ONE-w2),g01),SSC_ADD32(y[-T0+1],y[-T0-1]))
				+ SSC_MULT16x32(SSC_MULT16x16_Q15((Q15ONE-w2),g02),SSC_ADD32(y[-T0+2],y[-T0-2]));
#else
			Ltmp = SSC_MULT16x32(SSC_MULT16x16_Q15((Q15ONE-w2),g00),y[-T0]);
			AE_MULA32_HH(Ltmp, SSC_MULT16x16_Q15((Q15ONE-w2),g01),SSC_ADD32(y[-T0+1],y[-T0-1]));
			AE_MULA32_HH(Ltmp, SSC_MULT16x16_Q15((Q15ONE-w2),g02),SSC_ADD32(y[-T0+2],y[-T0-2]));
#endif
			*y += (int)((long long)Ltmp >> 15);
#else
#ifdef VC_PROJ
			Ltmp = SSC_MULT16x32(SSC_MULT16x32_Q15(g00,(Q22ONE - w2)), y[-T0])
				+ SSC_MULT16x32(SSC_MULT16x32_Q15(g01, (Q22ONE - w2)), SSC_ADD32(y[-T0 + 1], y[-T0 - 1]))
				+ SSC_MULT16x32(SSC_MULT16x32_Q15(g02, (Q22ONE - w2)), SSC_ADD32(y[-T0 + 2], y[-T0 - 2]));
#else
	//		Ltmp = SSC_MULT16x32(SSC_MULT16x32_Q15(g00, (Q22ONE - w2)), y[-T0]);
	//		AE_MULA32_HH(Ltmp, SSC_MULT16x32_Q15(g01, (Q22ONE - w2)), SSC_ADD32(y[-T0 + 1], y[-T0 - 1]));
	//		AE_MULA32_HH(Ltmp, SSC_MULT16x32_Q15(g02, (Q22ONE - w2)), SSC_ADD32(y[-T0 + 2], y[-T0 - 2]));

			Ltmp = AE_MUL32_HH((int)((long long)AE_SRAI64(AE_MUL32_HH(g00, (Q22ONE - w2)), 15)), y[-T0]);
			AE_MULA32_HH(Ltmp,(int)((long long)AE_SRAI64(AE_MUL32_HH(g01, (Q22ONE - w2)), 15)), SSC_ADD32(y[-T0 + 1], y[-T0 - 1]));
			AE_MULA32_HH(Ltmp,(int)((long long)AE_SRAI64(AE_MUL32_HH(g02, (Q22ONE - w2)), 15)), SSC_ADD32(y[-T0 + 2], y[-T0 - 2]));


#endif

			*y += (int)((long long)Ltmp >> 22);
#endif
			
			y++;
		}
		while(--i);

		return;
	}
	else
	{
		if(T0==T1)
		{
		
		for(i=0;i<overlap;i++)			
		{

				w2 = *win++;
#ifndef KHW_23BIT_WINDOW_SQUARE
#ifdef VC_PROJ
				Ltmp = SSC_MULT16x32((SSC_MULT16x16_Q15((Q15ONE-w2),g00)+SSC_MULT16x16_Q15(w2,g10)),y[-T0])
					+ SSC_MULT16x32((SSC_MULT16x16_Q15((Q15ONE-w2),g01)+SSC_MULT16x16_Q15(w2,g11)),SSC_ADD32(y[-T0+1],y[-T0-1]))
					+ SSC_MULT16x32((SSC_MULT16x16_Q15((Q15ONE-w2),g02)+SSC_MULT16x16_Q15(w2,g12)),SSC_ADD32(y[-T0+2],y[-T0-2]));
#else
				Ltmp = SSC_MULT16x32((SSC_MULT16x16_Q15((Q15ONE-w2),g00)+SSC_MULT16x16_Q15(w2,g10)),y[-T0]);
				AE_MULA32_HH(Ltmp, (SSC_MULT16x16_Q15((Q15ONE-w2),g01)+SSC_MULT16x16_Q15(w2,g11)),SSC_ADD32(y[-T0+1],y[-T0-1]));
				AE_MULA32_HH(Ltmp, (SSC_MULT16x16_Q15((Q15ONE-w2),g02)+SSC_MULT16x16_Q15(w2,g12)),SSC_ADD32(y[-T0+2],y[-T0-2]));
#endif
				*y += (int)((long long)Ltmp>>15);
#else
#ifdef VC_PROJ
				Ltmp = SSC_MULT16x32((SSC_MULT16x32_Q15(g00, (Q22ONE - w2)) + SSC_MULT16x32_Q15(g10,w2)), y[-T0])
					+ SSC_MULT16x32((SSC_MULT16x32_Q15(g01, (Q22ONE - w2)) + SSC_MULT16x32_Q15(g11, w2)), SSC_ADD32(y[-T0 + 1], y[-T0 - 1]))
					+ SSC_MULT16x32((SSC_MULT16x32_Q15(g02, (Q22ONE - w2)) + SSC_MULT16x32_Q15(g12, w2)), SSC_ADD32(y[-T0 + 2], y[-T0 - 2]));
#else
		//		Ltmp = SSC_MULT16x32((SSC_MULT16x32_Q15(g00, (Q22ONE - w2)) + SSC_MULT16x32_Q15(g10, w2)), y[-T0]);
		//		AE_MULA32_HH(Ltmp, (SSC_MULT16x32_Q15(g01, (Q22ONE - w2)) + SSC_MULT16x32_Q15(g11, w2)), SSC_ADD32(y[-T0 + 1], y[-T0 - 1]));
		//		AE_MULA32_HH(Ltmp, (SSC_MULT16x32_Q15(g02, (Q22ONE - w2)) + SSC_MULT16x32_Q15(g12, w2)), SSC_ADD32(y[-T0 + 2], y[-T0 - 2]));

				Ltmp = AE_MUL32_HH((((int)((long long)AE_SRAI64(AE_MUL32_HH(g00, (Q22ONE - w2)), 15))) + ((int)((long long)AE_SRAI64(AE_MUL32_HH(g10, w2), 15)))), y[-T0]);
				AE_MULA32_HH(Ltmp, (((int)((long long)AE_SRAI64(AE_MUL32_HH(g01, (Q22ONE - w2)), 15))) + ((int)((long long)AE_SRAI64(AE_MUL32_HH(g11, w2), 15)))), SSC_ADD32(y[-T0 + 1], y[-T0 - 1]));
				AE_MULA32_HH(Ltmp, (((int)((long long)AE_SRAI64(AE_MUL32_HH(g02, (Q22ONE - w2)), 15))) + ((int)((long long)AE_SRAI64(AE_MUL32_HH(g12, w2), 15)))), SSC_ADD32(y[-T0 + 2], y[-T0 - 2]));

#endif
				*y += (int)((long long)Ltmp >> 22);

#endif
				y++;				
			}

		}
		else
		{

	
		for(i=0;i<overlap;i++)			
		{
				w2 = *win++;
#ifndef KHW_23BIT_WINDOW_SQUARE
#ifdef VC_PROJ
						Ltmp = SSC_MULT16x32(SSC_MULT16x16_Q15((Q15ONE-w2),g00),y[-T0])
							+ SSC_MULT16x32(SSC_MULT16x16_Q15((Q15ONE-w2),g01),SSC_ADD32(y[-T0+1],y[-T0-1]))
							+ SSC_MULT16x32(SSC_MULT16x16_Q15((Q15ONE-w2),g02),SSC_ADD32(y[-T0+2],y[-T0-2]))
							+ SSC_MULT16x32(SSC_MULT16x16_Q15(w2,g10),y[-T1])
							+ SSC_MULT16x32(SSC_MULT16x16_Q15(w2,g11),SSC_ADD32(y[-T1+1],y[-T1-1]))
							+ SSC_MULT16x32(SSC_MULT16x16_Q15(w2,g12),SSC_ADD32(y[-T1+2],y[-T1-2]));
#else
						Ltmp = SSC_MULT16x32(SSC_MULT16x16_Q15((Q15ONE-w2),g00),y[-T0]);
						AE_MULA32_HH(Ltmp, SSC_MULT16x16_Q15((Q15ONE-w2),g01),SSC_ADD32(y[-T0+1],y[-T0-1]));
						AE_MULA32_HH(Ltmp, SSC_MULT16x16_Q15((Q15ONE-w2),g02),SSC_ADD32(y[-T0+2],y[-T0-2]));
						AE_MULA32_HH(Ltmp, SSC_MULT16x16_Q15(w2,g10),y[-T1]);
						AE_MULA32_HH(Ltmp, SSC_MULT16x16_Q15(w2,g11),SSC_ADD32(y[-T1+1],y[-T1-1]));
						AE_MULA32_HH(Ltmp, SSC_MULT16x16_Q15(w2,g12),SSC_ADD32(y[-T1+2],y[-T1-2]));
#endif
						*y += (int)((long long)Ltmp>>15);
#else
#ifdef VC_PROJ
				Ltmp = SSC_MULT16x32(SSC_MULT16x32_Q15(g00, (Q22ONE - w2)), y[-T0])
					+ SSC_MULT16x32(SSC_MULT16x32_Q15(g01, (Q22ONE - w2)), SSC_ADD32(y[-T0 + 1], y[-T0 - 1]))
					+ SSC_MULT16x32(SSC_MULT16x32_Q15(g02, (Q22ONE - w2)), SSC_ADD32(y[-T0 + 2], y[-T0 - 2]))
					+ SSC_MULT16x32(SSC_MULT16x32_Q15(g10, w2), y[-T1])
					+ SSC_MULT16x32(SSC_MULT16x32_Q15(g11, w2), SSC_ADD32(y[-T1 + 1], y[-T1 - 1]))
					+ SSC_MULT16x32(SSC_MULT16x32_Q15(g12, w2), SSC_ADD32(y[-T1 + 2], y[-T1 - 2]));
#else
		//		Ltmp = SSC_MULT16x32(SSC_MULT16x32_Q15(g00, (Q22ONE - w2)), y[-T0]);
		//		AE_MULA32_HH(Ltmp, SSC_MULT16x32_Q15(g01, (Q22ONE - w2)), SSC_ADD32(y[-T0 + 1], y[-T0 - 1]));
		//		AE_MULA32_HH(Ltmp, SSC_MULT16x32_Q15(g02, (Q22ONE - w2)), SSC_ADD32(y[-T0 + 2], y[-T0 - 2]));
		//		AE_MULA32_HH(Ltmp, SSC_MULT16x32_Q15(g10, w2), y[-T1]);
		//		AE_MULA32_HH(Ltmp, SSC_MULT16x32_Q15(g11, w2), SSC_ADD32(y[-T1 + 1], y[-T1 - 1]));
		//		AE_MULA32_HH(Ltmp, SSC_MULT16x32_Q15(g12, w2), SSC_ADD32(y[-T1 + 2], y[-T1 - 2]));


				Ltmp = AE_MUL32_HH((int)((long long)AE_SRAI64(AE_MUL32_HH(g00, (Q22ONE - w2)), 15)), y[-T0]);
				AE_MULA32_HH(Ltmp, (int)((long long)AE_SRAI64(AE_MUL32_HH(g01, (Q22ONE - w2)), 15)), SSC_ADD32(y[-T0 + 1], y[-T0 - 1]));
				AE_MULA32_HH(Ltmp, (int)((long long)AE_SRAI64(AE_MUL32_HH(g02, (Q22ONE - w2)), 15)), SSC_ADD32(y[-T0 + 2], y[-T0 - 2]));
				AE_MULA32_HH(Ltmp, (int)((long long)AE_SRAI64(AE_MUL32_HH(g10, w2), 15)), y[-T1]);
				AE_MULA32_HH(Ltmp, (int)((long long)AE_SRAI64(AE_MUL32_HH(g11, w2), 15)), SSC_ADD32(y[-T1 + 1], y[-T1 - 1]));
				AE_MULA32_HH(Ltmp, (int)((long long)AE_SRAI64(AE_MUL32_HH(g12, w2), 15)), SSC_ADD32(y[-T1 + 2], y[-T1 - 2]));

#endif
				*y += (int)((long long)Ltmp >> 22);
#endif
				y++;
			}
		}
	}

#ifndef FOR_VISUAL_C_NO_ASSM
	if(N-overlap != 0)
		comb_filter_const_asm(y, T1, N-overlap, g10, g11, g12);
#else
	comb_filter_const(y, T1, N-overlap, g10, g11, g12);
#endif

}

const signed char tf_select_table[8] = {
	0, -2, 0, -3, 3, 0, 1,-1
};
#endif



