From 27f0214032989e4e8eb32e6cfd0a5a0acb8e5d66 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Fri, 28 Mar 2014 23:09:51 -0700 Subject: [PATCH] first pass audio VU scope --- interface/src/Application.cpp | 106 ++++++++++++++++++++++++---------- interface/src/Application.h | 1 + interface/src/Menu.cpp | 2 +- 3 files changed, 78 insertions(+), 31 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 98f260c3bf..1974ddd60c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -151,6 +151,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : _lastQueriedViewFrustum(), _lastQueriedTime(usecTimestampNow()), _audioScope(256, 200, true), + _trailingAudioLoudness(0.f), _mirrorViewRect(QRect(MIRROR_VIEW_LEFT_PADDING, MIRROR_VIEW_TOP_PADDING, MIRROR_VIEW_WIDTH, MIRROR_VIEW_HEIGHT)), _mouseX(0), _mouseY(0), @@ -2504,56 +2505,101 @@ void Application::displayOverlay() { } } + // Audio Scope + const int AUDIO_SCOPE_Y_OFFSET = 135; if (Menu::getInstance()->isOptionChecked(MenuOption::Stats)) { - _audio.renderMuteIcon(1, _glWidget->height() - 50); if (Menu::getInstance()->isOptionChecked(MenuOption::Oscilloscope)) { - int oscilloscopeTop = _glWidget->height() - 135; - _audioScope.render(25, oscilloscopeTop); + int oscilloscopeTop = _glWidget->height() - AUDIO_SCOPE_Y_OFFSET; + _audioScope.render(MIRROR_VIEW_LEFT_PADDING, oscilloscopeTop); } } - const int AUDIO_METER_WIDTH = 200; + // Audio VU Meter and Mute Icon + const int MUTE_ICON_SIZE = 24; const int AUDIO_METER_INSET = 2; + const int AUDIO_METER_WIDTH = MIRROR_VIEW_WIDTH - MUTE_ICON_SIZE - AUDIO_METER_INSET; 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 int AUDIO_METER_Y_GAP = 8; + const int AUDIO_METER_X = MIRROR_VIEW_LEFT_PADDING + MUTE_ICON_SIZE + AUDIO_METER_INSET; + + int audioMeterY; + if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { + audioMeterY = MIRROR_VIEW_HEIGHT + AUDIO_METER_Y_GAP; + } else { + audioMeterY = AUDIO_METER_Y_GAP; + } + _audio.renderMuteIcon(MIRROR_VIEW_LEFT_PADDING, audioMeterY); + + + const float AUDIO_METER_BLUE[] = {0.0, 0.0, 1.0}; + const float AUDIO_METER_GREEN[] = {0.0, 1.0, 0.0}; + const float AUDIO_METER_RED[] = {1.0, 0.0, 0.0}; + const float AUDIO_GREEN_START = 0.25 * AUDIO_METER_SCALE_WIDTH; + const float AUDIO_RED_START = 0.80 * AUDIO_METER_SCALE_WIDTH; const float CLIPPING_INDICATOR_TIME = 1.0f; + const float AUDIO_METER_AVERAGING = 0.5; const float LOG2 = log(2.f); + const float MAX_LOG2_SAMPLE = 15.f; float audioLevel = 0.f; float loudness = _audio.getLastInputLoudness() + 1.f; - float log2loudness = log(loudness) / LOG2; - if (loudness < 2048) { - audioLevel = (log2loudness / 11.f) * (AUDIO_METER_SCALE_WIDTH / 5.f); - } else { - audioLevel = (log2loudness - 10.f) * (AUDIO_METER_SCALE_WIDTH / 5.f); - } + _trailingAudioLoudness = AUDIO_METER_AVERAGING * _trailingAudioLoudness + (1.f - AUDIO_METER_AVERAGING) * loudness; + + float log2loudness = log(_trailingAudioLoudness) / LOG2; + + audioLevel = log2loudness / MAX_LOG2_SAMPLE * AUDIO_METER_SCALE_WIDTH; + bool isClipping = ((_audio.getTimeSinceLastClip() > 0.f) && (_audio.getTimeSinceLastClip() < CLIPPING_INDICATOR_TIME)); + glBegin(GL_QUADS); 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 audio meter background Quad + glVertex2i(AUDIO_METER_X, audioMeterY); + glVertex2i(AUDIO_METER_X + AUDIO_METER_WIDTH, audioMeterY); + glVertex2i(AUDIO_METER_X + AUDIO_METER_WIDTH, audioMeterY + AUDIO_METER_HEIGHT); + glVertex2i(AUDIO_METER_X, audioMeterY + AUDIO_METER_HEIGHT); + + if (audioLevel > AUDIO_RED_START) { + if (!isClipping) { + glColor3fv(AUDIO_METER_RED); + } else { + glColor3f(1, 1, 1); + } + // Draw Red Quad + glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET + AUDIO_RED_START, audioMeterY + AUDIO_METER_INSET); + glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET + audioLevel, audioMeterY + AUDIO_METER_INSET); + glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET + audioLevel, audioMeterY + AUDIO_METER_HEIGHT - AUDIO_METER_INSET); + glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET + AUDIO_RED_START, audioMeterY + AUDIO_METER_HEIGHT - AUDIO_METER_INSET); + audioLevel = AUDIO_RED_START; } - // 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); - + if (audioLevel > AUDIO_GREEN_START) { + if (!isClipping) { + glColor3fv(AUDIO_METER_GREEN); + } else { + glColor3f(1, 1, 1); + } + // Draw Green Quad + glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET + AUDIO_GREEN_START, audioMeterY + AUDIO_METER_INSET); + glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET + audioLevel, audioMeterY + AUDIO_METER_INSET); + glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET + audioLevel, audioMeterY + AUDIO_METER_HEIGHT - AUDIO_METER_INSET); + glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET + AUDIO_GREEN_START, audioMeterY + AUDIO_METER_HEIGHT - AUDIO_METER_INSET); + audioLevel = AUDIO_GREEN_START; + } + // Draw Blue Quad + if (!isClipping) { + glColor3fv(AUDIO_METER_BLUE); + } else { + glColor3f(1, 1, 1); + } + // Draw Blue (low level) quad + glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET, audioMeterY + AUDIO_METER_INSET); + glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET + audioLevel, audioMeterY + AUDIO_METER_INSET); + glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET + audioLevel, audioMeterY + AUDIO_METER_HEIGHT - AUDIO_METER_INSET); + glVertex2i(AUDIO_METER_X + AUDIO_METER_INSET, audioMeterY + AUDIO_METER_HEIGHT - AUDIO_METER_INSET); glEnd(); if (Menu::getInstance()->isOptionChecked(MenuOption::HeadMouse)) { diff --git a/interface/src/Application.h b/interface/src/Application.h index 15778f2a17..af77adb8fc 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -397,6 +397,7 @@ private: quint64 _lastQueriedTime; Oscilloscope _audioScope; + float _trailingAudioLoudness; OctreeQuery _octreeQuery; // NodeData derived class for querying voxels from voxel server diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 7748c466c7..4d93016d4e 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -241,7 +241,7 @@ Menu::Menu() : addDisabledActionAndSeparator(viewMenu, "Stats"); addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Stats, Qt::Key_Slash); addActionToQMenuAndActionHash(viewMenu, MenuOption::Log, Qt::CTRL | Qt::Key_L, appInstance, SLOT(toggleLogDialog())); - addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Oscilloscope, 0, true); + addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Oscilloscope, 0, false); addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Bandwidth, 0, true); addActionToQMenuAndActionHash(viewMenu, MenuOption::BandwidthDetails, 0, this, SLOT(bandwidthDetails())); addActionToQMenuAndActionHash(viewMenu, MenuOption::OctreeStats, 0, this, SLOT(octreeStatsDetails()));