changeset 91:241d4d5df929

Double buffered the noise floor project; works without glitches now
author andrewm
date Sun, 19 Jul 2015 23:19:27 +0100
parents c74006ef86ca
children a55dcdcebdcd
files projects/measure_noisefloor/render.cpp
diffstat 1 files changed, 62 insertions(+), 54 deletions(-) [+]
line wrap: on
line diff
--- a/projects/measure_noisefloor/render.cpp	Sun Jul 19 16:42:51 2015 +0100
+++ b/projects/measure_noisefloor/render.cpp	Sun Jul 19 23:19:27 2015 +0100
@@ -12,19 +12,16 @@
 
 int gBufferSize = 8192;
 
-// Buffers to hold samples for noise analysis
-float* gBuffers[10];
-int gBufferPointers[10];
+// Double buffers to hold samples for noise analysis
+float *gReadBuffers[10], *gWriteBuffers[10];
+float *gBuffers0[10], *gBuffers1[10];
 
-// Outputs to display
-float gDCLevels[10];
-float gNoiseLevels[10];
-float gNumSamplesAnalysed[10];
+int gWriteBufferPointers[10], gReadBufferPointers[10];
 
-// Task to print results which would otherwise be too slow for render()
-AuxiliaryTask gPrintTask;
+// Task to analyse and print results which would otherwise be too slow for render()
+AuxiliaryTask gAnalysisTask;
 
-void printResults();
+void analyseResults();
 
 // setup() is called once before the audio rendering starts.
 // Use it to perform any initialisation and allocation which is dependent
