
#include "Define_config.h"

#if(FLAG_SELECT_C_DSP == 1)
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#endif

#include "SamsungSolomonVoiceW_ANC.h"
#include "SamsungSolomonVoiceW_Int.h"
#include "SamsungSolomonVoiceW_Table.h"
#include "SamsungSolomonVoiceW_basic_op.h"

#include "SamsungSolomonVoiceW_RES_NS.h"

#if(FLAG_SELECT_C_DSP == 1)
extern FILE *fp_inoutVAD;
extern FILE *fp_f0contour;
extern FILE *fp_Wfnlms_new;
extern FILE *fp_debug_ns_vec1, *fp_debug_ns_vec2, *fp_debug_ns_vec3, *fp_debug_ns_vec4, *fp_debug_ns_vec5;
extern FILE *fp_debug_ns_para;
extern FILE *fp_deg_2micBF[N_fp_2micBF_debuffiles];
#endif



static VAD_speechonFlag_inearPWR_NS = 0;



void SolomonVoiceWPreNSInit(PRENSStatus* PRENS_buf, SamsungSolomonVoiceWTxPRENSParam* PreNS_param, COMMONBUF* common_buf, CHANNEL channel)
{
	short k;
	int DVTX_fft_halflen;

	/*********** Buffer *************/
	PRENS_buf->L_tmp256 = (int *)&common_buf->Buff_L_WB;
	PRENS_buf->L_EEoo_07 = (int *)common_buf->gL_EEoo_07;
	PRENS_buf->L_Eoo = common_buf->Buff_L_WB;
	PRENS_buf->L_EEii = common_buf->gL_EEii;

	if (channel == CH_OUTER_1)
	{
		DVTX_fft_halflen = DVTX_FFT_HALFLEN_WB;
		PRENS_buf->tmpf0contour = common_buf->gtmpf0contour;
	}
	else
	{
		DVTX_fft_halflen = DVTX_FFT_HALFLEN_NB;
		PRENS_buf->tmpf0contour = &common_buf->gtmpf0contour[DVTX_M_FFT_HALFLEN_WB];
	}
	PRENS_buf->f0contourAvg = common_buf->gf0contourAvg;
	PRENS_buf->G_NS = (short *)common_buf->Buff_L_NB;

	// f0-based pre NS initialize
	for (k = 0; k < DVTX_fft_halflen; k++)
	{
		PRENS_buf->L_tmp256[k] = 0;
		PRENS_buf->L_EEoo_07[k] = 0;
		PRENS_buf->tmpf0contour[k] = DVTX_MAX_16;
		PRENS_buf->f0contourAvg[k] = DVTX_MAX_16;

		PRENS_buf->L_Eoo[k] = 0;
		PRENS_buf->G_NS[k] = DVTX_MAX_16;
	}

	PRENS_buf->F0flag = 0;
	PRENS_buf->ANCflag = 0;

	/*********** Parameter *************/
	PreNS_param->PreNS_onoff = 1;
	PreNS_param->PARA_wl = 0;
	PreNS_param->PARA_fh = 0;

	return;
}

void SolomonVoiceWNSInit(NSStatus* NS_buf, SamsungSolomonVoiceWTxNSParam* NS_param, COMMONBUF* common_buf, CHANNEL channel)
{
	short i;

	/**** Buffer *****/
	for (i = 0; i < DVTX_NUM_CHAN_WB; i++)
	{

		NS_buf->L_SNRMTX[i][0] = 0;
		NS_buf->L_SNRMTX[i][1] = 0;
		NS_buf->L_SNRMTX[i][2] = 0;
		NS_buf->L_SNRMTX[i][3] = 0;

		NS_buf->L_Npsd[i] = 0;
		NS_buf->L_Npsd_MMSE_ini[i] = 0;
		NS_buf->L_Npsd_MMSE_TMP[i] = 0;
		NS_buf->P_H1_ravg[i] = 0;
		NS_buf->L_SNRpost_prv[i] = 0;
		NS_buf->L_SERpost_prv[i] = 0;
		NS_buf->Gmmse[i] = DVTX_MAX_16;
		NS_buf->Gres[i] = DVTX_MAX_16;
		NS_buf->spp[i] = DVTX_MAX_16;
		NS_buf->L_SNRprio_avg[i] = 0;
		NS_buf->L_SNR_by_Nmmse_ini_avg[i] = 0;
	}
	for (i = 0; i < DVTX_M_Nfft_ceps_WB; i++)
	{
		NS_buf->beta_ceps[i] = 0;
		NS_buf->SNR_ini_ceps_avg[i] = 0;
		NS_buf->SNR_ini_ceps_Fixedavg[i] = 0;
	}

	NS_buf->INDEX_SNRMTX = 0;

	NS_buf->hov_tx_noisefree_cnt = 0;
	NS_buf->noise_floor_offset = 0;
	NS_buf->gain_Npsd = DVTX_MAX_16;

	NS_buf->L_SNR_by_Nmmse_ini = common_buf->ECNSbuff_L_SNR_by_Nmmse_ini;
	NS_buf->L_SNR_by_Nmmse_global = common_buf->ECNSbuff_L_SNR_by_Nmmse_global;

	for (i = 0; i < DVTX_M_NUM_CHAN_WB; i++)
	{
		NS_buf->L_Esqr[i] = 0;
		NS_buf->L_Esqr_q30[i] = 0;
		NS_buf->S_Gns_final[i] = 0;
	}

	NS_buf->L_tmpvec = common_buf->ECNSbuff_L_tmpvec;
	NS_buf->L_tmpvec1 = common_buf->ECNSbuff_L_tmpvec1;
	NS_buf->S_tmpvec = common_buf->ECNSbuff_S_tmpvec;
	NS_buf->S_noise_floor = common_buf->ECNSbuff_S_noise_floor;
	NS_buf->S_spp_ns = common_buf->ECNSbuff_S_spp_ns;

	NS_buf->P_H1 = common_buf->ECNSbuff_P_H1;
	NS_buf->P_H1_GbyL = common_buf->ECNSbuff_P_H1_GbyL;
	NS_buf->L_SNRpost = (int *)common_buf->gE_tx_AEC;
	NS_buf->L_SNRprio = (int *)&common_buf->gE_tx_AEC[80*2];
	NS_buf->L_Dsqr_q30 = (int *)&common_buf->gE_tx_AEC[160*2];
	NS_buf->L_PSD_resiEcho = (int *)&common_buf->gE_tx_AEC[240*2];
	NS_buf->L_SERpost = (int *)common_buf->gE_tx_AECaux;
	NS_buf->L_SERprio = (int *)&common_buf->gE_tx_AECaux[80*2];
	NS_buf->L_EsqrNS = (int *)&common_buf->gE_tx_AECaux[160*2];
	NS_buf->L_EsqrNS_q30 = (int *)&common_buf->gE_tx_AECaux[240*2];
	NS_buf->L_SNR_by_Nmmse_ini_cepsmooth = common_buf->ECNSbuff_L_SNR_by_Nmmse_ini_cepsmooth;
	NS_buf->L_SNR_by_Nmmse_ini_cepsmooth_fix = common_buf->ECNSbuff_L_SNR_by_Nmmse_ini_cepsmooth_fix;
	NS_buf->tmpvec_ceps = common_buf->ECNSbuff_tmpvec_ceps;
	NS_buf->SNR_ini_ceps = common_buf->ECNSbuff_SNR_ini_ceps;
	NS_buf->tmp_beta_ceps = common_buf->ECNSbuff_tmp_beta_ceps;

	if (channel == CH_OUTER_1)
	{
		NS_buf->L_RRBin_step = common_buf->gL_RRBin_step;
	}
	else
	{
		NS_buf->L_RRBin_step = &common_buf->gL_RRBin_step[DVTX_M_FFT_HALFLEN_WB];
	}


	/***** Param ******/
	NS_param->PARA_ns_level = 0;

	NS_param->PARA_HangOver_Cnt_NoiseFree = 0;
	NS_param->PARA_Gain_EchoPSD_NS = 0;	// Echo psd gain for Noisd psd calculation 0 to 32767 q15
	NS_param->PARA_xi_for_SPP_Table = 0;	// 0 to 15 [dB] scale
	NS_param->PARA_Npsd_Gain_MIN = 0;	//	Npsd	gain	in	silence	interval
	NS_param->PARA_NoiseFloor_Offset_MAX = 0;	//	Gain	floor	offset	in	silence	interval
	NS_param->PARA_MIN_CHAN_PWR = 0;
	NS_param->PARA_MIN_NOISE_PWR = 0;
	NS_param->PARA_NoiseFloorOffset_0_250Hz_low = 0;		// 0.2 Q15
	NS_param->PARA_NoiseFloorOffset_0_250Hz_high = 0;		// 0.25 Q15
	NS_param->PARA_NoiseFloorOffset_250_4000Hz_low = 0;	// 0.12 Q15
	NS_param->PARA_NoiseFloorOffset_250_4000Hz_high = 0;	// 0.3 Q15
	NS_param->PARA_NoiseFloorOffset_4000_8000Hz_low = 0;	// 0.04 Q15
	NS_param->PARA_NoiseFloorOffset_4000_8000Hz_high = 0;	// 0.3 Q15
	NS_param->PARA_THD_Pwr_Lo_1k_4k = 0;
	NS_param->PARA_THD_Pwr_Lo_1k_4k_lowbit = 0;
	NS_param->PARA_THD_Pwr_Lo_1k_4k_highbit = 0;
	NS_param->PARA_Slop_SNRiniAvg_for_beta = 0;
	NS_param->PARA_THD_Lo_SNRiniAvg_for_beta = 0;
	NS_param->PARA_THD_Lo_SNRiniAvg_for_beta_lowbit = 0;
	NS_param->PARA_THD_Lo_SNRiniAvg_for_beta_highbit = 0;
	NS_param->PARA_THD_Hi_SNRiniAvg_for_beta = 0;
	NS_param->PARA_THD_Hi_SNRiniAvg_for_beta_lowbit = 0;
	NS_param->PARA_THD_Hi_SNRiniAvg_for_beta_highbit = 0;
	NS_param->PARA_slope_prioriSNR_for_NoiseFloor = 0;
	NS_param->PARA_THD_Lo_prioriSNR_for_NoiseFloor = 0;
	NS_param->PARA_THD_Lo_prioriSNR_for_NoiseFloor_lowbit = 0;
	NS_param->PARA_THD_Lo_prioriSNR_for_NoiseFloor_highbit = 0;
	NS_param->PARA_THD_Hi_prioriSNR_for_NoiseFloor = 0;
	NS_param->PARA_THD_Hi_prioriSNR_for_NoiseFloor_lowbit = 0;
	NS_param->PARA_THD_Hi_prioriSNR_for_NoiseFloor_highbit = 0;
	for (i = 0; i < DVTX_M_NUM_CHAN_WB; i++)
	{
		NS_param->PARA_FixedXi[i][0] = 0;
		NS_param->PARA_FixedXi[i][1] = 0;
		NS_param->PARA_FixedXi[i][2] = 0;
		NS_param->PARA_FixedXi_iniSNR[i] = 0;
		NS_param->PARA_FixedXi_srtSNR[i] = 0;
		NS_param->PARA_FixedXi_lotSNR[i] = 0;
	}

	NS_param->PARA_reserved_4 = 1; // flag NS on off
	NS_param->PARA_reserved_61 = 0;  // PARA_post_fDRC_OnOff_FLAG : 0(off), 1(on)
	NS_param->PARA_reserved_62 = 0;// PARA_THD_TxPwr_LOWER
	NS_param->PARA_reserved_63 = 0;  // PARA_THD_TxPwr_UPPER
	NS_param->PARA_reserved_64 = 0; // PARA_fDRC_SNT_Gain : Rx off fDRC gain
	NS_param->PARA_reserved_65 = 0;

	NS_param->PARA_reserved_66 = 0;
	NS_param->PARA_reserved_67 = 0;
	NS_param->PARA_reserved_68 = 0;
	NS_param->PARA_reserved_69 = 0;
	NS_param->PARA_reserved_70 = 0;
	NS_param->PARA_reserved_71 = 0;
	NS_param->PARA_reserved_72 = 0;
	NS_param->PARA_reserved_73 = 0;
	NS_param->PARA_reserved_74 = 0;
	NS_param->PARA_reserved_75 = 0;
	NS_param->PARA_reserved_76 = 0;
	NS_param->PARA_reserved_77 = 0;
	NS_param->PARA_reserved_78 = 0;
	NS_param->PARA_reserved_79 = 0;
	NS_param->PARA_reserved_80 = 0;

	return;
}

void SolomonVoiceW_RES_ParamConfig(SamsungSolomonVoiceWTxRESParam* RES_param, RESStatus *RES_buf, SamsungSolomonVoiceWTxRESParam* param, CHANNEL channel)
{
	short i;
	
	RES_param->PARA_reserved_2 = param->PARA_reserved_2;
	RES_param->PARA_reserved_3 = param->PARA_reserved_3;
	RES_param->PARA_Gain_EchoPSD_RES = param->PARA_Gain_EchoPSD_RES;
	RES_param->PARA_NoiseFloor_RES = param->PARA_NoiseFloor_RES;
	for (i = 0; i < 40; i++)
		RES_param->PARA_Gain_Echo_PSD[i] = param->PARA_Gain_Echo_PSD[i];

	RES_param->PARA_reserved_31 = param->PARA_reserved_31;
	RES_param->PARA_reserved_32 = param->PARA_reserved_32;

	RES_param->PARA_reserved_41 = param->PARA_reserved_41;
	RES_param->PARA_reserved_42 = param->PARA_reserved_42;
	RES_param->PARA_reserved_43 = param->PARA_reserved_43;
	RES_param->PARA_reserved_44 = param->PARA_reserved_44;
	RES_param->PARA_reserved_45 = param->PARA_reserved_45;
	RES_param->PARA_reserved_46 = param->PARA_reserved_46;
	RES_param->PARA_reserved_47 = param->PARA_reserved_47;
	RES_param->PARA_reserved_48 = param->PARA_reserved_48;
	RES_param->PARA_reserved_49 = param->PARA_reserved_49;
	RES_param->PARA_reserved_50 = param->PARA_reserved_50;
	RES_param->PARA_reserved_51 = param->PARA_reserved_51;
	RES_param->PARA_reserved_52 = param->PARA_reserved_52;
	RES_param->PARA_reserved_53 = param->PARA_reserved_53;
	RES_param->PARA_reserved_54 = param->PARA_reserved_54;
	RES_param->PARA_reserved_55 = param->PARA_reserved_55;
	RES_param->PARA_reserved_56 = param->PARA_reserved_56;
	RES_param->PARA_reserved_57 = param->PARA_reserved_57;
	RES_param->PARA_reserved_58 = param->PARA_reserved_58;
	RES_param->PARA_reserved_59 = param->PARA_reserved_59;
	RES_param->PARA_reserved_60 = param->PARA_reserved_60;

	if (channel == CH_INNER)
	{
		for (i = 0; i < DVTX_M_FFT_HALFLEN_NB; i++) {
			RES_buf->W_fnlms_reression[i] = RES_param->PARA_reserved_46;
			RES_buf->W_fnlms_reression2[i] = RES_param->PARA_reserved_46;
		}
	}
	else
	{
		for (i = 0; i < DVTX_M_FFT_HALFLEN_WB; i++) {
			RES_buf->W_fnlms_reression[i] = RES_param->PARA_reserved_46;
			RES_buf->W_fnlms_reression2[i] = RES_param->PARA_reserved_46;
		}
	}

	return;
}

void SolomonVoiceWRESInit(RESStatus *RES_buf, SamsungSolomonVoiceWTxRESParam* RES_param, COMMONBUF* common_buf, CHANNEL channel)
{
	short i;

	/**** Buffer *****/
	for (i = 0; i < DVTX_M_NUM_CHAN_WB; i++) {
		RES_buf->L_Esqr_ravg_silence[i] = 0;
		RES_buf->L_Dsqr_ravg[i] = 0;
	}

	RES_buf->GmmseNFFT = (short *)common_buf->Buff_L_NB;

	//RES_buf->L_DDBin2 = NULL;
	
	RES_buf->L_RRBin = common_buf->Buff_L_WB;
	RES_buf->S_tmpfft1 = common_buf->gS_tmpfft1;
	RES_buf->CntFrmRxVADon = 0;

	// FNLMS
	if (channel == CH_OUTER_1)
	{
		RES_buf->L_DDBin = common_buf->gL_DDBin;
		RES_buf->L_EEBin = common_buf->gL_EEBin;
		RES_buf->Gpwrres = common_buf->gGpwrres;
		RES_buf->W_fnlms_reression = common_buf->gW_fnlms_reression;
		RES_buf->W_fnlms_reression2 = common_buf->gW_fnlms_reression2;
		RES_buf->G_fnlms = common_buf->gG_fnlms;

		for (i = 0; i < DVTX_M_FFT_HALFLEN_WB; i++) {
			RES_buf->Gpwrres[i] = DVTX_MAX_16;
			RES_buf->W_fnlms_reression[i] = 0;
			RES_buf->W_fnlms_reression2[i] = 0;
			RES_buf->G_fnlms[i] = DVTX_MAX_16;
		}
	}
	else {
		RES_buf->L_DDBin = &common_buf->gL_DDBin[DVTX_M_FFT_HALFLEN_WB];
		RES_buf->L_EEBin = &common_buf->gL_EEBin[DVTX_M_FFT_HALFLEN_WB];
		RES_buf->Gpwrres = &common_buf->gGpwrres[DVTX_M_FFT_HALFLEN_WB];
		RES_buf->W_fnlms_reression = &common_buf->gW_fnlms_reression[DVTX_M_FFT_HALFLEN_WB];
		RES_buf->W_fnlms_reression2 = &common_buf->gW_fnlms_reression2[DVTX_M_FFT_HALFLEN_WB];
		RES_buf->G_fnlms = &common_buf->gG_fnlms[DVTX_M_FFT_HALFLEN_WB];

		for (i = 0; i < DVTX_M_FFT_HALFLEN_NB; i++) {
			RES_buf->Gpwrres[i] = DVTX_MAX_16;
			RES_buf->W_fnlms_reression[i] = 20000;
			RES_buf->W_fnlms_reression2[i] = 20000;
			RES_buf->G_fnlms[i] = DVTX_MAX_16;
		}
	}

	RES_buf->Cnt_Cascade_tx_silent_frames = 0;

	RES_buf->Gain_echo_PSD_RES = DVTX_MAX_16;


	/***** Param ******/
	RES_param->PARA_Gain_EchoPSD_RES = 0;
	RES_param->PARA_NoiseFloor_RES = 0;
	for (i = 0; i < DVTX_M_NUM_CHAN_WB; i++)
		RES_param->PARA_Gain_Echo_PSD[i] = 0;

	RES_param->PARA_reserved_2 = 1; // flag FNLMS on off
	RES_param->PARA_reserved_3 = 1; // flag RES on off
	RES_param->PARA_reserved_31 = 0;// PARA_RESgainlIMIT_IniRxSigOnSet
	RES_param->PARA_reserved_32 = 0;// PARA_RES_prioSNRga in ST interval : not used

	RES_param->PARA_reserved_41 = 0;	// Fadf oversubtraction bit sifht 0~1kHz
	RES_param->PARA_reserved_42 = 0;	// Fadf oversubtraction bit sifht 1~4kHz
	RES_param->PARA_reserved_43 = 0;	// Fadf oversubtraction bit sifht 4~8kHz
	RES_param->PARA_reserved_44 = 0;	// over Rx psd estimation for single NET flag
	RES_param->PARA_reserved_45 = 0;	// single NET flag, Wiener gain THD 0~1.0
	RES_param->PARA_reserved_46 = 0;	// Wfnlms ini value
	RES_param->PARA_reserved_47 = 0; // reserved
	RES_param->PARA_reserved_48 = 0;
	RES_param->PARA_reserved_49 = 0;
	RES_param->PARA_reserved_50 = 0;
	RES_param->PARA_reserved_51 = 0;
	RES_param->PARA_reserved_52 = 0;
	RES_param->PARA_reserved_53 = 0;
	RES_param->PARA_reserved_54 = 0;
	RES_param->PARA_reserved_55 = 0;
	RES_param->PARA_reserved_56 = 0;
	RES_param->PARA_reserved_57 = 0;
	RES_param->PARA_reserved_58 = 0;
	RES_param->PARA_reserved_59 = 0;
	RES_param->PARA_reserved_60 = 0;

	return;
}

#if 0//#ifdef __EXE_ANC__
void SolomonVoiceWANCInit(ANCStatus* ANC_buf, SamsungSolomonVoiceWTxANCParam* ANC_param, COMMONBUF* common_buf, CHANNEL channel)
{
	short k;

	/************** Buffer **************/
	if (channel == CH_OUTER_1)
	{
		ANC_buf->ANC_sigPwr = common_buf->gANC_sigPwr;
		//ANC_buf->ANC_sigPwr_inner = common_buf->gANC_sigPwr_inner;
		ANC_buf->Enhenced_Signal = common_buf->gEnhenced_Signal;
		ANC_buf->ANC_W_Filter = common_buf->gANC_W_Filter;
	}
	else
	{
		ANC_buf->ANC_sigPwr = &common_buf->gANC_sigPwr[DVTX_M_FFT_HALFLEN_WB];
		//ANC_buf->ANC_sigPwr_inner = common_buf->gANC_sigPwr_inner/*+DVTX_M_FFT_HALFLEN_WB*/;
		ANC_buf->Enhenced_Signal = &common_buf->gEnhenced_Signal[DVTX_M_FFT_LEN_WB];
		ANC_buf->ANC_W_Filter = &common_buf->gANC_W_Filter[DVTX_M_FFT_LEN_WB];
	}

	for (k = 0; k < DVTX_M_FFT_HALFLEN_WB; k++)
	{
		ANC_buf->Aeq[k] = 16384;
	}

	/************ Parameter *************/

	ANC_param->ANC_onoff = 1;

	ANC_param->fl = 0;
	ANC_param->fh = 0;
	ANC_param->mu_in = 2621;		//0.01 in Q18
	ANC_param->mu_out = 2621;		//0.01 in Q18

	return;
}
#endif

void SolomonVoiceW_ANC_ParamConfig(SamsungSolomonVoiceWTxANCParam* ANC_param, SamsungSolomonVoiceWTxANCParam* param)
{

	ANC_param->ANC_onoff = param->ANC_onoff;

	return;
}

void SolomonVoiceW_PreNS_ParamConfig(SamsungSolomonVoiceWTxPRENSParam* PreNS_param, SamsungSolomonVoiceWTxPRENSParam* param)
{

	PreNS_param->PreNS_onoff = param->PreNS_onoff;

	return;
}

void SolomonVoiceW_NS_ParamConfig(SamsungSolomonVoiceWTxNSParam* NS_param, SamsungSolomonVoiceWTxNSParam* param)
{
	short i;

	NS_param->PARA_ns_level = param->PARA_ns_level;

	NS_param->PARA_HangOver_Cnt_NoiseFree = param->PARA_HangOver_Cnt_NoiseFree;
	NS_param->PARA_Gain_EchoPSD_NS = param->PARA_Gain_EchoPSD_NS;
	NS_param->PARA_xi_for_SPP_Table = param->PARA_xi_for_SPP_Table;
	NS_param->PARA_Npsd_Gain_MIN = param->PARA_Npsd_Gain_MIN;
	NS_param->PARA_NoiseFloor_Offset_MAX = param->PARA_NoiseFloor_Offset_MAX;
	NS_param->PARA_MIN_CHAN_PWR = param->PARA_MIN_CHAN_PWR;
	NS_param->PARA_MIN_NOISE_PWR = param->PARA_MIN_NOISE_PWR;
	NS_param->PARA_NoiseFloorOffset_0_250Hz_low = param->PARA_NoiseFloorOffset_0_250Hz_low;
	NS_param->PARA_NoiseFloorOffset_0_250Hz_high = param->PARA_NoiseFloorOffset_0_250Hz_high;
	NS_param->PARA_NoiseFloorOffset_250_4000Hz_low = param->PARA_NoiseFloorOffset_250_4000Hz_low;
	NS_param->PARA_NoiseFloorOffset_250_4000Hz_high = param->PARA_NoiseFloorOffset_250_4000Hz_high;
	NS_param->PARA_NoiseFloorOffset_4000_8000Hz_low = param->PARA_NoiseFloorOffset_4000_8000Hz_low;
	NS_param->PARA_NoiseFloorOffset_4000_8000Hz_high = param->PARA_NoiseFloorOffset_4000_8000Hz_high;

	NS_param->PARA_THD_Pwr_Lo_1k_4k = ((param->PARA_THD_Pwr_Lo_1k_4k_highbit << 16) + (param->PARA_THD_Pwr_Lo_1k_4k_lowbit & 0x0000ffff));
	NS_param->PARA_THD_Pwr_Lo_1k_4k_lowbit = param->PARA_THD_Pwr_Lo_1k_4k_lowbit;
	NS_param->PARA_THD_Pwr_Lo_1k_4k_highbit = param->PARA_THD_Pwr_Lo_1k_4k_highbit;
	NS_param->PARA_Slop_SNRiniAvg_for_beta = param->PARA_Slop_SNRiniAvg_for_beta;

	NS_param->PARA_THD_Lo_SNRiniAvg_for_beta = ((param->PARA_THD_Lo_SNRiniAvg_for_beta_highbit << 16) + (param->PARA_THD_Lo_SNRiniAvg_for_beta_lowbit & 0x0000ffff));
	NS_param->PARA_THD_Hi_SNRiniAvg_for_beta = ((param->PARA_THD_Hi_SNRiniAvg_for_beta_highbit << 16) + (param->PARA_THD_Hi_SNRiniAvg_for_beta_lowbit & 0x0000ffff));
	NS_param->PARA_THD_Lo_SNRiniAvg_for_beta_lowbit = param->PARA_THD_Lo_SNRiniAvg_for_beta_lowbit;
	NS_param->PARA_THD_Lo_SNRiniAvg_for_beta_highbit = param->PARA_THD_Lo_SNRiniAvg_for_beta_highbit;
	NS_param->PARA_THD_Hi_SNRiniAvg_for_beta_lowbit = param->PARA_THD_Hi_SNRiniAvg_for_beta_lowbit;
	NS_param->PARA_THD_Hi_SNRiniAvg_for_beta_highbit = param->PARA_THD_Hi_SNRiniAvg_for_beta_highbit;

	NS_param->PARA_THD_Lo_prioriSNR_for_NoiseFloor = ((param->PARA_THD_Lo_prioriSNR_for_NoiseFloor_highbit << 16) + (param->PARA_THD_Lo_prioriSNR_for_NoiseFloor_lowbit & 0x0000ffff));
	NS_param->PARA_THD_Hi_prioriSNR_for_NoiseFloor = ((param->PARA_THD_Hi_prioriSNR_for_NoiseFloor_highbit << 16) + (param->PARA_THD_Hi_prioriSNR_for_NoiseFloor_lowbit & 0x0000ffff));
	NS_param->PARA_THD_Lo_prioriSNR_for_NoiseFloor_lowbit = param->PARA_THD_Lo_prioriSNR_for_NoiseFloor_lowbit;
	NS_param->PARA_THD_Lo_prioriSNR_for_NoiseFloor_highbit = param->PARA_THD_Lo_prioriSNR_for_NoiseFloor_highbit;
	NS_param->PARA_THD_Hi_prioriSNR_for_NoiseFloor_lowbit = param->PARA_THD_Hi_prioriSNR_for_NoiseFloor_lowbit;
	NS_param->PARA_THD_Hi_prioriSNR_for_NoiseFloor_highbit = param->PARA_THD_Hi_prioriSNR_for_NoiseFloor_highbit;
	NS_param->PARA_slope_prioriSNR_for_NoiseFloor = param->PARA_slope_prioriSNR_for_NoiseFloor;

	for (i = 0; i < 40; i++) {
		NS_param->PARA_FixedXi[i][0] = param->PARA_FixedXi_iniSNR[i];
		NS_param->PARA_FixedXi[i][1] = param->PARA_FixedXi_srtSNR[i];
		NS_param->PARA_FixedXi[i][2] = param->PARA_FixedXi_lotSNR[i];
	}

	NS_param->PARA_reserved_4 = param->PARA_reserved_4;
	NS_param->PARA_reserved_61 = param->PARA_reserved_61;
	NS_param->PARA_reserved_62 = param->PARA_reserved_62;
	NS_param->PARA_reserved_63 = param->PARA_reserved_63;
	NS_param->PARA_reserved_64 = param->PARA_reserved_64;
	NS_param->PARA_reserved_65 = param->PARA_reserved_65;

	NS_param->PARA_reserved_66 = param->PARA_reserved_66;
	NS_param->PARA_reserved_67 = param->PARA_reserved_67;
	NS_param->PARA_reserved_68 = param->PARA_reserved_68;
	NS_param->PARA_reserved_69 = param->PARA_reserved_69;
	NS_param->PARA_reserved_70 = param->PARA_reserved_70;
	NS_param->PARA_reserved_71 = param->PARA_reserved_71;
	NS_param->PARA_reserved_72 = param->PARA_reserved_72;
	NS_param->PARA_reserved_73 = param->PARA_reserved_73;
	NS_param->PARA_reserved_74 = param->PARA_reserved_74;
	NS_param->PARA_reserved_75 = param->PARA_reserved_75;
	NS_param->PARA_reserved_76 = param->PARA_reserved_76;
	NS_param->PARA_reserved_77 = param->PARA_reserved_77;
	NS_param->PARA_reserved_78 = param->PARA_reserved_78;
	NS_param->PARA_reserved_79 = param->PARA_reserved_79;
	NS_param->PARA_reserved_80 = param->PARA_reserved_80;

	return;
}



#ifdef Right_Shift_vecter_OPT_DSP
void Right_Shift_vecter(short * in, short * out, int shift, int len) // in(i ), out(out)
{
	ae_valign align1, align2;
	ae_int16x4 *pt1, *pt2;
	ae_int16x4 A;
	int i;
	pt1=(ae_int16x4 *)in;
	pt2=(ae_int16x4 *)out;
	align1 = AE_LA64_PP(pt1);
	align2 = AE_ZALIGN64();
	for (i = 0; i < len; i+=4)
	{
		AE_LA16X4_IP(A, align1, pt1);
		A = AE_SRAA16RS(A, shift);
		AE_SA16X4_IP(A, align2, pt2);
	}
	AE_SA64POS_FP(align2, pt2);
}
#endif


#ifdef Multi_vecter_OPT_DSP
void Multi_vecter(short * in1, short * in2, int len)   // in1(i,o), in2(i)
{
	ae_f16x4 *pt1, *pt2, *pt3;
	ae_f16x4 A1, A2;
	ae_valign align1, align2, align3;

	int i;
	pt1=(ae_f16x4 *)in1;
	pt2=(ae_f16x4 *)in2;
	pt3=(ae_f16x4 *)in1;
	align1 = AE_LA64_PP(pt1);
	align2 = AE_LA64_PP(pt2);
	align3 = AE_ZALIGN64();

	for (i = 0; i < len; i+=4)
	{
		AE_LA16X4_IP(A1,align1, pt1);
		AE_LA16X4_IP(A2,align2, pt2);
		A1 = AE_MULFP16X4RAS(A1, A2);
		AE_SA16X4_IP(A1,align3, pt3);
	}
	AE_SA64POS_FP(align3, pt3);

}
#endif


