#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include "Define_config.h"
#include "SamsungSolomonVoiceW.h"
#include "SamsungSolomonVoiceW_Int.h"
#include "SamsungSolomonVoiceW_Table.h"

int HPFcoeff[5] = { 1058936990, -2117873982, 1058936990, 2117669841, -1044336298 };

void FFTBUF_init_NB(FFTBUF_NB *fftbuf)
{
	short i;

	fftbuf->PRE_EMP = 0;
	fftbuf->BLK_NORM = 0;
	fftbuf->NORM_PRV = 0;

	for (i = 0; i < DVTX_M_FFT_LEN_NB; i++)
		fftbuf->data_buffer[i] = 0;

	for (i = 0; i < DVTX_M_FFT_LEN_NB; i++)
		fftbuf->WINDOW_OVERLAP[i] = 0;

	return;
}

void FFTBUF_init_WB(FFTBUF_WB *fftbuf)
{
	short i;

	fftbuf->PRE_EMP = 0;
	fftbuf->BLK_NORM = 0;
	fftbuf->NORM_PRV = 0;

	for (i = 0; i < DVTX_M_FFT_LEN_WB; i++)
		fftbuf->data_buffer[i] = 0;

	for (i = 0; i < DVTX_M_FFT_LEN_WB; i++)
		fftbuf->WINDOW_OVERLAP[i] = 0;

	return;
}

void IFFTBUF_init_WB(IFFTBUF_WB *Ifftbuf)
{
	short i;

	Ifftbuf->DE_EMP = 0;

	for (i = 0; i < DVTX_M_FFT_LEN_WB - DVTX_M_FRM_LEN_WB; i++)
		Ifftbuf->OVERLAP[i] = 0;


	return;
}

void SolomonVoiceWCommonBufInit(COMMONBUF* buf)
{
	short i;

	// Inner output
	for (i = 0; i < SAMSUNGDIAMONDVOICEWIDEBAND_TX; i++)	{
		buf->Output_buf_Inner[i] = 0;
	}

	// common buffer
	for (i = 0; i < DVTX_M_FRM_LEN_NB; i++) {
		buf->Buff_L_NB[i] = 0;
	}
	for (i = 0; i < DVTX_M_FFT_LEN_WB; i++) {
		buf->Buff_L_WB[i] = 0;
	}

	// PreNS
	buf->Gmin = 32767;
	for (i = 0; i < DVTX_M_FFT_HALFLEN_NB; i++) {
		buf->gL_EEii[i] = 0;
	}
	for (i = 0; i < DVTX_M_FFT_HALFLEN_WB; i++) {
		buf->gf0contourAvg[i] = 0;
	}
	for (i = 0; i < DVTX_M_FFT_HALFLEN_WB + DVTX_M_FFT_HALFLEN_WB; i++) {
		buf->gtmpf0contour[i] = 0;
	}

	// RES
	for (i = 0; i < DVTX_M_FFT_HALFLEN_WB + DVTX_M_FFT_HALFLEN_NB; i++) {
		buf->gL_DDBin[i] = 0;
		buf->gL_EEBin[i] = 0;
		buf->gGpwrres[i] = 0;
		buf->gW_fnlms_reression[i] = 0;
		buf->gW_fnlms_reression2[i] = 0;
		buf->gG_fnlms[i] = 0;
	}

	// AEC
	for (i = 0; i < 2000 + 1000; i++) {
		buf->gRxFrm_Delay_AEC[i] = 0;
	}
	for (i = 0; i < DVTX_M_FRM_LEN_WB + DVTX_Nadf_MAX - 1 + DVTX_M_FRM_LEN_NB + DVTX_Nadf_MAX - 1; i++) {
		buf->gRxFrm_AECin_AEC[i] = 0;
	}
	for (i = 0; i < DVTX_M_FRM_LEN_WB + DVTX_M_FRM_LEN_NB; i++) {
		buf->gE_tx_AEC[i] = 0;
		buf->gE_tx_AECaux[i] = 0;
		buf->gRxFFTfrm_AEC[i] = 0;
		buf->gRxFFTfrm_clp_AEC[i] = 0;
	}

	// FrmVAD
	for (i = 0; i < DVTX_M_FFT_HALFLEN_WB + DVTX_M_FFT_HALFLEN_NB; i++) {
		buf->gavg_ANC_sigPwr[i] = 0;
	}

	// ANC
	for (i = 0; i < DVTX_M_FFT_HALFLEN_WB + DVTX_M_FFT_HALFLEN_NB; i++) {
		buf->gANC_sigPwr[i] = 0;
	}
	for (i = 0; i < DVTX_M_FFT_HALFLEN_WB; i++) {
		buf->gANC_sigPwr_inner[i] = 0;
	}
	for (i = 0; i < DVTX_M_FFT_LEN_WB + DVTX_M_FFT_LEN_NB; i++) {
		buf->gEnhenced_Signal[i] = 0;
		buf->gANC_W_Filter[i] = 0;
	}

	// BWE
	for (i = 0; i < DVTX_M_FFT_LEN_WB; i++) {
		buf->ginner_x_win[i] = 0;
	}
	for (i = 0; i < DVTX_M_FFT_LEN_WB / 2; i++) {
		buf->ginner_x_win_256[i] = 0;
	}for (i = 0; i < LPCORDER_NB + 1; i++) {
		buf->ginner_a_nbf[i] = 0;
	}
	for (i = 0; i < LPCORDER + 1; i++) {
		buf->gouter_a_wbf[i] = 0;
	}
	for (i = 0; i < DVTX_M_FFT_LEN_WB; i++) {
		buf->ginner_e_wb[i] = 0;
	}
	for (i = 0; i < 8; i++) {
		buf->greSampleBuf3[i] = 0;
		buf->greSampleBuf4[i] = 0;
	}

	// Mixing
	for (i = 0; i < DVTX_M_FFT_HALFLEN_WB; i++) {
		buf->ECNSbuff_L_EEBin_forMixing[i] = 0;
	}

	// NS
	buf->gL_EEoo_07 = (short *)(&buf->Buff_L_WB[DVTX_M_FFT_LEN_WB - (DVTX_M_FFT_HALFLEN_WB)]);
	buf->gS_tmpfft1 = (short *)(&buf->Buff_L_WB[DVTX_M_FFT_LEN_WB - (DVTX_M_FFT_HALFLEN_WB >> 1)]);

	for (i = 0; i < DVTX_M_NUM_CHAN_WB; i++) {
		buf->ECNSbuff_L_SNR_by_Nmmse_ini[i] = 0;
		buf->ECNSbuff_L_SNR_by_Nmmse_global[i] = 0;

		buf->ECNSbuff_L_tmpvec[i] = 0;
		buf->ECNSbuff_L_tmpvec1[i] = 0;
		buf->ECNSbuff_S_tmpvec[i] = 0;
		buf->ECNSbuff_S_noise_floor[i] = 0;
		buf->ECNSbuff_S_spp_ns[i] = 0;

		buf->ECNSbuff_P_H1[i] = 0;
		buf->ECNSbuff_P_H1_GbyL[i] = 0;
		buf->ECNSbuff_L_SNR_by_Nmmse_ini_cepsmooth[i] = 0;
		buf->ECNSbuff_L_SNR_by_Nmmse_ini_cepsmooth_fix[i] = 0;
	}

	for (i = 0; i < DVTX_M_Nfft_ceps_WB; i++) {
		buf->ECNSbuff_tmpvec_ceps[i] = 0;
		buf->ECNSbuff_SNR_ini_ceps[i] = 0;
		buf->ECNSbuff_tmp_beta_ceps[i] = 0;
	}

	for (i = 0; i < DVTX_M_FFT_HALFLEN_WB + DVTX_M_FFT_HALFLEN_NB; i++) {
		buf->gL_RRBin_step[i] = 0;
	}


	return;

}

