#include <v_lib.h>

#define	SAMPLE_RATE (11025)

/*
 *	TODO: use phase offset to generate both real and imaginary parts
 */
 
V_LOCAL	void
GenerateSines(
	vec_t *ReOut,
	u32_t samples,
	u32_t channels,
	vec_t freqs[],vec_t volumes[],vec_t *phase_info)
{
	u32_t s,c;
	vec_t out;
	vec_t *phase=(vec_t*)memAlloc(channels * sizeof(vec_t));
	vec_t *dph=(vec_t*)memAlloc(channels * sizeof(vec_t));
	vec_t *amp=(vec_t*)memAlloc(channels * sizeof(vec_t));
	if(phase_info)
		memCopy(phase,phase_info,channels * sizeof(vec_t));
	else
		memZero(phase,channels * sizeof(vec_t));
	for(c=0;c<channels;c++)
	{
		amp[c] = volumes[c] / (vec_t)channels;
		dph[c] = M_2PI * freqs[c] / (vec_t)SAMPLE_RATE;
	}
	for(s=0;s<samples;s++)
	{
		out = 0;
		for(c=0;c<channels;c++)
		{
			out += amp[c] * (vec_t)sin(phase[c]);
			phase[c]+=dph[c];
		}
		if(out < -1)
			out = -1;
		else
			if(out > 1)
				out = 1;
		ReOut[s]=out;
	}
	if(phase_info)
		memCopy(phase_info,phase,channels * sizeof(vec_t));
	memFree(phase);
	memFree(dph);
	memFree(amp);
}

V_LOCAL	void
DumpSignal(FILE *out,vec_t *Re,vec_t *Im,int nsamples,vboolean pwr_only)
{
	int i;
	if(pwr_only)
	{
		for(i=0;i<nsamples;i++)
			fprintf(out,"%8u\t%g\n",
				i,sqrt(Re[i]*Re[i]+Im[i]*Im[i]));
	}
	else
	{
		for(i=0;i<nsamples;i++)
			fprintf(out,"%8u\t%g\t%g\n",i,Re[i],Im[i]);
	}
}

int main()
{
	u32_t start;
	unsigned p=14;
	unsigned len=1 << p;
	vec_t *Re,*Im,*ReOut,*ImOut,freqs[10],volumes[10];
	Re=(vec_t*)memAlloc(len*sizeof(vec_t));
	Im=(vec_t*)memAlloc(len*sizeof(vec_t));
	
	freqs[0]=100;
	volumes[0]=0.5f;
	freqs[1]=300;
	volumes[1]=0.25f;
	freqs[2]=900;
	volumes[2]=0.05f;
	GenerateSines(Re,len,3,freqs,volumes,NULL);
	memZero(Im,len*sizeof(vec_t));

	/* DumpSignal(stdout,Re,Im,len,false); */
		
	ReOut=(vec_t*)memAlloc(len*sizeof(vec_t));
	ImOut=(vec_t*)memAlloc(len*sizeof(vec_t));

	puts("FFT");

	start=timeTickCount();
	fftCalcNip(ReOut,ImOut,Re,Im,p,1);
	start=timeTickCount() - start;
	DumpSignal(stdout,ReOut,ImOut,len,true);
	printf("Done: %u ms\n",(unsigned int)start);

	memFree(Re);
	memFree(Im);
	memFree(ReOut);
	memFree(ImOut);
	return 0;
}

