Mercurial > hg > beaglert
comparison projects/measure_noisefloor/render.cpp @ 89:d41631e0fe0e
Added noise floor measurement project; also added option to run script to run without screen
author | andrewm |
---|---|
date | Sun, 19 Jul 2015 16:15:28 +0100 |
parents | |
children | 241d4d5df929 |
comparison
equal
deleted
inserted
replaced
88:3a5823f7a11f | 89:d41631e0fe0e |
---|---|
1 /* | |
2 * render.cpp | |
3 * | |
4 * Created on: Oct 24, 2014 | |
5 * Author: parallels | |
6 */ | |
7 | |
8 | |
9 #include <BeagleRT.h> | |
10 #include <Utilities.h> | |
11 #include <cmath> | |
12 | |
13 int gBufferSize = 8192; | |
14 | |
15 // Buffers to hold samples for noise analysis | |
16 float* gBuffers[10]; | |
17 int gBufferPointers[10]; | |
18 | |
19 // Outputs to display | |
20 float gDCLevels[10]; | |
21 float gNoiseLevels[10]; | |
22 float gNumSamplesAnalysed[10]; | |
23 | |
24 // Task to print results which would otherwise be too slow for render() | |
25 AuxiliaryTask gPrintTask; | |
26 | |
27 void printResults(); | |
28 | |
29 // setup() is called once before the audio rendering starts. | |
30 // Use it to perform any initialisation and allocation which is dependent | |
31 // on the period size or sample rate. | |
32 // | |
33 // userData holds an opaque pointer to a data structure that was passed | |
34 // in from the call to initAudio(). | |
35 // | |
36 // Return true on success; returning false halts the program. | |
37 | |
38 bool setup(BeagleRTContext *context, void *userData) | |
39 { | |
40 // Clear the filter data structures | |
41 for(int i = 0; i < 10; i++) { | |
42 gBufferPointers[i] = 0; | |
43 gBuffers[i] = new float[gBufferSize]; | |
44 if(gBuffers[i] == 0) { | |
45 rt_printf("Error allocating buffer %d\n", i); | |
46 return false; | |
47 } | |
48 } | |
49 | |
50 gPrintTask = BeagleRT_createAuxiliaryTask(printResults, 50, "beaglert-print-results"); | |
51 | |
52 return true; | |
53 } | |
54 | |
55 // render() is called regularly at the highest priority by the audio engine. | |
56 // Input and output are given from the audio hardware and the other | |
57 // ADCs and DACs (if available). If only audio is available, numMatrixFrames | |
58 // will be 0. | |
59 | |
60 void render(BeagleRTContext *context, void *userData) | |
61 { | |
62 bool bufferIsFull = false; // Whether at least one buffer has filled | |
63 | |
64 for(unsigned int n = 0; n < context->audioFrames; n++) { | |
65 // Store audio inputs in buffer | |
66 for(unsigned int ch = 0; ch < context->audioChannels; ch++) { | |
67 if(gBufferPointers[ch] < gBufferSize) { | |
68 gBuffers[ch][gBufferPointers[ch]] = | |
69 context->audioIn[n * context->audioChannels + ch]; | |
70 gBufferPointers[ch]++; | |
71 if(gBufferPointers[ch] >= gBufferSize) | |
72 bufferIsFull = true; | |
73 } | |
74 } | |
75 } | |
76 | |
77 if(context->analogChannels != 0) { | |
78 for(unsigned int n = 0; n < context->analogFrames; n++) { | |
79 // Store analog inputs in buffer, starting at channel 2 | |
80 for(unsigned int ch = 0; ch < context->analogChannels; ch++) { | |
81 if(gBufferPointers[ch + 2] < gBufferSize) { | |
82 gBuffers[ch + 2][gBufferPointers[ch + 2]] = | |
83 context->analogIn[n * context->analogChannels + ch]; | |
84 gBufferPointers[ch + 2]++; | |
85 if(gBufferPointers[ch + 2] >= gBufferSize) | |
86 bufferIsFull = true; | |
87 } | |
88 } | |
89 } | |
90 } | |
91 | |
92 if(bufferIsFull) { | |
93 // Analyse all active channels at once | |
94 for(int ch = 0; ch < 10; ch++) { | |
95 // gBufferPointers[ch] tells us how many samples were stored in the buffer | |
96 gNumSamplesAnalysed[ch] = gBufferPointers[ch]; | |
97 | |
98 if(gBufferPointers[ch] != 0) { | |
99 float mean = 0; | |
100 for(int n = 0; n < gBufferPointers[ch]; n++) { | |
101 mean += gBuffers[ch][n]; | |
102 } | |
103 mean /= (float)gBufferPointers[ch]; | |
104 | |
105 float rms = 0; | |
106 for(int n = 0; n < gBufferPointers[ch]; n++) { | |
107 rms += (gBuffers[ch][n] - mean) * (gBuffers[ch][n] - mean); | |
108 } | |
109 rms = sqrtf(rms / (float)gBufferPointers[ch]); | |
110 | |
111 gDCLevels[ch] = mean; | |
112 gNoiseLevels[ch] = rms; | |
113 } | |
114 | |
115 // Reset pointer to 0 for next time | |
116 gBufferPointers[ch] = 0; | |
117 } | |
118 | |
119 BeagleRT_scheduleAuxiliaryTask(gPrintTask); | |
120 } | |
121 } | |
122 | |
123 void printResults() | |
124 { | |
125 rt_printf("\e[1;1H\e[2J"); // Command to clear the screen | |
126 | |
127 // Print the analysis results. channels 0-1 are audio, channels 2-9 are analog | |
128 for(int ch = 0; ch < 10; ch++) { | |
129 int samples = gNumSamplesAnalysed[ch]; | |
130 if(samples == 0) | |
131 continue; | |
132 | |
133 if(ch == 0) | |
134 rt_printf("Audio In L: "); | |
135 else if(ch == 1) | |
136 rt_printf("Audio In R: "); | |
137 else | |
138 rt_printf("Analog In %d: ", ch - 2); | |
139 | |
140 rt_printf("Noise %6.1fdB DC offset %6.4f (%6.1fdB) window size: %d\n", | |
141 20.0f * log10f(gNoiseLevels[ch]), | |
142 gDCLevels[ch], | |
143 20.0f * log10f(fabsf(gDCLevels[ch])), | |
144 samples); | |
145 } | |
146 } | |
147 | |
148 // cleanup() is called once at the end, after the audio has stopped. | |
149 // Release any resources that were allocated in setup(). | |
150 | |
151 void cleanup(BeagleRTContext *context, void *userData) | |
152 { | |
153 for(int i = 0; i < 10; i++) | |
154 delete gBuffers[i]; | |
155 } |