From 539e69cef02d3a047706f0947f840187795e8ae4 Mon Sep 17 00:00:00 2001 From: tosh Date: Thu, 16 May 2013 18:56:20 +0200 Subject: [PATCH 1/2] puts private members to the bottom of the class definition --- interface/src/Oscilloscope.h | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/interface/src/Oscilloscope.h b/interface/src/Oscilloscope.h index 2474753cdf..ea828b8bcf 100644 --- a/interface/src/Oscilloscope.h +++ b/interface/src/Oscilloscope.h @@ -15,17 +15,6 @@ class Oscilloscope { public: static unsigned const MAX_CHANNELS = 3; static unsigned const MAX_SAMPLES = 4096; // per channel -private: - unsigned _valWidth; - unsigned _valHeight; - short* _arrSamples; - short* _arrVertices; - unsigned _arrWritePos[MAX_CHANNELS]; - - float _valLowpass; - unsigned _valDownsample; - -public: Oscilloscope(int width, int height, bool isEnabled); ~Oscilloscope(); @@ -33,7 +22,6 @@ public: volatile bool enabled; volatile bool inputPaused; - void addSamples(unsigned ch, short const* data, unsigned n); void render(int x, int y); @@ -48,6 +36,15 @@ private: // implementation inline short* bufferBase(int i, int channel); + + unsigned _valWidth; + unsigned _valHeight; + short* _arrSamples; + short* _arrVertices; + unsigned _arrWritePos[MAX_CHANNELS]; + + float _valLowpass; + unsigned _valDownsample; }; #endif /* defined(__interface__oscilloscope__) */ From 489a0cb844157623f3fd7065b0bcd717ebc6acd0 Mon Sep 17 00:00:00 2001 From: tosh Date: Thu, 16 May 2013 18:56:32 +0200 Subject: [PATCH 2/2] adds comments and blank lines to clarify the code --- interface/src/Oscilloscope.cpp | 52 +++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/interface/src/Oscilloscope.cpp b/interface/src/Oscilloscope.cpp index dc582d4c49..ec22b2165a 100644 --- a/interface/src/Oscilloscope.cpp +++ b/interface/src/Oscilloscope.cpp @@ -23,9 +23,11 @@ namespace { // everything in here only exists while compiling this .cpp file unsigned const N_SAMPLES_ALLOC = Oscilloscope::MAX_SAMPLES * Oscilloscope::MAX_CHANNELS; // adding an x-coordinate yields twice the amount of vertices - unsigned const MAX_COORDS = Oscilloscope::MAX_SAMPLES * 2; + unsigned const MAX_COORDS = Oscilloscope::MAX_SAMPLES * 2; + // allocated once for each channel unsigned const N_COORDS_ALLOC = MAX_COORDS * Oscilloscope::MAX_CHANNELS; - + + // total amount of memory to allocate (in 16-bit integers)` unsigned const N_ALLOC_TOTAL = N_SAMPLES_ALLOC + N_COORDS_ALLOC; } @@ -42,7 +44,7 @@ Oscilloscope::Oscilloscope(int w, int h, bool isEnabled) : memset(_arrSamples, 0, N_ALLOC_TOTAL * sizeof(short)); _arrVertices = _arrSamples + N_SAMPLES_ALLOC; - // initialize write positions + // initialize write positions to start of each channel's region for (unsigned ch = 0; ch < MAX_CHANNELS; ++ch) { _arrWritePos[ch] = MAX_SAMPLES * ch; } @@ -58,25 +60,31 @@ void Oscilloscope::addSamples(unsigned ch, short const* data, unsigned n) { if (! enabled || inputPaused) { return; } - + + // determine start/end offset of this channel's region unsigned baseOffs = MAX_SAMPLES * ch; unsigned endOffs = baseOffs + MAX_SAMPLES; - - unsigned writePos = _arrWritePos[ch]; - unsigned newWritePos = writePos + n; + // fetch write position for this channel + unsigned writePos = _arrWritePos[ch]; + + // determine write position after adding the samples + unsigned newWritePos = writePos + n; unsigned n2 = 0; if (newWritePos >= endOffs) { + // passed boundary of the circular buffer? -> we need to copy two blocks n2 = newWritePos - endOffs; newWritePos = baseOffs + n2; n -= n2; } - + + // copy data memcpy(_arrSamples + writePos, data, n * sizeof(short)); if (n2 > 0) { memcpy(_arrSamples + baseOffs, data + n, n2 * sizeof(short)); } - + + // set new write position for this channel _arrWritePos[ch] = newWritePos; } @@ -85,46 +93,58 @@ void Oscilloscope::render(int x, int y) { if (! enabled) { return; } - - // expand data to vertex data, now + + // determine lowpass / downsample factors int lowpass = -int(std::numeric_limits::min()) * _valLowpass; unsigned downsample = _valDownsample; // keep half of the buffer for writing and ensure an even vertex count unsigned usedWidth = min(_valWidth, MAX_SAMPLES / (downsample * 2)) & ~1u; unsigned usedSamples = usedWidth * downsample; + // expand samples to vertex data for (unsigned ch = 0; ch < MAX_CHANNELS; ++ch) { - + // for each channel: determine memory regions short const* basePtr = _arrSamples + MAX_SAMPLES * ch; short const* endPtr = basePtr + MAX_SAMPLES; short const* inPtr = _arrSamples + _arrWritePos[ch]; short* outPtr = _arrVertices + MAX_COORDS * ch; int sample = 0, x = usedWidth; for (int i = int(usedSamples); --i >= 0 ;) { - if (inPtr == basePtr) { + // handle boundary, reading the circular sample buffer inPtr = endPtr; } - sample += ((*--inPtr - sample) * lowpass) >> 15; + // read and (eventually) filter sample + sample += ((*--inPtr - sample) * lowpass) >> 15; + // write every nth as y with a corresponding x-coordinate if (i % downsample == 0) { *outPtr++ = short(--x); *outPtr++ = short(sample); } } } - - glLineWidth(2.0); + + // set up rendering state (vertex data lives at _arrVertices) glPushMatrix(); + glLineWidth(2.0); glTranslatef((float)x + 0.0f, (float)y + _valHeight / 2.0f, 0.0f); glScaled(1.0f, _valHeight / 32767.0f, 1.0f); glVertexPointer(2, GL_SHORT, 0, _arrVertices); glEnableClientState(GL_VERTEX_ARRAY); + + // batch channel 0 glColor3f(1.0f, 1.0f, 1.0f); glDrawArrays(GL_LINES, MAX_SAMPLES * 0, usedWidth); + + // batch channel 1 glColor3f(0.0f, 1.0f ,1.0f); glDrawArrays(GL_LINES, MAX_SAMPLES * 1, usedWidth); + + // batch channel 2 glColor3f(1.0f, 1.0f ,0.0f); glDrawArrays(GL_LINES, MAX_SAMPLES * 2, usedWidth); + + // reset rendering state glDisableClientState(GL_VERTEX_ARRAY); glPopMatrix(); }