



#include "SamsungSolomonVoiceW_Int.h"
#include "SamsungSolomonVoiceW_Table.h"
#include "SamsungSolomonVoiceW_basic_op.h"

#include "SamsungSolomonVoiceW_Mixing.h"

#if 0//(FLAG_SELECT_C_DSP == 1)
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
extern FILE		*fp_dbg_NoiseState, *fp_dbg_MixingState, *fp_dbg_Mixing, *fp_dbg_Wind;
extern FILE		*fp_dbg_Mixingdbg0, *fp_dbg_Mixingdbg1, *fp_dbg_Mixingdbg2, *fp_dbg_Mixingdbg3;
#endif

short FreqMix_normalWind_Inner[2 * 80/*DVTX_FreqMix_MaxBin*/] = { 0, };

void SolomonVoiceWMixingInit(MixingStatus* Mix_buf, SamsungSolomonVoiceWTxMixParam* Mix_param, COMMONBUF* COMMON_buf)
{
	short i;

	/*************** Buffer *****************/
	Mix_buf->State = 0;
	Mix_buf->State_prev = 0;
	Mix_buf->State_Wind = 0;
	Mix_buf->State_Car = 0;
	Mix_buf->State_Noise2Clean = 0;
	Mix_buf->UnFit_State = 0;
	Mix_buf->UnFit_NS_ON = 0;
	Mix_buf->ECNS_out_VAD = 0;
	Mix_buf->Noise_Diff = 0;

	Mix_buf->w_outer = 32767;
	Mix_buf->w_inner = 0;
	Mix_buf->WND_normal_ON = 0;
	Mix_buf->WND_strong_cand = 0;
	Mix_buf->WND_strong_ON = 0;
	Mix_buf->mixing_cnt_up = 0;
	Mix_buf->mixing_cnt_down = 0;
	Mix_buf->mixing_cnt_up_car = 0;
	Mix_buf->mixing_cnt_down_car = 0;
	Mix_buf->mixing_cnt_up_verylowband = 0;
	Mix_buf->mixing_cnt_down_verylowband = 0;

	for (i = 0; i < 2 * 80/*DVTX_FreqMix_MaxBin*/; i++)
		Mix_buf->FreqMix_data_buffer[i] = 0;

	Mix_buf->FreqMix_BLK_NORM = 0;
	Mix_buf->eng_mean_high = 0;
	Mix_buf->eng_mean_low = 0;
	Mix_buf->HPFouter = 0;
	Mix_buf->LPFouter = 0;

	for (i = 0; i < DVTX_M_FFT_HALFLEN_WB; i++)
		Mix_buf->Inner_EEBin_UnFit[i] = 0;

	/*************** Parameter *****************/
	Mix_param->Mix_Freq_onoff = 1;
	Mix_param->Mix_Time_onoff = 1;
	Mix_param->PARA_reserved_9 = 0; //in/out Mixing flag
	Mix_param->PARA_reserved_5 = 0; //PARA_Modechange_Hangover
	Mix_param->PARA_reserved_6 = 0; // PARA_TxRxHPFcoef_index for BT path

	return;
}

void SolomonVoiceW_Mix_ParamConfig(SamsungSolomonVoiceWTxMixParam* Mix_param, SamsungSolomonVoiceWTxMixParam* param)
{
	Mix_param->Mix_Freq_onoff = param->Mix_Freq_onoff;
	Mix_param->Mix_Time_onoff = param->Mix_Time_onoff;
	Mix_param->PARA_reserved_9 = param->PARA_reserved_9;
	Mix_param->PARA_reserved_5 = param->PARA_reserved_5; //InPARA_Modechange_Hangover
	Mix_param->PARA_reserved_6 = param->PARA_reserved_6; // InPARA_TxRxHPFcoef_index for BT path

	return;
}

void fn_MixingGain(MixingStatus* Mix_buf, DVTX_ECNS_Cfg_t* DVTX_ECNS_vars)
{
	int i;
	int w_outer_curr = 0;
	int w_inner_curr = 0;
	//short Mix_buf->HPFouter = 0;
	short B20f_HPF_curr[21] = { 0, };

	short			mbdrc_param_idx;
	short			oneminusalpha;
	static short	alpha_mixing = 32767;
	static short	Clean_State = 1;
	static short	HighNoise_State = 0;

	SamsungSolomonVoiceWTxMBDRCParam* MBDRC_param = &DVTX_ECNS_vars->MBDRC_param;


	if (Mix_buf->State_Wind) {// wind
		w_outer_curr = (int)Mixing_Param[6][1];
		w_inner_curr = (int)Mixing_Param[6][2];
		Mix_buf->HPFouter = (short)Mixing_Param[6][3];
		Mix_buf->LPFouter = (short)Mixing_Param[6][4];
		DVTX_ECNS_vars->COMMON_buf.Gmin = (short)Mixing_Param[6][5];
		Clean_State = (short)Mixing_Param[6][6];
		HighNoise_State = (short)Mixing_Param[6][7];
		DVTX_ECNS_vars->PRENS_Inner_buf.F0flag = (short)Mixing_Param[6][8];
		DVTX_ECNS_vars->PRENS_Inner_buf.ANCflag = (short)Mixing_Param[6][9];
		DVTX_ECNS_vars->PRENS_Outer_buf.ANCflag = (short)Mixing_Param[6][10];
		//w_HPF_stopband_outer = (short)Mixing_Param[6][11];	//½ÇÁ¦·Î ¾²ÀÌÁø ¾ÊÀ½
	}
	else if (Mix_buf->State_Car) {// car
		w_outer_curr = (int)Mixing_Param[5][1];
		w_inner_curr = (int)Mixing_Param[5][2];
		Mix_buf->HPFouter = (short)Mixing_Param[5][3];
		Mix_buf->LPFouter = (short)Mixing_Param[5][4];
		DVTX_ECNS_vars->COMMON_buf.Gmin = (short)Mixing_Param[5][5];
		Clean_State = (short)Mixing_Param[5][6];
		HighNoise_State = (short)Mixing_Param[5][7];
		DVTX_ECNS_vars->PRENS_Inner_buf.F0flag = (short)Mixing_Param[5][8];
		DVTX_ECNS_vars->PRENS_Inner_buf.ANCflag = (short)Mixing_Param[5][9];
		DVTX_ECNS_vars->PRENS_Outer_buf.ANCflag = (short)Mixing_Param[5][10];
		//w_HPF_stopband_outer = (short)Mixing_Param[5][11];
	}
	else {
		w_outer_curr = (int)Mixing_Param[Mix_buf->State][1];
		w_inner_curr = (int)Mixing_Param[Mix_buf->State][2];
		Mix_buf->HPFouter = (short)Mixing_Param[Mix_buf->State][3];
		Mix_buf->LPFouter = (short)Mixing_Param[Mix_buf->State][4];
		DVTX_ECNS_vars->COMMON_buf.Gmin = (short)Mixing_Param[Mix_buf->State][5];
		Clean_State = (short)Mixing_Param[Mix_buf->State][6];
		HighNoise_State = (short)Mixing_Param[Mix_buf->State][7];
		DVTX_ECNS_vars->PRENS_Inner_buf.F0flag = (short)Mixing_Param[Mix_buf->State][8];
		DVTX_ECNS_vars->PRENS_Inner_buf.ANCflag = (short)Mixing_Param[Mix_buf->State][9];
		DVTX_ECNS_vars->PRENS_Outer_buf.ANCflag = (short)Mixing_Param[Mix_buf->State][10];
		//w_HPF_stopband_outer = (short)Mixing_Param[Mix_buf->State][11];
	}
	// add unfit state
	if (Mix_buf->UnFit_State == 1)
	{
		w_outer_curr = w_outer_curr;
		w_inner_curr = w_inner_curr;
		Mix_buf->HPFouter = Mix_buf->HPFouter;
		Mix_buf->LPFouter = Mix_buf->LPFouter;
		DVTX_ECNS_vars->COMMON_buf.Gmin = DVTX_ECNS_vars->COMMON_buf.Gmin;
		Clean_State = Clean_State;
		HighNoise_State = HighNoise_State;
		DVTX_ECNS_vars->PRENS_Inner_buf.F0flag = DVTX_ECNS_vars->PRENS_Inner_buf.F0flag;
		DVTX_ECNS_vars->PRENS_Inner_buf.ANCflag = DVTX_ECNS_vars->PRENS_Inner_buf.ANCflag;
		DVTX_ECNS_vars->PRENS_Outer_buf.ANCflag = DVTX_ECNS_vars->PRENS_Outer_buf.ANCflag;
		//w_HPF_stopband_outer = w_HPF_stopband_outer;
	}

	if (Mix_buf->HPFouter == 1)
		for (i = 0; i < 21; i++)
			B20f_HPF_curr[i] = B20f_hpfir_2k[i];
	else

		for (i = 0; i < 21; i++)
		{
			B20f_HPF_curr[i] = 0;
		}
	B20f_HPF_curr[10] = 32767;

	// parameter recursive averaging
	if (Mix_buf->State > Mix_buf->State_prev) //[round((2^15)*(exp(-6*framelen/Fs/sec)))]
		alpha_mixing = 30249; // up(1.5sec)
	if (Mix_buf->State < Mix_buf->State_prev)
		alpha_mixing = 25776; // down(0.5sec)

	oneminusalpha = 32767 - alpha_mixing;

	if (alpha_mixing != 32767)
	{
		Mix_buf->w_outer = DVTXOP_L_add(DVTXOP_L_mpy_ls(w_outer_curr, oneminusalpha), DVTXOP_L_mpy_ls(Mix_buf->w_outer, alpha_mixing));
		Mix_buf->w_inner = DVTXOP_L_add(DVTXOP_L_mpy_ls(w_inner_curr, oneminusalpha), DVTXOP_L_mpy_ls(Mix_buf->w_inner, alpha_mixing));

		for (i = 0; i < 21; i++)
			B20f_HPF[i] = DVTXOP_add(DVTXOP_mult(B20f_HPF_curr[i], oneminusalpha), DVTXOP_mult(B20f_HPF[i], alpha_mixing));
	}

	/* MBDRC param */
	mbdrc_param_idx = Mix_buf->State;
	if (mbdrc_param_idx > 4)		mbdrc_param_idx = 4;
	if (mbdrc_param_idx < 0)		mbdrc_param_idx = 0;
	if (Mix_buf->State_Wind)		mbdrc_param_idx = 5;
	fn_MBDRC_Noise_Param(MBDRC_param, &MBDRCparam_Noise[mbdrc_param_idx]);

	return;
}

