From d90244c01ef4715b2600e28e229cab73c19b432c Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Tue, 25 Mar 2014 22:31:44 -0700 Subject: [PATCH] first pass, clipping audio meter --- interface/src/Application.cpp | 38 ++++++++++++++++++++++++++++++++++- interface/src/Audio.cpp | 10 +++++++++ interface/src/Audio.h | 2 ++ 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 13c05fa702..549d1f04e2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2494,7 +2494,7 @@ void Application::displayOverlay() { renderCollisionOverlay(_glWidget->width(), _glWidget->height(), _audio.getCollisionSoundMagnitude()); } } - + if (Menu::getInstance()->isOptionChecked(MenuOption::Stats)) { _audio.renderMuteIcon(1, _glWidget->height() - 50); if (Menu::getInstance()->isOptionChecked(MenuOption::Oscilloscope)) { @@ -2502,6 +2502,42 @@ void Application::displayOverlay() { _audioScope.render(25, oscilloscopeTop); } } + + const int AUDIO_METER_WIDTH = 300; + const int AUDIO_METER_INSET = 2; + const int AUDIO_METER_SCALE_WIDTH = AUDIO_METER_WIDTH - 2 * AUDIO_METER_INSET; + const int AUDIO_METER_HEIGHT = 8; + const int AUDIO_METER_Y = _glWidget->height() - 40; + const int AUDIO_METER_X = 25; + const float CLIPPING_INDICATOR_TIME = 1.0f; + float audioLevel = log10(_audio.getLastInputLoudness() + 1.0) / log10(32767.0) * (float)AUDIO_METER_SCALE_WIDTH; + bool isClipping = ((_audio.getTimeSinceLastClip() > 0.f) && (_audio.getTimeSinceLastClip() < CLIPPING_INDICATOR_TIME)); + + if (isClipping) { + glColor3f(1, 0, 0); + } else { + glColor3f(0, 0, 0); + } + glBegin(GL_QUADS); + // Draw background Quad + glVertex2i(AUDIO_METER_X, AUDIO_METER_Y); + glVertex2i(AUDIO_METER_X + AUDIO_METER_WIDTH, AUDIO_METER_Y); + glVertex2i(AUDIO_METER_X + AUDIO_METER_WIDTH, AUDIO_METER_Y + AUDIO_METER_HEIGHT); + glVertex2i(AUDIO_METER_X, AUDIO_METER_Y + AUDIO_METER_HEIGHT); + + // Draw Meter Quad + if (isClipping) { + glColor3f(1, 1, 1); + } else { + glColor3f(0, 1, 1); + } + // Draw Meter quad + glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET, AUDIO_METER_Y + AUDIO_METER_INSET); + glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET + audioLevel, AUDIO_METER_Y + AUDIO_METER_INSET); + glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET + audioLevel, AUDIO_METER_Y + AUDIO_METER_HEIGHT - AUDIO_METER_INSET); + glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET, AUDIO_METER_Y + AUDIO_METER_HEIGHT - AUDIO_METER_INSET); + + glEnd(); if (Menu::getInstance()->isOptionChecked(MenuOption::HeadMouse)) { _myAvatar->renderHeadMouse(); diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 734b5345fb..92bbea3afe 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -60,6 +60,7 @@ Audio::Audio(Oscilloscope* scope, int16_t initialJitterBufferSamples, QObject* p _measuredJitter(0), _jitterBufferSamples(initialJitterBufferSamples), _lastInputLoudness(0), + _timeSinceLastClip(-1.0), _dcOffset(0), _noiseGateMeasuredFloor(0), _noiseGateSampleCounter(0), @@ -469,13 +470,22 @@ void Audio::handleAudioInput() { const int NOISE_GATE_CLOSE_FRAME_DELAY = 5; const int NOISE_GATE_FRAMES_TO_AVERAGE = 5; const float DC_OFFSET_AVERAGING = 0.99f; + const float CLIPPING_THRESHOLD = 0.90f; float measuredDcOffset = 0.f; + // Increment the time since the last clip + if (_timeSinceLastClip >= 0.0f) { + _timeSinceLastClip += (float) NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL / (float) SAMPLE_RATE; + } + for (int i = 0; i < NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL; i++) { measuredDcOffset += monoAudioSamples[i]; monoAudioSamples[i] -= (int16_t) _dcOffset; thisSample = fabsf(monoAudioSamples[i]); + if (thisSample > (32767.f * CLIPPING_THRESHOLD)) { + _timeSinceLastClip = 0.0f; + } loudness += thisSample; // Noise Reduction: Count peaks above the average loudness if (thisSample > (_noiseGateMeasuredFloor * NOISE_GATE_HEIGHT)) { diff --git a/interface/src/Audio.h b/interface/src/Audio.h index 7aa1ef5afe..2d79e82918 100644 --- a/interface/src/Audio.h +++ b/interface/src/Audio.h @@ -47,6 +47,7 @@ public: Audio(Oscilloscope* scope, int16_t initialJitterBufferSamples, QObject* parent = 0); float getLastInputLoudness() const { return glm::max(_lastInputLoudness - _noiseGateMeasuredFloor, 0.f); } + float getTimeSinceLastClip() const { return _timeSinceLastClip; } float getAudioAverageInputLoudness() const { return _lastInputLoudness; } void setNoiseGateEnabled(bool noiseGateEnabled) { _noiseGateEnabled = noiseGateEnabled; } @@ -130,6 +131,7 @@ private: float _measuredJitter; int16_t _jitterBufferSamples; float _lastInputLoudness; + float _timeSinceLastClip; float _dcOffset; float _noiseGateMeasuredFloor; float* _noiseSampleFrames;