/* SigLib Automatic Gain Control Example */

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

/* Define constants */
#define	SAMPLE_LENGTH				((SLArrayIndex_t)512)
#define AGC_OUTPUT_LEVEL			((SLData_t)0.9)		/* Desired peak level */
#define AGC_ADJUST_THRESHOLD		((SLData_t)0.05)	/* Min. level below which gain is maintained as constant */
#define AGC_SENSITIVITY				((SLData_t)0.005)	/* Sensitivity of gain adjustment */
#define AGC_ATTACK_SENSITIVITY		((SLData_t)1.004)	/* Sensitivity of attack gain adjustment */
#define AGC_DECAY_SENSITIVITY		((SLData_t)0.996)	/* Sensitivity of decay gain adjustment */
#define AGC_SUB_ARRAY_LEN			32L					/* Sub array length */
#define AGC_MEAN_LEN				32L					/* Mean length */

SLData_t	*pSrc, *pDst;
SLData_t	SinePhase;
SLData_t	AGCGain, AGCMax;

SLData_t	MeanState[AGC_MEAN_LEN];
SLArrayIndex_t	MeanStateIndex;
SLData_t	MeanSum;
SLData_t	DesiredMeanScaled;
SLData_t	ThresholdScaled;

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

	h2DGraph =										/* Initialize graph */
		Create2DGraph ("Automatic Gain Control",	/* Graph title */
					   "Time",						/* X-Axis label */
					   "Magnitude",					/* Y-Axis label */
					   1.0,							/* 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);
	}

	pSrc = SUF_VectorArrayAllocate (SAMPLE_LENGTH);	/* Allocate memory */
	pDst = SUF_VectorArrayAllocate (SAMPLE_LENGTH);


	SinePhase = SIGLIB_ZERO;
	SDA_SignalGenerate (pSrc,						/* Pointer to destination array */
						SIGLIB_SINE_WAVE,			/* Signal type - Sine wave */
						((SLData_t)0.4),			/* Signal peak level */
						SIGLIB_FILL,				/* Fill (overwrite) or add to existing array contents */
						((SLData_t)0.048),			/* 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 */

	AGCGain = SIGLIB_ONE; AGCMax = SIGLIB_ZERO;

	Display2DGraph (h2DGraph,						/* Graph handle */
				    "Source Signal",				/* Title of the dataset */
				    pSrc,							/* 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 ();

	SDA_AgcPeak (pSrc,								/* Pointer to source array */
				 pDst,								/* Pointer to destination array */
				 AGC_OUTPUT_LEVEL,					/* Peak to control to */
				 AGC_ADJUST_THRESHOLD,				/* Minimum threshold */
				 AGC_ATTACK_SENSITIVITY,			/* Attack sensitivity */
				 AGC_DECAY_SENSITIVITY,				/* Decay sensitivity */
				 &AGCGain,							/* Previous gain pointer */
				 &AGCMax,							/* Previous max pointer */
				 AGC_SUB_ARRAY_LEN,					/* Sub array length */
				 SAMPLE_LENGTH);					/* Array length */

	Display2DGraph (h2DGraph,						/* Graph handle */
				    "AGC Peak",						/* Title of the dataset */
				    pDst,							/* 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 ("\nAGC Peak\nPlease hit <Carriage Return> to continue . . ."); getchar ();


	SIF_AgcMeanAbs (MeanState,						/* Moving average state array */
					&MeanStateIndex,				/* Moving average state array index */
					&MeanSum,						/* Pointer to moving average sum */
					&AGCGain,						/* Pointer to AGC gain */
					&DesiredMeanScaled,				/* Pointer to scaled desired mean level */
					&ThresholdScaled,				/* Pointer to threshold mean level */
					AGC_OUTPUT_LEVEL,				/* Desired level of AGC output */
					AGC_ADJUST_THRESHOLD,			/* Threshold for update of AGC */
					AGC_MEAN_LEN);					/* Length of moving average */

	Display2DGraph (h2DGraph,						/* Graph handle */
				    "Source Signal",				/* Title of the dataset */
				    pSrc,							/* 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 ();

	SDA_AgcMeanAbs (pSrc,							/* Pointer to source array */
					pDst,							/* Pointer to destination array */
					DesiredMeanScaled,				/* Desired scaled value */
					ThresholdScaled,				/* Threshold scaled value */
					AGC_ATTACK_SENSITIVITY,			/* Attack sensitivity */
					AGC_DECAY_SENSITIVITY,			/* Decay sensitivity */
					MeanState,						/* Moving average state array */
					&MeanStateIndex,				/* Moving average state array index */
					&MeanSum,						/* Pointer to moving average sum */
					&AGCGain,						/* Pointer to AGC gain */
					AGC_MEAN_LEN,					/* Length of moving average state array */
					SAMPLE_LENGTH);					/* Length of input array */

	Display2DGraph (h2DGraph,						/* Graph handle */
				    "AGC Mean Absolute Value",		/* Title of the dataset */
				    pDst,							/* 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 ("\nAGC Mean Absolute Value\nPlease hit <Carriage Return> to continue . . ."); getchar ();


	SIF_AgcMeanSquared (MeanState,					/* Moving average state array */
						&MeanStateIndex,			/* Moving average state array index */
						&MeanSum,					/* Pointer to moving average sum */
						&AGCGain,					/* Pointer to AGC gain */
						&DesiredMeanScaled,			/* Pointer to scaled desired mean squared level */
						&ThresholdScaled,			/* Pointer to threshold mean squared level */
						AGC_OUTPUT_LEVEL,			/* Desired level of AGC output */
						AGC_ADJUST_THRESHOLD,		/* Threshold for update of AGC */
						AGC_MEAN_LEN);				/* Length of moving average */

	Display2DGraph (h2DGraph,						/* Graph handle */
				    "Source Signal",				/* Title of the dataset */
				    pSrc,							/* 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 ();

	SDA_AgcMeanSquared (pSrc,						/* Pointer to source array */
						pDst,						/* Pointer to destination array */
						DesiredMeanScaled,			/* Desired scaled value */
						ThresholdScaled,			/* Threshold scaled value */
						AGC_ATTACK_SENSITIVITY,		/* Attack sensitivity */
						AGC_DECAY_SENSITIVITY,		/* Decay sensitivity */
						MeanState,					/* Moving average state array */
						&MeanStateIndex,			/* Moving average state array index */
						&MeanSum,					/* Pointer to moving average sum */
						&AGCGain,					/* Pointer to AGC gain */
						AGC_MEAN_LEN,				/* Length of moving average state array */
						SAMPLE_LENGTH);				/* Length of input array */

	Display2DGraph (h2DGraph,						/* Graph handle */
				    "AGC Mean Squared Value",		/* Title of the dataset */
				    pDst,							/* 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 ("\nAGC Mean Squared Value\n");

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