#ifndef fn_fDRC_OPT_DSP
void fn_fDRC(AECStatus* AEC_buf, RESStatus* RES_buf, SamsungSolomonVoiceWTxNSParam* NS_param, short* data_buffer, short FFT_HALFLEN, short BLK_NORM, CHANNEL channel)
{
	short tmp;
	int i, j;
	int  enrgE;

	if (NS_param->PARA_reserved_61 == 1) // post fDRC on/off flag
	{
		//power calculation

		for (i = 0; i < FFT_HALFLEN; i++)
		{
			j = 2 * i;
			enrgE = DVTXOP_L_mult(data_buffer[j], data_buffer[j]);        //Q15,0*Q15,0 = Q30,1
			RES_buf->L_EEBin[i] = DVTXOP_L_shl(DVTXOP_L_mac(enrgE, data_buffer[j + 1], data_buffer[j + 1]), (short)(NS_param->PARA_reserved_65 - (2 * BLK_NORM)));/*30,1 -> 23,8*/

		}

		// post gain setting
		if (AEC_buf->Flag_RxVAD_AEC == 1)
			tmp = 0;
		else
			tmp = NS_param->PARA_reserved_64;
		// post fDRC gain calculation
		for (i = 0; i < FFT_HALFLEN; i++)
		{
			if (RES_buf->L_EEBin[i] > NS_param->PARA_reserved_62)
			{
				if (RES_buf->L_EEBin[i] < NS_param->PARA_reserved_63)
					RES_buf->S_tmpfft1[i] = tmp;
				else
					RES_buf->S_tmpfft1[i] = DVTX_MAX_16;
			}
			else
				RES_buf->S_tmpfft1[i] = DVTX_MAX_16;
		}
		for (i = 0; i < FFT_HALFLEN; i++)
		{
			data_buffer[2 * i] = DVTXOP_mult_r(data_buffer[2 * i], RES_buf->S_tmpfft1[i]);
			data_buffer[2 * i + 1] = DVTXOP_mult_r(data_buffer[2 * i + 1], RES_buf->S_tmpfft1[i]);
			////hard 0
			//if (RES_buf->S_tmpfft1[i] == tmp)
			//{
			//	data_buffer[2 * i] = 0;
			//	data_buffer[2 * i + 1] = 0;
			//}
		}

	}

	return;
}
#else
void fn_fDRC(AECStatus* AEC_buf, RESStatus* RES_buf, SamsungSolomonVoiceWTxNSParam* NS_param, short* data_buffer, short FFT_HALFLEN, short BLK_NORM, CHANNEL channel)
{	
	short tmp, shift;
	int i, j;
	int  enrgE;
	ae_f16x4 *pt1, *pt2;
	ae_f16x4 A1, A2;
	ae_f32x2 L_tmp1, L_tmp2, L_tmp3;
	ae_f32x2 *pOut;
	ae_valign alignout, alignin;

	if (NS_param->PARA_reserved_61 == 1) // post fDRC on/off flag
	{
		//power calculation

		pt1=(ae_f16x4 *)data_buffer;
		pt2=(ae_f32x2 *)RES_buf->L_EEBin;
		shift = (short)(NS_param->PARA_reserved_65 - (2 * BLK_NORM));
		alignout = AE_ZALIGN64();
		alignin = AE_LA64_PP(pt1);

		for (i = 0; i < FFT_HALFLEN; i+= 2)
		{
			AE_LA16X4_IP(A1, alignin, pt1);
			AE_MULF16X4SS(L_tmp1, L_tmp2, A1, A1);
			L_tmp3 = AE_SEL32_LH(L_tmp2, L_tmp1);
			L_tmp1 = AE_ADD32S(L_tmp1, L_tmp3);

			L_tmp3 = AE_SEL32_LH(L_tmp2, L_tmp2);
			L_tmp2 = AE_ADD32S(L_tmp2, L_tmp3);
			L_tmp1 = AE_SEL32_LL(L_tmp1, L_tmp2);

			L_tmp1 = AE_SLAA32S(L_tmp1, shift);
			AE_SA32X2_IP(L_tmp1, alignout, pt2);
		}
		AE_SA64POS_FP(alignout, pt2);


		// post gain setting
		if (AEC_buf->Flag_RxVAD_AEC == 1)
			tmp = 0;
		else
			tmp = NS_param->PARA_reserved_64;
		// post fDRC gain calculation

		for (i = 0; i < FFT_HALFLEN; i++)
		{
			RES_buf->S_tmpfft1[i] = DVTX_MAX_16;
			if (RES_buf->L_EEBin[i] > NS_param->PARA_reserved_62)
			{
				if (RES_buf->L_EEBin[i] < NS_param->PARA_reserved_63)
					RES_buf->S_tmpfft1[i] = tmp;
			}

		}


		{
		    ae_f16x4 *ae_pb1, *ae_pb2, *ae_pg;
			ae_f16x4 ae_bin1, ae_bin2, ae_gain1, ae_gain2, /*zerov,*/ tmpv;
			ae_valign ae_alignpb1, ae_alignpb2, ae_alignpg;
			xtbool4 fbool4;
			ae_pb1 = (ae_f16x4 *)data_buffer;
			ae_pb2 = (ae_f16x4 *)data_buffer;
			ae_pg = (ae_f16x4 *)RES_buf->S_tmpfft1;
			ae_alignpb1 = AE_LA64_PP(ae_pb1);
			ae_alignpb2 = AE_ZALIGN64();
			ae_alignpg = AE_LA64_PP(ae_pg);
			//zerov = AE_ZERO16();
			tmpv = AE_MOVDA16(tmp);
		    for (i = 0; i < FFT_HALFLEN; i+= 4)
		    {
				AE_LA16X4_IP(ae_gain1, ae_alignpg, ae_pg);
				AE_LA16X4_IP(ae_bin1, ae_alignpb1, ae_pb1);
				ae_gain2 = AE_SEL16_7362(ae_gain1, ae_gain1);
				AE_LA16X4_IP(ae_bin2, ae_alignpb1, ae_pb1);
				ae_gain1 = AE_SEL16_5410(ae_gain1, ae_gain1);
				ae_gain1 = AE_SEL16_7362(ae_gain1, ae_gain1);
				ae_bin1 = AE_MULFP16X4RAS(ae_bin1, ae_gain2);
				ae_bin2 = AE_MULFP16X4RAS(ae_bin2, ae_gain1);

				/*fbool4 = AE_EQ16(ae_gain2, tmp);
				AE_MOVT16X4(ae_bin1, zerov, fbool4);
				fbool4 = AE_EQ16(ae_gain1, tmp);
				AE_MOVT16X4(ae_bin2, zerov, fbool4);*/

				AE_SA16X4_IP(ae_bin1, ae_alignpb2, ae_pb2);
				AE_SA16X4_IP(ae_bin2, ae_alignpb2, ae_pb2);
		    }
		    AE_SA64POS_FP(ae_alignpb2, ae_pb2);
		}
	}

	return;
}
#endif
#ifndef fx_SolomonVoice_Npsd_ini_calculation_OPT_DSP
void fx_SolomonVoice_Npsd_ini_calculation(int *outSNR, int *outSNRtmp, short *PH1, int *EE, short Nband, short betaA, short betaB)
{
	short i, forgetOld, forgetNew;
	int Ltmp;

	short band_low;
	band_low = 21; //22 2500Hz, DVTX_M_NUM_CHAN_NB

	for (i = 0; i < band_low; i++)
	{	//Npsd tmp		
		{
			forgetOld = DVTX_MAX(PH1[i], betaA);
			forgetNew = DVTXOP_sub(DVTX_MAX_16, forgetOld);

			outSNRtmp[i] = fx_SolomonVoice_recursiveAVG_ls(outSNRtmp[i], EE[i], forgetOld, forgetNew, 0, 0);//Q23.8
		}

		//Npsd_ini		
		forgetOld = betaB;
		forgetNew = DVTXOP_sub(DVTX_MAX_16, forgetOld);
		Ltmp = fx_SolomonVoice_recursiveAVG_ls(outSNR[i], outSNRtmp[i], forgetOld, forgetNew, 0, 0);//Q23.8
		outSNR[i] = DVTX_MAX(Ltmp, 1);
	}
	for (i = band_low; i <= Nband; i++)
	{	//Npsd tmp
		{
			forgetOld = DVTX_MAX(PH1[i], DVTX_WORD16_0_95);
			forgetNew = DVTXOP_sub(DVTX_MAX_16, forgetOld);

			outSNRtmp[i] = fx_SolomonVoice_recursiveAVG_ls(outSNRtmp[i], EE[i], forgetOld, forgetNew, 0, 0);//Q23.8
		}

		//Npsd_ini
		forgetOld = DVTX_WORD16_0_95;
		forgetNew = DVTXOP_sub(DVTX_MAX_16, forgetOld);
		Ltmp = fx_SolomonVoice_recursiveAVG_ls(outSNR[i], outSNRtmp[i], forgetOld, forgetNew, 0, 0);//Q23.8
		outSNR[i] = DVTX_MAX(Ltmp, 1);
	}
}
#else
ae_int32x2 fx_SolomonVoice_recursiveAVG_ls_2_vector(ae_int32x2 OldVal, ae_int32x2 NewVal, ae_int16x4 beOld, ae_int16x4 beNew, short shift);
void fx_SolomonVoice_Npsd_ini_calculation(int *outSNR, int *outSNRtmp, short *PH1, int *EE, short Nband, short betaA, short betaB)
{
	short i, num, forgetOld, forgetNew, forgetNew1;
	int Ltmp;
	short band_low = 21;//22 2500Hz, DVTX_M_NUM_CHAN_NB
	ae_int16x4 LforgetOld1, LforgetNew1, LforgetOld2, LforgetNew2, LDVTX;
	ae_int16x4 LbetaA, LbetaB, tmp1 ;
	ae_int32x2 Ltmp1, Ltmp2, Ltmp3, Lset;
	ae_int32x2 *poutSNR_in, *poutSNR_out, *poutSNRtmp_in, *poutSNRtmp_out, *pEE;
	ae_int16x4 *pPH1;
	xtbool4 bool4;
	ae_valign align_outSNR_in, align_outSNR_out, align_outSNRtmp_in, align_outSNRtmp_out, align_EE, align_PH1;
	poutSNR_in = poutSNR_out = (ae_int32x2 *)&outSNR[0];
	poutSNRtmp_in = poutSNRtmp_out = (ae_int32x2 *)&outSNRtmp[0];
	pEE = (ae_int32x2 *)&EE[0];
	pPH1 = (ae_int16x4 *)&PH1[0];
	align_outSNR_in = AE_LA64_PP(poutSNR_in);
	align_outSNRtmp_in = AE_LA64_PP(poutSNRtmp_in);
	align_EE = AE_LA64_PP(pEE);
	align_PH1 = AE_LA64_PP(pPH1);
	align_outSNR_out = AE_ZALIGN64();
	align_outSNRtmp_out = AE_ZALIGN64();
	num = band_low / 4;
	LDVTX = AE_MOVDA16(DVTX_MAX_16);
	LbetaA = AE_MOVDA16(betaA);
	LforgetOld2 = AE_MOVDA16(betaB);
	LforgetNew2 = AE_SUB16S(LDVTX, LforgetOld2);
	Lset = AE_MOVDA32(1);
	for(i = 0; i < num; i++)
	{
		AE_LA16X4_IP(LforgetOld1, align_PH1, pPH1);
		bool4 = AE_LT16(LforgetOld1, LbetaA);
		AE_MOVT16X4(LforgetOld1, LbetaA, bool4);
		LforgetNew1 = AE_SUB16S(LDVTX, LforgetOld1);
		AE_LA32X2_IP(Ltmp1, align_outSNRtmp_in, poutSNRtmp_in);
		AE_LA32X2_IP(Ltmp2, align_EE, pEE);
		Ltmp3 = fx_SolomonVoice_recursiveAVG_ls_2_vector(Ltmp1, Ltmp2, LforgetOld1, LforgetNew1, 0);
		AE_SA32X2_IP(Ltmp3, align_outSNRtmp_out, poutSNRtmp_out);
		AE_LA32X2_IP(Ltmp1, align_outSNR_in, poutSNR_in);
		Ltmp2 = fx_SolomonVoice_recursiveAVG_ls_2_vector(Ltmp1, Ltmp3, LforgetOld2, LforgetNew2, 0);
		Ltmp2 = AE_MAX32(Ltmp2, Lset);
		AE_SA32X2_IP(Ltmp2, align_outSNR_out, poutSNR_out);
		AE_LA32X2_IP(Ltmp1, align_outSNRtmp_in, poutSNRtmp_in);
		AE_LA32X2_IP(Ltmp2, align_EE, pEE);
		LforgetOld1 = AE_SEL16_5432(LforgetOld1, LforgetOld1);
		LforgetNew1 = AE_SEL16_5432(LforgetNew1, LforgetNew1);
		Ltmp3 = fx_SolomonVoice_recursiveAVG_ls_2_vector(Ltmp1, Ltmp2, LforgetOld1, LforgetNew1, 0);
		AE_SA32X2_IP(Ltmp3, align_outSNRtmp_out, poutSNRtmp_out);
		AE_LA32X2_IP(Ltmp1, align_outSNR_in, poutSNR_in);
		Ltmp2 = fx_SolomonVoice_recursiveAVG_ls_2_vector(Ltmp1, Ltmp3, LforgetOld2, LforgetNew2, 0);
		Ltmp2 = AE_MAX32(Ltmp2, Lset);
		AE_SA32X2_IP(Ltmp2, align_outSNR_out, poutSNR_out);
	}
	AE_SA64POS_FP(align_outSNRtmp_out, poutSNRtmp_out);
	AE_SA64POS_FP(align_outSNR_out, poutSNR_out);
	forgetNew1 = DVTXOP_sub(DVTX_MAX_16, betaB);
	for(i = 4 * num; i < band_low; i++)
	{
		//Npsd tmp
		{
			forgetOld = DVTX_MAX(PH1[i], betaA);
			forgetNew = DVTXOP_sub(DVTX_MAX_16, forgetOld);
			outSNRtmp[i] = fx_SolomonVoice_recursiveAVG_ls(outSNRtmp[i], EE[i], forgetOld, forgetNew, 0, 0);//Q23.8
		}
		//Npsd_ini
		Ltmp = fx_SolomonVoice_recursiveAVG_ls(outSNR[i], outSNRtmp[i], betaB, forgetNew1, 0, 0);//Q23.8
		outSNR[i] = DVTX_MAX(Ltmp, 1);
	}
	num = (Nband + 1 - band_low) / 4;
	poutSNR_in = poutSNR_out = (ae_int32x2 *)&outSNR[band_low];
	poutSNRtmp_in = poutSNRtmp_out = (ae_int32x2 *)&outSNRtmp[band_low];
	pEE = (ae_int32x2 *)&EE[band_low];
	pPH1 = (ae_int16x4 *)&PH1[band_low];
	align_outSNR_in = AE_LA64_PP(poutSNR_in);
	align_outSNRtmp_in = AE_LA64_PP(poutSNRtmp_in);
	align_EE = AE_LA64_PP(pEE);
	align_PH1 = AE_LA64_PP(pPH1);
	align_outSNR_out = AE_ZALIGN64();
	align_outSNRtmp_out = AE_ZALIGN64();
	LforgetOld2 = AE_MOVDA16(DVTX_WORD16_0_95);
	LforgetNew2 = AE_SUB16S(LDVTX, LforgetOld2);
	for(i = 0; i < num; i++)
	{
		AE_LA16X4_IP(LforgetOld1, align_PH1, pPH1);
		bool4 = AE_LT16(LforgetOld1, LforgetOld2);
		AE_MOVT16X4(LforgetOld1, LforgetOld2, bool4);
		LforgetNew1 = AE_SUB16S(LDVTX, LforgetOld1);
		AE_LA32X2_IP(Ltmp1, align_outSNRtmp_in, poutSNRtmp_in);
		AE_LA32X2_IP(Ltmp2, align_EE, pEE);
		Ltmp3 = fx_SolomonVoice_recursiveAVG_ls_2_vector(Ltmp1, Ltmp2, LforgetOld1, LforgetNew1, 0);
		AE_SA32X2_IP(Ltmp3, align_outSNRtmp_out, poutSNRtmp_out);
		AE_LA32X2_IP(Ltmp1, align_outSNR_in, poutSNR_in);
		Ltmp2 = fx_SolomonVoice_recursiveAVG_ls_2_vector(Ltmp1, Ltmp3, LforgetOld2, LforgetNew2, 0);
		Ltmp2 = AE_MAX32(Ltmp2, Lset);
		AE_SA32X2_IP(Ltmp2, align_outSNR_out, poutSNR_out);
		AE_LA32X2_IP(Ltmp1, align_outSNRtmp_in, poutSNRtmp_in);
		AE_LA32X2_IP(Ltmp2, align_EE, pEE);
		LforgetOld1 = AE_SEL16_5432(LforgetOld1, LforgetOld1);
		LforgetNew1 = AE_SEL16_5432(LforgetNew1, LforgetNew1);
		Ltmp3 = fx_SolomonVoice_recursiveAVG_ls_2_vector(Ltmp1, Ltmp2, LforgetOld1, LforgetNew1, 0);
		AE_SA32X2_IP(Ltmp3, align_outSNRtmp_out, poutSNRtmp_out);
		AE_LA32X2_IP(Ltmp1, align_outSNR_in, poutSNR_in);
		Ltmp2 = fx_SolomonVoice_recursiveAVG_ls_2_vector(Ltmp1, Ltmp3, LforgetOld2, LforgetNew2, 0);
		Ltmp2 = AE_MAX32(Ltmp2, Lset);
		AE_SA32X2_IP(Ltmp2, align_outSNR_out, poutSNR_out);
	}
	AE_SA64POS_FP(align_outSNRtmp_out, poutSNRtmp_out);
	AE_SA64POS_FP(align_outSNR_out, poutSNR_out);
	forgetNew1 = DVTXOP_sub(DVTX_MAX_16, DVTX_WORD16_0_95);
	for(i = band_low + num * 4; i <= Nband; i++)
	{
		//Npsd tmp
		{
			forgetOld = DVTX_MAX(PH1[i], DVTX_WORD16_0_95);
			forgetNew = DVTXOP_sub(DVTX_MAX_16, forgetOld);
			outSNRtmp[i] = fx_SolomonVoice_recursiveAVG_ls(outSNRtmp[i], EE[i], forgetOld, forgetNew, 0, 0);//Q23.8
		}

		//Npsd_ini
		Ltmp = fx_SolomonVoice_recursiveAVG_ls(outSNR[i], outSNRtmp[i], DVTX_WORD16_0_95, forgetNew1, 0, 0);//Q23.8
		outSNR[i] = DVTX_MAX(Ltmp, 1);
	}
}
#endif
/*Solomonvoice function
16bit gain by lookup table
wiener(0.31) to gain(0.15)
*/
void fx_SolomonVoice_WienerQ31_to_GainQ15(short *G, int *Wiener, short powerIndex, short Nband)
{
	short i;

	if (powerIndex == 1)
	{
#ifndef OPT_int_sqrt_0_25_fourX     /// if¹® ¾ÈÀ¸·Î Àß ¾Èµé¾î¿Í¼­ È®ÀÎÀÌ ¾ÈµÊ.
		for (i = 0; i <= Nband; i++)
		{
			G[i] = int_sqrt_0_25(Wiener[i]);
		}
#else
		for (i = 0; i <= Nband; i+= 4)     //
		{
			int_sqrt_0_25_four(&Wiener[i], &G[i]);
		}
#endif
	}
	else if (powerIndex == 2)
	{
#ifndef OPT_int_sqrt_0_50_four
		for (i = 0; i <= Nband; i++)
		{
			G[i] = int_sqrt_0_50(Wiener[i]);
		}
#else
		{
			int Nbandremain,k, Nband4q;
			Nbandremain = (Nband + 1) & 0x3;
			Nband4q = (Nband + 1)>>2;
		    int_sqrt_0_50_four(Wiener, G,Nband4q);
            i = Nband4q*4;
		    for (k = 0; k < Nbandremain; k++)
		    {
			   G[i] = int_sqrt_0_50(Wiener[i]);
			   i ++;
		    }
		}
#endif
	}
	else if (powerIndex == 3)
	{
		for (i = 0; i <= Nband; i++)
		{
			G[i] = int_sqrt_0_75(Wiener[i]);
		}
	}
}

/* SolomonVoice_SubBlocks #25:
invSNR = (15 - min(max(sum(10*log10(SNR_ini_CEPavg))/DEF_NS.Nchn, 0), 15))/3, 0 ~ 5 to comensate PARA_FixedXi[i][1], local SNR
*/
int fx_SolomonVoice_invSNR_calculation(int *SNR, short OneOverNband, short Nband)
{
	short i;
	int Ltmp, Ltmpsum1, invSNR;

	Ltmpsum1 = 0;
	for (i = 0; i <= Nband; i++)
		Ltmpsum1 += SNR[i];

	Ltmpsum1 = DVTXOP_L_mpy_ls(Ltmpsum1, OneOverNband);//Q16,15
	Ltmp = DVTXOP_L_sub(Fx_10log10(Ltmpsum1, 0), 11559);//Q8- 11559=(10*log10(2^15))*2^8
	invSNR = DVTXOP_L_shr_r(DVTXOP_L_mpy_ls((3840 - DVTX_MIN(DVTX_MAX(Ltmp, 0), 3840)), 10922), 8); // min 0, max 3840=15*2^8, /3 : invSNR --> Q0

	return invSNR;
}

/*Solomonvoice function
step size and Wvar limit are fixed now
DD : Q23.8
RR : Q23.8
W  : Q5,10 --> 0.15 changed
step_fnlms, limit_fnlms should be controlled
*/
void fx_SolomonVoice_FNLMS_filter_update(short *W, short *Wvar, int *DD, int *RR, short NHalfFFT)
{
	short norm1, tmp, i, step_fnlms, limit_fnlms;
	int L_DDpow, L_RD;


	for (i = 0; i < NHalfFFT; i++) // Wres freezing for low freq.( 0Hz ~650Hz(20*32.5Hz))
	{
		//DD by DD
		norm1 = DVTXOP_norm_l(DD[i]);
		tmp = DVTXOP_extract_h(DVTXOP_L_shl(DD[i], norm1));
		L_DDpow = DVTXOP_L_mpy_ls(DD[i], tmp);
		//RR by DD
		L_RD = DVTXOP_L_mpy_ls(RR[i], tmp);

		if (i < 10) { step_fnlms = 10;	limit_fnlms = 20; } // ~300Hz
		else if (i < 96) { step_fnlms = 20;	limit_fnlms = 50; } // ~3000Hz
		else { step_fnlms = 20;	limit_fnlms = 60; }

		Wvar[i] = 0;//q5,10			
		if ((L_RD != 0) && (L_DDpow > 0))
		{
			if (L_RD > 0)
			{
				Wvar[i] = fx_SolomonVoice_FNLMS_coef_cal(L_RD, L_DDpow, 10, step_fnlms);
				Wvar[i] = DVTX_MIN(Wvar[i], limit_fnlms);// prevent counter overflow									
			}
			else // L_RD<0
			{
				L_RD = DVTXOP_L_negate(L_RD);
				Wvar[i] = fx_SolomonVoice_FNLMS_coef_cal(L_RD, L_DDpow, 10, 100);
				Wvar[i] = DVTX_MIN(Wvar[i], 100);// prevent counter overflow									
				Wvar[i] = DVTXOP_negate(Wvar[i]);
			}
		}
		// update the Wresres filter	
		W[i] = DVTXOP_add(W[i], Wvar[i]); //q5,10
	}
}

/*Solomonvoice function
ref. Q format : Q23.8, (Q=7)
*/
void fx_SolomonVoice_EchoPSD_estimation(int *EchoPSD, int *EchoPower, int b_new_dc, int b_old_dc, int b_new_ic, int b_old_ic, short blk_norm_rx, short minPSD, short Q, short Nband)
{
	short i;
	int Ltmp, L_forgetNew, L_forgetOld;

	for (i = 0; i <= Nband; i++)
	{
		//DVTX_ECNS_vars->ECNSbuff.L_Dsqr_q30[i] = DVTXOP_L_shl(DVTX_ECNS_vars->ECNSbuff.L_Dsqr_q30[i], BitShift_EchoPSD);

		// resi echo PSD estimation		
		Ltmp = DVTXOP_L_shl(EchoPower[i], (short)(Q - (2 * blk_norm_rx))); /*30,1 -> 23,8*/
		if (Ltmp < EchoPSD[i])// slow decreaing
		{
			L_forgetNew = b_new_dc;
			L_forgetOld = b_old_dc;
		}
		else //fast increaing phase
		{
			L_forgetNew = b_new_ic;
			L_forgetOld = b_old_ic;
		}

		//Q23,8
		EchoPSD[i] = fx_SolomonVoice_recursiveAVG_ll(EchoPSD[i], EchoPower[i], L_forgetOld, L_forgetNew, blk_norm_rx, Q); //Q23,8
#ifndef KHW_OPTI_20191216
		if (EchoPSD[i] < (int)minPSD) //16	/* 0.0625 scaled as 23,8 */
			EchoPSD[i] = (int)minPSD;
#else
		EchoPSD[i] = DVTX_MAX(EchoPSD[i],(int)minPSD);
#endif
	}
}

void fx_SolomonVoice_noisefloor_smoothing(short *Nfloor, int*NfloorTMP, short Nband)
{
	short i, j;
	int Ltmpsum1, Ltmp1, Ltmp2, Ltmp;

	for (i = 4; i <= Nband - 4; i++)
	{
		Ltmpsum1 = 0;
		for (j = -4; j <= 4; j++)
			Ltmpsum1 = DVTXOP_L_add(Ltmpsum1, NfloorTMP[i + j]);
		Nfloor[i] = DVTXOP_extract_l(DVTXOP_L_mpy_ls(Ltmpsum1, 3640));//  *1/9
	}
	for (i = 4; i >= 0; i--)
	{
		Ltmp1 = DVTXOP_L_mpy_ls(NfloorTMP[i + 2], DVTX_WORD16_0_1); //0.1
		Ltmp2 = DVTXOP_L_mpy_ls(NfloorTMP[i + 1], DVTX_WORD16_0_3); //0.3		
		Ltmp = DVTXOP_L_mpy_ls(NfloorTMP[i], DVTX_WORD16_0_6);    //0.6
		Nfloor[i] = DVTXOP_extract_l(Ltmp + Ltmp1 + Ltmp2);
	}
	for (i = Nband - 3; i <= Nband; i++)
	{
		Ltmp1 = DVTXOP_L_mpy_ls(NfloorTMP[i - 2], DVTX_WORD16_0_1); //0.1
		Ltmp2 = DVTXOP_L_mpy_ls(NfloorTMP[i - 1], DVTX_WORD16_0_3); //0.3		
		Ltmp = DVTXOP_L_mpy_ls(NfloorTMP[i], DVTX_WORD16_0_6);    //0.6
		Nfloor[i] = DVTXOP_extract_l(Ltmp + Ltmp1 + Ltmp2);
	}
}

void fx_SolomonVoice_global_SNR_averaging(int *SNRglobal, int SNRmtx[][4], short Nband)
{
	short i;
	int Ltmp1, Ltmp2;

	for (i = 0; i <= Nband; i++)
	{
		Ltmp1 = DVTXOP_L_add(SNRmtx[i][0], SNRmtx[i][1]);
		Ltmp2 = DVTXOP_L_add(SNRmtx[i][2], SNRmtx[i][3]);
		SNRglobal[i] = DVTXOP_L_shr(DVTXOP_L_add(Ltmp1, Ltmp2), 2);
	}
}

void fx_SolomonVoice_aprioriSNR_recursiveAVG(int *SNRavg, int *SNRtmp, short Nband4k, short Nband8k)
{
	short i;
	int Ltmp, Ltmp1;

	for (i = 0; i <= Nband4k; i++) //0 to 4kHz, forgetting factor =0.85
	{
		Ltmp = DVTXOP_L_mpy_ls(SNRavg[i], DVTX_WORD16_0_85); //0.85
		Ltmp1 = DVTXOP_L_mpy_ls(SNRtmp[i], DVTX_WORD16_0_15); //0.15
		SNRavg[i] = DVTXOP_L_add(Ltmp, Ltmp1);
	}
	for (i = Nband4k + 1; i <= Nband8k; i++) //4k to 8k, forgetting factor =0.2
	{
		Ltmp = DVTXOP_L_mpy_ls(SNRavg[i], DVTX_WORD16_0_5); //0.2
		Ltmp1 = DVTXOP_L_mpy_ls(SNRtmp[i], DVTX_WORD16_0_5); //0.8
		SNRavg[i] = DVTXOP_L_add(Ltmp, Ltmp1);
	}
}

/* SolomonVoice_SubBlocks #18:
calculate Tx. 1~4kHz Pwr --> silence interval detection
*/
// Noise free flag update using Pwr 1kHz to 4kHz
void fx_SolomonVoice_tx_Silence_mode_detection(FRAMEStatus* FRAME_buf, AECStatus* AEC_buf, RESStatus* RES_buf, NSStatus* NS_buf, SamsungSolomonVoiceWTxNSParam* NS_param)
{
	int L_Pwr_1kto4k, L_Pwr_100kto1k;
	short i;
	short NumOfCascadeFrame;
	
	//L_Pwr_1kto4k = 0;
	//for (i = 12; i <= DVTX_BAND_INDEX_4kHz; i++) // 1kHz to 4kHz
	//	L_Pwr_1kto4k = DVTXOP_L_add(L_Pwr_1kto4k, NS_buf->L_EsqrNS[i]); //Q23.8

	L_Pwr_100kto1k = 0;
	for (i = 3; i <12; i++) // 1kHz to 4kHz
		L_Pwr_100kto1k = DVTXOP_L_add(L_Pwr_100kto1k, NS_buf->L_EsqrNS[i]); //Q23.8

	L_Pwr_1kto4k = L_Pwr_100kto1k; // substitute Pwr1-4k to pwr0.1-1;

	FRAME_buf->Pwr_100Hz_to_1kHz_Outer = L_Pwr_100kto1k;

	NumOfCascadeFrame = 5;

	if (L_Pwr_1kto4k < NS_param->PARA_THD_Pwr_Lo_1k_4k)
	{
		if (FRAME_buf->Pwr_1kHz_to_4kHz_Outer < NS_param->PARA_THD_Pwr_Lo_1k_4k) // cascaded frame energy observation
		{
			RES_buf->Cnt_Cascade_tx_silent_frames++;
			RES_buf->Cnt_Cascade_tx_silent_frames = DVTX_MIN(RES_buf->Cnt_Cascade_tx_silent_frames, NumOfCascadeFrame);
		}
		if (RES_buf->Cnt_Cascade_tx_silent_frames == NumOfCascadeFrame)
		{
			AEC_buf->Flag_Tx_silent_mode = 1;
			NS_buf->hov_tx_noisefree_cnt = NS_param->PARA_HangOver_Cnt_NoiseFree;
		}
		else
		{
			AEC_buf->Flag_Tx_silent_mode = 0;
			NS_buf->hov_tx_noisefree_cnt = 0;
		}
	}
	else if (NS_buf->hov_tx_noisefree_cnt > 0)
	{
		AEC_buf->Flag_Tx_silent_mode = 1;
		NS_buf->hov_tx_noisefree_cnt--;
	}
	else
	{
		RES_buf->Cnt_Cascade_tx_silent_frames = 0;
		AEC_buf->Flag_Tx_silent_mode = 0;
		NS_buf->hov_tx_noisefree_cnt = 0;
	}

	/*if (FRAME_buf->Flag_SingleTalk == 1)
	{
	AEC_buf->Flag_Tx_silent_mode = 0;
	NS_buf->hov_tx_noisefree_cnt = 0;
	}*/


	FRAME_buf->Pwr_1kHz_to_4kHz_Outer = L_Pwr_1kto4k;

	return;
}

/* SolomonVoice_SubBlocks #20:
long term SNR estimation // frame SNR value : L_SNR_ini_avg_dB
to control cepstrum smoothing facotr
time-freq smoothing
L_SNR_by_Nmmse_ini_avg Q16.15
SNRavg_dB : Q8,7
*/

#ifndef fx_SolomonVoice_iniSNR_smoothing_OPT_DSP
int fx_SolomonVoice_iniSNR_smoothing(int *SNRsmoothout, int *SNRin, short OneOverNband, short forget, short Nband)
{
	short i;
	int SNRavg_dB;

	for (i = 0; i <= Nband; i++)
	{
		SNRsmoothout[i] = Fx_recursive_avg(SNRsmoothout[i], SNRin[i], forget);
	}
	// calculate FLAGsoft_SNR_ini : 0.0~1.0 forgetting factor
	SNRavg_dB = 0;
	for (i = 0; i <= Nband; i++)
	{
		SNRavg_dB += SNRsmoothout[i];
	}
	SNRavg_dB = DVTXOP_L_mpy_ls(SNRavg_dB, OneOverNband);//Q16,15
	SNRavg_dB = DVTXOP_L_sub(Fx_10log10(SNRavg_dB, 0), 11559);//Q8- (10*log10(2^15))*2^8

	return SNRavg_dB;

}
#else
int fx_SolomonVoice_iniSNR_smoothing(int *SNRsmoothout, int *SNRin, short OneOverNband, short forget, short Nband)
{
	short i,num;
	int SNRavg_dB=0;
	ae_int32x2 Ltmp1, Ltmp2, Ltmp3, LSNRavg_dB;
	ae_int16x4 Lbeta, Lbeta_inv;
	ae_int64 LLtmp1, LLtmp2;
	ae_int32x2 *pSNRsmoothout_in, *pSNRsmoothout_out, *pSNRin;
	ae_valign align_SNRsmoothout_in, align_SNRsmoothout_out, align_SNRin;
	pSNRsmoothout_in = pSNRsmoothout_out = (ae_int32x2 *)&SNRsmoothout[0];
	pSNRin = (ae_int32x2 *)&SNRin[0];
	align_SNRsmoothout_in  = AE_LA64_PP(pSNRsmoothout_in);
	align_SNRsmoothout_out = AE_ZALIGN64();
	align_SNRin = AE_LA64_PP(pSNRin);
	Lbeta = AE_MOVDA16(forget);
	Lbeta_inv = AE_SUB16S(AE_MOVDA16(DVTX_MAX_16), Lbeta);
	Lbeta_inv = AE_ADD16S(Lbeta_inv, AE_MOVDA16(1));
	ae_int32x2 mask = AE_MOVDA32(0xfffffffe);
	num = Nband/2;
	for(i = 0; i < num; i++)
	{
		AE_LA32X2_IP(Ltmp1, align_SNRsmoothout_in, pSNRsmoothout_in);
		AE_LA32X2_IP(Ltmp2, align_SNRin, pSNRin);
		//DVTXOP_L_mpy_ls(A, beta) Ltmp1 =  Ltmp1 * Lbeta
		Ltmp1 = AE_AND32(Ltmp1, mask);
		LLtmp1 = AE_MUL32X16_L0(Ltmp1, Lbeta);
		LLtmp2 = AE_MUL32X16_H1(Ltmp1, Lbeta);
		LLtmp1 = AE_SLAI64S(LLtmp1, 17);
		LLtmp2 = AE_SLAI64S(LLtmp2, 17);
		Ltmp1 = AE_TRUNCI32X2F64S(LLtmp2, LLtmp1,0);

		//DVTXOP_L_mpy_ls(B, beta_inv) Ltmp2 = Ltmp2 * Lbeta_inv;
		Ltmp2 = AE_AND32(Ltmp2, mask);
		LLtmp1 = AE_MUL32X16_L0(Ltmp2, Lbeta_inv);
		LLtmp2 = AE_MUL32X16_H1(Ltmp2, Lbeta_inv);
		LLtmp1 = AE_SLAI64S(LLtmp1, 17);
		LLtmp2 = AE_SLAI64S(LLtmp2, 17);
		Ltmp2 = AE_TRUNCI32X2F64S(LLtmp2, LLtmp1,0);
		Ltmp3 = AE_ADD32S(Ltmp1, Ltmp2);
		AE_LA32X2_IP(Ltmp3, align_SNRsmoothout_out, pSNRsmoothout_out);
		LSNRavg_dB = AE_ADD32S(LSNRavg_dB, Ltmp3);
	}
	AE_SA64POS_FP(align_SNRsmoothout_out, pSNRsmoothout_out);
	Ltmp1 = AE_SEL32_LH(LSNRavg_dB, LSNRavg_dB);
	Ltmp2 = AE_ADD32S(Ltmp1,LSNRavg_dB);
	SNRavg_dB = AE_MOVAD32_L(Ltmp2);
	if(Nband%2==0)
	{
		SNRsmoothout[Nband] = Fx_recursive_avg(SNRsmoothout[Nband], SNRin[Nband], forget);
		SNRavg_dB += SNRsmoothout[Nband];
	}
	SNRavg_dB = DVTXOP_L_mpy_ls(SNRavg_dB, OneOverNband);//Q16,15
	SNRavg_dB = DVTXOP_L_sub(Fx_10log10(SNRavg_dB, 0), 11559);//Q8- (10*log10(2^15))*2^8

	return SNRavg_dB;
}
#endif

void fx_SolomonVoice_noisefloor_cal(int *Nfloor, int *SNR, short y1, short y2, short OneOverX1X2Q8, int Lx1, short BandStart, short BandEnd)
{
	short suby1y2, i;
	int Ltmp1, Ltmp2;

	suby1y2 = y2 - y1;
	for (i = BandStart; i <= BandEnd; i++)
	{
		Ltmp1 = DVTXOP_L_sub(SNR[i], Lx1); //q15
		Ltmp2 = DVTXOP_L_mpy_ls(Ltmp1, OneOverX1X2Q8);//q18
		Ltmp2 = DVTXOP_L_shr(DVTXOP_L_mpy_ls(Ltmp2, suby1y2), 3);//q15
		Ltmp2 = DVTXOP_L_add(Ltmp2, (int)y1);//q15
		Nfloor[i] = DVTX_MIN(DVTX_MAX(Ltmp2, (int)y1), (int)y2);
	}
}

/* SolomonVoice_SubBlocks #28:
second Npsd estimation
L_Npsd
Q15.16
*/
void fx_SolomonVoice_Npsd_2nd_estimation(int *Npsd, int *EE, short *PH1, short MinNpsd, short NORM, short Q, short Nband, short BetaMin)
{
	short i, forgetOld, forgetNew, OneMinusBetaMin;

	OneMinusBetaMin = DVTXOP_sub(DVTX_MAX_16, BetaMin);
	for (i = 0; i <= Nband; i++)
	{
		////noise esimation 
		forgetOld = DVTXOP_add(BetaMin, DVTXOP_mult(OneMinusBetaMin, PH1[i])); //p=0.85+0.15*p1;
		forgetNew = DVTXOP_sub(DVTX_MAX_16, forgetOld);

		/*30,1 -> 15,16*/
		Npsd[i] = fx_SolomonVoice_recursiveAVG_ls(Npsd[i], EE[i], forgetOld, forgetNew, NORM, Q);
#ifndef KHW_OPTI_20191216
		if (Npsd[i] < MinNpsd) //16
			Npsd[i] = MinNpsd;
#else
		Npsd[i] = DVTX_MAX(Npsd[i],MinNpsd);
#endif
	}
}

/*Solomonvoice function
when Q=0, blk_norm=0, Q format is depending on input Q-format
when Q=15, 30,1 -> 15,16
*/
#ifndef fx_SolomonVoice_recursiveAVG_ls_OPT_DSP
int fx_SolomonVoice_recursiveAVG_ls(int OldVal, int NewVal, short beOld, short beNew, short blk_norm, short Q)
{
	short norm_shift;
	int Ltmp, Ltmp1, Ltmp2;

	norm_shift = DVTXOP_norm_l(OldVal);
	Ltmp = DVTXOP_L_shl(OldVal, norm_shift);
	Ltmp1 = DVTXOP_L_mpy_ls(Ltmp, beOld);
	Ltmp1 = DVTXOP_L_shr_r(Ltmp1, norm_shift);

	norm_shift = DVTXOP_norm_l(NewVal);
	Ltmp = DVTXOP_L_shl(NewVal, norm_shift);
	Ltmp2 = DVTXOP_L_mpy_ls(Ltmp, beNew);
	Ltmp2 = DVTXOP_L_shr_r(Ltmp2, norm_shift);

	Ltmp2 = DVTXOP_L_shl(Ltmp2, (short)(Q - (2 * blk_norm))); /*30,1 -> 15,16*/

	return DVTXOP_L_add(Ltmp1, Ltmp2);
}
#else
int fx_SolomonVoice_recursiveAVG_ls(int OldVal, int NewVal, short beOld, short beNew, short blk_norm, short Q)
{
	short norm_shift;
	int Ltmp, Ltmp1, Ltmp2;
	int tmpL;

	tmpL = ((long long)AE_MUL32_LL(OldVal, beOld) + 16384)>>15 ;
	Ltmp1 = tmpL;

	tmpL = ((long long)AE_MUL32_LL(NewVal, beNew) + 16384) >> 15;
	Ltmp2= tmpL;

	Ltmp2 = DVTXOP_L_shl(Ltmp2, (short)(Q - (2 * blk_norm))); /*30,1 -> 15,16*/

	return DVTXOP_L_add(Ltmp1, Ltmp2);
}
#endif

#ifndef fx_SolomonVoice_recursiveAVG_ls_2_OPT_DSP
void fx_SolomonVoice_recursiveAVG_ls_2(int* OldVal, int* NewVal, short beOld, short beNew, short blk_norm, short Q)
{
	short norm_shift;
	int Ltmp, Ltmp1, Ltmp2, result1, result2;
	int tmpL;

	tmpL = ((long long)MULL(OldVal[0], beOld) + 16384) >> 15;
	Ltmp1 = tmpL;
	tmpL = ((long long)MULL(NewVal[0], beNew) + 16384) >> 15;
	Ltmp2 = tmpL;

	Ltmp2 = DVTXOP_L_shl(Ltmp2, (short)(Q - (2 * blk_norm))); /*30,1 -> 15,16*/

	OldVal[0] = DVTXOP_L_add(Ltmp1, Ltmp2);

	tmpL = ((long long)MULL(OldVal[1], beOld) + 16384) >> 15;
	Ltmp1 = tmpL;

	tmpL = ((long long)MULL(NewVal[1], beNew) + 16384) >> 15;
	Ltmp2 = tmpL;

	Ltmp2 = DVTXOP_L_shl(Ltmp2, (short)(Q - (2 * blk_norm))); /*30,1 -> 15,16*/
	OldVal[1] = DVTXOP_L_add(Ltmp1, Ltmp2);

	return ;
}
#else
void fx_SolomonVoice_recursiveAVG_ls_2(int* OldVal, int* NewVal, short beOld, short beNew, short blk_norm, short Q)
{
	short norm_shift;
	int Ltmp, Ltmp1, Ltmp2, result1, result2;
	int tmpL;

	tmpL = ((long long)AE_MUL32_LL(OldVal[0], beOld) + 16384) >> 15;
	Ltmp1 = tmpL;
	tmpL = ((long long)AE_MUL32_LL(NewVal[0], beNew) + 16384) >> 15;
	Ltmp2 = tmpL;

	Ltmp2 = DVTXOP_L_shl(Ltmp2, (short)(Q - (2 * blk_norm))); /*30,1 -> 15,16*/

	OldVal[0] = DVTXOP_L_add(Ltmp1, Ltmp2);

	tmpL = ((long long)AE_MUL32_LL(OldVal[1], beOld) + 16384) >> 15;
	Ltmp1 = tmpL;

	tmpL = ((long long)AE_MUL32_LL(NewVal[1], beNew) + 16384) >> 15;
	Ltmp2 = tmpL;

	Ltmp2 = DVTXOP_L_shl(Ltmp2, (short)(Q - (2 * blk_norm))); /*30,1 -> 15,16*/
	OldVal[1] = DVTXOP_L_add(Ltmp1, Ltmp2);

	return ;
}
#endif
#ifdef fx_SolomonVoice_recursiveAVG_ls_vector_OPT_DSP
ae_int32x2 fx_SolomonVoice_recursiveAVG_ls_2_vector(ae_int32x2 OldVal, ae_int32x2 NewVal, ae_int16x4 beOld, ae_int16x4 beNew, short shift)
{
	ae_int64 value = AE_MOV64(0x0000000000004000LL);
	ae_int32x2 Ltmp1, Ltmp2, Ltmpret;
	ae_int64 tmp1, tmp2;

	tmp1 = AE_MUL32X16_L2(OldVal, beOld);
	tmp2 = AE_MUL32X16_H3(OldVal, beOld);
	tmp1 = AE_ADD64(tmp1, value);
	tmp2 = AE_ADD64(tmp2, value);
	tmp1 = AE_SLAI64S(tmp1, 17);
	tmp2 = AE_SLAI64S(tmp2, 17);
	Ltmp1 = AE_TRUNCI32X2F64S(tmp2, tmp1,0);

	tmp1 = AE_MUL32X16_L2(NewVal, beNew);
	tmp2 = AE_MUL32X16_H3(NewVal, beNew);
	tmp1 = AE_ADD64(tmp1, value);
	tmp2 = AE_ADD64(tmp2, value);
	tmp1 = AE_SLAI64S(tmp1, 17);
	tmp2 = AE_SLAI64S(tmp2, 17);
	Ltmp2 = AE_TRUNCI32X2F64S(tmp2, tmp1,0);
	Ltmp2 = AE_SLAA32S(Ltmp2, shift);
	Ltmpret = AE_ADD32S(Ltmp1, Ltmp2);
	return Ltmpret;

}
#endif

