
#if(FLAG_SELECT_C_DSP == 1)
#include <stdio.h>
#include <stdlib.h>
#endif

#include "SamsungSolomonVoiceW_AEC.h"
#include "SamsungSolomonVoiceW_Default_functions.h"

void SolomonVoiceWAECInit(AECStatus* AEC_buf, SamsungSolomonVoiceWTxAECParam* AEC_param, COMMONBUF* common_buf, CHANNEL channel)
{
	short i;

	/**** Buffer *****/
	AEC_buf->adf_var = (short *)&common_buf->Buff_L_WB;
#ifndef KHW_OPTI_20191216_HIFI
	for (i = 0; i < DVTX_Nadf_MAX; i++)
		AEC_buf->ADF_IN[i] = 0;
#else
	__vec_memset(AEC_buf->ADF_IN,0,DVTX_Nadf_MAX<<1);
#endif

#ifndef KHW_OPTI_20191216_HIFI
	for (i = 0; i < DVTX_Nadf_WB; i++) {
		AEC_buf->W[i] = 0;
		AEC_buf->Waux[i] = 0;
	}
#else
	__vec_memset(AEC_buf->W,0,DVTX_Nadf_WB<<1);
	__vec_memset(AEC_buf->Waux,0,DVTX_Nadf_WB<<1);
#endif

//#ifndef KHW_OPTI_20191216_HIFI
//	for (i = 0; i < DVTX_RxSigon_BuffLen_MAX; i++) {
//		AEC_buf->Buff_RxOnset_aecout[i] = 0; // max 4 frmae 320*4=1280, NB/WB common
//		AEC_buf->Buff_RxOnset_txin[i] = 0;
//	}
//#else
//	__vec_memset(AEC_buf->Buff_RxOnset_aecout,0,DVTX_RxSigon_BuffLen_MAX<<1);
//	__vec_memset(AEC_buf->Buff_RxOnset_txin,0,DVTX_RxSigon_BuffLen_MAX<<1);
//#endif

#ifndef KHW_OPTI_20191216_HIFI
	for (i = 0; i < DVTX_Nadfshort_WB; i++) {
		AEC_buf->ADF_IN_short[i] = 0;
	}
#else
	__vec_memset(AEC_buf->ADF_IN_short,0,DVTX_Nadfshort_WB<<1);
#endif

	AEC_buf->Pwr_RX_AECIN_dB = 0;
	AEC_buf->Pwr_TX_AECIN_dB = 0;
	AEC_buf->Pwr_TX_AECOUT_dB = 0;
	AEC_buf->Pwr_TX_AECauxOUT_dB = 0;
	AEC_buf->PwrDiff_AECinout_dB = 0;

	AEC_buf->L_Pwr_tonality_ringband = 0;
	AEC_buf->L_Pwr_tonality_otherband = 0;

	AEC_buf->Count_DelayCompensation_function_exe = 0;

	AEC_buf->Cnt_Samples_NLMSupdate = 0;

	if (channel == CH_OUTER_1)
	{
		AEC_buf->E_tx_AEC = common_buf->gE_tx_AEC;
		AEC_buf->E_tx_AECaux = common_buf->gE_tx_AECaux;
		AEC_buf->RxFrm_Delay_AEC = common_buf->gRxFrm_Delay_AEC;
		AEC_buf->RxFrm_AECin_AEC = common_buf->gRxFrm_AECin_AEC;
		AEC_buf->RxFFTfrm_AEC = common_buf->gRxFFTfrm_AEC;
		AEC_buf->RxFFTfrm_clp_AEC = common_buf->gRxFFTfrm_clp_AEC;
	}
	else if (channel == CH_OUTER_2)
	{
		AEC_buf->E_tx_AEC = &common_buf->gE_tx_AEC[DVTX_M_FRM_LEN_WB];
		AEC_buf->E_tx_AECaux = &common_buf->gE_tx_AECaux[DVTX_M_FRM_LEN_WB];
		AEC_buf->RxFrm_Delay_AEC = &common_buf->gRxFrm_Delay_AEC[2000];
		AEC_buf->RxFrm_AECin_AEC = &common_buf->gRxFrm_AECin_AEC[DVTX_M_FRM_LEN_WB + DVTX_Nadf_MAX - 1];
		AEC_buf->RxFFTfrm_AEC = &common_buf->gRxFFTfrm_AEC[DVTX_M_FRM_LEN_WB];
		AEC_buf->RxFFTfrm_clp_AEC = &common_buf->gRxFFTfrm_clp_AEC[DVTX_M_FRM_LEN_WB];
	}
	else
	{
		AEC_buf->E_tx_AEC = &common_buf->gE_tx_AEC[DVTX_M_FRM_LEN_WB * OUTER_NUM];
		AEC_buf->E_tx_AECaux = &common_buf->gE_tx_AECaux[DVTX_M_FRM_LEN_WB * OUTER_NUM];
		AEC_buf->RxFrm_Delay_AEC = &common_buf->gRxFrm_Delay_AEC[2000 * OUTER_NUM];
		AEC_buf->RxFrm_AECin_AEC = &common_buf->gRxFrm_AECin_AEC[(DVTX_M_FRM_LEN_WB + DVTX_Nadf_MAX - 1) * OUTER_NUM];
		AEC_buf->RxFFTfrm_AEC = &common_buf->gRxFFTfrm_AEC[DVTX_M_FRM_LEN_WB * OUTER_NUM];
		AEC_buf->RxFFTfrm_clp_AEC = &common_buf->gRxFFTfrm_clp_AEC[DVTX_M_FRM_LEN_WB * OUTER_NUM];
	}
	
	AEC_buf->Flag_RxVAD_AEC = 0;/*Flag_RxVAD_AEC=1 when PwrRx>THD, 	ini_val = 0	*/
	AEC_buf->Flag_TxSilence_AEC = 1;// 1:sig activ 0:silence, ini=1, Npsd_silence est. 
	AEC_buf->Flag_Tx_LoudSig = 1; // 1:oud Tx. avoid cepstral smoothing
	AEC_buf->Flag_SingleTalk = 0;
	AEC_buf->Flag_SingleNET = 0;
	AEC_buf->Flag_ringbakctone = 0;
	AEC_buf->Flag_IniRxSigOnset = 0;
	AEC_buf->Flag_Waux_update = 0;
	AEC_buf->Flag_Tx_silent_mode = 0;

	AEC_buf->hangover_cnt_flag_RxVAD_First = 0;

	AEC_buf->Qex_q = 0;
	AEC_buf->Qxx_q = 0;
	AEC_buf->L_Qex = 1;
	AEC_buf->L_Qxx = 1;
	AEC_buf->XECC = 0;
	AEC_buf->Threshold_XECC = 1000; //0.2*2^13

	/***** Param ******/
	AEC_param->DelayCompensation = 0;

	AEC_param->PARA_FLAG_RxVAD_First_AEC = 0;
	AEC_param->PARA_reserved_7 = 0; // PARA_EchoBulkDelay_Search_samplerange
	
	AEC_param->PARA_Nadfdelay = 0;
	AEC_param->PARA_Pwr_LoTHD_ADF_IN = 0;
	AEC_param->PARA_THD_Pwr_Rx_AEC_IN_dB = 0;
	AEC_param->PARA_THD_Pwr_Tx_dB = 0;
	AEC_param->PARA_THD_Pwr_Tx_Loud_dB = 0;
	AEC_param->PARA_THD_RxTx_Pwr_Difference = 0;
	AEC_param->PARA_ADF_reference_step = 0;
	AEC_param->PARA_ADF_reference_step_lowbit = 0; // int to two-short
	AEC_param->PARA_ADF_reference_step_highbit = 0;
	AEC_param->PARA_ADF_Wvar_THD = 0;
	AEC_param->PARA_ADF_Wvar_THD_lowbit = 0;
	AEC_param->PARA_ADF_Wvar_THD_highbit = 0;
	
	AEC_param->PARA_reserved_1 = 0;
	AEC_param->PARA_reserved_21 = 0;	// PARA_THD_XECC_high : xcorr upper threshold
	AEC_param->PARA_reserved_22 = 0;	// PARA_THD_XECC_low  : xcorr lower threshold
	AEC_param->PARA_reserved_23 = 0;	// PARA_EchoPSD_Gain_highXECC : resi Echo psd gain in high xcorr
	AEC_param->PARA_reserved_24 = 0;	// PARA_EchoPSD_Gain_lowXECC  : resi Echo psd gain in low  xcorr
	AEC_param->PARA_reserved_25 = 0;	// ringback sig pwrdiff thd lowbit
	AEC_param->PARA_reserved_26 = 0;	// ringback sig pwrdiff thd lowbit
	AEC_param->PARA_reserved_27 = 0;	// PwrDiff_TxRx_to detect strong ST
	AEC_param->PARA_reserved_28 = 0;	// PARA_RxClipping_Bound
	AEC_param->PARA_reserved_29 = 0;	// PARA_THD_Pwr_Tx_AECin_low
	AEC_param->PARA_reserved_30 = 0;	// PwrDiff TxRx to detect strong tx-NET only
	AEC_param->PARA_reserved_33 = 0;	// PARA_THD_AECinoutDIFFerence to update Waux
	
	AEC_param->PARA_reserved_34 = 0;	// reserved
	AEC_param->PARA_reserved_35 = 0;
	AEC_param->PARA_reserved_36 = 0;
	AEC_param->PARA_reserved_37 = 0;
	AEC_param->PARA_reserved_38 = 0;
	AEC_param->PARA_reserved_39 = 0;
	AEC_param->PARA_reserved_40 = 0;

	return;
}

void SolomonVoiceW_AEC_ParamConfig(SamsungSolomonVoiceWTxAECParam* AEC_param, SamsungSolomonVoiceWTxAECParam* param)
{
	AEC_param->PARA_reserved_1 = param->PARA_reserved_1;

	AEC_param->PARA_FLAG_RxVAD_First_AEC = param->PARA_FLAG_RxVAD_First_AEC;
	AEC_param->PARA_reserved_7 = param->PARA_reserved_7;

	AEC_param->PARA_Nadfdelay = param->PARA_Nadfdelay;
	AEC_param->PARA_Pwr_LoTHD_ADF_IN = param->PARA_Pwr_LoTHD_ADF_IN;
	AEC_param->PARA_THD_Pwr_Rx_AEC_IN_dB = param->PARA_THD_Pwr_Rx_AEC_IN_dB;
	AEC_param->PARA_THD_Pwr_Tx_dB = param->PARA_THD_Pwr_Tx_dB;
	AEC_param->PARA_THD_Pwr_Tx_Loud_dB = param->PARA_THD_Pwr_Tx_Loud_dB;
	AEC_param->PARA_THD_RxTx_Pwr_Difference = param->PARA_THD_RxTx_Pwr_Difference;
	AEC_param->PARA_ADF_reference_step = ((param->PARA_ADF_reference_step_highbit << 16) + (param->PARA_ADF_reference_step_lowbit & 0x0000ffff));
	AEC_param->PARA_ADF_Wvar_THD = ((param->PARA_ADF_Wvar_THD_highbit << 16) + (param->PARA_ADF_Wvar_THD_lowbit & 0x0000ffff));
	
	AEC_param->PARA_reserved_21 = param->PARA_reserved_21;
	AEC_param->PARA_reserved_22 = param->PARA_reserved_22;
	AEC_param->PARA_reserved_23 = param->PARA_reserved_23;
	AEC_param->PARA_reserved_24 = param->PARA_reserved_24;
	AEC_param->PARA_reserved_25 = param->PARA_reserved_25;
	AEC_param->PARA_reserved_26 = param->PARA_reserved_26;
	AEC_param->PARA_reserved_27 = param->PARA_reserved_27;
	AEC_param->PARA_reserved_28 = param->PARA_reserved_28;
	AEC_param->PARA_reserved_29 = param->PARA_reserved_29;
	AEC_param->PARA_reserved_30 = param->PARA_reserved_30;
	AEC_param->PARA_reserved_33 = param->PARA_reserved_33;

	AEC_param->PARA_reserved_34 = param->PARA_reserved_34;
	AEC_param->PARA_reserved_35 = param->PARA_reserved_35;
	AEC_param->PARA_reserved_36 = param->PARA_reserved_36;
	AEC_param->PARA_reserved_37 = param->PARA_reserved_37;
	AEC_param->PARA_reserved_38 = param->PARA_reserved_38;
	AEC_param->PARA_reserved_39 = param->PARA_reserved_39;
	AEC_param->PARA_reserved_40 = param->PARA_reserved_40;

	AEC_param->DelayCompensation = param->PARA_Nadfdelay;

	return;
}

short fx_SolomonVoice_Rx_ringbacktone_detection(AECStatus* AEC_buff, SamsungSolomonVoiceWTxAECParam* AEC_param)
{
	/* SolomonVoice_SubBlocks_AEC :
	ring back tone tedection, to avoid bulk delay estimation and NLMS update
	DVTX_ECNS_vars->AECADF.Flag_ringbakctone 1:ring back tone interval
	*/

	short Flag_ringbakctone;
	short param_0 = AEC_param->PARA_reserved_26;
	short param_1 = AEC_param->PARA_reserved_25;
	int Ltmp, THD_pwr_ringbacktone;
	int L_Pwr_tonality_ringband = AEC_buff->L_Pwr_tonality_ringband;
	int L_Pwr_tonality_otherband = AEC_buff->L_Pwr_tonality_otherband;

	THD_pwr_ringbacktone = ((param_0 << 16) + (param_1 & 0x0000ffff));
	Ltmp = L_Pwr_tonality_ringband - L_Pwr_tonality_otherband;

#if(FLAG_SELECT_C_DSP == 1)	
#if(Debug_File_Write_C == 1)
	fprintf(fp_fx_SolomonVoice_ringbacktone_detection, "%ld %ld\n", Ltmp, THD_pwr_ringbacktone);  //x/2^8
#endif
#endif

	if (Ltmp > THD_pwr_ringbacktone)
		Flag_ringbakctone = 1; // ring back tone
	else
		Flag_ringbakctone = 0;
	
	return Flag_ringbakctone;
}

void fx_SolomonVoice_Rx_In_for_ADF(/*In*/short *Speech_rx, /*Out*/short *RxFFTfrm_AEC, /*Out*/short *RxFrm_AECin_AEC,
	/*Param*/short PARA_Gain_RxSig, short PARA_Q_for_InSigGain, short *RxFrm_Delay_AEC, short DelayCompensation,
	short NadfMinun1, short FRM_LEN, COMMONBUF* COMMON_buf)
{	
	short *RxFrm_AEC = (short *)COMMON_buf->Buff_L_NB;

	// Rx input signal gain
	Fx_vector_copy_s(RxFrm_AEC, Speech_rx, FRM_LEN);
	//Fx_vector_gain(RxFrm_AEC, PARA_Gain_RxSig, PARA_Q_for_InSigGain, FRM_LEN); // gain is Q4.10 format... (can be omitted in the final version)

	// Rx synchronization & buffering for ADF
#if(FLAG_SELECT_C_DSP == 1)	//hoon_test
	Fx_vector_copy_s(RxFrm_Delay_AEC, RxFrm_Delay_AEC + FRM_LEN, DelayCompensation);
#else
#ifndef KHW_OPTI_20191216_HIFI
	Fx_vector_copy_s_for(RxFrm_Delay_AEC, RxFrm_Delay_AEC + FRM_LEN, DelayCompensation);
#else
	__vec_memcpy(RxFrm_Delay_AEC, RxFrm_Delay_AEC + FRM_LEN, DelayCompensation<<1);
#endif
#endif

	Fx_vector_copy_s(RxFrm_Delay_AEC + DelayCompensation, RxFrm_AEC, FRM_LEN);
#if(FLAG_SELECT_C_DSP == 1)	//hoon_test
	Fx_vector_copy_s(RxFrm_AECin_AEC, RxFrm_AECin_AEC + FRM_LEN, NadfMinun1);
#else
#ifndef KHW_OPTI_20191216_HIFI
	Fx_vector_copy_s_for(RxFrm_AECin_AEC, RxFrm_AECin_AEC + FRM_LEN, NadfMinun1);
#else
	__vec_memcpy(RxFrm_AECin_AEC, RxFrm_AECin_AEC + FRM_LEN, NadfMinun1<<1);
#endif
#endif
	Fx_vector_copy_s(RxFrm_AECin_AEC + NadfMinun1, RxFrm_Delay_AEC, FRM_LEN);

	// Rx FFT ref signal
	Fx_vector_copy_s(RxFFTfrm_AEC, RxFrm_Delay_AEC, FRM_LEN);


	return;
}

void fx_SolomonVoice_Tx_In_for_ADF(/*In*/short *Speech, /*Out*/short *TxFrm_AEC, /*Param*/short PARA_Gain_TxSig, short PARA_Q_for_InSigGain, short FRM_LEN)
{
	// Tx input signal gain
	Fx_vector_copy_s(TxFrm_AEC, Speech, FRM_LEN);
	//Fx_vector_gain(TxFrm_AEC, PARA_Gain_TxSig, PARA_Q_for_InSigGain, FRM_LEN); // gain is Q4.10 format... 

	return;
}


#ifndef SRCB_1016_OPT
void fx_SolomonVoice_rx_clipping_for_FNLMS(short *OutClipped, short *In, short ValClipp, short Nframe)
{
	short k;

	for (k = 0; k < Nframe; k++)
	{
		OutClipped[k] = DVTX_MAX(DVTX_MIN(In[k], ValClipp), -(ValClipp));
	}
}
#else
void fx_SolomonVoice_rx_clipping_for_FNLMS(short *OutClipped, short *In, short ValClipp, short Nframe)
{
	int k;
	ae_int16x4 *p1, *p2;
	ae_int16x4 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6;
	ae_valign align1, align2;
	xtbool4 bool4;

	p1 = (ae_int16x4 *)In;
	p2 = (ae_int16x4 *)OutClipped;
	align1 = AE_LA64_PP(p1);
	align2 = AE_ZALIGN64();
	tmp3 = AE_MOVDA16(ValClipp);
	tmp4 = AE_MOVDA16(-ValClipp);

	for(k=0; k<Nframe; k+=4)
	{
		AE_LA16X4_IP(tmp1, align1, p1);
		bool4 = AE_LT16(tmp3, tmp1);
		AE_MOVT16X4(tmp1, tmp3, bool4);
		bool4 = AE_LT16(tmp1, tmp4);
		AE_MOVT16X4(tmp1, tmp4, bool4);
		AE_SA16X4_IP(tmp1, align2, p2);
	}
	AE_SA64POS_FP(align2, p2);
}