void fn_MixingState(MixingStatus* Mix_buf, DVTX_ECNS_Cfg_t* DVTX_ECNS_vars, short OuterPwr_avrg_LowBand_Longterm, short OuterPwr_avrg_HighBand_Longterm, short OuterPwr_avrg_VeryLowBand)
{
	static short	MixingState_Car_tmp = 0;
	static short	MixingState_verylowband = 0;

	FRAMEStatus* Frame_buf = &DVTX_ECNS_vars->FRAME_buf;

	// Wind State
	Mix_buf->State_Wind = Mix_buf->WND_strong_ON;

	// Mixing State
	Mix_buf->State = HysteresisHangoverThresholding_MultiState(OuterPwr_avrg_LowBand_Longterm,
		Mixing_Thr, 4,
		50,
		50,
		Mix_buf->State,
		&Mix_buf->mixing_cnt_up,
		&Mix_buf->mixing_cnt_down);

	// Mixing State (Car state)
	MixingState_Car_tmp = HysteresisHangoverThresholding_MultiState(OuterPwr_avrg_HighBand_Longterm,
		Thr_MixingState_Car, 1,
		50,
		50,
		MixingState_Car_tmp,
		&Mix_buf->mixing_cnt_up_car,
		&Mix_buf->mixing_cnt_down_car);

	if ((Mix_buf->State > 2) && (MixingState_Car_tmp == 0))
		Mix_buf->State_Car = 1;
	else
		Mix_buf->State_Car = 0;

	// Mixing State (Noise2Clean detection) -> °©ÀÚ±â ÀâÀ½ ¾ø¾îÁö´Â °æ¿ì »¡¸® outer·Î º¯È¯
	MixingState_verylowband = HysteresisHangoverThresholding_MultiState(OuterPwr_avrg_VeryLowBand,
		Thr_MixingState_VeryLowBand, 1,
		10,
		10,
		MixingState_verylowband,
		&Mix_buf->mixing_cnt_up_verylowband,
		&Mix_buf->mixing_cnt_down_verylowband);

	if ((Mix_buf->State > 2) && (MixingState_verylowband == 0))
		Mix_buf->State_Noise2Clean = 1;
	else if ((Mix_buf->State > 2) && ((Frame_buf->Pwr_1kHz_to_4kHz_Outer < 4000) && (Frame_buf->Pwr_100Hz_to_1kHz_Outer < 30000)))
		Mix_buf->State_Noise2Clean = 1;
	else
		Mix_buf->State_Noise2Clean = 0;

	// UnFit flag
	if (Mix_buf->State_Wind || Mix_buf->State_Car)
		Mix_buf->UnFit_NS_ON = 0;
	else if ((Mix_buf->State > 2) && (Mix_buf->UnFit_State == 1))
		Mix_buf->UnFit_NS_ON = 1;
	else
		Mix_buf->UnFit_NS_ON = 0;

	// Clean state
	if (Mix_buf->State_Noise2Clean || ((Frame_buf->Pwr_1kHz_to_4kHz_Outer < 4000) && (Frame_buf->Pwr_100Hz_to_1kHz_Outer < 30000)))
	{
		Mix_buf->State = 0;
		Mix_buf->State_Wind = 0;
		Mix_buf->State_Car = 0;
	}

	return;

}

short fn_BandEnergy_forMixing(int* EEBin, short fl, short fh, short BLK_NORM)
{
	short i, tmpi, FrmPwr;
	int sum_tmp = 0;

	for (i = fl; i < fh; i++)
	{
		sum_tmp = DVTXOP_L_add(sum_tmp, EEBin[i]);
	}
	sum_tmp = DVTXOP_L_shr_r(sum_tmp, BLK_NORM * 2 + 1 - 4);	//Q4

	FrmPwr	= Fx_10log10(sum_tmp, 4);	// Q8

	//FrmPwr	= DVTXOP_mult(tmpi, 7545);	//Q4      7545 = 1/(10*log10(exp(1))) * Q15

	return FrmPwr;
}

short fn_RecursiveAverage_forMixing(short FrmPwr, short OuterPwr_prev, short alpha_down, short alpha_up)
{
	short alpha, oneminusalpha, OuterPwr;

	if (OuterPwr_prev > FrmPwr) // decreasing pwr
	{
		alpha = alpha_down;
		oneminusalpha = 32767 - alpha;
	}
	else
	{
		alpha = alpha_up;
		oneminusalpha = 32767 - alpha;
	}
	OuterPwr = DVTXOP_add(DVTXOP_mult(OuterPwr_prev, alpha), DVTXOP_mult(FrmPwr, oneminusalpha));

	return OuterPwr;
}

int fn_msc(int msc, int *MSC, int *phi_main, int *phi_sub, int *phi_cross_r, int *phi_cross_i, 
	short alpha_up, short oneminusalpha_up, short alpha_down, short oneminusalpha_down, short N)
{//magnitude spectral coherence
	short i;
	short bin_from, bin_to, tmps;
	short alpha, oneminusalpha;
	int tmpl1, tmpl2;
	int msc_curr = 0;	
	long long mean_phi, den, MSC_curr, MSC_tmp1, MSC_tmp2;
	
	bin_from = 0;
	bin_to = N;

	for (i = bin_from; i < bin_to; i++)
	{
		den = DVTXOP_LL_mult(phi_main[i], phi_sub[i]);
		MSC_tmp1 = DVTXOP_LL_mult(phi_cross_r[i], phi_cross_r[i]);
		MSC_tmp2 = DVTXOP_LL_mult(phi_cross_i[i], phi_cross_i[i]);
		MSC_curr = DVTXOP_LL_add(MSC_tmp1, MSC_tmp2);
		
		if (MSC_curr > den)
		{
			MSC[i] = 2147483647; //Q31
		}
		else
		{
			if (den < 2147483648)
			{
				tmpl1 = MSC_curr;
				tmpl2 = den;
				tmps = DVTXOP_norm_l(tmpl2);
				tmpl1 = tmpl1 << tmps;
				tmpl2 = tmpl2 << tmps;
				MSC[i] = DVTXOP_L_divide(tmpl1, tmpl2); //Q31
			}
			else
			{
				tmps = DVTXOP_norm_ll(den);
				tmpl1 = DVTXOP_L_extract_h(MSC_curr << tmps);
				tmpl2 = DVTXOP_L_extract_h(den << tmps);
				MSC[i] = DVTXOP_L_divide(tmpl1, tmpl2); //Q31
			}
		}
	}

	mean_phi = 0;
	for (i = bin_from; i < bin_to; i++)
	{
		mean_phi = DVTXOP_LL_add(mean_phi, MSC[i]); //Q31
	}
	mean_phi = DVTXOP_LL_shr(mean_phi, 2);//mean_phi=mean_phi/4 Q31
	
	if (mean_phi > msc)
	{
		alpha = alpha_up;
		oneminusalpha = oneminusalpha_up;
	}
	else
	{
		alpha = alpha_down;
		oneminusalpha = oneminusalpha_down;
	}

	if (mean_phi > 2147483647)
		msc_curr = 2147483647;
	else if (mean_phi < 0)
		msc_curr = 0;
	else
		msc_curr = (int)mean_phi;

	msc = DVTXOP_L_add(DVTXOP_L_mpy_ls(msc, alpha), DVTXOP_L_mpy_ls(msc_curr, oneminusalpha));

	return msc;
}

