/* SigLib Envelope Detection Using Hilbert Transform Example
The envelope detector square magnitude sums a Hilbert Transformed
signal with an appropriately delayed version of the original and
this gives the envelope.
The process is equivalent to generating an analytical signal.
*/

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

/* Define constants */
#define	SAMPLE_LENGTH	((SLArrayIndex_t)512)
#define	FFT_SIZE		SAMPLE_LENGTH
#define	LOG_FFT_SIZE	((SLArrayIndex_t)9)
#define	FILTER_LENGTH	31L
#define	DELAY_LENGTH	((SLArrayIndex_t)((FILTER_LENGTH + 1) / 2))

SLData_t	SinePhase;
SLData_t	*pDelay, *pTempDelay;
SLData_t	*pFilterCoeffs, *pFilterCoeffsStart, *pFilterState;
SLArrayIndex_t	FilterIndex;
SLData_t	*pSrc1, *pSrc2;

void	main(void);

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

	h2DGraph =										/* Initialize graph */
		Create2DGraph ("Hilbert Transform Envelope Detector",	/* 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);
	}

	printf ("Hilbert Transform Filter Length = %ld\n", FILTER_LENGTH);

	pFilterCoeffs = SUF_VectorArrayAllocate (FILTER_LENGTH);
	pFilterState = SUF_VectorArrayAllocate (FILTER_LENGTH);
	pSrc1 = SUF_VectorArrayAllocate (SAMPLE_LENGTH);
	pSrc2 = SUF_VectorArrayAllocate (SAMPLE_LENGTH);
	pTempDelay = SUF_VectorArrayAllocate (DELAY_LENGTH);

	pFilterCoeffsStart = pFilterCoeffs;
													/* Initialise Hilbert transformer coefficients */
	SIF_HilbertTransformer (pFilterCoeffs,			/* Pointer to filter coefficients */
							FILTER_LENGTH);			/* Filter length */
	SIF_Fir (pFilterState,							/* Pointer to filter state array */
			 &FilterIndex,							/* Pointer to filter index register */
			 FILTER_LENGTH);						/* Filter length */

	pDelay = SUF_VectorArrayAllocate (DELAY_LENGTH);
	SIF_Delay (pDelay, SIGLIB_NULL_ARRAY_INDEX_PTR, DELAY_LENGTH);		/* Initialise the delay */

	SinePhase = SIGLIB_ZERO;
	SDA_SignalGenerate (pSrc1,						/* 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.05),			/* 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 */
						SAMPLE_LENGTH);				/* Output array length */

	SinePhase = SIGLIB_ZERO;
	SDA_SignalGenerate (pSrc2,						/* 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.005),			/* 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 */
						SAMPLE_LENGTH);				/* Output array length */

	SDA_Multiply2 (pSrc1, pSrc2, pSrc1, SAMPLE_LENGTH);

	Display2DGraph (h2DGraph,						/* Graph handle */
				    "Source 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 */
	printf ("\nSource Signal\nPlease hit <Carriage Return> to continue . . ."); getchar ();


													/* Apply Hilbert transformerer */
	SDA_Fir (pSrc1,									/* Input array to be filtered */
			 pSrc2,									/* Filtered output array */
			 pFilterState,							/* Pointer to filter state array */
			 pFilterCoeffs,							/* Pointer to filter coefficients */
			 &FilterIndex,							/* Pointer to filter index register */
			 FILTER_LENGTH,							/* Filter length */
			 SAMPLE_LENGTH);						/* Array length */

	Display2DGraph (h2DGraph,						/* Graph handle */
				    "Filtered",						/* Title of the dataset */
				    pSrc2,							/* Array of Double dataset */
				    SAMPLE_LENGTH,					/* Number of data points */
					SV_GRAPH_LINE,					/* Graph type */
				    SV_BLUE,						/* Colour */
					SV_SHOW_MARKERS,				/* Marker enable / disable */
					SV_GRAPH_NEW);					/* New graph */
	printf ("\nFiltered\nPlease hit <Carriage Return> to continue . . ."); getchar ();


						/* Delay real component to generate an analytical signal */
	SDA_ShortDelay (pSrc1, pSrc1, pDelay, pTempDelay, DELAY_LENGTH, SAMPLE_LENGTH);

													/* Calculate real magnitude from complex */
	SDA_Magnitude (pSrc1,							/* Pointer to real source array */
				   pSrc2,							/* Pointer to imaginary source array */
				   pSrc1,							/* Pointer to magnitude destination array */
				   SAMPLE_LENGTH);					/* Array length */

	Display2DGraph (h2DGraph,						/* Graph handle */
				    "Signal Envelope",				/* Title of the dataset */
				    pSrc1,							/* 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 */
	SDA_Multiply (pSrc1, SIGLIB_MINUS_ONE, pSrc1, SAMPLE_LENGTH);
	Display2DGraph (h2DGraph,						/* Graph handle */
				    "Signal Envelope",				/* Title of the dataset */
				    pSrc1,							/* 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 ("\nSignal Envelope\n");

	SUF_MemoryFree (pFilterCoeffs);					/* Free memory */
	SUF_MemoryFree (pFilterState);
	SUF_MemoryFree (pSrc1);
	SUF_MemoryFree (pSrc2);
	SUF_MemoryFree (pDelay);
	SUF_MemoryFree (pTempDelay);
}


