/* SigLib FIR Filter Design Example */

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

/* Define constants */
#define	FILTER_LENGTH		((SLArrayIndex_t)125)
#define	FFT_LENGTH			((SLArrayIndex_t)512)

/* Declare global arrays and variables */
SLData_t	pLPFilterCoeffs[FILTER_LENGTH];
SLData_t	pLPFilterState[FILTER_LENGTH];
SLData_t	pBPFilterCoeffs[FILTER_LENGTH];
SLData_t	pHPFilterCoeffs[FILTER_LENGTH];
SLData_t	pHPFilterState[FILTER_LENGTH];

SLArrayIndex_t	LPFilterIndex;
SLArrayIndex_t	HPFilterIndex;

SLData_t	*pSrc;

void	main(void);

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

	SLData_t	FilterInverseCoherentGain;

	pSrc = SUF_VectorArrayAllocate (FFT_LENGTH);

	if (pSrc == NULL)
	{
		printf ("Memory allocation error in main ()\n");
		return;
	}

	h2DGraph =										/* Initialize graph */
		Create2DGraph ("FIR Filter Design",			/* 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 the filters */
	SIF_Fir (pLPFilterState,						/* Pointer to filter state array */
			 &LPFilterIndex,						/* Pointer to filter index register */
			 FILTER_LENGTH);						/* Filter length */
	SIF_Fir (pHPFilterState,						/* Pointer to filter state array */
			 &HPFilterIndex,						/* Pointer to filter index register */
			 FILTER_LENGTH);						/* Filter length */
	SIF_LowPassFirFilter (pLPFilterCoeffs,			/* Filter coeffs array */
						  (3000.0/8000.0),			/* Filter cut off frequency */
						  SIGLIB_HANNING,			/* Window type */
						  FILTER_LENGTH);			/* Filter length */
	SIF_BandPassFirFilter (pBPFilterCoeffs,			/* Filter coeffs array */
						   (1600.0/8000.0),			/* Filter center frequency */
						   (2000.0/8000.0),			/* Filter bandwidth */
						   SIGLIB_HANNING,			/* Window type */
						   FILTER_LENGTH);			/* Filter length */
	SIF_HighPassFirFilter (pHPFilterCoeffs,			/* Filter coeffs array */
						   (1000.0/8000.0),			/* Filter cut off frequency */
						   SIGLIB_HANNING,			/* Window type */
						   FILTER_LENGTH);			/* Filter length */

					/* Display coefficients for each filter */
	Display2DGraph (h2DGraph,						/* Graph handle */
				    "Low-pass Filter Coefficients",	/* Title of the dataset */
				    pLPFilterCoeffs,				/* Array of Double dataset */
				    FILTER_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 ("\nLow-pass Filter Coefficients\nPlease hit <Carriage Return> to continue . . ."); getchar ();

	Display2DGraph (h2DGraph,						/* Graph handle */
				    "Band-pass Filter Coefficients",	/* Title of the dataset */
				    pBPFilterCoeffs,				/* Array of Double dataset */
				    FILTER_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 ("\nBand-pass Filter Coefficients\nPlease hit <Carriage Return> to continue . . ."); getchar ();

	Display2DGraph (h2DGraph,						/* Graph handle */
				    "High-pass Filter Coefficients",	/* Title of the dataset */
				    pHPFilterCoeffs,				/* Array of Double dataset */
				    FILTER_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 ("\nHigh-pass Filter Coefficients\nPlease hit <Carriage Return> to continue . . ."); getchar ();


					/* Display frequency response for each filter */
	SDA_Clear (pSrc,								/* Pointer to destination array */
			   FFT_LENGTH);							/* Array length */
	SDA_Copy (pLPFilterCoeffs,						/* Pointer to source array */
			  pSrc,									/* Pointer to destination array */
			  FILTER_LENGTH);						/* Array length */
	plot_frequency_domain (pSrc, SIGLIB_FLAT_TOP, "Low-pass Filter Response", FFT_LENGTH, FFT_LENGTH);

	SDA_Clear (pSrc,								/* Pointer to destination array */
			   FFT_LENGTH);							/* Array length */
	SDA_Copy (pBPFilterCoeffs,						/* Pointer to source array */
			  pSrc,									/* Pointer to destination array */
			  FILTER_LENGTH);						/* Array length */
	plot_frequency_domain (pSrc, SIGLIB_FLAT_TOP, "Band-pass Filter Response", FFT_LENGTH, FFT_LENGTH);

	SDA_Clear (pSrc,								/* Pointer to destination array */
			   FFT_LENGTH);							/* Array length */
	SDA_Copy (pHPFilterCoeffs,						/* Pointer to source array */
			  pSrc,									/* Pointer to destination array */
			  FILTER_LENGTH);						/* Array length */
	plot_frequency_domain (pSrc, SIGLIB_FLAT_TOP, "High-pass Filter Response", FFT_LENGTH, FFT_LENGTH);


					/* Combine filters and display combined result */
				/* Generate an impulse input signal */
	SDA_SignalGenerate (pSrc,						/* Pointer to destination array */
						SIGLIB_IMPULSE,				/* Signal type - Impulse 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_ZERO,				/* Unused */
						SIGLIB_ZERO,				/* Signal end value - Unused */
						SIGLIB_NULL_DATA_PTR,		/* Unused */
						SIGLIB_NULL_DATA_PTR,		/* Unused */
						FFT_LENGTH);				/* Output array length */

				/* Low-pass filter */
	SDA_Fir(pSrc,									/* Input array to be filtered */
			pSrc,									/* Filtered output array */
			pLPFilterState,							/* Pointer to filter state array */
			pLPFilterCoeffs,						/* Pointer to filter coefficients */
			&LPFilterIndex,							/* Pointer to filter index register */
			FILTER_LENGTH,							/* Filter length */
			FFT_LENGTH);							/* Array length */
 
				/* High-pass filter */
	SDA_Fir(pSrc,									/* Input array to be filtered */
			pSrc,									/* Filtered output array */
			pHPFilterState,							/* Pointer to filter state array */
			pHPFilterCoeffs,						/* Pointer to filter coefficients */
			&HPFilterIndex,							/* Pointer to filter index register */
			FILTER_LENGTH,							/* Filter length */
			FFT_LENGTH);							/* Array length */

	Display2DGraph (h2DGraph,						/* Graph handle */
				    "Dual Filter Impulse Response",	/* Title of the dataset */
				    pSrc,							/* Array of Double dataset */
				    FFT_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 ("\nDual Filter Impulse Response\nPlease hit <Carriage Return> to continue . . ."); getchar ();

	plot_frequency_domain (pSrc, SIGLIB_FLAT_TOP, "Dual filter frequency response", FFT_LENGTH, FFT_LENGTH);


								/* We will design another LPF FIR filter and normalize the gain */
													/* Initialise the filters */
	SIF_Fir (pLPFilterState,						/* Pointer to filter state array */
			 &LPFilterIndex,						/* Pointer to filter index register */
			 FILTER_LENGTH);						/* Filter length */

	SIF_LowPassFirFilter (pLPFilterCoeffs,			/* Filter coeffs array */
						  0.012,					/* Filter cut off frequency */
						  SIGLIB_HAMMING,			/* Window type */
						  FILTER_LENGTH);			/* Filter length */

	FilterInverseCoherentGain = SDA_FirFilterInverseCoherentGain (pLPFilterCoeffs, FILTER_LENGTH);

	printf ("CoeffSum = %lf\n\n", SDA_Sum (pLPFilterCoeffs, FILTER_LENGTH));
	printf ("Inverse coherent gain = %lf\n\n", FilterInverseCoherentGain);

	SDA_Multiply (pLPFilterCoeffs, FilterInverseCoherentGain, pLPFilterCoeffs, FILTER_LENGTH);

													/* Normalize 0dB gain for graph */
	SDA_Multiply (pLPFilterCoeffs, 20000.0, pLPFilterCoeffs, FILTER_LENGTH);

					/* Display coefficients for each filter */
	Display2DGraph (h2DGraph,						/* Graph handle */
				    "Low-pass Filter Coefficients",	/* Title of the dataset */
				    pLPFilterCoeffs,				/* Array of Double dataset */
				    FILTER_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 ("\nLow-pass Filter Coefficients\nPlease hit <Carriage Return> to continue . . ."); getchar ();

					/* Display frequency response for each filter */
	plot_frequency_domain (pLPFilterCoeffs, SIGLIB_RECTANGLE, "Low-pass Filter Response", FILTER_LENGTH, FFT_LENGTH);

	SUF_MemoryFree (pSrc);							/* Free memory */
}