short FN_Wind_Detection(DVTX_ECNS_Cfg_t* DVTX_ECNS_vars)
{
	int		sum_tmp, ZCR_main;
	int		FrmPiLowBand_wind = 0;
	int		sigPwr_wind_main[4] = { 0, };
	int		sigPwr_wind_sub[4] = { 0, };
	static int		phi_main_r[4] = { 0, };
	static int		phi_sub_r[4] = { 0, };
	static int		phi_cross_r[4] = { 0, };
	static int		phi_cross_i[4] = { 0, };
	static short	Pwr_wind = 0;
	static short	mixing_cnt_up_wind_strong = 0;
	static short	mixing_cnt_down_wind_strong = 0;
	static short	mixing_cnt_up_wind_normal = 0;
	static short	mixing_cnt_down_wind_normal = 0;
	static int		msc = 0;
	int				Imsc = 0;
	short			wind_flag;
	static int		MSC[4] = { 0, };

	FRAMEStatus* FRAME_buf = &DVTX_ECNS_vars->FRAME_buf;
	MixingStatus* Mix_buf = &DVTX_ECNS_vars->Mix_buf;
	short* data_buffer_WB_main = FRAME_buf->fftbuf_Outer_1.data_buffer;
	short BLK_NORM_WB_main = FRAME_buf->fftbuf_Outer_1.BLK_NORM;
	short* data_buffer_WB_sub = FRAME_buf->fftbuf_Outer_2.data_buffer;
	short BLK_NORM_WB_sub = FRAME_buf->fftbuf_Outer_2.BLK_NORM;
		
	/* 0. power, coherence */
	fx_SolomonVoice_FFT_to_FFTpwr_ave(phi_main_r, sigPwr_wind_main, data_buffer_WB_main, 2 * (BLK_NORM_WB_main - 1), 29491, 3276, 4);
	fx_SolomonVoice_FFT_to_FFTpwr_ave(phi_sub_r,  sigPwr_wind_sub,  data_buffer_WB_sub,  2 * (BLK_NORM_WB_sub - 1),  29491, 3276, 4);
	fx_SolomonVoice_FFT_to_Phi_ave(phi_cross_r, phi_cross_i, data_buffer_WB_main, data_buffer_WB_sub, BLK_NORM_WB_main, BLK_NORM_WB_sub, 29491, 3276, 4);
	
	/* 1. band energy*/
	sum_tmp = 0;
	sum_tmp = DVTXOP_L_add(sum_tmp, sigPwr_wind_main[0]);
	sum_tmp = DVTXOP_L_add(sum_tmp, sigPwr_wind_main[1]);
	sum_tmp = DVTXOP_L_shr_r(sum_tmp, (BLK_NORM_WB_main << 1) - 4);   //Q8

	FrmPiLowBand_wind = Fx_10log10(sum_tmp, 8);                   // Q8

	// calculate Variable THD_Ratio_LowBandPwr
	//Pwr_wind = FrmPiLowBand_wind;// pwr differenct outer inner to decide wind noise condition
	if (Pwr_wind > FrmPiLowBand_wind) // decreasing pwrdiff
	{
		Pwr_wind =
			DVTXOP_add(DVTXOP_mult(Pwr_wind, DVTX_WORD16_0_99), DVTXOP_mult(FrmPiLowBand_wind, DVTX_WORD16_0_01));
	}
	else// increasing pwrdiff
	{
		Pwr_wind =
			DVTXOP_add(DVTXOP_mult(Pwr_wind, DVTX_WORD16_0_8), DVTXOP_mult(FrmPiLowBand_wind, DVTX_WORD16_0_2));
	}

	/* 2. magnitude squared coherence (MSC) */
	msc = fn_msc(msc, MSC, phi_main_r, phi_sub_r, phi_cross_r, phi_cross_i, 31736, 1031, 31736, 1031, 4);
	Imsc = DVTXOP_L_sub(2147483647, msc);	//Q31

	/* 3. ZCR */
	//ZCR_main = fn_WND_ZCR(WNDstr, &WNDstr->ch_main);

	/* 4. wind decision */
	if (Imsc > Thr_Imsc/*Q31*/)
		wind_flag = 1;
	else
		wind_flag = 0;

	Mix_buf->WND_strong_cand = HysteresisHangoverThresholding_MultiState(Pwr_wind,
		Thr_strong_Wind, 1,
		100,
		50,
		Mix_buf->WND_strong_cand,
		&mixing_cnt_up_wind_strong,
		&mixing_cnt_down_wind_strong);

	Mix_buf->WND_strong_ON = (wind_flag && Mix_buf->WND_strong_cand);

	Mix_buf->WND_normal_ON = HysteresisHangoverThresholding_MultiState(Pwr_wind,
		Thr_normal_Wind, 1,
		100,
		50,
		Mix_buf->WND_normal_ON,
		&mixing_cnt_up_wind_normal,
		&mixing_cnt_down_wind_normal);

#if 0//(FLAG_SELECT_C_DSP == 1)
	int i;
	short tmpS;
	for (i = 0; i < DVTX_FRM_LEN_WB; i++)
		fwrite(&Pwr_wind, sizeof(short), 1, fp_dbg_Mixingdbg3);

	tmpS = wind_flag * 16384;
	for (i = 0; i < DVTX_FRM_LEN_WB; i++)
		fwrite(&tmpS, sizeof(short), 1, fp_dbg_Wind_Imsc);

	fprintf(fp_dbg_Wind, "%d %d %d %d %d %d %d %d %d\n",
		Pwr_wind,
		Imsc,
		Thr_Imsc,
		Mix_buf->WND_strong_ON,
		Thr_strong_Wind[0][0],
		Thr_strong_Wind[0][1],
		Mix_buf->WND_strong_cand,
		Thr_normal_Wind[0][0],
		Thr_normal_Wind[0][1],
		Mix_buf->WND_normal_ON
	);
#endif

	return Pwr_wind;
}

short FN_UNFIT_Detection_Coh(DVTX_ECNS_Cfg_t* DVTX_ECNS_vars)
{
	int		sum_tmp;
	int		FrmPiLowBand_wind = 0;
	int		sigPwr_outer[5] = { 0, };
	int		sigPwr_inner[5] = { 0, };
	static int		phi_outer_r[5] = { 0, };
	static int		phi_inner_r[5] = { 0, };
	static int		phi_cross_r[5] = { 0, };
	static int		phi_cross_i[5] = { 0, };
	//static short	Pwr_wind = 0;
	static short	cnt_up = 0;
	static short	cnt_down = 0;
	//static short	mixing_cnt_up_wind_normal = 0;
	//static short	mixing_cnt_down_wind_normal = 0;
	static int		msc = 0;
	static short	unfit_flag = 0;
	static int		MSC[5] = { 0, };

	FRAMEStatus* FRAME_buf = &DVTX_ECNS_vars->FRAME_buf;
	short* data_buffer_outer_WB = FRAME_buf->FFTbuf_Tx_Outer_WB;
	short BLK_NORM_outer_WB = FRAME_buf->fftbuf_Outer_1.BLK_NORM;
	short* data_buffer_inner_NB = FRAME_buf->FFTbuf_Tx_Inner_NB;
	short BLK_NORM_inner_NB = FRAME_buf->fftbuf_Inner.BLK_NORM;

	/* 0. power, coherence */
	fx_SolomonVoice_FFT_to_FFTpwr_ave(phi_outer_r, sigPwr_outer, data_buffer_outer_WB, 2 * (BLK_NORM_outer_WB - 1), 29491, 3276, 5);
	fx_SolomonVoice_FFT_to_FFTpwr_ave(phi_inner_r, sigPwr_inner, data_buffer_inner_NB, 2 * (BLK_NORM_inner_NB - 1), 29491, 3276, 5);
	fx_SolomonVoice_FFT_to_Phi_ave(phi_cross_r, phi_cross_i, data_buffer_outer_WB, data_buffer_inner_NB, BLK_NORM_outer_WB, BLK_NORM_inner_NB, 29491, 3276, 5);
	
	/* 1. magnitude squared coherence (MSC) */
	msc = fn_msc(msc, MSC, phi_outer_r, phi_inner_r, phi_cross_r, phi_cross_i, 32440, 327, 29491, 3276, 4);

	/* 2. unfit decision */
	unfit_flag = HysteresisHangoverThresholding_MultiState(msc,
		Thr_Unfit_Coh, 1,
		35,
		40,
		unfit_flag,
		&cnt_up,
		&cnt_down);

#if 0//(FLAG_SELECT_C_DSP == 1)
	short i, tmpS;

	fprintf(fp_dbg_Unfit, "%d\t%d\n",
		msc,
		unfit_flag);//dbg

	tmpS = unfit_flag * 16384;
	for (i = 0; i < DVTX_FRM_LEN_WB; i++)
		fwrite(&tmpS, sizeof(short), 1, fp_dbg_Unfitpcm);

#endif

	return unfit_flag;
}

