/* SigLib One-pole Filter Example */

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

/* Define constants */
#define	SAMPLE_LENGTH		((SLArrayIndex_t)512)
#define	FFT_SIZE			((SLArrayIndex_t)512)
#define	HALF_FFT_SIZE		((SLArrayIndex_t)256)
#define	LOG_FFT_SIZE		((SLArrayIndex_t)9)

SLData_t	*pRealData, *pImagData, *pResults, *pSrc1, *pSrc2, *filtered, *delay, *pFFTCoeffs;
SLData_t	Alpha, Offset, OnePoleFilterState, SinePhase;

void main(int argc,char **argv)
{
	GraphObject *h2DGraph;							/* Declare graph object */

	if (argc != 2)
	{
		printf ("\nsyntax: Test_op <Alpha>\n\n");
		exit (0);
	}

	Alpha = (SLData_t) atof (argv[1]);

													/* Allocate memory */
	pSrc1 = SUF_VectorArrayAllocate (SAMPLE_LENGTH);
	pSrc2 = SUF_VectorArrayAllocate (SAMPLE_LENGTH);
	pRealData = SUF_VectorArrayAllocate (FFT_SIZE);
	pImagData = SUF_VectorArrayAllocate (FFT_SIZE);
	pResults = SUF_VectorArrayAllocate (FFT_SIZE);		/* RMS result array */
	filtered = SUF_VectorArrayAllocate (HALF_FFT_SIZE);
	delay = SUF_VectorArrayAllocate (HALF_FFT_SIZE);
	pFFTCoeffs = SUF_FftCoefficientAllocate (FFT_SIZE);

	h2DGraph =										/* Initialize graph */
		Create2DGraph ("One-pole Filter",			/* Graph title */
					   "Time / 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);
	}

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

	SDA_SignalGenerate (pSrc1,						/* Pointer to destination array */
						SIGLIB_STEP,				/* Signal type - step function */
						SIGLIB_ONE,					/* Signal peak level */
						SIGLIB_FILL,				/* Fill (overwrite) or add to existing array contents */
						SIGLIB_ZERO,				/* Signal frequency - Unused */
						SIGLIB_ZERO,				/* D.C. Offset */
						SIGLIB_TEN,					/* Unused */
						SIGLIB_ZERO,				/* Signal end value - Unused */
						SIGLIB_NULL_DATA_PTR,		/* Unused */
						SIGLIB_NULL_DATA_PTR,		/* Unused */
						SAMPLE_LENGTH);				/* Output array length */

	SIF_OnePole (&OnePoleFilterState);
	SDA_OnePole (pSrc1, pSrc2, Alpha, &OnePoleFilterState, SAMPLE_LENGTH);

	Display2DGraph (h2DGraph,						/* Graph handle */
				    "Unfiltered Signal",			/* Title of the dataset */
				    pSrc1,							/* Array of Double dataset */
				    SAMPLE_LENGTH,					/* Number of data points */
					SV_GRAPH_LINE,					/* Graph type */
				    SV_BLUE,						/* Colour */
					SV_HIDE_MARKERS,				/* Marker enable / disable */
					SV_GRAPH_NEW);					/* New graph */

	Display2DGraph (h2DGraph,						/* Graph handle */
				    "One-pole Filtered Signal",		/* Title of the dataset */
				    pSrc2,							/* Array of Double dataset */
				    SAMPLE_LENGTH,					/* Number of data points */
					SV_GRAPH_LINE,					/* Graph type */
				    SV_RED,							/* Colour */
					SV_HIDE_MARKERS,				/* Marker enable / disable */
					SV_GRAPH_ADD);					/* New graph */
	printf ("\nUnfiltered And One-pole Filtered Signal\nPlease hit <Carriage Return> to continue . . ."); getchar ();

													/* Copy data for FFT */
	SDA_Copy (pSrc2,								/* Pointer to source array */
			  pRealData,							/* Pointer to destination array */
			  FFT_SIZE);							/* Array length */

													/* 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 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);					/* Array length */

	Display2DGraph (h2DGraph,						/* Graph handle */
				    "Frequency Response Of One-pole Filter",	/* Title of the dataset */
				    pResults,						/* Array of Double dataset */
				    SAMPLE_LENGTH,					/* Number of data points */
					SV_GRAPH_LINE,					/* Graph type */
				    SV_BLUE,						/* Colour */
					SV_HIDE_MARKERS,				/* Marker enable / disable */
					SV_GRAPH_NEW);					/* New graph */
	printf ("\nFrequency Response Of One-pole Filter\nPlease hit <Carriage Return> to continue . . ."); getchar ();

	SinePhase = SIGLIB_ZERO;
	printf ("512 Point FFT, quantized data - one pole filter per bin (Alpha = %lf)\n", Alpha);
	OnePoleFilterState = SIGLIB_FIRST_SAMPLE;
													/* Initialise one pole filter state array */
	SDA_Clear (delay,								/* Pointer to destination array */
			   HALF_FFT_SIZE);						/* Array length */

	while (!kbhit())
	{
		SDA_SignalGenerate (pRealData,				/* Pointer to destination array */
							SIGLIB_SINE_WAVE,		/* Signal type - Sine wave */
							SIGLIB_ONE,				/* Signal peak level */
							SIGLIB_FILL,			/* Fill (overwrite) or add to existing array contents */
							((SLData_t)0.0625),		/* 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 */

				/* Quantisation - leads to spurious noise */	
		SDA_Quantize (pRealData,					/* Pointer to source array */
					  pRealData,					/* Pointer to destination array */
					  8,							/* Quantisation */
					  SIGLIB_ONE,					/* Peak value */
					  FFT_SIZE);					/* Source array size */

				/* Uncorrelated noise (8 bit ) */
		SDA_SignalGenerate (pRealData,				/* Pointer to destination array */
							SIGLIB_WHITE_NOISE,		/* Signal type - random white noise */
							((SLData_t)0.003906),	/* Signal peak level */
							SIGLIB_ADD,				/* Fill (overwrite) or add to existing array contents */
							SIGLIB_ZERO,			/* Signal frequency - Unused */
							SIGLIB_ZERO,			/* D.C. Offset */
							SIGLIB_ZERO,			/* Unused */
							SIGLIB_ZERO,			/* Signal end value - Unused */
							SIGLIB_NULL_DATA_PTR,	/* Unused */
							SIGLIB_NULL_DATA_PTR,	/* Unused */
							FFT_SIZE);				/* Output array length */

													/* 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 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);				/* Array length */

		Offset = SDA_AbsMax (pResults,				/* Pointer to source array */
						  FFT_SIZE);				/* Array length */
		SDA_Offset (pResults,						/* Pointer to source array */
					Offset,							/* D.C. offset */
					pResults,						/* Pointer to destination array */
					FFT_SIZE);						/* Array length */

		SDA_OnePolePerSample (pResults,				/* Pointer to input data */
							  filtered,				/* Pointer to destination array */
							  delay,				/* Pointer to state array */
							  Alpha,				/* Filter alpha */
							  HALF_FFT_SIZE);		/* Array length */

		Display2DGraph (h2DGraph,					/* Graph handle */
					    "Filtered Signal",			/* Title of the dataset */
					    filtered,					/* Array of Double dataset */
					    HALF_FFT_SIZE,				/* Number of data points */
						SV_GRAPH_STEM,				/* Graph type */
					    SV_BLUE,					/* Colour */
						SV_SHOW_MARKERS,			/* Marker enable / disable */
						SV_GRAPH_NEW);				/* New graph */
	}

	if (kbhit()) getchar ();						/* Clear keyboard buffer */

	SUF_MemoryFree (pSrc1);							/* Free memory */
	SUF_MemoryFree (pSrc2);
	SUF_MemoryFree (pRealData);
	SUF_MemoryFree (pImagData);
	SUF_MemoryFree (pResults);
	SUF_MemoryFree (filtered);
	SUF_MemoryFree (delay);
	SUF_MemoryFree (pFFTCoeffs);
}