/*Solomonvoice function
echo scalar gain recursive averaging
g_highxecc : Q5,10
g_lowxecc : Q5,10
g : Q0.15
*/
short fx_SolomonVoice_EchoPSD_gain_cal(short g, short g_res, short flag_rx, short flag_st, short xecc, short xecc_thd, short g_highxecc, short g_lowxecc)
{
	short tmp, tmp1, tmp2;

	if (flag_rx == 1) // Single talk 
	{
		if ((flag_st == 1))
			tmp2 = DVTXOP_shl(DVTXOP_mult(g_res, g_highxecc), 5); // Q15*Q10 
		else if (xecc < xecc_thd) //0.8
			tmp2 = DVTXOP_shl(DVTXOP_mult(g_res, g_lowxecc), 5); // Q15*Q10 
		else
			tmp2 = g_res;


		tmp = DVTXOP_mult(g, DVTX_WORD16_0_3); //0.9
		tmp1 = DVTXOP_mult(tmp2, DVTX_WORD16_0_7);
		g = DVTXOP_add(tmp, tmp1); //Q15
	}
	else // gain goes to zero for no rx
	{
		g = DVTXOP_mult(g, DVTX_WORD16_0_9); //0.9				
	}

	return g;
}
#ifndef fx_SolomonVoice_aprioriSNR_freqSmoothing_OPT_DSP
void fx_SolomonVoice_aprioriSNR_freqSmoothing(int *SNRsmooth, int *SNRin, short Nband)
{
	short i, j;
	int Ltmpsum1, Ltmp1, Ltmp2, Ltmp;

	for (i = 4; i <= Nband - 4; i++)
	{
		Ltmpsum1 = 0;
		for (j = -4; j <= 4; j++)
			Ltmpsum1 = DVTXOP_L_add(Ltmpsum1, SNRin[i + j]);
		SNRsmooth[i] = DVTXOP_L_mpy_ls(Ltmpsum1, 3640);//  *1/9
	}
	for (i = 4; i >= 0; i--)
	{
		Ltmp1 = DVTXOP_L_mpy_ls(SNRin[i + 2], DVTX_WORD16_0_1); //0.1
		Ltmp2 = DVTXOP_L_mpy_ls(SNRin[i + 1], DVTX_WORD16_0_3); //0.3		
		Ltmp = DVTXOP_L_mpy_ls(SNRin[i], DVTX_WORD16_0_6);    //0.6
		SNRsmooth[i] = Ltmp + Ltmp1 + Ltmp2;
	}
	for (i = Nband - 3; i <= Nband; i++)
	{
		Ltmp1 = DVTXOP_L_mpy_ls(SNRin[i - 2], DVTX_WORD16_0_1); //0.1
		Ltmp2 = DVTXOP_L_mpy_ls(SNRin[i - 1], DVTX_WORD16_0_3); //0.3		
		Ltmp = DVTXOP_L_mpy_ls(SNRin[i], DVTX_WORD16_0_6);    //0.6
		SNRsmooth[i] = Ltmp + Ltmp1 + Ltmp2;
	}
}
#else
void fx_SolomonVoice_aprioriSNR_freqSmoothing(int *SNRsmooth, int *SNRin, short Nband)
{
	short i, num;
	int tmp, tmp1, tmp2;
	ae_int32x2 *pSNRin, *pSNRsmooth;
	ae_valign align_SNRin, align_SNRsmooth;
	ae_int32x2 Ltmp1, Ltmp2, Ltmp3, Ltmp4;
	ae_int64 LLtmp1, LLtmp2;
	ae_int16x4 LWORD16_0_1, LWORD16_0_3, LWORD16_0_6;
	ae_int32x2 mask = AE_MOVDA32(0xfffffffe);
	LWORD16_0_1 = AE_MOVDA16(DVTX_WORD16_0_1);
	LWORD16_0_3 = AE_MOVDA16(DVTX_WORD16_0_3);
	LWORD16_0_6 = AE_MOVDA16(DVTX_WORD16_0_6);
	pSNRin = (ae_int32x2 *)&SNRin[0];
	pSNRsmooth = (ae_int32x2 *)&SNRsmooth[0];
	align_SNRin = AE_LA64_PP(pSNRin);
	align_SNRsmooth = AE_ZALIGN64();
	AE_LA32X2_IP(Ltmp4, align_SNRin, pSNRin);
	for(i = 0;i < 2; i++)
	{
		Ltmp1 = Ltmp4;
		AE_LA32X2_IP(Ltmp4, align_SNRin, pSNRin);
		Ltmp2 = AE_SEL32_LH(Ltmp1, Ltmp4);
		//Ltmp1 = Ltmp1 * LWORD16_0_6
		Ltmp1 = AE_AND32(Ltmp1, mask);
		LLtmp1 = AE_MUL32X16_L0(Ltmp1, LWORD16_0_6);
		LLtmp2 = AE_MUL32X16_H1(Ltmp1, LWORD16_0_6);
		LLtmp1 = AE_SLAI64S(LLtmp1, 17);
		LLtmp2 = AE_SLAI64S(LLtmp2, 17);
		Ltmp1 = AE_TRUNCI32X2F64S(LLtmp2, LLtmp1,0);
		//Ltmp2 = Ltmp2 * LWORD16_0_3
		Ltmp2 = AE_AND32(Ltmp2, mask);
		LLtmp1 = AE_MUL32X16_L0(Ltmp2, LWORD16_0_3);
		LLtmp2 = AE_MUL32X16_H1(Ltmp2, LWORD16_0_3);
		LLtmp1 = AE_SLAI64S(LLtmp1, 17);
		LLtmp2 = AE_SLAI64S(LLtmp2, 17);
		Ltmp2 = AE_TRUNCI32X2F64S(LLtmp2, LLtmp1,0);
		//Ltmp3 = Ltmp4 * LWORD16_0_1
		Ltmp3 = AE_AND32(Ltmp4, mask);
		LLtmp1 = AE_MUL32X16_L0(Ltmp3, LWORD16_0_1);
		LLtmp2 = AE_MUL32X16_H1(Ltmp3, LWORD16_0_1);
		LLtmp1 = AE_SLAI64S(LLtmp1, 17);
		LLtmp2 = AE_SLAI64S(LLtmp2, 17);
		Ltmp3 = AE_TRUNCI32X2F64S(LLtmp2, LLtmp1,0);
		Ltmp1 = AE_ADD32S(Ltmp1, Ltmp2);
		Ltmp2 = AE_ADD32S(Ltmp1, Ltmp3);
		AE_SA32X2_IP(Ltmp2, align_SNRsmooth, pSNRsmooth);
	}
	AE_SA64POS_FP(align_SNRsmooth, pSNRsmooth);
	tmp1 = DVTXOP_L_mpy_ls(SNRin[4 + 2], DVTX_WORD16_0_1); //0.1
	tmp2 = DVTXOP_L_mpy_ls(SNRin[4 + 1], DVTX_WORD16_0_3); //0.3
	tmp = DVTXOP_L_mpy_ls(SNRin[4], DVTX_WORD16_0_6);    //0.6
	SNRsmooth[4] = tmp + tmp1 + tmp2;

	pSNRin = (ae_int32x2 *)&SNRin[Nband - 5];
	pSNRsmooth = (ae_int32x2 *)&SNRsmooth[Nband - 3];
	align_SNRin = AE_LA64_PP(pSNRin);
	align_SNRsmooth = AE_ZALIGN64();
	AE_LA32X2_IP(Ltmp4, align_SNRin, pSNRin);
	for (i = 0; i < 2; i++)
	{
		Ltmp1 = Ltmp4;
		AE_LA32X2_IP(Ltmp4, align_SNRin, pSNRin);
		Ltmp2 = AE_SEL32_LH(Ltmp1, Ltmp4);
		//Ltmp1 = Ltmp1 * LWORD16_0_1
		Ltmp1 = AE_AND32(Ltmp1, mask);
		LLtmp1 = AE_MUL32X16_L0(Ltmp1, LWORD16_0_1);
		LLtmp2 = AE_MUL32X16_H1(Ltmp1, LWORD16_0_1);
		LLtmp1 = AE_SLAI64S(LLtmp1, 17);
		LLtmp2 = AE_SLAI64S(LLtmp2, 17);
		Ltmp1 = AE_TRUNCI32X2F64S(LLtmp2, LLtmp1,0);
		//Ltmp2 = Ltmp2 * LWORD16_0_3
		Ltmp2 = AE_AND32(Ltmp2, mask);
		LLtmp1 = AE_MUL32X16_L0(Ltmp2, LWORD16_0_3);
		LLtmp2 = AE_MUL32X16_H1(Ltmp2, LWORD16_0_3);
		LLtmp1 = AE_SLAI64S(LLtmp1, 17);
		LLtmp2 = AE_SLAI64S(LLtmp2, 17);
		Ltmp2 = AE_TRUNCI32X2F64S(LLtmp2, LLtmp1,0);
		//Ltmp3 = Ltmp4 * LWORD16_0_6
		Ltmp3 = AE_AND32(Ltmp4, mask);
		LLtmp1 = AE_MUL32X16_L0(Ltmp3, LWORD16_0_6);
		LLtmp2 = AE_MUL32X16_H1(Ltmp3, LWORD16_0_6);
		LLtmp1 = AE_SLAI64S(LLtmp1, 17);
		LLtmp2 = AE_SLAI64S(LLtmp2, 17);
		Ltmp3 = AE_TRUNCI32X2F64S(LLtmp2, LLtmp1,0);
		Ltmp1 = AE_ADD32S(Ltmp1, Ltmp2);
		Ltmp2 = AE_ADD32S(Ltmp1, Ltmp3);
		AE_SA32X2_IP(Ltmp2, align_SNRsmooth, pSNRsmooth);
	}
	AE_SA64POS_FP(align_SNRsmooth, pSNRsmooth);
	ae_int32x2 Lsum1;

    int Ltmpsum1 = 0;
	for(i = 0; i < 9; i++)
	{
		Ltmpsum1 += SNRin[i];
	}
	for (i = 5; i <= Nband - 4; i++)//Nband-8
	{
		Ltmpsum1 = DVTXOP_L_add(Ltmpsum1, SNRin[i+4]);
		Ltmpsum1 = DVTXOP_L_sub(Ltmpsum1, SNRin[i-5]);
		SNRsmooth[i] = DVTXOP_L_mpy_ls(Ltmpsum1, 3640);//  *1/9
	}
}
#endif
/* SolomonVoice_SubBlocks #24:
MMSE-based initial Npsd estimation
L_SNR_by_Nmmse_ini_cepsmooth_fix used as SNR , Q16.15
a priori SNR is from the tune para, PARA_FixedXi[i][0], 0~15[dB]
L_Npsd_MMSE_TMP = Q23.8
L_Npsd_MMSE_ini = Q23.8
*/
void fx_SolomonVoice_SNR_to_PH1_lookuptable(short *PH1, int *SNR, short FixXi[][3], short FixXiindex, short SPPtable_flag, short increase_flag, short SNRcompensation, short Nband)
{
	short i, tmp, tmp1;
	int Ltmp;

	for (i = 0; i <= Nband; i++)
	{
		//DVTX_ECNS_vars->ECNSbuff.P_H1 from look-up table
		// P_H1_exp2_increase_Q15[0][]:xi = 0dB
		// P_H1_exp2_increase_Q15[15][]:xi = 15dB xi is a tunning parameter
		Ltmp = DVTX_MIN(DVTX_MAX(SNR[i], 256), 262144);//min = 2^15*(1/128) max = 2^15*(8)		
		tmp = DVTXOP_extract_l(DVTXOP_L_shr(DVTXOP_L_sub(Ltmp, 256), 11));//16,15 2^8<snr<2^19¸¦ 128 look-up table·Î...
		tmp = DVTX_MIN(DVTX_MAX(tmp, 0), 128);
		tmp1 = DVTX_MIN(DVTX_MAX(FixXi[i][FixXiindex] + SNRcompensation, 0), 15); //0~15dB as lookup table index

		Ltmp = 32 + 256 * (tmp);
		PH1[i] = bayes_prob(SPPtable_flag, tmp1, Ltmp, increase_flag);

	}
}

void fx_32bit_Band_Forced_DownScaling(int *BandNoisePSD, short bit_shift, short Nband)
{
	short i;

	for (i = 0; i <= Nband; i++)
	{
		BandNoisePSD[i] = DVTX_MAX(DVTXOP_L_shr(BandNoisePSD[i], bit_shift), 1);
}
}
void fx_16bit_Band_Forced_DownScaling(short *BandNoisePSD, short bit_shift, short Nband)
{
	short i;

	for (i = 0; i <= Nband; i++)
	{
		BandNoisePSD[i] = DVTX_MAX(DVTXOP_L_shr(BandNoisePSD[i], bit_shift), 1);
	}

}

/*Solomonvoice function
two FNLMS filters
over estimation for high band is applied
DD : Q23.8
EE : Q23.8
RR : Q23.8
W  : Q5,10 --> 0.15 changed
*/
#ifdef fx_SolomonVoice_FNLMS_error_cal_DSP_OPT
#ifdef C_MoidfyToBitexact

void fx_SolomonVoice_FNLMS_error_cal(int *EE, int *DD, int *DD2, int *RR, int *RRstep, short *W, short *W2, short NHalfFFT)
{
	short i;
	int Ltmp, Ltmp1, Ltmp2;

	//calculate FNLMS error
	for (i = 0; i < NHalfFFT; i++)
	{
		Ltmp1 = DVTXOP_Ls_mult_r(DD[i], W[i]);//Q23,8*Q5.10=q28,18-15=q28.3
		Ltmp2 = DVTXOP_Ls_mult_r(DD2[i], W2[i]);//Q23,8*Q5.10=q28,18-15=q28.3
											   //		if (i < 96)
											   //		{
											   //			Ltmp = DVTXOP_L_mpy_ls(DVTXOP_L_add(Ltmp1, Ltmp2), 25000);
											   //			RRstep[i] = DVTX_MAX(DVTXOP_L_sub(EE[i], DVTXOP_L_shl(Ltmp, 1)), -1); //23, 8 * /	error floor PARA_PWR_MIN_ECHO_REGRESSION*2^8=1024...
											   //		}
											   //		else
											   //		{
		Ltmp = DVTXOP_Ls_mult_r(DVTXOP_L_add(Ltmp1, Ltmp2), 25000);
		RRstep[i] = DVTX_MAX(DVTXOP_L_sub(EE[i], DVTXOP_L_shl(Ltmp, 1)), -1); //23, 8 * /	error floor PARA_PWR_MIN_ECHO_REGRESSION*2^8=1024...
																			  //		}
		RR[i] = DVTX_MAX(RRstep[i], 0); //23, 8 * /	error floor PARA_PWR_MIN_ECHO_REGRESSION*2^8=1024...
	}

}
#else
void fx_SolomonVoice_FNLMS_error_cal(int *EE, int *DD, int *DD2, int *RR, int *RRstep, short *W, short *W2, short NHalfFFT)
{
	short i;
	int Ltmp, Ltmp1, Ltmp2;

	//calculate FNLMS error
//	for (i = 0; i < NHalfFFT; i++)
//	{
//		Ltmp1 = DVTXOP_L_mpy_ls(DD[i], W[i]);//Q23,8*Q5.10=q28,18-15=q28.3
//		Ltmp2 = DVTXOP_L_mpy_ls(DD2[i], W2[i]);//Q23,8*Q5.10=q28,18-15=q28.3
//		Ltmp = DVTXOP_L_mpy_ls(DVTXOP_L_add(Ltmp1, Ltmp2), 25000);
//		RRstep[i] = DVTX_MAX(DVTXOP_L_sub(EE[i], DVTXOP_L_shl(Ltmp, 1)), -1); //23, 8 * /	error floor PARA_PWR_MIN_ECHO_REGRESSION*2^8=1024...
//																			  //		}
//		RR[i] = DVTX_MAX(RRstep[i], 0); //23, 8 * /	error floor PARA_PWR_MIN_ECHO_REGRESSION*2^8=1024...
//	}
	ae_valign align1, align2,align3, align4,align5, align6,align7;
	ae_int32x2  tmp1,tmp2,tmp3,tmp4,tmp5,tmp6;
	ae_int16x4  tmp_sh1,tmp_sh2;
    xtbool2 bool2;
    ae_int16x4 tmp_con=AE_MOVDA16(25000);
    ae_int32x2 tmp_con1=AE_MOVDA32(-1);
    ae_int32x2 tmp_con2=AE_MOVDA32(0);
	ae_int32x2* p_DD=(ae_int32x2*)DD;
	ae_int32x2* p_DD2=(ae_int32x2*)DD2;
	ae_int32x2* p_RR=(ae_int32x2*)RR;
	ae_int32x2* p_RRstep=(ae_int32x2*)RRstep;
	ae_int32x2* p_EE=(ae_int32x2*)EE;

	ae_int16x4* p_W=(ae_int16x4*)W;
	ae_int16x4* p_W2=(ae_int16x4*)W2;

    align1 = AE_LA64_PP(p_DD);
    align2 = AE_LA64_PP(p_DD2);
    align3 = AE_LA64_PP(p_W);
    align4= AE_LA64_PP(p_W2);
    align5= AE_LA64_PP(p_EE);
    align6= AE_ZALIGN64();
    align7= AE_ZALIGN64();
	for (i = 0; i < NHalfFFT; i+=4)
	{
//		Ltmp1 = DVTXOP_L_mpy_ls(DD[i], W[i]);//Q23,8*Q5.10=q28,18-15=q28.3
//		Ltmp2 = DVTXOP_L_mpy_ls(DD2[i], W2[i]);//Q23,8*Q5.10=q28,18-15=q28.3
		AE_LA32X2_IP(tmp1,align1, p_DD);
		AE_LA32X2_IP(tmp2,align1, p_DD);
		AE_LA16X4_IP(tmp_sh1,align3, p_W);
		tmp1=AE_MULFP32X16X2RAS_H(tmp1, tmp_sh1);
		tmp2=AE_MULFP32X16X2RAS_L(tmp2, tmp_sh1);

		AE_LA32X2_IP(tmp4,align2, p_DD2);
		AE_LA32X2_IP(tmp5,align2, p_DD2);
		AE_LA16X4_IP(tmp_sh2,align4, p_W2);
		tmp4=AE_MULFP32X16X2RAS_H(tmp4, tmp_sh2);
		tmp5=AE_MULFP32X16X2RAS_L(tmp5, tmp_sh2);
//		Ltmp = DVTXOP_L_mpy_ls(DVTXOP_L_add(Ltmp1, Ltmp2), 25000);
		tmp1=AE_ADD32S(tmp1, tmp4);
		tmp2=AE_ADD32S(tmp2, tmp5);
		tmp1=AE_MULFP32X16X2RAS_H(tmp1, tmp_con);
		tmp2=AE_MULFP32X16X2RAS_L(tmp2, tmp_con);

		tmp1=AE_SLAI32S(tmp1, 1);
		tmp2=AE_SLAI32S(tmp2, 1);
		AE_LA32X2_IP(tmp3,align5, p_EE);
		AE_LA32X2_IP(tmp4,align5, p_EE);
		tmp3=AE_SUB32S(tmp3, tmp1);
		tmp4=AE_SUB32S(tmp4, tmp2);
		bool2 = AE_LE32(tmp3, tmp_con1);//±È½Ï£¬do<=d1Îª1
		AE_MOVT32X2(tmp3, tmp_con1, bool2);
		bool2 = AE_LE32(tmp4, tmp_con1);//±È½Ï£¬do<=d1Îª1
	    AE_MOVT32X2(tmp4, tmp_con1, bool2);
	    AE_SA32X2_IP(tmp3,align6, p_RRstep);
	    AE_SA32X2_IP(tmp4,align6, p_RRstep);
		//RRstep[i] = DVTX_MAX(DVTXOP_L_sub(EE[i], DVTXOP_L_shl(Ltmp, 1)), -1); //23, 8 * /	error floor PARA_PWR_MIN_ECHO_REGRESSION*2^8=1024...
		//RR[i] = DVTX_MAX(RRstep[i], 0); //23, 8 * /	error floor PARA_PWR_MIN_ECHO_REGRESSION*2^8=1024...
	    bool2 = AE_LE32(tmp3, tmp_con2);
	    AE_MOVT32X2(tmp2, tmp_con2, bool2);
	    bool2 = AE_LE32(tmp4, tmp_con2);
	    AE_MOVT32X2(tmp4, tmp_con2, bool2);
	    AE_SA32X2_IP(tmp3,align7, p_RR);
	    AE_SA32X2_IP(tmp4,align7, p_RR);
	}
	AE_SA64POS_FP(align6, p_RRstep);
	AE_SA64POS_FP(align7, p_RR);
}
#endif
#else
#ifndef fx_SolomonVoice_FNLMS_error_cal_vector_OPT_DSP
void fx_SolomonVoice_FNLMS_error_cal(int *EE, int *DD, int *DD2, int *RR, int *RRstep, short *W, short *W2, short NHalfFFT)
{
	short i;
	int Ltmp, Ltmp1, Ltmp2;

	//calculate FNLMS error
	for (i = 0; i < NHalfFFT; i++)
	{
		Ltmp1 = DVTXOP_L_mpy_ls(DD[i], W[i]);//Q23,8*Q5.10=q28,18-15=q28.3
		Ltmp2 = DVTXOP_L_mpy_ls(DD2[i], W2[i]);//Q23,8*Q5.10=q28,18-15=q28.3
											   //		if (i < 96)
											   //		{
											   //			Ltmp = DVTXOP_L_mpy_ls(DVTXOP_L_add(Ltmp1, Ltmp2), 25000);
											   //			RRstep[i] = DVTX_MAX(DVTXOP_L_sub(EE[i], DVTXOP_L_shl(Ltmp, 1)), -1); //23, 8 * /	error floor PARA_PWR_MIN_ECHO_REGRESSION*2^8=1024...
											   //		}
											   //		else
											   //		{
		Ltmp = DVTXOP_L_mpy_ls(DVTXOP_L_add(Ltmp1, Ltmp2), 25000);
		RRstep[i] = DVTX_MAX(DVTXOP_L_sub(EE[i], DVTXOP_L_shl(Ltmp, 1)), -1); //23, 8 * /	error floor PARA_PWR_MIN_ECHO_REGRESSION*2^8=1024...			
																			  //		}
		RR[i] = DVTX_MAX(RRstep[i], 0); //23, 8 * /	error floor PARA_PWR_MIN_ECHO_REGRESSION*2^8=1024...
	}

}
#else
void fx_SolomonVoice_FNLMS_error_cal(int *EE, int *DD, int *DD2, int *RR, int *RRstep, short *W, short *W2, short NHalfFFT)
{
	short i;
	ae_int16x4 tmpW, tmpW2, tmpdata;
	ae_int32x2 Ltmp1, Ltmp2, Ltmp3, Lmin, Lzero;
	ae_int64 LLtmp1, LLtmp2;
	ae_int16x4 *pW, *pW2;
	ae_int32x2 *pEE, *pDD, *pDD2, *pRRstep_out, *pRR_out;
	ae_valign align_W, align_W2, align_EE, align_DD, align_DD2;
	ae_valign align_RRstep_out, align_RR_out;
	pW = (ae_int16x4 *)&W[0];
	pW2 = (ae_int16x4 *)&W2[0];
	pEE = (ae_int32x2 *)&EE[0];
	pDD = (ae_int32x2 *)&DD[0];
	pDD2 = (ae_int32x2 *)&DD2[0];
	pRRstep_out = (ae_int32x2 *)&RRstep[0];
	pRR_out = (ae_int32x2 *)&RR[0];
	align_W = AE_LA64_PP(pW);
	align_W2 = AE_LA64_PP(pW2);
	align_EE = AE_LA64_PP(pEE);
	align_DD = AE_LA64_PP(pDD);
	align_DD2 = AE_LA64_PP(pDD2);
	align_RRstep_out = AE_ZALIGN64();
	align_RR_out = AE_ZALIGN64();
	ae_int32x2 mask = AE_MOVDA32(0xfffffffe);
	Lmin = AE_MOVDA32(-1);
	Lzero = AE_MOVDA32(0);
	tmpdata = AE_MOVDA16(25000);
	for(i = 0; i < NHalfFFT; i += 4)
	{
		AE_LA16X4_IP(tmpW, align_W, pW);
		AE_LA16X4_IP(tmpW2, align_W2, pW2);

		AE_LA32X2_IP(Ltmp1, align_DD, pDD);
		//DVTXOP_L_mpy_ls Ltmp1 * tmpW = Ltmp2
		Ltmp3 = AE_AND32(Ltmp1, mask);
		LLtmp1 = AE_MUL32X16_L2(Ltmp3, tmpW);
		LLtmp2 = AE_MUL32X16_H3(Ltmp3, tmpW);
		LLtmp1 = AE_SLAI64S(LLtmp1, 17);
		LLtmp2 = AE_SLAI64S(LLtmp2, 17);
		Ltmp2 = AE_TRUNCI32X2F64S(LLtmp2, LLtmp1, 0);

		AE_LA32X2_IP(Ltmp1, align_DD2, pDD2);
		//DVTXOP_L_mpy_ls Ltmp1 * tmpW2 = Ltmp3
		Ltmp3 = AE_AND32(Ltmp1, mask);
		LLtmp1 = AE_MUL32X16_L2(Ltmp3, tmpW2);
		LLtmp2 = AE_MUL32X16_H3(Ltmp3, tmpW2);
		LLtmp1 = AE_SLAI64S(LLtmp1, 17);
		LLtmp2 = AE_SLAI64S(LLtmp2, 17);
		Ltmp3 = AE_TRUNCI32X2F64S(LLtmp2, LLtmp1, 0);

		Ltmp1 = AE_ADD32S(Ltmp2, Ltmp3);
		//DVTXOP_L_mpy_ls Ltmp1 * tmpdata = Ltmp3
		Ltmp3 = AE_AND32(Ltmp1, mask);
		LLtmp1 = AE_MUL32X16_L2(Ltmp3, tmpdata);
		LLtmp2 = AE_MUL32X16_H3(Ltmp3, tmpdata);
		LLtmp1 = AE_SLAI64S(LLtmp1, 17);
		LLtmp2 = AE_SLAI64S(LLtmp2, 17);
		Ltmp3 = AE_TRUNCI32X2F64S(LLtmp2, LLtmp1, 0);

		Ltmp2 = AE_SLAA32S(Ltmp3, 1);
		AE_LA32X2_IP(Ltmp1, align_EE, pEE);
		Ltmp3 = AE_SUB32S(Ltmp1, Ltmp2);
		Ltmp1 = AE_MAX32(Ltmp3, Lmin);
		Ltmp2 = AE_MAX32(Ltmp1, Lzero);
		AE_SA32X2_IP(Ltmp1, align_RRstep_out, pRRstep_out);
		AE_SA32X2_IP(Ltmp2, align_RR_out, pRR_out);

		///////
		AE_LA32X2_IP(Ltmp1, align_DD, pDD);
		//DVTXOP_L_mpy_ls Ltmp1 * tmpW = Ltmp2
		Ltmp3 = AE_AND32(Ltmp1, mask);
		LLtmp1 = AE_MUL32X16_L0(Ltmp3, tmpW);
		LLtmp2 = AE_MUL32X16_H1(Ltmp3, tmpW);
		LLtmp1 = AE_SLAI64S(LLtmp1, 17);
		LLtmp2 = AE_SLAI64S(LLtmp2, 17);
		Ltmp2 = AE_TRUNCI32X2F64S(LLtmp2, LLtmp1, 0);

		AE_LA32X2_IP(Ltmp1, align_DD2, pDD2);
		//DVTXOP_L_mpy_ls Ltmp1 * tmpW2 = Ltmp3
		Ltmp3 = AE_AND32(Ltmp1, mask);
		LLtmp1 = AE_MUL32X16_L0(Ltmp3, tmpW2);
		LLtmp2 = AE_MUL32X16_H1(Ltmp3, tmpW2);
		LLtmp1 = AE_SLAI64S(LLtmp1, 17);
		LLtmp2 = AE_SLAI64S(LLtmp2, 17);
		Ltmp3 = AE_TRUNCI32X2F64S(LLtmp2, LLtmp1, 0);

		Ltmp1 = AE_ADD32S(Ltmp2, Ltmp3);
		//DVTXOP_L_mpy_ls Ltmp1 * tmpdata = Ltmp3
		Ltmp3 = AE_AND32(Ltmp1, mask);
		LLtmp1 = AE_MUL32X16_L2(Ltmp3, tmpdata);
		LLtmp2 = AE_MUL32X16_H3(Ltmp3, tmpdata);
		LLtmp1 = AE_SLAI64S(LLtmp1, 17);
		LLtmp2 = AE_SLAI64S(LLtmp2, 17);
		Ltmp3 = AE_TRUNCI32X2F64S(LLtmp2, LLtmp1, 0);

		Ltmp2 = AE_SLAA32S(Ltmp3, 1);
		AE_LA32X2_IP(Ltmp1, align_EE, pEE);
		Ltmp3 = AE_SUB32S(Ltmp1, Ltmp2);
		Ltmp1 = AE_MAX32(Ltmp3, Lmin);
		Ltmp2 = AE_MAX32(Ltmp1, Lzero);
		AE_SA32X2_IP(Ltmp1, align_RRstep_out, pRRstep_out);
		AE_SA32X2_IP(Ltmp2, align_RR_out, pRR_out);
	}
	AE_SA64POS_FP(align_RRstep_out, pRRstep_out);
	AE_SA64POS_FP(align_RR_out, pRR_out);
}
#endif
#endif
#ifdef FNLMS_MEMCPY_RED
/*Solomonvoice function
two FNLMS filters
over estimation for high band is applied
DD : Q23.8
EE : Q23.8
RR : Q23.8
W  : Q5,10 --> 0.15 changed
*/
void fx_SolomonVoice_FNLMS_error_cal_comb_sh(int *EE, int *DD, int *DD2, int *RR, int *RRstep, short *W, short *W2, short NHalfFFT)
{
	short i;
	int Ltmp, Ltmp1, Ltmp2;

	//calculate FNLMS error
	for (i = 0; i < 40; i++)
	{
		Ltmp1 = DVTXOP_L_mpy_ls(DVTXOP_L_shl(DD[i],6), W[i]);//Q23,8*Q5.10=q28,18-15=q28.3
		Ltmp2 = DVTXOP_L_mpy_ls(DVTXOP_L_shl(DD2[i],6), W2[i]);//Q23,8*Q5.10=q28,18-15=q28.3
											   //		if (i < 96)
											   //		{
											   //			Ltmp = DVTXOP_L_mpy_ls(DVTXOP_L_add(Ltmp1, Ltmp2), 25000);
											   //			RRstep[i] = DVTX_MAX(DVTXOP_L_sub(EE[i], DVTXOP_L_shl(Ltmp, 1)), -1); //23, 8 * /	error floor PARA_PWR_MIN_ECHO_REGRESSION*2^8=1024...
											   //		}
											   //		else
											   //		{
		Ltmp = DVTXOP_L_mpy_ls(DVTXOP_L_add(Ltmp1, Ltmp2), 25000);
		RRstep[i] = DVTX_MAX(DVTXOP_L_sub(EE[i], DVTXOP_L_shl(Ltmp, 1)), -1); //23, 8 * /	error floor PARA_PWR_MIN_ECHO_REGRESSION*2^8=1024...
																			  //		}
		RR[i] = DVTX_MAX(RRstep[i], 0); //23, 8 * /	error floor PARA_PWR_MIN_ECHO_REGRESSION*2^8=1024...
	}
	for (i = 40; i < NHalfFFT; i++)
	{
		Ltmp1 = DVTXOP_L_mpy_ls(DVTXOP_L_shl(DD[i],13), W[i]);//Q23,8*Q5.10=q28,18-15=q28.3
		Ltmp2 = DVTXOP_L_mpy_ls(DVTXOP_L_shl(DD2[i],13), W2[i]);//Q23,8*Q5.10=q28,18-15=q28.3
											   //		if (i < 96)
											   //		{
											   //			Ltmp = DVTXOP_L_mpy_ls(DVTXOP_L_add(Ltmp1, Ltmp2), 25000);
											   //			RRstep[i] = DVTX_MAX(DVTXOP_L_sub(EE[i], DVTXOP_L_shl(Ltmp, 1)), -1); //23, 8 * /	error floor PARA_PWR_MIN_ECHO_REGRESSION*2^8=1024...
											   //		}
											   //		else
											   //		{
		Ltmp = DVTXOP_L_mpy_ls(DVTXOP_L_add(Ltmp1, Ltmp2), 25000);
		RRstep[i] = DVTX_MAX(DVTXOP_L_sub(EE[i], DVTXOP_L_shl(Ltmp, 1)), -1); //23, 8 * /	error floor PARA_PWR_MIN_ECHO_REGRESSION*2^8=1024...
																			  //		}
		RR[i] = DVTX_MAX(RRstep[i], 0); //23, 8 * /	error floor PARA_PWR_MIN_ECHO_REGRESSION*2^8=1024...
	}
}
#endif
/* SolomonVoice_SubBlocks #29:
additional SPP calculation
loop up table : P_H1_exp1_Q15
Q15.16
*/
void fx_SolomonVoice_2nd_PH1_estimation(short *PH1, int *EE, int *Npsd, short Xi, short SPPtable_flag, short NORM, short Nband)
{
	short i, tmp;
	int Ltmp, Ltmp2, Ltmp5;

	for (i = 0; i <= Nband; i++)
	{
		Ltmp5 = DVTXOP_L_shl(EE[i], (short)(15 - (2 * NORM))); /*30,1 -> 23,8*/
		Ltmp2 = fx_SolomonVoice_32bit_Divide(Ltmp5, Npsd[i], 0, 16);//Q16.15

		Ltmp = DVTX_MIN(DVTX_MAX(Ltmp2, 256), 262144);//min = 2^15*(1/128) max = 2^15*(8)		
		tmp = DVTXOP_extract_l(DVTXOP_L_shr(DVTXOP_L_sub(Ltmp, 256), 11));//16,15 2^8<snr<2^19¸¦ 128 look-up table·Î...		
		tmp = DVTX_MIN(DVTX_MAX(tmp, 0), 128);

		Ltmp = 32 + 256 * (tmp);
		PH1[i] = bayes_prob(SPPtable_flag, Xi, Ltmp, 0);
	}
}

void fx_SolomonVoice_recursive_avg_SS_highcomplexity(short *avg, short *in, short forgetNew, short forgetOld, short Nand)
{
	short i, tmp, norm_shift;
	int Ltmp1, Ltmp2;

	for (i = 0; i <= Nand; i++)
	{
		//calculate P_H1_ravg
		norm_shift = DVTXOP_norm_s(in[i]);
		tmp = DVTXOP_shl(in[i], norm_shift);
		Ltmp1 = DVTXOP_L_shr_r(DVTXOP_L_mult(forgetNew, tmp), norm_shift); //0.1
		norm_shift = DVTXOP_norm_s(avg[i]);
		tmp = DVTXOP_shl(avg[i], norm_shift);
		Ltmp2 = DVTXOP_L_shr_r(DVTXOP_L_mult(forgetOld, tmp), norm_shift); //0.9
		avg[i] = DVTXOP_extract_h(DVTXOP_L_add(Ltmp1, Ltmp2));
	}
}

void fx_SolomonVoice_prevent_stagnation_PH1(short *ph1, short *ph1_avg, short Nband)
{
	short i, tmp;


#ifndef KHW_OPTI_20191216
	for (i = 0; i <= Nband; i++)
	{
		// prevent stagnation
		if (FLAG_WB_OuterECNSOnly == 1) // WB Á¤·®ÃøÁ¤
		{
			if (i < 13) // 13th band 1200Hz
				tmp = 32730;
			else
				tmp = DVTX_WORD16_0_99;
		}
		else
		{
			tmp = DVTX_WORD16_0_99;
		}
		if (ph1_avg[i] > tmp) //DVTX_WORD16_0_99 32730
			ph1[i] = tmp;
	}
#else
	if (FLAG_WB_OuterECNSOnly == 1) // WB Á¤·®ÃøÁ¤
	{
		short tmp;
		for (i = 0; i <= Nband; i++)
		{
			if (i < 13) // 13th band 1200Hz
				tmp = 32730;
			else
				tmp = DVTX_WORD16_0_99;

			if (ph1_avg[i] > tmp) //DVTX_WORD16_0_99 32730
				ph1[i] = tmp;
		}
	}
	else
	{
		for (i = 0; i <= Nband; i++)
		{
			if (ph1_avg[i] > DVTX_WORD16_0_99) //DVTX_WORD16_0_99 32730
				ph1[i] = DVTX_WORD16_0_99;
		}
	}

#endif


}

