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


#define RT_SAMPLE_LENGTH 1000
#define NHALF RT_SAMPLE_LENGTH/2

#define ERR_THRESHOLD 1000000  // Min power freq to accept a freq as local maximum
#define FREQ_MAXDEV 0.10	//Percentage of freq desviaion to be recognized

#define FREQ_ZERO 2000
#define FREQ_ZERO_MIN FREQ_ZERO-(FREQ_ZERO*FREQ_MAXDEV)
#define FREQ_ZERO_MAX FREQ_ZERO+(FREQ_ZERO*FREQ_MAXDEV)


#define FREQ_ONE 5000
#define FREQ_ONE_MIN FREQ_ONE-(FREQ_ONE*FREQ_MAXDEV)
#define FREQ_ONE_MAX FREQ_ONE+(FREQ_ONE*FREQ_MAXDEV)

#define FREQ_SEPARATION 7000
#define FREQ_SEPARATION_MIN FREQ_SEPARATION-(FREQ_SEPARATION*FREQ_MAXDEV)
#define FREQ_SEPARATION_MAX FREQ_SEPARATION+(FREQ_SEPARATION*FREQ_MAXDEV)

#define FREQ_NEWFILE 12000
#define FREQ_NEWFILE_MIN FREQ_NEWFILE-(FREQ_NEWFILE*FREQ_MAXDEV)
#define FREQ_NEWFILE_MAX FREQ_NEWFILE+(FREQ_NEWFILE*FREQ_MAXDEV)

#define ORIG_SAMPLERATE 44100
#define BANDWIDTH ORIG_SAMPLERATE/2
#define SCALE_PONDERATION (double)ORIG_SAMPLERATE/ (double)RT_SAMPLE_LENGTH

#define MIN_COUNT_ACCEPT 10

// Files must be 44100, 16bit wav files

int main(int argc, char *argv[]) {
	FILE *input_file;
	int v,m,i;
	double maxval,maxpos;
	double curpos,absval;
	double last_freq=0;
	int count_repeat=MIN_COUNT_ACCEPT;
	int in_value,in_value_2b;
	static double *in_data = NULL, *out_data = NULL;
	static fftw_plan plan;
	char tmp[50];
	int position=0;
	int final_value;
	
	if (argc < 2 ) {
		printf ("Ussage ./ssss file.wav");
		return 1;
	}
	input_file = fopen(argv[1], "r");
	
	// skip  the wav file header
	fgets(tmp,37,input_file);
	fgets(tmp,9,input_file);

	//in_data input real data from wavfile
	in_data = (double *)fftw_malloc(RT_SAMPLE_LENGTH * sizeof(double));
	//out_data where the output will reside
	out_data = (double *)fftw_malloc(RT_SAMPLE_LENGTH * sizeof(double));
	// r to r fft 
	plan = fftw_plan_r2r_1d(RT_SAMPLE_LENGTH, in_data, out_data, FFTW_R2HC, FFTW_FORWARD); 
	
	//Vector that will hold the final binary number
	position =0;
	for (i = 0; i < 50 ; i++) tmp[i]=0;	
	int stop=0;
	long double power_org=0;
	long double power_fft=0;
	while (stop==0) {
		// read data and fill "A"-array
		for (v=0;v<RT_SAMPLE_LENGTH;v++) {
			in_value = fgetc(input_file);
			if (in_value == EOF) {
				stop=1;
				break;
			}
			in_value_2b = fgetc(input_file);
			if (in_value_2b > 127) { in_value_2b = in_value_2b - 255; }
			in_data[v] = 256*in_value_2b  + in_value;
			//power_org=power_org+pow(in_data[v],2);
		}
		//printf ("POWER ORIG: %d \n",power_org);
		
		fftw_execute(plan);
	
		m = 0;
		maxval=0;
		maxpos=0;
		for (i = 0; i < (RT_SAMPLE_LENGTH-2); i++) {
			//absval = sqrt(pow(in_data[i],2) + pow(out_data[i],2));
			//absval = sqrt(pow(out_data[i],2) + pow(out_data[i],2));
			absval = sqrt(out_data[i] * out_data[i]);
			//power_fft = power_fft + pow ( absval, 2);
			curpos = (double)m * SCALE_PONDERATION;
			if (absval>maxval && curpos < BANDWIDTH){ 
				maxval=absval;
				maxpos=curpos;
			}
			m++;
		}

		//printf ("POWERFFT: %d \n",power_fft);
		if (maxval>ERR_THRESHOLD) { 
			//printf ("Maximum at freq:%f, %f\n",maxpos,maxval);
			if ( maxpos > FREQ_ONE_MIN && maxpos < FREQ_ONE_MAX ) {
				if (last_freq != FREQ_ONE ) {
					count_repeat--;
					if (count_repeat == 0 ) {
						count_repeat = MIN_COUNT_ACCEPT;
						last_freq = FREQ_ONE;
						tmp[position]=1;
						position++;
						//printf ("ONE\n");
					}
					
	
				}
				
			}
			if ( maxpos > FREQ_ZERO_MIN && maxpos < FREQ_ZERO_MAX ) {
				if (last_freq != FREQ_ZERO ) {
					count_repeat--;
                                        if (count_repeat == 0 ) {
                                                count_repeat = MIN_COUNT_ACCEPT;
						last_freq = FREQ_ZERO;
						//printf ("ZERO\n");
						tmp[position]=0;
						position++;
					}
				}
			}
			if ( maxpos > FREQ_SEPARATION_MIN && maxpos < FREQ_SEPARATION_MAX ) {
				if (last_freq != FREQ_SEPARATION ){
					count_repeat--;
                                        if (count_repeat == 0 ) {
                                                count_repeat = MIN_COUNT_ACCEPT;
						last_freq = FREQ_SEPARATION;
						//printf ("SEPARATION\n");
					}
				}
			}
			if ( maxpos > FREQ_NEWFILE_MIN && maxpos < FREQ_NEWFILE_MAX ) {
				if (last_freq != FREQ_NEWFILE ){
					count_repeat--;
                                        if (count_repeat == 0 ) {
                                                count_repeat = MIN_COUNT_ACCEPT;
						last_freq = FREQ_NEWFILE;
						//printf ("NEWFILE\n");
					}
				}
			}
		}
	}
	// housekeeping
	fclose(input_file);
	fftw_destroy_plan(plan);
	fftw_free(in_data);
	fftw_free(out_data);

	final_value=0;
	for (i=0;i<position;i++){ 
		final_value = final_value + tmp[i]*(1<<(position-i-1)); 	
	}
	printf ("%d\n",final_value);

	return 0;
}

