#include <stdio.h>
#include <math.h>
#include <fftw3.h>
#include <limits.h>

#define FFT_SIZE 512
#define FRAME_SIZE 320
#define OUT_FILE_PCM "input.raw"
#define OUT_FILE_FFT "fft.raw"


struct fd_nc_data
{
	size_t fft_buf_size;
	fftw_plan fft_plan;
	fftw_complex *fft_buf;

	double mainFrame[FRAME_SIZE];
	double subFrame[FRAME_SIZE];

};

void test_fd_nc_init(fd_nc_data *fd_nc_d)
{
	size_t fft_buf_size = sizeof(fftw_complex) * FRAME_SIZE;
	fd_nc_d->fft_buf_size = fft_buf_size;
	
	fft_buf = (fftw_complex*) fftw_malloc( fft_buf_size );
	fft_buf = (fftw_complex*) fftw_malloc( fft_buf_size );
	
	// -------------------------------------------------------
	// FFTW Read -> Complex
	// -------------------------------------------------------
	fd_nc_d->fft_plan = fftw_plan_dft_r2c_1d(FRAME_SIZE, fd_nc_d->mainFrame, fft_buf, FFTW_ESTIMATE);
	fd_nc_d->fft_plan = fftw_plan_dft_r2c_1d(FRAME_SIZE, fd_nc_d->subFrame,  fft_buf, FFTW_ESTIMATE);
	
}

void test_fd_nc_proc(fd_nc_data *fd_nc_d)
{
	
	// fft exec time sig -> freq sig
	fftw_execute(plan_r2c);
	

}



int main (int argc, char *argv[])
{
	FILE *fhMainIn;
	FILE *fhSubIn;

	if( NULL == (fhMainIn = fopen("main.pcm", "wb") ) )
	{
		printf("file open error main pcm\n");
	}

	if( NULL == (fhSubIn = fopen("sub.pcm", "wb") ) )
	{
		printf("file open error main pcm\n");
	}

	// -- FFTW file IO
	FILE *fhOutPcm = NULL;
	FILE *fhOutFft = NULL;
	
	if((fhOutPcm = fopen(OUT_FILE_PCM, "wb")) == NULL) {
		printf("file open error : %s", OUT_FILE_PCM);
		return 1;
	}

	if((fhOutFft = fopen(OUT_FILE_FFT, "wb")) == NULL) {
		printf("file open error : %s", OUT_FILE_FFT);
		return 1;
	}
	
	short mainPcm[FRAME_SIZE];
	short subPcm[FRAME_SIZE];
	
	// FFTW  time sig -> freq sig -> time sig 
	double *sig1 = new double[FRAME_SIZE];
	double *sig2 = new double[FRAME_SIZE];

	// -------------------------------------------------------
	// create input data sig1
	// -------------------------------------------------------
	for(int i = 0; i < FRAME_SIZE; i++) {
		sig1[i] = sin( 2 * M_PI * i / FRAME_SIZE ) * 0.5 + sin( 44 * M_PI * i / FRAME_SIZE ) * 0.5;
	}

	// -------------------------------------------------------
	// FFTW buffers
	// -------------------------------------------------------
	size_t fft_buf_size = sizeof(fftw_complex) * FRAME_SIZE;
	fftw_plan plan_r2c    = NULL;
	fftw_plan plan_c2r    = NULL;
	
	fftw_complex *fft_buf = NULL;
	fft_buf = (fftw_complex*) fftw_malloc( fft_buf_size );

	// -------------------------------------------------------
	// FFTW Read -> Complex
	// -------------------------------------------------------
	plan_r2c = fftw_plan_dft_r2c_1d(FRAME_SIZE, sig1, fft_buf, FFTW_ESTIMATE);
	
	// fft exec time sig -> freq sig
	fftw_execute(plan_r2c);


	fd_nc_data nc_data;
	
	test_fd_nc_init(&nc_data);
	

	while ( ( NULL != fread(mainPcm, sizeof(short), FRAME_SIZE, fhMainIn) ) &&
			( NULL != fread(subPcm, sizeof(short), FRAME_SIZE, fhSubIn) ) )
	{
		//
		for ( int i = 0; i < FRAME_SIZE; i++ )
		{
			nc_data.mainFrame = (double) mainPcm[ i ];
			nc_data.subFrame  = (double) subPcm[ i ];
		}
		test_fd_nc_proc(&nc_data);

		for ( int i = 0; i < FRAME_SIZE; i++ )
		{

		}
	}

	// -------------------------------------------------------
	// FFTW Complex -> Real
	// -------------------------------------------------------
	plan_c2r = fftw_plan_dft_c2r_1d(FRAME_SIZE, fft_buf, sig2, FFTW_ESTIMATE);
	fftw_execute(plan_c2r);

	// -------------------------------------------------------
	// print signal data
	// -------------------------------------------------------
	printf("num\tsig1\t\tsig2\t\treal\t\timag\n");
	for(int i = 0; i < FRAME_SIZE; i++) {
		printf("%d\t%lf\t%lf\t%lf\t%lf\n", i, sig1[i], sig2[i] / FRAME_SIZE
		                                 , fft_buf[i][0], fft_buf[i][1]);
	}

	// -------------------------------------------------------
	// debug out 
	// -------------------------------------------------------
	short *tmps = new short[FRAME_SIZE];
	
	for(int i = 0; i < FRAME_SIZE; i++) {
		tmps[i] = (short) (fft_buf[i][0] / FRAME_SIZE * SHRT_MAX);
	}
	fwrite(tmps, sizeof(short), FRAME_SIZE, fhOutFft);
	fclose(fhOutFft);
	
	for(int i = 0; i < FRAME_SIZE; i++) {
		tmps[i] = (short) (sig1[i] * SHRT_MAX);
	}
	fwrite(tmps, sizeof(short), FRAME_SIZE, fhOutPcm);
	fclose(fhOutPcm);
	// ----- debug out [end]

	if(sig1) {
		delete[] sig1;
	}
	
	if(sig2) {
		delete[] sig2;
	}

	if(plan_r2c) {
		fftw_destroy_plan(plan_r2c);
	}

	if(fft_buf) {
		fftw_free(fft_buf);
	}

	
	while( ( fread( mainPcm, FRAME_SIZE, sizeof(short), fhMainIn ) == FRAME_SIZE ) &&
		   ( fread( subPcm,  FRAME_SIZE, sizeof(short), fhSubIn  ) == FRAME_SIZE ) )
	{
		// FFT


		// 


	}
	
	

	return 0;
}
