/* SigLib Example to Compare The Output Scaling Of The DFT And FFT Functions */

/* 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)

/* Declare global variables */
SLData_t	*pSrcData, *pRealData, *pImagData, *pFFTCoeffs;
SLData_t	SinePhase;

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

	pSrcData = SUF_VectorArrayAllocate (FFT_SIZE);				/* Allocate memory */
	pRealData = SUF_VectorArrayAllocate (FFT_SIZE);
	pImagData = SUF_VectorArrayAllocate (FFT_SIZE);
	pFFTCoeffs = SUF_FftCoefficientAllocate (FFT_SIZE);

	printf ("\n\nA very common question in DSP is :\n\n");
	printf ("\"why does the FFT give different resutls to the DFT ?\"\n\n");
	printf ("The answer is that the difference is just the scaling of the results and it\n");
	printf ("due to the efficient nature of the FFT.\n");
	printf ("This example program attempts to show the differences by performing a DFT and\n");
	printf ("an FFT on the same input data. When you run the program you will notice that\n");
	printf ("the FFT results are much larger than those of the DFT. In fact they are N\n");
	printf ("times larger than the DFT results, where N is the size of the FFT.\n");
	printf ("In order to overcome this it is necessary to scale the results of theFFT to\n");
	printf ("match those of the DFT. In many DSP applications (especially fixed point)\n");
	printf (", scaling is a system level issue and for that reason Numerix has decided not\n");
	printf ("to scale the output right after performing the FFT but to leave it to the\n");
	printf ("developer to decide where is the most appropriate place to locate the scaling\n");
	printf ("for his or her application.\n\n");
	printf ("This issue is discussed in further detail within the SigLib documentation.\n\n");
	printf ("Please hit <CR> to continue . . .");
	getchar ();

	h2DGraph =										/* Initialize graph */
		Create2DGraph ("Discrete / Fast Fourier Transforms",	/* Graph title */
					   "Frequency",					/* 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);
	}

													/* Create sine wave with suitable freq to avoid edge effects */
	SinePhase = SIGLIB_ZERO;
	SDA_SignalGenerate (pSrcData,					/* Pointer to destination array */
						SIGLIB_SINE_WAVE,			/* Signal type - Sine wave */
						((SLData_t)1.0),			/* Signal peak level */
						SIGLIB_FILL,				/* Fill (overwrite) or add to existing array contents */
						((SLData_t)(1.0/16.0)),		/* 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 */
				    pSrcData,						/* 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 DFT */
	SDA_Rft (pSrcData,								/* Pointer to real source array */
			 pRealData,								/* Pointer to real destination array */
			 pImagData,								/* Pointer to imaginary destination array */
			 FFT_SIZE);								/* Transform size */
													/* Calculate real magnitude from complex */
	SDA_Magnitude (pRealData,						/* Pointer to real source array */
				   pImagData,						/* Pointer to imaginary source array */
				   pRealData,						/* Pointer to magnitude destination array */
				   FFT_SIZE);						/* Array length */

	Display2DGraph (h2DGraph,						/* Graph handle */
				    "Discrete Fourier Transform Results",		/* 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 ("\nDiscrete Fourier Transform Results\nPlease hit <Carriage Return> to continue . . ."); getchar ();

													/* Create sine wave with suitable freq to avoid edge effects */
	SinePhase = SIGLIB_ZERO;
	SDA_SignalGenerate (pRealData,					/* Pointer to destination array */
						SIGLIB_SINE_WAVE,			/* Signal type - Sine wave */
						((SLData_t)1.0),			/* Signal peak level */
						SIGLIB_FILL,				/* Fill (overwrite) or add to existing array contents */
						((SLData_t)(1.0/16.0)),		/* 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 */

													/* 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 */

													/* 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 */

													/* Calculate real magnitude from complex */
	SDA_Magnitude (pRealData,						/* Pointer to real source array */
				   pImagData,						/* Pointer to imaginary source array */
				   pRealData,						/* Pointer to magnitude destination array */
				   FFT_SIZE);						/* Array length */
	
	Display2DGraph (h2DGraph,						/* Graph handle */
				    "Fast Fourier Transform Results",		/* 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 ("\nFast Fourier Transform Results\nPlease hit <Carriage Return> to continue . . ."); getchar ();


	SUF_MemoryFree (pRealData);						/* Free memory */
	SUF_MemoryFree (pSrcData);
	SUF_MemoryFree (pImagData);
	SUF_MemoryFree (pFFTCoeffs);
}