#endif


short fx_SolomonVoice_AEC_Flag_RxVAD(short Pwr_RX_AECIN_dB, short PARA_THD_Pwr_Rx_AEC_IN_dB)
{
	return (Pwr_RX_AECIN_dB >= PARA_THD_Pwr_Rx_AEC_IN_dB); // 1:on   0:off	
}

short fx_SolomonVoice_AEC_Flag_TxSilence(short Pwr_TX_AECIN_dB, short PARA_THD_Pwr_Tx_dB)
{
	return (Pwr_TX_AECIN_dB >= PARA_THD_Pwr_Tx_dB); // 1:sig activ 0:silence, not used 
}

short fx_SolomonVoice_AEC_Flag_LoudSig(short Pwr_TX_AECIN_dB, short PARA_THD_Pwr_Tx_Loud_dB)
{
	return (Pwr_TX_AECIN_dB >= PARA_THD_Pwr_Tx_Loud_dB); // 1:sig loud 0:sig normal,   used to avoid cepstral smoothing for speech
}

short fx_SolomonVoice_AEC_Flag_SingleTalk(short Pwr_RX_AECIN_dB, short Pwr_TX_AECIN_dB, short PARA_reserved_27, AECStatus* AECADF)
{
	short PwrDiff_Tx_Rx_Frm;
	short Flag_SingleTalk;
	short XECC = AECADF->XECC;
	short Threshold_XECC = AECADF->Threshold_XECC;
	
	PwrDiff_Tx_Rx_Frm = DVTXOP_sub(Pwr_TX_AECIN_dB, Pwr_RX_AECIN_dB);

	if ((PwrDiff_Tx_Rx_Frm < PARA_reserved_27) || (XECC > Threshold_XECC))
		Flag_SingleTalk = 1;
	else
		Flag_SingleTalk = 0;

	return Flag_SingleTalk;
}

short fx_SolomonVoice_AEC_Flag_SingleNET(short Pwr_RX_AECIN_dB, short Pwr_TX_AECIN_dB, short PARA_reserved_30)
{
	short PwrDiff_Tx_Rx_Frm;
	short Flag_SingleNET;

	PwrDiff_Tx_Rx_Frm = DVTXOP_sub(Pwr_TX_AECIN_dB, Pwr_RX_AECIN_dB);
	
	if (PwrDiff_Tx_Rx_Frm > PARA_reserved_30)
		Flag_SingleNET = 1;
	else
		Flag_SingleNET = 0;

	return Flag_SingleNET;
}
//#ifndef EC_DELAY_ESTIMATION_OPT_DSP
//void fx_SolomonVoice_bulk_delay_estimation(AECStatus* AEC_buf, SamsungSolomonVoiceWTxAECParam* AEC_param, SamsungSolomonVoiceWTxFRAMEParam* FRAME_param, RESStatus* RES_buf, short *TxFrm_AEC, CHANNEL channel)
//{
//	short k, m, pt_crtsmp;
//	short auto_corr, cross_corr, tmp_corr, sign_ear_W;
//	short delay_comp = 0;
//	short 	FRM_LEN;
//	short 	Nadf;
//	short 	Nadfshort;
//	short 	NadfMinun1;
//	short 	RxSigOnset_FRAME;
//	short 	DelayCompenRange_Less;
//	short 	DelayCompenRange_More;
//
//#ifndef UNOPT_MEMORY
//	int var_L_RxAEC_Out_AEC = 0;
//#endif
//
//	if (channel == CH_OUTER_1)
//	{
//		FRM_LEN = DVTX_FRM_LEN_WB;
//		Nadf = DVTX_Nadf_WB;
//		Nadfshort = DVTX_Nadfshort_WB;
//		NadfMinun1 = DVTX_NadfMinun1_WB;
//		RxSigOnset_FRAME = DVTX_RxSigOnset_FRAME_WB;
//		DelayCompenRange_Less = DVTX_DelayCompenRange_Less_WB;
//		DelayCompenRange_More = AEC_param->PARA_reserved_7;
//	}
//	else if (channel == CH_OUTER_2)
//	{
//		FRM_LEN = DVTX_FRM_LEN_WB;
//		Nadf = DVTX_Nadf_WB;
//		Nadfshort = DVTX_Nadfshort_WB;
//		NadfMinun1 = DVTX_NadfMinun1_WB;
//		RxSigOnset_FRAME = DVTX_RxSigOnset_FRAME_WB;
//		DelayCompenRange_Less = DVTX_DelayCompenRange_Less_WB;
//		DelayCompenRange_More = AEC_param->PARA_reserved_7;
//	}
//	else
//	{
//		FRM_LEN = DVTX_FRM_LEN_NB;
//		Nadf = DVTX_Nadf_NB;
//		Nadfshort = DVTX_Nadfshort_NB;
//		NadfMinun1 = DVTX_NadfMinun1_NB;
//		RxSigOnset_FRAME = DVTX_RxSigOnset_FRAME_NB;
//		DelayCompenRange_Less = DVTX_DelayCompenRange_Less_NB;
//		DelayCompenRange_More = AEC_param->PARA_reserved_7;
//	}
//
//
//	//ADF filtering
//	for (k = 0; k < FRM_LEN; k++)
//	{
//		// read ADF input data
//		if (k == 0)  //read first Nadf samples
//		{
//			Fx_vector_copy_s(AEC_buf->ADF_IN_short, AEC_buf->RxFrm_AECin_AEC + Nadf - Nadfshort, Nadfshort);
//			pt_crtsmp = Nadfshort - 1;
//		}
//		else
//			AEC_buf->ADF_IN_short[pt_crtsmp] = AEC_buf->RxFrm_AECin_AEC[NadfMinun1 + k];
//		// ADF convolution
//
//
//#ifndef Fx_convolve_OPT_DSP
//		var_L_RxAEC_Out_AEC = Fx_convolve(AEC_buf->ADF_IN_short, AEC_buf->W, pt_crtsmp, Nadfshort); //Q0*Q17=Q13,18
//#else
//		var_L_RxAEC_Out_AEC = Fx_convolve_optimized(AEC_buf->ADF_IN_short, AEC_buf->W, Nadfshort); //Q0*Q17=Q13,18
//#endif
//
//
//
//
//
//																																	// current sample pointer update
//		pt_crtsmp++;
//		if (pt_crtsmp >= Nadfshort)
//			pt_crtsmp = 0;
//
//		m = RxSigOnset_FRAME - AEC_buf->hangover_cnt_flag_RxVAD_First - 1;
//
//		if (var_L_RxAEC_Out_AEC > 100000)
//			AEC_buf->Buff_RxOnset_aecout[m*FRM_LEN + k] = +1;
//		else if (var_L_RxAEC_Out_AEC < -100000)
//			AEC_buf->Buff_RxOnset_aecout[m*FRM_LEN + k] = -1;
//		else
//			AEC_buf->Buff_RxOnset_aecout[m*FRM_LEN + k] = 0;
//		if (TxFrm_AEC[k] > 10)
//			AEC_buf->Buff_RxOnset_txin[m*FRM_LEN + k] = 1;
//		else if (TxFrm_AEC[k] < -10)
//			AEC_buf->Buff_RxOnset_txin[m*FRM_LEN + k] = -1;
//		else
//			AEC_buf->Buff_RxOnset_txin[m*FRM_LEN + k] = 0;
//	}
//
//	// read ADF input data
//	// ADF convolution
//	// current sample pointer update
//
//	//delay compensation by sign x-correlation
//	// calculated cross correlation between two clipped signals
//	if (AEC_buf->hangover_cnt_flag_RxVAD_First == 0)
//	{
//		// auto correlation to detect tone signal
//		auto_corr = DVTX_MIN_16;
//		for (m = 100; m <= 150; m++) // 100~200 to calculate auto correlation
//		{
//			tmp_corr = 0;
//			for (k = 200; k < DVTX_RxSigon_BuffLen_MAX - 300; k++) // 200~1620 : 1420 sample interval
//			{
//				tmp_corr = tmp_corr + (AEC_buf->Buff_RxOnset_aecout[k] * AEC_buf->Buff_RxOnset_aecout[k + m]);
//			}
//			//aaa[m -100] = tmp_corr;
//			if (auto_corr < tmp_corr)
//			{
//				auto_corr = tmp_corr;
//			}
//		}
//
//		// bulk delay calculation by 
//		sign_ear_W = 1;
//		delay_comp = 0;
//		cross_corr = DVTX_MIN_16;
//		for (m = -DelayCompenRange_Less; m <= DelayCompenRange_More; m++) // -20~120 delay search range 
//		{
//			tmp_corr = 0;
//			for (k = 200; k < DVTX_RxSigon_BuffLen_MAX - 300; k++) // 200~1420
//			{
//				tmp_corr = tmp_corr + (AEC_buf->Buff_RxOnset_aecout[k] * AEC_buf->Buff_RxOnset_txin[k + m]);
//			}
//			//bbb[m + DelayCompenRange_Less] = tmp_corr;
//			if (cross_corr < tmp_corr)
//			{
//				cross_corr = tmp_corr;
//				delay_comp = m;
//			}
//		}
//
//		if (FRAME_param->PARA_call_mode_HS_HF_EAR == 2) // for EAR mode
//		{
//			for (m = -DelayCompenRange_Less; m <= DelayCompenRange_More; m++) // -20~120 delay search range 
//			{
//				tmp_corr = 0;
//				for (k = 200; k < DVTX_RxSigon_BuffLen_MAX - 300; k++) // 200~1420
//				{
//					tmp_corr = tmp_corr + (-1 * AEC_buf->Buff_RxOnset_aecout[k] * AEC_buf->Buff_RxOnset_txin[k + m]);
//				}
//				//bbb[m + DelayCompenRange_Less] = tmp_corr;
//				if (cross_corr < tmp_corr)
//				{
//					cross_corr = tmp_corr;
//					delay_comp = m;
//					sign_ear_W = -1;
//				}
//			}
//		}
//		if (cross_corr == 0) // no valid search case
//		{
//			delay_comp = 0;
//			sign_ear_W = 1;
//		}
//
//		if (delay_comp + AEC_param->PARA_Nadfdelay < 0)
//			delay_comp = 0;
//
//		if (auto_corr > 710 || cross_corr < 710) // auto-corr=1420*0.5=710, cross_corr 1420*0.4
//		{
//			AEC_buf->hangover_cnt_flag_RxVAD_First = (RxSigOnset_FRAME);
//		}
//		else
//		{
//			// delay compensation
//			AEC_param->DelayCompensation = AEC_param->PARA_Nadfdelay + delay_comp;
//			// copy W to Waux				
//			if (FRAME_param->PARA_call_mode_HS_HF_EAR == 2 && sign_ear_W == -1) // for EAR mode
//			{
//				for (k = 0; k < Nadf; k++) // 200~1420
//				{
//					AEC_buf->W[k] = AEC_buf->W[k] * (-1);
//					AEC_buf->Waux[k] = AEC_buf->Waux[k] * (-1);
//				}
//			}
//		}
//	}
//
//	// RxOnset hangover count.. 3-frames
//	if (AEC_buf->hangover_cnt_flag_RxVAD_First > 0)
//		AEC_buf->hangover_cnt_flag_RxVAD_First--;
//	else
//		AEC_param->PARA_FLAG_RxVAD_First_AEC = 0;
//
//	// terminate delay compensation after 2 minute = 0.02*6000 frames
//	AEC_buf->Count_DelayCompensation_function_exe++;
//	if ((AEC_buf->Count_DelayCompensation_function_exe > DVTX_Num_of_BulkDelaySearch_exe) || (RES_buf->CntFrmRxVADon > DVTX_Num_of_ini_RxOn_Frmae)) // within 1sec
//		AEC_param->PARA_FLAG_RxVAD_First_AEC = 0;
//
//	return;
//
//}
//#else
//void fx_SolomonVoice_bulk_delay_estimation_clip1(short *d, int *s, int V, int len)
//{
//	int k;
//	ae_int16x4 *p1;
//	ae_int32x2 *Lp1;
//	ae_int16x4 tmp1;
//	ae_int32x2 Ltmp1, Ltmp2, Ltmp3, Ltmp4, Ltmp5, Ltmp6, Ltmp7;
//	ae_valign align1, align2;
//	xtbool2 bool2;
//
//	Lp1 = (ae_int32x2 *)s;
//	p1 = (ae_int16x4 *)d;
//	align1 = AE_LA64_PP(Lp1);
//	align2 = AE_ZALIGN64();
//	Ltmp4 = AE_MOVDA32(V);
//	Ltmp5 = AE_MOVDA32(-V);
//	Ltmp6 = AE_MOVDA32(1);
//	Ltmp7 = AE_MOVDA32(-1);
//	for(k=0; k<len; k+=4)
//	{
//		AE_LA32X2_IP(Ltmp1, align1, Lp1);
//		Ltmp2 = AE_ZERO32();
//		bool2 = AE_LT32(Ltmp4, Ltmp1);
//		AE_MOVT32X2(Ltmp2, Ltmp6, bool2);
//		bool2 = AE_LT32(Ltmp1, Ltmp5);
//		AE_MOVT32X2(Ltmp2, Ltmp7, bool2);
//		AE_LA32X2_IP(Ltmp1, align1, Lp1);
//		Ltmp3 = AE_ZERO32();
//		bool2 = AE_LT32(Ltmp4, Ltmp1);
//		AE_MOVT32X2(Ltmp3, Ltmp6, bool2);
//		bool2 = AE_LT32(Ltmp1, Ltmp5);
//		AE_MOVT32X2(Ltmp3, Ltmp7, bool2);
//		tmp1 = AE_SEL16_6420(AE_MOVINT16X4_FROMINT32X2(Ltmp3), AE_MOVINT16X4_FROMINT32X2(Ltmp2));
//		AE_SA16X4_IP(tmp1, align2, p1);
//	}
//	AE_SA64POS_FP(align2, p1);
//
//	return;
//}
//
//void fx_SolomonVoice_bulk_delay_estimation_clip2(short *d, short *s, int V, int len)
//{
//	int k;
//	ae_int16x4 *p1, *p2;
//	ae_int16x4 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6;
//	ae_valign align1, align2;
//	xtbool4 bool4;
//
//	p1 = (ae_int16x4 *)s;
//	p2 = (ae_int16x4 *)d;
//	align1 = AE_LA64_PP(p1);
//	align2 = AE_ZALIGN64();
//	tmp3 = AE_MOVDA16(V);
//	tmp4 = AE_MOVDA16(-V);
//	tmp5 = AE_MOVDA16(1);
//	tmp6 = AE_MOVDA16(-1);
//	for(k=0; k<len; k+=4)
//	{
//		AE_LA16X4_IP(tmp1, align1, p1);
//		tmp2 = AE_ZERO16();
//		bool4 = AE_LT16(tmp3, tmp1);
//		AE_MOVT16X4(tmp2, tmp5, bool4);
//		bool4 = AE_LT16(tmp1, tmp4);
//		AE_MOVT16X4(tmp2, tmp6, bool4);
//		AE_SA16X4_IP(tmp2, align2, p2);
//	}
//	AE_SA64POS_FP(align2, p2);
//
//	return;
//}
//
//short binary_vector_mult(short *bv1, short *bv2, int len)
//{
//	int i;
//	ae_int16x4 *p1, *p2;
//	ae_int16x4 tmp1, tmp2;
//	ae_int32x2 Ltmp1, Ltmp2;
//	ae_valign align1, align2;
//
//	p1 = (ae_int16x4 *)bv1;
//	p2 = (ae_int16x4 *)bv2;
//	align1 = AE_LA64_PP(p1);
//	align2 = AE_LA64_PP(p2);
//	Ltmp1 = AE_ZERO32();
//	Ltmp2 = AE_ZERO32();
//	for(i=0; i<len; i+=4)
//	{
//		AE_LA16X4_IP(tmp1, align1, p1);
//		AE_LA16X4_IP(tmp2, align2, p2);
//		AE_MULA16X4(Ltmp1, Ltmp2, tmp1, tmp2);
//	}
//	Ltmp1 = AE_ADD32(Ltmp1, Ltmp2);
//	Ltmp2 = AE_SEL32_LH(Ltmp2, Ltmp1);
//	Ltmp1 = AE_ADD32(Ltmp1, Ltmp2);
//
//	return (short)AE_MOVAD32_L(Ltmp1);
//}
//
//extern int *gBuff_L_WB;
//
//void fx_SolomonVoice_bulk_delay_estimation(AECStatus* AEC_buf, SamsungSolomonVoiceWTxAECParam* AEC_param, SamsungSolomonVoiceWTxFRAMEParam* FRAME_param, RESStatus* RES_buf, short *TxFrm_AEC, CHANNEL channel)
//{
//	short k, m;
//	short auto_corr, cross_corr, tmp_corr, sign_ear_W;
//	short delay_comp=0;
//	short 	FRM_LEN;
//	short 	Nadf;
//	short 	Nadfshort;
//	short 	NadfMinun1;
//	short 	RxSigOnset_FRAME;
//	short 	DelayCompenRange_Less;
//	short 	DelayCompenRange_More;
//
//	if (channel == CH_OUTER_1)
//	{
//		FRM_LEN = DVTX_FRM_LEN_WB;
//		Nadf = DVTX_Nadf_WB;
//		Nadfshort = DVTX_Nadfshort_WB;
//		NadfMinun1 = DVTX_NadfMinun1_WB;
//		RxSigOnset_FRAME = DVTX_RxSigOnset_FRAME_WB;
//		DelayCompenRange_Less = DVTX_DelayCompenRange_Less_WB;
//		DelayCompenRange_More = AEC_param->PARA_reserved_7;
//	}
//	else if (channel == CH_OUTER_2)
//	{
//		FRM_LEN = DVTX_FRM_LEN_WB;
//		Nadf = DVTX_Nadf_WB;
//		Nadfshort = DVTX_Nadfshort_WB;
//		NadfMinun1 = DVTX_NadfMinun1_WB;
//		RxSigOnset_FRAME = DVTX_RxSigOnset_FRAME_WB;
//		DelayCompenRange_Less = DVTX_DelayCompenRange_Less_WB;
//		DelayCompenRange_More = AEC_param->PARA_reserved_7;
//	}
//	else
//	{
//		FRM_LEN = DVTX_FRM_LEN_NB; //160
//		Nadf = DVTX_Nadf_NB; //80
//		Nadfshort = DVTX_Nadfshort_NB; //32
//		NadfMinun1 = DVTX_NadfMinun1_NB; //79
//		RxSigOnset_FRAME = DVTX_RxSigOnset_FRAME_NB; //12
//		DelayCompenRange_Less = DVTX_DelayCompenRange_Less_NB; //10
//		DelayCompenRange_More = AEC_param->PARA_reserved_7;
//	}
//
//	//ADF filtering
//	for (k = 0; k < FRM_LEN; k++)
//	{
//		gBuff_L_WB[k] = Fx_convolve_optimized(&AEC_buf->RxFrm_AECin_AEC[NadfMinun1 + k], AEC_buf->W, Nadfshort); //Q0*Q17=Q13,18
//	}
//
//	m = RxSigOnset_FRAME - AEC_buf->hangover_cnt_flag_RxVAD_First - 1;
//	fx_SolomonVoice_bulk_delay_estimation_clip1(&AEC_buf->Buff_RxOnset_aecout[m*FRM_LEN], &gBuff_L_WB[0], 100000, FRM_LEN);
//	fx_SolomonVoice_bulk_delay_estimation_clip2(&AEC_buf->Buff_RxOnset_txin[m*FRM_LEN], &TxFrm_AEC[0], 10, FRM_LEN);
//
//	//delay compensation by sign x-correlation
//	if (AEC_buf->hangover_cnt_flag_RxVAD_First == 0)
//	{
//		// auto correlation to detect tone signal
//		auto_corr = DVTX_MIN_16;
//		for (m = 100; m <= 150; m++) // 100~200 to calculate auto correlation
//		{
//			tmp_corr = binary_vector_mult(&AEC_buf->Buff_RxOnset_aecout[200], &AEC_buf->Buff_RxOnset_aecout[200+m], DVTX_RxSigon_BuffLen_MAX - 500);
//			auto_corr = auto_corr<tmp_corr?tmp_corr:auto_corr;
//		}
//
//		// bulk delay calculation by
//		sign_ear_W = 1;
//		delay_comp = 0;
//		cross_corr = DVTX_MIN_16;
//		if (FRAME_param->PARA_call_mode_HS_HF_EAR == 2) // for EAR mode
//		{
//			for (m = -DelayCompenRange_Less; m <= DelayCompenRange_More; m++) // -20~120 delay search range
//			{
//				tmp_corr = binary_vector_mult(&AEC_buf->Buff_RxOnset_aecout[200], &AEC_buf->Buff_RxOnset_txin[200+m], DVTX_RxSigon_BuffLen_MAX - 500);
//				if (cross_corr < tmp_corr)
//				{
//					cross_corr = tmp_corr;
//					delay_comp = m;
//					sign_ear_W = 1;
//				}
//				else if (cross_corr < -tmp_corr)
//				{
//					cross_corr = -tmp_corr;
//					delay_comp = m;
//					sign_ear_W = 1;
//				}
//			}
//		}
//		else
//		{
//			for (m = -DelayCompenRange_Less; m <= DelayCompenRange_More; m++) // -20~120 delay search range
//			{
//				tmp_corr = binary_vector_mult(&AEC_buf->Buff_RxOnset_aecout[200], &AEC_buf->Buff_RxOnset_txin[200+m], DVTX_RxSigon_BuffLen_MAX - 500);
//				if (cross_corr < tmp_corr)
//				{
//					cross_corr = tmp_corr;
//					delay_comp = m;
//				}
//			}
//		}
//
//		if (cross_corr == 0) // no valid search case
//		{
//			delay_comp = 0;
//			sign_ear_W = 1;
//		}
//
//		#ifdef newECNS
//			if (delay_comp + DVTX_ECNS_vars->PARA_Nadfdelay < 0)
//				delay_comp = 0;
//		#endif
//
//		if (auto_corr > 710 || cross_corr < 710) // auto-corr=1420*0.5=710, cross_corr 1420*0.4
//		{
//			AEC_buf->hangover_cnt_flag_RxVAD_First = (RxSigOnset_FRAME);
//		}
//		else
//		{
//			// delay compensation
//			AEC_param->DelayCompensation = AEC_param->PARA_Nadfdelay + delay_comp;
//			// copy W to Waux
//			if (FRAME_param->PARA_call_mode_HS_HF_EAR == 2 && sign_ear_W == -1) // for EAR mode
//			{
//				for (k = 0; k < Nadf; k++) // 200~1420
//				{
//					AEC_buf->W[k] = AEC_buf->W[k] * (-1);
//					AEC_buf->Waux[k] = AEC_buf->Waux[k] * (-1);
//					//AEC_buf->W2nd[k] = AEC_buf->W2nd[k] * (-1);
//				}
//			}
//		}
//	}
//
//	// RxOnset hangover count.. 3-frames
//	if (AEC_buf->hangover_cnt_flag_RxVAD_First > 0)
//		AEC_buf->hangover_cnt_flag_RxVAD_First--;
//	else
//		AEC_param->PARA_FLAG_RxVAD_First_AEC = 0;
//
//	// terminate delay compensation after 2 minute = 0.02*6000 frames
//	AEC_buf->Count_DelayCompensation_function_exe++;
//	if ((AEC_buf->Count_DelayCompensation_function_exe > DVTX_Num_of_BulkDelaySearch_exe) || (RES_buf->CntFrmRxVADon > DVTX_Num_of_ini_RxOn_Frmae)) // within 1sec
//		AEC_param->PARA_FLAG_RxVAD_First_AEC = 0;
//}
//#endif
//short fx_SolomonVoice_AEC_Delay_Compensation(AECStatus* AEC_buf, SamsungSolomonVoiceWTxAECParam* AEC_param, SamsungSolomonVoiceWTxFRAMEParam* FRAME_param, RESStatus* RES_buf, short FrmDT, short *TxFrm_AEC, CHANNEL channel)
//{
//	short Flag_IniRxSigOnset;
//	short Flag_RxVAD_AEC = AEC_buf->Flag_RxVAD_AEC;
//	short Flag_TxSilence_AEC = AEC_buf->Flag_TxSilence_AEC;
//	short Flag_SingleTalk = AEC_buf->Flag_SingleTalk;
//	short Flag_ringbakctone = AEC_buf->Flag_ringbakctone;
//	short hangover_cnt_flag_RxVAD_First = AEC_buf->hangover_cnt_flag_RxVAD_First;
//	short PARA_FLAG_RxVAD_First_AEC = AEC_param->PARA_FLAG_RxVAD_First_AEC;
//	short PARA_call_mode_HS_HF_EAR = FRAME_param->PARA_call_mode_HS_HF_EAR;
//
//	Flag_IniRxSigOnset = (Flag_RxVAD_AEC == 1) && (PARA_FLAG_RxVAD_First_AEC == 1) && (Flag_TxSilence_AEC == 1)
//		&& (Flag_SingleTalk == 1) && (Flag_ringbakctone == 0) && (FrmDT == 0);
//
//	// in BT mode no delay compensation
//	if (PARA_call_mode_HS_HF_EAR == 3)
//	{
//		Flag_IniRxSigOnset = 0;
//		// RxOnset hangover count.. 3-frames
//		if (hangover_cnt_flag_RxVAD_First > 0)
//			hangover_cnt_flag_RxVAD_First--;
//		else
//			PARA_FLAG_RxVAD_First_AEC = 0;
//	}
//
//	AEC_buf->hangover_cnt_flag_RxVAD_First = hangover_cnt_flag_RxVAD_First;
//	AEC_param->PARA_FLAG_RxVAD_First_AEC = PARA_FLAG_RxVAD_First_AEC;
//
//	// for HF, HS, EAR mode
//	if (Flag_IniRxSigOnset)
//	{
//		fx_SolomonVoice_bulk_delay_estimation(AEC_buf, AEC_param, FRAME_param, RES_buf, TxFrm_AEC, channel);
//	}
//
//	return Flag_IniRxSigOnset;
//}