void SolomonVoiceWFrameInit(FRAMEStatus* FRAME_buf, SamsungSolomonVoiceWTxFRAMEParam* FRAME_param, COMMONBUF* common_buf)
{
	short i;

	/**************** Buffers *****************/
	FRAME_buf->Flag_Tx_Clipping_Inner = 0;
	FRAME_buf->Flag_Tx_Clipping_Outer = 0;

	// back up inner 16kHz input signal
	for (i = 0; i < SAMSUNGDIAMONDVOICEWIDEBAND_TX; i++) {
		FRAME_buf->Speech_Tx_Inner_WB[i] = 0;
	}

	for (i = 0; i < DVTX_M_FFT_LEN_WB; i++) {
		FRAME_buf->dbg_buffer_Outer[i] = 0;
		FRAME_buf->data_buffer_forMixing[i] = 0;
	}

	// OLA
	FFTBUF_init_NB(&FRAME_buf->fftbuf_Inner);
	FFTBUF_init_NB(&FRAME_buf->fftbuf_RX_Inner);
	FFTBUF_init_NB(&FRAME_buf->fftbuf_RX2_Inner);
	FFTBUF_init_WB(&FRAME_buf->fftbuf_Inner_WB);
	FFTBUF_init_WB(&FRAME_buf->fftbuf_Outer);
	FFTBUF_init_WB(&FRAME_buf->fftbuf_RX_Outer);
	FFTBUF_init_WB(&FRAME_buf->fftbuf_RX2_Outer);
		
	// IOLA
	IFFTBUF_init_WB(&FRAME_buf->Ifftbuf_Output);
	IFFTBUF_init_WB(&FRAME_buf->Ifftbuf_Inner_WB);
	IFFTBUF_init_WB(&FRAME_buf->Ifftbuf_Outer_WB);
	IFFTBUF_init_WB(&FRAME_buf->Ifftbuf_BWE);

	FRAME_buf->L_EEBin_forMixing = &common_buf->ECNSbuff_L_EEBin_forMixing;

	for (i = 0; i < 5; i++)	{
		FRAME_buf->HPFstateOuterTx[i] = 0;
		FRAME_buf->HPFstateOuterRx[i] = 0;
	}

	for (i = 0; i < 8; i++)	{
		FRAME_buf->Buf_Downsample_InnerRx[i] = 0;
		FRAME_buf->Buf_Downsample_InnerTx[i] = 0;
	}

	FRAME_buf->Pwr_1kHz_to_4kHz_Inner = 0;
	FRAME_buf->Pwr_100Hz_to_1kHz_Inner = 0;
	FRAME_buf->Pwr_1kHz_to_4kHz_Outer = 0;
	FRAME_buf->Pwr_100Hz_to_1kHz_Outer = 0;

	FRAME_buf->avg_ANC_sigPwr_Inner = &common_buf->gavg_ANC_sigPwr[DVTX_M_FFT_HALFLEN_WB];
	FRAME_buf->avg_ANC_sigPwr_Outer = &common_buf->gavg_ANC_sigPwr;

	FRAME_buf->FrmPiLowBand_Inner = 0;
	FRAME_buf->FrmRioLowBand_Inner = 0;
	FRAME_buf->FrmPiLowBand_Outer = 0;
	FRAME_buf->FrmRioLowBand_Outer = 0;

	FRAME_buf->VariableTHD_Ratio_LowBandPwr = 2000;
	FRAME_buf->VariableTHD_THD_Pwr_inner = 1000;
	FRAME_buf->FrmDT_Inner = 0;
	FRAME_buf->FrmDT_Outer = 0;

	FRAME_buf->FrmVAD_Inner = 0;
	FRAME_buf->FrmVAD_Outer = 0;

	FRAME_buf->Avg_FrmPiLowBand = 1500;
	FRAME_buf->PtBuff_FrmPiLowBand = 0;
	for (i = 0; i < DVTX_NumFrm_MCRA_VAD; i++)
		FRAME_buf->Buff_FrmPiLowBand[i] = 0;

	FRAME_buf->MinVal_FrmPiLowBand = 0;

	/****************Params*****************/
	FRAME_param->PARA_txMode= 0;// DO NOT CHANGE
	FRAME_param->PARA_call_mode_HS_HF_EAR= 0;

	FRAME_param->TX_Inner_bandwidth= 0;
	FRAME_param->TX_Outer_bandwidth= 0;

	FRAME_param->PARA_AEC_ONOFF_Inner= 0; // Outer_PARA_AEC_on_off
	FRAME_param->PARA_AEC_ONOFF_Outer= 0; // Outer_PARA_AEC_on_off
	FRAME_param->PARA_FNLMS_ONOFF_Inner= 0; // Outer_PARA_FNLMS_on_off
	FRAME_param->PARA_FNLMS_ONOFF_Outer= 0; // Outer_PARA_FNLMS_on_off
	FRAME_param->PARA_RES_ONOFF_Inner= 0; // Outer_PARA_RES_on_off
	FRAME_param->PARA_RES_ONOFF_Outer= 0; // Outer_PARA_RES_on_off
	FRAME_param->PARA_NS_ONOFF_Inner= 0; // Outer_PARA_NS_on_off
	FRAME_param->PARA_NS_ONOFF_Outer= 0; // Outer_PARA_NS_on_off
	FRAME_param->PARA_BWE_ONOFF_Inner= 0; // Outer_PARA_BWE_on_off
	FRAME_param->PARA_Mixing_ONOFF_Outer= 0; // Outer_PARA_Mixing_on_off

	FRAME_param->PARA_FLAG_FIRST_FRM_Inner = 0;
	FRAME_param->PARA_FLAG_FIRST_FRM_Outer = 0;

	FRAME_param->PARA_Q_for_InSigGain_Inner = 0;
	FRAME_param->PARA_Gain_TxSig_Inner = 0;
	FRAME_param->PARA_Gain_RxSig_Inner = 0;
	FRAME_param->PARA_Gain_TxSig_NS_IN_Inner = 0;
	FRAME_param->PARA_Gain_RxSig_NS_IN_Inner = 0;
	FRAME_param->PARA_Gain_TxSig_NS_Out_Inner = 0;

	FRAME_param->PARA_Q_for_InSigGain_Outer = 0;
	FRAME_param->PARA_Gain_TxSig_Outer = 0;
	FRAME_param->PARA_Gain_RxSig_Outer = 0;
	FRAME_param->PARA_Gain_TxSig_NS_IN_Outer = 0;
	FRAME_param->PARA_Gain_RxSig_NS_IN_Outer = 0;
	FRAME_param->PARA_Gain_TxSig_NS_Out_Outer = 0;

	FRAME_param->PARA_Gain_TxSig_BWE_IN= 0;
	FRAME_param->PARA_Gain_TxSig_BWE_Out= 0;

	FRAME_param->PARA_reserved_11= 0; // gain is Q4.11 format...

	FRAME_param->PARA_reserved_12= 0; //reserved
	FRAME_param->PARA_reserved_13= 0;
	FRAME_param->PARA_reserved_14= 0;
	FRAME_param->PARA_reserved_15= 0;
	FRAME_param->PARA_reserved_16= 0;
	FRAME_param->PARA_reserved_17= 0;
	FRAME_param->PARA_reserved_18= 0;
	FRAME_param->PARA_reserved_19= 0;
	FRAME_param->PARA_reserved_20= 0;

	return;
}