#ifndef KHW_OPTI_20191216
void fx_SolomonVoice_prevent_stagnation_PH1_1mic(short *ph1, short *ph1_avg, short Nband)
{
	short i, tmp;

	for (i = 0; i <= Nband; i++)
	{
		// prevent stagnation
		if (i < 13) // 13th band 1200Hz
			tmp = 32730;
		else
			tmp = DVTX_WORD16_0_99;

		//tmp = DVTX_WORD16_0_99;
		if (ph1_avg[i] > tmp) //DVTX_WORD16_0_99 32730
			ph1[i] = tmp;
	}
}
#endif
/*Solomonvoice function
Decision directed a priori SNR estimation
SNRpost : Q 16.15
SNRprio : Q 16.15
*/
#ifndef fx_SolomonVoice_DD_SNRprio_estimation_OPT_DSP
void fx_SolomonVoice_DD_SNRprio_estimation(int *SNRprio, int *SNRprioCopy, int *SNRpost, int *SNRpostPrev, short *G, short b_old, short b_new, int SNRmin, int SNRmax, short Nband)
{
	short i, norm_shift, GbyG, tmp1;
	int L_SNR_inst, Ltmp, L_GbySNRpost;

	for (i = 0; i <= Nband; i++)
	{
		// Decision directed
		L_SNR_inst = DVTX_MAX(DVTXOP_L_sub(SNRpost[i], DVTX_MAX_16), 0); //SNRpost-1.0

		norm_shift = DVTXOP_norm_s(G[i]);
		tmp1 = DVTXOP_shl(G[i], norm_shift);
		Ltmp = DVTXOP_L_mult(tmp1, tmp1);
		Ltmp = DVTXOP_L_shr(Ltmp, 2 * norm_shift);
		GbyG = DVTXOP_extract_h(Ltmp);  //G^2

		L_GbySNRpost = DVTXOP_L_mpy_ls(SNRpostPrev[i], GbyG); //G^2*SNRprev

		Ltmp = fx_SolomonVoice_recursiveAVG_ls(L_GbySNRpost, L_SNR_inst, b_old, b_new, 0, 0); // fixed Q

		SNRprio[i] = DVTX_MIN(DVTX_MAX(Ltmp, SNRmin), SNRmax);//min = 2^15*(1/128) max = 2^15*(256)
		SNRprioCopy[i] = SNRprio[i]; // copy the out SNRprio

		SNRpostPrev[i] = SNRpost[i];
	}
}
#else
void fx_SolomonVoice_DD_SNRprio_estimation(int *SNRprio, int *SNRprioCopy, int *SNRpost, int *SNRpostPrev, short *G, short b_old, short b_new, int SNRmin, int SNRmax, short Nband)
{
	short i, num;
	short GbyG, data1;
	int L_SNR_inst, Ltmp, L_GbySNRpost;

	ae_int16x4 tmp1, Beold, Benew;
	ae_int32x2 Ltmp1, Ltmp2, Ltmp3, Lmax, Lzero, LSNRmax, LSNRmin;
	ae_int64 LLtmp1, LLtmp2;
	ae_int32x2 *pSNRprio, *pSNRprioCopy, *pSNRpost, *pSNRpostPrev_in, *pSNRpostPrev_out;
	ae_int16x4 *pG;
	ae_int32x2 mask = AE_MOVDA32X2(0xfffffffe, 0xfffffffe);
	ae_valign align_SNRprio, align_SNRprioCopy, align_SNRpost, align_SNRpostPrev_in, align_SNRpostPrev_out, align_G;
	pSNRprio = (ae_int32x2 *)&SNRprio[0];
	pSNRprioCopy = (ae_int32x2 *)&SNRprioCopy[0];
	pSNRpost = (ae_int32x2 *)&SNRpost[0];
	pSNRpostPrev_in = pSNRpostPrev_out = (ae_int32x2 *)&SNRpostPrev[0];
	pG = (ae_int16x4 *)&G[0];
	align_SNRprio = AE_ZALIGN64();
	align_SNRprioCopy = AE_ZALIGN64();
	align_SNRpost = AE_LA64_PP(pSNRpost);
	align_SNRpostPrev_in = AE_LA64_PP(pSNRpostPrev_in);
	align_SNRpostPrev_out = AE_ZALIGN64();
	align_G = AE_LA64_PP(pG);
	num = (Nband+1) / 4;
	Lmax = AE_MOVDA32(DVTX_MAX_16);
	Lzero = AE_MOVDA32(0);
	Beold = AE_MOVDA16(b_old);
	Benew = AE_MOVDA16(b_new);
	LSNRmax = AE_MOVDA32(SNRmax);
	LSNRmin = AE_MOVDA32(SNRmin);
	for(i = 0; i < num; i++)
	{
		AE_LA16X4_IP(tmp1, align_G, pG);
		AE_MULF16X4SS(Ltmp2, Ltmp3, tmp1, tmp1);
		tmp1 = AE_TRUNC16X4F32(Ltmp2, Ltmp3);//tmp1 -> GbyG
		AE_LA32X2_IP(Ltmp1, align_SNRpost, pSNRpost);
		AE_LA32X2_IP(Ltmp2, align_SNRpostPrev_in, pSNRpostPrev_in);
		AE_SA32X2_IP(Ltmp1, align_SNRpostPrev_out, pSNRpostPrev_out);
		Ltmp3 = AE_SUB32S(Ltmp1, Lmax);
		Ltmp1 = AE_MAX32(Ltmp3, Lzero);//Ltmp1 ->L_SNR_inst
		//Ltmp3 = DVTXOP_L_mpy_ls Ltmp2 * tmp1
		Ltmp3 = AE_AND32(Ltmp2, mask);
		LLtmp1 = AE_MUL32X16_L2(Ltmp3, tmp1);
		LLtmp2 = AE_MUL32X16_H3(Ltmp3, tmp1);
		LLtmp1 = AE_SLAI64S(LLtmp1, 17);
		LLtmp2 = AE_SLAI64S(LLtmp2, 17);
		Ltmp3 = AE_TRUNCI32X2F64S(LLtmp2, LLtmp1,0);//Ltmp3 ->L_GbySNRpost
		Ltmp2 = fx_SolomonVoice_recursiveAVG_ls_2_vector(Ltmp3, Ltmp1, Beold, Benew,0);
		Ltmp1 = AE_MAX32(Ltmp2, LSNRmin);
		Ltmp2 = AE_MIN32(Ltmp1, LSNRmax);
		AE_SA32X2_IP(Ltmp2, align_SNRprio, pSNRprio);
		AE_SA32X2_IP(Ltmp2, align_SNRprioCopy, pSNRprioCopy);

		AE_LA32X2_IP(Ltmp1, align_SNRpost, pSNRpost);
		AE_LA32X2_IP(Ltmp2, align_SNRpostPrev_in, pSNRpostPrev_in);
		AE_SA32X2_IP(Ltmp1, align_SNRpostPrev_out, pSNRpostPrev_out);
		Ltmp3 = AE_SUB32S(Ltmp1, Lmax);
		Ltmp1 = AE_MAX32(Ltmp3, Lzero);//Ltmp1 ->L_SNR_inst
		//Ltmp3 = DVTXOP_L_mpy_ls Ltmp2 * tmp1
		Ltmp3 = AE_AND32(Ltmp2, mask);
		LLtmp1 = AE_MUL32X16_L0(Ltmp3, tmp1);
		LLtmp2 = AE_MUL32X16_H1(Ltmp3, tmp1);
		LLtmp1 = AE_SLAI64S(LLtmp1, 17);
		LLtmp2 = AE_SLAI64S(LLtmp2, 17);
		Ltmp3 = AE_TRUNCI32X2F64S(LLtmp2, LLtmp1,0);
		Ltmp2 = fx_SolomonVoice_recursiveAVG_ls_2_vector(Ltmp3, Ltmp1, Beold, Benew,0);
		Ltmp1 = AE_MAX32(Ltmp2, LSNRmin);
		Ltmp2 = AE_MIN32(Ltmp1, LSNRmax);
		AE_SA32X2_IP(Ltmp2, align_SNRprio, pSNRprio);
		AE_SA32X2_IP(Ltmp2, align_SNRprioCopy, pSNRprioCopy);
	}
	AE_SA64POS_FP(align_SNRpostPrev_out, pSNRpostPrev_out);
	AE_SA64POS_FP(align_SNRprio, pSNRprio);
	AE_SA64POS_FP(align_SNRprioCopy, pSNRprioCopy);
	for(i = num * 4; i <= Nband; i++)
	{
		L_SNR_inst = DVTX_MAX(DVTXOP_L_sub(SNRpost[i], DVTX_MAX_16), 0); //SNRpost-1.0

		data1 = G[i];
		Ltmp = DVTXOP_L_mult(data1, data1);
		GbyG = DVTXOP_extract_h(Ltmp);  //G^2

		L_GbySNRpost = DVTXOP_L_mpy_ls(SNRpostPrev[i], GbyG); //G^2*SNRprev

		Ltmp = fx_SolomonVoice_recursiveAVG_ls(L_GbySNRpost, L_SNR_inst, b_old, b_new, 0, 0); // fixed Q

		SNRprio[i] = DVTX_MIN(DVTX_MAX(Ltmp, SNRmin), SNRmax);//min = 2^15*(1/128) max = 2^15*(256)
		SNRprioCopy[i] = SNRprio[i]; // copy the out SNRprio
		SNRpostPrev[i] = SNRpost[i];
	}
}

#endif
void fx_SolomonVoice_Npsd_2nd_estimation_1mic(int *Npsd, int *EE, short *PH1, short MinNpsd, short NORM, short Q, short Nband)
{
	short i, forgetOld, forgetNew;

	for (i = 0; i <= Nband; i++)
	{
		////noise esimation 
		forgetOld = DVTXOP_add(DVTX_WORD16_0_9, DVTXOP_mult(DVTX_WORD16_0_1, PH1[i])); //p=0.85+0.15*p1;
		forgetNew = DVTXOP_sub(DVTX_MAX_16, forgetOld);

		/*30,1 -> 15,16*/
		Npsd[i] = fx_SolomonVoice_recursiveAVG_ls(Npsd[i], EE[i], forgetOld, forgetNew, NORM, Q);

		if (Npsd[i] < MinNpsd) //16
			Npsd[i] = MinNpsd;
	}
}

/*Solomonvoice function
ref. Q format : Q23.8, (Q=7)
*/
void fx_SolomonVoice_Npsd_Silence_estimation(int *NpsdSilence, int *EE, short FlagSilence, int b_old, int b_new, short blk_norm, short Q, short Nband)
{
	short i;

	if (FlagSilence == 0)
	{
		for (i = 0; i <= Nband; i++)
		{
			//Q23,8			
			NpsdSilence[i] = fx_SolomonVoice_recursiveAVG_ll(NpsdSilence[i], EE[i], b_old, b_new, blk_norm, Q);
		}
	}
}

#ifndef fx_SolomonVoice_FFTbin_gain_applying_OPT_DSP
void fx_SolomonVoice_FFTbin_gain_applying(short *OutBin, short *GainBin, short NHalfFFT)
{
	short i;

	for (i = 0; i < NHalfFFT; i++)
	{
		OutBin[2 * i] = DVTXOP_mult_r(OutBin[2 * i], GainBin[i]);
		OutBin[2 * i + 1] = DVTXOP_mult_r(OutBin[2 * i + 1], GainBin[i]);
	}
}
#else
void fx_SolomonVoice_FFTbin_gain_applying(short *OutBin, short *GainBin, short NHalfFFT) //NHalfFFT must be integer*4
{
	short i;
	ae_f16x4 *ae_pb1, *ae_pb2, *ae_pg;
	ae_f16x4 ae_bin1, ae_bin2, ae_gain1, ae_gain2;
	ae_valign ae_alignpb1, ae_alignpb2, ae_alignpg;

	ae_pb1 = (ae_f16x4 *)OutBin;
	ae_pb2 = (ae_f16x4 *)OutBin;
	ae_pg = (ae_f16x4 *)GainBin;

	ae_alignpb1 = AE_LA64_PP(ae_pb1);
	ae_alignpb2 = AE_ZALIGN64();
	ae_alignpg = AE_LA64_PP(ae_pg);
	for(i=0; i<(NHalfFFT>>2); i++)
	{
		AE_LA16X4_IP(ae_bin1, ae_alignpb1, ae_pb1);
		AE_LA16X4_IP(ae_bin2, ae_alignpb1, ae_pb1);
		AE_LA16X4_IP(ae_gain1, ae_alignpg, ae_pg);
		ae_gain2 = AE_SEL16_7362(ae_gain1, ae_gain1);
		ae_gain1 = AE_SEL16_5410(ae_gain1, ae_gain1);
		ae_gain1 = AE_SEL16_7362(ae_gain1, ae_gain1);
		ae_bin1 = AE_MULFP16X4RAS(ae_bin1, ae_gain2);
		ae_bin2 = AE_MULFP16X4RAS(ae_bin2, ae_gain1);
		AE_SA16X4_IP(ae_bin1, ae_alignpb2, ae_pb2);
		AE_SA16X4_IP(ae_bin2, ae_alignpb2, ae_pb2);
	}
	AE_SA64POS_FP(ae_alignpb2, ae_pb2);
}

#endif


/*Solomonvoice function
1st order recursive avg. for 32bit values. Forgetting facotor is also 32bit
output Q format : 30-Q,Q+1
*/
int fx_SolomonVoice_recursiveAVG_ll(int OldVal, int NewVal, int beOld, int beNew, short BLK_NORM, short Q)
{
	short norm_shift;
	int Ltmp1, Ltmp2, Ltmp3;

	norm_shift = DVTXOP_norm_l(NewVal);
	Ltmp1 = DVTXOP_L_shl(NewVal, norm_shift);
	Ltmp1 = DVTXOP_L_mpy_ls(beNew, DVTXOP_extract_h(Ltmp1));
	Ltmp1 = DVTXOP_L_shr(Ltmp1, norm_shift);

	Ltmp2 = DVTXOP_L_shl(Ltmp1, (short)(Q - (2 * BLK_NORM))); /*30,1 -> 30-Q,Q+1*/


	norm_shift = DVTXOP_norm_l(OldVal);
	Ltmp1 = DVTXOP_L_shl(OldVal, norm_shift);
	Ltmp3 = DVTXOP_L_mpy_ls(beOld, DVTXOP_extract_h(Ltmp1));
	Ltmp3 = DVTXOP_L_shr(Ltmp3, norm_shift);

	OldVal = DVTXOP_L_add(Ltmp3, Ltmp2); //23,8

	return OldVal;
}
#ifndef BM_SRCB_1019_OPT1
void fx_SolomonVoice_WienerQ31_to_GainQ15_Gmin(short *G, int *Wiener, short powerIndex, short Nband, short Gmin)
{
	short i;

	if (powerIndex == 1)
	{
		if (Gmin == 32767)
		{
#ifndef OPT_int_sqrt_0_25_fourX       // NOT BIT MATCH.   strange ????????????
			for (i = 0; i <= Nband; i++)
			{
				G[i] = int_sqrt_0_25(Wiener[i]);
			}
#else
/*
			for (i = 0; i <= Nband; i+=4)
			{
				//		G[i] = int_sqrt_0_25(Wiener[i]);
				int_sqrt_0_25_four(&Wiener[i], &G[i]);
			}
*/
			int_sqrt_0_25_four(&Wiener[0], &G[0]);
			int_sqrt_0_25_four(&Wiener[4], &G[4]);
			int_sqrt_0_25_four(&Wiener[8], &G[8]);
			int_sqrt_0_25_four(&Wiener[12], &G[12]);
			int_sqrt_0_25_four(&Wiener[16], &G[16]);
			int_sqrt_0_25_four(&Wiener[20], &G[20]);
			int_sqrt_0_25_four(&Wiener[24], &G[24]);
/*
			if(Nband == 39)
			{
				int_sqrt_0_25_four(&Wiener[28], &G[28]);
				int_sqrt_0_25_four(&Wiener[32], &G[32]);
				int_sqrt_0_25_four(&Wiener[36], &G[36]);
			}
*/
			for (i = 28; i <= Nband; i++)
			{
				G[i] = int_sqrt_0_25(Wiener[i]);
			}


#endif
		}
		else {
#ifndef OPT_int_sqrt_0_25_four
			for (i = 0; i <= 20; i++) //~2.5kHz
			{
				G[i] = int_sqrt_0_25(Wiener[i]);
			}
#else
			int_sqrt_0_25_four(&Wiener[0], &G[0]);
			int_sqrt_0_25_four(&Wiener[4], &G[4]);
			int_sqrt_0_25_four(&Wiener[8], &G[8]);
			int_sqrt_0_25_four(&Wiener[12], &G[12]);
			int_sqrt_0_25_four(&Wiener[16], &G[16]);
			G[20] = int_sqrt_0_25(Wiener[20]);
			i=21;
#endif
			for (; i <= DVTX_BAND_INDEX_4kHz; i++)
			{
				G[i] = int_sqrt_0_50(Wiener[i]);
			}
			for (; i <= Nband; i++)
			{
				G[i] = int_sqrt_0_75(Wiener[i]);
			}
		}
	}
	else if (powerIndex == 2)
	{
		for (i = 0; i <= Nband; i++)
		{
			G[i] = int_sqrt_0_50(Wiener[i]);
		}
	}
	else if (powerIndex == 3)
	{
		for (i = 0; i <= Nband; i++)
		{
			G[i] = int_sqrt_0_75(Wiener[i]);
		}
	}
}
#else
void fx_SolomonVoice_WienerQ31_to_GainQ15_Gmin(short *G, int *Wiener, short powerIndex, short Nband, short Gmin)
{
	short i;

	if (powerIndex == 1)
	{
		if(Gmin == 32767)
		{
#ifndef OPT_int_sqrt_0_25_fourX
			for (i = 0; i <= Nband; i++)
			{
				G[i] = int_sqrt_0_25(Wiener[i]);
			}
#else
			for (i = 0; i <= Nband; i+=4)
			{
				int_sqrt_0_25_four(&Wiener[i], &G[i]);
			}
#endif
		}
		else {
#ifndef OPT_int_sqrt_0_25_four
			for (i = 0; i <= 20; i++) //~2.5kHz
			{
				G[i] = int_sqrt_0_25(Wiener[i]);
			}
#else
			int_sqrt_0_25_four(&Wiener[0], &G[0]);
			int_sqrt_0_25_four(&Wiener[4], &G[4]);
			int_sqrt_0_25_four(&Wiener[8], &G[8]);
			int_sqrt_0_25_four(&Wiener[12], &G[12]);
			int_sqrt_0_25_four(&Wiener[16], &G[16]);
			G[20] = int_sqrt_0_25(Wiener[20]);
			i=21;
#endif
			for (; i <= DVTX_BAND_INDEX_4kHz; i++)
			{
				G[i] = int_sqrt_0_50(Wiener[i]);
			}
			for (; i <= Nband; i++)
			{
				G[i] = int_sqrt_0_75(Wiener[i]);
			}
		}
	}
	else if (powerIndex == 2)
	{
		for (i = 0; i <= Nband; i++)
		{
			G[i] = int_sqrt_0_50(Wiener[i]);
		}
	}
	else if (powerIndex == 3)
	{
		for (i = 0; i <= Nband; i++)
		{
			G[i] = int_sqrt_0_75(Wiener[i]);
		}
	}
}
#endif
/* SolomonVoice_SubBlocks #19:
initial SNR estimation :
EE, NN, DD : Q23.8
L_SNR_by_Nmmse_ini
Q16.15
//min = 2^15*(1/512) max = 2^15*(512)
*/
void fx_SolomonVoice_initial_SNR_estimation(int *SNRout, int *EE, int *NN, int*DD, short DDgain, short Qsnr, short Nband)
{
	short i;
	int Ltmp, Ltmp4;
	// SNR calculation: Esqr/Npsd		

	for (i = 0; i <= Nband; i++)
	{
		Ltmp = DVTXOP_L_mpy_ls(DD[i], DDgain); // Dsqr * 1/16
		Ltmp = DVTXOP_L_add(NN[i], Ltmp);
		Ltmp4 = fx_SolomonVoice_32bit_Divide(EE[i], Ltmp, 1, Qsnr);//Q16.15

		SNRout[i] = DVTX_MIN(DVTX_MAX(Ltmp4, 64), 16777216);//min = 2^15*(1/512) max = 2^15*(512)						
	}
}

/*Solomonvoice function
Decision directed a priori SNR estimation
SNRprio : Q16.15
Gwiener : Q0.31
L_Gavg  : Q0.15
*/
int fx_SolomonVoice_Wiener_gainvector_Q31(int *Gwiener, int *SNRprio, short Nband, short OneOverNband)
{
	short i;
	int L_SNRplusONE, L_Gavg;

	L_Gavg = 0;
	for (i = 0; i <= Nband; i++)
	{
		L_SNRplusONE = DVTXOP_L_add(SNRprio[i], DVTX_MAX_16);

		Gwiener[i] = fx_SolomonVoice_32bit_Divide(SNRprio[i], L_SNRplusONE, 0, 0);//Q0.31

		L_Gavg = DVTXOP_L_add(L_Gavg, DVTXOP_L_shr(Gwiener[i], 16)); //q16,15
	}
	L_Gavg = DVTXOP_L_mpy_ls(L_Gavg, OneOverNband); // 1/40*2^15, //q0,15

	return L_Gavg;
}

/* SolomonVoice_SubBlocks #31:
DD priori SNR calculation
first STAGE : post SNR && priori SNR
EEq30 : Q30.1
Npsd : Q16.15
outSNR : Q16.15
*/
void fx_SolomonVoice_postSNR_estimation(int* outSNR, int *EEq30, int *Npsd, short Norm, short gainNpsd, short Nband)
{
	short i;
	int Ltmp, Ltmp5, Ltmp2;

	for (i = 0; i <= Nband; i++)
	{

		Ltmp = DVTXOP_L_mpy_ls(Npsd[i], gainNpsd);
		Ltmp5 = DVTXOP_L_shl(EEq30[i], (short)(15 - (2 * Norm))); /*30,1 -> 15,16*/
		Ltmp2 = fx_SolomonVoice_32bit_Divide(Ltmp5, Ltmp, 1, 16);//Q16.15

		outSNR[i] = DVTX_MIN(DVTX_MAX(Ltmp2, 256), 4194304); //min = 2^15*(1/128) max = 2^15*(128);		
	}
}

void fx_SolomonVoice_forgetfactor_cal_Cepstral_smoothing(short *Beta_ceps_smoothing, short *Beta_ceps, short Flag_loud, short forget)
{
	short i, OneMinusFLAGsoft_SNR_ini;

	OneMinusFLAGsoft_SNR_ini = DVTXOP_sub(DVTX_MAX_16, forget);
	if (Flag_loud == 0) //if Loud signal, DVTX_ECNS_vars->ECNSbuff.tmp_beta_ceps[i]=0; else-->below
	{
		Beta_ceps[0] = DVTX_WORD16_0_1;
		Beta_ceps[1] = DVTX_WORD16_0_1;
		// FLAGsoft_SNR_ini °ªÀÌ 1¿¡ °¡±î¿ì¸é(high SNR) cepstral smoothing Àû°Ô ÇÔ
		for (i = 1; i < 3; i++) {
			Beta_ceps[2 * i] = DVTXOP_add(DVTXOP_mult(forget, DVTX_WORD16_0_01), DVTXOP_mult(OneMinusFLAGsoft_SNR_ini, DVTX_WORD16_0_2));
			Beta_ceps[2 * i + 1] = DVTXOP_add(DVTXOP_mult(forget, DVTX_WORD16_0_01), DVTXOP_mult(OneMinusFLAGsoft_SNR_ini, DVTX_WORD16_0_2));
		}
		for (i = 3; i < 16; i++) {
			Beta_ceps[2 * i] = DVTXOP_add(DVTXOP_mult(forget, DVTX_WORD16_0_5), DVTXOP_mult(OneMinusFLAGsoft_SNR_ini, DVTX_WORD16_0_92));
			Beta_ceps[2 * i + 1] = DVTXOP_add(DVTXOP_mult(forget, DVTX_WORD16_0_5), DVTXOP_mult(OneMinusFLAGsoft_SNR_ini, DVTX_WORD16_0_92));
		}
		for (i = 16; i < 32; i++) {
			Beta_ceps[2 * i] = DVTXOP_add(DVTXOP_mult(forget, DVTX_WORD16_0_8), DVTXOP_mult(OneMinusFLAGsoft_SNR_ini, DVTX_WORD16_0_92));
			Beta_ceps[2 * i + 1] = DVTXOP_add(DVTXOP_mult(forget, DVTX_WORD16_0_8), DVTXOP_mult(OneMinusFLAGsoft_SNR_ini, DVTX_WORD16_0_92));
		}
	}
	else
	{
		for (i = 0; i < 32; i++) {
			Beta_ceps[2 * i] = 0;
			Beta_ceps[2 * i + 1] = 0;
		}
	}

	for (i = 0; i < 64; i++)
		Beta_ceps_smoothing[i] = DVTXOP_add(DVTXOP_mult(Beta_ceps_smoothing[i], DVTX_WORD16_0_5), DVTXOP_mult(Beta_ceps[i], DVTX_WORD16_0_5));
}

/*Solomonvoice function
echo PSD gain = scalar gain * band gain
EchoPSD = DD*gain
*/
#ifdef fx_SolomonVoice_EchoPower_estimation_DSP_OPT//Õâ¸öÓÐÎÊÌâµÄ£¬DVTXOP_L_mpy_lsÃ»ÓÐËÄÉáÎåÈë
#if 0

#else
void fx_SolomonVoice_EchoPower_estimation(int *EchoPSD, short *EchoBandGain, short EchoGain, short Nband)
{
	short i, tmp;

//	for (i = 0; i <= Nband; i++)//Nband equals  to 27 or 39
//	{
//		// RES : residual echo PSD
//		tmp = DVTXOP_mult(EchoBandGain[i], EchoGain);
//		EchoPSD[i] = DVTXOP_L_mpy_ls(EchoPSD[i], tmp); //residual echo gain
//	}

	ae_valign align1, align2,align3;
	ae_int16x4   *p_EchoBandGain = (ae_int16x4*)EchoBandGain;
	ae_int32x2   *p_EchoPSD = (ae_int32x2*)EchoPSD;
	ae_int32x2   *p_EchoPSD_s = (ae_int32x2*)EchoPSD;
	ae_int16x4 tmp1,tmp2,tmp3,tmp4;
	ae_int32x2 tmp_int1,tmp_int2;
	ae_int16x4 tmp_cons=AE_MOVDA16( EchoGain);
	align1 = AE_LA64_PP(p_EchoBandGain);
	align2 = AE_LA64_PP(p_EchoPSD);
	align3 = AE_ZALIGN64();

	for (i = 0; i <= Nband; i+=4)//Nband equals  to 27 or 39
	{
		AE_LA16X4_IP(tmp1, align1, p_EchoBandGain);
		AE_LA32X2_IP(tmp_int1, align2, p_EchoPSD);
		AE_LA32X2_IP(tmp_int2, align2, p_EchoPSD);
		tmp1=AE_MULFP16X4S(tmp1, tmp_cons);
		tmp_int1=AE_MULFP32X16X2RAS_H(tmp_int1, tmp1);
		tmp_int2=AE_MULFP32X16X2RAS_L(tmp_int2, tmp1);
		AE_SA32X2_IP(tmp_int1, align3, p_EchoPSD_s);
		AE_SA32X2_IP(tmp_int2, align3, p_EchoPSD_s);
	}
	 AE_SA64POS_FP(align3, p_EchoPSD_s);
}
#endif
#else

#if 0
void fx_SolomonVoice_EchoPower_estimation(int *EchoPSD, short *EchoBandGain, short EchoGain, short Nband)
{
	short i, tmp;

	for (i = 0; i <= Nband; i++)
	{
		// RES : residual echo PSD
		tmp = DVTXOP_mult(EchoBandGain[i], EchoGain);
		EchoPSD[i] = DVTXOP_L_mpy_ls(EchoPSD[i], tmp); //residual echo gain		
	}
}
#else// bit mached C code
void fx_SolomonVoice_EchoPower_estimation(int *EchoPSD, short *EchoBandGain, short EchoGain, short Nband)
{
	short i, tmp;

	for (i = 0; i <= Nband; i++)
	{		
		// RES : residual echo PSD
		tmp = DVTXOP_mult(EchoBandGain[i], EchoGain);
		EchoPSD[i] = DVTXOP_Ls_mult_r(EchoPSD[i], tmp); //residual echo gain
	}
}
#endif


#endif

/*Solomonvoice function
ref. Q format : Q16.15 fixed
SNR min = 2^15*(1/128) max = 2^15*(256)
*/
void fx_SolomonVoice_postSNR_cal_with_limitation_Q15(int *SNRpost, int *EE, int *NN, int SNRmin, int SNRmax, short Nband)
{
	short i;
	int Ltmp2;

	for (i = 0; i <= Nband; i++)
	{
		Ltmp2 = fx_SolomonVoice_32bit_Divide(EE[i], NN[i], 1, 16); //q16,15

		SNRpost[i] = DVTX_MIN(DVTX_MAX(Ltmp2, SNRmin), SNRmax); //min = 2^15*(1/128) max = 2^15*(256)		
	}
}

/*Solomonvoice function
calculate FFT bin power
ErrbyIn : Err*In
PwrIn : In*In
PwrInMin : denominator min
step_fnlms : NLMS step size
*/
int fx_SolomonVoice_FNLMS_coef_cal(int ErrbyIn, int PwrIn, short PwrInMin, short step_fnlms)
{
	short norm_shift_num, norm_shift_denom;
	int L_num, L_denom, Lout;

	// numerator
	norm_shift_num = DVTXOP_norm_l(ErrbyIn);
	L_num = DVTXOP_L_shl(ErrbyIn, (short)(norm_shift_num - 1));

	//denominator
	norm_shift_denom = DVTXOP_norm_l(PwrIn);
	L_denom = DVTXOP_L_shl(PwrIn, norm_shift_denom);
	L_denom = DVTX_MAX(L_denom, PwrInMin); // normalization

										   // devide
	Lout = DVTXOP_L_divide(L_num, L_denom);   // 1

	Lout = DVTXOP_L_mpy_ls(Lout, step_fnlms);//step size

	Lout = DVTXOP_extract_h(DVTXOP_L_shr(Lout, (short)(-1 + norm_shift_num - norm_shift_denom)));

	return Lout;
}

/*Solomonvoice function
band to bin with minimum gain
*/
void fx_SolomonVoice_Gain_band_to_bin(short *Gbin, short *Gband, short CHindex[][2], short MinGband, short Nband)
{
	short i, j1, j2, j;

	for (i = 0; i <= Nband; i++)
	{
		Gband[i] = DVTX_MAX(Gband[i], MinGband); //0.05noise flooring

		j1 = CHindex[i][0], j2 = CHindex[i][1];
		for (j = j1; j <= j2; j++)
			Gbin[j] = Gband[i];
	}
}

//void fn_FrmVAD(DVTX_ECNS_Cfg_t* DVTX_ECNS_vars) {
//
//	short i, fl, fh;
//
//	int sum_tmp, tmpi;
//	short THD_Ratio_LowBandPwr, THD_Ratio_LowBandPwr_wind, THD_Ratio_LowBandPwr_State0, THD_Ratio_LowBandPwr_State1, THD_Ratio_LowBandPwr_State2, THD_Ratio_LowBandPwr_State3, THD_Ratio_LowBandPwr_State4, THD_Ratio_LowBandPwr_Unfit;
//	short THD_Pwr_inner, THD_Pwr_inner_wind, THD_Pwr_inner_State0, THD_Pwr_inner_State1, THD_Pwr_inner_State2, THD_Pwr_inner_State3, THD_Pwr_inner_State4, THD_Pwr_inner_Unfit;
//	short THD_DT_PwrOuter;
//	//short Pwr_wind;
//
//	FRAMEStatus* FRAME_buf = &DVTX_ECNS_vars->FRAME_buf;
//	ANCStatus* ANC_Inner_buf = &DVTX_ECNS_vars->ANC_Inner_buf;
//	ANCStatus* ANC_Outer_buf = &DVTX_ECNS_vars->ANC_Outer_buf;
//	AECStatus* AEC_Inner_buf = &DVTX_ECNS_vars->AEC_Inner_buf;
//	AECStatus* AEC_Outer_buf_1 = &DVTX_ECNS_vars->AEC_Outer_buf_1;
//	MixingStatus* Mix_buf = &DVTX_ECNS_vars->Mix_buf;
//
//	short* data_buffer_NB = FRAME_buf->fftbuf_Inner.data_buffer;
//	short BLK_NORM_NB = FRAME_buf->fftbuf_Inner.BLK_NORM;
//	short* data_buffer_WB = FRAME_buf->fftbuf_Outer_2.data_buffer;
//	short BLK_NORM_WB = FRAME_buf->fftbuf_Outer_2.BLK_NORM;
//	//short* data_buffer_inner_WB = FRAME_buf->fftbuf_Inner_WB.data_buffer;
//#ifndef fx_SolomonVoice_FFT_to_FFTpwr_ave_OPT_DSP
//	fx_SolomonVoice_FFT_to_FFTpwr_ave(FRAME_buf->avg_ANC_sigPwr_Inner, ANC_Inner_buf->ANC_sigPwr, data_buffer_NB, 2 * (BLK_NORM_NB - 4), 22937, 9830, DVTX_FFT_HALFLEN_NB);  // DVTX_ECNS_vars->preNS.avg_ANC_sigPwr is Q8
//	fx_SolomonVoice_FFT_to_FFTpwr_ave(FRAME_buf->avg_ANC_sigPwr_Outer, ANC_Outer_buf->ANC_sigPwr, data_buffer_WB, 2 * (BLK_NORM_WB - 1), 22937, 9830, DVTX_FFT_HALFLEN_NB);  // DVTX_ECNS_vars_outer->preNS.avg_ANC_sigPwr  is Q2
//	//fx_SolomonVoice_FFT_to_FFTpwr(ANC_Inner_buf->ANC_sigPwr_inner, data_buffer_inner_WB, DVTX_FFT_HALFLEN_WB);   //DVTX_ECNS_vars->preNS.ANC_sigPwr_inner is Q(2*DVTX_ECNS_vars->preNS.BLK_NORM_inner_WB +1)
//#else
//	fx_SolomonVoice_FFT_to_FFTpwr_ave_vector(FRAME_buf->avg_ANC_sigPwr_Inner, ANC_Inner_buf->ANC_sigPwr, data_buffer_NB, 2 * (BLK_NORM_NB - 4), 22937, 9830, DVTX_FFT_HALFLEN_NB);  // DVTX_ECNS_vars->preNS.avg_ANC_sigPwr is Q8
//	fx_SolomonVoice_FFT_to_FFTpwr_ave_vector(FRAME_buf->avg_ANC_sigPwr_Outer, ANC_Outer_buf->ANC_sigPwr, data_buffer_WB, 2 * (BLK_NORM_WB - 1), 22937, 9830, DVTX_FFT_HALFLEN_NB);  // DVTX_ECNS_vars_outer->preNS.avg_ANC_sigPwr  is Q2
//#endif
//	fl = 6;	//187.5 Hz
//	fh = 52;//1625 Hz
//
//	// low band power ratio R = Pinner/Pouter
//	sum_tmp = 0;
//	for (i = fl; i < fh; i++) {
//		int tmp;
//		tmp = fx_SolomonVoice_32bit_Divide(FRAME_buf->avg_ANC_sigPwr_Inner[i], FRAME_buf->avg_ANC_sigPwr_Outer[i], 1, Q_check); //Q_check 16, Q8/Q2
//		sum_tmp += tmp;
//	}
//	FRAME_buf->FrmRioLowBand_Inner = Fx_10log10(sum_tmp, Q_check);                   // Q8
//
//#if(FLAG_SELECT_C_DSP == 1)	
//#if(Debug_File_Write_C == 1)
//	for (i = 0; i < DVTX_FFT_HALFLEN_NB; i++)
//	{
//		fprintf(fp_deg_2micBF[6], "%ld %ld %ld\n",
//			FRAME_buf->avg_ANC_sigPwr_Inner[i],
//			FRAME_buf->avg_ANC_sigPwr_Outer[i],
//			fx_SolomonVoice_32bit_Divide(FRAME_buf->avg_ANC_sigPwr_Inner[i], FRAME_buf->avg_ANC_sigPwr_Outer[i], 1, Q_check) //Q_check 16, Q8/Q2		
//		);
//
//		fprintf(fp_deg_2micBF[7], "%ld\n", sum_tmp);
//	}
//#endif
//#endif
//
//	// Lowbannd inner Signal power
//	sum_tmp = 0;
//	for (i = fl; i < fh; i++)
//	{
//		sum_tmp = DVTXOP_L_add(sum_tmp, ANC_Inner_buf->ANC_sigPwr[i]);
//	}
//	sum_tmp = DVTXOP_L_shr_r(sum_tmp, BLK_NORM_NB * 2 + 1 - 8);   //Q8
//	tmpi = Fx_10log10(sum_tmp, 8);                   // Q8
//	FRAME_buf->FrmPiLowBand_Inner = DVTXOP_mult(tmpi, 7545);   //   FRAME_buf->FrmPiLowBand is Q8      7545 = 1/(10*log10(exp(1))) * Q15
//
//
//	VAD_speechonFlag_inearPWR_NS = 0;
//	if (FRAME_buf->FrmPiLowBand_Inner > 2700)
//		VAD_speechonFlag_inearPWR_NS = 1;
//
//
//	// Wind Detection
//	//Pwr_wind = FN_Wind_Detection(DVTX_ECNS_vars);
//	
//	// VAD based on inner outer
//	THD_DT_PwrOuter = 4200;
//
//	THD_Ratio_LowBandPwr_State0 = 7000;
//	THD_Ratio_LowBandPwr_State1 = 7000;
//	THD_Ratio_LowBandPwr_State2 = 7000;
//	THD_Ratio_LowBandPwr_State3 = 7000;
//	THD_Ratio_LowBandPwr_State4 = 6000;
//	THD_Ratio_LowBandPwr_wind = 3700;
//	THD_Ratio_LowBandPwr_Unfit = 8900;
//	THD_Pwr_inner_State0 = 1800;
//	THD_Pwr_inner_State1 = 2000;
//	THD_Pwr_inner_State2 = 2200;
//	THD_Pwr_inner_State3 = 2500;
//	THD_Pwr_inner_State4 = 2900;
//	THD_Pwr_inner_wind = 2700;
//	THD_Pwr_inner_Unfit = 2000;
//
//	if (Mix_buf->State == 0)
//	{
//		THD_Ratio_LowBandPwr = THD_Ratio_LowBandPwr_State0;
//		THD_Pwr_inner = THD_Pwr_inner_State0;
//	}
//	else if (Mix_buf->State == 1)
//	{
//		THD_Ratio_LowBandPwr = THD_Ratio_LowBandPwr_State1;
//		THD_Pwr_inner = THD_Pwr_inner_State1;
//	}
//	else if (Mix_buf->State == 2)
//	{
//		THD_Ratio_LowBandPwr = THD_Ratio_LowBandPwr_State2;
//		THD_Pwr_inner = THD_Pwr_inner_State2;
//	}
//	else if (Mix_buf->State == 3)
//	{
//		THD_Ratio_LowBandPwr = THD_Ratio_LowBandPwr_State3;
//		THD_Pwr_inner = THD_Pwr_inner_State3;
//	}
//	else // MixingState4
//	{
//		THD_Ratio_LowBandPwr = THD_Ratio_LowBandPwr_State4;
//		THD_Pwr_inner = THD_Pwr_inner_State4;
//	}
//	if (Mix_buf->WND_strong_ON == 1)
//	{
//		THD_Ratio_LowBandPwr = THD_Ratio_LowBandPwr_wind;
//		THD_Pwr_inner = THD_Pwr_inner_wind;
//	}
//	if (FLAG_WB_OuterECNSOnly == 0)
//	{
//		if (Mix_buf->UnFit_State == 1)
//		{
//			THD_Ratio_LowBandPwr = THD_Ratio_LowBandPwr_Unfit;
//			THD_Pwr_inner = THD_Pwr_inner_Unfit;
//		}
//	}
//
//	FRAME_buf->VariableTHD_Ratio_LowBandPwr =
//				DVTXOP_add(DVTXOP_mult(FRAME_buf->VariableTHD_Ratio_LowBandPwr, DVTX_WORD16_0_95), DVTXOP_mult(THD_Ratio_LowBandPwr, DVTX_WORD16_0_05));
//	FRAME_buf->VariableTHD_THD_Pwr_inner =
//				DVTXOP_add(DVTXOP_mult(FRAME_buf->VariableTHD_THD_Pwr_inner, DVTX_WORD16_0_95), DVTXOP_mult(THD_Pwr_inner, DVTX_WORD16_0_05));
//	if (Mix_buf->State_Noise2Clean) //abrupt noise change : high noise-->noise free
//	{
//		FRAME_buf->VariableTHD_Ratio_LowBandPwr = THD_Ratio_LowBandPwr_State0;
//		FRAME_buf->VariableTHD_THD_Pwr_inner = THD_Pwr_inner_State0;
//	}
//
//
//	// Lowband outer signal power difference : for DT detection
//	sum_tmp = 0;
//	for (i = fl; i < fh; i++)
//	{
//		sum_tmp = DVTXOP_L_add(sum_tmp, ANC_Outer_buf->ANC_sigPwr[i]);
//	}
//	sum_tmp = DVTXOP_L_shr_r(sum_tmp, BLK_NORM_WB * 2 + 1 - 5);   //Q8
//	tmpi = Fx_10log10(sum_tmp, 5);                   // Q8
//	//FRAME_buf->FrmPiLowBand_Outer = DVTXOP_mult(tmpi, 7545);   //   FRAME_buf->FrmPiLowBand is Q8      7545 = 1/(10*log10(exp(1))) * Q15
//	tmpi = DVTXOP_mult(tmpi, 7545);
//
//	if (FRAME_buf->FrmPiLowBand_Outer < tmpi)
//		FRAME_buf->FrmPiLowBand_Outer = DVTXOP_L_add(DVTXOP_L_mpy_ls(FRAME_buf->FrmPiLowBand_Outer, DVTX_WORD16_0_1), DVTXOP_L_mpy_ls(tmpi, DVTX_WORD16_0_9));
//	else
//		FRAME_buf->FrmPiLowBand_Outer = DVTXOP_L_add(DVTXOP_L_mpy_ls(FRAME_buf->FrmPiLowBand_Outer, DVTX_WORD16_0_9), DVTXOP_L_mpy_ls(tmpi, DVTX_WORD16_0_1));
//
//
//	// Minimum val tracking && additional VAD
//	if (AEC_Outer_buf_1->Flag_RxVAD_AEC == 0 && FRAME_buf->FrmRioLowBand_Inner < THD_Ratio_LowBandPwr_Unfit)
//	{
//		FRAME_buf->Avg_FrmPiLowBand = DVTXOP_add(DVTXOP_mult(FRAME_buf->Avg_FrmPiLowBand, DVTX_WORD16_0_9), DVTXOP_mult(FRAME_buf->FrmPiLowBand_Inner, DVTX_WORD16_0_1));
//	}
//	FRAME_buf->Buff_FrmPiLowBand[FRAME_buf->PtBuff_FrmPiLowBand] = FRAME_buf->Avg_FrmPiLowBand;
//	FRAME_buf->PtBuff_FrmPiLowBand++;
//	if (FRAME_buf->PtBuff_FrmPiLowBand >= DVTX_NumFrm_MCRA_VAD)
//		FRAME_buf->PtBuff_FrmPiLowBand = 0;
//
//	//////////////////////////////////////////////////////////////////
//	/*
//	short AE_INT16X4_RMIN(ae_int16x4 d0);
//	ae_int16x4 AE_INT16X4_MIN(ae_int16x4 d0, ae_int16x4 d1);
//
//	*/
//	FRAME_buf->MinVal_FrmPiLowBand = DVTX_MAX_16;
//	for (i = 0; i < DVTX_NumFrm_MCRA_VAD; i++)
//	{
//		if (FRAME_buf->Buff_FrmPiLowBand[i] < FRAME_buf->MinVal_FrmPiLowBand)
//			FRAME_buf->MinVal_FrmPiLowBand = FRAME_buf->Buff_FrmPiLowBand[i];
//	}
//
//	//////////////////////////////////////////////////////////////
//	FRAME_buf->MinVal_FrmPiLowBand = DVTXOP_add(FRAME_buf->MinVal_FrmPiLowBand, 120);// MCRA bias compensation
//	FRAME_buf->MinVal_FrmPiLowBand = DVTX_MAX(FRAME_buf->MinVal_FrmPiLowBand, 1000); // minimum value MCRA Min.
//
//	if (FRAME_buf->VariableTHD_THD_Pwr_inner > FRAME_buf->MinVal_FrmPiLowBand)
//	{
//		if (Mix_buf->State <= 1)
//			FRAME_buf->VariableTHD_THD_Pwr_inner = DVTXOP_add(DVTXOP_mult(FRAME_buf->VariableTHD_THD_Pwr_inner, DVTX_WORD16_0_1), DVTXOP_mult(FRAME_buf->MinVal_FrmPiLowBand, DVTX_WORD16_0_9));
//		else if (Mix_buf->State == 2)
//			FRAME_buf->VariableTHD_THD_Pwr_inner = DVTXOP_add(DVTXOP_mult(FRAME_buf->VariableTHD_THD_Pwr_inner, DVTX_WORD16_0_3), DVTXOP_mult(FRAME_buf->MinVal_FrmPiLowBand, DVTX_WORD16_0_7));
//		else if (Mix_buf->State == 3)
//			FRAME_buf->VariableTHD_THD_Pwr_inner = DVTXOP_add(DVTXOP_mult(FRAME_buf->VariableTHD_THD_Pwr_inner, DVTX_WORD16_0_5), DVTXOP_mult(FRAME_buf->MinVal_FrmPiLowBand, DVTX_WORD16_0_5));
//		else if (Mix_buf->State == 4)
//			FRAME_buf->VariableTHD_THD_Pwr_inner = DVTXOP_add(DVTXOP_mult(FRAME_buf->VariableTHD_THD_Pwr_inner, DVTX_WORD16_0_7), DVTXOP_mult(FRAME_buf->MinVal_FrmPiLowBand, DVTX_WORD16_0_3));
//		else
//			FRAME_buf->VariableTHD_THD_Pwr_inner = DVTXOP_add(DVTXOP_mult(FRAME_buf->VariableTHD_THD_Pwr_inner, DVTX_WORD16_0_5), DVTXOP_mult(FRAME_buf->MinVal_FrmPiLowBand, DVTX_WORD16_0_5));
//
//	}
//
//	FRAME_buf->FrmVAD_Inner = 1;
//	if (FRAME_buf->FrmRioLowBand_Inner < FRAME_buf->VariableTHD_Ratio_LowBandPwr || FRAME_buf->FrmPiLowBand_Inner < FRAME_buf->VariableTHD_THD_Pwr_inner)
//	{
//		FRAME_buf->FrmVAD_Inner = 0;
//	}
//	// copy VAD to outer
//	FRAME_buf->FrmVAD_Outer = FRAME_buf->FrmVAD_Inner;
//
//	// Double Talk 
//	if (AEC_Outer_buf_1->Flag_RxVAD_AEC == 1 && FRAME_buf->FrmPiLowBand_Outer > THD_DT_PwrOuter)
//		FRAME_buf->FrmDT_Outer = 1;
//	else
//		FRAME_buf->FrmDT_Outer = 0;
//
//	FRAME_buf->FrmDT_Inner = FRAME_buf->FrmDT_Outer; // copy the flag 
//#if(FLAG_SELECT_C_DSP == 1)
//#if(Debug_File_Write_C == 1)
//	fprintf(fp_inoutVAD, "%d %d %d %d %d %ld %d %ld %d %d %ld\n",
//		FRAME_buf->MinVal_FrmPiLowBand,
//		FRAME_buf->FrmDT_Inner,
//		THD_DT_PwrOuter,
//		0,
//		0,
//		FRAME_buf->FrmRioLowBand_Inner,
//		FRAME_buf->VariableTHD_Ratio_LowBandPwr,
//		FRAME_buf->FrmPiLowBand_Inner,
//		FRAME_buf->VariableTHD_THD_Pwr_inner,
//		FRAME_buf->FrmVAD_Outer,
//		FRAME_buf->FrmPiLowBand_Outer
//	);
//#endif
//#endif
//	return;
//}