@@ -39,15 +36,18 @@
 {	
 	// Clear the filter data structures
 	for(int i = 0; i < 10; i++) {
-		gBufferPointers[i] = 0;
-		gBuffers[i] = new float[gBufferSize];
-		if(gBuffers[i] == 0) {
+		gReadBufferPointers[i] = gWriteBufferPointers[i] = 0;
+		gBuffers0[i] = new float[gBufferSize];
+		gBuffers1[i] = new float[gBufferSize];		
+		gWriteBuffers[i] = gBuffers0[i];
+		gReadBuffers[i] = gBuffers1[i];
+		if(gBuffers0[i] == 0 || gBuffers1[i] == 0) {
 			rt_printf("Error allocating buffer %d\n", i);
 			return false;
 		}
 	}
 	
-	gPrintTask = BeagleRT_createAuxiliaryTask(printResults, 50, "beaglert-print-results");
+	gAnalysisTask = BeagleRT_createAuxiliaryTask(analyseResults, 50, "beaglert-analyse-results");
 
 	return true;
 }
@@ -64,11 +64,11 @@
 	for(unsigned int n = 0; n < context->audioFrames; n++) {
 		// Store audio inputs in buffer
 		for(unsigned int ch = 0; ch < context->audioChannels; ch++) {
-			if(gBufferPointers[ch] < gBufferSize) {
-				gBuffers[ch][gBufferPointers[ch]] = 
+			if(gWriteBufferPointers[ch] < gBufferSize) {
+				gWriteBuffers[ch][gWriteBufferPointers[ch]] = 
 					context->audioIn[n * context->audioChannels + ch];
-				gBufferPointers[ch]++;
-				if(gBufferPointers[ch] >= gBufferSize)
+				gWriteBufferPointers[ch]++;
+				if(gWriteBufferPointers[ch] >= gBufferSize)
 					bufferIsFull = true;
 			}
 		}
@@ -78,58 +78,64 @@
 		for(unsigned int n = 0; n < context->analogFrames; n++) {
 			// Store analog inputs in buffer, starting at channel 2
 			for(unsigned int ch = 0; ch < context->analogChannels; ch++) {
-				if(gBufferPointers[ch + 2] < gBufferSize) {
-					gBuffers[ch + 2][gBufferPointers[ch + 2]] = 
+				if(gWriteBufferPointers[ch + 2] < gBufferSize) {
+					gWriteBuffers[ch + 2][gWriteBufferPointers[ch + 2]] = 
 						context->analogIn[n * context->analogChannels + ch];
-					gBufferPointers[ch + 2]++;
-					if(gBufferPointers[ch + 2] >= gBufferSize)
+					gWriteBufferPointers[ch + 2]++;
+					if(gWriteBufferPointers[ch + 2] >= gBufferSize)
 						bufferIsFull = true;
 				}
+				
+				// Set all analog outputs to halfway point so they can be more
+				// easily measured for noise
+				context->analogOut[n * context->analogChannels + ch] = 0.5;
 			}
 		}	
 	}
+	
 
 	if(bufferIsFull) {
-		// Analyse all active channels at once
+		// Swap buffers and reset write pointers
 		for(int ch = 0; ch < 10; ch++) {
-			// gBufferPointers[ch] tells us how many samples were stored in the buffer
-			gNumSamplesAnalysed[ch] = gBufferPointers[ch];
+			gReadBufferPointers[ch] = gWriteBufferPointers[ch];
+			gWriteBufferPointers[ch] = 0;
 			
-			if(gBufferPointers[ch] != 0) {
-				float mean = 0;
-				for(int n = 0; n < gBufferPointers[ch]; n++) {
-					mean += gBuffers[ch][n];
-				}
-				mean /= (float)gBufferPointers[ch];
-				
-				float rms = 0;
-				for(int n = 0; n < gBufferPointers[ch]; n++) {
-					rms += (gBuffers[ch][n] - mean) * (gBuffers[ch][n] - mean);
-				}				
-				rms = sqrtf(rms / (float)gBufferPointers[ch]);
-				
-				gDCLevels[ch] = mean;
-				gNoiseLevels[ch] = rms;
+			if(gReadBuffers[ch] == gBuffers0[ch]) {
+				gReadBuffers[ch] = gBuffers1[ch];
+				gWriteBuffers[ch] = gBuffers0[ch];
 			}
-			
-			// Reset pointer to 0 for next time
-			gBufferPointers[ch] = 0;
+			else {
+				gReadBuffers[ch] = gBuffers0[ch];
+				gWriteBuffers[ch] = gBuffers1[ch];				
+			}
 		}
 		
-		BeagleRT_scheduleAuxiliaryTask(gPrintTask);
+		BeagleRT_scheduleAuxiliaryTask(gAnalysisTask);
 	}
 }
 
-void printResults()
+void analyseResults()
 {
 	rt_printf("\e[1;1H\e[2J");	// Command to clear the screen
-	
+
 	// Print the analysis results. channels 0-1 are audio, channels 2-9 are analog
 	for(int ch = 0; ch < 10; ch++) {
-		int samples = gNumSamplesAnalysed[ch];
-		if(samples == 0)
+		// Skip unused channels
+		if(gReadBufferPointers[ch] == 0)
 			continue;
 		
+		float mean = 0;
+		for(int n = 0; n < gReadBufferPointers[ch]; n++) {
+			mean += gReadBuffers[ch][n];
+		}
+		mean /= (float)gReadBufferPointers[ch];
+		
+		float rms = 0;
+		for(int n = 0; n < gReadBufferPointers[ch]; n++) {
+			rms += (gReadBuffers[ch][n] - mean) * (gReadBuffers[ch][n] - mean);
+		}				
+		rms = sqrtf(rms / (float)gReadBufferPointers[ch]);
+		
 		if(ch == 0)
 			rt_printf("Audio In L:  ");
 		else if(ch == 1)
@@ -138,10 +144,10 @@
 			rt_printf("Analog In %d: ", ch - 2);
 		
 		rt_printf("Noise %6.1fdB    DC offset %6.4f (%6.1fdB)    window size: %d\n", 
-					20.0f * log10f(gNoiseLevels[ch]),
-					gDCLevels[ch], 
-					20.0f * log10f(fabsf(gDCLevels[ch])),
-					samples);
+					20.0f * log10f(rms),
+					mean, 
+					20.0f * log10f(fabsf(mean)),
+					gReadBufferPointers[ch]);
 	}
 }
 
@@ -150,6 +156,8 @@
 
 void cleanup(BeagleRTContext *context, void *userData)
 {
-	for(int i = 0; i < 10; i++)
-		delete gBuffers[i];
+	for(int i = 0; i < 10; i++) {
+		delete gBuffers0[i];
+		delete gBuffers1[i];
+	}
 }