#ifndef fx_SolomonVoice_AEC_ADFfiltering_OPT
void fx_SolomonVoice_AEC_ADFfiltering(DVTX_ECNS_Cfg_t* DVTX_ECNS_vars, AECStatus* AEC_buf1, AECStatus* AEC_buf2,
	SamsungSolomonVoiceWTxAECParam* AEC_param, SamsungSolomonVoiceWTxFRAMEParam* FRAME_param,
	short *TxFrm_AEC1, short *TxFrm_AEC2,
	short AECout_bit_shift_by_qformatW, short OneOverFrmQ22, short frame_pwr_bitshiftoffset, 
	short NadfMinun1, short Nadf, int step_fast, short FrmDT, short FRM_LEN, CHANNEL channel)
{
	/////////////// ADF filtering & update//////////////////////////////////////		
	short n, k, q;
	int  pwr_adfin;
	short sqr_q;
	short tmpX, tmp16;
	short pwr_adfin_dB;
	short pt_crtsmp, pt_conv;
	short TxRxPwrDiff;
#ifndef HOON_OPT_HIFI_12
	short Flag_2smp_sparse, Flag_8smp_sparse;
#else
	short Flag_2smp_sparse = 1;
#endif
	short FlagSampleADFupate;
	short norm_shift, norm_shift1;
	short sh_qex, sh_tmpE, sh_tmpX, sh_qxx, shft, shxx;
	int   LtmpE;
	int  sqrsum_adfin, sqr_new, sqr_end, sqr_diff;
	int  tmp32;
	int  Ltmp, Ltmp2, Ltmp3;
	int  adf_var_avg1 = 0;
	int  adf_var_avg2 = 0;

	pwr_adfin = 0;
	pwr_adfin_dB = 0;
#ifdef FN_DVTX_AEC_NB_UPDATE_OPT_DSP
	ae_f16x4 *pin, *pin2;
	ae_f16x4  XtmpH, XtmpL, Xtmp16, Xtmp, Xcondata2;
	ae_int16x4 *pout;
	ae_f32x2 Xrdata1, Xrdata2, Xtmp32, Xtmp_sum, Xcondata1;
	ae_valign align1, align2, align3;
	Xcondata1 = AE_MOVDA32(1024);
	Xcondata2 = AE_MOVDA16(32767);
#endif

#ifndef HOON_OPT_HIFI_12
	Flag_2smp_sparse = 1;//!(k & 1);
	Flag_8smp_sparse = 1;//!(k & 3);
#endif	
	for (k = 0; k < FRM_LEN; k++)
	{
		// upadate interval decision : per xx-samples
		int var_L_RxAEC_Out_AEC, var_L_RxAEC_Out_AEC1, var_L_RxAEC_Out_AEC2;

		//Flag_2smp_sparse = 1;//!(k & 1);
		//Flag_8smp_sparse = 1;//!(k & 3);

		// read ADF input data & ADF input Rx power calculation sample by sample
#ifndef HOON_OPT_HIFI_12
		if (k == 0)  //read first Nadf samples
		{
			Fx_vector_copy_s(AEC_buf1->ADF_IN, AEC_buf1->RxFrm_AECin_AEC, Nadf);
			sqrsum_adfin = Fx_vector_sum_squares(AEC_buf1->ADF_IN, Nadf, &sqr_q);
			pt_crtsmp = NadfMinun1;
		}
		else
			AEC_buf1->ADF_IN[pt_crtsmp] = AEC_buf1->RxFrm_AECin_AEC[NadfMinun1 + k];

		// ADF input power calculation
		if (k != 0)
		{
			n = DVTXOP_add(NadfMinun1, k);
			sqr_new = DVTXOP_L_mult(AEC_buf1->RxFrm_AECin_AEC[n], AEC_buf1->RxFrm_AECin_AEC[n]);
			n = DVTXOP_sub(k, 1);
			sqr_end = DVTXOP_L_mult(AEC_buf1->RxFrm_AECin_AEC[n], AEC_buf1->RxFrm_AECin_AEC[n]);
			sqr_diff = DVTXOP_L_sub(sqr_new, sqr_end);
			sqrsum_adfin = DVTXOP_L_add(sqrsum_adfin, DVTXOP_L_shr(sqr_diff, sqr_q));
			if (sqrsum_adfin > 0x40000000)
			{
				sqrsum_adfin = DVTXOP_L_shr(sqrsum_adfin, 1);
				sqr_q = DVTXOP_add(sqr_q, 1);
			}
		}
#else
		// read ADF input data & ADF input Rx power calculation sample by sample
		if (k == 0)  //read first Nadf samples
		{
			Fx_vector_copy_s(AEC_buf1->ADF_IN, AEC_buf1->RxFrm_AECin_AEC, Nadf);
			sqrsum_adfin = Fx_vector_sum_squares(AEC_buf1->ADF_IN, Nadf, &sqr_q);
			pt_crtsmp = NadfMinun1;
		}
		else
		{
			AEC_buf1->ADF_IN[pt_crtsmp] = AEC_buf1->RxFrm_AECin_AEC[NadfMinun1 + k];
			// ADF input power calculation
			n = DVTXOP_add(NadfMinun1, k);
			sqr_new = DVTXOP_L_mult(AEC_buf1->RxFrm_AECin_AEC[n], AEC_buf1->RxFrm_AECin_AEC[n]);
			n = DVTXOP_sub(k, 1);
			sqr_end = DVTXOP_L_mult(AEC_buf1->RxFrm_AECin_AEC[n], AEC_buf1->RxFrm_AECin_AEC[n]);

			sqr_diff = DVTXOP_L_sub(sqr_new, sqr_end);
			sqrsum_adfin = DVTXOP_L_add(sqrsum_adfin, DVTXOP_L_shr(sqr_diff, sqr_q));
			if (sqrsum_adfin > 0x40000000)
			{
				sqrsum_adfin = DVTXOP_L_shr(sqrsum_adfin, 1);
				sqr_q = DVTXOP_add(sqr_q, 1);
			}
		}
#endif
		q = DVTXOP_sub(DVTXOP_sub(32, sqr_q), frame_pwr_bitshiftoffset);    // q: 31+1-sqr_q-n, for N=160 k is 23
		pwr_adfin = DVTXOP_L_shl(DVTXOP_L_mpy_ls(sqrsum_adfin, OneOverFrmQ22), 1); //WB 1/320*2^22
		pwr_adfin = DVTXOP_L_add(pwr_adfin, DVTXOP_L_shr(DVTX_ADF_Xpwr_OFFSET, DVTXOP_sub(DVTX_ADF_Xpwr_OFFSET_q, q)));
		pwr_adfin_dB = Fx_10log10(pwr_adfin, q);//Q7,8 // can be omitted by linear scaling comparison 

		// ADF update calculation	
		TxRxPwrDiff = DVTXOP_sub(AEC_buf1->Pwr_TX_AECIN_dB, pwr_adfin_dB);

#ifndef Merge_two_convolve_OPT_DSP
		// ADF convolution by W
#ifndef Fx_convolve_OPT_DSP
		var_L_RxAEC_Out_AEC = Fx_convolve(AEC_buf1->ADF_IN, AEC_buf1->W, pt_crtsmp, Nadf); //Q18(outer) or Q16(inner)
#else
		var_L_RxAEC_Out_AEC = Fx_convolve_optimized(&AEC_buf1->RxFrm_AECin_AEC[NadfMinun1 + k], AEC_buf1->W, Nadf); //Q18(outer) or Q16(inner)
#endif
		var_L_RxAEC_Out_AEC1 = DVTXOP_L_sub(DVTXOP_L_shl(TxFrm_AEC1[k], 15), DVTXOP_L_shr(var_L_RxAEC_Out_AEC, AECout_bit_shift_by_qformatW));//Q31.15
		AEC_buf1->E_tx_AEC[k] = DVTXOP_extract_h(DVTXOP_L_shl(var_L_RxAEC_Out_AEC1, 1));

		if (channel != CH_INNER)
		{
#ifndef Fx_convolve_OPT_DSP
			var_L_RxAEC_Out_AEC = Fx_convolve(AEC_buf1->ADF_IN, AEC_buf2->W, pt_crtsmp, Nadf); //Q18(outer) or Q16(inner)
#else
			var_L_RxAEC_Out_AEC = Fx_convolve_optimized(&AEC_buf1->RxFrm_AECin_AEC[NadfMinun1 + k], AEC_buf2->W, Nadf); //Q18(outer) or Q16(inner)
#endif
			var_L_RxAEC_Out_AEC2 = DVTXOP_L_sub(DVTXOP_L_shl(TxFrm_AEC2[k], 15), DVTXOP_L_shr(var_L_RxAEC_Out_AEC, AECout_bit_shift_by_qformatW));//Q31.15
			AEC_buf2->E_tx_AEC[k] = DVTXOP_extract_h(DVTXOP_L_shl(var_L_RxAEC_Out_AEC2, 1));
		}

		// ADF convolution by Waux
#ifndef Fx_convolve_OPT_DSP
		var_L_RxAEC_Out_AEC = Fx_convolve(AEC_buf1->ADF_IN, AEC_buf1->Waux, pt_crtsmp, Nadf); //Q13,18
#else
		var_L_RxAEC_Out_AEC = Fx_convolve_optimized(&AEC_buf1->RxFrm_AECin_AEC[NadfMinun1 + k], AEC_buf1->Waux, Nadf); //Q13,18
#endif
		var_L_RxAEC_Out_AEC = DVTXOP_L_sub(DVTXOP_L_shl(TxFrm_AEC1[k], 15), DVTXOP_L_shr(var_L_RxAEC_Out_AEC, AECout_bit_shift_by_qformatW));//Q31.15

		AEC_buf1->E_tx_AECaux[k] = DVTXOP_extract_h(DVTXOP_L_shl(var_L_RxAEC_Out_AEC, 1));

		if (channel != CH_INNER)
		{
#ifndef Fx_convolve_OPT_DSP
			var_L_RxAEC_Out_AEC = Fx_convolve(AEC_buf1->ADF_IN, AEC_buf2->Waux, pt_crtsmp, Nadf); //Q13,18
#else
			var_L_RxAEC_Out_AEC = Fx_convolve_optimized(&AEC_buf1->RxFrm_AECin_AEC[NadfMinun1 + k], AEC_buf2->Waux, Nadf); //Q13,18
#endif
			var_L_RxAEC_Out_AEC = DVTXOP_L_sub(DVTXOP_L_shl(TxFrm_AEC2[k], 15), DVTXOP_L_shr(var_L_RxAEC_Out_AEC, AECout_bit_shift_by_qformatW));//Q31.15

			AEC_buf2->E_tx_AECaux[k] = DVTXOP_extract_h(DVTXOP_L_shl(var_L_RxAEC_Out_AEC, 1));
		}
#else
		{
			int out1, out2;

			Fx_convolve_2(&AEC_buf1->RxFrm_AECin_AEC[NadfMinun1 + k], AEC_buf1->W, AEC_buf1->Waux, &out1, &out2,pt_crtsmp, Nadf); //Q13,18
#ifndef HOON_OPT_HIFI_12
			var_L_RxAEC_Out_AEC1 = DVTXOP_L_sub(DVTXOP_L_shl(TxFrm_AEC1[k], 15), DVTXOP_L_shr(out1, AECout_bit_shift_by_qformatW));//Q31.15
			AEC_buf1->E_tx_AEC[k] = DVTXOP_extract_h(DVTXOP_L_shl(var_L_RxAEC_Out_AEC1, 1));

			var_L_RxAEC_Out_AEC = DVTXOP_L_sub(DVTXOP_L_shl(TxFrm_AEC1[k], 15), DVTXOP_L_shr(out2, AECout_bit_shift_by_qformatW));//Q31.15
			AEC_buf1->E_tx_AECaux[k] = DVTXOP_extract_h(DVTXOP_L_shl(var_L_RxAEC_Out_AEC, 1));
#else
			tmp32 = DVTXOP_L_shl(TxFrm_AEC1[k], 15);
			var_L_RxAEC_Out_AEC1 = DVTXOP_L_sub(tmp32, DVTXOP_L_shr(out1, AECout_bit_shift_by_qformatW));//Q31.15
			AEC_buf1->E_tx_AEC[k] = DVTXOP_extract_h(DVTXOP_L_shl(var_L_RxAEC_Out_AEC1, 1));

			var_L_RxAEC_Out_AEC = DVTXOP_L_sub(tmp32, DVTXOP_L_shr(out2, AECout_bit_shift_by_qformatW));//Q31.15
			AEC_buf1->E_tx_AECaux[k] = DVTXOP_extract_h(DVTXOP_L_shl(var_L_RxAEC_Out_AEC, 1));
#endif
			if (channel != CH_INNER)
	    	{
				Fx_convolve_2(&AEC_buf1->RxFrm_AECin_AEC[NadfMinun1 + k], AEC_buf2->W, AEC_buf2->Waux, &out1, &out2,pt_crtsmp, Nadf); //Q13,18
#ifndef HOON_OPT_HIFI_12
				var_L_RxAEC_Out_AEC2 = DVTXOP_L_sub(DVTXOP_L_shl(TxFrm_AEC2[k], 15), DVTXOP_L_shr(out1, AECout_bit_shift_by_qformatW));//Q31.15
				AEC_buf2->E_tx_AEC[k] = DVTXOP_extract_h(DVTXOP_L_shl(var_L_RxAEC_Out_AEC2, 1));
				var_L_RxAEC_Out_AEC = DVTXOP_L_sub(DVTXOP_L_shl(TxFrm_AEC2[k], 15), DVTXOP_L_shr(out2, AECout_bit_shift_by_qformatW));//Q31.15
				AEC_buf2->E_tx_AECaux[k] = DVTXOP_extract_h(DVTXOP_L_shl(var_L_RxAEC_Out_AEC, 1));
#else
				tmp32 = DVTXOP_L_shl(TxFrm_AEC2[k], 15);
				var_L_RxAEC_Out_AEC2 = DVTXOP_L_sub(tmp32, DVTXOP_L_shr(out1, AECout_bit_shift_by_qformatW));//Q31.15
				AEC_buf2->E_tx_AEC[k] = DVTXOP_extract_h(DVTXOP_L_shl(var_L_RxAEC_Out_AEC2, 1));
				var_L_RxAEC_Out_AEC = DVTXOP_L_sub(tmp32, DVTXOP_L_shr(out2, AECout_bit_shift_by_qformatW));//Q31.15
				AEC_buf2->E_tx_AECaux[k] = DVTXOP_extract_h(DVTXOP_L_shl(var_L_RxAEC_Out_AEC, 1));
#endif
			}
		}
#endif

		//// Double Talk detection by X correlation
		//if (!(k & 3))
		//{
		//	// Double Talk detection
		//	tmpX = TxFrm_AEC1[k];   // 16bit Q15,0
		//	LtmpE = var_L_RxAEC_Out_AEC1; //32bit Q16,15

		//	if (AEC_buf1->L_Qex == 0)
		//		sh_qex = 31;
		//	else
		//		sh_qex = DVTXOP_add(DVTXOP_norm_l(AEC_buf1->L_Qex), AEC_buf1->Qex_q);
		//	if (AEC_buf1->L_Qxx == 0)
		//		sh_qxx = 31;
		//	else
		//		sh_qxx = DVTXOP_add(DVTXOP_norm_l(AEC_buf1->L_Qxx), AEC_buf1->Qxx_q);
		//	if (LtmpE == 0)
		//		sh_tmpE = 31;
		//	else
		//		sh_tmpE = DVTXOP_add(DVTXOP_norm_l(LtmpE), 15);
		//	if (tmpX == 0)
		//		sh_tmpX = 31;
		//	else
		//		sh_tmpX = DVTXOP_add(DVTXOP_norm_s(tmpX), 16);

		//	shft = DVTX_MIN(sh_qex, sh_qxx);
		//	shft = DVTX_MIN(shft, sh_tmpX);
		//	tmp16 = DVTXOP_sub(sh_tmpE, 15);
		//	shft = DVTX_MIN(shft, tmp16);
		//	tmp16 = DVTXOP_sub(DVTXOP_add(sh_tmpX, sh_tmpX), 15);
		//	shft = DVTX_MIN(shft, tmp16);

		//	AEC_buf1->L_Qex = Fx_recursive_avg(DVTXOP_L_shl(AEC_buf1->L_Qex, DVTXOP_sub(shft, AEC_buf1->Qex_q)), DVTXOP_L_mpy_ls(DVTXOP_L_shl(LtmpE, shft), tmpX), DVTX_WORD16_0_99);
		//	AEC_buf1->L_Qxx = Fx_recursive_avg(DVTXOP_L_shl(AEC_buf1->L_Qxx, DVTXOP_sub(shft, AEC_buf1->Qxx_q)), DVTXOP_L_shl(DVTXOP_L_mult(tmpX, tmpX), DVTXOP_sub(shft, 1)), DVTX_WORD16_0_99);
		//	AEC_buf1->Qex_q = shft;
		//	AEC_buf1->Qxx_q = shft;

		//	AEC_buf1->L_Qex = DVTX_MAX(AEC_buf1->L_Qex, 1);
		//	AEC_buf1->L_Qxx = DVTX_MAX(AEC_buf1->L_Qxx, 1);
		//	{
		//		shxx = DVTXOP_norm_l(AEC_buf1->L_Qxx);
		//		tmp32 = DVTXOP_L_divide(DVTXOP_L_shr_r(AEC_buf1->L_Qex, 1), DVTXOP_L_shl(AEC_buf1->L_Qxx, shxx));   //4
		//		tmp16 = DVTX_MAX(DVTXOP_sub(DVTX_FIXED_ONE(13), DVTXOP_extract_l(DVTXOP_L_shr_r(tmp32, DVTXOP_sub(17, shxx)))), 0); //Q2.13
		//	}
		//	tmp16 = DVTX_MIN(tmp16, 8192); // 1*2^13		

		//	if (AEC_buf1->Flag_RxVAD_AEC == 0)
		//		AEC_buf1->XECC = 0;
		//	else
		//	{
		//		if (AEC_buf1->XECC > tmp16) // decreasing
		//			AEC_buf1->XECC = DVTXOP_add(DVTXOP_mult(AEC_buf1->XECC, DVTX_WORD16_0_99), DVTXOP_mult(tmp16, DVTX_WORD16_0_01));//Q2.13
		//		else
		//			AEC_buf1->XECC = DVTXOP_add(DVTXOP_mult(AEC_buf1->XECC, DVTX_WORD16_0_8), DVTXOP_mult(tmp16, DVTX_WORD16_0_2));//Q2.13
		//	}
		//}

		if (AEC_param->PARA_FLAG_RxVAD_First_AEC == 0)
		{
			adf_var_avg1 = 0;
			adf_var_avg2 = 0;
			FlagSampleADFupate = (Flag_2smp_sparse) && (pwr_adfin_dB > AEC_param->PARA_Pwr_LoTHD_ADF_IN) && (TxRxPwrDiff < AEC_param->PARA_THD_RxTx_Pwr_Difference) && (AEC_buf1->Pwr_TX_AECIN_dB > AEC_param->PARA_reserved_29)
				&& (AEC_buf1->Flag_ringbakctone == 0) && (FrmDT == 0);
			if (FlagSampleADFupate == 1)
			{
				if (AEC_buf1->Cnt_Samples_NLMSupdate < DVTX_MAX_32)
					AEC_buf1->Cnt_Samples_NLMSupdate++; // 

				if(channel != CH_INNER)
					if (AEC_buf2->Cnt_Samples_NLMSupdate < DVTX_MAX_32)
						AEC_buf2->Cnt_Samples_NLMSupdate++; // 

				//num
				norm_shift1 = DVTXOP_norm_l(step_fast); //Q0.31?
				Ltmp3 = DVTXOP_L_shl(step_fast, (short)(norm_shift1 - 1));
				//denom
				Ltmp = DVTX_MAX(pwr_adfin, 1);
				norm_shift = DVTXOP_norm_l(Ltmp);
				Ltmp = DVTXOP_L_shl(Ltmp, norm_shift);
				if (Ltmp3 <= 0)
					Ltmp2 = 0;
				else
					Ltmp2 = DVTXOP_L_divide(Ltmp3, Ltmp);   //5

				Ltmp2 = DVTXOP_L_shr(Ltmp2, (short)(0 - 1 + norm_shift1 - norm_shift - q)); //Q0,31

				Ltmp = DVTXOP_L_mpy_ls(Ltmp2, AEC_buf1->E_tx_AEC[k]); //Q0,31*15.0 = 15,31-15 = q15,16
#ifndef FN_DVTX_AEC_NB_UPDATE_OPT_DSP
				pt_conv = pt_crtsmp;

				for (n = 0; n < DVTX_ADF_early_index; n++) // change from 32 to 64
				{
					tmp32 = DVTXOP_L_mpy_ls(Ltmp, AEC_buf1->ADF_IN[pt_conv]); //q15,16*q15,0=q30,16-15 = q30,1?					
					//tmp32 = DVTXOP_L_shr_r(tmp32, 11); //Q17?
					tmp32 = (tmp32 + 1024) >> 11;

					if (tmp32 > 0)
						adf_var_avg1 = DVTXOP_L_add(adf_var_avg1, tmp32);
					else
						adf_var_avg1 = DVTXOP_L_sub(adf_var_avg1, tmp32);

					AEC_buf1->adf_var[n] = DVTXOP_extract_l(tmp32);
					pt_conv--;
					if (pt_conv < 0)
						pt_conv = NadfMinun1;
				}
#else
				pin = (ae_f16x4 *)(&AEC_buf1->RxFrm_AECin_AEC[DVTX_NadfMinun1_NB + k]);
				align1 = AE_LA64_PP(pin);
				Xtmp32 = AE_MOVDA32(Ltmp);
				XtmpH = AE_TRUNC16X4F32(Xtmp32, Xtmp32);
				XtmpL = AE_SRAA16S(AE_CVT16X4(Xtmp32, Xtmp32), 1);
				XtmpL = AE_AND16(XtmpL, Xcondata2);
				Xtmp_sum = AE_MOVDA32(adf_var_avg1);
				pout = (ae_int16x4 *)&AEC_buf1->adf_var[0];//DVTX_ECNS_vars->ECNSbuff.adf_var;
				align2 = AE_ZALIGN64();
				for (n = 0; n < DVTX_ADF_early_index; n+=4) // change from 32 to 64
				{
					AE_LA16X4_RIP(Xtmp16,align1,pin);
					AE_MULF16X4SS(Xrdata1, Xrdata2, XtmpL, Xtmp16);
					Xrdata1 = AE_SRAA32S(Xrdata1, 15);
					Xrdata2 = AE_SRAA32S(Xrdata2, 15);
					AE_MULAF16X4SS(Xrdata1, Xrdata2, XtmpH, Xtmp16);
					Xrdata1 = AE_SRAA32S(AE_ADD32S(Xrdata1, Xcondata1), 11);
					Xrdata2 = AE_SRAA32S(AE_ADD32S(Xrdata2, Xcondata1), 11);
					Xtmp_sum = AE_ADD32S(Xtmp_sum, AE_ABS32S(Xrdata1));
					Xtmp_sum = AE_ADD32S(Xtmp_sum, AE_ABS32S(Xrdata2));
					Xtmp16 = AE_CVT16X4(Xrdata1, Xrdata2);
					AE_SA16X4_IP(Xtmp16,align2,pout);
				}
				AE_SA64POS_FP(align2, pout);
				//for (n = 0; n < DVTX_ADF_early_index_NB; n++)
				//	DVTX_ECNS_vars->ECNSbuff.adf_var[n] = tmpbuf[n];
				Xtmp32 = AE_SEL32_LH(Xtmp_sum, Xtmp_sum);
				Xtmp_sum = AE_ADD32S(Xtmp32, Xtmp_sum);
				adf_var_avg1 = (int)AE_MOVAD32_L(Xtmp_sum);

#endif
				if (adf_var_avg1 < AEC_param->PARA_ADF_Wvar_THD)
				{
#ifndef FN_DVTX_AEC_NB_UPDATE_OPT_DSP
					for (n = 0; n < DVTX_ADF_early_index; n++)
						AEC_buf1->W[n] = DVTXOP_add(AEC_buf1->W[n], AEC_buf1->adf_var[n]); // q17

					if ((FRAME_param->PARA_call_mode_HS_HF_EAR == 0) || (FRAME_param->PARA_call_mode_HS_HF_EAR == 1)) // only for HF and HS mode
					{
						for (n = DVTX_ADF_early_index; n < Nadf; n++)
						{
							tmp32 = DVTXOP_L_mpy_ls(Ltmp, AEC_buf1->ADF_IN[pt_conv]); //q15,16*q15,0=q30,16-15 = q30,1?					
							//tmp32 = DVTXOP_L_shr_r(tmp32, 11); //Q17?
							tmp32 = (tmp32 + 1024) >> 11;
							AEC_buf1->adf_var[n] = DVTXOP_extract_l(tmp32);
							AEC_buf1->W[n] = DVTXOP_add(AEC_buf1->W[n], AEC_buf1->adf_var[n]); // q17
							pt_conv--;
							if (pt_conv < 0)
								pt_conv = NadfMinun1;
						}
					}
#else
					pin2 = (ae_f16x4 *)(&AEC_buf1->W[0]);
					pin = (ae_f16x4 *)(&AEC_buf1->W[0]);
					pout = (ae_int16x4 *)&AEC_buf1->adf_var[0];
					align1 = AE_LA64_PP(pout);
					align3 = AE_LA64_PP(pin2);
					align2 = AE_ZALIGN64();
					for (n = 0; n < DVTX_ADF_early_index; n+=4)
					{
						//DVTX_ECNS_vars->ECNSbuff.W[n] = DVTXOP_add(DVTX_ECNS_vars->ECNSbuff.W[n], DVTX_ECNS_vars->ECNSbuff.adf_var[n]); // q17
						AE_LA16X4_IP(Xtmp,align3,pin2);
						AE_LA16X4_IP(Xtmp16,align1,pout);
						Xtmp = AE_ADD16S(Xtmp, Xtmp16);
						AE_SA16X4_IP(Xtmp,align2,pin);
					}
					AE_SA64POS_FP(align2, pin);
					if ((FRAME_param->PARA_call_mode_HS_HF_EAR == 0) || (FRAME_param->PARA_call_mode_HS_HF_EAR == 1)) // only for HF mode
					{
						pin = (ae_f16x4 *)(&AEC_buf1->RxFrm_AECin_AEC[16 + k]);
						//pin2 = (ae_f16x4 *)(&DVTX_ECNS_vars->ECNSbuff.W[64]);
						align1 = AE_LA64_PP(pin);
						Xtmp32 = AE_MOVDA32(Ltmp);
						XtmpH = AE_TRUNC16X4F32(Xtmp32, Xtmp32);
						XtmpL = AE_SRAA16S(AE_CVT16X4(Xtmp32, Xtmp32), 1);
						XtmpL = AE_AND16(XtmpL, Xcondata2);

						//pout = (ae_f16x4 *)&DVTX_ECNS_vars->ECNSbuff.adf_var[64];
						align2 = AE_ZALIGN64();

						AE_LA16X4_RIP(Xtmp16,align1,pin);
						AE_L16X4_IP(Xtmp,pin2,0);
						AE_MULF16X4SS(Xrdata1, Xrdata2, XtmpL, Xtmp16);
						Xrdata1 = AE_SRAA32S(Xrdata1, 15);
						Xrdata2 = AE_SRAA32S(Xrdata2, 15);
						AE_MULAF16X4SS(Xrdata1, Xrdata2, XtmpH, Xtmp16);
						Xrdata1 = AE_SRAA32S(AE_ADD32S(Xrdata1, Xcondata1), 11);
						Xrdata2 = AE_SRAA32S(AE_ADD32S(Xrdata2, Xcondata1), 11);
						Xtmp16 = AE_CVT16X4(Xrdata1, Xrdata2);
						AE_SA16X4_IP(Xtmp16,align2,pout);
						Xtmp = AE_ADD16S(Xtmp, Xtmp16);
						AE_S16X4_IP(Xtmp,pin2,8);

						AE_LA16X4_RIP(Xtmp16,align1,pin);
						AE_L16X4_IP(Xtmp,pin2,0);
						AE_MULF16X4SS(Xrdata1, Xrdata2, XtmpL, Xtmp16);
						Xrdata1 = AE_SRAA32S(Xrdata1, 15);
						Xrdata2 = AE_SRAA32S(Xrdata2, 15);
						AE_MULAF16X4SS(Xrdata1, Xrdata2, XtmpH, Xtmp16);
						Xrdata1 = AE_SRAA32S(AE_ADD32S(Xrdata1, Xcondata1), 11);
						Xrdata2 = AE_SRAA32S(AE_ADD32S(Xrdata2, Xcondata1), 11);
						Xtmp16 = AE_CVT16X4(Xrdata1, Xrdata2);
						AE_SA16X4_IP(Xtmp16,align2,pout);
						Xtmp = AE_ADD16S(Xtmp, Xtmp16);
						AE_S16X4_IP(Xtmp,pin2,8);

						AE_SA64POS_FP(align2, pout);

					}
#endif

				}

				if (channel != CH_INNER)
				{
					Ltmp = DVTXOP_L_mpy_ls(Ltmp2, AEC_buf2->E_tx_AEC[k]); //Q0,31*15.0 = 15,31-15 = q15,16
#ifndef FN_DVTX_AEC_NB_UPDATE_OPT_DSP
					pt_conv = pt_crtsmp;

					for (n = 0; n < DVTX_ADF_early_index; n++) // change from 32 to 64
					{
						tmp32 = DVTXOP_L_mpy_ls(Ltmp, AEC_buf1->ADF_IN[pt_conv]); //q15,16*q15,0=q30,16-15 = q30,1?					
						//tmp32 = DVTXOP_L_shr_r(tmp32, 11); //Q17?
						tmp32 = (tmp32 + 1024) >> 11;

						if (tmp32 > 0)
							adf_var_avg2 = DVTXOP_L_add(adf_var_avg2, tmp32);
						else
							adf_var_avg2 = DVTXOP_L_sub(adf_var_avg2, tmp32);

						AEC_buf2->adf_var[n] = DVTXOP_extract_l(tmp32);
						pt_conv--;
						if (pt_conv < 0)
							pt_conv = NadfMinun1;
					}
#else
					pin = (ae_f16x4 *)(&AEC_buf1->RxFrm_AECin_AEC[DVTX_NadfMinun1_NB + k]);
					align1 = AE_LA64_PP(pin);
					Xtmp32 = AE_MOVDA32(Ltmp);
					XtmpH = AE_TRUNC16X4F32(Xtmp32, Xtmp32);
					XtmpL = AE_SRAA16S(AE_CVT16X4(Xtmp32, Xtmp32), 1);
					XtmpL = AE_AND16(XtmpL, Xcondata2);
					Xtmp_sum = AE_MOVDA32(adf_var_avg2);
					pout = (ae_int16x4 *)&AEC_buf2->adf_var[0];//DVTX_ECNS_vars->ECNSbuff.adf_var;
					align2 = AE_ZALIGN64();
					for (n = 0; n < DVTX_ADF_early_index; n += 4) // change from 32 to 64
					{
						AE_LA16X4_RIP(Xtmp16, align1, pin);
						AE_MULF16X4SS(Xrdata1, Xrdata2, XtmpL, Xtmp16);
						Xrdata1 = AE_SRAA32S(Xrdata1, 15);
						Xrdata2 = AE_SRAA32S(Xrdata2, 15);
						AE_MULAF16X4SS(Xrdata1, Xrdata2, XtmpH, Xtmp16);
						Xrdata1 = AE_SRAA32S(AE_ADD32S(Xrdata1, Xcondata1), 11);
						Xrdata2 = AE_SRAA32S(AE_ADD32S(Xrdata2, Xcondata1), 11);
						Xtmp_sum = AE_ADD32S(Xtmp_sum, AE_ABS32S(Xrdata1));
						Xtmp_sum = AE_ADD32S(Xtmp_sum, AE_ABS32S(Xrdata2));
						Xtmp16 = AE_CVT16X4(Xrdata1, Xrdata2);
						AE_SA16X4_IP(Xtmp16, align2, pout);
					}
					AE_SA64POS_FP(align2, pout);
					//for (n = 0; n < DVTX_ADF_early_index_NB; n++)
					//	DVTX_ECNS_vars->ECNSbuff.adf_var[n] = tmpbuf[n];
					Xtmp32 = AE_SEL32_LH(Xtmp_sum, Xtmp_sum);
					Xtmp_sum = AE_ADD32S(Xtmp32, Xtmp_sum);
					adf_var_avg2 = (int)AE_MOVAD32_L(Xtmp_sum);

#endif
					if (adf_var_avg2 < AEC_param->PARA_ADF_Wvar_THD)
					{
#ifndef FN_DVTX_AEC_NB_UPDATE_OPT_DSP
						for (n = 0; n < DVTX_ADF_early_index; n++)
							AEC_buf2->W[n] = DVTXOP_add(AEC_buf2->W[n], AEC_buf2->adf_var[n]); // q17

						if ((FRAME_param->PARA_call_mode_HS_HF_EAR == 0) || (FRAME_param->PARA_call_mode_HS_HF_EAR == 1)) // only for HF and HS mode
						{
							for (n = DVTX_ADF_early_index; n < Nadf; n++)
							{
								tmp32 = DVTXOP_L_mpy_ls(Ltmp, AEC_buf1->ADF_IN[pt_conv]); //q15,16*q15,0=q30,16-15 = q30,1?					
								//tmp32 = DVTXOP_L_shr_r(tmp32, 11); //Q17?
								tmp32 = (tmp32 + 1024) >> 11;
								AEC_buf2->adf_var[n] = DVTXOP_extract_l(tmp32);
								AEC_buf2->W[n] = DVTXOP_add(AEC_buf2->W[n], AEC_buf2->adf_var[n]); // q17
								pt_conv--;
								if (pt_conv < 0)
									pt_conv = NadfMinun1;
							}
						}
#else
						pin2 = (ae_f16x4 *)(&AEC_buf2->W[0]);
						pin = (ae_f16x4 *)(&AEC_buf2->W[0]);
						pout = (ae_int16x4 *)&AEC_buf2->adf_var[0];
						align1 = AE_LA64_PP(pout);
						align3 = AE_LA64_PP(pin2);
						align2 = AE_ZALIGN64();
						for (n = 0; n < DVTX_ADF_early_index; n += 4)
						{
							//DVTX_ECNS_vars->ECNSbuff.W[n] = DVTXOP_add(DVTX_ECNS_vars->ECNSbuff.W[n], DVTX_ECNS_vars->ECNSbuff.adf_var[n]); // q17
							AE_LA16X4_IP(Xtmp, align3, pin2);
							AE_LA16X4_IP(Xtmp16, align1, pout);
							Xtmp = AE_ADD16S(Xtmp, Xtmp16);
							AE_SA16X4_IP(Xtmp, align2, pin);
						}
						AE_SA64POS_FP(align2, pin);
						if ((FRAME_param->PARA_call_mode_HS_HF_EAR == 0) || (FRAME_param->PARA_call_mode_HS_HF_EAR == 1)) // only for HF mode
						{
							pin = (ae_f16x4 *)(&AEC_buf1->RxFrm_AECin_AEC[16 + k]);
							//pin2 = (ae_f16x4 *)(&DVTX_ECNS_vars->ECNSbuff.W[64]);
							align1 = AE_LA64_PP(pin);
							Xtmp32 = AE_MOVDA32(Ltmp);
							XtmpH = AE_TRUNC16X4F32(Xtmp32, Xtmp32);
							XtmpL = AE_SRAA16S(AE_CVT16X4(Xtmp32, Xtmp32), 1);
							XtmpL = AE_AND16(XtmpL, Xcondata2);

							//pout = (ae_f16x4 *)&DVTX_ECNS_vars->ECNSbuff.adf_var[64];
							align2 = AE_ZALIGN64();

							AE_LA16X4_RIP(Xtmp16, align1, pin);
							AE_L16X4_IP(Xtmp, pin2, 0);
							AE_MULF16X4SS(Xrdata1, Xrdata2, XtmpL, Xtmp16);
							Xrdata1 = AE_SRAA32S(Xrdata1, 15);
							Xrdata2 = AE_SRAA32S(Xrdata2, 15);
							AE_MULAF16X4SS(Xrdata1, Xrdata2, XtmpH, Xtmp16);
							Xrdata1 = AE_SRAA32S(AE_ADD32S(Xrdata1, Xcondata1), 11);
							Xrdata2 = AE_SRAA32S(AE_ADD32S(Xrdata2, Xcondata1), 11);
							Xtmp16 = AE_CVT16X4(Xrdata1, Xrdata2);
							AE_SA16X4_IP(Xtmp16, align2, pout);
							Xtmp = AE_ADD16S(Xtmp, Xtmp16);
							AE_S16X4_IP(Xtmp, pin2, 8);

							AE_LA16X4_RIP(Xtmp16, align1, pin);
							AE_L16X4_IP(Xtmp, pin2, 0);
							AE_MULF16X4SS(Xrdata1, Xrdata2, XtmpL, Xtmp16);
							Xrdata1 = AE_SRAA32S(Xrdata1, 15);
							Xrdata2 = AE_SRAA32S(Xrdata2, 15);
							AE_MULAF16X4SS(Xrdata1, Xrdata2, XtmpH, Xtmp16);
							Xrdata1 = AE_SRAA32S(AE_ADD32S(Xrdata1, Xcondata1), 11);
							Xrdata2 = AE_SRAA32S(AE_ADD32S(Xrdata2, Xcondata1), 11);
							Xtmp16 = AE_CVT16X4(Xrdata1, Xrdata2);
							AE_SA16X4_IP(Xtmp16, align2, pout);
							Xtmp = AE_ADD16S(Xtmp, Xtmp16);
							AE_S16X4_IP(Xtmp, pin2, 8);

							AE_SA64POS_FP(align2, pout);

						}
#endif
					}
				}
			}
		} // end of AEC update

		// current sample pointer update
		pt_crtsmp++;
		if (pt_crtsmp >= Nadf)
			pt_crtsmp = 0;
#if (FLAG_SELECT_C_DSP == 1)
#if(Debug_File_Write_C == 1)
		if (channel == FLAG_ECNS_WRITE_SELECTION)
		{
			fprintf(fp_debug_ADF_C, "%d %d %d %d %d %d %d %ld %d %ld %ld\n",
				AEC_buf1->XECC,
				AEC_buf1->Threshold_XECC,
				AEC_param->PARA_reserved_22,
				pwr_adfin_dB,
				AEC_param->PARA_Pwr_LoTHD_ADF_IN,
				TxRxPwrDiff,
				AEC_param->PARA_THD_RxTx_Pwr_Difference,
				adf_var_avg1,
				AEC_param->PARA_ADF_Wvar_THD,
				AEC_param->PARA_ADF_reference_step,
				step_fast
			);
		}
#endif
#endif
	}

	return;
}
#else
#define	Qq 8
void fx_SolomonVoice_AEC_ADFfiltering(DVTX_ECNS_Cfg_t* DVTX_ECNS_vars, AECStatus* AEC_buf1, AECStatus* AEC_buf2,
	SamsungSolomonVoiceWTxAECParam* AEC_param, SamsungSolomonVoiceWTxFRAMEParam* FRAME_param,
	short *TxFrm_AEC1, short *TxFrm_AEC2,
	short AECout_bit_shift_by_qformatW, short OneOverFrmQ22, short frame_pwr_bitshiftoffset,
	short NadfMinun1, short Nadf, int step_fast, short FrmDT, short FRM_LEN, CHANNEL channel)
{
	/////////////// ADF filtering & update//////////////////////////////////////
	short n, k, q;
	int  pwr_adfin;
	short sqr_q;
	short tmpX, tmp16;
	short pwr_adfin_dB;
	short pt_crtsmp, pt_conv;
	short TxRxPwrDiff;
#ifndef HOON_OPT_HIFI_12
	short Flag_2smp_sparse, Flag_8smp_sparse;
#else
	short Flag_2smp_sparse = 1;
#endif
	short FlagSampleADFupate;
	short norm_shift, norm_shift1;
	short sh_qex, sh_tmpE, sh_tmpX, sh_qxx, shft, shxx;
	int   LtmpE;
	int  sqrsum_adfin, sqr_new, sqr_end, sqr_diff;
	int  tmp32;
	int  Ltmp, Ltmp2, Ltmp3;
	int  adf_var_avg1 = 0;
	int  adf_var_avg2 = 0;

	short tmp_zh, tmp_zh1, tmp_zh2;
	int exp_zh, exp_zh1, exp_zh2, q_save, tmpint;

	pwr_adfin = 0;
	pwr_adfin_dB = 0;
#ifdef FN_DVTX_AEC_NB_UPDATE_OPT_DSP
	ae_f16x4 *pin, *pin2;
	ae_f16x4  XtmpH, XtmpL, Xtmp16, Xtmp, Xcondata2;
	ae_int16x4 *pout;
	ae_f32x2 Xrdata1, Xrdata2, Xtmp32, Xtmp_sum, Xcondata1;
	ae_valign align1, align2, align3;
	Xcondata1 = AE_MOVDA32(1024);
	Xcondata2 = AE_MOVDA16(32767);
#endif


	    tmp_zh = AEC_buf1->Pwr_TX_AECIN_dB;
		tmpint = DVTXOP_mult( AEC_buf1->Pwr_TX_AECIN_dB,3277);
		tmpint = (int)(tmpint*(1<<18));
		exp_zh = DVTXOP_fnExp10(-tmpint);
		exp_zh = fx_SolomonVoice_32bit_Divide(((1<<31) - 1),exp_zh,0, 31-Qq);


		tmp_zh = AEC_param->PARA_Pwr_LoTHD_ADF_IN;
		tmpint = DVTXOP_mult( tmp_zh,3277);
		tmpint = (int)(tmpint*(1<<18));
		exp_zh1 = DVTXOP_fnExp10(-tmpint);
		exp_zh1 = fx_SolomonVoice_32bit_Divide(((1<<31) - 1),exp_zh1,0, 31-Qq);


		tmp_zh = AEC_param->PARA_THD_RxTx_Pwr_Difference;
		if(tmp_zh == -2560)
		{
			exp_zh2 = 25;
		}else
		{
			tmpint = DVTXOP_mult( tmp_zh,3277);
			tmpint = (int)(tmpint*(1<<18));
			exp_zh2 = DVTXOP_fnExp10(-tmpint);
			exp_zh2 = fx_SolomonVoice_32bit_Divide(((1<<31) - 1),exp_zh2,0, 31-Qq);
		}


	for (k = 0; k < FRM_LEN; k++)
	{
		// upadate interval decision : per xx-samples
		int var_L_RxAEC_Out_AEC, var_L_RxAEC_Out_AEC1, var_L_RxAEC_Out_AEC2;
#ifndef HOON_OPT_HIFI_12
		Flag_2smp_sparse = 1;//!(k & 1);
		Flag_8smp_sparse = 1;//!(k & 3);
#endif
		// read ADF input data & ADF input Rx power calculation sample by sample
		if (k == 0)  //read first Nadf samples
		{
			Fx_vector_copy_s(AEC_buf1->ADF_IN, AEC_buf1->RxFrm_AECin_AEC, Nadf);
			sqrsum_adfin = Fx_vector_sum_squares(AEC_buf1->ADF_IN, Nadf, &sqr_q);
			pt_crtsmp = NadfMinun1;
		}
		else
			AEC_buf1->ADF_IN[pt_crtsmp] = AEC_buf1->RxFrm_AECin_AEC[NadfMinun1 + k];

		// ADF input power calculation
		if (k != 0)
		{
			n = DVTXOP_add(NadfMinun1, k);
			sqr_new = DVTXOP_L_mult(AEC_buf1->RxFrm_AECin_AEC[n], AEC_buf1->RxFrm_AECin_AEC[n]);
			n = DVTXOP_sub(k, 1);
			sqr_end = DVTXOP_L_mult(AEC_buf1->RxFrm_AECin_AEC[n], AEC_buf1->RxFrm_AECin_AEC[n]);
			sqr_diff = DVTXOP_L_sub(sqr_new, sqr_end);
			sqrsum_adfin = DVTXOP_L_add(sqrsum_adfin, DVTXOP_L_shr(sqr_diff, sqr_q));
			if (sqrsum_adfin > 0x40000000)
			{
				sqrsum_adfin = DVTXOP_L_shr(sqrsum_adfin, 1);
				sqr_q = DVTXOP_add(sqr_q, 1);
			}
		}
		q = DVTXOP_sub(DVTXOP_sub(32, sqr_q), frame_pwr_bitshiftoffset);    // q: 31+1-sqr_q-n, for N=160 k is 23
		pwr_adfin = DVTXOP_L_shl(DVTXOP_L_mpy_ls(sqrsum_adfin, OneOverFrmQ22), 1); //WB 1/320*2^22
		pwr_adfin = DVTXOP_L_add(pwr_adfin, DVTXOP_L_shr(DVTX_ADF_Xpwr_OFFSET, DVTXOP_sub(DVTX_ADF_Xpwr_OFFSET_q, q)));
	//	pwr_adfin_dB = Fx_10log10(pwr_adfin, q);//Q7,8 // can be omitted by linear scaling comparison

		// ADF update calculation
	//	TxRxPwrDiff = DVTXOP_sub(AEC_buf1->Pwr_TX_AECIN_dB, pwr_adfin_dB);
		q_save = q;

#ifndef Merge_two_convolve_OPT_DSP
		// ADF convolution by W
#ifndef Fx_convolve_OPT_DSP
		var_L_RxAEC_Out_AEC = Fx_convolve(AEC_buf1->ADF_IN, AEC_buf1->W, pt_crtsmp, Nadf); //Q18(outer) or Q16(inner)
#else
		var_L_RxAEC_Out_AEC = Fx_convolve_optimized(&AEC_buf1->RxFrm_AECin_AEC[NadfMinun1 + k], AEC_buf1->W, Nadf); //Q18(outer) or Q16(inner)
#endif
		var_L_RxAEC_Out_AEC1 = DVTXOP_L_sub(DVTXOP_L_shl(TxFrm_AEC1[k], 15), DVTXOP_L_shr(var_L_RxAEC_Out_AEC, AECout_bit_shift_by_qformatW));//Q31.15
		AEC_buf1->E_tx_AEC[k] = DVTXOP_extract_h(DVTXOP_L_shl(var_L_RxAEC_Out_AEC1, 1));

		if (channel != CH_INNER)
		{
#ifndef Fx_convolve_OPT_DSP
			var_L_RxAEC_Out_AEC = Fx_convolve(AEC_buf1->ADF_IN, AEC_buf2->W, pt_crtsmp, Nadf); //Q18(outer) or Q16(inner)
#else
			var_L_RxAEC_Out_AEC = Fx_convolve_optimized(&AEC_buf1->RxFrm_AECin_AEC[NadfMinun1 + k], AEC_buf2->W, Nadf); //Q18(outer) or Q16(inner)
#endif
			var_L_RxAEC_Out_AEC2 = DVTXOP_L_sub(DVTXOP_L_shl(TxFrm_AEC2[k], 15), DVTXOP_L_shr(var_L_RxAEC_Out_AEC, AECout_bit_shift_by_qformatW));//Q31.15
			AEC_buf2->E_tx_AEC[k] = DVTXOP_extract_h(DVTXOP_L_shl(var_L_RxAEC_Out_AEC2, 1));
		}

		// ADF convolution by Waux
#ifndef Fx_convolve_OPT_DSP
		var_L_RxAEC_Out_AEC = Fx_convolve(AEC_buf1->ADF_IN, AEC_buf1->Waux, pt_crtsmp, Nadf); //Q13,18
#else
		var_L_RxAEC_Out_AEC = Fx_convolve_optimized(&AEC_buf1->RxFrm_AECin_AEC[NadfMinun1 + k], AEC_buf1->Waux, Nadf); //Q13,18
#endif
		var_L_RxAEC_Out_AEC = DVTXOP_L_sub(DVTXOP_L_shl(TxFrm_AEC1[k], 15), DVTXOP_L_shr(var_L_RxAEC_Out_AEC, AECout_bit_shift_by_qformatW));//Q31.15

		AEC_buf1->E_tx_AECaux[k] = DVTXOP_extract_h(DVTXOP_L_shl(var_L_RxAEC_Out_AEC, 1));

		if (channel != CH_INNER)
		{
#ifndef Fx_convolve_OPT_DSP
			var_L_RxAEC_Out_AEC = Fx_convolve(AEC_buf1->ADF_IN, AEC_buf2->Waux, pt_crtsmp, Nadf); //Q13,18
#else
			var_L_RxAEC_Out_AEC = Fx_convolve_optimized(&AEC_buf1->RxFrm_AECin_AEC[NadfMinun1 + k], AEC_buf2->Waux, Nadf); //Q13,18
#endif
			var_L_RxAEC_Out_AEC = DVTXOP_L_sub(DVTXOP_L_shl(TxFrm_AEC2[k], 15), DVTXOP_L_shr(var_L_RxAEC_Out_AEC, AECout_bit_shift_by_qformatW));//Q31.15

			AEC_buf2->E_tx_AECaux[k] = DVTXOP_extract_h(DVTXOP_L_shl(var_L_RxAEC_Out_AEC, 1));
		}
#else
		{
			int out1, out2;

			Fx_convolve_2(&AEC_buf1->RxFrm_AECin_AEC[NadfMinun1 + k], AEC_buf1->W, AEC_buf1->Waux, &out1, &out2,pt_crtsmp, Nadf); //Q13,18

			var_L_RxAEC_Out_AEC1 = DVTXOP_L_sub(DVTXOP_L_shl(TxFrm_AEC1[k], 15), DVTXOP_L_shr(out1, AECout_bit_shift_by_qformatW));//Q31.15
			AEC_buf1->E_tx_AEC[k] = DVTXOP_extract_h(DVTXOP_L_shl(var_L_RxAEC_Out_AEC1, 1));

			var_L_RxAEC_Out_AEC = DVTXOP_L_sub(DVTXOP_L_shl(TxFrm_AEC1[k], 15), DVTXOP_L_shr(out2, AECout_bit_shift_by_qformatW));//Q31.15
			AEC_buf1->E_tx_AECaux[k] = DVTXOP_extract_h(DVTXOP_L_shl(var_L_RxAEC_Out_AEC, 1));

			if (channel != CH_INNER)
			{
				Fx_convolve_2(&AEC_buf1->RxFrm_AECin_AEC[NadfMinun1 + k], AEC_buf2->W, AEC_buf2->Waux, &out1, &out2,pt_crtsmp, Nadf); //Q13,18

				var_L_RxAEC_Out_AEC2 = DVTXOP_L_sub(DVTXOP_L_shl(TxFrm_AEC2[k], 15), DVTXOP_L_shr(out1, AECout_bit_shift_by_qformatW));//Q31.15

				AEC_buf2->E_tx_AEC[k] = DVTXOP_extract_h(DVTXOP_L_shl(var_L_RxAEC_Out_AEC2, 1));

				var_L_RxAEC_Out_AEC = DVTXOP_L_sub(DVTXOP_L_shl(TxFrm_AEC2[k], 15), DVTXOP_L_shr(out2, AECout_bit_shift_by_qformatW));//Q31.15

				AEC_buf2->E_tx_AECaux[k] = DVTXOP_extract_h(DVTXOP_L_shl(var_L_RxAEC_Out_AEC, 1));

			}

		}
#endif

		//// Double Talk detection by X correlation
		if (!(k & 3))
		{
			// Double Talk detection
			tmpX = TxFrm_AEC1[k];   // 16bit Q15,0
			LtmpE = var_L_RxAEC_Out_AEC1; //32bit Q16,15

			if (AEC_buf1->L_Qex == 0)
				sh_qex = 31;
			else
				sh_qex = DVTXOP_add(DVTXOP_norm_l(AEC_buf1->L_Qex), AEC_buf1->Qex_q);
			if (AEC_buf1->L_Qxx == 0)
				sh_qxx = 31;
			else
				sh_qxx = DVTXOP_add(DVTXOP_norm_l(AEC_buf1->L_Qxx), AEC_buf1->Qxx_q);
			if (LtmpE == 0)
				sh_tmpE = 31;
			else
				sh_tmpE = DVTXOP_add(DVTXOP_norm_l(LtmpE), 15);
			if (tmpX == 0)
				sh_tmpX = 31;
			else
				sh_tmpX = DVTXOP_add(DVTXOP_norm_s(tmpX), 16);

			shft = DVTX_MIN(sh_qex, sh_qxx);
			shft = DVTX_MIN(shft, sh_tmpX);
			tmp16 = DVTXOP_sub(sh_tmpE, 15);
			shft = DVTX_MIN(shft, tmp16);
			tmp16 = DVTXOP_sub(DVTXOP_add(sh_tmpX, sh_tmpX), 15);
			shft = DVTX_MIN(shft, tmp16);

			AEC_buf1->L_Qex = Fx_recursive_avg(DVTXOP_L_shl(AEC_buf1->L_Qex, DVTXOP_sub(shft, AEC_buf1->Qex_q)), DVTXOP_L_mpy_ls(DVTXOP_L_shl(LtmpE, shft), tmpX), DVTX_WORD16_0_99);
			AEC_buf1->L_Qxx = Fx_recursive_avg(DVTXOP_L_shl(AEC_buf1->L_Qxx, DVTXOP_sub(shft, AEC_buf1->Qxx_q)), DVTXOP_L_shl(DVTXOP_L_mult(tmpX, tmpX), DVTXOP_sub(shft, 1)), DVTX_WORD16_0_99);
			AEC_buf1->Qex_q = shft;
			AEC_buf1->Qxx_q = shft;

			AEC_buf1->L_Qex = DVTX_MAX(AEC_buf1->L_Qex, 1);
			AEC_buf1->L_Qxx = DVTX_MAX(AEC_buf1->L_Qxx, 1);
			{
				shxx = DVTXOP_norm_l(AEC_buf1->L_Qxx);
				tmp32 = DVTXOP_L_divide(DVTXOP_L_shr_r(AEC_buf1->L_Qex, 1), DVTXOP_L_shl(AEC_buf1->L_Qxx, shxx));   //4
				tmp16 = DVTX_MAX(DVTXOP_sub(DVTX_FIXED_ONE(13), DVTXOP_extract_l(DVTXOP_L_shr_r(tmp32, DVTXOP_sub(17, shxx)))), 0); //Q2.13
			}
			tmp16 = DVTX_MIN(tmp16, 8192); // 1*2^13

			if (AEC_buf1->Flag_RxVAD_AEC == 0)
				AEC_buf1->XECC = 0;
			else
			{
				if (AEC_buf1->XECC > tmp16) // decreasing
					AEC_buf1->XECC = DVTXOP_add(DVTXOP_mult(AEC_buf1->XECC, DVTX_WORD16_0_99), DVTXOP_mult(tmp16, DVTX_WORD16_0_01));//Q2.13
				else
					AEC_buf1->XECC = DVTXOP_add(DVTXOP_mult(AEC_buf1->XECC, DVTX_WORD16_0_8), DVTXOP_mult(tmp16, DVTX_WORD16_0_2));//Q2.13
			}
		}

		if (AEC_param->PARA_FLAG_RxVAD_First_AEC == 0)
		{
			adf_var_avg1 = 0;
			adf_var_avg2 = 0;
//			FlagSampleADFupate = (Flag_2smp_sparse) && (pwr_adfin_dB > AEC_param->PARA_Pwr_LoTHD_ADF_IN) && (TxRxPwrDiff < AEC_param->PARA_THD_RxTx_Pwr_Difference) && (AEC_buf1->Pwr_TX_AECIN_dB > AEC_param->PARA_reserved_29)
//				&& (AEC_buf1->Flag_ringbakctone == 0) && (FrmDT == 0);
//	       FlagSampleADFupate = (Flag_2smp_sparse) && (pwr_adfin_dB > AEC_param->PARA_Pwr_LoTHD_ADF_IN) && (TxRxPwrDiff < AEC_param->PARA_THD_RxTx_Pwr_Difference) && (AEC_buf->Pwr_TX_AECIN_dB > AEC_param->PARA_reserved_29)
//				&& (AEC_buf->Flag_ringbakctone == 0) && (FrmDT == 0);
			FlagSampleADFupate = (Flag_2smp_sparse) && (pwr_adfin > DVTXOP_L_shl(exp_zh1, q_save - Qq)) && (exp_zh < ((long long)(DVTXOP_LL_mult(exp_zh2,pwr_adfin))>>(q_save+1)) )  && (AEC_buf1->Pwr_TX_AECIN_dB > AEC_param->PARA_reserved_29)
								&& (AEC_buf1->Flag_ringbakctone == 0) && (FrmDT == 0);

			if (FlagSampleADFupate == 1)
			{
				if (AEC_buf1->Cnt_Samples_NLMSupdate < DVTX_MAX_32)
					AEC_buf1->Cnt_Samples_NLMSupdate++; //

				if(channel != CH_INNER)
					if (AEC_buf2->Cnt_Samples_NLMSupdate < DVTX_MAX_32)
						AEC_buf2->Cnt_Samples_NLMSupdate++; //

				//num
				norm_shift1 = DVTXOP_norm_l(step_fast); //Q0.31?
				Ltmp3 = DVTXOP_L_shl(step_fast, (short)(norm_shift1 - 1));
				//denom
				Ltmp = DVTX_MAX(pwr_adfin, 1);
				norm_shift = DVTXOP_norm_l(Ltmp);
				Ltmp = DVTXOP_L_shl(Ltmp, norm_shift);
				if (Ltmp3 <= 0)
					Ltmp2 = 0;
				else
					Ltmp2 = DVTXOP_L_divide(Ltmp3, Ltmp);   //5

				Ltmp2 = DVTXOP_L_shr(Ltmp2, (short)(0 - 1 + norm_shift1 - norm_shift - q)); //Q0,31

				Ltmp = DVTXOP_L_mpy_ls(Ltmp2, AEC_buf1->E_tx_AEC[k]); //Q0,31*15.0 = 15,31-15 = q15,16
#ifndef FN_DVTX_AEC_NB_UPDATE_OPT_DSP
				pt_conv = pt_crtsmp;

				for (n = 0; n < DVTX_ADF_early_index; n++) // change from 32 to 64
				{
					tmp32 = DVTXOP_L_mpy_ls(Ltmp, AEC_buf1->ADF_IN[pt_conv]); //q15,16*q15,0=q30,16-15 = q30,1?
					//tmp32 = DVTXOP_L_shr_r(tmp32, 11); //Q17?
					tmp32 = (tmp32 + 1024) >> 11;

					if (tmp32 > 0)
						adf_var_avg1 = DVTXOP_L_add(adf_var_avg1, tmp32);
					else
						adf_var_avg1 = DVTXOP_L_sub(adf_var_avg1, tmp32);

					AEC_buf1->adf_var[n] = DVTXOP_extract_l(tmp32);
					pt_conv--;
					if (pt_conv < 0)
						pt_conv = NadfMinun1;
				}
#else
				pin = (ae_f16x4 *)(&AEC_buf1->RxFrm_AECin_AEC[DVTX_NadfMinun1_NB + k]);
				align1 = AE_LA64_PP(pin);
				Xtmp32 = AE_MOVDA32(Ltmp);
				XtmpH = AE_TRUNC16X4F32(Xtmp32, Xtmp32);
				XtmpL = AE_SRAA16S(AE_CVT16X4(Xtmp32, Xtmp32), 1);
				XtmpL = AE_AND16(XtmpL, Xcondata2);
				Xtmp_sum = AE_MOVDA32(adf_var_avg1);
				pout = (ae_int16x4 *)&AEC_buf1->adf_var[0];//DVTX_ECNS_vars->ECNSbuff.adf_var;
				align2 = AE_ZALIGN64();
				for (n = 0; n < DVTX_ADF_early_index; n+=4) // change from 32 to 64
				{
					AE_LA16X4_RIP(Xtmp16,align1,pin);
					AE_MULF16X4SS(Xrdata1, Xrdata2, XtmpL, Xtmp16);
					Xrdata1 = AE_SRAA32S(Xrdata1, 15);
					Xrdata2 = AE_SRAA32S(Xrdata2, 15);
					AE_MULAF16X4SS(Xrdata1, Xrdata2, XtmpH, Xtmp16);
					Xrdata1 = AE_SRAA32S(AE_ADD32S(Xrdata1, Xcondata1), 11);
					Xrdata2 = AE_SRAA32S(AE_ADD32S(Xrdata2, Xcondata1), 11);
					Xtmp_sum = AE_ADD32S(Xtmp_sum, AE_ABS32S(Xrdata1));
					Xtmp_sum = AE_ADD32S(Xtmp_sum, AE_ABS32S(Xrdata2));
					Xtmp16 = AE_CVT16X4(Xrdata1, Xrdata2);
					AE_SA16X4_IP(Xtmp16,align2,pout);
				}
				AE_SA64POS_FP(align2, pout);
				//for (n = 0; n < DVTX_ADF_early_index_NB; n++)
				//	DVTX_ECNS_vars->ECNSbuff.adf_var[n] = tmpbuf[n];
				Xtmp32 = AE_SEL32_LH(Xtmp_sum, Xtmp_sum);
				Xtmp_sum = AE_ADD32S(Xtmp32, Xtmp_sum);
				adf_var_avg1 = (int)AE_MOVAD32_L(Xtmp_sum);

#endif
				if (adf_var_avg1 < AEC_param->PARA_ADF_Wvar_THD)
				{
#ifndef FN_DVTX_AEC_NB_UPDATE_OPT_DSP
					for (n = 0; n < DVTX_ADF_early_index; n++)
						AEC_buf1->W[n] = DVTXOP_add(AEC_buf1->W[n], AEC_buf1->adf_var[n]); // q17

					if ((FRAME_param->PARA_call_mode_HS_HF_EAR == 0) || (FRAME_param->PARA_call_mode_HS_HF_EAR == 1)) // only for HF and HS mode
					{
						for (n = DVTX_ADF_early_index; n < Nadf; n++)
						{
							tmp32 = DVTXOP_L_mpy_ls(Ltmp, AEC_buf1->ADF_IN[pt_conv]); //q15,16*q15,0=q30,16-15 = q30,1?
							//tmp32 = DVTXOP_L_shr_r(tmp32, 11); //Q17?
							tmp32 = (tmp32 + 1024) >> 11;
							AEC_buf1->adf_var[n] = DVTXOP_extract_l(tmp32);
							AEC_buf1->W[n] = DVTXOP_add(AEC_buf1->W[n], AEC_buf1->adf_var[n]); // q17
							pt_conv--;
							if (pt_conv < 0)
								pt_conv = NadfMinun1;
						}
					}
#else
					pin2 = (ae_f16x4 *)(&AEC_buf1->W[0]);
					pin = (ae_f16x4 *)(&AEC_buf1->W[0]);
					pout = (ae_int16x4 *)&AEC_buf1->adf_var[0];
					align1 = AE_LA64_PP(pout);
					align3 = AE_LA64_PP(pin2);
					align2 = AE_ZALIGN64();
					for (n = 0; n < DVTX_ADF_early_index; n+=4)
					{
						//DVTX_ECNS_vars->ECNSbuff.W[n] = DVTXOP_add(DVTX_ECNS_vars->ECNSbuff.W[n], DVTX_ECNS_vars->ECNSbuff.adf_var[n]); // q17
						AE_LA16X4_IP(Xtmp,align3,pin2);
						AE_LA16X4_IP(Xtmp16,align1,pout);
						Xtmp = AE_ADD16S(Xtmp, Xtmp16);
						AE_SA16X4_IP(Xtmp,align2,pin);
					}
					AE_SA64POS_FP(align2, pin);
					if ((FRAME_param->PARA_call_mode_HS_HF_EAR == 0) || (FRAME_param->PARA_call_mode_HS_HF_EAR == 1)) // only for HF mode
					{
						pin = (ae_f16x4 *)(&AEC_buf1->RxFrm_AECin_AEC[16 + k]);
						//pin2 = (ae_f16x4 *)(&DVTX_ECNS_vars->ECNSbuff.W[64]);
						align1 = AE_LA64_PP(pin);
						Xtmp32 = AE_MOVDA32(Ltmp);
						XtmpH = AE_TRUNC16X4F32(Xtmp32, Xtmp32);
						XtmpL = AE_SRAA16S(AE_CVT16X4(Xtmp32, Xtmp32), 1);
						XtmpL = AE_AND16(XtmpL, Xcondata2);

						//pout = (ae_f16x4 *)&DVTX_ECNS_vars->ECNSbuff.adf_var[64];
						align2 = AE_ZALIGN64();

						AE_LA16X4_RIP(Xtmp16,align1,pin);
						AE_L16X4_IP(Xtmp,pin2,0);
						AE_MULF16X4SS(Xrdata1, Xrdata2, XtmpL, Xtmp16);
						Xrdata1 = AE_SRAA32S(Xrdata1, 15);
						Xrdata2 = AE_SRAA32S(Xrdata2, 15);
						AE_MULAF16X4SS(Xrdata1, Xrdata2, XtmpH, Xtmp16);
						Xrdata1 = AE_SRAA32S(AE_ADD32S(Xrdata1, Xcondata1), 11);
						Xrdata2 = AE_SRAA32S(AE_ADD32S(Xrdata2, Xcondata1), 11);
						Xtmp16 = AE_CVT16X4(Xrdata1, Xrdata2);
						AE_SA16X4_IP(Xtmp16,align2,pout);
						Xtmp = AE_ADD16S(Xtmp, Xtmp16);
						AE_S16X4_IP(Xtmp,pin2,8);

						AE_LA16X4_RIP(Xtmp16,align1,pin);
						AE_L16X4_IP(Xtmp,pin2,0);
						AE_MULF16X4SS(Xrdata1, Xrdata2, XtmpL, Xtmp16);
						Xrdata1 = AE_SRAA32S(Xrdata1, 15);
						Xrdata2 = AE_SRAA32S(Xrdata2, 15);
						AE_MULAF16X4SS(Xrdata1, Xrdata2, XtmpH, Xtmp16);
						Xrdata1 = AE_SRAA32S(AE_ADD32S(Xrdata1, Xcondata1), 11);
						Xrdata2 = AE_SRAA32S(AE_ADD32S(Xrdata2, Xcondata1), 11);
						Xtmp16 = AE_CVT16X4(Xrdata1, Xrdata2);
						AE_SA16X4_IP(Xtmp16,align2,pout);
						Xtmp = AE_ADD16S(Xtmp, Xtmp16);
						AE_S16X4_IP(Xtmp,pin2,8);

						AE_SA64POS_FP(align2, pout);

					}
#endif

				}

				if (channel != CH_INNER)
				{
					Ltmp = DVTXOP_L_mpy_ls(Ltmp2, AEC_buf2->E_tx_AEC[k]); //Q0,31*15.0 = 15,31-15 = q15,16
#ifndef FN_DVTX_AEC_NB_UPDATE_OPT_DSP
					pt_conv = pt_crtsmp;

					for (n = 0; n < DVTX_ADF_early_index; n++) // change from 32 to 64
					{
						tmp32 = DVTXOP_L_mpy_ls(Ltmp, AEC_buf1->ADF_IN[pt_conv]); //q15,16*q15,0=q30,16-15 = q30,1?
						//tmp32 = DVTXOP_L_shr_r(tmp32, 11); //Q17?
						tmp32 = (tmp32 + 1024) >> 11;

						if (tmp32 > 0)
							adf_var_avg2 = DVTXOP_L_add(adf_var_avg2, tmp32);
						else
							adf_var_avg2 = DVTXOP_L_sub(adf_var_avg2, tmp32);

						AEC_buf2->adf_var[n] = DVTXOP_extract_l(tmp32);
						pt_conv--;
						if (pt_conv < 0)
							pt_conv = NadfMinun1;
					}
#else
					pin = (ae_f16x4 *)(&AEC_buf1->RxFrm_AECin_AEC[DVTX_NadfMinun1_NB + k]);
					align1 = AE_LA64_PP(pin);
					Xtmp32 = AE_MOVDA32(Ltmp);
					XtmpH = AE_TRUNC16X4F32(Xtmp32, Xtmp32);
					XtmpL = AE_SRAA16S(AE_CVT16X4(Xtmp32, Xtmp32), 1);
					XtmpL = AE_AND16(XtmpL, Xcondata2);
					Xtmp_sum = AE_MOVDA32(adf_var_avg2);
					pout = (ae_int16x4 *)&AEC_buf2->adf_var[0];//DVTX_ECNS_vars->ECNSbuff.adf_var;
					align2 = AE_ZALIGN64();
					for (n = 0; n < DVTX_ADF_early_index; n += 4) // change from 32 to 64
					{
						AE_LA16X4_RIP(Xtmp16, align1, pin);
						AE_MULF16X4SS(Xrdata1, Xrdata2, XtmpL, Xtmp16);
						Xrdata1 = AE_SRAA32S(Xrdata1, 15);
						Xrdata2 = AE_SRAA32S(Xrdata2, 15);
						AE_MULAF16X4SS(Xrdata1, Xrdata2, XtmpH, Xtmp16);
						Xrdata1 = AE_SRAA32S(AE_ADD32S(Xrdata1, Xcondata1), 11);
						Xrdata2 = AE_SRAA32S(AE_ADD32S(Xrdata2, Xcondata1), 11);
						Xtmp_sum = AE_ADD32S(Xtmp_sum, AE_ABS32S(Xrdata1));
						Xtmp_sum = AE_ADD32S(Xtmp_sum, AE_ABS32S(Xrdata2));
						Xtmp16 = AE_CVT16X4(Xrdata1, Xrdata2);
						AE_SA16X4_IP(Xtmp16, align2, pout);
					}
					AE_SA64POS_FP(align2, pout);
					//for (n = 0; n < DVTX_ADF_early_index_NB; n++)
					//	DVTX_ECNS_vars->ECNSbuff.adf_var[n] = tmpbuf[n];
					Xtmp32 = AE_SEL32_LH(Xtmp_sum, Xtmp_sum);
					Xtmp_sum = AE_ADD32S(Xtmp32, Xtmp_sum);
					adf_var_avg2 = (int)AE_MOVAD32_L(Xtmp_sum);

#endif
					if (adf_var_avg2 < AEC_param->PARA_ADF_Wvar_THD)
					{
#ifndef FN_DVTX_AEC_NB_UPDATE_OPT_DSP
						for (n = 0; n < DVTX_ADF_early_index; n++)
							AEC_buf2->W[n] = DVTXOP_add(AEC_buf2->W[n], AEC_buf2->adf_var[n]); // q17

						if ((FRAME_param->PARA_call_mode_HS_HF_EAR == 0) || (FRAME_param->PARA_call_mode_HS_HF_EAR == 1)) // only for HF and HS mode
						{
							for (n = DVTX_ADF_early_index; n < Nadf; n++)
							{
								tmp32 = DVTXOP_L_mpy_ls(Ltmp, AEC_buf1->ADF_IN[pt_conv]); //q15,16*q15,0=q30,16-15 = q30,1?
								//tmp32 = DVTXOP_L_shr_r(tmp32, 11); //Q17?
								tmp32 = (tmp32 + 1024) >> 11;
								AEC_buf2->adf_var[n] = DVTXOP_extract_l(tmp32);
								AEC_buf2->W[n] = DVTXOP_add(AEC_buf2->W[n], AEC_buf2->adf_var[n]); // q17
								pt_conv--;
								if (pt_conv < 0)
									pt_conv = NadfMinun1;
							}
						}
#else
						pin2 = (ae_f16x4 *)(&AEC_buf2->W[0]);
						pin = (ae_f16x4 *)(&AEC_buf2->W[0]);
						pout = (ae_int16x4 *)&AEC_buf2->adf_var[0];
						align1 = AE_LA64_PP(pout);
						align3 = AE_LA64_PP(pin2);
						align2 = AE_ZALIGN64();
						for (n = 0; n < DVTX_ADF_early_index; n += 4)
						{
							//DVTX_ECNS_vars->ECNSbuff.W[n] = DVTXOP_add(DVTX_ECNS_vars->ECNSbuff.W[n], DVTX_ECNS_vars->ECNSbuff.adf_var[n]); // q17
							AE_LA16X4_IP(Xtmp, align3, pin2);
							AE_LA16X4_IP(Xtmp16, align1, pout);
							Xtmp = AE_ADD16S(Xtmp, Xtmp16);
							AE_SA16X4_IP(Xtmp, align2, pin);
						}
						AE_SA64POS_FP(align2, pin);
						if ((FRAME_param->PARA_call_mode_HS_HF_EAR == 0) || (FRAME_param->PARA_call_mode_HS_HF_EAR == 1)) // only for HF mode
						{
							pin = (ae_f16x4 *)(&AEC_buf1->RxFrm_AECin_AEC[16 + k]);
							//pin2 = (ae_f16x4 *)(&DVTX_ECNS_vars->ECNSbuff.W[64]);
							align1 = AE_LA64_PP(pin);
							Xtmp32 = AE_MOVDA32(Ltmp);
							XtmpH = AE_TRUNC16X4F32(Xtmp32, Xtmp32);
							XtmpL = AE_SRAA16S(AE_CVT16X4(Xtmp32, Xtmp32), 1);
							XtmpL = AE_AND16(XtmpL, Xcondata2);

							//pout = (ae_f16x4 *)&DVTX_ECNS_vars->ECNSbuff.adf_var[64];
							align2 = AE_ZALIGN64();

							AE_LA16X4_RIP(Xtmp16, align1, pin);
							AE_L16X4_IP(Xtmp, pin2, 0);
							AE_MULF16X4SS(Xrdata1, Xrdata2, XtmpL, Xtmp16);
							Xrdata1 = AE_SRAA32S(Xrdata1, 15);
							Xrdata2 = AE_SRAA32S(Xrdata2, 15);
							AE_MULAF16X4SS(Xrdata1, Xrdata2, XtmpH, Xtmp16);
							Xrdata1 = AE_SRAA32S(AE_ADD32S(Xrdata1, Xcondata1), 11);
							Xrdata2 = AE_SRAA32S(AE_ADD32S(Xrdata2, Xcondata1), 11);
							Xtmp16 = AE_CVT16X4(Xrdata1, Xrdata2);
							AE_SA16X4_IP(Xtmp16, align2, pout);
							Xtmp = AE_ADD16S(Xtmp, Xtmp16);
							AE_S16X4_IP(Xtmp, pin2, 8);

							AE_LA16X4_RIP(Xtmp16, align1, pin);
							AE_L16X4_IP(Xtmp, pin2, 0);
							AE_MULF16X4SS(Xrdata1, Xrdata2, XtmpL, Xtmp16);
							Xrdata1 = AE_SRAA32S(Xrdata1, 15);
							Xrdata2 = AE_SRAA32S(Xrdata2, 15);
							AE_MULAF16X4SS(Xrdata1, Xrdata2, XtmpH, Xtmp16);
							Xrdata1 = AE_SRAA32S(AE_ADD32S(Xrdata1, Xcondata1), 11);
							Xrdata2 = AE_SRAA32S(AE_ADD32S(Xrdata2, Xcondata1), 11);
							Xtmp16 = AE_CVT16X4(Xrdata1, Xrdata2);
							AE_SA16X4_IP(Xtmp16, align2, pout);
							Xtmp = AE_ADD16S(Xtmp, Xtmp16);
							AE_S16X4_IP(Xtmp, pin2, 8);

							AE_SA64POS_FP(align2, pout);

						}
#endif
					}
				}
			}
		} // end of AEC update

		// current sample pointer update
		pt_crtsmp++;
		if (pt_crtsmp >= Nadf)
			pt_crtsmp = 0;
#if(FLAG_SELECT_C_DSP == 1)
#if(Debug_File_Write_C == 1)
		if (channel == FLAG_ECNS_WRITE_SELECTION)
		{
			fprintf(fp_debug_ADF_C, "%d %d %d %d %d %d %d %ld %d %ld %ld\n",
				AEC_buf1->XECC,
				AEC_buf1->Threshold_XECC,
				AEC_param->PARA_reserved_22,
				pwr_adfin_dB,
				AEC_param->PARA_Pwr_LoTHD_ADF_IN,
				TxRxPwrDiff,
				AEC_param->PARA_THD_RxTx_Pwr_Difference,
				adf_var_avg1,
				AEC_param->PARA_ADF_Wvar_THD,
				AEC_param->PARA_ADF_reference_step,
				step_fast
			);
		}
#endif
#endif
	}

	return;
}
#endif

