/* SigLib FFT and Hanning window Example */

/* Include files */

#include <stdio.h>
#include <siglib.h>
#include "GraphFunctions.h"

/* Define constants */
#define	FFT_SIZE		((SLArrayIndex_t)512)
#define	LOG_FFT_SIZE	((SLArrayIndex_t)9)
#define	WINDOW_SIZE		FFT_SIZE

/* Declare global variables */
SLData_t	*pRealData, *pImagData, *pRealDataCopy, *pImagDataCopy, *pWindowCoeffs, *pResults, *pFFTCoeffs;
SLData_t	SinePhase;

void main(void)
{
	GraphObject *h2DGraph;							/* Declare graph object */

													/* Allocate memory */
	pRealData = SUF_VectorArrayAllocate (FFT_SIZE);
	pImagData = SUF_VectorArrayAllocate (FFT_SIZE);
	pRealDataCopy = SUF_VectorArrayAllocate (FFT_SIZE);
	pImagDataCopy = SUF_VectorArrayAllocate (FFT_SIZE);
	pFFTCoeffs = SUF_FftCoefficientAllocate (FFT_SIZE);
	pResults = SUF_VectorArrayAllocate (FFT_SIZE);			/* RMS result array */
	pWindowCoeffs = SUF_VectorArrayAllocate (WINDOW_SIZE);	/* Window array */

	SinePhase = SIGLIB_ZERO;
	SDA_SignalGenerate (pRealData,					/* Pointer to destination array */
						SIGLIB_SINE_WAVE,			/* Signal type - Sine wave */
						((SLData_t)0.9),			/* Signal peak level */
						SIGLIB_FILL,				/* Fill (overwrite) or add to existing array contents */
						((SLData_t)0.015625),		/* Signal frequency */
						SIGLIB_ZERO,				/* D.C. Offset */
						SIGLIB_ZERO,				/* Unused */
						SIGLIB_ZERO,				/* Signal end value - Unused */
						&SinePhase,					/* Signal phase - maintained across array boundaries */
						SIGLIB_NULL_DATA_PTR ,		/* Unused */
						FFT_SIZE);					/* Output array length */

	h2DGraph =										/* Initialize graph */
		Create2DGraph ("Fast Fourier Transform",	/* Graph title */
					   "Time",						/* X-Axis label */
					   "Magnitude",					/* Y-Axis label */
					   SV_AUTO_SCALE,				/* Scaling mode */
					   SV_SIGNED,					/* Sign mode */
					   SV_GRAPH_LINE,				/* Graph type */
					   "localhost");				/* Graph server */
	if (h2DGraph == NULL)							/* Graph creation failed - e.g is server running ? */
	{
		printf ("\nGraph creation failure. Please check that the server is running\n");
		exit (1);
	}

													/* Initialise FFT */
	SIF_Fft (pFFTCoeffs,							/* Pointer to FFT coefficients */
			 SIGLIB_NULL_ARRAY_INDEX_PTR,			/* Pointer to bit reverse address table - NOT USED */
			 FFT_SIZE);								/* FFT Size */

	Display2DGraph (h2DGraph,						/* Graph handle */
				    "Synthesized sine wave",		/* Title of the dataset */
				    pRealData,						/* Array of Double dataset */
				    FFT_SIZE,						/* Number of data points */
					SV_GRAPH_LINE,					/* Graph type */
				    SV_MAGENTA,						/* Colour */
					SV_HIDE_MARKERS,				/* Marker enable / disable */
					SV_GRAPH_NEW);					/* New graph */
	printf ("\nSynthesized sine wave\nPlease hit <Carriage Return> to continue . . ."); getchar ();

													/* Perform real FFT */
	SDA_Rfft (pRealData,							/* Pointer to real array */
			  pImagData,							/* Pointer to imaginary array */
			  pFFTCoeffs,							/* Pointer to FFT coefficients */
			  SIGLIB_NULL_ARRAY_INDEX_PTR,			/* Pointer to bit reverse address table - NOT USED */
			  FFT_SIZE,								/* FFT size */
			  LOG_FFT_SIZE);						/* log2 FFT size */

	SDA_Copy (pRealData,							/* Pointer to source array */
			  pRealDataCopy,						/* Pointer to destination array */
			  FFT_SIZE);							/* Array length */
	SDA_Copy (pImagData,							/* Pointer to source array */
			  pImagDataCopy,						/* Pointer to destination array */
			  FFT_SIZE);							/* Array length */

													/* Calculate real power from complex */
	SDA_LogMagnitude (pRealData,					/* Pointer to real source array */
					  pImagData,					/* Pointer to imaginary source array */
					  pResults,						/* Pointer to log magnitude destination array */
					  FFT_SIZE);					/* Data array length */

	Display2DGraph (h2DGraph,						/* Graph handle */
				    "FFT of pure sine wave (integer number of bins)",	/* Title of the dataset */
				    pResults,						/* Array of Double dataset */
				    FFT_SIZE,						/* Number of data points */
					SV_GRAPH_LINE,					/* Graph type */
				    SV_BLUE,						/* Colour */
					SV_HIDE_MARKERS,				/* Marker enable / disable */
					SV_GRAPH_NEW);					/* New graph */
	printf ("\nFFT of pure sine wave (integer number of bins)\nPlease hit <Carriage Return> to continue . . ."); getchar ();

	SinePhase = SIGLIB_ZERO;
	SDA_SignalGenerate (pRealData,					/* Pointer to destination array */
						SIGLIB_SINE_WAVE,			/* Signal type - Sine wave */
						((SLData_t)0.9),			/* Signal peak level */
						SIGLIB_FILL,				/* Fill (overwrite) or add to existing array contents */
						((SLData_t)0.019),			/* Signal frequency */
						SIGLIB_ZERO,				/* D.C. Offset */
						SIGLIB_ZERO,				/* Unused */
						SIGLIB_ZERO,				/* Signal end value - Unused */
						&SinePhase,					/* Signal phase - maintained across array boundaries */
						SIGLIB_NULL_DATA_PTR ,		/* Unused */
						FFT_SIZE);					/* Output array length */

	Display2DGraph (h2DGraph,						/* Graph handle */
				    "Synthesized sine wave",		/* Title of the dataset */
				    pRealData,						/* Array of Double dataset */
				    FFT_SIZE,						/* Number of data points */
					SV_GRAPH_LINE,					/* Graph type */
				    SV_MAGENTA,						/* Colour */
					SV_HIDE_MARKERS,				/* Marker enable / disable */
					SV_GRAPH_NEW);					/* New graph */
	printf ("\nSynthesized sine wave\nPlease hit <Carriage Return> to continue . . ."); getchar ();

													/* Perform real FFT */
	SDA_Rfft (pRealData,							/* Pointer to real array */
			  pImagData,							/* Pointer to imaginary array */
			  pFFTCoeffs,							/* Pointer to FFT coefficients */
			  SIGLIB_NULL_ARRAY_INDEX_PTR,			/* Pointer to bit reverse address table - NOT USED */
			  FFT_SIZE,								/* FFT size */
			  LOG_FFT_SIZE);						/* log2 FFT size */

	SDA_Copy (pRealData,							/* Pointer to source array */
			  pRealDataCopy,						/* Pointer to destination array */
			  FFT_SIZE);							/* Array length */
	SDA_Copy (pImagData,							/* Pointer to source array */
			  pImagDataCopy,						/* Pointer to destination array */
			  FFT_SIZE);							/* Array length */

													/* Calculate real power from complex */
	SDA_LogMagnitude (pRealData,					/* Pointer to real source array */
					  pImagData,					/* Pointer to imaginary source array */
					  pResults,						/* Pointer to log magnitude destination array */
					  FFT_SIZE);					/* Data array length */

	Display2DGraph (h2DGraph,						/* Graph handle */
				    "FFT of pure sine wave (integer number of bins)",	/* Title of the dataset */
				    pResults,						/* Array of Double dataset */
				    FFT_SIZE,						/* Number of data points */
					SV_GRAPH_LINE,					/* Graph type */
				    SV_BLUE,						/* Colour */
					SV_HIDE_MARKERS,				/* Marker enable / disable */
					SV_GRAPH_NEW);					/* New graph */
	printf ("\nFFT of pure sine wave (integer number of bins)\nPlease hit <Carriage Return> to continue . . ."); getchar ();

	SinePhase = SIGLIB_ZERO;
	SDA_SignalGenerate (pRealData,					/* Pointer to destination array */
						SIGLIB_COS_WAVE,			/* Signal type - Cosine wave */
						((SLData_t)0.9),			/* Signal peak level */
						SIGLIB_FILL,				/* Fill (overwrite) or add to existing array contents */
						((SLData_t)0.0078125),		/* Signal frequency */
						SIGLIB_ZERO,				/* D.C. Offset */
						SIGLIB_ZERO,				/* Unused */
						SIGLIB_ZERO,				/* Signal end value - Unused */
						&SinePhase,					/* Signal phase - maintained across array boundaries */
						SIGLIB_NULL_DATA_PTR ,		/* Unused */
						FFT_SIZE);					/* Output array length */

	Display2DGraph (h2DGraph,						/* Graph handle */
				    "Hanning windowed sine wave",	/* Title of the dataset */
				    pRealData,						/* Array of Double dataset */
				    FFT_SIZE,						/* Number of data points */
					SV_GRAPH_LINE,					/* Graph type */
				    SV_MAGENTA,						/* Colour */
					SV_HIDE_MARKERS,				/* Marker enable / disable */
					SV_GRAPH_NEW);					/* New graph */
	printf ("\nHanning windowed sine wave\nPlease hit <Carriage Return> to continue . . ."); getchar ();

													/* Generate Hanning window table */
	SIF_Window (pWindowCoeffs,						/* Pointer to window oefficient */
				SIGLIB_HANNING,						/* Window type */
				SIGLIB_ZERO,						/* Window coefficient */
				FFT_SIZE);							/* Window length */
													/* Apply window to real data */
													/* Apply window to data */
	SDA_Window (pRealData,							/* Pointer to source array */
				pRealData,							/* Pointer to destination array */
				pWindowCoeffs,						/* Pointer to window oefficients */
				WINDOW_SIZE);						/* Window length */

	Display2DGraph (h2DGraph,						/* Graph handle */
				    "Hanning windowed sine wave",	/* Title of the dataset */
				    pRealData,						/* Array of Double dataset */
				    FFT_SIZE,						/* Number of data points */
					SV_GRAPH_LINE,					/* Graph type */
				    SV_MAGENTA,						/* Colour */
					SV_HIDE_MARKERS,				/* Marker enable / disable */
					SV_GRAPH_NEW);					/* New graph */
	printf ("\nHanning windowed sine wave\nPlease hit <Carriage Return> to continue . . ."); getchar ();

													/* Perform real FFT */
	SDA_Rfft (pRealData,							/* Pointer to real array */
			  pImagData,							/* Pointer to imaginary array */
			  pFFTCoeffs,							/* Pointer to FFT coefficients */
			  SIGLIB_NULL_ARRAY_INDEX_PTR,			/* Pointer to bit reverse address table - NOT USED */
			  FFT_SIZE,								/* FFT size */
			  LOG_FFT_SIZE);						/* log2 FFT size */

	SDA_Copy (pRealData,							/* Pointer to source array */
			  pRealDataCopy,						/* Pointer to destination array */
			  FFT_SIZE);							/* Array length */
	SDA_Copy (pImagData,							/* Pointer to source array */
			  pImagDataCopy,						/* Pointer to destination array */
			  FFT_SIZE);							/* Array length */

	SDA_CfftShift (pRealData, pImagData, pRealData, pImagData, FFT_SIZE);	/* Shift D.C. location */
													/* Calculate real power from complex */
	SDA_LogMagnitude (pRealData,					/* Pointer to real source array */
					  pImagData,					/* Pointer to imaginary source array */
					  pResults,						/* Pointer to log magnitude destination array */
					  FFT_SIZE);					/* Data array length */

	Display2DGraph (h2DGraph,						/* Graph handle */
				    "FFT of windowed sine wave (dB), non integer # of bins, D.C. Shifted",		/* Title of the dataset */
				    pResults,						/* Array of Double dataset */
				    FFT_SIZE,						/* Number of data points */
					SV_GRAPH_LINE,					/* Graph type */
				    SV_BLUE,						/* Colour */
					SV_HIDE_MARKERS,				/* Marker enable / disable */
					SV_GRAPH_NEW);					/* New graph */
	printf ("\nFFT of windowed sine wave (dB), non integer # of bins, D.C. Shifted\nPlease hit <Carriage Return> to continue . . ."); getchar ();

	SDA_Cifft (pRealDataCopy, pImagDataCopy, pFFTCoeffs, SIGLIB_NULL_ARRAY_INDEX_PTR, FFT_SIZE, LOG_FFT_SIZE);	/* Perform inverse FFT */

	Display2DGraph (h2DGraph,						/* Graph handle */
				    "IFFT done",					/* Title of the dataset */
				    pRealDataCopy,					/* Array of Double dataset */
				    FFT_SIZE,						/* Number of data points */
					SV_GRAPH_LINE,					/* Graph type */
				    SV_MAGENTA,						/* Colour */
					SV_HIDE_MARKERS,				/* Marker enable / disable */
					SV_GRAPH_NEW);					/* New graph */
	printf ("\nIFFT done\n");

	SUF_MemoryFree (pRealData);						/* Free memory */
	SUF_MemoryFree (pImagData);
	SUF_MemoryFree (pRealDataCopy);
	SUF_MemoryFree (pImagDataCopy);
	SUF_MemoryFree (pResults);
	SUF_MemoryFree (pWindowCoeffs);
	SUF_MemoryFree (pFFTCoeffs);
}


