Sound capture (Part 3)

Part 12345

Let’s have a look at the code structure for acquiring the signal and computing FFT. The big limitation here is memory. In spite of the ‘in place’ FFT calculation, at least 2 vectors of doubles are required occupying 2 times 4 bytes (for each double) times the number of samples. I built the acquisition routine in such a way that the least memory is used. The large (doubles) real and imaginary values vectors are temporary, while the smaller frequency spectrum data vectors (bytes) are made global.

Let’s describe the process in details:

set acquisition parameters in the set up routine:

	/* Set acquisition parameters */
	DAC.SetAcquisitionParameters(samplingFrequency, samples, acqMode, vRef);

for which the parameters where set in the declaration section of the sketch:

const uint16_t samplingFrequency = 8000; /* Set default sampling frequency value */
const uint8_t acqMode = DAC_ACQ_MOD_DOUBLE; /* Set default acquisition mode value */
const uint16_t samples = 128; /* Set default samples value */
const uint8_t vRef = DAC_VRF_DEFAULT; /* Set default voltage reference value */

Then , within the loop:

	/* Initialize data vector */
	uint8_t *vData = (uint8_t*)malloc(samples * sizeof(double)); 
	/* Acquire data in bytes array */
	DAC.AcquireData(vData, channel);

Comment: A pointer is created for a bytes array, but the size of the array is four times a byte size. The reason is that this array will in fact contain doubles. That’s a tricky way that I found in order to use the same AcquireData() routine for any data type (Bytes, Integers, delta encoded values and Doubles)

Next step is really special!

	/* Reallocate memory space to doubles array for real values */
	double *vReal = (double*)realloc(vData, samples * sizeof(double));

Comment: What we do here is that we create a pointer to an array of Doubles which points to the memory space which contains the Bytes array. In this way, I do not have to create an other vector of data.

The rest is quite easy. This is a level adjuster loop which converts the digital values to Volts, taking into account the input bias:

	/* Adjust signal level */
	for (uint16_t i = 0; i < samples; i++) {
		vReal[i] = (((vReal[i] * 5.0) / 1024.0) - 2.5);

Then comes the FFT part of the signal analysis

	/* Allocate memory space to doubles array for imaginary values (all 0ed) */
	double *vImag = (double*)calloc(samples, sizeof(double)); 
	/* Weigh data */
	FFT.Windowing(vReal, samples, FFT_WIN_TYP_RECTANGLE, FFT_FORWARD); 
	/* Compute FFT */
	FFT.Compute(vReal, vImag, samples, FFT_FORWARD); 
	/* Compute magnitudes */
	FFT.ComplexToMagnitude(vReal, vImag, samples);

In the next post, I will describe how to handle the frequency spectrum for comparisons.

Next post on same subject

One Comment

Leave a Reply

You must be logged in to post a comment.