#ifdef OPT_Fx_vector_average
void  Fx_vector_average(short * out, short * in, short gain, short len)
{
	int k;
	ae_int16x4  *pt1, *pt2, *pt3;
	ae_valign align1, align2, align3;
	ae_int16x4  data1,data2, gainV, eve1, eve2;
	xtbool4 bool4;

	pt1=(ae_int16x4 *)in;
	pt2=(ae_int16x4 *)out;
	pt3=(ae_int16x4 *)out;

	align1 = AE_LA64_PP(pt1);
	align2 = AE_LA64_PP(pt2);
	align3 = AE_ZALIGN64();

	gainV = AE_MOVDA16(gain);

	for (k = 0; k < len; k+= 4)
	{
		AE_LA16X4_IP(data1, align1, pt1);
		AE_LA16X4_IP(data2, align2, pt2);
		eve1 = AE_MULFP16X4S(data1, gainV);
		eve2 = AE_MULFP16X4S(data2, gainV);
		eve1 = AE_ADD16S(eve1, eve2);

		AE_SA16X4_IP(eve1, align3, pt3);
	}
	AE_SA64POS_FP(align3, pt3);

}
#endif


#ifdef OPT_Fx_vector_Max
void Fx_vector_Max(short * out, short * in, short Gmin, short len)
{
	int k;
	ae_int16x4  *pt1, *pt2;
	ae_valign align1, align2;
	ae_int16x4  data, GminV;
	xtbool4 bool4;

	pt1=(ae_int16x4 *)in;
	pt2=(ae_int16x4 *)out;

	align1 = AE_LA64_PP(pt1);
	align2 = AE_ZALIGN64();

	GminV = AE_MOVDA16(Gmin);

	for (k = 0; k < len; k+= 4)
	{
		AE_LA16X4_IP(data, align1, pt1);
		bool4 = AE_LT16(data, GminV);
		AE_MOVT16X4(data, GminV, bool4);
		AE_SA16X4_IP(data, align2, pt2);
	}
	AE_SA64POS_FP(align2, pt2);

}
#endif


#ifdef OPT_Gain_averaging

#ifdef Gain_averaging_DSP_OPT
void Gain_averaging(short * in, short *out, int len, int tmpindex )//tmpindex=9   len=256
{
	int i,j;
	short tmp,tmp_short,tmp_short1,tmp_short2,tmp_short3;
	short tmpp;
	tmp = 0;

//	for( i = 0; i <= tmpindex*2; i++)
//		tmp = DVTXOP_add(tmp, DVTXOP_mult(in[i],1724) );
{
    ae_int16x4* p_in=(ae_int16x4*)in;
    ae_int16x4 tmp_con=AE_MOVDA16(1724);
    ae_valign align1;
    ae_int16x4 tmp1,tmp2, tmp3,tmp4;
    align1 = AE_LA64_PP(p_in);

//	for( i = 0; i <tmpindex*2; i+=4)
//	{
		AE_LA16X4_IP(tmp1,align1, p_in);
		tmp1=AE_MULFP16X4S(tmp1, tmp_con);//4

		AE_LA16X4_IP(tmp2,align1, p_in);
		tmp2=AE_MULFP16X4S(tmp2, tmp_con);//8

		AE_LA16X4_IP(tmp3,align1, p_in);
		tmp3=AE_MULFP16X4S(tmp3, tmp_con);//12

		AE_LA16X4_IP(tmp4,align1, p_in);
		tmp4=AE_MULFP16X4S(tmp4, tmp_con);//16



		tmp1=AE_ADD16S(tmp1, tmp2);
		tmp3=AE_ADD16S(tmp3, tmp4);
		tmp1=AE_ADD16S(tmp1, tmp3);
		tmp2=AE_SEL16_6543(tmp1, tmp1);
		tmp1=AE_ADD16S(tmp1, tmp2);
		tmp2=AE_SEL16_5410(tmp1, tmp1);
		tmp1=AE_ADD16S(tmp1, tmp2);
		tmp=AE_MOVAD16_3(tmp1);
//		tmp = DVTXOP_add(tmp, DVTXOP_mult(in[i],1724) );
//		tmp1 = DVTXOP_add(tmp1, DVTXOP_mult(in[i+1],1724) );
//	}
	tmp = DVTXOP_add(tmp, DVTXOP_mult(in[16],1724) );
	tmp = DVTXOP_add(tmp, DVTXOP_mult(in[17],1724) );
	tmp = DVTXOP_add(tmp, DVTXOP_mult(in[18],1724) );
}

//	for(i = tmpindex; i < len - tmpindex; i++)
//	{
//		out[i] = tmp ;
//		tmp = DVTXOP_sub(tmp, DVTXOP_mult(in[i - tmpindex ],1724));
//		tmp = DVTXOP_add(tmp, DVTXOP_mult(in[i + tmpindex +1], 1724));
//
//	}

//	for(i = tmpindex; i < len - tmpindex-1; i+=2)
//	{
//
//	    tmp_short=DVTXOP_mult(in[i - tmpindex ],1724);
//	    tmp_short2=DVTXOP_mult(in[i + tmpindex +1], 1724);
//
//	    tmp_short1=DVTXOP_mult(in[i+1 - tmpindex ],1724);
//	    tmp_short3=DVTXOP_mult(in[i + tmpindex +2], 1724);
//
//	    tmpp = DVTXOP_sub(tmp,tmp_short );
//	    tmpp = DVTXOP_add(tmpp, tmp_short2);
//	    out[i] = tmp ;
//		out[i+1] = tmpp ;
//		tmpp = DVTXOP_sub(tmpp,tmp_short1 );
//		tmp = DVTXOP_add(tmpp, tmp_short3);
//
//	}
	for(i = tmpindex; i < len - tmpindex-1; i+=2)
	{

	    tmp_short=DVTXOP_mult(in[i - tmpindex ],1724);
	    tmp_short2=DVTXOP_mult(in[i + tmpindex +1], 1724);

	    tmp_short1=DVTXOP_mult(in[i+1 - tmpindex ],1724);
	    tmp_short3=DVTXOP_mult(in[i + tmpindex +2], 1724);

	    tmpp = DVTXOP_sub(tmp,tmp_short );
	    tmpp = DVTXOP_add(tmpp, tmp_short2);
	    out[i] = tmp ;
		out[i+1] = tmpp ;
		tmpp = DVTXOP_sub(tmpp,tmp_short1 );
		tmp = DVTXOP_add(tmpp, tmp_short3);

	}

}
#else
void Gain_averaging(short * in, short *out, int len, int tmpindex )
{
	int i,j;
	short tmp;
	tmp = 0;
	for( i = 0; i <= tmpindex*2; i++)
		tmp = DVTXOP_add(tmp, DVTXOP_mult(in[i],1724) );
	for(i = tmpindex; i < len - tmpindex; i++)
	{
		out[i] = tmp ;
		tmp = DVTXOP_sub(tmp, DVTXOP_mult(in[i - tmpindex ],1724));
		tmp = DVTXOP_add(tmp, DVTXOP_mult(in[i + tmpindex +1], 1724));

	}
}
#endif

#endif

#ifdef OPT_FN_f0_based_pre_Noise_suppression_forloop
int FN_f0_based_pre_Noise_suppression_forloop(int*a,int*b,int val,int LEN)
{
	ae_int32x2 *pt1,*pt2,*pt3;
	ae_int32x2 tmp_pt1,tmp_pt2;
	ae_valign align1,align2,align3;

	ae_int32x2  beta_inv;
	ae_int32x2  tmp,tmp1,tmp2;

	int tmpll;
	ae_int64 All,All1,All2,All3;
	int out,out1;
	int k;

	tmpll=DVTX_MAX_16;
	tmp1=AE_MOVDA32X2(tmpll, tmpll);
	tmp2=AE_MOVDA32X2(val, val);

	tmp=AE_SUB32S(tmp1, tmp2);
	beta_inv = AE_ADD32S(tmp, 1);
	tmpll=0xfffffffe;
	tmp=AE_MOVDA32X2(tmpll, tmpll);

	pt1=(ae_int32x2 *)(a);
	pt2=(ae_int32x2 *)(b);
	pt3=(ae_int32x2 *)(a);
	align1=AE_LA64_PP(pt1);
	align2=AE_LA64_PP(pt2);

	align3=AE_ZALIGN64();

	for (k = 0; k < LEN; k+=2)
	{
		AE_LA32X2_IP(tmp_pt1, align1, pt1);//A
		AE_LA32X2_IP(tmp_pt2, align2, pt2);//B

		tmp_pt2=AE_AND32(tmp_pt2, tmp);


		All = AE_MUL32_LL(tmp_pt2, beta_inv);  //DVTXOP_L_mpy_ls(B, beta_inv)
		All1= AE_MUL32_HH(tmp_pt2, beta_inv);



		tmp_pt1=AE_AND32(tmp_pt1, tmp);

		All2 = AE_MUL32_LL(tmp_pt1, tmp2);  //DVTXOP_L_mpy_ls(B, beta_inv)
		All3= AE_MUL32_HH(tmp_pt1, tmp2);

		All = AE_SRAI64(All,15);
		All2 = AE_SRAI64(All2,15);
		All=AE_ADD64S(All, All2);

		All1 = AE_SRAI64(All1,15);
		All3 = AE_SRAI64(All3,15);
		All1=AE_ADD64S(All1, All3);


		tmp1 = AE_MOVF32X2_FROMF64(All);
		out = AE_MOVAD32_L(tmp1);
		tmp1 = AE_MOVF32X2_FROMF64(All1);
		out1 = AE_MOVAD32_L(tmp1);

		//            DVTX_ECNS_vars->ANC_Inner_buf.L_EEii[k+1]=out;
		tmp1=AE_MOVDA32X2(out1,out);
		AE_SA32X2_IP(tmp1, align3, pt3);


		//DVTX_ECNS_vars->ANC_Inner_buf.L_EEii[k] = Fx_recursive_avg(DVTX_ECNS_vars->ANC_Inner_buf.L_EEii[k], DVTX_ECNS_vars->ANC_Inner_buf.L_tmp256[k], DVTX_WORD16_0_3); //0.3


	}
	AE_SA64POS_FP(align3, pt3);


}


#endif



#if(0)//f0-based pre-NS off
// f0-based pre-NS
int FN_f0_based_pre_Noise_suppression(DVTX_ECNS_Cfg_t* DVTX_ECNS_vars, short F0flag)
{

	short k, i, wl, fh;

	short Gmin = DVTX_ECNS_vars->COMMON_buf.Gmin;
	short SPPmin = 26213;

	FRAMEStatus* FRAME_buf = &DVTX_ECNS_vars->FRAME_buf;
	PRENSStatus* PRENS_Inner_buf = &DVTX_ECNS_vars->PRENS_Inner_buf;
	PRENSStatus* PRENS_Outer_buf = &DVTX_ECNS_vars->PRENS_Outer_buf;
	
	SamsungSolomonVoiceWTxPRENSParam* PRENS_Inner_param = &DVTX_ECNS_vars->PreNS_Inner_param;
	SamsungSolomonVoiceWTxPRENSParam* PRENS_Outer_param = &DVTX_ECNS_vars->PreNS_Outer_param;
	
	short* data_buffer_NB = FRAME_buf->fftbuf_Inner.data_buffer;
	short BLK_NORM_NB = FRAME_buf->fftbuf_Inner.BLK_NORM;
	short* data_buffer_WB = FRAME_buf->fftbuf_Outer_1.data_buffer;
	short BLK_NORM_WB = FRAME_buf->fftbuf_Outer_1.BLK_NORM;
	
	if ((PRENS_Inner_param->PreNS_onoff == 0) || (PRENS_Outer_param->PreNS_onoff == 0))
		return 0;
	
	/////// candidate inner & outer signals //////////////////////////////
	// EEii calculation
	fx_SolomonVoice_FFT_to_FFTpwr(PRENS_Inner_buf->L_tmp256, data_buffer_NB, DVTX_FFT_HALFLEN_NB);
	fx_SolomonVoice_PwrBin_FixQ_BlkDeNorm(PRENS_Inner_buf->L_tmp256, PRENS_Inner_buf->L_tmp256, BLK_NORM_NB, 7, 1, DVTX_FFT_HALFLEN_NB);/*30,1 -> 23,8*/
#ifndef OPT_FN_f0_based_pre_Noise_suppression_forloop
	for (k = 0; k < DVTX_FFT_HALFLEN_NB; k++)
	{
		PRENS_Inner_buf->L_EEii[k] = Fx_recursive_avg(PRENS_Inner_buf->L_EEii[k], PRENS_Inner_buf->L_tmp256[k], DVTX_WORD16_0_3); //0.3
	}
#else
	FN_f0_based_pre_Noise_suppression_forloop(PRENS_Inner_buf->L_EEii,PRENS_Inner_buf->L_tmp256,DVTX_WORD16_0_3,DVTX_FFT_HALFLEN_NB);
#endif


	// EXoo and EXooS calculation
	fx_SolomonVoice_FFT_to_FFTpwr(PRENS_Inner_buf->L_Eoo, data_buffer_WB, DVTX_FFT_HALFLEN_WB); // L_Eoo Q30.1
	fx_SolomonVoice_PwrBin_FixQ_BlkDeNorm(PRENS_Inner_buf->L_tmp256, PRENS_Inner_buf->L_Eoo, BLK_NORM_WB, 7, 1, DVTX_FFT_HALFLEN_WB);/*30,1 -> 23,8*/
#ifndef OPT_FN_f0_based_pre_Noise_suppression_forloop
	for (k = 0; k < DVTX_FFT_HALFLEN_WB; k++)
	{
		PRENS_Inner_buf->L_EEoo_07[k] = Fx_recursive_avg(PRENS_Inner_buf->L_EEoo_07[k], PRENS_Inner_buf->L_tmp256[k], DVTX_WORD16_0_7); //0.7
	}
#else
	FN_f0_based_pre_Noise_suppression_forloop(PRENS_Inner_buf->L_EEoo_07,PRENS_Inner_buf->L_tmp256,DVTX_WORD16_0_7,DVTX_FFT_HALFLEN_WB);
#endif

	//L_tmp256 = EXooS..smoothed EXoo
	Fn_vector_smoothing_over_3_rectangularwin_length(PRENS_Inner_buf->L_tmp256, PRENS_Inner_buf->L_EEoo_07, DVTX_FFT_HALFLEN_WB, 0);
	
	/////// peak-picking based harmonic contour vector estimation //////////////////////////////
	wl = 3;
	fh = 64;//round(2000/31.25)
	fx_SolomonVoice_peak_peaking_based_Harmonic_Contour_estimation
	(PRENS_Inner_buf->tmpf0contour, SPPmin, FRAME_buf->FrmVAD_Inner, PRENS_Inner_buf->L_EEii, PRENS_Inner_buf->L_tmp256, wl, fh, DVTX_FFT_HALFLEN_WB);
#ifndef OPT_Fx_vector_average
	for (k = 0; k < DVTX_FFT_HALFLEN_WB; k++)
	{
		PRENS_Inner_buf->f0contourAvg[k] = DVTXOP_add(DVTXOP_mult(PRENS_Inner_buf->f0contourAvg[k], DVTX_WORD16_0_5), DVTXOP_mult(PRENS_Inner_buf->tmpf0contour[k], DVTX_WORD16_0_5));
	}
#else
	Fx_vector_average(PRENS_Inner_buf->f0contourAvg, PRENS_Inner_buf->tmpf0contour, DVTX_WORD16_0_5, DVTX_FFT_HALFLEN_WB);
#endif

	// f0-based pre MMSE Noise suppression //////////////////////////////
	/*MMSE-based pre NS gain estimation*/

#ifndef OPT_Fx_vector_Max
	for (k = 0; k < DVTX_FFT_HALFLEN_WB; k++)
		PRENS_Inner_buf->G_NS[k] = DVTX_MAX(PRENS_Inner_buf->f0contourAvg[k], Gmin); //Gmin
#else
	Fx_vector_Max(PRENS_Inner_buf->G_NS, PRENS_Inner_buf->f0contourAvg, Gmin, DVTX_FFT_HALFLEN_WB);

#endif
	// gain applying

#ifndef fx_SolomonVoice_FFTbin_gain_applying_OPT_DSP
	if (F0flag)
	{
		for (i = 0; i < DVTX_FFT_HALFLEN_WB; i++)
		{
			data_buffer_WB[2 * i] = DVTXOP_mult(data_buffer_WB[2 * i], PRENS_Inner_buf->G_NS[i]);
			data_buffer_WB[2 * i + 1] = DVTXOP_mult(data_buffer_WB[2 * i + 1], PRENS_Inner_buf->G_NS[i]);
		}
	}
#else
	if (F0flag) 
	{
		fx_SolomonVoice_FFTbin_gain_applying(data_buffer_WB,PRENS_Inner_buf->G_NS,DVTX_FFT_HALFLEN_WB);
	}
#endif


#if(FLAG_SELECT_C_DSP == 1)
#if(Debug_File_Write_C == 1)
	for (k = 0; k < DVTX_FFT_HALFLEN_WB; k++)
	{
		fprintf(fp_f0contour, "%d\n", PRENS_Inner_buf->f0contourAvg[k]);
	}
#endif
#endif

	return 0;
}
#endif

#if 0
void fx_SolomonVoice_RES_minGain(ECNSBufferStatus* ECNSbuff, ECNSStatus* AECNS, short CHAN_HIGH)
{
	short i, j1, j2;
	int Ltmp;

	Ltmp = DVTX_MAX_32;
	
	//for (i = 0; i <= CHAN_HIGH; i++)
	//{
	//	if (ECNSbuff->P_H1_GbyL[i] == 0) // estimate only for low spp bin
	//	{
	//		if (ECNSbuff->L_Npsd_for_minGain[i] > AECNS->L_Npsd[i]) // fast decreasing
	//		{
	//			ECNSbuff->L_Npsd_for_minGain[i] =
	//				DVTXOP_L_add(DVTXOP_L_mpy_ls(ECNSbuff->L_Npsd_for_minGain[i], DVTX_WORD16_0_5), DVTXOP_L_mpy_ls(AECNS->L_Npsd[i], DVTX_WORD16_0_5));// Q15.16
	//		}
	//		else
	//		{
	//			ECNSbuff->L_Npsd_for_minGain[i] =
	//				DVTXOP_L_add(DVTXOP_L_mpy_ls(ECNSbuff->L_Npsd_for_minGain[i], DVTX_WORD16_0_99), DVTXOP_L_mpy_ls(AECNS->L_Npsd[i], DVTX_WORD16_0_01));// Q15.16
	//		}
	//	}
	//	if (ECNSbuff->L_Npsd_for_minGain[i] < Ltmp)
	//		Ltmp = ECNSbuff->L_Npsd_for_minGain[i];
	//}
	//for (i = 0; i <= CHAN_HIGH; i++)
	//	ECNSbuff->L_Npsd_for_minGain[i] = 0;
	//// FNLMS minimum 
	//for (i = 0; i <= CHAN_HIGH; i++)
	//{
	//	Ltmp = DVTXOP_L_shr(ECNSbuff->L_Npsd_for_minGain[i], 8); //Q15,16 --> Q23.8
	//	j1 = tx_ch_tbl_nswb[i][0], j2 = tx_ch_tbl_nswb[i][1];
	//	for (j = j1; j <= j2; j++)
	//		ECNSbuff->L_tmpfft1[j] = Ltmp;
	//}

	return;
}
#endif

void fx_SolomonVoice_FNLMS_filter(short* data_buffer, RESStatus* RES_buf, AECStatus* AEC_buf, NSStatus* NS_buf, short FrmDT, short DIVID_BY_SHIFT_NUM_BIN, short FFT_HALFLEN, short FFT_LEN, short Flag_Tx_Clipping, CHANNEL channel, short NBBTmode)
{
	short i, j, tmp, tmpindex;
	int Ltmp, L_sum_Wres;

	int L_sum_Rx_highband, THD_Rx_highband_fricative;
	short Flag_rx_fricative;
	short gmin1, gmin2, gmin3, gmin4;


#ifndef OPT_int_sqrt_0_25_four
	int L_Elowband;
#else
	int count;
	int tmpin[4];
	short tmpout[4];
	int iv[4];
#endif
#ifndef FNLMS_MEMCPY_RED
	if (NBBTmode == 0)
	{
		if (FFT_LEN == DVTX_FFT_LEN_NB)
		{
			for (i = 0; i < 40; i++)
			{
				RES_buf->L_DDBin[i] = DVTXOP_L_shl(RES_buf->L_DDBin[i], 6);
				RES_buf->L_DDBin2[i] = DVTXOP_L_shl(RES_buf->L_DDBin2[i], 6);
			}
			for (i = 40; i < FFT_HALFLEN; i++)
			{
				RES_buf->L_DDBin[i] = DVTXOP_L_shl(RES_buf->L_DDBin[i], 13);
				RES_buf->L_DDBin2[i] = DVTXOP_L_shl(RES_buf->L_DDBin2[i], 13);
			}
		}	
		else
		{
			for (i = 20; i < 60; i++)
			{
				RES_buf->L_DDBin[i] = DVTXOP_L_shl(RES_buf->L_DDBin[i], 3);
				RES_buf->L_DDBin2[i] = DVTXOP_L_shl(RES_buf->L_DDBin2[i], 3);
			}
		}
		
	}
	fx_SolomonVoice_FNLMS_error_cal(RES_buf->L_EEBin, RES_buf->L_DDBin, RES_buf->L_DDBin2,
		RES_buf->L_RRBin, NS_buf->L_RRBin_step,
		RES_buf->W_fnlms_reression, RES_buf->W_fnlms_reression2, FFT_HALFLEN);
#else
	if (NBBTmode == 0)
	{
		if (FFT_LEN != DVTX_FFT_LEN_NB)
		{
			fx_SolomonVoice_FNLMS_error_cal(RES_buf->L_EEBin, RES_buf->L_DDBin, RES_buf->L_DDBin2,
				RES_buf->L_RRBin, NS_buf->L_RRBin_step,
				RES_buf->W_fnlms_reression, RES_buf->W_fnlms_reression2, FFT_HALFLEN);
		}
		else
		{
			fx_SolomonVoice_FNLMS_error_cal_comb_sh(RES_buf->L_EEBin, RES_buf->L_DDBin, RES_buf->L_DDBin2,
				RES_buf->L_RRBin, NS_buf->L_RRBin_step,
				RES_buf->W_fnlms_reression, RES_buf->W_fnlms_reression2, FFT_HALFLEN);
		}
	}
	else
	{
		fx_SolomonVoice_FNLMS_error_cal(RES_buf->L_EEBin, RES_buf->L_DDBin, RES_buf->L_DDBin2,
				RES_buf->L_RRBin, NS_buf->L_RRBin_step,
				RES_buf->W_fnlms_reression, RES_buf->W_fnlms_reression2, FFT_HALFLEN);
	}
#endif
	//tmporary calculate Wres filter power(can be omitted)
	L_sum_Wres = 0;
	for (i = 0; i < FFT_HALFLEN; i++)
		L_sum_Wres = DVTXOP_L_add(L_sum_Wres, (long)RES_buf->W_fnlms_reression2[i]);//q5,10
	L_sum_Wres = DVTXOP_L_shr(L_sum_Wres, DIVID_BY_SHIFT_NUM_BIN);


	//update Wres filter
	if ((AEC_buf->Flag_SingleTalk == 1) && (AEC_buf->Flag_ringbakctone == 0) && (AEC_buf->Flag_TxSilence_AEC == 1) && (FrmDT == 0))	
	{
		/*Solomonvoice function
		step size and Wvar limit are fixed now
		DD : Q23.8
		RR : Q23.8
		W  : Q5,10 --> 0.15 changed
		*/
		if (channel == CH_INNER)
		{
			fx_SolomonVoice_FNLMS_filter_update(RES_buf->W_fnlms_reression, RES_buf->S_tmpfft1, RES_buf->L_DDBin, NS_buf->L_RRBin_step, DVTX_FreqMix_MaxBin);
			fx_SolomonVoice_FNLMS_filter_update(RES_buf->W_fnlms_reression2, RES_buf->S_tmpfft1, RES_buf->L_DDBin2, NS_buf->L_RRBin_step, DVTX_FreqMix_MaxBin);
		}
		else
		{
			fx_SolomonVoice_FNLMS_filter_update(RES_buf->W_fnlms_reression, RES_buf->S_tmpfft1, RES_buf->L_DDBin, NS_buf->L_RRBin_step, FFT_HALFLEN);
			//fx_SolomonVoice_FNLMS_filter_update(RES_buf->W_fnlms_reression2, RES_buf->S_tmpfft1, RES_buf->L_DDBin2, NS_buf->L_RRBin_step, FFT_HALFLEN);
		}

	}// end of FNLMS update



	 // res gain calculation
	 // spectral subtaction gain  S^2 = X^2-N^2=G^2*X^2.. G = E^2/X^2
	 // should be compared with decision-directed+Wienner(or MMSE gain)
	
#ifndef OPT_int_sqrt_0_25_four
	if (channel == CH_INNER)
		tmpindex = DVTX_FreqMix_MaxBin;
	else
		tmpindex = FFT_HALFLEN;

	L_Elowband = 0;
	for (i = 0; i < tmpindex; i++)
	{
		if (RES_buf->L_RRBin[i] > 0 && RES_buf->L_EEBin[i] > 0)
		{
			Ltmp = fx_SolomonVoice_32bit_Divide(RES_buf->L_RRBin[i], RES_buf->L_EEBin[i], 0, 0);
			RES_buf->S_tmpfft1[i] = int_sqrt_0_25(Ltmp);    /////////////////////
		}
		else
			RES_buf->S_tmpfft1[i] = 0;

		L_Elowband = DVTXOP_L_add(L_Elowband, RES_buf->S_tmpfft1[i]);
	}
#else
	count = 0;
	for (i = 0; i < FFT_HALFLEN; i++)
	{
		if (RES_buf->L_RRBin[i] > 0 && RES_buf->L_EEBin[i] > 0)
		{
			Ltmp = fx_SolomonVoice_32bit_Divide(RES_buf->L_RRBin[i], RES_buf->L_EEBin[i], 0, 0);
			tmpin[count] = Ltmp;
			iv[count] = i;
			count++;
			if(count == 4)
			{
				int_sqrt_0_25_four(tmpin, tmpout);
				count = 0;
				RES_buf->S_tmpfft1[iv[0]] = tmpout[0];
				RES_buf->S_tmpfft1[iv[1]] = tmpout[1];
				RES_buf->S_tmpfft1[iv[2]] = tmpout[2];
				RES_buf->S_tmpfft1[iv[3]] = tmpout[3];

			}
		}
		else
		{
			RES_buf->S_tmpfft1[i] = 0;
		}
	}

	for(i=0;i<count; i++)
	{
		RES_buf->S_tmpfft1[iv[i]] = int_sqrt_0_25(tmpin[i]);
	}
#endif
	

	// gain averaging 
	// RES_buf->Gpwrres averaging num of bins = (tmpindex*2+1)
#ifndef OPT_Gain_averaging
	tmpindex = 9;
	for (i = tmpindex; i < FFT_HALFLEN - tmpindex; i++)
	{
		tmp = 0;
		for (j = -tmpindex; j <= tmpindex; j++)
			tmp = DVTXOP_add(tmp, DVTXOP_mult(RES_buf->S_tmpfft1[i - j], 1724));  //1/19*32767=1724 1/11*32767=2979
		RES_buf->G_fnlms[i] = tmp;
	}
#else
	tmpindex = 9;
	Gain_averaging(RES_buf->S_tmpfft1, RES_buf->G_fnlms, FFT_HALFLEN, tmpindex);
#endif



	/*for (i = 0; i < tmpindex; i++)
	RES_buf->G_fnlms[i] = RES_buf->S_tmpfft1[i];
	for (i = FFT_HALFLEN - tmpindex; i < FFT_HALFLEN; i++)
	RES_buf->G_fnlms[i] = RES_buf->S_tmpfft1[i];*/
#ifndef KHW_OPTI_20191216_HIFI
	for (i = 0; i < tmpindex; i++)
		RES_buf->G_fnlms[i] = RES_buf->S_tmpfft1[i];
#else
	 __vec_memcpy(RES_buf->G_fnlms,RES_buf->S_tmpfft1,(tmpindex<<1));
#endif



	tmp = 0;
	for (i = FFT_HALFLEN - tmpindex - 10; i < FFT_HALFLEN - tmpindex; i++)
		tmp = DVTXOP_add(tmp, DVTXOP_mult(RES_buf->G_fnlms[i], 3276));
	for (i = FFT_HALFLEN - tmpindex; i < FFT_HALFLEN; i++)
		RES_buf->G_fnlms[i] = tmp;



#ifndef KHW_OPTI_20191216_HIFI
	for (i = 5; i < 70; i++)
	{
		RES_buf->Gpwrres[i] = RES_buf->G_fnlms[i];
	}
#else
	 __vec_memcpy(&RES_buf->Gpwrres[5],&RES_buf->G_fnlms[5],(65<<1));

#endif


	if (channel == CH_INNER)
		tmpindex = DVTX_FreqMix_MaxBin;
	else
		tmpindex = FFT_HALFLEN;

	for (i = 0; i < tmpindex; i++)
	{
		if (RES_buf->Gpwrres[i] < RES_buf->G_fnlms[i]) // fast decreasing
			RES_buf->Gpwrres[i] = DVTXOP_add(DVTXOP_mult(RES_buf->Gpwrres[i], DVTX_WORD16_0_9), DVTXOP_mult(RES_buf->G_fnlms[i], DVTX_WORD16_0_1));
		else
			RES_buf->Gpwrres[i] = RES_buf->G_fnlms[i];
	}
	//for (i = 0; i < 5; i++)
	//{
	//	if (RES_buf->Gpwrres[i] < RES_buf->G_fnlms[i]) // fast decreasing
	//		RES_buf->Gpwrres[i] = DVTXOP_add(DVTXOP_mult(RES_buf->Gpwrres[i], DVTX_WORD16_0_9), DVTXOP_mult(RES_buf->G_fnlms[i], DVTX_WORD16_0_1));
	//	else
	//		RES_buf->Gpwrres[i] = RES_buf->G_fnlms[i];
	//}

	// bypass fnlms for outer ec
	if (NBBTmode == 0)
	{	

		THD_Rx_highband_fricative = 200000000;
		L_sum_Rx_highband = 0;
		for (i = 180; i < 224; i++) //5600~7000Hz
			L_sum_Rx_highband = DVTXOP_L_add(L_sum_Rx_highband, RES_buf->L_DDBin[i]);

		Flag_rx_fricative = L_sum_Rx_highband > THD_Rx_highband_fricative ? 1 : 0;
		if (Flag_rx_fricative == 1)
		{
			gmin1 = 8000;
			gmin2 = 100;
			gmin3 = 100;
			gmin4 = 100;			
		}
		else
		{
			gmin1 = 8000;
			gmin2 = 2000;
			gmin3 = 5000;
			gmin4 = 10000;			
		}
		
#if(FLAG_SELECT_C_DSP == 1)
#if(Debug_File_Write_C == 1)
		if (channel == FLAG_ECNS_WRITE_SELECTION)
		{
			fprintf(fp_deg_2micBF[21], "%ld %ld\n", L_sum_Rx_highband, THD_Rx_highband_fricative);
		}
#endif
#endif

		if (FFT_LEN == DVTX_FFT_LEN_WB)
		{
			for (i = 0; i < 10; i++) // ~320Hz
				RES_buf->Gpwrres[i] = DVTX_MAX(RES_buf->Gpwrres[i], gmin1);
			for (i = 10; i < 50; i++) // 320~1562Hz
				RES_buf->Gpwrres[i] = DVTX_MAX(RES_buf->Gpwrres[i], gmin2);
			for (i = 50; i < 100; i++) // 1562~3125Hz
				RES_buf->Gpwrres[i] = DVTX_MAX(RES_buf->Gpwrres[i], gmin3);
			for (i = 100; i < FFT_HALFLEN; i++) // 6250~8000Hz
				RES_buf->Gpwrres[i] = DVTX_MAX(RES_buf->Gpwrres[i], gmin4);

			if (channel != CH_INNER)
			{
				for (i = 100; i < 150; i++) //3125~4687Hz
					RES_buf->Gpwrres[i] = DVTX_MAX(RES_buf->Gpwrres[i], 120);
				for (i = 150; i < 200; i++) // 4687~6250Hz
					RES_buf->Gpwrres[i] = DVTX_MAX(RES_buf->Gpwrres[i], 50);
				for (i = 200; i < FFT_HALFLEN; i++) // 6250~8000Hz
					RES_buf->Gpwrres[i] = DVTX_MAX(RES_buf->Gpwrres[i], 10);
			}
		}
		if (Flag_Tx_Clipping == 1)
		{
			for (i = 0; i < 10; i++) // ~3200Hz
				RES_buf->Gpwrres[i] = DVTXOP_mult(RES_buf->Gpwrres[i], 26000);
			for (i = 10; i < tmpindex; i++) // ~3200Hz
				RES_buf->Gpwrres[i] = DVTXOP_mult(RES_buf->Gpwrres[i], 20000);


			fx_SolomonVoice_FFTbin_gain_applying(data_buffer, RES_buf->Gpwrres, FFT_HALFLEN);
		}
	}


#ifndef SRCB_1016_OPT
	/// mininum gain setting
	for (i = 1; i < tmpindex; i++)
	{
		if (i < 4)
			RES_buf->Gpwrres[i] = DVTX_MAX(RES_buf->Gpwrres[i], 1000);
		else if (i < 16)
			RES_buf->Gpwrres[i] = DVTX_MAX(RES_buf->Gpwrres[i], 120);
		else if (i < 32)
			RES_buf->Gpwrres[i] = DVTX_MAX(RES_buf->Gpwrres[i], 120);
		else
			RES_buf->Gpwrres[i] = DVTX_MAX(RES_buf->Gpwrres[i], 10);
	}

	fx_SolomonVoice_FFTbin_gain_applying(data_buffer, RES_buf->Gpwrres, FFT_HALFLEN);
#else
		MinGain_ApplyGain(data_buffer,RES_buf->Gpwrres, FFT_HALFLEN);
#endif



#if(FLAG_SELECT_C_DSP == 1)
#if(Debug_File_Write_C == 1)
	if (channel == FLAG_ECNS_WRITE_SELECTION)
	{
		for (i = 0; i < FFT_HALFLEN; i++) {
			if ((RES_buf->L_EEBin[i] == 3133440) &&
				(RES_buf->L_DDBin2[i] == 2686976) &&
				(RES_buf->L_RRBin[i] == 0) &&
				(RES_buf->W_fnlms_reression[i] == 29605) &&
				(0 == 0) &&
				(RES_buf->Gpwrres[i] == 0) &&
				(L_sum_Wres == 29090) &&
				(L_Elowband == 30587)) {
				i = i;
			}

			fprintf(fp_Wfnlms_new, "%ld %ld %ld %ld %d %d %d %ld %ld\n",
				0, //RES_buf->FNLMS_GAIN_MIN[i], // deleted to save memory
				RES_buf->L_EEBin[i],
				RES_buf->L_DDBin2[i],
				RES_buf->L_RRBin[i],
				RES_buf->W_fnlms_reression[i],
				0, // RES_buf->W_fnlms_update2[i], // deleted to save memory
				RES_buf->Gpwrres[i],
				L_sum_Wres,
				L_Elowband
			);
		}
	}
#endif
#endif

	return;

}

