#include <stdio.h>
#include<string.h>
#include "SV_Frame.h"
#if defined(_WIN64) || defined(_WIN32) // for window
#include <io.h>
#include <direct.h>
#include "Define_config.h"
#endif

#ifdef BSH_DEBUG
#define OUT_SIZE 12
#else
#define OUT_SIZE 1
#endif

#define FRAME_SIZE SVTX_WB_FRM_SIZE


#define DB_PATH "D:\\Audio_Solutions\\IN_EAR\\Recording_samples\\4_Berry_Dump\\20210108_Lab1-8\\"
#define DB_FILE_EXT "pcm"
//#define DB_PATH "D:\\workspace\\02_TWS_ECNS\\01_dev\\03_testvectors\\1023 1-4Ã¨¹ö ´ýÇÁ(echo, ns, wind)\\1023_ecns\\"
//#define DB_FILE_EXT "raw"
#define TEST_TX_IN1 DB_PATH"audio_dump_main_mic_in."DB_FILE_EXT
#define TEST_TX_IN2 DB_PATH"audio_dump_sub_mic_in."DB_FILE_EXT
#define TEST_TX_IN3 DB_PATH"audio_dump_third_mic_in."DB_FILE_EXT
#define TEST_TX_IN4 DB_PATH"audio_dump_fourth_mic_in."DB_FILE_EXT
#define TEST_RX_IN DB_PATH"audio_dump_rx_in."DB_FILE_EXT
#if defined(_WIN64) || defined(_WIN32) // for window
#define TEST_OUT DB_PATH"_C_out_."DB_FILE_EXT
#else
#define TEST_OUT DB_PATH"_ARM_out_."DB_FILE_EXT
#endif

#define DBG_PATH DB_PATH"debug\\"
#define TEST_OUT2 DBG_PATH"audio_dump.BF_out."DB_FILE_EXT
#define TEST_OUT3 DBG_PATH"audio_dump.BM_out."DB_FILE_EXT
#define TEST_OUT4 DBG_PATH"audio_dump.inEar_out."DB_FILE_EXT
#define TEST_OUT5 DBG_PATH"audio_dump.InEarBF_out."DB_FILE_EXT
#define TEST_OUT6 DBG_PATH"audio_dump.DNN_in1."DB_FILE_EXT
#define TEST_OUT7 DBG_PATH"audio_dump.DNN_in2."DB_FILE_EXT
#define TEST_OUT8 DBG_PATH"audio_dump.DNN_out."DB_FILE_EXT
#define TEST_OUT9 DBG_PATH"audio_dump.InEarBM_out."DB_FILE_EXT
#define TEST_OUT10 DBG_PATH"audio_dump.AEC_in1."DB_FILE_EXT
#define TEST_OUT11 DBG_PATH"audio_dump.AEC_in2."DB_FILE_EXT
#define TEST_OUT12 DBG_PATH"audio_dump.AEC_in3."DB_FILE_EXT

char fin_name_outer1[] = TEST_TX_IN1;
char fin_name_outer2[] = TEST_TX_IN2;
char fin_name_inner[] = TEST_TX_IN3;
char fin_name_acc[] = TEST_TX_IN4;
char fin_name_rx[] = TEST_RX_IN;
char fout_name[] = TEST_OUT;


FILE *fid_outer1, *fid_outer2, *fid_inner, *fid_rx, *fid_acc;
FILE* fout[OUT_SIZE];

#ifdef Debug_File_Write_C
FILE *fp_chPwr, *fp_vad, *fp_aec, *fp_agc, *fp_bf, *fp_fft, *fp_wnd, *fp_mic_check;
FILE *f_aec[4];
FILE *f_acc[4];
FILE *f_acc_ns[4];
FILE *fCRN_speechLogSpec, *fCRN_noiseLogSpec, *fCRN_estMask;
FILE *f_flag[7];
FILE *f_inEar[10];
FILE *f_mixer[4];
FILE *f_echo_mix[4];
FILE *f_mmse[6];
FILE *f_tws_gev[6];
#endif