int FN_UNFIT_Detection_Leakage(DVTX_ECNS_Cfg_t* DVTX_ECNS_vars, short RxVAD_count)
{
	short	i, j, fl, fh;
	int		eng_mean_curr, enrgE;
	short	alpha_mean_eng_high, oneminusalpha_mean_eng_high;

	static int		FitUnFit_InnerLeakage = 0;
	static short	fitunfit_cnt_up_leakage = 0;
	static short	fitunfit_cnt_down_leakage = 0;

	FRAMEStatus* FRAME_buf = &DVTX_ECNS_vars->FRAME_buf;
	AECStatus* AEC_Outer_buf_1 = &DVTX_ECNS_vars->AEC_Outer_buf_1;
	MixingStatus* Mix_buf = &DVTX_ECNS_vars->Mix_buf;

	short* data_buffer_inner_NB = FRAME_buf->FFTbuf_Tx_Inner_NB;
	short BLK_NORM_inner_NB = FRAME_buf->fftbuf_Inner.BLK_NORM;
	int* Inner_EEBin_UnFit = Mix_buf->Inner_EEBin_UnFit;

	eng_mean_curr = 0;

	fl = 192;
	fh = 256;

	if ((AEC_Outer_buf_1->Flag_RxVAD_AEC == 0) && (RxVAD_count == Thr_RxVAD_count))
	{
		for (i = fl; i < fh; i++)
		{
			j = 2 * i;
			enrgE = DVTXOP_L_mult(data_buffer_inner_NB[j], data_buffer_inner_NB[j]);
			Inner_EEBin_UnFit[i] = DVTXOP_L_mac(enrgE, data_buffer_inner_NB[j + 1], data_buffer_inner_NB[j + 1]);

			eng_mean_curr = DVTXOP_L_add(eng_mean_curr, DVTXOP_L_shr(Inner_EEBin_UnFit[i], 3)); //Q15,0*Q15,0 = Q30,1
		}
		eng_mean_curr = DVTXOP_L_shl(eng_mean_curr, (short)(7 - (2 * BLK_NORM_inner_NB)));/*30,1 -> 23,8*/

		alpha_mean_eng_high = 1638; // 0.05
		oneminusalpha_mean_eng_high = 31129;

		Mix_buf->eng_mean_high = DVTXOP_L_add(DVTXOP_L_mpy_ls(eng_mean_curr, alpha_mean_eng_high),
			DVTXOP_L_mpy_ls(Mix_buf->eng_mean_high, oneminusalpha_mean_eng_high));
	}

	FitUnFit_InnerLeakage = HysteresisHangoverThresholding_MultiState(Mix_buf->eng_mean_high,
		Thr_FitUnFit_leakage, 1,
		50,
		50,
		FitUnFit_InnerLeakage,
		&fitunfit_cnt_up_leakage,
		&fitunfit_cnt_down_leakage);

	return FitUnFit_InnerLeakage;
}

int FN_UNFIT_Detection_Occlusion(DVTX_ECNS_Cfg_t* DVTX_ECNS_vars, short RxVAD_count)
{
	short	i, j, fl, fh;
	int		eng_mean_curr, enrgE;
	short	alpha_mean_eng_low, oneminusalpha_mean_eng_low;

	static int		FitUnFit_InnerOcclusion = 1;
	static short	fitunfit_cnt_up_InnerOcclusion = 0;
	static short	fitunfit_cnt_down_InnerOcclusion = 0;

	FRAMEStatus* FRAME_buf = &DVTX_ECNS_vars->FRAME_buf;
	AECStatus* AEC_Outer_buf_1 = &DVTX_ECNS_vars->AEC_Outer_buf_1;
	MixingStatus* Mix_buf = &DVTX_ECNS_vars->Mix_buf;

	short* data_buffer_inner_NB = FRAME_buf->FFTbuf_Tx_Inner_NB;
	short BLK_NORM_inner_NB = FRAME_buf->fftbuf_Inner.BLK_NORM;
	int* Inner_EEBin_UnFit = Mix_buf->Inner_EEBin_UnFit;

	eng_mean_curr = 0;

	fl = 0;
	fh = 1;

	if ((AEC_Outer_buf_1->Flag_RxVAD_AEC == 0) && (RxVAD_count == Thr_RxVAD_count))
	{
		for (i = fl; i < fh; i++)
		{
			j = 2 * i;
			enrgE = DVTXOP_L_mult(data_buffer_inner_NB[j], data_buffer_inner_NB[j]);
			Inner_EEBin_UnFit[i] = DVTXOP_L_mac(enrgE, data_buffer_inner_NB[j + 1], data_buffer_inner_NB[j + 1]);

			eng_mean_curr = DVTXOP_L_add(eng_mean_curr, DVTXOP_L_shr(Inner_EEBin_UnFit[i], 3)); //Q15,0*Q15,0 = Q30,1
		}
		eng_mean_curr = DVTXOP_L_shl(eng_mean_curr, (short)(7 - (2 * BLK_NORM_inner_NB)));/*30,1 -> 23,8*/

		alpha_mean_eng_low = 1638; // 0.05
		oneminusalpha_mean_eng_low = 31129;

		Mix_buf->eng_mean_low = DVTXOP_L_add(DVTXOP_L_mpy_ls(eng_mean_curr, alpha_mean_eng_low),
			DVTXOP_L_mpy_ls(Mix_buf->eng_mean_low, oneminusalpha_mean_eng_low));
	}

	FitUnFit_InnerOcclusion = HysteresisHangoverThresholding_MultiState(Mix_buf->eng_mean_low,
		Thr_FitUnFit_InnerOcclusion, 1,
		50,
		50,
		FitUnFit_InnerOcclusion,
		&fitunfit_cnt_up_InnerOcclusion,
		&fitunfit_cnt_down_InnerOcclusion);

	return FitUnFit_InnerOcclusion;
}