int SolomonVoiceECNSINIT(DVTX_ECNS_Cfg_t* DVTX_ECNS_vars)
{
	DVTX_ECNS_vars->TX_bandwidth_Inner = DVTX_FRAME_LENGTH_NB;
	DVTX_ECNS_vars->TX_bandwidth_Outer = DVTX_FRAME_LENGTH_WB;

	SolomonVoiceWCommonBufInit(&DVTX_ECNS_vars->COMMON_buf);
	SolomonVoiceWFrameInit(&DVTX_ECNS_vars->FRAME_buf, &DVTX_ECNS_vars->FRAME_param, &DVTX_ECNS_vars->COMMON_buf);
	SolomonVoiceWAECInit(&DVTX_ECNS_vars->AEC_Inner_buf, &DVTX_ECNS_vars->AEC_Inner_param, &DVTX_ECNS_vars->COMMON_buf, CH_INNER);
	SolomonVoiceWAECInit(&DVTX_ECNS_vars->AEC_Outer_buf, &DVTX_ECNS_vars->AEC_Outer_param, &DVTX_ECNS_vars->COMMON_buf, CH_OUTER);
	SolomonVoiceWRESInit(&DVTX_ECNS_vars->RES_Inner_buf, &DVTX_ECNS_vars->RES_Inner_param, &DVTX_ECNS_vars->COMMON_buf, CH_INNER);
	SolomonVoiceWRESInit(&DVTX_ECNS_vars->RES_Outer_buf, &DVTX_ECNS_vars->RES_Outer_param, &DVTX_ECNS_vars->COMMON_buf, CH_OUTER);
	SolomonVoiceWNSInit(&DVTX_ECNS_vars->NS_Inner_buf, &DVTX_ECNS_vars->NS_Inner_param, &DVTX_ECNS_vars->COMMON_buf, CH_INNER);
	SolomonVoiceWNSInit(&DVTX_ECNS_vars->NS_Outer_buf, &DVTX_ECNS_vars->NS_Outer_param, &DVTX_ECNS_vars->COMMON_buf, CH_OUTER);
	SolomonVoiceWPreNSInit(&DVTX_ECNS_vars->PRENS_Inner_buf, &DVTX_ECNS_vars->PreNS_Inner_param, &DVTX_ECNS_vars->COMMON_buf, CH_INNER);
	SolomonVoiceWPreNSInit(&DVTX_ECNS_vars->PRENS_Outer_buf, &DVTX_ECNS_vars->PreNS_Outer_param, &DVTX_ECNS_vars->COMMON_buf, CH_OUTER);
	SolomonVoiceWANCInit(&DVTX_ECNS_vars->ANC_Inner_buf, &DVTX_ECNS_vars->ANC_Inner_param, &DVTX_ECNS_vars->COMMON_buf, CH_INNER);
	SolomonVoiceWANCInit(&DVTX_ECNS_vars->ANC_Outer_buf, &DVTX_ECNS_vars->ANC_Outer_param, &DVTX_ECNS_vars->COMMON_buf, CH_OUTER);
	SolomonVoiceWBWEInit(&DVTX_ECNS_vars->BWE_buf, &DVTX_ECNS_vars->BWE_param, &DVTX_ECNS_vars->COMMON_buf);
	SolomonVoiceWMixingInit(&DVTX_ECNS_vars->Mix_buf, &DVTX_ECNS_vars->Mix_param, &DVTX_ECNS_vars->COMMON_buf);

	return 0;
}

