Mercurial > hg > beaglert
comparison examples/04-Audio/measure-noisefloor/render.cpp @ 464:8fcfbfb32aa0 prerelease
Examples reorder with subdirectories. Added header to each project. Moved Doxygen to bottom of render.cpp.
author | Robert Jack <robert.h.jack@gmail.com> |
---|---|
date | Mon, 20 Jun 2016 16:20:38 +0100 |
parents | |
children | cdabbaf3a252 |
comparison
equal
deleted
inserted
replaced
463:c47709e8b5c9 | 464:8fcfbfb32aa0 |
---|---|
1 /* | |
2 ____ _____ _ _ | |
3 | __ )| ____| | / \ | |
4 | _ \| _| | | / _ \ | |
5 | |_) | |___| |___ / ___ \ | |
6 |____/|_____|_____/_/ \_\ | |
7 | |
8 The platform for ultra-low latency audio and sensor processing | |
9 | |
10 http://bela.io | |
11 | |
12 A project of the Augmented Instruments Laboratory within the | |
13 Centre for Digital Music at Queen Mary University of London. | |
14 http://www.eecs.qmul.ac.uk/~andrewm | |
15 | |
16 (c) 2016 Augmented Instruments Laboratory: Andrew McPherson, | |
17 Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack, | |
18 Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved. | |
19 | |
20 The Bela software is distributed under the GNU Lesser General Public License | |
21 (LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt | |
22 */ | |
23 | |
24 | |
25 #include <Bela.h> | |
26 #include <cmath> | |
27 | |
28 int gBufferSize = 8192; | |
29 | |
30 // Double buffers to hold samples for noise analysis | |
31 float *gReadBuffers[10], *gWriteBuffers[10]; | |
32 float *gBuffers0[10], *gBuffers1[10]; | |
33 | |
34 int gWriteBufferPointers[10], gReadBufferPointers[10]; | |
35 | |
36 // Task to analyse and print results which would otherwise be too slow for render() | |
37 AuxiliaryTask gAnalysisTask; | |
38 | |
39 void analyseResults(); | |
40 | |
41 // setup() is called once before the audio rendering starts. | |
42 // Use it to perform any initialisation and allocation which is dependent | |
43 // on the period size or sample rate. | |
44 // | |
45 // userData holds an opaque pointer to a data structure that was passed | |
46 // in from the call to initAudio(). | |
47 // | |
48 // Return true on success; returning false halts the program. | |
49 | |
50 bool setup(BelaContext *context, void *userData) | |
51 { | |
52 // Clear the filter data structures | |
53 for(int i = 0; i < 10; i++) { | |
54 gReadBufferPointers[i] = gWriteBufferPointers[i] = 0; | |
55 gBuffers0[i] = new float[gBufferSize]; | |
56 gBuffers1[i] = new float[gBufferSize]; | |
57 gWriteBuffers[i] = gBuffers0[i]; | |
58 gReadBuffers[i] = gBuffers1[i]; | |
59 if(gBuffers0[i] == 0 || gBuffers1[i] == 0) { | |
60 rt_printf("Error allocating buffer %d\n", i); | |
61 return false; | |
62 } | |
63 } | |
64 | |
65 gAnalysisTask = Bela_createAuxiliaryTask(analyseResults, 50, "bela-analyse-results"); | |
66 | |
67 return true; | |
68 } | |
69 | |
70 // render() is called regularly at the highest priority by the audio engine. | |
71 // Input and output are given from the audio hardware and the other | |
72 // ADCs and DACs (if available). If only audio is available, numMatrixFrames | |
73 // will be 0. | |
74 | |
75 void render(BelaContext *context, void *userData) | |
76 { | |
77 bool bufferIsFull = false; // Whether at least one buffer has filled | |
78 | |
79 for(unsigned int n = 0; n < context->audioFrames; n++) { | |
80 // Store audio inputs in buffer | |
81 for(unsigned int ch = 0; ch < context->audioChannels; ch++) { | |
82 if(gWriteBufferPointers[ch] < gBufferSize) { | |
83 gWriteBuffers[ch][gWriteBufferPointers[ch]] = | |
84 context->audioIn[n * context->audioChannels + ch]; | |
85 gWriteBufferPointers[ch]++; | |
86 if(gWriteBufferPointers[ch] >= gBufferSize) | |
87 bufferIsFull = true; | |
88 } | |
89 } | |
90 } | |
91 | |
92 if(context->analogChannels != 0) { | |
93 for(unsigned int n = 0; n < context->analogFrames; n++) { | |
94 // Store analog inputs in buffer, starting at channel 2 | |
95 for(unsigned int ch = 0; ch < context->analogChannels; ch++) { | |
96 if(gWriteBufferPointers[ch + 2] < gBufferSize) { | |
97 gWriteBuffers[ch + 2][gWriteBufferPointers[ch + 2]] = | |
98 context->analogIn[n * context->analogChannels + ch]; | |
99 gWriteBufferPointers[ch + 2]++; | |
100 if(gWriteBufferPointers[ch + 2] >= gBufferSize) | |
101 bufferIsFull = true; | |
102 } | |
103 | |
104 // Set all analog outputs to halfway point so they can be more | |
105 // easily measured for noise | |
106 context->analogOut[n * context->analogChannels + ch] = 0.5; | |
107 } | |
108 } | |
109 } | |
110 | |
111 | |
112 if(bufferIsFull) { | |
113 // Swap buffers and reset write pointers | |
114 for(int ch = 0; ch < 10; ch++) { | |
115 gReadBufferPointers[ch] = gWriteBufferPointers[ch]; | |
116 gWriteBufferPointers[ch] = 0; | |
117 | |
118 if(gReadBuffers[ch] == gBuffers0[ch]) { | |
119 gReadBuffers[ch] = gBuffers1[ch]; | |
120 gWriteBuffers[ch] = gBuffers0[ch]; | |
121 } | |
122 else { | |
123 gReadBuffers[ch] = gBuffers0[ch]; | |
124 gWriteBuffers[ch] = gBuffers1[ch]; | |
125 } | |
126 } | |
127 | |
128 Bela_scheduleAuxiliaryTask(gAnalysisTask); | |
129 } | |
130 } | |
131 | |
132 void analyseResults() | |
133 { | |
134 rt_printf("\e[1;1H\e[2J"); // Command to clear the screen | |
135 | |
136 // Print the analysis results. channels 0-1 are audio, channels 2-9 are analog | |
137 for(int ch = 0; ch < 10; ch++) { | |
138 // Skip unused channels | |
139 if(gReadBufferPointers[ch] == 0) | |
140 continue; | |
141 | |
142 float mean = 0; | |
143 for(int n = 0; n < gReadBufferPointers[ch]; n++) { | |
144 mean += gReadBuffers[ch][n]; | |
145 } | |
146 mean /= (float)gReadBufferPointers[ch]; | |
147 | |
148 float rms = 0; | |
149 for(int n = 0; n < gReadBufferPointers[ch]; n++) { | |
150 rms += (gReadBuffers[ch][n] - mean) * (gReadBuffers[ch][n] - mean); | |
151 } | |
152 rms = sqrtf(rms / (float)gReadBufferPointers[ch]); | |
153 | |
154 if(ch == 0) | |
155 rt_printf("Audio In L: "); | |
156 else if(ch == 1) | |
157 rt_printf("Audio In R: "); | |
158 else | |
159 rt_printf("Analog In %d: ", ch - 2); | |
160 | |
161 rt_printf("Noise %6.1fdB DC offset %6.4f (%6.1fdB) window size: %d\n", | |
162 20.0f * log10f(rms), | |
163 mean, | |
164 20.0f * log10f(fabsf(mean)), | |
165 gReadBufferPointers[ch]); | |
166 } | |
167 } | |
168 | |
169 // cleanup() is called once at the end, after the audio has stopped. | |
170 // Release any resources that were allocated in setup(). | |
171 | |
172 void cleanup(BelaContext *context, void *userData) | |
173 { | |
174 for(int i = 0; i < 10; i++) { | |
175 delete gBuffers0[i]; | |
176 delete gBuffers1[i]; | |
177 } | |
178 } |