void fx_SolomonVoice_AEC_ErrPower(AECStatus* AEC_buf1, AECStatus* AEC_buf2,
	short PARA_reserved_33,	short Nadf, int Nsamples2sec, short FRM_LEN, CHANNEL channel)
{
	short k;
	short tmp16;
	short EminVal;

	AEC_buf1->Pwr_TX_AECOUT_dB = Fx_time_vector_power_dB(AEC_buf1->E_tx_AEC, FRM_LEN);
	AEC_buf1->Pwr_TX_AECauxOUT_dB = Fx_time_vector_power_dB(AEC_buf1->E_tx_AECaux, FRM_LEN);

	tmp16 = AEC_buf1->Pwr_TX_AECIN_dB - AEC_buf1->Pwr_TX_AECOUT_dB;
	AEC_buf1->PwrDiff_AECinout_dB = DVTXOP_add(DVTXOP_mult(AEC_buf1->PwrDiff_AECinout_dB, DVTX_WORD16_0_9), DVTXOP_mult(tmp16, DVTX_WORD16_0_1));// used in RES module

	AEC_buf1->Flag_Waux_update = 0;

	if (channel != CH_INNER)
	{
		AEC_buf2->Pwr_TX_AECOUT_dB = Fx_time_vector_power_dB(AEC_buf2->E_tx_AEC, FRM_LEN);
		AEC_buf2->Pwr_TX_AECauxOUT_dB = Fx_time_vector_power_dB(AEC_buf2->E_tx_AECaux, FRM_LEN);

		tmp16 = AEC_buf2->Pwr_TX_AECIN_dB - AEC_buf2->Pwr_TX_AECOUT_dB;
		AEC_buf2->PwrDiff_AECinout_dB = DVTXOP_add(DVTXOP_mult(AEC_buf2->PwrDiff_AECinout_dB, DVTX_WORD16_0_9), DVTXOP_mult(tmp16, DVTX_WORD16_0_1));// used in RES module

		AEC_buf2->Flag_Waux_update = 0;
	}

	if (AEC_buf1->Cnt_Samples_NLMSupdate < Nsamples2sec)  // 1.0 sec
	{
		Fx_vector_copy_s(AEC_buf1->Waux, AEC_buf1->W, Nadf);
		if (channel != CH_INNER)
			Fx_vector_copy_s(AEC_buf2->Waux, AEC_buf2->W, Nadf);
	}
	else
	{
		if (AEC_buf1->Flag_RxVAD_AEC)
		{
			EminVal = DVTX_MIN(AEC_buf1->Pwr_TX_AECOUT_dB, AEC_buf1->Pwr_TX_AECauxOUT_dB);

			if (AEC_buf1->Pwr_TX_AECIN_dB > EminVal)
			{
				if (EminVal == AEC_buf1->Pwr_TX_AECOUT_dB) // W is the best
				{
					//tmp16 = AEC_buf1->Pwr_TX_AECIN_dB - EminVal;
					if ((AEC_buf1->PwrDiff_AECinout_dB > PARA_reserved_33))
					{
						Fx_vector_copy_s(AEC_buf1->Waux, AEC_buf1->W, Nadf);
						AEC_buf1->Flag_Waux_update = 1;
					}
				}
				if (EminVal == AEC_buf1->Pwr_TX_AECauxOUT_dB) // Waux is the best
				{
					Fx_vector_copy_s(AEC_buf1->W, AEC_buf1->Waux, Nadf);
#ifndef KHW_OPTI_20191216_HIFI
					for (k = 0; k < FRM_LEN; k++)
						AEC_buf1->E_tx_AEC[k] = AEC_buf1->E_tx_AECaux[k];
#else
					__vec_memcpy(AEC_buf1->E_tx_AEC,AEC_buf1->E_tx_AECaux,(FRM_LEN<<1));
#endif
				}
			}

			if(channel != CH_INNER)
			{
				EminVal = DVTX_MIN(AEC_buf2->Pwr_TX_AECOUT_dB, AEC_buf2->Pwr_TX_AECauxOUT_dB);

				if (AEC_buf1->Pwr_TX_AECIN_dB > EminVal)
				{
					if (EminVal == AEC_buf2->Pwr_TX_AECOUT_dB) // W is the best
					{
						if ((AEC_buf2->PwrDiff_AECinout_dB > PARA_reserved_33))
						{
							Fx_vector_copy_s(AEC_buf2->Waux, AEC_buf2->W, Nadf);
							AEC_buf2->Flag_Waux_update = 1;
						}
					}
					if (EminVal == AEC_buf2->Pwr_TX_AECauxOUT_dB) // Waux is the best
					{
						Fx_vector_copy_s(AEC_buf2->W, AEC_buf2->Waux, Nadf);
#ifndef KHW_OPTI_20191216_HIFI
						for (k = 0; k < FRM_LEN; k++)
							AEC_buf2->E_tx_AEC[k] = AEC_buf2->E_tx_AECaux[k];
#else
						__vec_memcpy(AEC_buf2->E_tx_AEC,AEC_buf2->E_tx_AECaux,(FRM_LEN<<1));
#endif
					}
				}
			}
		}
		else
		{
			AEC_buf1->PwrDiff_AECinout_dB = 0;
			if (channel != CH_INNER)
				AEC_buf2->PwrDiff_AECinout_dB = 0;
		}
	}

	return;
}