#ifdef fx_SolomonVoice_NS_1_OPT_DSP
void fx_SolomonVoice_NS_average_vector(short *S_tmpvec,short *Gns_final,short CHAN_HIGH)
{
	short tmp, tmp1, tmp2, tmp3;
	int i,num;
	ae_int16x4 *pvec, *pfinal, *pout;
	ae_valign align_vec, align_final, align_out;
	ae_int16x4 data0123, data1234, data2345, data4567, dataadd;
	ae_int16x4 DVTX_WORD1, DVTX_WORD2, DVTX_WORD3;

	pvec =  (ae_int16x4 *)&S_tmpvec[0];
	pfinal = (ae_int16x4 *)&Gns_final[1];
	pout = (ae_int16x4 *)&Gns_final[1];
	align_vec = AE_LA64_PP(pvec);
	align_final = AE_LA64_PP(pfinal);
	align_out = AE_ZALIGN64();

	DVTX_WORD1 = AE_MOVDA16(DVTX_WORD16_0_5);
	DVTX_WORD2 = AE_MOVDA16(DVTX_WORD16_0_1);
	DVTX_WORD3 = AE_MOVDA16(DVTX_WORD16_0_9);
	//////1~4//////////
	AE_LA16X4_IP(data0123, align_vec, pvec);
	AE_LA16X4_IP(data4567, align_vec, pvec);
	data1234 = AE_SEL16_6543(data0123, data4567);
	data2345 = AE_SEL16_5432(data0123, data4567);
	data1234 = AE_SRAA16S(data1234 ,1);
	data0123 = AE_SRAA16S(data0123, 2);
	data2345 = AE_SRAA16S(data2345, 2);
	dataadd = AE_ADD16S(data0123, data1234);
	dataadd = AE_ADD16S(dataadd, data2345);
	AE_LA16X4_IP(data0123, align_final, pfinal);
	//DVTXOP_add(DVTXOP_mult(NS_buf->S_Gns_final[i], DVTX_WORD16_0_5), DVTXOP_mult(tmp3, DVTX_WORD16_0_5));
	data1234 = AE_MULFP16X4S(data0123, DVTX_WORD1);
	data0123 = AE_MULFP16X4S(dataadd, DVTX_WORD1);
	dataadd = AE_ADD16S(data1234, data0123);
	AE_SA16X4_IP(dataadd, align_out, pout);
	//////5~8//////////
	data0123 = data4567;
	AE_LA16X4_IP(data4567, align_vec, pvec);
	data1234 = AE_SEL16_6543(data0123, data4567);
	data2345 = AE_SEL16_5432(data0123, data4567);
	data1234 = AE_SRAA16S(data1234 ,1);
	data0123 = AE_SRAA16S(data0123, 2);
	data2345 = AE_SRAA16S(data2345, 2);
	dataadd = AE_ADD16S(data0123, data1234);
	dataadd = AE_ADD16S(dataadd, data2345);
	AE_LA16X4_IP(data0123, align_final, pfinal);
	data2345 = AE_SEL16_6543(DVTX_WORD1,DVTX_WORD2);
	//DVTXOP_add(DVTXOP_mult(NS_buf->S_Gns_final[i], DVTX_WORD16_0_5), DVTXOP_mult(tmp3, DVTX_WORD16_0_5));
	data1234 = AE_MULFP16X4S(data0123, data2345);
	data2345 = AE_SEL16_6543(DVTX_WORD1,DVTX_WORD3);
	data0123 = AE_MULFP16X4S(dataadd, data2345);
	dataadd = AE_ADD16S(data1234, data0123);
	AE_SA16X4_IP(dataadd, align_out, pout);
	/////9~CHAN_HIGH - 1//////////
	num = (CHAN_HIGH-9)/4;
	for(i = 0; i < num; i++)
	{
		data0123 = data4567;
		AE_LA16X4_IP(data4567, align_vec, pvec);
		data1234 = AE_SEL16_6543(data0123, data4567);
		data2345 = AE_SEL16_5432(data0123, data4567);
		data1234 = AE_SRAA16S(data1234 ,1);
		data0123 = AE_SRAA16S(data0123, 2);
		data2345 = AE_SRAA16S(data2345, 2);
		dataadd = AE_ADD16S(data0123, data1234);
		dataadd = AE_ADD16S(dataadd, data2345);
		AE_LA16X4_IP(data0123, align_final, pfinal);
		//DVTXOP_add(DVTXOP_mult(NS_buf->S_Gns_final[i], DVTX_WORD16_0_1), DVTXOP_mult(tmp3, DVTX_WORD16_0_9));
		data1234 = AE_MULFP16X4S(data0123, DVTX_WORD2);
		data0123 = AE_MULFP16X4S(dataadd, DVTX_WORD3);
		dataadd = AE_ADD16S(data1234, data0123);
		AE_SA16X4_IP(dataadd, align_out, pout);
	}
	AE_SA64POS_FP(align_out, pout);
	for(i=(num*4 + 9); i<=CHAN_HIGH - 1; i++)
	{
		tmp = DVTXOP_shr(S_tmpvec[i], 1);
		tmp1 = DVTXOP_shr(S_tmpvec[i - 1], 2);
		tmp2 = DVTXOP_shr(S_tmpvec[i + 1], 2);

		tmp3 = DVTXOP_add(DVTXOP_add(tmp, tmp1), tmp2);

		Gns_final[i] = DVTXOP_add(DVTXOP_mult(Gns_final[i], DVTX_WORD16_0_1), DVTXOP_mult(tmp3, DVTX_WORD16_0_9));
	}
}
#endif
void fx_SolomonVoice_RES(COMMONBUF* common_buf, AECStatus* AEC_buf, RESStatus* RES_buf, NSStatus* NS_buf, SamsungSolomonVoiceWTxAECParam* AEC_param, SamsungSolomonVoiceWTxFRAMEParam* Frame_param, SamsungSolomonVoiceWTxRESParam* RES_param, SamsungSolomonVoiceWTxNSParam* NS_param,
	short *data_buffer, short DIVID_BY_MULT_NUM_CH, short BLK_NORM, short BLK_NORM_rx, short CHAN_HIGH, short NUM_CHAN, short FFT_HALFLEN, CHANNEL channel)
{
	short i, tmp;
	short GresOffsetHF, forgetNew, forgetOld;
	int Ltmp, L_GwienerAvg;
	int  L_forgetNew_dc, L_forgetOld_dc;
	int  L_forgetNew_ic, L_forgetOld_ic;

	/*
	Solomonvoice function
	calculate FFT bin power
	input  : Q15,0
	output : Q30,1
	*/
	fx_SolomonVoice_FFT_to_FFTpwr(RES_buf->L_EEBin, data_buffer, FFT_HALFLEN);

	/*Solomonvoice function
	FFTbin to Band power
	input  : Q30,1, Nfft/2+1
	output : Q30,1, Nband
	*/
	fx_SolomonVoice_FFTpwr_to_FFTband(NS_buf->L_Esqr_q30, RES_buf->L_EEBin, tx_ch_tbl_nswb, tx_ch_tbl_sh_wb, CHAN_HIGH);

	// Band Q-format change : 30,1 -> 23,8
	fx_SolomonVoice_PwrBand_FixQ_BlkDeNorm(NS_buf->L_Esqr, NS_buf->L_Esqr_q30, BLK_NORM, 7, CHAN_HIGH);


	/* SolomonVoice_SubBlocks #11:
	echo psd manipulation, Fixed band gain
	*/
	L_forgetNew_dc = DVTX_WORD32_0_2;// default for HS EAR : slow decreasing
	L_forgetOld_dc = DVTX_WORD32_0_8;
	L_forgetNew_ic = DVTX_WORD32_0_8; // fast increasing
	L_forgetOld_ic = DVTX_WORD32_0_2;
	if (Frame_param->PARA_call_mode_HS_HF_EAR == 0) // only for HF mode
	{
		L_forgetNew_dc = DVTX_WORD32_0_1; // slow decreasing
		L_forgetOld_dc = DVTX_WORD32_0_9;
		L_forgetNew_ic = DVTX_WORD32_0_9; // fast increasing
		L_forgetOld_ic = DVTX_WORD32_0_1;
	}
	if (Frame_param->PARA_call_mode_HS_HF_EAR == 4) // only for GEAR mode
	{
		L_forgetNew_dc = DVTX_WORD32_0_1; // slow decreasing
		L_forgetOld_dc = DVTX_WORD32_0_9;
		L_forgetNew_ic = DVTX_WORD32_0_9; // fast increasing
		L_forgetOld_ic = DVTX_WORD32_0_1;
		if ((AEC_buf->Flag_RxVAD_AEC == 0) && (AEC_buf->Flag_SingleNET == 1))
		{
			L_forgetNew_dc = DVTX_WORD32_0_8; // slow decreasing
			L_forgetOld_dc = DVTX_WORD32_0_2;
		}
	}

	/* SolomonVoice_SubBlocks #12:
	echo scalar gain recursive averaging
	g_highxecc : Q5,10
	g_lowxecc : Q5,10
	g : Q0.15
	*/
	RES_buf->Gain_echo_PSD_RES =
		fx_SolomonVoice_EchoPSD_gain_cal(RES_buf->Gain_echo_PSD_RES,
			RES_param->PARA_Gain_EchoPSD_RES, AEC_buf->Flag_RxVAD_AEC, AEC_buf->Flag_SingleTalk, AEC_buf->XECC, AEC_param->PARA_reserved_22,
			AEC_param->PARA_reserved_23, AEC_param->PARA_reserved_24);


	/* SolomonVoice_SubBlocks #13:
	echo PSD gain = scalar gain * band gain
	EchoPSD = DD*gain
	*/
	//Q30.1
	fx_SolomonVoice_EchoPower_estimation(NS_buf->L_Dsqr_q30, RES_param->PARA_Gain_Echo_PSD, RES_buf->Gain_echo_PSD_RES, CHAN_HIGH);
	//L_Dsqr_ravg: Q23.8
	fx_SolomonVoice_EchoPSD_estimation(RES_buf->L_Dsqr_ravg, NS_buf->L_Dsqr_q30,
		L_forgetNew_dc, L_forgetOld_dc, L_forgetNew_ic, L_forgetOld_ic, BLK_NORM_rx, NS_param->PARA_MIN_CHAN_PWR, 7, CHAN_HIGH);


	/* SolomonVoice_SubBlocks #14:
	Esqr_silence estimation
	L_Esqr_ravg_silence
	Q23.8
	*/
	fx_SolomonVoice_Npsd_Silence_estimation(RES_buf->L_Esqr_ravg_silence, NS_buf->L_Esqr_q30, AEC_buf->Flag_TxSilence_AEC,
		DVTX_WORD32_0_5, DVTX_WORD32_0_5, BLK_NORM, 7, CHAN_HIGH);


	/* SolomonVoice_SubBlocks #15:
	Post SER / Post SER smoothing / prioi SER
	L_SERpost : Q16.15
	L_SERprio : Q16.15
	*/
	//23,8		
	fx_SolomonVoice_VectorAdd_ll(NS_buf->L_PSD_resiEcho, RES_buf->L_Dsqr_ravg, RES_buf->L_Esqr_ravg_silence, CHAN_HIGH);

	//16.15
	//SNR min = 2 ^ 15 * (1 / 128) max = 2 ^ 15 * (256)
	fx_SolomonVoice_postSNR_cal_with_limitation_Q15(NS_buf->L_tmpvec, NS_buf->L_Esqr, NS_buf->L_PSD_resiEcho, 32, 8388608, CHAN_HIGH);

	// RES : post SER averaging	//16.15			
	Fn_vector_smoothing_over_3_win_length(NS_buf->L_SERpost, NS_buf->L_tmpvec, (short)NUM_CHAN, (short)NUM_CHAN);

	/*Solomonvoice function
	Decision directed a priori SNR estimation
	SNRpost : Q 16.15
	SNRprio : Q 16.15
	*/
	forgetOld = 30800; //0.94
	forgetNew = 32767 - forgetOld;
	fx_SolomonVoice_DD_SNRprio_estimation(NS_buf->L_SERprio, NS_buf->L_tmpvec, NS_buf->L_SERpost, NS_buf->L_SERpost_prv,
		NS_buf->Gres, forgetOld, forgetNew, 32, 8388608, CHAN_HIGH);//16.15	


	/* SolomonVoice_SubBlocks #16:
	priori SER control / Wiener gain avg / RES gain offset
	if ST : SER=SER*0.002
	SER freq. smoothing
	if GresAvg<0.05 : Gres <=0.1
	if GresAvg<0.3 :  GresOffset 0.02
	*/
	// RES :  priori SER smoothing
	Fn_vector_smoothing_over_3_win_length(NS_buf->L_SERprio, NS_buf->L_tmpvec, (short)NUM_CHAN, (short)NUM_CHAN);//16.15	


	/*Solomonvoice function
	Decision directed a priori SNR estimation
	SNRprio : Q16.15
	Gwiener : Q0.31
	L_Gavg  : Q0.15
	*/
	L_GwienerAvg = fx_SolomonVoice_Wiener_gainvector_Q31(NS_buf->L_tmpvec1, NS_buf->L_SERprio, CHAN_HIGH, DIVID_BY_MULT_NUM_CH);//Gain=Q0.31, GainAVG=Q0.15

	// RES gain control for HF call 
	GresOffsetHF = 0;
	if ((Frame_param->PARA_call_mode_HS_HF_EAR == 0) || (Frame_param->PARA_call_mode_HS_HF_EAR == 4)) // only for HF and GEAR mode
	{
		if (L_GwienerAvg < 4259) //Q0.15 0.05*32767
		{
			for (i = 0; i < 7; i++)
			{
				Ltmp = DVTXOP_L_mpy_ls(NS_buf->L_tmpvec1[i], 2000);
				NS_buf->L_tmpvec1[i] = DVTX_MIN(Ltmp, 214748364);//Q0.31 0.1*2^31
			}
			for (i = 7; i <= CHAN_HIGH; i++)
			{
				Ltmp = DVTXOP_L_mpy_ls(NS_buf->L_tmpvec1[i], 6553);
				NS_buf->L_tmpvec1[i] = DVTX_MIN(Ltmp, 429496729);//Q0.31 0.2*2^31
			}
		}
		else if (L_GwienerAvg > 9830) //0.3
			GresOffsetHF = 655; //0.02
	}

	Fn_vector_smoothing_over_3_win_length(NS_buf->L_tmpvec, NS_buf->L_tmpvec1, (short)NUM_CHAN, (short)NUM_CHAN);//Gain=Q0.31

	/* SolomonVoice_SubBlocks #17:
	RES gain control, RES
	CntFrmRxVADon<50 : 0.05 gain
	Single NET       : 0.5 noise floor
	RES minimum gain = G>SQRT(N^2/X^2)
	*/
	// RES :  gain table index search
	if ((Frame_param->PARA_call_mode_HS_HF_EAR == 0) || (Frame_param->PARA_call_mode_HS_HF_EAR == 4)) // only for HF and GEAR mode
	{
		fx_SolomonVoice_WienerQ31_to_GainQ15(NS_buf->Gres, NS_buf->L_tmpvec, 2, CHAN_HIGH);
	}
	else
	{
		fx_SolomonVoice_WienerQ31_to_GainQ15(NS_buf->Gres, NS_buf->L_tmpvec, 1, CHAN_HIGH);
	}

	//if ((DVTX_ECNS_vars->PARA_FLAG_RxVAD_First_AEC == 1) && (AEC_buf->Flag_RxVAD_AEC == 1))
	if ((RES_buf->CntFrmRxVADon < DVTX_Num_of_ini_RxOn_Frmae) && (AEC_buf->Flag_RxVAD_AEC == 1))
	{
		for (i = 0; i <= CHAN_HIGH; i++)
			NS_buf->Gres[i] = DVTX_MIN(NS_buf->Gres[i], RES_param->PARA_reserved_31); //0.05noise flooring
	}
	// for NET interval
	if ((AEC_buf->Flag_RxVAD_AEC == 0) && (AEC_buf->Flag_SingleNET == 1))
	{
		for (i = 0; i <= CHAN_HIGH; i++)
			NS_buf->Gres[i] = DVTX_MAX(NS_buf->Gres[i], 29490); //0.5noise flooring
	}
	// for NET band
	//for (i = 0; i <= CHAN_HIGH; i++)
	//{
	//	if (ECNSbuff->SingleNETflagBand[i] == 1)
	//		NS_buf->Gres[i] = DVTX_MAX(NS_buf->Gres[i], 29490); //0.5noise flooring
	//}

	// RES minimum gain : X^2*G^2=Y^2>N^2, G>SQRT(N^2/X^2)	
	for (i = 0; i <= CHAN_HIGH; i++)
	{
		//Ltmp = DVTXOP_L_shl(ECNSbuff->L_EsqrNS_q30[i], (short)(15 - (2 * BLK_NORM))); //Q15,16		
		//norm_shift = DVTXOP_norm_l(Ltmp); //denominator ºÐ¸ð
		//Ltmp = DVTXOP_L_shl(Ltmp, norm_shift);
		////Ltmp = DVTX_MAX(Ltmp, 1);

		//Ltmp5 = ECNSbuff->L_Npsd_for_minGain[i]; //Q15,16
		//norm_shift1 = DVTXOP_norm_l(Ltmp5);
		//Ltmp3 = DVTXOP_L_shl(Ltmp5, (short)(norm_shift1 - 1)); // numerator ºÐÀÚ
		////Ltmp3 = DVTX_MAX(Ltmp3, 1);

		//Ltmp4 = DVTXOP_L_divide(Ltmp3, Ltmp);// Q0.31		
		//
		//ECNSbuff->REG_Gain_MIN[i] = DVTXOP_extract_h(DVTXOP_L_shr_r(Ltmp4, (short)(-1 + norm_shift1 - norm_shift)));   //0,31

		//ECNSbuff->REG_Gain_MIN[i] = DVTXOP_L_mpy_ls(ECNSbuff->REG_Gain_MIN[i], 25000); // N^2*a, a=0.7*32767

		//if (DVTX_ECNS_vars->PARA_call_mode_HS_HF_EAR == 3)
		//	ECNSbuff->REG_Gain_MIN[i] = DVTXOP_L_shr_r(ECNSbuff->REG_Gain_MIN[i], 1);

		//if (NS_buf->Gres[i] < ECNSbuff->REG_Gain_MIN[i])
		//	NS_buf->Gres[i] = ECNSbuff->REG_Gain_MIN[i];
#ifndef KHW_OPTI_20191216
		if (NS_buf->Gres[i] < 3000)
			NS_buf->Gres[i] = 3000;
#else
		NS_buf->Gres[i] = DVTX_MAX(NS_buf->Gres[i],3000);
#endif

	}

	tmp = DVTXOP_add(RES_param->PARA_NoiseFloor_RES, GresOffsetHF); // minimu RES gain

	RES_buf->GmmseNFFT = (short *)common_buf->Buff_L_NB;

	fx_SolomonVoice_Gain_band_to_bin(RES_buf->GmmseNFFT, NS_buf->Gres, tx_ch_tbl_nswb, tmp, CHAN_HIGH);
	RES_buf->GmmseNFFT[0] = DVTX_MAX_16;

	fx_SolomonVoice_FFTbin_gain_applying(data_buffer, RES_buf->GmmseNFFT, FFT_HALFLEN);

	for (i = 0; i < FFT_HALFLEN; i++)
	{
		if (data_buffer[2 * i] == -1 && RES_buf->GmmseNFFT[i] == RES_param->PARA_NoiseFloor_RES)
			data_buffer[2 * i] = 0;
		if (data_buffer[2 * i + 1] == -1 && RES_buf->GmmseNFFT[i] == RES_param->PARA_NoiseFloor_RES)
			data_buffer[2 * i + 1] = 0;
	}

#if(FLAG_SELECT_C_DSP == 1)
#if(Debug_File_Write_C == 1)
	if (channel == FLAG_ECNS_WRITE_SELECTION)
	{
		for (i = 0; i <= CHAN_HIGH; i++)
			fprintf(fp_debug_ns_vec3, "%d %ld %ld %ld %ld %ld %ld %d %ld\n",
				0,//ECNSbuff->SingleNETflagBand[i],
				NS_buf->L_Esqr[i],
				RES_buf->L_Dsqr_ravg[i],
				RES_buf->L_Esqr_ravg_silence[i],
				NS_buf->L_PSD_resiEcho[i],
				NS_buf->L_SERpost[i],
				NS_buf->L_SERprio[i],
				NS_buf->Gres[i], L_GwienerAvg
			);
		fprintf(fp_debug_ns_vec2, "%d\n", RES_buf->Gain_echo_PSD_RES);
	}
#endif
#endif

	return;
}


int L_tmp_NpsdBF_Band[DVTX_M_NUM_CHAN_WB] = { 0, };
int L_tmp_NpsdBF_Bin[DVTX_M_FFT_HALFLEN_WB] = { 0, };