short    readbuf[BUFSIZE];
short    writebuf[BUFSIZE * OUT_SIZE];

int    readbuf_outer1_32[BUFSIZE];
int    readbuf_outer2_32[BUFSIZE];
int    readbuf_inner_32[BUFSIZE];
int    readbuf_rx_32[BUFSIZE];
int    readbuf_acc_32[BUFSIZE];

int    writebuf_32[BUFSIZE * OUT_SIZE];

int frmCnt;
void IntToShort(short* out, int* in, int n)
{
	/* ³ªÁß¿£ SolomonVoice_Frame_Exe ³»ºÎ·Î ÀÌµ¿ */
	/* int -> short Ã³¸® Àü¿¡ overflow check or AGC? */
	do
	{
		if (*in > 32767)
			*(out++) = 32767;
		else if (*in < -32768)
			*(out++) = -32768;
		else
			*(out++) = (short)(*in);

		in++;

	} while (--n > 0);

	return;
}

void ShortToInt(int* out, short* in, int n)
{
	do
	{
		*(out++) = (int)(*(in++));
	} while (--n > 0);
}

int main()
{
	int framenum = 0;
	int i;

	fid_outer1 = fopen(fin_name_outer1, "rb");
	fid_outer2 = fopen(fin_name_outer2, "rb");
	fid_inner = fopen(fin_name_inner, "rb");
	fid_rx = fopen(fin_name_rx, "rb");
	fid_acc = fopen(fin_name_acc, "rb");

	fout[0] = fopen(fout_name, "wb");
#ifdef BSH_DEBUG
	char tmpStr[1024];

	tmpStr[0] = "\n";
	sprintf(tmpStr, DBG_PATH);
	if (_access(tmpStr, 0) == -1)
		_mkdir(tmpStr);

	if ((fout[1] = fopen(TEST_OUT2, "wb")) == NULL) {
		fprintf(stderr, "output file error..\n");
		exit(-1);
	}
	if ((fout[2] = fopen(TEST_OUT3, "wb")) == NULL) {
		fprintf(stderr, "output file error..\n");
		exit(-1);
	}
	if ((fout[3] = fopen(TEST_OUT4, "wb")) == NULL) {
		fprintf(stderr, "output file error..\n");
		exit(-1);
	}
	if ((fout[4] = fopen(TEST_OUT5, "wb")) == NULL) {
		fprintf(stderr, "output file error..\n");
		exit(-1);
	}
	if ((fout[5] = fopen(TEST_OUT6, "wb")) == NULL) {
		fprintf(stderr, "output file error..\n");
		exit(-1);
	}
	if ((fout[6] = fopen(TEST_OUT7, "wb")) == NULL) {
		fprintf(stderr, "output file error..\n");
		exit(-1);
	}
	if ((fout[7] = fopen(TEST_OUT8, "wb")) == NULL) {
		fprintf(stderr, "output file error..\n");
		exit(-1);
	}
	if ((fout[8] = fopen(TEST_OUT9, "wb")) == NULL) {
		fprintf(stderr, "output file error..\n");
		exit(-1);
	}
	if ((fout[9] = fopen(TEST_OUT10, "wb")) == NULL) {
		fprintf(stderr, "output file error..\n");
		exit(-1);
	}
	if ((fout[10] = fopen(TEST_OUT11, "wb")) == NULL) {
		fprintf(stderr, "output file error..\n");
		exit(-1);
	}
	if ((fout[11] = fopen(TEST_OUT12, "wb")) == NULL) {
		fprintf(stderr, "output file error..\n");
		exit(-1);
	}

	tmpStr[0] = "\n";
	sprintf(tmpStr, DBG_PATH"AEC_Analysis");
	if (_access(tmpStr, 0) == -1)
		_mkdir(tmpStr);

	tmpStr[0] = "\n";
	sprintf(tmpStr, DBG_PATH"ACC_Analysis");
	if (_access(tmpStr, 0) == -1)
		_mkdir(tmpStr);

	tmpStr[0] = "\n";
	sprintf(tmpStr, DBG_PATH"CRNAnalysis");
	if (_access(tmpStr, 0) == -1)
		_mkdir(tmpStr);

	tmpStr[0] = "\n";
	sprintf(tmpStr, DBG_PATH"flagAnalysis");
	if (_access(tmpStr, 0) == -1)
		_mkdir(tmpStr);

	tmpStr[0] = "\n";
	sprintf(tmpStr, DBG_PATH"inEarAnalysis");
	if (_access(tmpStr, 0) == -1)
		_mkdir(tmpStr);

	tmpStr[0] = "\n";
	sprintf(tmpStr, DBG_PATH"MixerAnalysis");
	if (_access(tmpStr, 0) == -1)
		_mkdir(tmpStr);

	tmpStr[0] = "\n";
	sprintf(tmpStr, DBG_PATH"mmseAnalysis");
	if (_access(tmpStr, 0) == -1)
		_mkdir(tmpStr);

	tmpStr[0] = "\n";
	sprintf(tmpStr, DBG_PATH"TWS_GEV_Analysis");
	if (_access(tmpStr, 0) == -1)
		_mkdir(tmpStr);

#endif

#ifdef Debug_File_Write_C
	fp_chPwr = fopen(DBG_PATH"0_ch_power.txt", "w");
	fp_vad = fopen(DBG_PATH"1_vad.txt", "w");
	fp_aec = fopen(DBG_PATH"2_aec.txt", "w");
	fp_agc = fopen(DBG_PATH"3_agc.txt", "w");
	fp_bf = fopen(DBG_PATH"4_bf.txt", "w");
	fp_fft = fopen(DBG_PATH"5_fft_.txt", "w");
	fp_wnd = fopen(DBG_PATH"6_wnd.txt", "w");
	fp_mic_check = fopen(DBG_PATH"6_mic_check.txt", "w");


	f_aec[0] = fopen(DBG_PATH"AEC_Analysis\\inear_estimated_ec.raw", "wb");
	f_aec[1] = fopen(DBG_PATH"AEC_Analysis\\inear_aec_result.raw", "wb");
	f_aec[2] = fopen(DBG_PATH"AEC_Analysis\\inearAux_estimated_ec.raw", "wb");
	f_aec[3] = fopen(DBG_PATH"AEC_Analysis\\inearAux_aec_result.raw", "wb");

	f_acc[0] = fopen(DBG_PATH"ACC_Analysis\\Energy.bin", "wb");
	f_acc[1] = fopen(DBG_PATH"ACC_Analysis\\Energy_thd_onset.bin", "wb");
	f_acc[2] = fopen(DBG_PATH"ACC_Analysis\\Energy_thd_offset.bin", "wb");
	f_acc[3] = fopen(DBG_PATH"ACC_Analysis\\VAD.bin", "wb");

	f_acc_ns[0] = fopen(DBG_PATH"ACC_Analysis\\input.bin", "wb");
	f_acc_ns[1] = fopen(DBG_PATH"ACC_Analysis\\Npsd.bin", "wb");
	f_acc_ns[2] = fopen(DBG_PATH"ACC_Analysis\\SNR.bin", "wb");
	f_acc_ns[3] = fopen(DBG_PATH"ACC_Analysis\\Gain.bin", "wb");

	fCRN_speechLogSpec = fopen(DBG_PATH"CRNAnalysis\\speechLogSpec.bin", "wb");
	fCRN_noiseLogSpec = fopen(DBG_PATH"CRNAnalysis\\noiseLogSpec.bin", "wb");
	fCRN_estMask = fopen(DBG_PATH"CRNAnalysis\\estMask.bin", "wb");

	f_flag[0] = fopen(DBG_PATH"flagAnalysis\\input.bin", "wb");
	f_flag[1] = fopen(DBG_PATH"flagAnalysis\\Energy.bin", "wb");
	f_flag[2] = fopen(DBG_PATH"flagAnalysis\\Onset.bin", "wb");
	f_flag[3] = fopen(DBG_PATH"flagAnalysis\\Offset.bin", "wb");

	f_flag[4] = fopen(DBG_PATH"flagAnalysis\\EnhSigE.bin", "wb");
	f_flag[5] = fopen(DBG_PATH"flagAnalysis\\NoisySigE.bin", "wb");
	f_flag[6] = fopen(DBG_PATH"flagAnalysis\\NoiseOnset.bin", "wb");

	f_inEar[0] = fopen(DBG_PATH"inEarAnalysis\\SNR.bin", "wb");
	f_inEar[1] = fopen(DBG_PATH"inEarAnalysis\\Npsd.bin", "wb");
	f_inEar[2] = fopen(DBG_PATH"inEarAnalysis\\SNR_threshold.bin", "wb");
	f_inEar[3] = fopen(DBG_PATH"inEarAnalysis\\TxVAD.bin", "wb");
	f_inEar[4] = fopen(DBG_PATH"inEarAnalysis\\inEarInput.bin", "wb");
	f_inEar[5] = fopen(DBG_PATH"inEarAnalysis\\enhancedOutput.bin", "wb");
	f_inEar[6] = fopen(DBG_PATH"inEarAnalysis\\enhancedOutputWithGain.bin", "wb");
	f_inEar[7] = fopen(DBG_PATH"inEarAnalysis\\gain.bin", "wb");
	f_inEar[8] = fopen(DBG_PATH"inEarAnalysis\\maxPowerIndex.bin", "wb");
	f_inEar[9] = fopen(DBG_PATH"inEarAnalysis\\Update.bin", "wb");

	f_mixer[0] = fopen(DBG_PATH"MixerAnalysis\\BFOut.bin", "wb");
	f_mixer[1] = fopen(DBG_PATH"MixerAnalysis\\SNR.bin", "wb");
	f_mixer[2] = fopen(DBG_PATH"MixerAnalysis\\InEarMask.bin", "wb");
	f_mixer[3] = fopen(DBG_PATH"MixerAnalysis\\ReliableFreq.bin", "wb");

	f_echo_mix[0] = fopen(DBG_PATH"MixerAnalysis\\InEarBFSpec.bin", "wb");
	f_echo_mix[1] = fopen(DBG_PATH"MixerAnalysis\\RxSpec.bin", "wb");
	f_echo_mix[2] = fopen(DBG_PATH"MixerAnalysis\\Mask.bin", "wb");
	f_echo_mix[3] = fopen(DBG_PATH"MixerAnalysis\\echoMixGain.bin", "wb");

	f_mmse[0] = fopen(DBG_PATH"mmseAnalysis\\input.bin", "wb");
	f_mmse[1] = fopen(DBG_PATH"mmseAnalysis\\Npsd.bin", "wb");
	f_mmse[2] = fopen(DBG_PATH"mmseAnalysis\\SNR.bin", "wb");
	f_mmse[3] = fopen(DBG_PATH"mmseAnalysis\\SPP.bin", "wb");
	f_mmse[4] = fopen(DBG_PATH"mmseAnalysis\\NoiseLevel.bin", "wb");
	f_mmse[5] = fopen(DBG_PATH"mmseAnalysis\\NpsdSum.bin", "wb");

	f_tws_gev[0] = fopen(DBG_PATH"TWS_GEV_Analysis\\speechMask.bin", "wb");
	f_tws_gev[1] = fopen(DBG_PATH"TWS_GEV_Analysis\\noiseMask.bin", "wb");
	f_tws_gev[2] = fopen(DBG_PATH"TWS_GEV_Analysis\\GainForInEarOut.bin", "wb");
	f_tws_gev[3] = fopen(DBG_PATH"TWS_GEV_Analysis\\GainForInEarBM.bin", "wb");
	f_tws_gev[4] = fopen(DBG_PATH"TWS_GEV_Analysis\\MaskSumX.bin", "wb");
	f_tws_gev[5] = fopen(DBG_PATH"TWS_GEV_Analysis\\MaskSumN.bin", "wb");

#endif

	if ((fid_outer1 == NULL) || (fid_outer2 == NULL) || (fid_inner == NULL) || (fid_rx == NULL) || (fid_acc == NULL) || (fout == NULL))
		return -1;

	// Init
	SV_Frame_Init(16000);

	while (1)// (framenum<3)
	{
		frmCnt++;
		int Nframe;

		printf("frame %d\n", framenum++);

		Nframe = fread(readbuf, sizeof(short), BUFSIZE, fid_outer1);
		if (Nframe <= 0) break;
		ShortToInt(readbuf_outer1_32, readbuf, Nframe);

		Nframe = fread(readbuf, sizeof(short), BUFSIZE, fid_outer2);
		if (Nframe <= 0) break;
		ShortToInt(readbuf_outer2_32, readbuf, Nframe);

		Nframe = fread(readbuf, sizeof(short), BUFSIZE, fid_inner);
		if (Nframe <= 0) break;
		ShortToInt(readbuf_inner_32, readbuf, Nframe);

		Nframe = fread(readbuf, sizeof(short), BUFSIZE, fid_rx);
		if (Nframe <= 0) break;
		ShortToInt(readbuf_rx_32, readbuf, Nframe);

		Nframe = fread(readbuf, sizeof(short), BUFSIZE, fid_acc);
		if (Nframe <= 0) break;
		ShortToInt(readbuf_acc_32, readbuf, Nframe);

		SV_Frame_Exe(writebuf_32, readbuf_outer1_32, readbuf_outer2_32, readbuf_inner_32, readbuf_rx_32, readbuf_acc_32, Nframe);

		IntToShort(writebuf, writebuf_32, Nframe * OUT_SIZE);

		fwrite(writebuf, sizeof(short), Nframe, fout[0]);
#ifdef BSH_DEBUG
		for (i = 1; i < OUT_SIZE; i++)
		{
			fwrite(writebuf + FRAME_SIZE * i, sizeof(short), FRAME_SIZE, fout[i]);
		}
#endif
		
		//if(frmCnt==100) break;
	}

	SV_Frame_Deinit();


	fclose(fid_outer1);
	fclose(fid_outer2);
	fclose(fid_inner);
	fclose(fid_rx);
	fclose(fid_acc);
	for (i = 0; i < OUT_SIZE; i++) fclose(fout[i]);

#ifdef Debug_File_Write_C
	fclose(fp_chPwr);
	fclose(fp_vad);
	fclose(fp_aec);
	fclose(fp_agc);
	fclose(fp_bf);
	fclose(fp_fft);
	fclose(fp_wnd);
	fclose(fp_mic_check);

	fclose(f_aec[0]);
	fclose(f_aec[1]);
	fclose(f_aec[2]);
	fclose(f_aec[3]);

	fclose(f_acc[0]);
	fclose(f_acc[1]);
	fclose(f_acc[2]);
	fclose(f_acc[3]);

	fclose(f_acc_ns[0]);
	fclose(f_acc_ns[1]);
	fclose(f_acc_ns[2]);
	fclose(f_acc_ns[3]);

	fclose(fCRN_speechLogSpec);
	fclose(fCRN_noiseLogSpec);
	fclose(fCRN_estMask);

	for (i = 0; i < 7; i++)
		fclose(f_flag[i]);

	for (i = 0; i < 10; i++)
		fclose(f_inEar[i]);

	for (i = 0; i < 4; i++)
		fclose(f_mixer[i]);

	for (i = 0; i < 4; i++)
		fclose(f_echo_mix[i]);

	for (i = 0; i < 6; i++)
		fclose(f_mmse[i]);

	fclose(f_tws_gev[0]);
	fclose(f_tws_gev[1]);
	fclose(f_tws_gev[2]);
	fclose(f_tws_gev[3]);
	fclose(f_tws_gev[4]);
	fclose(f_tws_gev[5]);
#endif

	return 1;
}