void SolomonVoiceW_FRAME_ParamConfig(SamsungSolomonVoiceWTxFRAMEParam* param_buf, SamsungSolomonVoiceWTxFRAMEParam* param)
{
	param_buf->PARA_txMode = param->PARA_txMode;
	param_buf->PARA_call_mode_HS_HF_EAR = param->PARA_call_mode_HS_HF_EAR;
	
	param_buf->TX_Inner_bandwidth = param->TX_Inner_bandwidth;
	param_buf->TX_Outer_bandwidth = param->TX_Outer_bandwidth;
	
	param_buf->PARA_AEC_ONOFF_Inner = param->PARA_AEC_ONOFF_Inner;
	param_buf->PARA_AEC_ONOFF_Outer = param->PARA_AEC_ONOFF_Outer;
	param_buf->PARA_FNLMS_ONOFF_Inner = param->PARA_FNLMS_ONOFF_Inner;
	param_buf->PARA_FNLMS_ONOFF_Outer = param->PARA_FNLMS_ONOFF_Outer;
	param_buf->PARA_RES_ONOFF_Inner = param->PARA_RES_ONOFF_Inner;
	param_buf->PARA_RES_ONOFF_Outer = param->PARA_RES_ONOFF_Outer;
	param_buf->PARA_NS_ONOFF_Inner = param->PARA_NS_ONOFF_Inner;
	param_buf->PARA_NS_ONOFF_Outer = param->PARA_NS_ONOFF_Outer;
	param_buf->PARA_BWE_ONOFF_Inner = param->PARA_BWE_ONOFF_Inner;
	param_buf->PARA_Mixing_ONOFF_Outer = param->PARA_Mixing_ONOFF_Outer;
	
	param_buf->PARA_FLAG_FIRST_FRM_Inner = param->PARA_FLAG_FIRST_FRM_Inner;
	param_buf->PARA_FLAG_FIRST_FRM_Outer = param->PARA_FLAG_FIRST_FRM_Outer;
	
	param_buf->PARA_Q_for_InSigGain_Inner = param->PARA_Q_for_InSigGain_Inner;
	param_buf->PARA_Gain_TxSig_Inner = param->PARA_Gain_TxSig_Inner;
	param_buf->PARA_Gain_RxSig_Inner = param->PARA_Gain_RxSig_Inner;
	param_buf->PARA_Gain_TxSig_NS_IN_Inner = param->PARA_Gain_TxSig_NS_IN_Inner;
	param_buf->PARA_Gain_RxSig_NS_IN_Inner = param->PARA_Gain_RxSig_NS_IN_Inner;
	param_buf->PARA_Gain_TxSig_NS_Out_Inner = param->PARA_Gain_TxSig_NS_Out_Inner;

	param_buf->PARA_Q_for_InSigGain_Outer = param->PARA_Q_for_InSigGain_Outer;
	param_buf->PARA_Gain_TxSig_Outer = param->PARA_Gain_TxSig_Outer;
	param_buf->PARA_Gain_RxSig_Outer = param->PARA_Gain_RxSig_Outer;
	param_buf->PARA_Gain_TxSig_NS_IN_Outer = param->PARA_Gain_TxSig_NS_IN_Outer;
	param_buf->PARA_Gain_RxSig_NS_IN_Outer = param->PARA_Gain_RxSig_NS_IN_Outer;
	param_buf->PARA_Gain_TxSig_NS_Out_Outer = param->PARA_Gain_TxSig_NS_Out_Outer;

	param_buf->PARA_Gain_TxSig_BWE_IN = param->PARA_Gain_TxSig_BWE_IN;
	param_buf->PARA_Gain_TxSig_BWE_Out = param->PARA_Gain_TxSig_BWE_Out;
	
	param_buf->PARA_reserved_11 = param->PARA_reserved_11;
	
	param_buf->PARA_reserved_12 = param->PARA_reserved_12;
	param_buf->PARA_reserved_13 = param->PARA_reserved_13;
	param_buf->PARA_reserved_14 = param->PARA_reserved_14;
	param_buf->PARA_reserved_15 = param->PARA_reserved_15;
	param_buf->PARA_reserved_16 = param->PARA_reserved_16;
	param_buf->PARA_reserved_17 = param->PARA_reserved_17;
	param_buf->PARA_reserved_18 = param->PARA_reserved_18;
	param_buf->PARA_reserved_19 = param->PARA_reserved_19;
	param_buf->PARA_reserved_20 = param->PARA_reserved_20;

	return;
}

