annotate projects/measure_noisefloor/render.cpp @ 151:e9c9404e3d1f ClockSync

Pff partially working. No PID. When setting the audio clock on the bbb to 44098 the master and slave clock keep diverging instead of converging ...
author Giulio Moro <giuliomoro@yahoo.it>
date Tue, 22 Sep 2015 04:10:07 +0100
parents 241d4d5df929
children
rev   line source
andrewm@89 1 /*
andrewm@89 2 * render.cpp
andrewm@89 3 *
andrewm@89 4 * Created on: Oct 24, 2014
andrewm@89 5 * Author: parallels
andrewm@89 6 */
andrewm@89 7
andrewm@89 8
andrewm@89 9 #include <BeagleRT.h>
andrewm@89 10 #include <Utilities.h>
andrewm@89 11 #include <cmath>
andrewm@89 12
andrewm@89 13 int gBufferSize = 8192;
andrewm@89 14
andrewm@91 15 // Double buffers to hold samples for noise analysis
andrewm@91 16 float *gReadBuffers[10], *gWriteBuffers[10];
andrewm@91 17 float *gBuffers0[10], *gBuffers1[10];
andrewm@89 18
andrewm@91 19 int gWriteBufferPointers[10], gReadBufferPointers[10];
andrewm@89 20
andrewm@91 21 // Task to analyse and print results which would otherwise be too slow for render()
andrewm@91 22 AuxiliaryTask gAnalysisTask;
andrewm@89 23
andrewm@91 24 void analyseResults();
andrewm@89 25
andrewm@89 26 // setup() is called once before the audio rendering starts.
andrewm@89 27 // Use it to perform any initialisation and allocation which is dependent
andrewm@89 28 // on the period size or sample rate.
andrewm@89 29 //
andrewm@89 30 // userData holds an opaque pointer to a data structure that was passed
andrewm@89 31 // in from the call to initAudio().
andrewm@89 32 //
andrewm@89 33 // Return true on success; returning false halts the program.
andrewm@89 34
andrewm@89 35 bool setup(BeagleRTContext *context, void *userData)
andrewm@89 36 {
andrewm@89 37 // Clear the filter data structures
andrewm@89 38 for(int i = 0; i < 10; i++) {
andrewm@91 39 gReadBufferPointers[i] = gWriteBufferPointers[i] = 0;
andrewm@91 40 gBuffers0[i] = new float[gBufferSize];
andrewm@91 41 gBuffers1[i] = new float[gBufferSize];
andrewm@91 42 gWriteBuffers[i] = gBuffers0[i];
andrewm@91 43 gReadBuffers[i] = gBuffers1[i];
andrewm@91 44 if(gBuffers0[i] == 0 || gBuffers1[i] == 0) {
andrewm@89 45 rt_printf("Error allocating buffer %d\n", i);
andrewm@89 46 return false;
andrewm@89 47 }
andrewm@89 48 }
andrewm@89 49
andrewm@91 50 gAnalysisTask = BeagleRT_createAuxiliaryTask(analyseResults, 50, "beaglert-analyse-results");
andrewm@89 51
andrewm@89 52 return true;
andrewm@89 53 }
andrewm@89 54
andrewm@89 55 // render() is called regularly at the highest priority by the audio engine.
andrewm@89 56 // Input and output are given from the audio hardware and the other
andrewm@89 57 // ADCs and DACs (if available). If only audio is available, numMatrixFrames
andrewm@89 58 // will be 0.
andrewm@89 59
andrewm@89 60 void render(BeagleRTContext *context, void *userData)
andrewm@89 61 {
andrewm@89 62 bool bufferIsFull = false; // Whether at least one buffer has filled
andrewm@89 63
andrewm@89 64 for(unsigned int n = 0; n < context->audioFrames; n++) {
andrewm@89 65 // Store audio inputs in buffer
andrewm@89 66 for(unsigned int ch = 0; ch < context->audioChannels; ch++) {
andrewm@91 67 if(gWriteBufferPointers[ch] < gBufferSize) {
andrewm@91 68 gWriteBuffers[ch][gWriteBufferPointers[ch]] =
andrewm@89 69 context->audioIn[n * context->audioChannels + ch];
andrewm@91 70 gWriteBufferPointers[ch]++;
andrewm@91 71 if(gWriteBufferPointers[ch] >= gBufferSize)
andrewm@89 72 bufferIsFull = true;
andrewm@89 73 }
andrewm@89 74 }
andrewm@89 75 }
andrewm@89 76
andrewm@89 77 if(context->analogChannels != 0) {
andrewm@89 78 for(unsigned int n = 0; n < context->analogFrames; n++) {
andrewm@89 79 // Store analog inputs in buffer, starting at channel 2
andrewm@89 80 for(unsigned int ch = 0; ch < context->analogChannels; ch++) {
andrewm@91 81 if(gWriteBufferPointers[ch + 2] < gBufferSize) {
andrewm@91 82 gWriteBuffers[ch + 2][gWriteBufferPointers[ch + 2]] =
andrewm@89 83 context->analogIn[n * context->analogChannels + ch];
andrewm@91 84 gWriteBufferPointers[ch + 2]++;
andrewm@91 85 if(gWriteBufferPointers[ch + 2] >= gBufferSize)
andrewm@89 86 bufferIsFull = true;
andrewm@89 87 }
andrewm@91 88
andrewm@91 89 // Set all analog outputs to halfway point so they can be more
andrewm@91 90 // easily measured for noise
andrewm@91 91 context->analogOut[n * context->analogChannels + ch] = 0.5;
andrewm@89 92 }
andrewm@89 93 }
andrewm@89 94 }
andrewm@91 95
andrewm@89 96
andrewm@89 97 if(bufferIsFull) {
andrewm@91 98 // Swap buffers and reset write pointers
andrewm@89 99 for(int ch = 0; ch < 10; ch++) {
andrewm@91 100 gReadBufferPointers[ch] = gWriteBufferPointers[ch];
andrewm@91 101 gWriteBufferPointers[ch] = 0;
andrewm@89 102
andrewm@91 103 if(gReadBuffers[ch] == gBuffers0[ch]) {
andrewm@91 104 gReadBuffers[ch] = gBuffers1[ch];
andrewm@91 105 gWriteBuffers[ch] = gBuffers0[ch];
andrewm@89 106 }
andrewm@91 107 else {
andrewm@91 108 gReadBuffers[ch] = gBuffers0[ch];
andrewm@91 109 gWriteBuffers[ch] = gBuffers1[ch];
andrewm@91 110 }
andrewm@89 111 }
andrewm@89 112
andrewm@91 113 BeagleRT_scheduleAuxiliaryTask(gAnalysisTask);
andrewm@89 114 }
andrewm@89 115 }
andrewm@89 116
andrewm@91 117 void analyseResults()
andrewm@89 118 {
andrewm@89 119 rt_printf("\e[1;1H\e[2J"); // Command to clear the screen
andrewm@91 120
andrewm@89 121 // Print the analysis results. channels 0-1 are audio, channels 2-9 are analog
andrewm@89 122 for(int ch = 0; ch < 10; ch++) {
andrewm@91 123 // Skip unused channels
andrewm@91 124 if(gReadBufferPointers[ch] == 0)
andrewm@89 125 continue;
andrewm@89 126
andrewm@91 127 float mean = 0;
andrewm@91 128 for(int n = 0; n < gReadBufferPointers[ch]; n++) {
andrewm@91 129 mean += gReadBuffers[ch][n];
andrewm@91 130 }
andrewm@91 131 mean /= (float)gReadBufferPointers[ch];
andrewm@91 132
andrewm@91 133 float rms = 0;
andrewm@91 134 for(int n = 0; n < gReadBufferPointers[ch]; n++) {
andrewm@91 135 rms += (gReadBuffers[ch][n] - mean) * (gReadBuffers[ch][n] - mean);
andrewm@91 136 }
andrewm@91 137 rms = sqrtf(rms / (float)gReadBufferPointers[ch]);
andrewm@91 138
andrewm@89 139 if(ch == 0)
andrewm@89 140 rt_printf("Audio In L: ");
andrewm@89 141 else if(ch == 1)
andrewm@89 142 rt_printf("Audio In R: ");
andrewm@89 143 else
andrewm@89 144 rt_printf("Analog In %d: ", ch - 2);
andrewm@89 145
andrewm@89 146 rt_printf("Noise %6.1fdB DC offset %6.4f (%6.1fdB) window size: %d\n",
andrewm@91 147 20.0f * log10f(rms),
andrewm@91 148 mean,
andrewm@91 149 20.0f * log10f(fabsf(mean)),
andrewm@91 150 gReadBufferPointers[ch]);
andrewm@89 151 }
andrewm@89 152 }
andrewm@89 153
andrewm@89 154 // cleanup() is called once at the end, after the audio has stopped.
andrewm@89 155 // Release any resources that were allocated in setup().
andrewm@89 156
andrewm@89 157 void cleanup(BeagleRTContext *context, void *userData)
andrewm@89 158 {
andrewm@91 159 for(int i = 0; i < 10; i++) {
andrewm@91 160 delete gBuffers0[i];
andrewm@91 161 delete gBuffers1[i];
andrewm@91 162 }
andrewm@89 163 }