/*---------------------------------------------------------------------------*\

	Common code for ERL utilities.

         Voicetronix Voice Processing Board (VPB) Software

         Copyright (C) 1999-2008 Voicetronix www.voicetronix.com.au

         This library is free software; you can redistribute it and/or
         modify it under the terms of the GNU Lesser General Public
         License version 2.1 as published by the Free Software Foundation;

         This library is distributed in the hope that it will be useful,
         but WITHOUT ANY WARRANTY; without even the implied warranty of
         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
         Lesser General Public License for more details.

         You should have received a copy of the GNU Lesser General Public
         License along with this library; if not, write to the Free Software
         Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
         MA  02110-1301  USA

\*---------------------------------------------------------------------------*/

#include "vpbapi.h"

#include <cstdio>
#include <math.h>

#define N	        160	// size of processing frame
#define MNSAM           40      // number of frames to sample
#define NCONV           20      // number of frames to wait for convergence
#define AMP             4000    // peak amplitude of test signal
#define FS              8000.0  // sampling frequency

// number of test frequencies 
#define NFREQS          (sizeof(freqs) / sizeof(*freqs))


static float freqs[] = {300.0, 500.0, 1000.0, 2000.0, 3000.0};
static FILE *fscan;


// measure erl at a single frequency
static float measure_erl(int h, float f)
{ //{{{
	short   bufrd[N],
		bufwr[N];
	float   echo_pwr = 0.0,
		ref_pwr  = 0.0;

	for(int i = 0; i < MNSAM; ++i)
	{
		// generate a buffer of sine samples and output
		for(int j = 0; j < N; ++j)
		{
			float sam = cos(2 * M_PI * (f/FS) * (i*N+j)) * AMP;

			bufwr[j] = (short)sam;
			if(i >= NCONV) ref_pwr += sam * sam;
		}

		vpb_play_buf_sync(h, (char*)bufwr, sizeof(short)*N);

		// wait for buffer of echo samples
		vpb_record_buf_sync(h, (char*)bufrd, sizeof(short)*N);

		for(int j = 0; j < N; ++j)
		{
			short sam = bufrd[j];
			if(i >= NCONV) echo_pwr += sam * sam;
		}
	}

	// print results
	float erl = 10 * log10(echo_pwr / ref_pwr);

	printf("\t%.2f", erl);
	if(fscan) fprintf(fscan, "\t%.2f", erl);

	return erl;
} //}}}

// measeure erl across a range of frequencies
static void scan_erl(int h, float *av_erl, float *max_erl, float *min_erl)
{ //{{{
	float erl;

	vpb_record_buf_start(h, VPB_LINEAR);
	vpb_play_buf_start(h, VPB_LINEAR);

	*av_erl = 0.0;
	*max_erl = -100.0;
	*min_erl = 100.0;
	for(size_t i = 0; i < NFREQS; ++i)
	{
		erl = measure_erl(h, freqs[i]);
		*av_erl += erl;
		if(erl > *max_erl) *max_erl = erl;
		if(erl < *min_erl) *min_erl = erl;
	}
	// Average ERL
	*av_erl /= NFREQS;

	// clean up and finish
	vpb_record_buf_finish(h);
	vpb_play_buf_finish(h);

	printf("\t\t%.2f\t%.2f\t%.2f\t%.2f",
	       *av_erl, *max_erl, *min_erl, *max_erl-*min_erl);
	if(fscan) fprintf(fscan, "\t\t%.2f\t%.2f\t%.2f\t%.2f",
			  *av_erl, *max_erl, *min_erl, *max_erl-*min_erl);
} //}}}