void SamsungTxECNSInOutConfig(DVTX_ECNS_Cfg_t* DVTX_ECNS_vars,
	short* Speech_Tx_Inner, short* Speech_Tx_Outer, short* Speech_rx_Inner, short* Speech_rx_Outer, short* OutSignal,
	short *Output_buf_Inner_NB, short *Output_buf_Inner_WB, short *Output_buf_BWE, short *Output_buf_Outer)
{
	short i;

	//Tx input config
	DVTX_ECNS_vars->Speech_Tx_Inner = Speech_Tx_Inner;
	DVTX_ECNS_vars->Speech_Tx_Outer = Speech_Tx_Outer;

	//Rx input 
	DVTX_ECNS_vars->Speech_Rx_Inner = Speech_rx_Inner;
	DVTX_ECNS_vars->Speech_Rx_Outer = Speech_rx_Outer;

	//Output config
	DVTX_ECNS_vars->OutSignal_Inner = DVTX_ECNS_vars->COMMON_buf.Output_buf_Inner;
	DVTX_ECNS_vars->OutSignal_Outer = OutSignal;

	// dbg
	DVTX_ECNS_vars->dbgOutput_buf_Inner_NB = Output_buf_Inner_NB;
	DVTX_ECNS_vars->dbgOutput_buf_Inner_WB = Output_buf_Inner_WB;
	DVTX_ECNS_vars->dbgOutput_buf_BWE = Output_buf_BWE;
	DVTX_ECNS_vars->dbgOutput_buf_Outer = Output_buf_Outer;

	return;
}