void fx_SolomonVoice_NS(DVTX_ECNS_Cfg_t* DVTX_ECNS_vars, FRAMEStatus* FRAME_buf, AECStatus* AEC_buf, RESStatus* RES_buf, NSStatus* NS_buf, MixingStatus* Mix_buf,
	SamsungSolomonVoiceWTxFRAMEParam* Frame_param, SamsungSolomonVoiceWTxNSParam* NS_param,
	short *data_buffer, short DIVID_BY_MULT_NUM_CH, short BLK_NORM, short CHAN_HIGH, short NUM_CHAN, short FFT_HALFLEN, CHANNEL channel, short NBBTmode, VADACCStatus *VADACC_buf, short BLK_NORM_Acc)
{
	
	BFStatus*      BF_buf = &DVTX_ECNS_vars->BF_buf;
	ContextStatus* Context_buf = &DVTX_ECNS_vars->Context_buf;


	short i;
	short tmp, tmp1, tmp2, tmp3, forgetNew, forgetOld, y1, y2, suby1y2, FLAGsoft_SNR_ini;
	int Lx1, Lx2, Ltmp1, Ltmp2, L_SNR_ini_avg_dB, L_GwienerAvg, invSNR;
	short PARA_FLAG_FIRST_FRM;
	short Gmin = DVTX_ECNS_vars->COMMON_buf.Gmin;
	short cntx_NpsdGain, cntx_NoiseOffSet, MaxSPP; // 0 (noise free) ~ 7(high noise)

	short NoiseFloorOffset_0_250Hz_low,     NoiseFloorOffset_0_250Hz_high;
	short NoiseFloorOffset_250_4000Hz_low,  NoiseFloorOffset_250_4000Hz_high;
	short NoiseFloorOffset_4000_8000Hz_low, NoiseFloorOffset_4000_8000Hz_high;
	short NoiseLevel;
	short FlagEXE;

	NoiseLevel = 0;
#ifdef __SV_USE_ANC_RESULT__
	InterChnanelANCStatus *ANC_buf = (InterChnanelANCStatus*)DVTX_ECNS_vars->ICANC_buf;
#endif
	if (channel == CH_OUTER_1)
		PARA_FLAG_FIRST_FRM = Frame_param->PARA_FLAG_FIRST_FRM_Outer;
	else
		PARA_FLAG_FIRST_FRM = Frame_param->PARA_FLAG_FIRST_FRM_Inner;

	// Noise suppression
	// initial SNR by MMSE-based VAD////////////////////////////////////////////////////////////////////////////////////////		
	if (PARA_FLAG_FIRST_FRM == DVTX_TRUE)
	{
#ifndef fx_SolomonVoice_NS_MEMCPY_OPT_DSP
		for (i = 0; i <= CHAN_HIGH; i++)
		{
			NS_buf->L_Npsd[i] = NS_buf->L_EsqrNS_q30[i]; //30.0
			NS_buf->L_Npsd_MMSE_ini[i] = NS_buf->L_EsqrNS[i]; //q23,8
			NS_buf->L_Npsd_MMSE_TMP[i] = NS_buf->L_EsqrNS[i];
			NS_buf->P_H1_ravg[i] = 0;
		}
#else
		__vec_memcpy(NS_buf->L_Npsd, NS_buf->L_EsqrNS_q30, ((CHAN_HIGH+1)<<2));
		__vec_memcpy(NS_buf->L_Npsd_MMSE_ini, NS_buf->L_EsqrNS, ((CHAN_HIGH+1)<<2));
		__vec_memcpy(NS_buf->L_Npsd_MMSE_TMP, NS_buf->L_EsqrNS, ((CHAN_HIGH+1)<<2));
		for (i = 0; i <= CHAN_HIGH; i++)
		{
			NS_buf->P_H1_ravg[i] = 0;
		}
#endif
	}

	if (channel == CH_INNER)
	{
		if (VADACC_buf->VADACCframe_Fast == 0)
		{
#ifndef fx_SolomonVoice_NS_MEMCPY_OPT_DSP
			for (i = 0; i <= CHAN_HIGH; i++)
			{
				NS_buf->L_Npsd_MMSE_ini[i] = NS_buf->L_EsqrNS[i]; //q23,8
			}
#else
			__vec_memcpy(NS_buf->L_Npsd_MMSE_ini,NS_buf->L_EsqrNS,((CHAN_HIGH+1)<<2));
#endif
		}
	}
	/* SolomonVoice_SubBlocks #19:
	initial SNR estimation :
	EE, NN, DD : Q23.8
	L_SNR_by_Nmmse_ini
	Q16.15
	//min = 2^15*(1/512) max = 2^15*(512)
	*/
	// SNR calculation: Esqr/Npsd		
	fx_SolomonVoice_initial_SNR_estimation(NS_buf->L_SNR_by_Nmmse_ini,
		NS_buf->L_EsqrNS, NS_buf->L_Npsd_MMSE_ini, RES_buf->L_Dsqr_ravg, NS_param->PARA_Gain_EchoPSD_NS, 16, CHAN_HIGH);

	/* SolomonVoice_SubBlocks #20:
	long term SNR estimation // frame SNR value : L_SNR_ini_avg_dB
	to control cepstrum smoothing facotr
	time-freq smoothing
	L_SNR_by_Nmmse_ini_avg 		Q16.15
	L_SNR_ini_avg_dB : Q8,7
	*/
	//Fn_vector_smoothing_over_5_win_length(NS_buf->L_tmpvec1, NS_buf->L_SNR_by_Nmmse_ini, NUM_CHAN);
	//Fn_vector_smoothing_over_5_win_length(NS_buf->L_tmpvec1, NS_buf->L_tmpvec, NUM_CHAN);
	//L_SNR_ini_avg_dB = fx_SolomonVoice_iniSNR_smoothing(NS_buf->L_SNR_by_Nmmse_ini_avg, NS_buf->L_tmpvec1, DIVID_BY_MULT_NUM_CH, DVTX_WORD16_0_9, CHAN_HIGH);
	L_SNR_ini_avg_dB = fx_SolomonVoice_iniSNR_smoothing(NS_buf->L_SNR_by_Nmmse_ini_avg, NS_buf->L_SNR_by_Nmmse_ini, DIVID_BY_MULT_NUM_CH, DVTX_WORD16_0_5, CHAN_HIGH);


#if(0)
	/* SolomonVoice_SubBlocks #21:
	forgetting factor calculation for cepstral smoothing
	FLAGsoft_SNR_ini : Q0.15, --> calculate tmp_beta_ceps[i], FLAGsoft_SNR_ini °ªÀÌ 1¿¡ °¡±î¿ì¸é(high SNR) calculate tmp_beta_ceps[i] ÀÛ¾ÆÁü(cepstral smoothing Àû°Ô ÇÔ)
	tmp_beta_ceps[i] band1 : quefrency 0~2, 0.01~0.2
	band2 : quefrency 3~15, 0.5~0.92
	band3 : quefrency 16~end, 0.8~0.92
	64point cepstrum analysis
	input : SNRvecotr Q16.15(no block norm since input Q is fixed)
	output : cepstrum 16bit
	*/
	fx_SolomonVoice_64point_cepstrum_transform(NS_buf->L_SNR_by_Nmmse_ini, NS_buf->SNR_ini_ceps, CHAN_HIGH);



	if (PARA_FLAG_FIRST_FRM == DVTX_TRUE)
	{
		for (i = 0; i < DVTX_Nfft_ceps; i++)
		{
			NS_buf->SNR_ini_ceps_avg[i] = NS_buf->SNR_ini_ceps[i]; //30.0
			NS_buf->SNR_ini_ceps_Fixedavg[i] = NS_buf->SNR_ini_ceps[i]; //30.0
		}
	}

	// forgettinf factor for cepstral smoothing
	Lx1 = NS_param->PARA_THD_Lo_SNRiniAvg_for_beta;  // 49152;  //1.5*2^15 q15
	Lx2 = NS_param->PARA_THD_Hi_SNRiniAvg_for_beta; // 163840; //5.0*2^15 q15
	tmp = NS_param->PARA_Slop_SNRiniAvg_for_beta;   // 9362;   //1/(5.0-1.5)*2^15 q15
	y1 = 0;
	y2 = DVTX_MAX_16;
	suby1y2 = y2 - y1;
	Ltmp1 = DVTXOP_L_sub(DVTXOP_L_shl(L_SNR_ini_avg_dB, 7), Lx1); //q15 278528
	Ltmp2 = DVTXOP_L_mpy_ls(Ltmp1, tmp);//q15 79577
	Ltmp2 = DVTXOP_L_shr(DVTXOP_L_mpy_ls(Ltmp2, suby1y2), 0);//q15
	Ltmp2 = DVTXOP_L_add(Ltmp2, (int)y1);//q15
	FLAGsoft_SNR_ini = (short)DVTX_MIN(DVTX_MAX(Ltmp2, (int)y1), (int)y2);
	// forgetting factor calcuation
	if (NBBTmode == 0)
	{
		if (FLAG_WB_OuterECNSOnly == 1) // WB Á¤·®ÃøÁ¤
		{
			fx_SolomonVoice_forgetfactor_cal_Cepstral_smoothing(NS_buf->beta_ceps, NS_buf->tmp_beta_ceps, AEC_buf->Flag_Tx_LoudSig, FLAGsoft_SNR_ini);
		}
		else
		{
			fx_SolomonVoice_forgetfactor_cal_Cepstral_smoothing(NS_buf->beta_ceps, NS_buf->tmp_beta_ceps, FRAME_buf->FrmVAD_Inner, FLAGsoft_SNR_ini);
		}
	}
	else
	{
		fx_SolomonVoice_forgetfactor_cal_Cepstral_smoothing(NS_buf->beta_ceps, NS_buf->tmp_beta_ceps, AEC_buf->Flag_Tx_LoudSig, FLAGsoft_SNR_ini);
	}

	/* SolomonVoice_SubBlocks #22:
	SNR cepstrum smoothing and return to SNR
	L_SNR_by_Nmmse_ini_cepsmooth : used at 2nd Npsd estimation
	Q16.15
	*/
	// cepstrum smoothing	
	fx_SolomonVoice_cepstral_smoothing_softForgetting(NS_buf->SNR_ini_ceps_avg, NS_buf->tmpvec_ceps, NS_buf->SNR_ini_ceps, NS_buf->beta_ceps);

	// cepstrum to smoothed SNR	
	// Q16.15
	fx_SolomonVoice_64point_INVERSE_cepstrum_transform(NS_buf->L_SNR_by_Nmmse_ini_cepsmooth, NS_buf->tmpvec_ceps, CHAN_HIGH);


	/* SolomonVoice_SubBlocks #23:
	SNR cepstrum smoothing and return to SNR
	Fixed forgetting factor
	L_SNR_by_Nmmse_ini_cepsmooth_fix : used at initial Npsd estimation
	band1 : quefrency 0~2, 0.3
	band2 : quefrency 3~15, 0.8
	band3 : quefrency 16~end, 0.9
	if FlagLoudTx ==1, less smoothing
	*/
	// second cepstrum smoothing : fixed forgetting factor
	// loud signal ÀÏ°æ¿ì forgetting ÀÛ°Ô--ºü¸¥ ½º¹Çµù

	if (NBBTmode == 0)
	{
		if (FLAG_WB_OuterECNSOnly == 1) // WB Á¤·®ÃøÁ¤
		{
			fx_SolomonVoice_cepstral_smoothing_FixForgetting(AEC_buf->Flag_Tx_LoudSig, NS_buf->SNR_ini_ceps_Fixedavg, NS_buf->tmpvec_ceps, NS_buf->SNR_ini_ceps,
				DVTX_WORD16_0_3, DVTX_WORD16_0_8, DVTX_WORD16_0_9, DVTX_WORD16_0_1, DVTX_WORD16_0_4, DVTX_WORD16_0_6);
		}
		else
		{
			if (channel == CH_INNER)
			{
				fx_SolomonVoice_cepstral_smoothing_FixForgetting(FRAME_buf->FrmVAD_Inner, NS_buf->SNR_ini_ceps_Fixedavg, NS_buf->tmpvec_ceps, NS_buf->SNR_ini_ceps,
					DVTX_WORD16_0_3, DVTX_WORD16_0_8, DVTX_WORD16_0_9, DVTX_WORD16_0_1, DVTX_WORD16_0_4, DVTX_WORD16_0_6);
			}
			else
			{
				if (Mix_buf->State <= 2)
				{
					fx_SolomonVoice_cepstral_smoothing_FixForgetting(FRAME_buf->FrmVAD_Inner, NS_buf->SNR_ini_ceps_Fixedavg, NS_buf->tmpvec_ceps, NS_buf->SNR_ini_ceps,
						DVTX_WORD16_0_3, DVTX_WORD16_0_8, DVTX_WORD16_0_9, DVTX_WORD16_0_1, DVTX_WORD16_0_4, DVTX_WORD16_0_6);
				}
				else
				{
					fx_SolomonVoice_cepstral_smoothing_FixForgetting(FRAME_buf->FrmVAD_Inner, NS_buf->SNR_ini_ceps_Fixedavg, NS_buf->tmpvec_ceps, NS_buf->SNR_ini_ceps,
						DVTX_WORD16_0_7, DVTX_WORD16_0_8, DVTX_WORD16_0_9, DVTX_WORD16_0_4, DVTX_WORD16_0_7, DVTX_WORD16_0_8);
				}
			}
		}
	}
	else
	{
		fx_SolomonVoice_cepstral_smoothing_FixForgetting(AEC_buf->Flag_Tx_LoudSig, NS_buf->SNR_ini_ceps_Fixedavg, NS_buf->tmpvec_ceps, NS_buf->SNR_ini_ceps,
			DVTX_WORD16_0_3, DVTX_WORD16_0_8, DVTX_WORD16_0_9, DVTX_WORD16_0_1, DVTX_WORD16_0_4, DVTX_WORD16_0_6);
	}

	// cepstrum to smoothed SNR
	fx_SolomonVoice_64point_INVERSE_cepstrum_transform(NS_buf->L_SNR_by_Nmmse_ini_cepsmooth_fix, NS_buf->tmpvec_ceps, CHAN_HIGH);
	//end of cepstrum smoothing ............................................................

#else

#ifndef KHW_OPTI_20191216_HIFI
	for (i = 0; i <= CHAN_HIGH; i++)
	{
		NS_buf->L_SNR_by_Nmmse_ini_cepsmooth[i]     = NS_buf->L_SNR_by_Nmmse_ini[i]; //30.0
		NS_buf->L_SNR_by_Nmmse_ini_cepsmooth_fix[i] = NS_buf->L_SNR_by_Nmmse_ini[i]; //q23,8
		
	}
#else
	__vec_memcpy(NS_buf->L_SNR_by_Nmmse_ini_cepsmooth,NS_buf->L_SNR_by_Nmmse_ini,((CHAN_HIGH+1)<<2));
	__vec_memcpy(NS_buf->L_SNR_by_Nmmse_ini_cepsmooth_fix,NS_buf->L_SNR_by_Nmmse_ini,((CHAN_HIGH+1)<<2));
#endif

#if(FLAG_SELECT_C_DSP == 1)
	FLAGsoft_SNR_ini = 0;
#endif
#endif





	/* SolomonVoice_SubBlocks #24:
	MMSE-based initial Npsd estimation
	L_SNR_by_Nmmse_ini_cepsmooth_fix used as SNR , Q16.15
	a priori SNR is from the tune para, PARA_FixedXi[i][0], 0~15[dB]
	L_Npsd_MMSE_TMP = Q23.8
	L_Npsd_MMSE_ini = Q23.8
	*/
	if ((channel == CH_INNER) && (DVTX_ECNS_vars->Mix_buf.State_Wind == 1))
	{
		fx_SolomonVoice_SNR_to_PH1_lookuptable(NS_buf->P_H1, NS_buf->L_SNR_by_Nmmse_ini_cepsmooth_fix, NS_param->PARA_FixedXi, 2, 2, 1, 0, CHAN_HIGH);
		fx_SolomonVoice_recursive_avg_SS_highcomplexity(NS_buf->P_H1_ravg, NS_buf->P_H1, DVTX_WORD16_0_99, DVTX_WORD16_0_01, CHAN_HIGH);
	}
	else
	{
		fx_SolomonVoice_SNR_to_PH1_lookuptable(NS_buf->P_H1, NS_buf->L_SNR_by_Nmmse_ini_cepsmooth_fix, NS_param->PARA_FixedXi, 0, 2, 1, 0, CHAN_HIGH);
		fx_SolomonVoice_recursive_avg_SS_highcomplexity(NS_buf->P_H1_ravg, NS_buf->P_H1, DVTX_WORD16_0_5, DVTX_WORD16_0_5, CHAN_HIGH);
	}


	fx_SolomonVoice_prevent_stagnation_PH1(NS_buf->P_H1, NS_buf->P_H1_ravg, CHAN_HIGH);

	if (NBBTmode == 1)
	{
		if (AEC_buf->Flag_Tx_silent_mode == 1)
		{
			if (AEC_buf->Flag_TxSilence_AEC == 0)
			{
				fx_SolomonVoice_Npsd_ini_calculation(NS_buf->L_Npsd_MMSE_ini, NS_buf->L_Npsd_MMSE_TMP, NS_buf->P_H1, NS_buf->L_EsqrNS, CHAN_HIGH, 26213, 27851);
			}
		}
		else
		{
			fx_SolomonVoice_Npsd_ini_calculation(NS_buf->L_Npsd_MMSE_ini, NS_buf->L_Npsd_MMSE_TMP, NS_buf->P_H1, NS_buf->L_EsqrNS, CHAN_HIGH, 26213, 27851);
		}
	}
	else
	{		


		if (FRAME_buf->STATE_Voice_Active == 0)
		{
			if ((channel == CH_OUTER_1) && (DVTX_ECNS_vars->Mix_buf.State_Wind == 0)) // use BF BM out as initial Npsd
			{
				if (FRAME_buf->STATE_ACC_Effective == 0)// use Npsd BM
				{ 
					if((BF_buf->LSTV_value_BF < DVTX_LTSV_03) || (VADACC_buf->LogPwrXXacc_LF_AVG < (82 << 23)))//THD_VARIABLE_VADACC_LOGPWR_XXACC_LF_MIN))
					{
						tmp = 13000;// 19000;
						tmp1 = 13000;
					}
					else
					{
						tmp = 3000;// 19000;
						tmp1 = 3000;
					}
					for (i = 0; i < 16; i++)//500Hz
						L_tmp_NpsdBF_Bin[i] = DVTXOP_L_mpy_ls(DVTX_ECNS_vars->BF_buf.NpsdBM[i], tmp);
					for (i = 16; i < 32; i++)//1000Hz
						L_tmp_NpsdBF_Bin[i] = DVTXOP_L_mpy_ls(DVTX_ECNS_vars->BF_buf.NpsdBM[i], tmp);
					for (i = 32; i < 64; i++)//2000Hz
						L_tmp_NpsdBF_Bin[i] = DVTXOP_L_mpy_ls(DVTX_ECNS_vars->BF_buf.NpsdBM[i], tmp);
					for (i = 64; i < 128; i++)//4000Hz
						L_tmp_NpsdBF_Bin[i] = DVTXOP_L_mpy_ls(DVTX_ECNS_vars->BF_buf.NpsdBM[i], tmp1);
					for (i = 128; i < 192; i++)//6000Hz
						L_tmp_NpsdBF_Bin[i] = DVTXOP_L_mpy_ls(DVTX_ECNS_vars->BF_buf.NpsdBM[i], tmp1);
					for (i = 192; i < FFT_HALFLEN; i++)//8000Hz
						L_tmp_NpsdBF_Bin[i] = DVTXOP_L_mpy_ls(DVTX_ECNS_vars->BF_buf.NpsdBM[i], tmp1);
					fx_SolomonVoice_FFTpwr_to_FFTband(L_tmp_NpsdBF_Band, L_tmp_NpsdBF_Bin, tx_ch_tbl_nswb, tx_ch_tbl_sh_wb, CHAN_HIGH);

					fx_SolomonVoice_Npsd_ini_calculation(NS_buf->L_Npsd_MMSE_ini, NS_buf->L_Npsd_MMSE_TMP, NS_buf->P_H1, NS_buf->L_EsqrNS, CHAN_HIGH, DVTX_WORD16_0_8, DVTX_WORD16_0_8);


					if ((BF_buf->LSTV_value_BF < DVTX_LTSV_MIN) || (VADACC_buf->LogPwrXXacc_LF_AVG < THD_VARIABLE_VADACC_LOGPWR_XXACC_LF_MIN))
					{
						tmp = 16000;// 19000;
						tmp1 = 16000;
					}
					else
					{
						tmp = 11000; // weight for L_Npsd_MMSE_ini
						tmp1 = 17000;
					}
					for (i = 0; i <= CHAN_HIGH; i++)
					{						
						NS_buf->L_Npsd_MMSE_ini[i] = DVTXOP_L_add(DVTXOP_L_mpy_ls(NS_buf->L_Npsd_MMSE_ini[i], tmp), DVTXOP_L_mpy_ls(L_tmp_NpsdBF_Band[i], tmp1));
					}

					if(VADACC_buf->LogPwrXXacc_LF_AVG < (82 << 23))
					{

						if (DVTX_ECNS_vars->Context_buf.CNTX_N_LEVEL == Noise_Extreme)
							forgetOld = DVTX_WORD16_0_1;
						else if (DVTX_ECNS_vars->Context_buf.CNTX_N_LEVEL == Noise_76dBA)
							forgetOld = DVTX_WORD16_0_2;
						else if (DVTX_ECNS_vars->Context_buf.CNTX_N_LEVEL == Noise_72dBA)
							forgetOld = DVTX_WORD16_0_5;
						else if (DVTX_ECNS_vars->Context_buf.CNTX_N_LEVEL == Noise_68dBA)
							forgetOld = DVTX_WORD16_0_8;
						else if (DVTX_ECNS_vars->Context_buf.CNTX_N_LEVEL == Noise_64dBA)
							forgetOld = DVTX_MAX_16;
						else if (DVTX_ECNS_vars->Context_buf.CNTX_N_LEVEL == Noise_60dBA)
							forgetOld = DVTX_MAX_16;
						else if (DVTX_ECNS_vars->Context_buf.CNTX_N_LEVEL == Noise_56dBA)
							forgetOld = DVTX_MAX_16;
						else if (DVTX_ECNS_vars->Context_buf.CNTX_N_LEVEL == Noise_52dBA)
							forgetOld = DVTX_MAX_16;
						else
							forgetOld = DVTX_MAX_16;

						forgetNew = DVTXOP_sub(DVTX_MAX_16, forgetOld);
						for (i = 0; i <= CHAN_HIGH; i++)
						{
							NS_buf->L_Npsd_MMSE_ini[i] = fx_SolomonVoice_recursiveAVG_ls(NS_buf->L_Npsd_MMSE_ini[i], NS_buf->L_EsqrNS[i], forgetOld, forgetNew, 0, 0);//Q23.8						
						}
					}


				}
				else // use Npsd X BM
				{ 
					fx_SolomonVoice_FFT_to_FFTpwr(L_tmp_NpsdBF_Bin, DVTX_ECNS_vars->BF_buf.X_B_NSR, FFT_HALFLEN);

					//for (i = 0; i < 16; i++)//500Hz
					//	L_tmp_NpsdBF_Bin[i] = DVTXOP_L_mpy_ls(L_tmp_NpsdBF_Bin[i], 32000);
					//for (i = 16; i < 32; i++)//1000Hz
					//	L_tmp_NpsdBF_Bin[i] = DVTXOP_L_mpy_ls(L_tmp_NpsdBF_Bin[i], 30000);
					//for (i = 32; i < 64; i++)//2000Hz
					//	L_tmp_NpsdBF_Bin[i] = DVTXOP_L_mpy_ls(L_tmp_NpsdBF_Bin[i], 28000);
					//for (i = 64; i < 128; i++)//4000Hz
					//	L_tmp_NpsdBF_Bin[i] = DVTXOP_L_mpy_ls(L_tmp_NpsdBF_Bin[i], 26000);
					//for (i = 128; i < 192; i++)//6000Hz
					//	L_tmp_NpsdBF_Bin[i] = DVTXOP_L_mpy_ls(L_tmp_NpsdBF_Bin[i], 24000);
					//for (i = 192; i < FFT_HALFLEN; i++)//8000Hz
					//	L_tmp_NpsdBF_Bin[i] = DVTXOP_L_mpy_ls(L_tmp_NpsdBF_Bin[i], 22000);
					fx_SolomonVoice_FFTpwr_to_FFTband(L_tmp_NpsdBF_Band, L_tmp_NpsdBF_Bin, tx_ch_tbl_nswb, tx_ch_tbl_sh_wb, CHAN_HIGH);
					fx_SolomonVoice_PwrBand_FixQ_BlkDeNorm(L_tmp_NpsdBF_Band, L_tmp_NpsdBF_Band, BLK_NORM, 7, CHAN_HIGH);/*30,1 -> 23,8*/

					fx_SolomonVoice_Npsd_ini_calculation(NS_buf->L_Npsd_MMSE_ini, NS_buf->L_Npsd_MMSE_TMP, NS_buf->P_H1, NS_buf->L_EsqrNS, CHAN_HIGH, DVTX_WORD16_0_8, DVTX_WORD16_0_8);

					for (i = 0; i <= CHAN_HIGH; i++)
					{
						tmp = 10000; // weight for L_Npsd_MMSE_ini
						tmp1 = DVTXOP_sub(DVTX_MAX_16, tmp);
						NS_buf->L_Npsd_MMSE_ini[i] = DVTXOP_L_add(DVTXOP_L_mpy_ls(NS_buf->L_Npsd_MMSE_ini[i], tmp), DVTXOP_L_mpy_ls(L_tmp_NpsdBF_Band[i], tmp1));
					}
				}

				
			}
			else
			{
				fx_SolomonVoice_Npsd_ini_calculation(NS_buf->L_Npsd_MMSE_ini, NS_buf->L_Npsd_MMSE_TMP, NS_buf->P_H1, NS_buf->L_EsqrNS, CHAN_HIGH, DVTX_WORD16_0_8, DVTX_WORD16_0_8);
			}
		}

		if (DVTX_ECNS_vars->Context_buf.CNTX_VOICE_ACTIVE == Noise_Confirmed)
		{

			if (DVTX_ECNS_vars->Context_buf.CNTX_N_LEVEL == Noise_Extreme)
				forgetOld = DVTX_WORD16_0_1;
			else if (DVTX_ECNS_vars->Context_buf.CNTX_N_LEVEL == Noise_76dBA)
				forgetOld = DVTX_WORD16_0_2;
			else if (DVTX_ECNS_vars->Context_buf.CNTX_N_LEVEL == Noise_72dBA)
				forgetOld = DVTX_WORD16_0_5;
			else if (DVTX_ECNS_vars->Context_buf.CNTX_N_LEVEL == Noise_68dBA)
				forgetOld = DVTX_WORD16_0_8;
			else if (DVTX_ECNS_vars->Context_buf.CNTX_N_LEVEL == Noise_64dBA)
				forgetOld = DVTX_MAX_16;
			else if (DVTX_ECNS_vars->Context_buf.CNTX_N_LEVEL == Noise_60dBA)
				forgetOld = DVTX_MAX_16;
			else if (DVTX_ECNS_vars->Context_buf.CNTX_N_LEVEL == Noise_56dBA)
				forgetOld = DVTX_MAX_16;
			else if (DVTX_ECNS_vars->Context_buf.CNTX_N_LEVEL == Noise_52dBA)
				forgetOld = DVTX_MAX_16;
			else
				forgetOld = DVTX_MAX_16;
						
			forgetNew = DVTXOP_sub(DVTX_MAX_16, forgetOld);
			for (i = 0; i <= CHAN_HIGH; i++)
			{
				NS_buf->L_Npsd_MMSE_ini[i] = fx_SolomonVoice_recursiveAVG_ls(NS_buf->L_Npsd_MMSE_ini[i], NS_buf->L_EsqrNS[i], forgetOld, forgetNew, 0, 0);//Q23.8						
			}
		}
	}


	/* SolomonVoice_SubBlocks #26:
	Global SNR estimation
	//global SNR matrix, prev 4 frames
	local SNR  : L_SNR_by_Nmmse_ini_cepsmooth, Q16.15
	global SNR : L_SNR_by_Nmmse_global, Q16.15
	*/
	if (PARA_FLAG_FIRST_FRM == DVTX_TRUE)
	{
		// global SNR, averaged SNR
		for (i = 0; i <= CHAN_HIGH; i++)
		{
			NS_buf->L_SNRMTX[i][0] = NS_buf->L_SNR_by_Nmmse_ini_cepsmooth[i];
			NS_buf->L_SNRMTX[i][1] = NS_buf->L_SNR_by_Nmmse_ini_cepsmooth[i];
			NS_buf->L_SNRMTX[i][2] = NS_buf->L_SNR_by_Nmmse_ini_cepsmooth[i];
			NS_buf->L_SNRMTX[i][3] = NS_buf->L_SNR_by_Nmmse_ini_cepsmooth[i];
		}
		NS_buf->INDEX_SNRMTX = 0;
	}
	else
	{
		NS_buf->INDEX_SNRMTX++;
		if (NS_buf->INDEX_SNRMTX >= 4)
			NS_buf->INDEX_SNRMTX = 0;
		for (i = 0; i <= CHAN_HIGH; i++)
			NS_buf->L_SNRMTX[i][NS_buf->INDEX_SNRMTX] = NS_buf->L_SNR_by_Nmmse_ini_cepsmooth[i];
	}

	// global SNR calculation
	fx_SolomonVoice_global_SNR_averaging(NS_buf->L_tmpvec, NS_buf->L_SNRMTX, CHAN_HIGH);
	
	Fn_vector_smoothing_over_3_rectangularwin_length(NS_buf->L_SNR_by_Nmmse_global, NS_buf->L_tmpvec, NUM_CHAN, NUM_CHAN);


	/* SolomonVoice_SubBlocks #25:
	invSNR = (15 - min(max(sum(10*log10(SNR_ini_CEPavg))/DEF_NS.Nchn, 0), 15))/3, 0 ~ 5 to comensate PARA_FixedXi[i][1], local SNR
	*/
	invSNR = fx_SolomonVoice_invSNR_calculation(NS_buf->L_SNR_by_Nmmse_ini_cepsmooth, DIVID_BY_MULT_NUM_CH, CHAN_HIGH);


	/* SolomonVoice_SubBlocks #27:
	SPP calculation from the lookup table // low band SPP smoothing
	p1_local  : P_H1_exp2_Q15
	p1_global : P_H1_exp5_Q15
	refer to test_SPP_fixed_xi15.m file for lookup table modification
	Q0.15
	MMSE-based initial Npsd estimation
	L_SNR_by_Nmmse_ini_cepsmooth_fix used as SNR , Q16.15
	a priori SNR is from the tune para, PARA_FixedXi[i][0], 0~15[dB]
	L_Npsd_MMSE_TMP = Q23.8
	L_Npsd_MMSE_ini = Q23.8
	*/
	//// p1_GbyL calculation	
	//p1_local
	if ((channel == CH_INNER) && (DVTX_ECNS_vars->Mix_buf.State_Wind == 1))
		fx_SolomonVoice_SNR_to_PH1_lookuptable(NS_buf->S_tmpvec, NS_buf->L_SNR_by_Nmmse_ini_cepsmooth, NS_param->PARA_FixedXi, 2, 2, 0, invSNR, CHAN_HIGH);
	else
		fx_SolomonVoice_SNR_to_PH1_lookuptable(NS_buf->S_tmpvec, NS_buf->L_SNR_by_Nmmse_ini_cepsmooth, NS_param->PARA_FixedXi, 1, 2, 0, invSNR, CHAN_HIGH);

	//p1_global
	fx_SolomonVoice_SNR_to_PH1_lookuptable(NS_buf->P_H1_GbyL, NS_buf->L_SNR_by_Nmmse_global, NS_param->PARA_FixedXi, 2, 5, 0, invSNR, CHAN_HIGH);;

	// Add use Acc information
	if (DVTX_ECNS_vars->Context_buf.CNTX_VOICE_ACTIVE == Noise_Confirmed)
	{
		if (DVTX_ECNS_vars->Context_buf.CNTX_N_LEVEL == Noise_Extreme)
			MaxSPP =  2000;
		else if (DVTX_ECNS_vars->Context_buf.CNTX_N_LEVEL == Noise_76dBA)
			MaxSPP =  6000;
		else if (DVTX_ECNS_vars->Context_buf.CNTX_N_LEVEL == Noise_72dBA)
			MaxSPP = 10000;
		else if (DVTX_ECNS_vars->Context_buf.CNTX_N_LEVEL == Noise_68dBA)
			MaxSPP = 14000;
		else if (DVTX_ECNS_vars->Context_buf.CNTX_N_LEVEL == Noise_64dBA)
			MaxSPP = 18000;
		else if (DVTX_ECNS_vars->Context_buf.CNTX_N_LEVEL == Noise_60dBA)
			MaxSPP = 22000;
		else if (DVTX_ECNS_vars->Context_buf.CNTX_N_LEVEL == Noise_56dBA)
			MaxSPP = 26000;
		else if (DVTX_ECNS_vars->Context_buf.CNTX_N_LEVEL == Noise_52dBA)
			MaxSPP = 30000;
		else
			MaxSPP = DVTX_MAX_16;

		for (i = 0; i <= CHAN_HIGH; i++)
		{
			NS_buf->S_tmpvec[i] = DVTX_MIN(NS_buf->S_tmpvec[i], MaxSPP);//min = 2^15*(1/128) max = 2^15*(8)		
			NS_buf->P_H1_GbyL[i] = DVTX_MIN(NS_buf->P_H1_GbyL[i], MaxSPP);//min = 2^15*(1/128) max = 2^15*(8)		
		}		
	}

	// p1_GbyL
	for (i = 0; i <= CHAN_HIGH; i++)
	{
		NS_buf->P_H1_GbyL[i] = DVTXOP_mult(NS_buf->P_H1_GbyL[i], NS_buf->S_tmpvec[i]);
		//NS_buf->P_H1_GbyL[i] = DVTX_MAX(NS_buf->P_H1_GbyL[i], 16384);
	}
	//low band P1 averaging
	//for (i = 4; i >= 0; i--) {
	//	tmp = DVTXOP_mult(NS_buf->P_H1_GbyL[i + 2], 9830); //*0.3
	//	tmp1 = DVTXOP_mult(NS_buf->P_H1_GbyL[i + 1], 9830);//*0.3
	//	tmp2 = DVTXOP_mult(NS_buf->P_H1_GbyL[i], 13107);//*0.4
	//	NS_buf->P_H1_GbyL[i] = DVTXOP_add(DVTXOP_add(tmp, tmp1), tmp2);
	//}

	/* SolomonVoice_SubBlocks #28:
	second Npsd estimation
	L_Npsd
	Q15.16
	*/
	if (NBBTmode == 1)
	{
		if (L_SNR_ini_avg_dB < 1500)
		{
			fx_SolomonVoice_Npsd_2nd_estimation_1mic(NS_buf->L_Npsd, NS_buf->L_EsqrNS_q30, NS_buf->P_H1_GbyL, NS_param->PARA_MIN_NOISE_PWR, BLK_NORM, 15, CHAN_HIGH);
		}
	}
	else
	{
		if ((FLAG_WB_OuterECNSOnly == 1))
		{
			if (L_SNR_ini_avg_dB < 1000)
			{
				fx_SolomonVoice_Npsd_2nd_estimation_1mic(NS_buf->L_Npsd, NS_buf->L_EsqrNS_q30, NS_buf->P_H1_GbyL, NS_param->PARA_MIN_NOISE_PWR, BLK_NORM, 15, CHAN_HIGH);
			}
		}
		else
		{
			//if (VADACC_buf->VADACCframe == 0 || FRAME_buf->STATE_Voice_Active == 0)
			//if( (DVTX_ECNS_vars->Context_buf.CNTX_VOICE_ACTIVE < Soft5step_2_Voice))
			FlagEXE = 0;
			if (FRAME_buf->STATE_ACC_Effective == 1)
			{
				if (VADACC_buf->VADACCframe_Fast == 0)
					FlagEXE = 1;
			}
			else
			{
				if (DVTX_ECNS_vars->Context_buf.CNTX_VOICE_ACTIVE < Soft5step_2_Voice)
				//if ((BF_buf->LSTV_value_BF < DVTX_LTSV_03) || (VADACC_buf->LogPwrXXacc_LF_AVG < (82 << 23)))//THD_VARIABLE_VADACC_LOGPWR_XXACC_LF_MIN))
					FlagEXE = 1;
			}
			if(FlagEXE)
			{
				if ((channel == CH_INNER) && (DVTX_ECNS_vars->Mix_buf.State_Wind == 1))
					fx_SolomonVoice_Npsd_2nd_estimation(NS_buf->L_Npsd, NS_buf->L_EsqrNS_q30, NS_buf->P_H1_GbyL, NS_param->PARA_MIN_NOISE_PWR, BLK_NORM, 15, CHAN_HIGH, DVTX_WORD16_0_1);
				else
					fx_SolomonVoice_Npsd_2nd_estimation(NS_buf->L_Npsd, NS_buf->L_EsqrNS_q30, NS_buf->P_H1_GbyL, NS_param->PARA_MIN_NOISE_PWR, BLK_NORM, 15, CHAN_HIGH, DVTX_WORD16_0_9);
			}			
		}		
	}

	/* SolomonVoice_SubBlocks #29:
	additional SPP calculation // averaging // smoothing
	loop up table : P_H1_exp1_Q15
	Q15.16
	*/
	if ((channel == CH_INNER) && (DVTX_ECNS_vars->Mix_buf.State_Wind == 1))
		fx_SolomonVoice_2nd_PH1_estimation(NS_buf->S_tmpvec, NS_buf->L_EsqrNS_q30, NS_buf->L_Npsd, 15, 1, BLK_NORM, CHAN_HIGH);
	else
		fx_SolomonVoice_2nd_PH1_estimation(NS_buf->S_tmpvec, NS_buf->L_EsqrNS_q30, NS_buf->L_Npsd, NS_param->PARA_xi_for_SPP_Table, 1, BLK_NORM, CHAN_HIGH);

	//spp frequency averaging
#ifndef KHW_OPTI_20191216_HIFI
	for (i = 1; i <= CHAN_HIGH - 1; i++)
	{
		//tmp = DVTXOP_mult(NS_buf->S_tmpvec[i + 1], 10922); //1/3 q15
		//tmp1 = DVTXOP_mult(NS_buf->S_tmpvec[i], 10923);
		//tmp2 = DVTXOP_mult(NS_buf->S_tmpvec[i - 1], 10922);
		//NS_buf->P_H1[i] = DVTXOP_add(DVTXOP_add(tmp, tmp1), tmp2);
		NS_buf->P_H1[i] = NS_buf->S_tmpvec[i];
	}
#else
	__vec_memcpy(&NS_buf->P_H1[1],&NS_buf->S_tmpvec[1],((CHAN_HIGH - 1)<<1) );
//	__vec_memcpy(NS_buf->P_H1,NS_buf->S_tmpvec,(CHAN_HIGH<<1) );
#endif

	NS_buf->P_H1[0] = NS_buf->S_tmpvec[0];
	NS_buf->P_H1[CHAN_HIGH] = NS_buf->S_tmpvec[CHAN_HIGH];

	// spp recurisve averaging
	if ((channel == CH_INNER) && (DVTX_ECNS_vars->Mix_buf.State_Wind == 1))
		fx_SolomonVoice_recursive_avg_SS_highcomplexity(NS_buf->spp, NS_buf->P_H1, DVTX_WORD16_0_9, DVTX_WORD16_0_1, CHAN_HIGH);
	else
	fx_SolomonVoice_recursive_avg_SS_highcomplexity(NS_buf->spp, NS_buf->P_H1, DVTX_WORD16_0_1, DVTX_WORD16_0_9, CHAN_HIGH);

	
	/* SolomonVoice_SubBlocks #30:
	gain_Npsd, gain_floor calculation
	if FlagNoiseFree : gainNpsd<1.0, gain floor >0
	else             : gainNpsd = 1.0, gain floor = 0
	Q0.15
	*/
	// noise_floor_offset and Npsd_gain calculation
	if (AEC_buf->Flag_Tx_silent_mode == 1)
	{
		//Npsd gain
		NS_buf->gain_Npsd = DVTXOP_add(DVTXOP_mult(NS_buf->gain_Npsd, DVTX_WORD16_0_9), DVTXOP_mult(NS_param->PARA_Npsd_Gain_MIN, DVTX_WORD16_0_1)); //Q15
																																													   //noise floor offset
		NS_buf->noise_floor_offset = DVTXOP_add(DVTXOP_mult(NS_buf->noise_floor_offset, DVTX_WORD16_0_9), DVTXOP_mult(NS_param->PARA_NoiseFloor_Offset_MAX, DVTX_WORD16_0_1)); //Q15
	}
	else
	{
				
		if (DVTX_ECNS_vars->Context_buf.CNTX_N_LEVEL == Noise_Extreme)
		{
			cntx_NoiseOffSet = 100;
		}
		else if (DVTX_ECNS_vars->Context_buf.CNTX_N_LEVEL == Noise_76dBA)
		{
			cntx_NoiseOffSet = 100;
		}
		else if (DVTX_ECNS_vars->Context_buf.CNTX_N_LEVEL == Noise_72dBA)
		{
			cntx_NoiseOffSet = 100;
		}
		else if (DVTX_ECNS_vars->Context_buf.CNTX_N_LEVEL == Noise_68dBA)
		{
			cntx_NoiseOffSet = 100;
		}
		else if (DVTX_ECNS_vars->Context_buf.CNTX_N_LEVEL == Noise_64dBA)
		{
			cntx_NoiseOffSet = 100;
		}
		else if (DVTX_ECNS_vars->Context_buf.CNTX_N_LEVEL == Noise_60dBA)
		{
			cntx_NoiseOffSet = 100;
		}
		else if (DVTX_ECNS_vars->Context_buf.CNTX_N_LEVEL == Noise_56dBA)
		{
			cntx_NoiseOffSet = 100;
		}
		else if (DVTX_ECNS_vars->Context_buf.CNTX_N_LEVEL == Noise_52dBA)
		{
			cntx_NoiseOffSet = 100;
		}
		else
		{
			cntx_NoiseOffSet = 50;
		}
		cntx_NpsdGain = 32767;		
		
		//Npsd gain
		NS_buf->gain_Npsd = DVTXOP_add(DVTXOP_mult(NS_buf->gain_Npsd, DVTX_WORD16_0_85), DVTXOP_mult(cntx_NpsdGain, DVTX_WORD16_0_15)); //q15																																								  //noise floor offset
		NS_buf->noise_floor_offset = DVTXOP_add(DVTXOP_mult(NS_buf->noise_floor_offset, DVTX_WORD16_0_9), DVTXOP_mult(cntx_NoiseOffSet, DVTX_WORD16_0_1)); //Q15
	}

	/* SolomonVoice_SubBlocks #31:
	DD priori SNR calculation
	first STAGE : post SNR && priori SNR
	L_SNRpost : Q16.15
	L_SNRprio : Q16.15
	*/
	//SNR min = 2^15*(1/128) SNRmax = 2^15*(128);	
if (NBBTmode == 0)
{
#ifdef __SV_USE_ANC_RESULT__
	if (ANC_buf->VAD != Rx_ON && ANC_buf->NoiseLevel == 1)
	{
		for (i = 0; i < ANC_REF_FBAND_SIZE; i++)
	{
#if 1
		if (ANC_buf->H1[i] > 20000)
			NS_buf->L_EsqrNS_q30[i] = (NS_buf->L_EsqrNS_q30[i] > ANC_buf->XXenh_band[i]) ? NS_buf->L_EsqrNS_q30[i] : ANC_buf->XXenh_band[i];
		else
#endif
			NS_buf->L_EsqrNS_q30[i] = ANC_buf->XXenh_band[i];
	}
	}
#endif
}
	fx_SolomonVoice_postSNR_estimation(NS_buf->L_SNRpost, NS_buf->L_EsqrNS_q30, NS_buf->L_Npsd, BLK_NORM, NS_buf->gain_Npsd, CHAN_HIGH);

	// first STAGE : DD apriori SNR estimation
	forgetOld = DVTX_WORD16_0_9; //31128=0.95 , 31456=0.96
	forgetNew = DVTX_WORD16_0_1;
	fx_SolomonVoice_DD_SNRprio_estimation(NS_buf->L_SNRprio, NS_buf->L_tmpvec, NS_buf->L_SNRpost, NS_buf->L_SNRpost_prv
		, NS_buf->Gmmse, forgetOld, forgetNew, 256, 4194304, CHAN_HIGH);//16.15	
	
	/* SolomonVoice_SubBlocks #32:
	a priori SNR averaging // smoothing
	*/
	fx_SolomonVoice_aprioriSNR_recursiveAVG(NS_buf->L_SNRprio_avg, NS_buf->L_SNRprio, DVTX_BAND_INDEX_4kHz, CHAN_HIGH);
	// freq smoothing
	fx_SolomonVoice_aprioriSNR_freqSmoothing(NS_buf->L_tmpvec, NS_buf->L_SNRprio_avg, CHAN_HIGH);
		

	/* SolomonVoice_SubBlocks #33:
	NS gain floor calculation // NS gain floor smoothing
	Á÷¼±ÀÇ ¹æÁ¤½Ä (x1,x2)(y1,y2)
	*/
	// noise floor offset calculation
	Lx1 = NS_param->PARA_THD_Lo_prioriSNR_for_NoiseFloor;//20675;  //10^(-2/10) q15
	Lx2 = NS_param->PARA_THD_Hi_prioriSNR_for_NoiseFloor;//327680; //10^(10/10) q15
	tmp = NS_param->PARA_slope_prioriSNR_for_NoiseFloor;// 27979; //=1/(x2-x1) = 1/(10^(10/10)-10^(-2/10))*2^18 q18

	/*
	0.02   655
	0.03   983
	0.04  1311
	0.05  1638
	0.06  1966
	0.07  2293
	0.08  2621
	0.10  3277
	0.12  3932	
	0.14  4587
	0.16  5243
	0.18  5898
	0.20  6553
	*/
	if (channel == CH_OUTER_1)
	{
		if ((FRAME_buf->STATE_ACC_Effective == 0) || (DVTX_ECNS_vars->AEC_Outer_buf_1.Flag_Tx_silent_mode == 1))
		{
			NoiseFloorOffset_0_250Hz_low = 1311; //0.8
			NoiseFloorOffset_0_250Hz_high = 1966; //0.10
			NoiseFloorOffset_250_4000Hz_low = 1311;
			NoiseFloorOffset_250_4000Hz_high = 1966;
			NoiseFloorOffset_4000_8000Hz_low = 1311;
			NoiseFloorOffset_4000_8000Hz_high = 1966;
						
		}
		else
		{
			if (VADACC_buf->VADACCframe_Fast == 0)
			{
				NoiseFloorOffset_0_250Hz_low = 655; //0.8
				NoiseFloorOffset_0_250Hz_high = 1311; //0.10
				NoiseFloorOffset_250_4000Hz_low = 655;
				NoiseFloorOffset_250_4000Hz_high = 1311;
				NoiseFloorOffset_4000_8000Hz_low = 655;
				NoiseFloorOffset_4000_8000Hz_high = 1311;
			}
			else
			{
				NoiseFloorOffset_0_250Hz_low = 655; //0.8
				NoiseFloorOffset_0_250Hz_high = 1311; //0.10
				NoiseFloorOffset_250_4000Hz_low = 655;
				NoiseFloorOffset_250_4000Hz_high = 1311;
				NoiseFloorOffset_4000_8000Hz_low = 655;
				NoiseFloorOffset_4000_8000Hz_high = 1311;
			}
		}
	}
	else
	{
		NoiseFloorOffset_0_250Hz_low  = NS_param->PARA_NoiseFloorOffset_0_250Hz_low;
		NoiseFloorOffset_0_250Hz_high = NS_param->PARA_NoiseFloorOffset_0_250Hz_high;
		NoiseFloorOffset_250_4000Hz_low  = NS_param->PARA_NoiseFloorOffset_250_4000Hz_low;
		NoiseFloorOffset_250_4000Hz_high = NS_param->PARA_NoiseFloorOffset_250_4000Hz_high;
		NoiseFloorOffset_4000_8000Hz_low  = NS_param->PARA_NoiseFloorOffset_4000_8000Hz_low;
		NoiseFloorOffset_4000_8000Hz_high = NS_param->PARA_NoiseFloorOffset_4000_8000Hz_low;
	}

	// 0 ~250Hz
	y1 = DVTXOP_add(NS_buf->noise_floor_offset, NoiseFloorOffset_0_250Hz_low); //+0.2   q15
	y2 = DVTXOP_add(NS_buf->noise_floor_offset, NoiseFloorOffset_0_250Hz_high); //+0.25  q15;	
	fx_SolomonVoice_noisefloor_cal(NS_buf->L_tmpvec1, NS_buf->L_tmpvec, y1, y2, tmp, Lx1, 0, 4);
	// 250~4000Hz
	y1 = (int)DVTXOP_add(NS_buf->noise_floor_offset, NoiseFloorOffset_250_4000Hz_low); //+0.12   q15
	y2 = (int)DVTXOP_add(NS_buf->noise_floor_offset, NoiseFloorOffset_250_4000Hz_high); //+0.3  q15;
	fx_SolomonVoice_noisefloor_cal(NS_buf->L_tmpvec1, NS_buf->L_tmpvec, y1, y2, tmp, Lx1, 5, DVTX_BAND_INDEX_4kHz);
	// 4000~8000Hz
	y1 = (int)DVTXOP_add(NS_buf->noise_floor_offset, NoiseFloorOffset_4000_8000Hz_low); //+0.04   q15
	y2 = (int)DVTXOP_add(NS_buf->noise_floor_offset, NoiseFloorOffset_4000_8000Hz_high); //+0.3  q15;
	fx_SolomonVoice_noisefloor_cal(NS_buf->L_tmpvec1, NS_buf->L_tmpvec, y1, y2, tmp, Lx1, DVTX_BAND_INDEX_4kHz + 1, CHAN_HIGH);

	// NS gain floor smoothing
	fx_SolomonVoice_noisefloor_smoothing(NS_buf->S_noise_floor, NS_buf->L_tmpvec1, CHAN_HIGH);


	/* SolomonVoice_SubBlocks #34:
	Wiener gain calculation = 1/(1+SNRprio)
	()^a, a=0.25, 0.5, 0.75 select by loopup table
	*/
	L_GwienerAvg = fx_SolomonVoice_Wiener_gainvector_Q31(NS_buf->L_tmpvec, NS_buf->L_SNRprio, CHAN_HIGH, DIVID_BY_MULT_NUM_CH);//Gain=Q0.31, GainAVG=Q16.15
	//fx_SolomonVoice_WienerQ31_to_GainQ15(NS_buf->Gmmse, NS_buf->L_tmpvec, 1, CHAN_HIGH);
	if ((channel == CH_INNER) && (DVTX_ECNS_vars->Mix_buf.State_Wind == 1))
		fx_SolomonVoice_WienerQ31_to_GainQ15_Gmin(NS_buf->Gmmse, NS_buf->L_tmpvec, 3, CHAN_HIGH, Gmin);
	else
		fx_SolomonVoice_WienerQ31_to_GainQ15_Gmin(NS_buf->Gmmse, NS_buf->L_tmpvec, 1, CHAN_HIGH, Gmin);

	/* SolomonVoice_SubBlocks #35:
	spp_ns calculation : spp for NS becomes average between p1_GbyL(hard spp) and spp(soft spp)
	SPP = avg(P_H1_GbyL, spp), 8:2(~4kHz), 9:1(4~8kHz)
	*/
	if ((channel == CH_INNER) && (DVTX_ECNS_vars->Mix_buf.State_Wind == 1))
	{
		for (i = 0; i <= CHAN_HIGH; i++)
			NS_buf->S_spp_ns[i] = DVTXOP_add(DVTXOP_mult(DVTX_WORD16_0_9, NS_buf->P_H1_GbyL[i]), DVTXOP_mult(DVTX_WORD16_0_1, NS_buf->spp[i])); //0.2
	}
	else
	{
	for (i = 0; i <= DVTX_BAND_INDEX_4kHz; i++)
		NS_buf->S_spp_ns[i] = DVTXOP_add(DVTXOP_mult(DVTX_WORD16_0_8, NS_buf->P_H1_GbyL[i]), DVTXOP_mult(DVTX_WORD16_0_2, NS_buf->spp[i])); //0.2
	for (i = DVTX_BAND_INDEX_4kHz + 1; i <= CHAN_HIGH; i++)
		NS_buf->S_spp_ns[i] = DVTXOP_add(DVTXOP_mult(DVTX_WORD16_0_9, NS_buf->P_H1_GbyL[i]), DVTXOP_mult(DVTX_WORD16_0_1, NS_buf->spp[i])); //0.1
	}

if (NBBTmode == 0)
{
#ifdef __ANC_XCORR_BASED_VAD_IN_PF__
	if (ANC_buf->VAD == NOISE)
	{
		for (i = 0; i <= CHAN_HIGH; i++) NS_buf->S_spp_ns[i] = 0;
	}
#endif
}
	/* SolomonVoice_SubBlocks #36:
	gain calculation : G=G*spp + noisefloor*(1-spp)
	gain averaging
	gain applying
	*/
	for (i = 0; i <= CHAN_HIGH; i++)
	{
		tmp1 = DVTXOP_mult(NS_buf->Gmmse[i], NS_buf->S_spp_ns[i]); //GH1*spp_ns
		tmp2 = DVTXOP_mult(NS_buf->S_noise_floor[i], DVTXOP_sub(DVTX_MAX_16, NS_buf->S_spp_ns[i])); //noise floor * (1-spp_ns)
		NS_buf->S_tmpvec[i] = DVTXOP_add(tmp1, tmp2);
	}
	// gain averaging	
#ifndef fx_SolomonVoice_NS_1_OPT_DSP
	for (i = 1; i <= CHAN_HIGH - 1; i++)
	{
		tmp = DVTXOP_shr(NS_buf->S_tmpvec[i], 1);
		tmp1 = DVTXOP_shr(NS_buf->S_tmpvec[i - 1], 2);
		tmp2 = DVTXOP_shr(NS_buf->S_tmpvec[i + 1], 2);

		tmp3 = DVTXOP_add(DVTXOP_add(tmp, tmp1), tmp2);
		if (i < 8) {
			NS_buf->S_Gns_final[i] = DVTXOP_add(DVTXOP_mult(NS_buf->S_Gns_final[i], DVTX_WORD16_0_5), DVTXOP_mult(tmp3, DVTX_WORD16_0_5));
		}
		else {
			NS_buf->S_Gns_final[i] = DVTXOP_add(DVTXOP_mult(NS_buf->S_Gns_final[i], DVTX_WORD16_0_1), DVTXOP_mult(tmp3, DVTX_WORD16_0_9));
		}
	}
#else
	fx_SolomonVoice_NS_average_vector(NS_buf->S_tmpvec,NS_buf->S_Gns_final,CHAN_HIGH);
#endif
	//NS_buf->S_Gns_final[1] = NS_buf->S_tmpvec[1];
	NS_buf->S_Gns_final[0] = DVTXOP_add(DVTXOP_mult(NS_buf->S_Gns_final[0], DVTX_WORD16_0_7), DVTXOP_mult(NS_buf->S_tmpvec[0], DVTX_WORD16_0_3));
	NS_buf->S_Gns_final[CHAN_HIGH] = NS_buf->S_tmpvec[CHAN_HIGH];
		

	// gain : band to bin
	fx_SolomonVoice_Gain_band_to_bin(RES_buf->GmmseNFFT, NS_buf->S_Gns_final, tx_ch_tbl_nswb, NS_param->PARA_ns_level, CHAN_HIGH);

	// first STAGE : NS Gain applying
	RES_buf->GmmseNFFT[0] = DVTX_MAX_16;



#if 0//#ifdef __USE_HIGH_RESOLUTION_NS__
	/* POST-POST-POST NS TO ENHANCE NS RESOLUTION : USING MORE BANDS*/
	if ((NBBTmode == 0) && (channel == CH_OUTER_1) && (FRAME_buf->STATE_ACC_Effective == 1))
	{
		// NOISE PSD
		fx_SolomonVoice_FFTpwr_to_FFTband(NS_buf->L_tmpvec, L_tmp_NpsdBF_Bin, tx_ch_tbl_79BAND, tx_ch_tbl_sh_79BAND, DVTX_CHAN_HIGH_79BAND);
		fx_SolomonVoice_PwrBand_FixQ_BlkDeNorm(NS_buf->L_tmpvec, NS_buf->L_tmpvec, BLK_NORM, 7, DVTX_CHAN_HIGH_79BAND);/*30,1 -> 23,8*/
		
		if (FRAME_buf->STATE_Voice_Active == 0)
		{
			for (i = 0; i <= DVTX_CHAN_HIGH_79BAND; i++) {
				FRAME_buf->NN_79BAND[i] = Fx_recursive_avg(FRAME_buf->NN_79BAND[i], NS_buf->L_tmpvec[i], DVTX_WORD16_0_9);
			}
		}
		
		// SPEECH PSD
		fx_SolomonVoice_FFT_to_FFTpwr(L_tmp_NpsdBF_Bin, data_buffer, FFT_HALFLEN);
		fx_SolomonVoice_FFTpwr_to_FFTband(NS_buf->L_tmpvec, L_tmp_NpsdBF_Bin, tx_ch_tbl_79BAND, tx_ch_tbl_sh_79BAND, DVTX_CHAN_HIGH_79BAND);		
		fx_SolomonVoice_PwrBand_FixQ_BlkDeNorm(FRAME_buf->XX_79BAND, NS_buf->L_tmpvec, BLK_NORM, 7, DVTX_CHAN_HIGH_79BAND);/*30,1 -> 23,8*/
		/*for (i = 0; i <= DVTX_CHAN_HIGH_79BAND; i++) {
			FRAME_buf->XX_79BAND[i] = Fx_recursive_avg(FRAME_buf->XX_79BAND[i], NS_buf->L_tmpvec[i], DVTX_WORD16_0_2);
		}*/
		
		//POST SNR		
		for (i = 0; i <= DVTX_CHAN_HIGH_79BAND; i++) {
			FRAME_buf->SNRpost_79BAND[i] = divide(FRAME_buf->XX_79BAND[i], (BLK_NORM * 2 + 1), FRAME_buf->NN_79BAND[i], (BLK_NORM * 2 + 1), 15);//Q15		
		}
		
		// PRIORI SNR
		forgetOld = DVTX_WORD16_0_9; //31128=0.95 , 31456=0.96
		forgetNew = DVTX_WORD16_0_1;
		fx_SolomonVoice_DD_SNRprio_estimation(FRAME_buf->SNRprio_79BAND, NS_buf->L_tmpvec, FRAME_buf->SNRpost_79BAND, FRAME_buf->SNRpostPrev_79BAND
			, FRAME_buf->Gain_79BAND, forgetOld, forgetNew, 256, 4194304, DVTX_CHAN_HIGH_79BAND);//16.15	

		// GAIN
		Ltmp1 = fx_SolomonVoice_Wiener_gainvector_Q31(NS_buf->L_tmpvec, FRAME_buf->SNRprio_79BAND, DVTX_CHAN_HIGH_79BAND, DIVID_BY_MULT_NUM_CH);//Gain=Q0.31, GainAVG=Q16.15

		fx_SolomonVoice_WienerQ31_to_GainQ15_Gmin(FRAME_buf->Gain_79BAND, NS_buf->L_tmpvec, 3, DVTX_CHAN_HIGH_79BAND, 0);

		// noise floor
		tmp1 = 0;
		tmp3 = 0;
		if (DVTX_ECNS_vars->Context_buf.CNTX_N_LEVEL == Noise_Extreme) {
			tmp = 14000 - tmp3; tmp2 = 18000 - tmp3;		}
		else if (DVTX_ECNS_vars->Context_buf.CNTX_N_LEVEL == Noise_76dBA) {
			tmp = 16000 - tmp3; tmp2 = 20000 - tmp3;		}
		else if (DVTX_ECNS_vars->Context_buf.CNTX_N_LEVEL == Noise_72dBA) {
			tmp = 18000 - tmp3; tmp2 = 22000 - tmp3;		}
		else if (DVTX_ECNS_vars->Context_buf.CNTX_N_LEVEL == Noise_68dBA) {
			tmp = 20000 - tmp1; tmp2 = 24000 - tmp1;		}
		else if (DVTX_ECNS_vars->Context_buf.CNTX_N_LEVEL == Noise_64dBA) {
			tmp = 22000 - tmp1; tmp2 = 26000 - tmp1;		}
		else if (DVTX_ECNS_vars->Context_buf.CNTX_N_LEVEL == Noise_60dBA) {
			tmp = 24000 - tmp1; tmp2 = 26000 - tmp1;		}
		else if (DVTX_ECNS_vars->Context_buf.CNTX_N_LEVEL == Noise_56dBA) {
			tmp = 26000 - tmp1; tmp2 = 26000 - tmp1;		}
		else if (DVTX_ECNS_vars->Context_buf.CNTX_N_LEVEL == Noise_52dBA) {
			tmp = 26000 - tmp1; tmp2 = 26000 - tmp1;		}
		else {
			tmp = 26000 - tmp1; tmp2 = 26000 - tmp1;		}

		tmp1 = 32767 - tmp;
		tmp3 = 32767 - tmp2;
		for (i = 0; i < 54; i++)
			FRAME_buf->Gain_79BAND[i] = DVTXOP_mult(tmp1, FRAME_buf->Gain_79BAND[i]) + tmp - 32; // 32 is biae to prevent satuation
		for (i = 54; i <= DVTX_CHAN_HIGH_79BAND; i++)
			FRAME_buf->Gain_79BAND[i] = DVTXOP_mult(tmp3, FRAME_buf->Gain_79BAND[i]) + tmp2 - 32; // 32 is biae to prevent satuation

		fx_SolomonVoice_Gain_band_to_bin(NS_buf->S_tmpvec, FRAME_buf->Gain_79BAND, tx_ch_tbl_79BAND, 0, DVTX_CHAN_HIGH_79BAND);
		
		for (i = 0; i < DVTX_M_FFT_HALFLEN_WB; i++)
			RES_buf->GmmseNFFT[i] = DVTXOP_mult_r(RES_buf->GmmseNFFT[i], NS_buf->S_tmpvec[i]);


		// DEBUGING
#if(FLAG_SELECT_C_DSP == 1)
#if(Debug_File_Write_C == 1)
		if (channel == FLAG_ECNS_WRITE_SELECTION)
		{
			for (i = 0; i <= DVTX_CHAN_HIGH_79BAND; i++)
			{
				fprintf(fp_deg_2micBF[22], "%ld %ld %ld %ld %d\n",
					//DVTXOP_L_shl(FRAME_buf->XX_79BAND[i], (short)8 - (2 * BLK_NORM + 1)),
					//DVTXOP_L_shl(FRAME_buf->NN_79BAND[i], (short)8 - (2 * BLK_NORM + 1)),					
					FRAME_buf->XX_79BAND[i],
					FRAME_buf->NN_79BAND[i],
					FRAME_buf->SNRpost_79BAND[i],
					FRAME_buf->SNRprio_79BAND[i],
					FRAME_buf->Gain_79BAND[i]

				);
			}
		}
#endif
#endif
	}

#endif

	// gain
	fx_SolomonVoice_FFTbin_gain_applying(data_buffer, RES_buf->GmmseNFFT, FFT_HALFLEN);
	//tmp = 1;
	//for (i = 0; i < FFT_HALFLEN; i++)
	//{
	//	if ((DVTXOP_abs_s(data_buffer[2 * i]) > tmp) || (DVTXOP_abs_s(data_buffer[2 * i + 1]) > tmp))
	//	{
	//		//forgetNew = data_buffer[2 * i];
	//		//forgetOld = data_buffer[2 * i+1];
	//		tmp1 = DVTXOP_mult_r(data_buffer[2 * i], RES_buf->GmmseNFFT[i]);
	//		tmp2 = DVTXOP_mult_r(data_buffer[2 * i+1], RES_buf->GmmseNFFT[i]);
	//		
	//		//if((DVTXOP_abs_s(tmp1) > tmp) || (DVTXOP_abs_s(tmp2) > tmp))
	//		{
	//			data_buffer[2 * i] = tmp1;// DVTXOP_mult_r(data_buffer[2 * i], RES_buf->GmmseNFFT[i]);
	//			data_buffer[2 * i + 1] = tmp2;// DVTXOP_mult_r(data_buffer[2 * i + 1], RES_buf->GmmseNFFT[i]);
	//		}
	//	}
	//}
		



	//if (NBBTmode == 0) 
	//{
	//	if (Frame_param->PARA_reserved_11 == 1) // post inner LPF on/off flag
	//	{
	//		if (channel == CH_INNER) // for inner mic 8kHz
	//		{
	//			for (i = 80; i < FFT_HALFLEN; i++)
	//			{
	//				data_buffer[2 * i] = DVTXOP_mult_r(data_buffer[2 * i], 4);
	//				data_buffer[2 * i + 1] = DVTXOP_mult_r(data_buffer[2 * i + 1], 4);
	//			}
	//		}
	//	}
	//}

	data_buffer[0] = 0; // 0 Hz
	data_buffer[1] = 0; // pi/2 Hz
	data_buffer[2] = 0; // 62.5 Hz
	data_buffer[3] = 0; // 62.5 Hz



#if(FLAG_SELECT_C_DSP == 1)
#if(Debug_File_Write_C == 1)
	if (channel == FLAG_ECNS_WRITE_SELECTION)
	{

		fprintf(fp_debug_ns_para, "%ld %d %ld %ld %ld %d %d %d %d\n", FRAME_buf->Pwr_100Hz_to_1kHz_Outer, FLAGsoft_SNR_ini, L_SNR_ini_avg_dB, FRAME_buf->Pwr_1kHz_to_4kHz_Outer, NS_param->PARA_THD_Pwr_Lo_1k_4k, AEC_buf->Flag_Tx_silent_mode, invSNR,
			NS_buf->gain_Npsd, NS_buf->noise_floor_offset
		);

		for (i = 0; i <= CHAN_HIGH; i++)
		{
			fprintf(fp_debug_ns_vec1, "%d %ld %d %ld %ld %d %ld %ld %d %ld %d %ld %ld %d %d\n",
				NS_buf->P_H1[i],
				0,// NS_buf->L_Npsd_for_minGain[i],
				0,//NS_buf->REG_Gain_MIN[i],
				NS_buf->L_SNR_by_Nmmse_ini_cepsmooth_fix[i],
				NS_buf->L_SNR_by_Nmmse_ini_cepsmooth[i],
				NS_buf->L_SNR_by_Nmmse_ini_avg[i],
				NS_buf->L_SNR_by_Nmmse_ini[i],
				NS_buf->L_Npsd_MMSE_ini[i],
				NS_buf->P_H1_GbyL[i],
				NS_buf->L_Npsd[i],
				NS_buf->spp[i],
				NS_buf->L_SNRpost[i],
				NS_buf->L_SNRprio[i],
				NS_buf->S_noise_floor[i],
				NS_buf->S_spp_ns[i]
			);
		}

		for (i = 0; i < FFT_HALFLEN; i++)
		{
			fprintf(fp_debug_ns_vec4, "%d\n", RES_buf->GmmseNFFT[i]);
		}

		for (i = 0; i < DVTX_Nfft_ceps; i++)
		{
			fprintf(fp_debug_ns_vec5, "%d %d\n", NS_buf->beta_ceps[i], NS_buf->SNR_ini_ceps_avg[i]);

		}
	}
#endif
#endif

	// NS end

	return;

}