void FN_SOLOMONVOICEW_TX_MIXING_SET(DVTX_ECNS_Cfg_t* DVTX_ECNS_vars)
{
	short	i, nonstationary_curr;
#if(FLAG_SELECT_C_DSP == 1)
	short print0;
#endif
	//short	*data_buffer;
	short	BLK_NORM;

	// Unfit
	int				FitUnFit_InnerLeakage=0;
	int				FitUnFit_InnerOcclusion;
	static short	RxVAD_count = 0;

	// Mixing
	static short	FrmPwr_mixing_LowBand = 0;
	static short	FrmPwr_mixing_HighBand = 0;
	static short	FrmPwr_mixing_VeryLowBand = 0;
	static short	OuterPwr_avrg_VeryLowBand = 0;
	static short	OuterPwr_avrg_LowBand_Longterm = 0;
	static short	OuterPwr_avrg_HighBand_Longterm = 0;
	static short	OuterPwr_avrg_HighBand_Shortterm = 0;
	short			Thr_nonstationary = 2200;
	int				nonstationary_flag = 0;

	int sum_tmp = 0;


	FRAMEStatus* FRAME_buf = &DVTX_ECNS_vars->FRAME_buf;
	AECStatus* AEC_Outer_buf_1 = &DVTX_ECNS_vars->AEC_Outer_buf_1;
	MixingStatus* Mix_buf = &DVTX_ECNS_vars->Mix_buf;
	short* data_buffer_NB = FRAME_buf->fftbuf_Inner.data_buffer; // data_buffer_NB
	short* data_buffer_WB = FRAME_buf->fftbuf_Outer_1.data_buffer; // data_buffer_WB

	short BLK_NORM_WB = FRAME_buf->fftbuf_Outer_1.BLK_NORM;

	//Mixing.State_prev = Mixing.State;

	// Non-stationary detection
	static int		Outer_hangover_cnt = 10;


	/************* VAD for mixing *************/
	//data_buffer = data_buffer_NB;

	BLK_NORM = BLK_NORM_WB;
	//data_buffer = data_buffer_WB;

	if ((AEC_Outer_buf_1->Flag_RxVAD_AEC == 0) && (RxVAD_count < Thr_RxVAD_count))
	{
		RxVAD_count++;
	}
	if (AEC_Outer_buf_1->Flag_RxVAD_AEC == 1)
	{
		RxVAD_count = 0;
	}

	/************* Fit / UnFit ÆÇ´Ü (Inner Leakage) *************/
	//FitUnFit_InnerLeakage = FN_UNFIT_Detection_Leakage(DVTX_ECNS_vars, RxVAD_count);
	
	/************* Fit / UnFit ÆÇ´Ü (Occlusion Effect) *************/
	//FitUnFit_InnerOcclusion = FN_UNFIT_Detection_Occlusion(DVTX_ECNS_vars, RxVAD_count);

	/************* Fit / UnFit ÆÇ´Ü (inner/outer À¯»çµµ) *************/
	FitUnFit_InnerOcclusion = FN_UNFIT_Detection_Coh(DVTX_ECNS_vars);

	/*if ((FitUnFit_InnerLeakage == 1) && (FitUnFit_InnerOcclusion == 0))
		Mix_buf->UnFit_State = 1;
	else
		Mix_buf->UnFit_State = 0;*/

	Mix_buf->UnFit_State = FitUnFit_InnerOcclusion;


	/******** Band Energy for Mixing ********/
	Mix_buf->ECNS_out_VAD = FRAME_buf->FrmVAD_Outer;

	// Band Energy for Mixing
	if ((Mix_buf->State < 3) && (Mix_buf->ECNS_out_VAD == 1))
	{
		FrmPwr_mixing_LowBand = FrmPwr_mixing_LowBand;
		FrmPwr_mixing_HighBand = FrmPwr_mixing_HighBand;
	}
	else
	{
		FrmPwr_mixing_VeryLowBand // (for Noise2Clean state) 62.5 ~ 125Hz
			= fn_BandEnergy_forMixing(FRAME_buf->L_EEBin_forMixing, 2/*fl*/, 4/*fh*/, BLK_NORM);
		FrmPwr_mixing_LowBand // 0 ~ 500Hz
			= fn_BandEnergy_forMixing(FRAME_buf->L_EEBin_forMixing, 0/*fl*/, 16/*fh*/, BLK_NORM);
		FrmPwr_mixing_HighBand // 2kHz ~ 8kHz
			= fn_BandEnergy_forMixing(FRAME_buf->L_EEBin_forMixing, 64/*fl*/, 255/*fh*/, BLK_NORM);
	}

	// recursive averaging
	OuterPwr_avrg_VeryLowBand = fn_RecursiveAverage_forMixing(FrmPwr_mixing_VeryLowBand, OuterPwr_avrg_VeryLowBand, 26297/*alpha_down*/, 32055/*alpha_up*/);
	OuterPwr_avrg_LowBand_Longterm = fn_RecursiveAverage_forMixing(FrmPwr_mixing_LowBand, OuterPwr_avrg_LowBand_Longterm, 32055/*alpha_down*/, 32055/*alpha_up*/);
	OuterPwr_avrg_HighBand_Longterm = fn_RecursiveAverage_forMixing(FrmPwr_mixing_HighBand, OuterPwr_avrg_HighBand_Longterm, 32055/*alpha_down*/, 32055/*alpha_up*/);
	OuterPwr_avrg_HighBand_Shortterm = fn_RecursiveAverage_forMixing(FrmPwr_mixing_HighBand, OuterPwr_avrg_HighBand_Shortterm, 26297/*alpha_down*/, 26297/*alpha_up*/);

	/******** Non-stationary detection ********/
	Mix_buf->Noise_Diff = OuterPwr_avrg_HighBand_Longterm - OuterPwr_avrg_HighBand_Shortterm;
	if (Mix_buf->Noise_Diff < 0) Mix_buf->Noise_Diff = -1 * Mix_buf->Noise_Diff;

	if (Mix_buf->Noise_Diff > Thr_nonstationary)
	{
		nonstationary_curr = 32767;
	}
	else {
		nonstationary_curr = 0;
	}

	nonstationary_flag = HysteresisHangoverThresholding((int)nonstationary_curr, 16384, 200, nonstationary_flag, &Outer_hangover_cnt); //Outer_hangover_cnt => static??

	/******** Mixing (Mixing state ÆÇ´Ü) ********/
	//Mixing.State_prev = Mixing.State;
	fn_MixingState(Mix_buf, DVTX_ECNS_vars, OuterPwr_avrg_LowBand_Longterm, OuterPwr_avrg_HighBand_Longterm, OuterPwr_avrg_VeryLowBand);


	/******** Mixing (Mixing °¡ÁßÄ¡ »êÃâ) ********/
	fn_MixingGain(Mix_buf, DVTX_ECNS_vars);

#if 0//(FLAG_SELECT_C_DSP == 1)
	/******** dbg files ********/
	print0 = Mix_buf->State * 3276;
	for (i = 0; i < DVTX_FRM_LEN_WB; i++)
		fwrite(&print0, sizeof(short), 1, fp_dbg_NoiseState);

	if (Mix_buf->WND_strong_ON)
		print0 = -15000;
	else if (Mix_buf->WND_normal_ON)
		print0 = -10000;
	else if (Mix_buf->State_Car)
		print0 = -5000;
	else
		print0 = Mix_buf->State * 3276;

	if (Mix_buf->State_Noise2Clean)
		print0 = -16384;

	for (i = 0; i < DVTX_FRM_LEN_WB; i++)
		fwrite(&print0, sizeof(short), 1, fp_dbg_MixingState);

	for (i = 0; i < DVTX_FRM_LEN_WB; i++)
		fwrite(&OuterPwr_avrg_VeryLowBand, sizeof(short), 1, fp_dbg_Mixingdbg0);

	for (i = 0; i < DVTX_FRM_LEN_WB; i++)
		fwrite(&OuterPwr_avrg_LowBand_Longterm, sizeof(short), 1, fp_dbg_Mixingdbg1);

	for (i = 0; i < DVTX_FRM_LEN_WB; i++)
		fwrite(&OuterPwr_avrg_HighBand_Longterm, sizeof(short), 1, fp_dbg_Mixingdbg2);

	fprintf(fp_dbg_Mixing, "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n",
		OuterPwr_avrg_LowBand_Longterm,
		OuterPwr_avrg_HighBand_Longterm,
		0, Mix_buf->w_outer, Mix_buf->w_inner, Mix_buf->HPFouter, print0,
		0,
		Mix_buf->ECNS_out_VAD,
		nonstationary_flag,
		/*phi_mean_low_curr_f,
		phi_mean_low_sm_f,*/
		0, 0, 0,
		Mix_buf->eng_mean_high,
		Mix_buf->eng_mean_low,
		FitUnFit_InnerLeakage,
		FitUnFit_InnerOcclusion,
		Mix_buf->UnFit_State,
		Mix_buf->UnFit_NS_ON,
		AEC_Outer_buf_1->Flag_RxVAD_AEC);
#endif

	Mix_buf->State_prev = Mix_buf->State;

	return;
}