int SolomonVoiceWParamConfig(DVTX_ECNS_Cfg_t* DVTX_ECNS_vars, SamsungSolomonVoiceParam* param)
{
	short i;
	
	SolomonVoiceW_FRAME_ParamConfig(&DVTX_ECNS_vars->FRAME_param, &param->FRAME_param);
	SolomonVoiceW_AEC_ParamConfig(&DVTX_ECNS_vars->AEC_Inner_param, &param->AEC_Inner_param);
	SolomonVoiceW_AEC_ParamConfig(&DVTX_ECNS_vars->AEC_Outer_param, &param->AEC_Outer_param);
	SolomonVoiceW_RES_ParamConfig(&DVTX_ECNS_vars->RES_Inner_param, &DVTX_ECNS_vars->RES_Inner_buf, &param->RES_Inner_param, CH_INNER);
	SolomonVoiceW_RES_ParamConfig(&DVTX_ECNS_vars->RES_Outer_param, &DVTX_ECNS_vars->RES_Outer_buf, &param->RES_Outer_param, CH_OUTER);
	SolomonVoiceW_NS_ParamConfig(&DVTX_ECNS_vars->NS_Inner_param, &param->NS_Inner_param);
	SolomonVoiceW_NS_ParamConfig(&DVTX_ECNS_vars->NS_Outer_param, &param->NS_Outer_param);
	SolomonVoiceW_PreNS_ParamConfig(&DVTX_ECNS_vars->PreNS_Inner_param, &param->PreNS_Inner_param);
	SolomonVoiceW_PreNS_ParamConfig(&DVTX_ECNS_vars->PreNS_Outer_param, &param->PreNS_Outer_param);
	SolomonVoiceW_ANC_ParamConfig(&DVTX_ECNS_vars->ANC_Inner_param, &param->ANC_Inner_param);
	SolomonVoiceW_ANC_ParamConfig(&DVTX_ECNS_vars->ANC_Outer_param, &param->ANC_Outer_param);
	SolomonVoiceW_BWE_ParamConfig(&DVTX_ECNS_vars->BWE_param, &param->BWE_param);
	SolomonVoiceW_Mix_ParamConfig(&DVTX_ECNS_vars->Mix_param, &param->Mix_param);

	return 0;
}

short fx_SolomonVoice_clipping_detection(short *pTxinner, short TX_bandwidth, short Thr)
{
	short i;
	short Flag_Clipping = 0;

	for (i = 0; i < TX_bandwidth; i++)
	{
		if (*(pTxinner + i) > Thr)
		{
			Flag_Clipping = 1;
			break;
		}
	}

	return Flag_Clipping;
}