#ifdef Fx_convolve_OPT_DSP
int *gBuff_L_WB;
#endif
void FN_SOLOMONVOICEW_TX_AEC(DVTX_ECNS_Cfg_t* DVTX_ECNS_vars, CHANNEL channel)
{

	//AEC parameters
	short k;
	short FRM_LEN, NadfMinun1, Nadf, frame_pwr_bitshiftoffset, OneOverFrmQ22;
	short ValClipp;
	int   step_fast;
	int   Nsamples2sec;

	AECStatus* AEC_buf1=NULL;
    AECStatus* AEC_buf2 = NULL;
	SamsungSolomonVoiceWTxAECParam* AEC_param;
	FRAMEStatus* FRAME_buf = &DVTX_ECNS_vars->FRAME_buf;
	SamsungSolomonVoiceWTxFRAMEParam* FRAME_param = &DVTX_ECNS_vars->FRAME_param;
	RESStatus* RES_buf;
	COMMONBUF* COMMON_buf = &DVTX_ECNS_vars->COMMON_buf;

	short* Speech_Tx1;
    short* Speech_Tx2 = NULL;
	short* Speech_Rx;
	short* OutSignal;

	short Flag_Tx_Clipping1;
	short Flag_Tx_Clipping2;

	short AECout_bit_shift_by_qformatW;

	int *Buff_L_NB = DVTX_ECNS_vars->COMMON_buf.Buff_L_NB;
	int *Buff_L_NB2 = DVTX_ECNS_vars->COMMON_buf.Buff_L_NB2;
	int *Buff_L_WB = DVTX_ECNS_vars->COMMON_buf.Buff_L_WB;
//#ifdef Fx_convolve_OPT_DSP
//	gBuff_L_WB = Buff_L_WB;
//#endif
	short PARA_Gain_RxSig;
	short PARA_Gain_TxSig;
	short PARA_Q_for_InSigGain;

	short *TxFrm_AEC1 = (short *)Buff_L_NB;
	short *TxFrm_AEC2 = (short *)Buff_L_NB2;
	short *RxFFTfrm_AEC;
    short *E_tx_AEC1 = NULL;
    short *E_tx_AEC2 = NULL;
	short PARA_THD_Pwr_Rx_AEC_IN_dB;
	short PARA_THD_Pwr_Tx_dB;
	short PARA_THD_Pwr_Tx_Loud_dB;
	short PARA_reserved_21, PARA_reserved_27, PARA_reserved_29, PARA_reserved_30, PARA_reserved_33;

	short FrmDT;

	short *RxFrm_Delay_AEC;
	short DelayCompensation;

#ifdef Fx_convolve_OPT_DSP
	gBuff_L_WB = Buff_L_WB;
#endif

	if (channel == CH_INNER)
	{
		AEC_buf1 = &DVTX_ECNS_vars->AEC_Inner_buf;
		AEC_param = &DVTX_ECNS_vars->AEC_Inner_param;
		RES_buf = &DVTX_ECNS_vars->RES_Inner_buf;

		Speech_Rx = DVTX_ECNS_vars->Speech_Rx_Inner;
		Speech_Tx1 = DVTX_ECNS_vars->Speech_Tx_Inner;
		OutSignal = DVTX_ECNS_vars->OutSignal_Inner;

		Flag_Tx_Clipping1 = FRAME_buf->Flag_Tx_Clipping_Inner;

		PARA_Gain_RxSig = DVTX_ECNS_vars->FRAME_param.PARA_Gain_RxSig_Inner;
		PARA_Gain_TxSig = DVTX_ECNS_vars->FRAME_param.PARA_Gain_TxSig_Inner;
		PARA_Q_for_InSigGain = DVTX_ECNS_vars->FRAME_param.PARA_Q_for_InSigGain_Inner;

		FRM_LEN = DVTX_FRM_LEN_NB;
		NadfMinun1 = DVTX_NadfMinun1_NB;
		Nadf = DVTX_Nadf_NB;
		frame_pwr_bitshiftoffset = DVTX_frame_pwr_bitshiftoffset_NB;
		OneOverFrmQ22 = DVTX_OneOverFrmQ22_NB;
		Nsamples2sec = 16000;
		AECout_bit_shift_by_qformatW = -2; // aecW Q15 case, innerAEC

		FrmDT = FRAME_buf->FrmDT_Inner;
	}
	else
	{
		AEC_buf1 = &DVTX_ECNS_vars->AEC_Outer_buf_1;
		AEC_buf2 = &DVTX_ECNS_vars->AEC_Outer_buf_2;
		AEC_param = &DVTX_ECNS_vars->AEC_Outer_param_1;
		Speech_Tx2 = DVTX_ECNS_vars->Speech_Tx_Outer_2;
		RES_buf = &DVTX_ECNS_vars->RES_Outer_buf;
		
		Speech_Rx = DVTX_ECNS_vars->Speech_Rx_Outer;
		Speech_Tx1 = DVTX_ECNS_vars->Speech_Tx_Outer_1;
		OutSignal = DVTX_ECNS_vars->OutSignal_Outer;
		
		Flag_Tx_Clipping1 = FRAME_buf->Flag_Tx_Clipping_Outer_1;
		Flag_Tx_Clipping2 = FRAME_buf->Flag_Tx_Clipping_Outer_2;

		PARA_Gain_RxSig = DVTX_ECNS_vars->FRAME_param.PARA_Gain_RxSig_Outer;
		PARA_Gain_TxSig = DVTX_ECNS_vars->FRAME_param.PARA_Gain_TxSig_Outer;
		PARA_Q_for_InSigGain = DVTX_ECNS_vars->FRAME_param.PARA_Q_for_InSigGain_Outer;

		if (DVTX_ECNS_vars->FRAME_param.TX_Outer_bandwidth == DVTX_FRM_LEN_WB)
		{
			FRM_LEN = DVTX_FRM_LEN_WB;
			NadfMinun1 = DVTX_NadfMinun1_WB;
			Nadf = DVTX_Nadf_WB;
			frame_pwr_bitshiftoffset = DVTX_frame_pwr_bitshiftoffset_WB;
			OneOverFrmQ22 = DVTX_OneOverFrmQ22_WB;
			Nsamples2sec = 32000;
			AECout_bit_shift_by_qformatW = 3; // aecW Q17 case, outerAEC
		}
		else
		{
			FRM_LEN = DVTX_FRM_LEN_NB;
			NadfMinun1 = DVTX_NadfMinun1_NB;
			Nadf = DVTX_Nadf_NB;
			frame_pwr_bitshiftoffset = DVTX_frame_pwr_bitshiftoffset_NB;
			OneOverFrmQ22 = DVTX_OneOverFrmQ22_NB;
			Nsamples2sec = 16000;
			AECout_bit_shift_by_qformatW = -2; // aecW Q15 case, innerAEC
		}

		FrmDT = FRAME_buf->FrmDT_Outer;
	}

	ValClipp = AEC_param->PARA_reserved_28;
	RxFFTfrm_AEC = AEC_buf1->RxFFTfrm_AEC;
	E_tx_AEC1 = AEC_buf1->E_tx_AEC;
	if(channel != CH_INNER)
		E_tx_AEC2 = AEC_buf2->E_tx_AEC;
	RxFrm_Delay_AEC = AEC_buf1->RxFrm_Delay_AEC;
	DelayCompensation = AEC_param->DelayCompensation;
	PARA_THD_Pwr_Rx_AEC_IN_dB = AEC_param->PARA_THD_Pwr_Rx_AEC_IN_dB;
	PARA_THD_Pwr_Tx_dB = AEC_param->PARA_THD_Pwr_Tx_dB;
	PARA_THD_Pwr_Tx_Loud_dB = AEC_param->PARA_THD_Pwr_Tx_Loud_dB;
	PARA_reserved_21 = AEC_param->PARA_reserved_21;
	PARA_reserved_27 = AEC_param->PARA_reserved_27;
	PARA_reserved_29 = AEC_param->PARA_reserved_29;
	PARA_reserved_30 = AEC_param->PARA_reserved_30;
	PARA_reserved_33 = AEC_param->PARA_reserved_33;

#if(FLAG_SELECT_C_DSP == 1)
#if(Debug_File_Write_C == 1)
	if (channel == CH_INNER)
	{
		fwrite(Speech_Tx1, sizeof(short), FRM_LEN, fp_debug_AEC_in_inner);
	}
	else
	{
		fwrite(Speech_Tx1, sizeof(short), FRM_LEN, fp_debug_AEC_in_outer1);
		fwrite(Speech_Tx2, sizeof(short), FRM_LEN, fp_debug_AEC_in_outer2);
	}
#endif
#endif
	/*AEC_buf1->adf_var = (short *)Buff_L_WB;*/

	// Fixed step size 
	step_fast = AEC_param->PARA_ADF_reference_step;

	/* 
	ring back tone tedection, to avoid bulk delay estimation and NLMS update
	DVTX_ECNS_vars->AECADF.Flag_ringbakctone 1:ring back tone interval
	*/
	if (channel == CH_INNER)
	{
		AEC_buf1->Flag_ringbakctone = fx_SolomonVoice_Rx_ringbacktone_detection(AEC_buf1, AEC_param);
	}

	/* 
	Rx & Tx input for ADF
	(Rx)[In]  : DVTX_ECNS_vars->Speech_rx,	[Out] : DVTX_ECNS_vars->AECADF.RxFFTfrm_AEC, DVTX_ECNS_vars->AECADF.RxFrm_AECin_AEC		  
	(Tx)[In]  : DVTX_ECNS_vars->Speech,	    [Out] : TxFrm_AEC1	*/
	fx_SolomonVoice_Rx_In_for_ADF(Speech_Rx, RxFFTfrm_AEC, AEC_buf1->RxFrm_AECin_AEC, PARA_Gain_RxSig, PARA_Q_for_InSigGain, RxFrm_Delay_AEC, DelayCompensation, NadfMinun1, FRM_LEN, COMMON_buf);
	fx_SolomonVoice_Tx_In_for_ADF(Speech_Tx1, TxFrm_AEC1, PARA_Gain_TxSig, PARA_Q_for_InSigGain, FRM_LEN);
	if(channel != CH_INNER)
		fx_SolomonVoice_Tx_In_for_ADF(Speech_Tx2, TxFrm_AEC2, PARA_Gain_TxSig, PARA_Q_for_InSigGain, FRM_LEN);

	/*
		clipping for Rx FFT ref signal
		*/
	fx_SolomonVoice_rx_clipping_for_FNLMS(AEC_buf1->RxFFTfrm_clp_AEC, RxFFTfrm_AEC, ValClipp, FRM_LEN);


	/* 
	 Rx VAD for AEC and Tx silence detection	
	*/
	AEC_buf1->Pwr_RX_AECIN_dB	= Fx_time_vector_power_dB(RxFFTfrm_AEC, FRM_LEN); //Q8
	AEC_buf1->Pwr_TX_AECIN_dB	= Fx_time_vector_power_dB(TxFrm_AEC1, FRM_LEN); // ref pwr changed since main mic. can be blocked, AMS!
	AEC_buf1->Flag_RxVAD_AEC		= fx_SolomonVoice_AEC_Flag_RxVAD(AEC_buf1->Pwr_RX_AECIN_dB, PARA_THD_Pwr_Rx_AEC_IN_dB); // 1:on   0:off	
	AEC_buf1->Flag_TxSilence_AEC	= fx_SolomonVoice_AEC_Flag_TxSilence(AEC_buf1->Pwr_TX_AECIN_dB, PARA_THD_Pwr_Tx_dB);  // 1:sig activ 0:silence, not used 
	AEC_buf1->Flag_Tx_LoudSig	= fx_SolomonVoice_AEC_Flag_LoudSig(AEC_buf1->Pwr_TX_AECIN_dB, PARA_THD_Pwr_Tx_Loud_dB);  // 1:sig loud 0:sig normal,   used to avoid cepstral smoothing for speech

	/* 
	 variable  XECC Threshold
	*/
	//if ((AEC_buf1->Flag_RxVAD_AEC == 1) && (AEC_buf1->Flag_ringbakctone == 0))
	//{
	//	AEC_buf1->Threshold_XECC = DVTXOP_add(DVTXOP_mult(AEC_buf1->Threshold_XECC, DVTX_WORD16_0_95), DVTXOP_mult(PARA_reserved_21, DVTX_WORD16_0_05));// used in RES module
	//}

	/* 
	 TX RX FRM POWER DIFF
	 Tx Single NET
	*/
	AEC_buf1->Flag_SingleTalk = fx_SolomonVoice_AEC_Flag_SingleTalk(AEC_buf1->Pwr_RX_AECIN_dB, AEC_buf1->Pwr_TX_AECIN_dB, PARA_reserved_27, AEC_buf1);
	AEC_buf1->Flag_SingleNET = fx_SolomonVoice_AEC_Flag_SingleNET(AEC_buf1->Pwr_RX_AECIN_dB, AEC_buf1->Pwr_TX_AECIN_dB, PARA_reserved_30);

#if(FLAG_SELECT_C_DSP == 1)
#if(Debug_File_Write_C == 1)
	if (channel == FLAG_ECNS_WRITE_SELECTION)
	{
		short PwrDiff_Tx_Rx_Frm;
		PwrDiff_Tx_Rx_Frm = DVTXOP_sub(AEC_buf1->Pwr_TX_AECIN_dB, AEC_buf1->Pwr_RX_AECIN_dB);
		fprintf(fp_debug_Pwr_RX_AECIN_dB_C, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
			Flag_Tx_Clipping1,
			PARA_reserved_30,
			PwrDiff_Tx_Rx_Frm,
			PARA_reserved_27,
			AEC_buf1->Pwr_RX_AECIN_dB,
			AEC_buf1->Pwr_TX_AECIN_dB,
			PARA_THD_Pwr_Rx_AEC_IN_dB,
			PARA_THD_Pwr_Tx_dB,
			PARA_THD_Pwr_Tx_Loud_dB,
			AEC_buf1->Flag_SingleTalk,
			PARA_reserved_29,
			AEC_buf1->Pwr_TX_AECOUT_dB,
			AEC_buf1->PwrDiff_AECinout_dB,
			AEC_buf1->Pwr_TX_AECauxOUT_dB,
			PARA_reserved_33,
			AEC_buf1->Flag_Waux_update
		);  //x/2^8
	}
#endif
#endif

	/* 
	delay compensation at first Rx.VAD frame : only at first Rx VAD on frame 
	*/
	//fx_SolomonVoice_AEC_Delay_Compensation(AEC_buf1, AEC_param, FRAME_param, RES_buf, FrmDT, TxFrm_AEC1, channel);


	/* 
	ADF filtering & update
	*/
	if(channel == CH_INNER)
		fx_SolomonVoice_AEC_ADFfiltering(DVTX_ECNS_vars, AEC_buf1, AEC_buf1, AEC_param, FRAME_param,
			TxFrm_AEC1, TxFrm_AEC1, AECout_bit_shift_by_qformatW, OneOverFrmQ22, frame_pwr_bitshiftoffset, NadfMinun1, Nadf, step_fast, FrmDT, FRM_LEN, channel);
	else
		fx_SolomonVoice_AEC_ADFfiltering(DVTX_ECNS_vars, AEC_buf1, AEC_buf2, AEC_param, FRAME_param,
			TxFrm_AEC1, TxFrm_AEC2, AECout_bit_shift_by_qformatW, OneOverFrmQ22, frame_pwr_bitshiftoffset, NadfMinun1, Nadf, step_fast, FrmDT, FRM_LEN, channel);


	/* 
	 error output power calculation	
	*/
	if (channel == CH_INNER)
		fx_SolomonVoice_AEC_ErrPower(AEC_buf1, AEC_buf1, AEC_param->PARA_reserved_33, Nadf, Nsamples2sec, FRM_LEN, channel);
	else
		fx_SolomonVoice_AEC_ErrPower(AEC_buf1, AEC_buf2, AEC_param->PARA_reserved_33, Nadf, Nsamples2sec, FRM_LEN, channel);
	

	/* 
	tmp out
	*/
#ifndef FN_SOLOMONVOICEW_TX_AEC_loop1
	for (k = 0; k < FRM_LEN; k++)
	{
		if (channel == CH_OUTER_1)
			OutSignal[k] = E_tx_AEC1[k];
		Speech_Tx1[k] = E_tx_AEC1[k];         // copy ADF output to NS input		
		if (channel != CH_INNER)
			Speech_Tx2[k] = E_tx_AEC2[k];         // copy ADF output to NS input		
	}
#else
	if (channel == CH_OUTER_1)
	{
#ifndef KHW_OPTI_20191216_HIFI
		for (k = 0; k < FRM_LEN; k++)
		{
		    OutSignal[k] = E_tx_AEC1[k];
		}
#else
		__vec_memcpy(OutSignal,E_tx_AEC1,(FRM_LEN<<1));
#endif
	}

	if (channel != CH_INNER)
	{
#ifndef KHW_OPTI_20191216_HIFI
		for (k = 0; k < FRM_LEN; k++)
		{
			Speech_Tx2[k] = E_tx_AEC2[k];         // copy ADF output to NS input
		}
#else
		__vec_memcpy(Speech_Tx2,E_tx_AEC2,(FRM_LEN<<1));
#endif
	}
#ifndef KHW_OPTI_20191216_HIFI
	for (k = 0; k < FRM_LEN; k++)
	{
		Speech_Tx1[k] = E_tx_AEC1[k];         // copy ADF output to NS input
	}
#else
	__vec_memcpy(Speech_Tx1,E_tx_AEC1,(FRM_LEN<<1));
#endif
#endif

	if (AEC_param->PARA_reserved_1 == 0)// flag AEC on off
	{
#ifndef HOON_OPT_HIFI_12
		for (k = 0; k < FRM_LEN; k++)
		{
			if (channel == CH_OUTER_1)
			{
				OutSignal[k] = TxFrm_AEC1[k]; // BYPASS
			}
			Speech_Tx1[k] = TxFrm_AEC1[k];         // copy ADF output to NS input		
		}
#else
		if (channel == CH_OUTER_1)
		{

#ifndef KHW_OPTI_20191216_HIFI
			for (k = 0; k < FRM_LEN; k++)
			{
				OutSignal[k] = TxFrm_AEC1[k]; // BYPASS
				Speech_Tx1[k] = TxFrm_AEC1[k];         // copy ADF output to NS input
			}
#else
			__vec_memcpy(OutSignal,TxFrm_AEC1,(FRM_LEN<<1));
			__vec_memcpy(Speech_Tx1,TxFrm_AEC1,(FRM_LEN<<1));
#endif
		}
		else
		{
#ifndef KHW_OPTI_20191216_HIFI
			for (k = 0; k < FRM_LEN; k++)
			{
				Speech_Tx1[k] = TxFrm_AEC1[k];         // copy ADF output to NS input
			}
#else
			__vec_memcpy(Speech_Tx1,TxFrm_AEC1,(FRM_LEN<<1));
#endif
		}
#endif
	}
#if(FLAG_SELECT_C_DSP == 1)
#if(Debug_File_Write_C == 1)
	if (channel == CH_INNER)
	{
		fwrite(Speech_Tx1, sizeof(short), FRM_LEN, fp_debug_AEC_out_inner);
	}
	else
	{
		fwrite(Speech_Tx1, sizeof(short), FRM_LEN, fp_debug_AEC_out_outer1);
		fwrite(Speech_Tx2, sizeof(short), FRM_LEN, fp_debug_AEC_out_outer2);
	}
#endif
#endif
	return;
}