#ifndef FN_Mixing_FreqDomain_OPT_DSP
void FN_Mixing_FreqDomain(DVTX_ECNS_Cfg_t* DVTX_ECNS_vars)
{
	short	i, j, tmp, tmp1, tmp2;
	int		Ltmp1, Ltmp2;
	short	*data_buffer_inner;
	short	*data_buffer_outer;
	short	centerFreq_Mix = 0;

	FRAMEStatus* FRAME_buf = &DVTX_ECNS_vars->FRAME_buf;
	MixingStatus* Mix_buf = &DVTX_ECNS_vars->Mix_buf;
#ifdef DEBUG_MODULE
	SamsungSolomonVoiceWTxMixParam* Mix_param = &DVTX_ECNS_vars->Mix_param;
#endif

	short BLK_NORM_NB = FRAME_buf->fftbuf_Inner.BLK_NORM;
	short BLK_NORM_WB = FRAME_buf->fftbuf_Outer_1.BLK_NORM;

	int	WND_strong_ON = Mix_buf->WND_strong_ON;
	int	WND_normal_ON = Mix_buf->WND_normal_ON;
	int	w_outer = Mix_buf->w_outer;
	int	w_inner = Mix_buf->w_inner;

	if (FLAG_WB_OuterECNSOnly == 1)
		return;

#ifdef DEBUG_MODULE
	if (Mix_param->Mix_Freq_onoff == 0)
		return;
#endif
	data_buffer_inner = DVTX_ECNS_vars->FRAME_buf.fftbuf_Inner.data_buffer; // data_buffer_NB;
	data_buffer_outer = DVTX_ECNS_vars->FRAME_buf.fftbuf_Outer_1.data_buffer; // data_buffer_WB;

	// mixing band
	if (Mix_buf->State_Car == 1)
		centerFreq_Mix = (short)Mixing_Param[5][11];
	else if (WND_strong_ON == 1)
		centerFreq_Mix = (short)Mixing_Param[6][11];
	else if (WND_normal_ON == 1)
		centerFreq_Mix = 16;
	else
		centerFreq_Mix = (short)Mixing_Param[Mix_buf->State_prev][11];

	// backup copy for mixing
	for (i = 0; i < DVTX_FreqMix_MaxBin; i++)
	{
		Mix_buf->FreqMix_data_buffer[2 * i] = data_buffer_inner[2 * i];
		Mix_buf->FreqMix_data_buffer[2 * i + 1] = data_buffer_inner[2 * i + 1];
	}
	Mix_buf->FreqMix_BLK_NORM = BLK_NORM_NB;

	// (Inner) w_inner & sig EQ
	tmp = Mix_buf->FreqMix_BLK_NORM - BLK_NORM_WB;
	for (i = 0; i < DVTX_FreqMix_MaxBin; i++) // 2500Hz
	{
		// fre-EQ
		Ltmp1 = DVTXOP_L_mult(Mix_buf->FreqMix_data_buffer[2 * i], FreqMix_EQ[i]);//Q:tmp+9+1
		Ltmp2 = DVTXOP_L_mult(Mix_buf->FreqMix_data_buffer[2 * i + 1], FreqMix_EQ[i]);

		// WND_normal_ON
		if (WND_normal_ON)
		{
			//normalization
			FreqMix_normalWind_Inner[2 * i] = DVTXOP_extract_l(DVTXOP_L_shr(Ltmp1, tmp + 9 + 1 - 1 + 2));
			FreqMix_normalWind_Inner[2 * i + 1] = DVTXOP_extract_l(DVTXOP_L_shr(Ltmp2, tmp + 9 + 1 - 1 + 2));
		}

		Ltmp1 = DVTXOP_L_mpy_ls(Ltmp1, w_inner);
		Ltmp2 = DVTXOP_L_mpy_ls(Ltmp2, w_inner);

		//normalization
		Mix_buf->FreqMix_data_buffer[2 * i] = DVTXOP_extract_l(DVTXOP_L_shr(Ltmp1, tmp + 9 + 1 - 1 + 2));
		Mix_buf->FreqMix_data_buffer[2 * i + 1] = DVTXOP_extract_l(DVTXOP_L_shr(Ltmp2, tmp + 9 + 1 - 1 + 2));
	}

	/***** (Inner) inner corssover *****/
	if (centerFreq_Mix > 16)
	{
		for (i = 0; i < centerFreq_Mix - 16; i++)
		{
			Mix_buf->FreqMix_data_buffer[2 * i] = DVTXOP_mult_r(Mix_buf->FreqMix_data_buffer[2 * i], FreqMix_gain_inner[0]);
			Mix_buf->FreqMix_data_buffer[2 * i + 1] = DVTXOP_mult_r(Mix_buf->FreqMix_data_buffer[2 * i + 1], FreqMix_gain_inner[0]);
		}
		for (i = centerFreq_Mix - 16, j = 0; i < centerFreq_Mix + 16; i++, j++)
		{
			Mix_buf->FreqMix_data_buffer[2 * i] = DVTXOP_mult_r(Mix_buf->FreqMix_data_buffer[2 * i], FreqMix_gain_inner[j]);
			Mix_buf->FreqMix_data_buffer[2 * i + 1] = DVTXOP_mult_r(Mix_buf->FreqMix_data_buffer[2 * i + 1], FreqMix_gain_inner[j]);
		}
		for (i = centerFreq_Mix + 16; i < DVTX_FreqMix_MaxBin; i++)
		{
			Mix_buf->FreqMix_data_buffer[2 * i] = DVTXOP_mult_r(Mix_buf->FreqMix_data_buffer[2 * i], FreqMix_gain_inner[31]);
			Mix_buf->FreqMix_data_buffer[2 * i + 1] = DVTXOP_mult_r(Mix_buf->FreqMix_data_buffer[2 * i + 1], FreqMix_gain_inner[31]);
		}
	}

	/***** (Outer) outer crossover *****/
	if (WND_strong_ON)
		{
			for (i = 0; i < 128; i++)
			{
				data_buffer_outer[2 * i] = DVTXOP_mult_r(data_buffer_outer[2 * i], FreqMix_Wind[i]);
				data_buffer_outer[2 * i + 1] = DVTXOP_mult_r(data_buffer_outer[2 * i + 1], FreqMix_Wind[i]);
			}
		}
	else
		{
		i = 0;

		//if (Mix_buf->UnFit_State == 1) // unfit state
		//{
		//	for (i = 0; i < DVTX_FreqMix_Outer_LPF_cutoff_UnFit; i++)
		//	{
		//		data_buffer_outer[2 * i] = DVTXOP_mult_r(data_buffer_outer[2 * i], 22000);
		//		data_buffer_outer[2 * i + 1] = DVTXOP_mult_r(data_buffer_outer[2 * i + 1], 22000);
		//	}
		//}

		if (centerFreq_Mix > 16)
		{
			for (; i < centerFreq_Mix - 16; i++)
			{
				data_buffer_outer[2 * i] = DVTXOP_mult_r(data_buffer_outer[2 * i], FreqMix_gain_outer[0]);
				data_buffer_outer[2 * i + 1] = DVTXOP_mult_r(data_buffer_outer[2 * i + 1], FreqMix_gain_outer[0]);
			}
			for (i = centerFreq_Mix - 16, j = 0; i < centerFreq_Mix + 16; i++, j++)
			{
				data_buffer_outer[2 * i] = DVTXOP_mult_r(data_buffer_outer[2 * i], FreqMix_gain_outer[j]);
				data_buffer_outer[2 * i + 1] = DVTXOP_mult_r(data_buffer_outer[2 * i + 1], FreqMix_gain_outer[j]);
		}
			for (i = centerFreq_Mix + 16; i < DVTX_FreqMix_MaxBin; i++)
		{
				data_buffer_outer[2 * i] = DVTXOP_mult_r(data_buffer_outer[2 * i], FreqMix_gain_outer[31]);
				data_buffer_outer[2 * i + 1] = DVTXOP_mult_r(data_buffer_outer[2 * i + 1], FreqMix_gain_outer[31]);
			}
		}
	}

	// (Outer) w_outer
	for (i = 0; i < DVTX_M_FFT_HALFLEN_WB; i++)
	{
		data_buffer_outer[2 * i] = DVTXOP_mult_r(data_buffer_outer[2 * i], w_outer);
		data_buffer_outer[2 * i + 1] = DVTXOP_mult_r(data_buffer_outer[2 * i + 1], w_outer);
	}

	/***** (Mixing) *****/
	for (i = 0; i < DVTX_FreqMix_MaxBin; i++)
	{
		data_buffer_outer[2 * i] = DVTXOP_add(data_buffer_outer[2 * i], Mix_buf->FreqMix_data_buffer[2 * i]);
		data_buffer_outer[2 * i + 1] = DVTXOP_add(data_buffer_outer[2 * i + 1], Mix_buf->FreqMix_data_buffer[2 * i + 1]);
	}

	if (WND_normal_ON && !WND_strong_ON && !Mix_buf->UnFit_State)
	{
		for (i = 0; i < 32; i++)
		{
			FreqMix_normalWind_Inner[2 * i] = DVTXOP_mult_r(FreqMix_normalWind_Inner[2 * i], FreqMix_gain_inner[i]);
			FreqMix_normalWind_Inner[2 * i + 1] = DVTXOP_mult_r(FreqMix_normalWind_Inner[2 * i + 1], FreqMix_gain_inner[i]);

			data_buffer_outer[2 * i] = DVTXOP_mult_r(data_buffer_outer[2 * i], FreqMix_gain_outer[i]);
			data_buffer_outer[2 * i + 1] = DVTXOP_mult_r(data_buffer_outer[2 * i + 1], FreqMix_gain_outer[i]);

			data_buffer_outer[2 * i] = DVTXOP_add(data_buffer_outer[2 * i], FreqMix_normalWind_Inner[2 * i]);
			data_buffer_outer[2 * i + 1] = DVTXOP_add(data_buffer_outer[2 * i + 1], FreqMix_normalWind_Inner[2 * i + 1]);
		}
	}

	return;
}
#else
void FN_Mixing_FreqDomain(DVTX_ECNS_Cfg_t* DVTX_ECNS_vars)
{
	short	i, j, tmp, tmp1, tmp2;
	int		Ltmp1, Ltmp2;
	short	*data_buffer_inner;
	short	*data_buffer_outer;
	short	centerFreq_Mix = 0;

	FRAMEStatus* FRAME_buf = &DVTX_ECNS_vars->FRAME_buf;
	MixingStatus* Mix_buf = &DVTX_ECNS_vars->Mix_buf;
#ifdef DEBUG_MODULE
	SamsungSolomonVoiceWTxMixParam* Mix_param = &DVTX_ECNS_vars->Mix_param;
#endif

	short BLK_NORM_NB = FRAME_buf->fftbuf_Inner.BLK_NORM;
	short BLK_NORM_WB = FRAME_buf->fftbuf_Outer_1.BLK_NORM;

	int	WND_strong_ON = Mix_buf->WND_strong_ON;
	int	WND_normal_ON = Mix_buf->WND_normal_ON;
	int	w_outer = Mix_buf->w_outer;
	int	w_inner = Mix_buf->w_inner;

	if (FLAG_WB_OuterECNSOnly == 1)
		return;

#ifdef DEBUG_MODULE
	if (Mix_param->Mix_Freq_onoff == 0)
		return;
#endif
	data_buffer_inner = DVTX_ECNS_vars->FRAME_buf.fftbuf_Inner.data_buffer; // data_buffer_NB;
	data_buffer_outer = DVTX_ECNS_vars->FRAME_buf.fftbuf_Outer_1.data_buffer; // data_buffer_WB;

	// mixing band
	if (Mix_buf->State_Car == 1)
		centerFreq_Mix = (short)Mixing_Param[5][11];
	else if (WND_strong_ON == 1)
		centerFreq_Mix = (short)Mixing_Param[6][11];
	else if (WND_normal_ON == 1)
		centerFreq_Mix = 16;
	else
		centerFreq_Mix = (short)Mixing_Param[Mix_buf->State_prev][11];
	// backup copy for mixing



	{
		ae_valign  align1, align2;
		ae_int16x4 *pt1, *pt2;
		pt1 = (ae_int16x4 *)data_buffer_inner;            //??????????????
		pt2 = (ae_int16x4 *)Mix_buf->FreqMix_data_buffer;
			align1 = AE_LA64_PP(pt1);     //?memeory????????align1,??????????pt1
			align2 = AE_ZALIGN64();       //??????0
		ae_int16x4 data,data1;
		for (i = 0; i < DVTX_FreqMix_MaxBin; i+=4)
		{
				AE_LA16X4_IP(data, align1, pt1);// ???
			AE_LA16X4_IP(data1, align1, pt1);// ???
				AE_SA16X4_IP(data, align2, pt2);// ???
			AE_SA16X4_IP(data1, align2, pt2);// ???
		}
		AE_SA64POS_FP(align2, pt2);

	}
	Mix_buf->FreqMix_BLK_NORM = BLK_NORM_NB;

	// (Inner) w_inner & sig EQ
	tmp = Mix_buf->FreqMix_BLK_NORM - BLK_NORM_WB;
	tmp=tmp + 9 + 1 - 1 + 2;
	if (WND_normal_ON)
	{
	for (i = 0; i < DVTX_FreqMix_MaxBin; i++) // 2500Hz
	{
		// fre-EQ
		Ltmp1 = DVTXOP_L_mult(Mix_buf->FreqMix_data_buffer[2 * i], FreqMix_EQ[i]);//Q:tmp+9+1
		Ltmp2 = DVTXOP_L_mult(Mix_buf->FreqMix_data_buffer[2 * i + 1], FreqMix_EQ[i]);

			// WND_normal_ON
			//normalization
			FreqMix_normalWind_Inner[2 * i] = DVTXOP_extract_l(DVTXOP_L_shr(Ltmp1, tmp));
			FreqMix_normalWind_Inner[2 * i + 1] = DVTXOP_extract_l(DVTXOP_L_shr(Ltmp2, tmp ));

		Ltmp1 = DVTXOP_L_mpy_ls(Ltmp1, w_inner);
		Ltmp2 = DVTXOP_L_mpy_ls(Ltmp2, w_inner);

		//normalization
			Mix_buf->FreqMix_data_buffer[2 * i] = DVTXOP_extract_l(DVTXOP_L_shr(Ltmp1, tmp));
			Mix_buf->FreqMix_data_buffer[2 * i + 1] = DVTXOP_extract_l(DVTXOP_L_shr(Ltmp2, tmp));
		}
	}
	else
	{
		for (i = 0; i < DVTX_FreqMix_MaxBin; i++) // 2500Hz
		{
		// fre-EQ
			Ltmp1 = DVTXOP_L_mult(Mix_buf->FreqMix_data_buffer[2 * i], FreqMix_EQ[i]);//Q:tmp+9+1
			Ltmp2 = DVTXOP_L_mult(Mix_buf->FreqMix_data_buffer[2 * i + 1], FreqMix_EQ[i]);

			Ltmp1 = DVTXOP_L_mpy_ls(Ltmp1, w_inner);
			Ltmp2 = DVTXOP_L_mpy_ls(Ltmp2, w_inner);

	   //normalization
			Mix_buf->FreqMix_data_buffer[2 * i] = DVTXOP_extract_l(DVTXOP_L_shr(Ltmp1,tmp ));
			Mix_buf->FreqMix_data_buffer[2 * i + 1] = DVTXOP_extract_l(DVTXOP_L_shr(Ltmp2, tmp));
		}
	}
	// (Inner) inner corssover
	if (centerFreq_Mix > 16)
	{
		for (i = 0; i < centerFreq_Mix - 16; i++)
		{
			Mix_buf->FreqMix_data_buffer[2 * i] = DVTXOP_mult_r(Mix_buf->FreqMix_data_buffer[2 * i], FreqMix_gain_inner[0]);
			Mix_buf->FreqMix_data_buffer[2 * i + 1] = DVTXOP_mult_r(Mix_buf->FreqMix_data_buffer[2 * i + 1], FreqMix_gain_inner[0]);
		}
		/*for (i = centerFreq_Mix - 16, j = 0; i < centerFreq_Mix + 16; i++, j++)
		{
			Mix_buf->FreqMix_data_buffer[2 * i] = DVTXOP_mult_r(Mix_buf->FreqMix_data_buffer[2 * i], FreqMix_gain_inner[j]);
			Mix_buf->FreqMix_data_buffer[2 * i + 1] = DVTXOP_mult_r(Mix_buf->FreqMix_data_buffer[2 * i + 1], FreqMix_gain_inner[j]);
		}*/
		{
			short i;
			ae_valign  align1,align2, align3;
			ae_int16x4 *pouter=(ae_int16x4 *)&(Mix_buf->FreqMix_data_buffer[2*(centerFreq_Mix - 16)]);
			ae_int16x4 *pouter1=pouter;
			align1 = AE_LA64_PP(pouter);
			ae_int16x4 tmp16x4,tmp_outer;
			align2 = AE_ZALIGN64();
			for (i = centerFreq_Mix - 16, j = 0; i < centerFreq_Mix + 16; i+=2, j+=2)
			{
				tmp_outer = AE_MOVDA16X2(FreqMix_gain_inner[j],FreqMix_gain_inner[j+1]);
				tmp_outer = AE_SEL16_7362(tmp_outer, tmp_outer);
				AE_LA16X4_IP(tmp16x4,align1,pouter);
				tmp16x4=AE_MULFP16X4RAS_vector(tmp16x4, tmp_outer);
				AE_SA16X4_IP(tmp16x4, align2, pouter1);
			}
			AE_SA64POS_FP(align2, pouter1);
		}

			for (i = centerFreq_Mix + 16; i < DVTX_FreqMix_MaxBin; i++)
		{
				Mix_buf->FreqMix_data_buffer[2 * i] = DVTXOP_mult_r(Mix_buf->FreqMix_data_buffer[2 * i], FreqMix_gain_inner[31]);
				Mix_buf->FreqMix_data_buffer[2 * i + 1] = DVTXOP_mult_r(Mix_buf->FreqMix_data_buffer[2 * i + 1], FreqMix_gain_inner[31]);
			}
		}

	/***** (Outer) outer crossover *****/
	if (WND_strong_ON)
	{
		/*for (i = 0; i < 128; i++)
		{
			data_buffer_outer[2 * i] = DVTXOP_mult_r(data_buffer_outer[2 * i], FreqMix_Wind[i]);
			data_buffer_outer[2 * i + 1] = DVTXOP_mult_r(data_buffer_outer[2 * i + 1], FreqMix_Wind[i]);
		}*/
		{
			short i;
			ae_valign  align1,align2, align3;
			ae_int16x4 *pouter=(ae_int16x4 *)&(data_buffer_outer[0]);
			ae_int16x4 *pouter1=pouter;
			align1 = AE_LA64_PP(pouter);
			ae_int16x4 tmp16x4,tmp_outer;
	align2 = AE_ZALIGN64();
			for (i = 0; i < 128; i+=2)
	{
				tmp_outer = AE_MOVDA16X2(FreqMix_Wind[i],FreqMix_Wind[i+1]);
				tmp_outer = AE_SEL16_7362(tmp_outer, tmp_outer);
				AE_LA16X4_IP(tmp16x4,align1,pouter);
				tmp16x4=AE_MULFP16X4RAS_vector(tmp16x4, tmp_outer);
				AE_SA16X4_IP(tmp16x4, align2, pouter1);
			}
			AE_SA64POS_FP(align2, pouter1);
	}
		}
		else
		{
		i = 0;

		//if (Mix_buf->UnFit_State == 1) // unfit state
		//{
		//	/*for (i = 0; i < DVTX_FreqMix_Outer_LPF_cutoff_UnFit; i++)
		//	{
		//		data_buffer_outer[2 * i] = DVTXOP_mult_r(data_buffer_outer[2 * i], 22000);
		//		data_buffer_outer[2 * i + 1] = DVTXOP_mult_r(data_buffer_outer[2 * i + 1], 22000);
		//	}*/
		//	{
		//		short i;
		//		ae_valign  align1,align2, align3;
		//		ae_int16x4 *pouter=(ae_int16x4 *)&data_buffer_outer[0];
		//		ae_int16x4 *pouter1=pouter;
		//		align1 = AE_LA64_PP(pouter);
		//		ae_int16x4 tmp16x4,tmp_outer;
		//			align2 = AE_ZALIGN64();
		//		tmp_outer=AE_MOVDA16X2(22000,22000);
		//		for (i = 0; i < DVTX_FreqMix_Outer_LPF_cutoff_UnFit-2; i+=2)
		//			{
		//			AE_LA16X4_IP(tmp16x4,align1,pouter);
		//			tmp16x4=AE_MULFP16X4RAS_vector(tmp16x4, tmp_outer);
		//			AE_SA16X4_IP(tmp16x4, align2, pouter1);
		//		}
		//		AE_SA64POS_FP(align2, pouter1);

		//		data_buffer_outer[40] = DVTXOP_mult_r(data_buffer_outer[40], 22000);
		//		data_buffer_outer[41] = DVTXOP_mult_r(data_buffer_outer[41], 22000);
		//		data_buffer_outer[42] = DVTXOP_mult_r(data_buffer_outer[42], 22000);
		//		data_buffer_outer[43] = DVTXOP_mult_r(data_buffer_outer[43], 22000);
		//			}
		//		}

		if (centerFreq_Mix > 16)
		{
			for ( ; i < centerFreq_Mix - 16; i++)
		{
				data_buffer_outer[2 * i] = DVTXOP_mult_r(data_buffer_outer[2 * i], FreqMix_gain_outer[0]);
				data_buffer_outer[2 * i + 1] = DVTXOP_mult_r(data_buffer_outer[2 * i + 1], FreqMix_gain_outer[0]);
		}
			/*for (i = centerFreq_Mix - 16, j = 0; i < centerFreq_Mix + 16; i++, j++)
			{
				data_buffer_outer[2 * i] = DVTXOP_mult_r(data_buffer_outer[2 * i], FreqMix_gain_outer[j]);
				data_buffer_outer[2 * i + 1] = DVTXOP_mult_r(data_buffer_outer[2 * i + 1], FreqMix_gain_outer[j]);
			}*/
			{
				short i;
				ae_valign  align1,align2, align3;
				ae_int16x4 *pouter=(ae_int16x4 *)&(data_buffer_outer[2*(centerFreq_Mix - 16)]);
				ae_int16x4 *pouter1=pouter;
		align1 = AE_LA64_PP(pouter);
				ae_int16x4 tmp16x4,tmp_outer;
		align2 = AE_ZALIGN64();
				for (i = centerFreq_Mix - 16, j = 0; i < centerFreq_Mix + 16; i+=2, j+=2)
		{
					tmp_outer = AE_MOVDA16X2(FreqMix_gain_outer[j],FreqMix_gain_outer[j+1]);
					tmp_outer = AE_SEL16_7362(tmp_outer, tmp_outer);
					AE_LA16X4_IP(tmp16x4,align1,pouter);
					tmp16x4=AE_MULFP16X4RAS_vector(tmp16x4, tmp_outer);
					AE_SA16X4_IP(tmp16x4, align2, pouter1);
		}
		AE_SA64POS_FP(align2, pouter1);
	}
				for (i = centerFreq_Mix + 16; i < DVTX_FreqMix_MaxBin; i++)
				{
					data_buffer_outer[2 * i] = DVTXOP_mult_r(data_buffer_outer[2 * i], FreqMix_gain_outer[31]);
					data_buffer_outer[2 * i + 1] = DVTXOP_mult_r(data_buffer_outer[2 * i + 1], FreqMix_gain_outer[31]);
				}
			}
		}

	// (Outer) w_outer
	/*for (i = 0; i < DVTX_FreqMix_MaxBin; i++)
	{
		data_buffer_outer[2 * i] = DVTXOP_add(DVTXOP_mult_r(data_buffer_outer[2 * i], w_outer),Mix_buf->FreqMix_data_buffer[2 * i]);
		data_buffer_outer[2 * i + 1] = DVTXOP_add(DVTXOP_mult_r(data_buffer_outer[2 * i + 1], w_outer),Mix_buf->FreqMix_data_buffer[2 * i + 1]);
	    }*/

		{
				short i;
		ae_valign  align1,align2, align3;
		ae_int16x4 *pouter=(ae_int16x4 *)&data_buffer_outer[0];
		ae_int16x4 *pouter1=pouter;
		ae_int16x4 *pFreqMix_data=(ae_int16x4 *)&(Mix_buf->FreqMix_data_buffer[0]);
				align1 = AE_LA64_PP(pouter);
		align3 = AE_LA64_PP(pFreqMix_data);
		ae_int16x4 tmp16x4,tmp_outer,FreqMix_data16x4;
				align2 = AE_ZALIGN64();
		tmp_outer=AE_MOVDA16X2(w_outer,w_outer);
		for (i = 0; i < DVTX_FreqMix_MaxBin; i+=2)
				{
			AE_LA16X4_IP(tmp16x4,align1,pouter);
			AE_LA16X4_IP(FreqMix_data16x4,align3,pFreqMix_data);
			tmp16x4=AE_MULFP16X4RAS_vector(tmp16x4, tmp_outer)+FreqMix_data16x4;
			AE_SA16X4_IP(tmp16x4, align2, pouter1);
				}
		AE_SA64POS_FP(align2, pouter1);
		}
	/***** (Mixing) *****/
	/*for (i = DVTX_FreqMix_MaxBin; i < DVTX_M_FFT_HALFLEN_WB; i++)
	{
		data_buffer_outer[2 * i] = DVTXOP_mult_r(data_buffer_outer[2 * i], w_outer);
		data_buffer_outer[2 * i + 1] = DVTXOP_mult_r(data_buffer_outer[2 * i + 1], w_outer);
	}*/

		{
			    short i;
		ae_valign  align1,align2;
		ae_int16x4 *pouter=(ae_int16x4 *)&data_buffer_outer[2 * DVTX_FreqMix_MaxBin];
		ae_int16x4 *pouter1=pouter;
				align1 = AE_LA64_PP(pouter);
		ae_int16x4 tmp16x4,tmp_outer;
				align2 = AE_ZALIGN64();
		tmp_outer=AE_MOVDA16X2(w_outer,w_outer);
		for (i = DVTX_FreqMix_MaxBin; i < DVTX_M_FFT_HALFLEN_WB; i+=2)
				{
			AE_LA16X4_IP(tmp16x4,align1,pouter);
			tmp16x4=AE_MULFP16X4RAS_vector(tmp16x4, tmp_outer);
			AE_SA16X4_IP(tmp16x4, align2, pouter1);
				}
				AE_SA64POS_FP(align2, pouter1);
	}
	if (WND_normal_ON && !WND_strong_ON && !Mix_buf->UnFit_State)
	{
		/*for (i = 0; i < 32; i++)
		{
			FreqMix_normalWind_Inner[2 * i] = DVTXOP_mult_r(FreqMix_normalWind_Inner[2 * i], FreqMix_gain_inner[i]);
			FreqMix_normalWind_Inner[2 * i + 1] = DVTXOP_mult_r(FreqMix_normalWind_Inner[2 * i + 1], FreqMix_gain_inner[i]);

			data_buffer_outer[2 * i] = DVTXOP_mult_r(data_buffer_outer[2 * i], FreqMix_gain_outer[i]);
			data_buffer_outer[2 * i + 1] = DVTXOP_mult_r(data_buffer_outer[2 * i + 1], FreqMix_gain_outer[i]);

			data_buffer_outer[2 * i] = DVTXOP_add(data_buffer_outer[2 * i], FreqMix_normalWind_Inner[2 * i]);
			data_buffer_outer[2 * i + 1] = DVTXOP_add(data_buffer_outer[2 * i + 1], FreqMix_normalWind_Inner[2 * i + 1]);
		}*/
		{
			short i;
			ae_valign  align1,align2, align3;
			ae_int16x4 *pouter=(ae_int16x4 *)&(data_buffer_outer[0]);
			ae_int16x4 *pouter1=pouter;
			ae_int16x4 *pFreqMix=(ae_int16x4 *)&(FreqMix_normalWind_Inner[0]);
			align1 = AE_LA64_PP(pouter);
			align3 = AE_LA64_PP(pFreqMix);
			ae_int16x4 tmp16x4,FreqMix16x4,tmp_outer,tmp_inner;
			align2 = AE_ZALIGN64();
			for (i = 0; i < 32; i+=2)
			{
				tmp_outer = AE_MOVDA16X2(FreqMix_gain_outer[i],FreqMix_gain_outer[i+1]);
				tmp_inner = AE_MOVDA16X2(FreqMix_gain_inner[i],FreqMix_gain_inner[i+1]);
				tmp_outer = AE_SEL16_7362(tmp_outer, tmp_outer);
				tmp_inner = AE_SEL16_7362(tmp_inner, tmp_inner);
				AE_LA16X4_IP(tmp16x4,align1,pouter);
				AE_LA16X4_IP(FreqMix16x4,align3,pFreqMix);
				tmp16x4=AE_MULFP16X4RAS_vector(tmp16x4, tmp_outer);
				tmp16x4=AE_MULFP16X4RAS_vector(FreqMix16x4, tmp_inner)+tmp16x4;
				AE_SA16X4_IP(tmp16x4, align2, pouter1);
		}
			AE_SA64POS_FP(align2, pouter1);
		}

	}

	return;
}
#endif