int SolomonVoiceWECNSExe(DVTX_ECNS_Cfg_t* DVTX_ECNS_vars)
{
	short i, ret;

	short *Speech_Tx_Inner = DVTX_ECNS_vars->Speech_Tx_Inner;
	short *Speech_Tx_Outer = DVTX_ECNS_vars->Speech_Tx_Outer;
	short *Speech_Rx_Inner = DVTX_ECNS_vars->Speech_Rx_Inner;
	short *Speech_Rx_Outer = DVTX_ECNS_vars->Speech_Rx_Outer;
	
	short TX_Inner_bandwidth = DVTX_ECNS_vars->FRAME_param.TX_Inner_bandwidth;
	short TX_Outer_bandwidth = DVTX_ECNS_vars->FRAME_param.TX_Outer_bandwidth;

	short *Speech_Tx_Inner_WB = DVTX_ECNS_vars->FRAME_buf.Speech_Tx_Inner_WB;
	int *HPFstateOuterTx = DVTX_ECNS_vars->FRAME_buf.HPFstateOuterTx;
	int *HPFstateOuterRx = DVTX_ECNS_vars->FRAME_buf.HPFstateOuterRx;
	long *Buf_Downsample_InnerRx = DVTX_ECNS_vars->FRAME_buf.Buf_Downsample_InnerRx;
	long *Buf_Downsample_InnerTx = DVTX_ECNS_vars->FRAME_buf.Buf_Downsample_InnerTx;

	short* RxFFTfrm_AEC_Inner = DVTX_ECNS_vars->AEC_Inner_buf.RxFFTfrm_AEC;
	short* RxFFTfrm_AEC_Outer = DVTX_ECNS_vars->AEC_Outer_buf.RxFFTfrm_AEC;
	short* RxFFTfrm_clp_AEC_Inner = DVTX_ECNS_vars->AEC_Inner_buf.RxFFTfrm_clp_AEC;
	short* RxFFTfrm_clp_AEC_Outer = DVTX_ECNS_vars->AEC_Outer_buf.RxFFTfrm_clp_AEC;
	short PARA_Gain_TxSig_NS_IN_Inner = DVTX_ECNS_vars->FRAME_param.PARA_Gain_TxSig_NS_IN_Inner;
	short PARA_Gain_RxSig_NS_IN_Inner = DVTX_ECNS_vars->FRAME_param.PARA_Gain_RxSig_NS_IN_Inner;
	short PARA_Gain_TxSig_NS_IN_Outer = DVTX_ECNS_vars->FRAME_param.PARA_Gain_TxSig_NS_IN_Outer;
	short PARA_Gain_RxSig_NS_IN_Outer = DVTX_ECNS_vars->FRAME_param.PARA_Gain_RxSig_NS_IN_Outer;
	short PARA_Q_for_InSigGain_Inner = DVTX_ECNS_vars->FRAME_param.PARA_Q_for_InSigGain_Inner;
	short PARA_Q_for_InSigGain_Outer = DVTX_ECNS_vars->FRAME_param.PARA_Q_for_InSigGain_Outer;
	
	short* data_buffer_NB = &DVTX_ECNS_vars->FRAME_buf.fftbuf_Inner.data_buffer; // data_buffer_NB
	short* data_buffer_WB = &DVTX_ECNS_vars->FRAME_buf.fftbuf_Outer.data_buffer; // data_buffer_WB

	/********* inner tx clipping detection in time domain ********/
	DVTX_ECNS_vars->FRAME_buf.Flag_Tx_Clipping_Inner = fx_SolomonVoice_clipping_detection(Speech_Tx_Inner, TX_Inner_bandwidth, 18000);

	/********* outer tx clipping detection in time domain ********/
	DVTX_ECNS_vars->FRAME_buf.Flag_Tx_Clipping_Outer = fx_SolomonVoice_clipping_detection(Speech_Tx_Outer, TX_Outer_bandwidth, 18000);


	/********* outer IIR Filtering ********/
	FN_2ndIIR_FILTERING(Speech_Tx_Outer, TX_Outer_bandwidth, HPFcoeff, HPFstateOuterTx); //¸Þ¸ð : HPFcoeff Ã³¸®ÇÒ °Í, IIRÇÊÅÍ Á¤¸® ÇÊ¿ä
	FN_2ndIIR_FILTERING(Speech_Rx_Outer, TX_Outer_bandwidth, HPFcoeff, HPFstateOuterRx);

	/********* copy inner 16kHz data for VAD and ANC and pref0NS ********/
	Fx_vector_copy_s(Speech_Tx_Inner_WB, Speech_Tx_Inner, DVTX_FRM_LEN_WB);

	/********* inner downsampling : 16kHz to 8kHz ********/
	WebRtcSpl_DownsampleBy2(Speech_Rx_Inner, DVTX_FRAME_LENGTH_WB, Speech_Rx_Inner, Buf_Downsample_InnerRx);
	WebRtcSpl_DownsampleBy2(Speech_Tx_Inner, DVTX_FRAME_LENGTH_WB, Speech_Tx_Inner, Buf_Downsample_InnerTx);

	for (i = DVTX_FRAME_LENGTH_NB + 1; i < DVTX_FRAME_LENGTH_WB; i++) {
		Speech_Rx_Inner[i] = 0;
		Speech_Tx_Inner[i] = 0;
	}

	/********* EC inner : 8kHz Fs ********/
	FN_SOLOMONVOICEW_TX_AEC(DVTX_ECNS_vars, CH_INNER);

	/********* EC outer : 16kHz Fs ********/
	FN_SOLOMONVOICEW_TX_AEC(DVTX_ECNS_vars, CH_OUTER);


	/********* input signal gain for NS module ********/
	Fx_vector_gain(Speech_Tx_Inner, PARA_Gain_TxSig_NS_IN_Inner, PARA_Q_for_InSigGain_Inner, DVTX_FRM_LEN_NB); // gain is Q4.11 format... 
	Fx_vector_gain(RxFFTfrm_AEC_Inner, PARA_Gain_RxSig_NS_IN_Inner, PARA_Q_for_InSigGain_Inner, DVTX_FRM_LEN_NB); // gain is Q4.11 format... 
	Fx_vector_gain(RxFFTfrm_clp_AEC_Inner, PARA_Gain_RxSig_NS_IN_Inner, PARA_Q_for_InSigGain_Inner, DVTX_FRM_LEN_NB); // gain is Q4.11 format... 

	Fx_vector_gain(Speech_Tx_Outer, PARA_Gain_TxSig_NS_IN_Outer, PARA_Q_for_InSigGain_Outer, DVTX_FRM_LEN_WB); // gain is Q4.11 format... 
	Fx_vector_gain(RxFFTfrm_AEC_Outer, PARA_Gain_RxSig_NS_IN_Outer, PARA_Q_for_InSigGain_Outer, DVTX_FRM_LEN_WB); // gain is Q4.11 format... 
	Fx_vector_gain(RxFFTfrm_clp_AEC_Outer, PARA_Gain_RxSig_NS_IN_Outer, PARA_Q_for_InSigGain_Outer, DVTX_FRM_LEN_WB); // gain is Q4.11 format... 
	Fx_vector_gain(Speech_Tx_Inner_WB, PARA_Gain_TxSig_NS_IN_Outer, PARA_Q_for_InSigGain_Outer, DVTX_FRM_LEN_WB); // gain is Q4.11 format... 

	/********* FFT ********/
	FFT_functions(DVTX_ECNS_vars);

	fn_FrmVAD(DVTX_ECNS_vars);

	if (FLAG_WB_OuterECNSOnly == 1) // WB Á¤·®ÃøÁ¤
	{
		DVTX_ECNS_vars->FRAME_buf.FrmVAD_Outer = 1;
		DVTX_ECNS_vars->FRAME_buf.FrmDT_Outer = 1;
				
		DVTX_ECNS_vars->NS_Outer_param.PARA_xi_for_SPP_Table = 0;// 0 to 15 [dB] scale
		DVTX_ECNS_vars->NS_Outer_param.PARA_Npsd_Gain_MIN = 22000;//DVTX_FLOAT2FIXED(0.67f, 15);//	Npsd	gain	in	silence	interval
		DVTX_ECNS_vars->NS_Outer_param.PARA_NoiseFloor_Offset_MAX = 5500;// DVTX_FLOAT2FIXED(0.18f, 15);//	Gain	floor	offset	in	silence	interval
		DVTX_ECNS_vars->Mix_param.PARA_reserved_9 = 0;	// in/out Mixing flag

		DVTX_ECNS_vars->AEC_Outer_param.PARA_THD_Pwr_Tx_dB = 7168;// DVTX_FLOAT2FIXED(35.0f, 8);
		DVTX_ECNS_vars->NS_Outer_param.PARA_THD_Pwr_Lo_1k_4k = 5000;

		DVTX_ECNS_vars->NS_Outer_param.PARA_reserved_61 = 0;
		DVTX_ECNS_vars->COMMON_buf.Gmin = 32767;
	}
	else
	{
		ret = fn_Adaptive_NC(DVTX_ECNS_vars, DVTX_ECNS_vars->PRENS_Inner_buf.ANCflag, DVTX_ECNS_vars->PRENS_Outer_buf.ANCflag); // ACN inner on, ANC outer off
		ret = FN_f0_based_pre_Noise_suppression(DVTX_ECNS_vars, DVTX_ECNS_vars->PRENS_Inner_buf.F0flag); // f0 always		
	}

	DVTX_ECNS_vars->TX_bandwidth_Inner = DVTX_FRAME_LENGTH_NB;

	/********* NS inner : 8kHz Fs ********/
	FN_SOLOMONVOICEW_TX_RES_NS(DVTX_ECNS_vars, CH_INNER);

	DVTX_ECNS_vars->FRAME_param.TX_Outer_bandwidth = DVTX_FRAME_LENGTH_WB;

	/********* ECNS outer : 16kHz Fs ********/
	FN_SOLOMONVOICEW_TX_RES_NS(DVTX_ECNS_vars, CH_OUTER);

	/********* Mixing (Frequency Domain) ********/
	FN_Mixing_FreqDomain(DVTX_ECNS_vars);

	/********* IFFT ********/
	IFFT_functions(DVTX_ECNS_vars);

	/********* output signal gain ********/
	Fx_vector_gain(data_buffer_NB, DVTX_ECNS_vars->FRAME_param.PARA_Gain_TxSig_NS_Out_Inner, DVTX_ECNS_vars->FRAME_param.PARA_Q_for_InSigGain_Inner, DVTX_FFT_LEN_NB); // gain is Q4.10 format... 
	Fx_vector_gain(data_buffer_WB, DVTX_ECNS_vars->FRAME_param.PARA_Gain_TxSig_NS_Out_Outer, DVTX_ECNS_vars->FRAME_param.PARA_Q_for_InSigGain_Outer, DVTX_FFT_LEN_WB); // gain is Q4.10 format... 
	if (DVTX_ECNS_vars->Mix_buf.State > 1)
		Fx_vector_gain(data_buffer_WB, 1149, DVTX_ECNS_vars->FRAME_param.PARA_Q_for_InSigGain_Outer, DVTX_FFT_LEN_WB); // +1dB for high noise gain is Q4.10 format... 
																											// Txinput gain applying to inner signal for mixing	
	Fx_vector_gain(DVTX_ECNS_vars->BWE_buf.inner_x_win, DVTX_ECNS_vars->FRAME_param.PARA_Gain_TxSig_Outer, DVTX_ECNS_vars->FRAME_param.PARA_Q_for_InSigGain_Outer, DVTX_FFT_LEN_WB); // gain is Q4.11 format... 
	Fx_vector_gain(DVTX_ECNS_vars->BWE_buf.inner_x_win, DVTX_ECNS_vars->FRAME_param.PARA_Gain_TxSig_NS_Out_Outer, DVTX_ECNS_vars->FRAME_param.PARA_Q_for_InSigGain_Outer, DVTX_FFT_LEN_WB); // gain is Q4.11 format... 


	/********* BWE ********/
	FN_SOLOMONVOICEW_TX_BWE(DVTX_ECNS_vars);

	/********* Mixing (mixing state, gain»êÃâ) ********/
	FN_SOLOMONVOICEW_TX_MIXING_SET(DVTX_ECNS_vars);

	/********* Mixing (Time Domain) ********/
	FN_SOLOMONVOICEW_TX_MIXING_TIMEDOMAIN(DVTX_ECNS_vars);

	/********* OLA ********/
	IOLA_functions(DVTX_ECNS_vars);

	
	

	return 0;
}
