From 41115fc0f114c39a25a41c6955239e29bdbf037f Mon Sep 17 00:00:00 2001 From: tosh Date: Fri, 26 Apr 2013 04:25:58 +0200 Subject: [PATCH 1/2] reimplements oscilloscope and connects output channels --- interface/src/Audio.cpp | 19 +++-- interface/src/Oscilloscope.cpp | 137 ++++++++++++++++++++++++++------- interface/src/Oscilloscope.h | 51 ++++++++---- 3 files changed, 158 insertions(+), 49 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 4b522d5823..b2ff87e396 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -117,7 +117,7 @@ int audioCallback (const void *inputBuffer, // int16_t *inputRight = ((int16_t **) inputBuffer)[1]; //printLog("Audio callback at %6.0f\n", usecTimestampNow()/1000); - + if (inputLeft != NULL) { // @@ -132,13 +132,9 @@ int audioCallback (const void *inputBuffer, data->lastInputLoudness = loudness; // - // If scope is turned on, copy input buffer to scope + // Add data to the scope // - if (scope->getState()) { - for (int i = 0; i < BUFFER_LENGTH_SAMPLES; i++) { - scope->addData((float)inputLeft[i]/32767.0, 1, i); - } - } + scope->addSamples(0, inputLeft, BUFFER_LENGTH_SAMPLES); if (data->mixerAddress != 0) { sockaddr_in audioMixerSocket; @@ -334,6 +330,12 @@ int audioCallback (const void *inputBuffer, outputRight[s] = rightSample; } + // + // Add data to the scope + // + scope->addSamples(1, outputLeft, PACKET_LENGTH_SAMPLES_PER_CHANNEL); + scope->addSamples(2, outputRight, PACKET_LENGTH_SAMPLES_PER_CHANNEL); + ringBuffer->setNextOutput(ringBuffer->getNextOutput() + PACKET_LENGTH_SAMPLES); if (ringBuffer->getNextOutput() == ringBuffer->getBuffer() + RING_BUFFER_SAMPLES) { @@ -386,8 +388,9 @@ void *receiveAudioViaUDP(void *args) { delete[] directory; delete[] filename; } - + while (!stopAudioReceiveThread) { + if (sharedAudioData->audioSocket->receive((void *)receivedData, &receivedBytes)) { gettimeofday(¤tReceiveTime, NULL); diff --git a/interface/src/Oscilloscope.cpp b/interface/src/Oscilloscope.cpp index 34cf9a62c8..8c7240ffe2 100644 --- a/interface/src/Oscilloscope.cpp +++ b/interface/src/Oscilloscope.cpp @@ -8,38 +8,123 @@ #include "Oscilloscope.h" -Oscilloscope::Oscilloscope(int w, - int h, bool isOn) { - width = w; - height = h; - data1 = new float[width]; - data2 = new float[width]; - for (int i = 0; i < width; i++) { - data1[i] = 0.0; - data2[i] = 0.0; +#include "InterfaceConfig.h" +#include +#include +#include + +// Reimplemented 4/26/13 (tosh) - don't blame Philip for bugs + +using namespace std; + +namespace { // everything in here only exists while compiling this .cpp file + + // one sample buffer per channel + 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 N_COORDS_ALLOC = MAX_COORDS * Oscilloscope::MAX_CHANNELS; + + unsigned const N_ALLOC_TOTAL = N_SAMPLES_ALLOC + N_COORDS_ALLOC; +} + + +Oscilloscope::Oscilloscope(int w, int h, bool isEnabled) : + _valWidth(w), _valHeight(h), + _arrSamples(0l), _arrVertices(0l), + _valLowpass(0.4f), _valDownsample(3), + enabled(isEnabled), inputPaused(false) { + + // allocate enough space for the sample data and to turn it into + // vertices and since they're all 'short', do so in one shot + _arrSamples = new short[N_ALLOC_TOTAL]; + memset(_arrSamples, 0, N_ALLOC_TOTAL * sizeof(short)); + _arrVertices = _arrSamples + N_SAMPLES_ALLOC; + + // initialize write positions + for (unsigned ch = 0; ch < MAX_CHANNELS; ++ch) { + _arrWritePos[ch] = MAX_SAMPLES * ch; } - state = isOn; - current_sample = 0; } -void Oscilloscope::addData(float d, int channel, int position) { - if (channel == 1) data1[position] = d; - else data2[position] = d; +Oscilloscope::~Oscilloscope() { + + delete[] _arrSamples; } +void Oscilloscope::addSamples(unsigned ch, short const* data, unsigned n) { + + if (! enabled || inputPaused) { + return; + } + + unsigned baseOffs = MAX_SAMPLES * ch; + unsigned endOffs = baseOffs + MAX_SAMPLES; + + unsigned writePos = _arrWritePos[ch]; + unsigned newWritePos = writePos + n; + + unsigned n2 = 0; + if (newWritePos >= endOffs) { + n2 = newWritePos - endOffs; + newWritePos = baseOffs + n2; + n -= n2; + } + + memcpy(_arrSamples + writePos, data, n * sizeof(short)); + if (n2 > 0) { + memcpy(_arrSamples + baseOffs, data + n, n2 * sizeof(short)); + } + + _arrWritePos[ch] = newWritePos; +} + void Oscilloscope::render() { - glColor3f(1,1,1); - glBegin(GL_LINES); - for (int i = 0; i < width; i++) { - glVertex2f((float)i, height/2 + data1[i]*(float)height); + + if (! enabled) { + return; } - glEnd(); - glColor3f(0,1,1); - glBegin(GL_LINES); - for (int i = 0; i < width; i++) { - glVertex2f((float)i, height/2 + data2[i]*(float)height); - } - glEnd(); + // expand data to vertex data, now + 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; -} \ No newline at end of file + for (unsigned ch = 0; ch < MAX_CHANNELS; ++ch) { + + 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) { + inPtr = endPtr; + } + sample += ((*--inPtr - sample) * lowpass) >> 15; + if (i % downsample == 0) { + *outPtr++ = short(--x); + *outPtr++ = short(sample); + } + } + } + + glPushMatrix(); + glTranslatef(0.0f, _valHeight / 2.0f, 0.0f); + glScaled(1.0f, _valHeight / 32767.0f, 1.0f); + glVertexPointer(2, GL_SHORT, 0, _arrVertices); + glEnableClientState(GL_VERTEX_ARRAY); + glColor3f(1.0f, 1.0f, 1.0f); + glDrawArrays(GL_LINES, MAX_SAMPLES * 0, usedWidth); + glColor3f(0.0f, 1.0f ,1.0f); + glDrawArrays(GL_LINES, MAX_SAMPLES * 1, usedWidth); + glColor3f(1.0f, 1.0f ,0.0f); + glDrawArrays(GL_LINES, MAX_SAMPLES * 2, usedWidth); + glDisableClientState(GL_VERTEX_ARRAY); + glPopMatrix(); +} + diff --git a/interface/src/Oscilloscope.h b/interface/src/Oscilloscope.h index 7d925faf29..47c6375eb1 100644 --- a/interface/src/Oscilloscope.h +++ b/interface/src/Oscilloscope.h @@ -9,24 +9,45 @@ #ifndef __interface__Oscilloscope__ #define __interface__Oscilloscope__ -#include -#include "Util.h" -#include "world.h" -#include "InterfaceConfig.h" +#include class Oscilloscope { public: - Oscilloscope(int width, - int height, bool isOn); - void addData(float d, int channel, int position); - void render(); - void setState(bool s) {state = s;}; - bool getState() {return state;}; + static unsigned const MAX_CHANNELS = 3; + static unsigned const MAX_SAMPLES = 4096; // per channel private: - int width; - int height; - float *data1, *data2; - int current_sample; - bool state; + 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(); + + volatile bool enabled; + volatile bool inputPaused; + + + void addSamples(unsigned ch, short const* data, unsigned n); + + void render(); + + void setLowpass(float w) { assert(w > 0.0f && w <= 1.0f); _valLowpass = w; } + void setDownsampling(unsigned f) { assert(f > 0); _valDownsample = f; } + +private: + // don't copy/assign + Oscilloscope(Oscilloscope const&); // = delete; + Oscilloscope& operator=(Oscilloscope const&); // = delete; + + // implementation + inline short* bufferBase(int i, int channel); }; + #endif /* defined(__interface__oscilloscope__) */ From 95f2b4373d4b24fa6ebccf2186020373cf8813ae Mon Sep 17 00:00:00 2001 From: tosh Date: Fri, 26 Apr 2013 05:09:00 +0200 Subject: [PATCH 2/2] adjusts main.cpp (oscilloscope does not render when disabled and does no longer need an external check) --- interface/src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 06478f4a7e..5fbdb980e2 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -973,7 +973,7 @@ void display(void) #ifndef _WIN32 audio.render(WIDTH, HEIGHT); - if (audioScope.getState()) audioScope.render(); + audioScope.render(); #endif if (displayHeadMouse && !::lookingInMirror && statsOn) {