int FN_SOLOMONVOICEW_TX_RES_NS_NBBT(DVTX_ECNS_Cfg_t* DVTX_ECNS_vars, CHANNEL channel)
{
	short BLK_NORM, BLK_NORM_rx, BLK_NORM_rx2, BLK_NORM_Acc;
	short FFT_LEN, FFT_HALFLEN, CHAN_HIGH, NUM_CHAN, DIVID_BY_SHIFT_NUM_BIN, DIVID_BY_MULT_NUM_CH;
	short FrmDT;
	short *data_buffer;
	short *data_buffer_rx;
	short *data_buffer_rx2;

	FRAMEStatus* FRAME_buf = &DVTX_ECNS_vars->FRAME_buf;
	COMMONBUF* common_buf = &DVTX_ECNS_vars->COMMON_buf;
	ANCStatus* ANC_Inner_buf = &DVTX_ECNS_vars->ANC_Inner_buf;
	ANCStatus* ANC_Outer_buf = &DVTX_ECNS_vars->ANC_Outer_buf;
	AECStatus* AEC_buf;
	RESStatus* RES_buf;
	NSStatus* NS_buf;
	MixingStatus* Mix_buf = &DVTX_ECNS_vars->Mix_buf;

	SamsungSolomonVoiceWTxFRAMEParam* Frame_param;
	SamsungSolomonVoiceWTxAECParam* AEC_param;
	SamsungSolomonVoiceWTxRESParam* RES_param;
	SamsungSolomonVoiceWTxNSParam* NS_param;

	VADACCStatus*  VADACC_buf = &DVTX_ECNS_vars->VADACC_buf;
	BLK_NORM_Acc = FRAME_buf->fftbuffer_Acc.BLK_NORM;

	short Flag_Tx_Clipping;

	Frame_param = &DVTX_ECNS_vars->FRAME_param;

	FFT_LEN = DVTX_FFT_LEN_NB;
	FFT_HALFLEN = DVTX_FFT_HALFLEN_NB;
	CHAN_HIGH = DVTX_CHAN_HIGH_NB;
	NUM_CHAN = DVTX_NUM_CHAN_NB;
	DIVID_BY_SHIFT_NUM_BIN = DIVID_BY_SHIFT_NUM_BIN_NB;
	DIVID_BY_MULT_NUM_CH = DIVID_BY_MULT_NUM_CH_NB;

	data_buffer = FRAME_buf->fftbuf_Outer_NB.data_buffer; //data_buffer_NB;
	data_buffer_rx = FRAME_buf->fftbuf_RX_Outer_NB.data_buffer;
	//data_buffer_rx2 = FRAME_buf->fftbuf_RX2_Outer_NB.data_buffer;

	BLK_NORM = FRAME_buf->fftbuf_Outer_NB.BLK_NORM;
	BLK_NORM_rx = FRAME_buf->fftbuf_RX_Outer_NB.BLK_NORM;
	//BLK_NORM_rx2 = FRAME_buf->fftbuf_RX2_Outer_NB.BLK_NORM;

	RES_buf = &DVTX_ECNS_vars->RES_Outer_buf;
	NS_buf = &DVTX_ECNS_vars->NS_Outer_buf;
	AEC_buf = &DVTX_ECNS_vars->AEC_Outer_buf_1;

	RES_param = &DVTX_ECNS_vars->RES_Outer_param;
	AEC_param = &DVTX_ECNS_vars->AEC_Outer_param_1;
	NS_param = &DVTX_ECNS_vars->NS_Outer_param;

	FrmDT = FRAME_buf->FrmDT_Outer;

	Flag_Tx_Clipping = FRAME_buf->Flag_Tx_Clipping_Outer_1;


	/*Solomonvoice function
	calculate FFT bin power
	input  : Q15,0
	output : Q30,1
	*/
	//RES_buf->L_DDBin2 = (int *)data_buffer_rx2;
	fx_SolomonVoice_FFT_to_FFTpwr(RES_buf->L_EEBin, data_buffer, FFT_HALFLEN);
	fx_SolomonVoice_FFT_to_FFTpwr(FRAME_buf->L_EEBin_forMixing, FRAME_buf->FFTbuf_Tx_Outer_WB, FFT_HALFLEN);
	fx_SolomonVoice_FFT_to_FFTpwr(RES_buf->L_DDBin, data_buffer_rx, FFT_HALFLEN);
	//fx_SolomonVoice_FFT_to_FFTpwr(RES_buf->L_DDBin2, data_buffer_rx2, FFT_HALFLEN);


	/* SolomonVoice_SubBlocks #1:
	Rx band pwr estimation to detect ringback tone interval
	pwr band 1 : ring band
	pwr band 2 : other band
	*/
	//fx_SolomonVoice_Rx_ringbacktone_bandpwr_estimation(AEC_buf, RES_buf->L_DDBin2, FFT_HALFLEN, BLK_NORM_rx2);
	fx_SolomonVoice_Rx_ringbacktone_bandpwr_estimation(AEC_buf, RES_buf->L_DDBin, FFT_HALFLEN, 0);


	/* SolomonVoice_SubBlocks #4:
	FFTbin to Band power
	input  : Q30,1, Nfft/2+1
	output : Q30,1, Nband
	*/
#ifndef  Merge_FFTband_calc
	fx_SolomonVoice_FFTpwr_to_FFTband(NS_buf->L_EsqrNS_q30, RES_buf->L_EEBin, tx_ch_tbl_nswb, tx_ch_tbl_sh_wb, CHAN_HIGH);
	fx_SolomonVoice_FFTpwr_to_FFTband(NS_buf->L_Dsqr_q30, RES_buf->L_DDBin, tx_ch_tbl_nswb, tx_ch_tbl_sh_wb, CHAN_HIGH);
#else
	fx_SolomonVoice_FFTpwr_to_FFTband_merge(NS_buf->L_EsqrNS_q30, RES_buf->L_EEBin, NS_buf->L_Dsqr_q30, RES_buf->L_DDBin, tx_ch_tbl_nswb, tx_ch_tbl_sh_wb, CHAN_HIGH);
#endif


	// Band Q-format change : 30,1 -> 23,8
	fx_SolomonVoice_PwrBand_FixQ_BlkDeNorm(NS_buf->L_EsqrNS, NS_buf->L_EsqrNS_q30, BLK_NORM, 7, CHAN_HIGH);/*30,1 -> 23,8*/

	// Bin Q-format change : 30,1 -> 23,8
	fx_SolomonVoice_PwrBin_FixQ_BlkDeNorm(RES_buf->L_EEBin, RES_buf->L_EEBin, BLK_NORM, 7, 1, FFT_HALFLEN);/*30,1 -> 23,8*/
	fx_SolomonVoice_PwrBin_FixQ_BlkDeNorm(RES_buf->L_DDBin, RES_buf->L_DDBin, BLK_NORM_rx, 7, 0, FFT_HALFLEN);/*30,1 -> 23,8*/
	//fx_SolomonVoice_PwrBin_FixQ_BlkDeNorm(RES_buf->L_DDBin2, RES_buf->L_DDBin2, BLK_NORM_rx2, 7, 0, FFT_HALFLEN);/*30,1 -> 23,8*/


	/* SolomonVoice_SubBlocks #18:
	calculate Tx. 1~4kHz Pwr --> silence interval detection
	Noise free flag update using Pwr 1kHz to 4kHz
	*/
	fx_SolomonVoice_tx_Silence_mode_detection(FRAME_buf, AEC_buf, RES_buf, NS_buf, NS_param);

	// count RxVAD on frame
	if (AEC_buf->Flag_RxVAD_AEC == 1)
	{
		RES_buf->CntFrmRxVADon++;
		RES_buf->CntFrmRxVADon = DVTX_MIN(RES_buf->CntFrmRxVADon, 30000);// prevent counter overflow			
	}

	if (RES_param->PARA_reserved_2 == 1)// flag FNLMS on off
	{
		/* SolomonVoice_SubBlocks #8:
		noise psd to limit minimum RES gain
		L_Npsd_for_minGain
		Q15.16
		spectral subtraction min gain = L_Npsd_for_minGain*alpha
		*/
		//fx_SolomonVoice_RES_minGain(&DVTX_ECNS_vars->ECNSbuff, &DVTX_ECNS_vars->AECNS, CHAN_HIGH);

		/*Solomonvoice function
		two FNLMS filters
		over estimation for high band is applied
		DD : Q23.8
		EE : Q23.8
		RR : Q23.8
		W  : Q5,10 --> 0.15 changed
		*/
		fx_SolomonVoice_FNLMS_filter(data_buffer, RES_buf, AEC_buf, NS_buf, FrmDT, DIVID_BY_SHIFT_NUM_BIN, FFT_HALFLEN, FFT_LEN, Flag_Tx_Clipping, channel, 1);
	}


	if (RES_param->PARA_reserved_3 == 1)// flag RES on off
	{
		fx_SolomonVoice_RES(common_buf, AEC_buf, RES_buf, NS_buf, AEC_param, Frame_param, RES_param, NS_param,
			data_buffer, DIVID_BY_MULT_NUM_CH, BLK_NORM, BLK_NORM_rx, CHAN_HIGH, NUM_CHAN, FFT_HALFLEN, channel);
	}


	if (NS_param->PARA_reserved_4 == 1)// flag NS on off
	{
		fx_SolomonVoice_NS(DVTX_ECNS_vars, FRAME_buf, AEC_buf, RES_buf, NS_buf, Mix_buf, Frame_param, NS_param,
			data_buffer, DIVID_BY_MULT_NUM_CH, BLK_NORM, CHAN_HIGH, NUM_CHAN, FFT_HALFLEN, channel, 1, VADACC_buf, BLK_NORM_Acc);
	}
	fn_fDRC(AEC_buf, RES_buf, NS_param, data_buffer, FFT_HALFLEN, BLK_NORM, channel);
	
	if (channel == CH_INNER)
		Frame_param->PARA_FLAG_FIRST_FRM_Inner = DVTX_FALSE;
	else
		Frame_param->PARA_FLAG_FIRST_FRM_Outer = DVTX_FALSE;

	return 0;
}

int FN_SOLOMONVOICEW_TX_RES_NS(DVTX_ECNS_Cfg_t* DVTX_ECNS_vars, CHANNEL channel)
{
	int i;
	short BLK_NORM, BLK_NORM_rx, BLK_NORM_rx2, BLK_NORM_Acc;
	short FFT_LEN, FFT_HALFLEN, CHAN_HIGH, NUM_CHAN, DIVID_BY_SHIFT_NUM_BIN, DIVID_BY_MULT_NUM_CH;
	short FrmDT;
	short *data_buffer;
	short *data_buffer_rx;
	short *data_buffer_rx2;
#if(FLAG_SELECT_C_DSP == 1)
	short *dbg_data_buffer_FNLMSin;
	short *dbg_data_buffer_FNLMSout;
	short *dbg_data_buffer_RESout;
	short *dbg_data_buffer_NSout;
#endif
	
	FRAMEStatus* FRAME_buf = &DVTX_ECNS_vars->FRAME_buf;
	COMMONBUF* common_buf = &DVTX_ECNS_vars->COMMON_buf;
	ANCStatus* ANC_Inner_buf = &DVTX_ECNS_vars->ANC_Inner_buf;
	ANCStatus* ANC_Outer_buf = &DVTX_ECNS_vars->ANC_Outer_buf;
	AECStatus* AEC_buf;
	RESStatus* RES_buf;
	NSStatus* NS_buf;
	MixingStatus* Mix_buf = &DVTX_ECNS_vars->Mix_buf;

	VADACCStatus*  VADACC_buf = &DVTX_ECNS_vars->VADACC_buf;
	BLK_NORM_Acc = FRAME_buf->fftbuffer_Acc.BLK_NORM;

#ifdef __SV_USE_ANC_RESULT__
	InterChnanelANCStatus* ANC_buf = (InterChnanelANCStatus*)DVTX_ECNS_vars->ICANC_buf;
	short BLK_NORM_INNER = FRAME_buf->fftbuf_Inner.BLK_NORM;
#endif

	SamsungSolomonVoiceWTxFRAMEParam* Frame_param;
	SamsungSolomonVoiceWTxAECParam* AEC_param;
	SamsungSolomonVoiceWTxRESParam* RES_param;
	SamsungSolomonVoiceWTxNSParam* NS_param;
	
	short Flag_Tx_Clipping;

	Frame_param = &DVTX_ECNS_vars->FRAME_param;

	if (channel == CH_OUTER_1)
	{
		FFT_LEN = DVTX_FFT_LEN_WB;
		FFT_HALFLEN = DVTX_FFT_HALFLEN_WB;
		CHAN_HIGH = DVTX_CHAN_HIGH_WB;
		NUM_CHAN = DVTX_NUM_CHAN_WB;
		DIVID_BY_SHIFT_NUM_BIN = DIVID_BY_SHIFT_NUM_BIN_WB;
		DIVID_BY_MULT_NUM_CH = DIVID_BY_MULT_NUM_CH_WB;

		data_buffer = FRAME_buf->fftbuf_Outer_1.data_buffer; //data_buffer_WB;
		data_buffer_rx = FRAME_buf->fftbuf_RX_Outer.data_buffer;
		//data_buffer_rx2 = FRAME_buf->fftbuf_RX2_Outer.data_buffer;

		BLK_NORM = FRAME_buf->fftbuf_Outer_1.BLK_NORM;
		BLK_NORM_rx = FRAME_buf->fftbuf_RX_Outer.BLK_NORM;
		//BLK_NORM_rx2 = FRAME_buf->fftbuf_RX2_Outer.BLK_NORM;
		
		RES_buf = &DVTX_ECNS_vars->RES_Outer_buf;
		NS_buf = &DVTX_ECNS_vars->NS_Outer_buf;
		AEC_buf = &DVTX_ECNS_vars->AEC_Outer_buf_1;

		RES_param = &DVTX_ECNS_vars->RES_Outer_param;
		AEC_param = &DVTX_ECNS_vars->AEC_Outer_param_1;
		NS_param = &DVTX_ECNS_vars->NS_Outer_param;

		FrmDT = FRAME_buf->FrmDT_Outer;

		Flag_Tx_Clipping = FRAME_buf->Flag_Tx_Clipping_Inner;

#if(FLAG_SELECT_C_DSP == 1)
		dbg_data_buffer_FNLMSin = FRAME_buf->fftbuf_Outer_1.dbg_data_buffer_FNLMSin;
		dbg_data_buffer_FNLMSout = FRAME_buf->fftbuf_Outer_1.dbg_data_buffer_FNLMSout;
		dbg_data_buffer_RESout = FRAME_buf->fftbuf_Outer_1.dbg_data_buffer_RESout;
		dbg_data_buffer_NSout = FRAME_buf->fftbuf_Outer_1.dbg_data_buffer_NSout;
#endif

	}
	else
	{
		FFT_LEN = DVTX_FFT_LEN_NB;
		FFT_HALFLEN = DVTX_FreqMix_MaxBin; 
		CHAN_HIGH = DVTX_FreqMix_MaxBand; 
		NUM_CHAN = DVTX_NUM_CHAN_NB;
		DIVID_BY_SHIFT_NUM_BIN = DIVID_BY_SHIFT_NUM_BIN_NB;
		DIVID_BY_MULT_NUM_CH = DIVID_BY_MULT_NUM_CH_NB;
		
		data_buffer = FRAME_buf->fftbuf_Inner.data_buffer; //data_buffer_WB;
		data_buffer_rx = FRAME_buf->fftbuf_RX_Inner.data_buffer;
		data_buffer_rx2 = FRAME_buf->fftbuf_RX2_Inner.data_buffer;

		BLK_NORM = FRAME_buf->fftbuf_Inner.BLK_NORM;
		BLK_NORM_rx = FRAME_buf->fftbuf_RX_Inner.BLK_NORM;
		BLK_NORM_rx2 = FRAME_buf->fftbuf_RX2_Inner.BLK_NORM;

		RES_buf = &DVTX_ECNS_vars->RES_Inner_buf;
		NS_buf = &DVTX_ECNS_vars->NS_Inner_buf;
		AEC_buf = &DVTX_ECNS_vars->AEC_Inner_buf;

		RES_param = &DVTX_ECNS_vars->RES_Inner_param;
		AEC_param = &DVTX_ECNS_vars->AEC_Inner_param;
		NS_param = &DVTX_ECNS_vars->NS_Inner_param;

		FrmDT = FRAME_buf->FrmDT_Inner;

		Flag_Tx_Clipping = FRAME_buf->Flag_Tx_Clipping_Inner;

#if(FLAG_SELECT_C_DSP == 1)
		dbg_data_buffer_FNLMSin = FRAME_buf->fftbuf_Inner.dbg_data_buffer_FNLMSin;
		dbg_data_buffer_FNLMSout = FRAME_buf->fftbuf_Inner.dbg_data_buffer_FNLMSout;
		dbg_data_buffer_RESout = FRAME_buf->fftbuf_Inner.dbg_data_buffer_RESout;
		dbg_data_buffer_NSout = FRAME_buf->fftbuf_Inner.dbg_data_buffer_NSout;
#endif
	}

	
	/*Solomonvoice function
	calculate FFT bin power
	input  : Q15,0
	output : Q30,1
	*/
	//RES_buf->L_DDBin2 = (int *)data_buffer_rx2;
	fx_SolomonVoice_FFT_to_FFTpwr(RES_buf->L_EEBin, data_buffer, FFT_HALFLEN);
	fx_SolomonVoice_FFT_to_FFTpwr(FRAME_buf->L_EEBin_forMixing, FRAME_buf->FFTbuf_Tx_Outer_WB, FFT_HALFLEN);
	fx_SolomonVoice_FFT_to_FFTpwr(RES_buf->L_DDBin, data_buffer_rx, FFT_HALFLEN);
	//fx_SolomonVoice_FFT_to_FFTpwr(RES_buf->L_DDBin2, data_buffer_rx2, FFT_HALFLEN);


	/* SolomonVoice_SubBlocks #1:
	Rx band pwr estimation to detect ringback tone interval
	pwr band 1 : ring band
	pwr band 2 : other band
	*/
	if (channel == CH_INNER)
	{
		//fx_SolomonVoice_Rx_ringbacktone_bandpwr_estimation(AEC_buf, RES_buf->L_DDBin2, FFT_HALFLEN, BLK_NORM_rx2);
		fx_SolomonVoice_Rx_ringbacktone_bandpwr_estimation(AEC_buf, RES_buf->L_DDBin, FFT_HALFLEN, BLK_NORM_rx2);
	}

	
	
	/* SolomonVoice_SubBlocks #4:
	FFTbin to Band power
	input  : Q30,1, Nfft/2+1
	output : Q30,1, Nband
	*/
#ifndef  Merge_FFTband_calc
	fx_SolomonVoice_FFTpwr_to_FFTband(NS_buf->L_EsqrNS_q30, RES_buf->L_EEBin, tx_ch_tbl_nswb, tx_ch_tbl_sh_wb, CHAN_HIGH);
	fx_SolomonVoice_FFTpwr_to_FFTband(NS_buf->L_Dsqr_q30, RES_buf->L_DDBin, tx_ch_tbl_nswb, tx_ch_tbl_sh_wb, CHAN_HIGH);
#else
	fx_SolomonVoice_FFTpwr_to_FFTband_merge(NS_buf->L_EsqrNS_q30, RES_buf->L_EEBin,NS_buf->L_Dsqr_q30,RES_buf->L_DDBin, tx_ch_tbl_nswb, tx_ch_tbl_sh_wb, CHAN_HIGH);
#endif
#ifdef __SV_USE_ANC_RESULT__
	fx_SolomonVoice_FFTpwr_to_FFTband(ANC_buf->XXenh_band, ANC_buf->XX_inner, tx_ch_tbl_nswb, tx_ch_tbl_sh_wb, ANC_REF_FBAND_SIZE);
	for (i = 0; i < ANC_REF_FBAND_SIZE; i++)
	{
		ANC_buf->XXenh_band[i] = DVTXOP_L_shr(ANC_buf->XXenh_band[i], 2 * BLK_NORM_INNER - (2 * BLK_NORM + 1));
	}
#endif

	// Band Q-format change : 30,1 -> 23,8
	fx_SolomonVoice_PwrBand_FixQ_BlkDeNorm(NS_buf->L_EsqrNS, NS_buf->L_EsqrNS_q30, BLK_NORM, 7, CHAN_HIGH);/*30,1 -> 23,8*/

	// Bin Q-format change : 30,1 -> 23,8
	fx_SolomonVoice_PwrBin_FixQ_BlkDeNorm(RES_buf->L_EEBin, RES_buf->L_EEBin, BLK_NORM, 7, 1, FFT_HALFLEN);/*30,1 -> 23,8*/
	fx_SolomonVoice_PwrBin_FixQ_BlkDeNorm(RES_buf->L_DDBin, RES_buf->L_DDBin, BLK_NORM_rx, 7, 0, FFT_HALFLEN);/*30,1 -> 23,8*/
	//fx_SolomonVoice_PwrBin_FixQ_BlkDeNorm(RES_buf->L_DDBin2, RES_buf->L_DDBin2, BLK_NORM_rx2, 7, 0, FFT_HALFLEN);/*30,1 -> 23,8*/


	/* SolomonVoice_SubBlocks #18:
	calculate Tx. 1~4kHz Pwr --> silence interval detection
	Noise free flag update using Pwr 1kHz to 4kHz
	*/
	if (channel == CH_OUTER_1)
	{
		fx_SolomonVoice_tx_Silence_mode_detection(FRAME_buf, AEC_buf, RES_buf, NS_buf, NS_param);
	}


	// count RxVAD on frame
	if (AEC_buf->Flag_RxVAD_AEC == 1)
	{
		RES_buf->CntFrmRxVADon++;
		RES_buf->CntFrmRxVADon = DVTX_MIN(RES_buf->CntFrmRxVADon, 30000);// prevent counter overflow			
	}

	if (RES_param->PARA_reserved_2 == 1)// flag FNLMS on off
	{
		/* SolomonVoice_SubBlocks #8:
		noise psd to limit minimum RES gain
		L_Npsd_for_minGain
		Q15.16
		spectral subtraction min gain = L_Npsd_for_minGain*alpha
		*/
		//fx_SolomonVoice_RES_minGain(&DVTX_ECNS_vars->ECNSbuff, &DVTX_ECNS_vars->AECNS, CHAN_HIGH);

		/*Solomonvoice function
		two FNLMS filters
		over estimation for high band is applied
		DD : Q23.8
		EE : Q23.8
		RR : Q23.8
		W  : Q5,10 --> 0.15 changed
		*/
#if(FLAG_SELECT_C_DSP == 1)
		if (channel == CH_INNER)	
			for (i = 0; i < DVTX_FFT_LEN_NB; i++) dbg_data_buffer_FNLMSin[i] = data_buffer[i];
		else
			for (i = 0; i < DVTX_FFT_LEN_WB; i++) dbg_data_buffer_FNLMSin[i] = data_buffer[i];
#endif

		fx_SolomonVoice_FNLMS_filter(data_buffer, RES_buf, AEC_buf, NS_buf, FrmDT, DIVID_BY_SHIFT_NUM_BIN, FFT_HALFLEN, FFT_LEN, Flag_Tx_Clipping, channel, 0);

#if(FLAG_SELECT_C_DSP == 1)
		if (channel == CH_INNER)
			for (i = 0; i < DVTX_FFT_LEN_NB; i++) dbg_data_buffer_FNLMSout[i] = data_buffer[i];
		else
			for (i = 0; i < DVTX_FFT_LEN_WB; i++) dbg_data_buffer_FNLMSout[i] = data_buffer[i];
#endif
	}
	

	if (RES_param->PARA_reserved_3 == 1)// flag RES on off
	{
		fx_SolomonVoice_RES(common_buf, AEC_buf, RES_buf, NS_buf, AEC_param, Frame_param, RES_param, NS_param,
			data_buffer, DIVID_BY_MULT_NUM_CH, BLK_NORM, BLK_NORM_rx, CHAN_HIGH, NUM_CHAN, FFT_HALFLEN, channel);
#if(FLAG_SELECT_C_DSP == 1)
		if (channel == CH_INNER)
			for (i = 0; i < DVTX_FFT_LEN_NB; i++) dbg_data_buffer_RESout[i] = data_buffer[i];
		else
			for (i = 0; i < DVTX_FFT_LEN_WB; i++) dbg_data_buffer_RESout[i] = data_buffer[i];
#endif
	}


	if (NS_param->PARA_reserved_4 == 1)// flag NS on off
	{
		fx_SolomonVoice_NS(DVTX_ECNS_vars, FRAME_buf, AEC_buf, RES_buf, NS_buf, Mix_buf, Frame_param, NS_param,
			data_buffer, DIVID_BY_MULT_NUM_CH, BLK_NORM, CHAN_HIGH, NUM_CHAN, FFT_HALFLEN, channel, 0, VADACC_buf, BLK_NORM_Acc);

#if(FLAG_SELECT_C_DSP == 1)
		if (channel == CH_INNER)
			for (i = 0; i < DVTX_FFT_LEN_NB; i++) dbg_data_buffer_NSout[i] = data_buffer[i];
		else
			for (i = 0; i < DVTX_FFT_LEN_WB; i++) dbg_data_buffer_NSout[i] = data_buffer[i];
#endif
	}
	
	/* SolomonVoice_SubBlocks #add :
	post ECNS fDRC to reduce residual noise
	*/
	fn_fDRC(AEC_buf, RES_buf, NS_param, data_buffer, FFT_HALFLEN, BLK_NORM, channel);
				
	if(channel == CH_INNER)
		Frame_param->PARA_FLAG_FIRST_FRM_Inner = DVTX_FALSE;
	else
		Frame_param->PARA_FLAG_FIRST_FRM_Outer = DVTX_FALSE;
		
	return 0;
}
