Mercurial > hg > beaglert
comparison examples/measure_noisefloor/render.cpp @ 300:dbeed520b014 prerelease
Renamed projects to examples
author | Giulio Moro <giuliomoro@yahoo.it> |
---|---|
date | Fri, 27 May 2016 13:58:20 +0100 |
parents | projects/measure_noisefloor/render.cpp@241d4d5df929 |
children | e4392164b458 |
comparison
equal
deleted
inserted
replaced
297:a3d83ebdf49b | 300:dbeed520b014 |
---|---|
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 // Double buffers to hold samples for noise analysis | |
16 float *gReadBuffers[10], *gWriteBuffers[10]; | |
17 float *gBuffers0[10], *gBuffers1[10]; | |
18 | |
19 int gWriteBufferPointers[10], gReadBufferPointers[10]; | |
20 | |
21 // Task to analyse and print results which would otherwise be too slow for render() | |
22 AuxiliaryTask gAnalysisTask; | |
23 | |
24 void analyseResults(); | |
25 | |
26 // setup() is called once before the audio rendering starts. | |
27 // Use it to perform any initialisation and allocation which is dependent | |
28 // on the period size or sample rate. | |
29 // | |
30 // userData holds an opaque pointer to a data structure that was passed | |
31 // in from the call to initAudio(). | |
32 // | |
33 // Return true on success; returning false halts the program. | |
34 | |
35 bool setup(BeagleRTContext *context, void *userData) | |
36 { | |
37 // Clear the filter data structures | |
38 for(int i = 0; i < 10; i++) { | |
39 gReadBufferPointers[i] = gWriteBufferPointers[i] = 0; | |
40 gBuffers0[i] = new float[gBufferSize]; | |
41 gBuffers1[i] = new float[gBufferSize]; | |
42 gWriteBuffers[i] = gBuffers0[i]; | |
43 gReadBuffers[i] = gBuffers1[i]; | |
44 if(gBuffers0[i] == 0 || gBuffers1[i] == 0) { | |
45 rt_printf("Error allocating buffer %d\n", i); | |
46 return false; | |
47 } | |
48 } | |
49 | |
50 gAnalysisTask = BeagleRT_createAuxiliaryTask(analyseResults, 50, "beaglert-analyse-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(gWriteBufferPointers[ch] < gBufferSize) { | |
68 gWriteBuffers[ch][gWriteBufferPointers[ch]] = | |
69 context->audioIn[n * context->audioChannels + ch]; | |
70 gWriteBufferPointers[ch]++; | |
71 if(gWriteBufferPointers[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(gWriteBufferPointers[ch + 2] < gBufferSize) { | |
82 gWriteBuffers[ch + 2][gWriteBufferPointers[ch + 2]] = | |
83 context->analogIn[n * context->analogChannels + ch]; | |
84 gWriteBufferPointers[ch + 2]++; | |
85 if(gWriteBufferPointers[ch + 2] >= gBufferSize) | |
86 bufferIsFull = true; | |
87 } | |
88 | |
89 // Set all analog outputs to halfway point so they can be more | |
90 // easily measured for noise | |
91 context->analogOut[n * context->analogChannels + ch] = 0.5; | |
92 } | |
93 } | |
94 } | |
95 | |
96 | |
97 if(bufferIsFull) { | |
98 // Swap buffers and reset write pointers | |
99 for(int ch = 0; ch < 10; ch++) { | |
100 gReadBufferPointers[ch] = gWriteBufferPointers[ch]; | |
101 gWriteBufferPointers[ch] = 0; | |
102 | |
103 if(gReadBuffers[ch] == gBuffers0[ch]) { | |
104 gReadBuffers[ch] = gBuffers1[ch]; | |
105 gWriteBuffers[ch] = gBuffers0[ch]; | |
106 } | |
107 else { | |
108 gReadBuffers[ch] = gBuffers0[ch]; | |
109 gWriteBuffers[ch] = gBuffers1[ch]; | |
110 } | |
111 } | |
112 | |
113 BeagleRT_scheduleAuxiliaryTask(gAnalysisTask); | |
114 } | |
115 } | |
116 | |
117 void analyseResults() | |
118 { | |
119 rt_printf("\e[1;1H\e[2J"); // Command to clear the screen | |
120 | |
121 // Print the analysis results. channels 0-1 are audio, channels 2-9 are analog | |
122 for(int ch = 0; ch < 10; ch++) { | |
123 // Skip unused channels | |
124 if(gReadBufferPointers[ch] == 0) | |
125 continue; | |
126 | |
127 float mean = 0; | |
128 for(int n = 0; n < gReadBufferPointers[ch]; n++) { | |
129 mean += gReadBuffers[ch][n]; | |
130 } | |
131 mean /= (float)gReadBufferPointers[ch]; | |
132 | |
133 float rms = 0; | |
134 for(int n = 0; n < gReadBufferPointers[ch]; n++) { | |
135 rms += (gReadBuffers[ch][n] - mean) * (gReadBuffers[ch][n] - mean); | |
136 } | |
137 rms = sqrtf(rms / (float)gReadBufferPointers[ch]); | |
138 | |
139 if(ch == 0) | |
140 rt_printf("Audio In L: "); | |
141 else if(ch == 1) | |
142 rt_printf("Audio In R: "); | |
143 else | |
144 rt_printf("Analog In %d: ", ch - 2); | |
145 | |
146 rt_printf("Noise %6.1fdB DC offset %6.4f (%6.1fdB) window size: %d\n", | |
147 20.0f * log10f(rms), | |
148 mean, | |
149 20.0f * log10f(fabsf(mean)), | |
150 gReadBufferPointers[ch]); | |
151 } | |
152 } | |
153 | |
154 // cleanup() is called once at the end, after the audio has stopped. | |
155 // Release any resources that were allocated in setup(). | |
156 | |
157 void cleanup(BeagleRTContext *context, void *userData) | |
158 { | |
159 for(int i = 0; i < 10; i++) { | |
160 delete gBuffers0[i]; | |
161 delete gBuffers1[i]; | |
162 } | |
163 } |