From 925f8241e5062baf69cdc3d63209c41458596034 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Tue, 25 Mar 2014 11:48:46 -0700 Subject: [PATCH 1/8] adding joint animation --- examples/bot.js | 53 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 11 deletions(-) diff --git a/examples/bot.js b/examples/bot.js index ea78f40de9..c606b55274 100644 --- a/examples/bot.js +++ b/examples/bot.js @@ -23,10 +23,10 @@ function printVector(string, vector) { } var CHANCE_OF_MOVING = 0.005; -var CHANCE_OF_SOUND = 0.005; +var CHANCE_OF_SOUND = 0.000; var CHANCE_OF_HEAD_TURNING = 0.05; var CHANCE_OF_BIG_MOVE = 0.1; -var CHANCE_OF_WAVING = 0.005; // Currently this isn't working +var CHANCE_OF_WAVING = 0.009; var shouldReceiveVoxels = true; var VOXEL_FPS = 60.0; @@ -39,12 +39,16 @@ var isWaving = false; var waveFrequency = 0.0; var waveAmplitude = 0.0; -var X_MIN = 0.0; -var X_MAX = 5.0; -var Z_MIN = 0.0; -var Z_MAX = 5.0; +var X_MIN = 20.0; +var X_MAX = 25.0; +var Z_MIN = 20.0; +var Z_MAX = 25.0; var Y_PELVIS = 2.5; -var SHOULDER_JOINT_NUMBER = 15; +var SPINE_JOINT_NUMBER = 13; +var SHOULDER_JOINT_NUMBER = 17; +var ELBOW_JOINT_NUMBER = 18; +var JOINT_R_HIP = 1; +var JOINT_R_KNEE = 2; var MOVE_RANGE_SMALL = 0.5; var MOVE_RANGE_BIG = Math.max(X_MAX - X_MIN, Z_MAX - Z_MIN) / 2.0; @@ -61,6 +65,9 @@ var targetDirection = { x: 0, y: 0, z: 0, w: 0 }; var currentDirection = { x: 0, y: 0, z: 0, w: 0 }; var targetHeadPitch = 0.0; +var walkFrequency = 5.0; +var walkAmplitude = 45.0; + var cumulativeTime = 0.0; var sounds = []; @@ -115,12 +122,29 @@ printVector("New bot, position = ", Avatar.position); function stopWaving() { isWaving = false; Avatar.clearJointData(SHOULDER_JOINT_NUMBER); + Avatar.clearJointData(ELBOW_JOINT_NUMBER); + Avatar.clearJointData(SPINE_JOINT_NUMBER); +} + +function keepWalking() { + Avatar.setJointData(JOINT_R_HIP, Quat.fromPitchYawRollDegrees(walkAmplitude * Math.sin(cumulativeTime * walkFrequency), 0.0, 0.0)); +} + +function stopWalking() { + Avatar.clearJointData(JOINT_R_HIP); + Avatar.clearJointData(JOINT_R_KNEE); } function updateBehavior(deltaTime) { cumulativeTime += deltaTime; + // Hack - right now you need to set the avatar position a bit after the avatar is made to make sure it's there. + + if (CHANCE_OF_MOVING = 0.000) { + Avatar.position = firstPosition; + } + if (shouldReceiveVoxels && ((cumulativeTime - lastVoxelQueryTime) > (1.0 / VOXEL_FPS))) { VoxelViewer.setPosition(Avatar.position); VoxelViewer.setOrientation(Avatar.orientation); @@ -134,13 +158,18 @@ function updateBehavior(deltaTime) { if (!isWaving && (Math.random() < CHANCE_OF_WAVING)) { isWaving = true; - waveFrequency = 1.0 + Math.random() * 5.0; + waveFrequency = 3.0 + Math.random() * 5.0; waveAmplitude = 5.0 + Math.random() * 60.0; Script.setTimeout(stopWaving, 1000 + Math.random() * 2000); + Avatar.setJointData(ELBOW_JOINT_NUMBER, Quat.fromPitchYawRollDegrees(0.0, 45, 0.0)); // Initially turn the palm outward } else if (isWaving) { - Avatar.setJointData(SHOULDER_JOINT_NUMBER, Quat.fromPitchYawRollDegrees(0.0, 0.0, waveAmplitude * Math.sin(cumulativeTime * waveFrequency))); + Avatar.setJointData(SHOULDER_JOINT_NUMBER, Quat.fromPitchYawRollDegrees(0.0, 0.0, 60 + waveAmplitude * Math.sin((cumulativeTime - 0.25) * waveFrequency))); + Avatar.setJointData(ELBOW_JOINT_NUMBER, Quat.fromPitchYawRollDegrees(0.0, 0.0, 25 + waveAmplitude/2.0 * Math.sin(cumulativeTime * 1.2 * waveFrequency))); + Avatar.setJointData(SPINE_JOINT_NUMBER, Quat.fromPitchYawRollDegrees(0.0, 0.0, 60 + waveAmplitude/4.0 * Math.sin(cumulativeTime * waveFrequency))); + } + if (Math.random() < CHANCE_OF_SOUND) { playRandomSound(); } @@ -168,11 +197,13 @@ function updateBehavior(deltaTime) { targetPosition.y = Y_PELVIS; isMoving = true; - } else { + } else if (isMoving) { + keepWalking(); Avatar.position = Vec3.sum(Avatar.position, Vec3.multiply(Vec3.subtract(targetPosition, Avatar.position), MOVE_RATE)); Avatar.orientation = Quat.mix(Avatar.orientation, targetDirection, TURN_RATE); if (Vec3.length(Vec3.subtract(Avatar.position, targetPosition)) < STOP_TOLERANCE) { - isMoving = false; + isMoving = false; + stopWalking(); } } } From d90244c01ef4715b2600e28e229cab73c19b432c Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Tue, 25 Mar 2014 22:31:44 -0700 Subject: [PATCH 2/8] 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; From 5cce4b3c03f96d26af9d5df8b4873aeea9df50b0 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Wed, 26 Mar 2014 12:14:03 -0700 Subject: [PATCH 3/8] added more movement --- examples/bot.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/bot.js b/examples/bot.js index c606b55274..acd837e3b8 100644 --- a/examples/bot.js +++ b/examples/bot.js @@ -128,6 +128,7 @@ function stopWaving() { function keepWalking() { Avatar.setJointData(JOINT_R_HIP, Quat.fromPitchYawRollDegrees(walkAmplitude * Math.sin(cumulativeTime * walkFrequency), 0.0, 0.0)); + Avatar.setJointData(JOINT_R_KNEE, Quat.fromPitchYawRollDegrees(walkAmplitude * Math.sin(cumulativeTime * walkFrequency), 0.0, 0.0)); } function stopWalking() { @@ -141,7 +142,7 @@ function updateBehavior(deltaTime) { // Hack - right now you need to set the avatar position a bit after the avatar is made to make sure it's there. - if (CHANCE_OF_MOVING = 0.000) { + if (CHANCE_OF_MOVING == 0.000) { Avatar.position = firstPosition; } From 0b13a7173cb065f9c8fbe897ea0cb66ed0215859 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Wed, 26 Mar 2014 23:24:36 -0700 Subject: [PATCH 4/8] disable wheel for size scaling --- examples/editVoxels.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/editVoxels.js b/examples/editVoxels.js index 5e4b77a10f..4922caf0d8 100644 --- a/examples/editVoxels.js +++ b/examples/editVoxels.js @@ -1326,7 +1326,7 @@ function wheelEvent(event) { } } -Controller.wheelEvent.connect(wheelEvent); +// Controller.wheelEvent.connect(wheelEvent); Controller.mousePressEvent.connect(mousePressEvent); Controller.mouseReleaseEvent.connect(mouseReleaseEvent); Controller.mouseMoveEvent.connect(mouseMoveEvent); From 41e9017953a2261774c8ec50ee1fe12fbb355c85 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Thu, 27 Mar 2014 15:14:38 -0700 Subject: [PATCH 5/8] more audio level meter work, improved gun --- examples/gun.js | 36 ++++++++++++++++++++++++++--------- interface/src/Application.cpp | 12 ++++++++++-- 2 files changed, 37 insertions(+), 11 deletions(-) diff --git a/examples/gun.js b/examples/gun.js index 94f3fd4ee3..e358e6b391 100644 --- a/examples/gun.js +++ b/examples/gun.js @@ -27,6 +27,9 @@ var BULLET_VELOCITY = 5.0; var MIN_THROWER_DELAY = 1000; var MAX_THROWER_DELAY = 1000; var LEFT_BUTTON_3 = 3; +var RELOAD_INTERVAL = 9; + +var showScore = false; // Load some sound to use for loading and firing var fireSound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Guns/GUN-SHOT2.raw"); @@ -38,6 +41,8 @@ var targetLaunchSound = new Sound("http://highfidelity-public.s3-us-west-1.amazo var audioOptions = new AudioInjectionOptions(); audioOptions.volume = 0.9; +var shotsFired = 0; + var shotTime = new Date(); // initialize our triggers @@ -63,7 +68,8 @@ var reticle = Overlays.addOverlay("image", { alpha: 1 }); -var text = Overlays.addOverlay("text", { +if (showScore) { + var text = Overlays.addOverlay("text", { x: screenSize.x / 2 - 100, y: screenSize.y / 2 - 50, width: 150, @@ -74,6 +80,8 @@ var text = Overlays.addOverlay("text", { leftMargin: 4, text: "Score: " + score }); +} + function printVector(string, vector) { @@ -94,6 +102,10 @@ function shootBullet(position, velocity) { // Play firing sounds audioOptions.position = position; Audio.playSound(fireSound, audioOptions); + shotsFired++; + if ((shotsFired % RELOAD_INTERVAL) == 0) { + Audio.playSound(loadSound, audioOptions); + } } function shootTarget() { @@ -147,12 +159,15 @@ function particleCollisionWithVoxel(particle, voxel, penetration) { Voxels.eraseVoxel(position.x, position.y, position.z, HOLE_SIZE); //audioOptions.position = position; audioOptions.position = Vec3.sum(Camera.getPosition(), Quat.getFront(Camera.getOrientation())); - Audio.playSound(targetHitSound, audioOptions); + Audio.playSound(impactSound, audioOptions); } function particleCollisionWithParticle(particle1, particle2) { score++; - Overlays.editOverlay(text, { text: "Score: " + score } ); + if (showScore) { + Overlays.editOverlay(text, { text: "Score: " + score } ); + } + // Sort out which particle is which // Record shot time @@ -171,12 +186,12 @@ function keyPressEvent(event) { if (event.text == "t") { var time = MIN_THROWER_DELAY + Math.random() * MAX_THROWER_DELAY; Script.setTimeout(shootTarget, time); + } if (event.text == ".") { + shootFromMouse(); } } function update(deltaTime) { - - // Check for mouseLook movement, update rotation // rotate body yaw for yaw received from mouse var newOrientation = Quat.multiply(MyAvatar.orientation, Quat.fromVec3Radians( { x: 0, y: yawFromMouse, z: 0 } )); @@ -257,18 +272,21 @@ function mousePressEvent(event) { isMouseDown = true; lastX = event.x; lastY = event.y; - audioOptions.position = Vec3.sum(Camera.getPosition(), Quat.getFront(Camera.getOrientation())); - Audio.playSound(loadSound, audioOptions); + //audioOptions.position = Vec3.sum(Camera.getPosition(), Quat.getFront(Camera.getOrientation())); + //Audio.playSound(loadSound, audioOptions); } -function mouseReleaseEvent(event) { - // position +function shootFromMouse() { var DISTANCE_FROM_CAMERA = 2.0; var camera = Camera.getPosition(); var forwardVector = Quat.getFront(Camera.getOrientation()); var newPosition = Vec3.sum(camera, Vec3.multiply(forwardVector, DISTANCE_FROM_CAMERA)); var velocity = Vec3.multiply(forwardVector, BULLET_VELOCITY); shootBullet(newPosition, velocity); +} + +function mouseReleaseEvent(event) { + // position isMouseDown = false; } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 864be460e7..c67f992536 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2503,14 +2503,22 @@ void Application::displayOverlay() { } } - const int AUDIO_METER_WIDTH = 300; + const int AUDIO_METER_WIDTH = 200; 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; + const float LOG2 = log(2.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); + } bool isClipping = ((_audio.getTimeSinceLastClip() > 0.f) && (_audio.getTimeSinceLastClip() < CLIPPING_INDICATOR_TIME)); if (isClipping) { From 27f0214032989e4e8eb32e6cfd0a5a0acb8e5d66 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Fri, 28 Mar 2014 23:09:51 -0700 Subject: [PATCH 6/8] 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())); From 81d1eb7ed264540d670d23cbca081933fc5a873c Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Mon, 31 Mar 2014 18:24:58 -0700 Subject: [PATCH 7/8] removed unused procedural movement code --- interface/interface_en.ts | 16 ++++++++-------- interface/src/Application.cpp | 10 ---------- interface/src/Application.h | 1 - interface/src/Audio.cpp | 2 -- interface/src/Audio.h | 7 +------ 5 files changed, 9 insertions(+), 27 deletions(-) diff --git a/interface/interface_en.ts b/interface/interface_en.ts index 7c5d1ecbcf..a1abb57b52 100644 --- a/interface/interface_en.ts +++ b/interface/interface_en.ts @@ -4,22 +4,22 @@ Application - + Export Voxels - + Sparse Voxel Octree Files (*.svo) - + Open Script - + JavaScript Files (*.js) @@ -113,18 +113,18 @@ Menu - + Open .ini config file - - + + Text files (*.ini) - + Save .ini config file diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index dc1a843e47..fa1f4ae0a1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1846,15 +1846,6 @@ void Application::updateDialogs(float deltaTime) { } } -void Application::updateAudio(float deltaTime) { - bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); - PerformanceWarning warn(showWarnings, "Application::updateAudio()"); - - // Update audio stats for procedural sounds - _audio.setLastAcceleration(_myAvatar->getThrust()); - _audio.setLastVelocity(_myAvatar->getVelocity()); -} - void Application::updateCursor(float deltaTime) { bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::updateCursor()"); @@ -1903,7 +1894,6 @@ void Application::update(float deltaTime) { updateMetavoxels(deltaTime); // update metavoxels updateCamera(deltaTime); // handle various camera tweaks like off axis projection updateDialogs(deltaTime); // update various stats dialogs if present - updateAudio(deltaTime); // Update audio stats for procedural sounds updateCursor(deltaTime); // Handle cursor updates _particles.update(); // update the particles... diff --git a/interface/src/Application.h b/interface/src/Application.h index fcf8810378..f638d947d9 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -312,7 +312,6 @@ private: void updateMetavoxels(float deltaTime); void updateCamera(float deltaTime); void updateDialogs(float deltaTime); - void updateAudio(float deltaTime); void updateCursor(float deltaTime); Avatar* findLookatTargetAvatar(glm::vec3& eyePosition, QUuid &nodeUUID); diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index dc34fb2e2d..312a6c5699 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -67,8 +67,6 @@ Audio::Audio(Oscilloscope* scope, int16_t initialJitterBufferSamples, QObject* p _noiseGateOpen(false), _noiseGateEnabled(true), _noiseGateFramesToClose(0), - _lastVelocity(0), - _lastAcceleration(0), _totalPacketsReceived(0), _collisionSoundMagnitude(0.0f), _collisionSoundFrequency(0.0f), diff --git a/interface/src/Audio.h b/interface/src/Audio.h index 0ffcb77baf..f98e18eb0b 100644 --- a/interface/src/Audio.h +++ b/interface/src/Audio.h @@ -51,10 +51,7 @@ public: float getAudioAverageInputLoudness() const { return _lastInputLoudness; } void setNoiseGateEnabled(bool noiseGateEnabled) { _noiseGateEnabled = noiseGateEnabled; } - - void setLastAcceleration(const glm::vec3 lastAcceleration) { _lastAcceleration = lastAcceleration; } - void setLastVelocity(const glm::vec3 lastVelocity) { _lastVelocity = lastVelocity; } - + void setJitterBufferSamples(int samples) { _jitterBufferSamples = samples; } int getJitterBufferSamples() { return _jitterBufferSamples; } @@ -139,8 +136,6 @@ private: bool _noiseGateOpen; bool _noiseGateEnabled; int _noiseGateFramesToClose; - glm::vec3 _lastVelocity; - glm::vec3 _lastAcceleration; int _totalPacketsReceived; float _collisionSoundMagnitude; From 7d12fcee9db07ca8900619c12b22e817b5e457f3 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Mon, 31 Mar 2014 21:55:29 -0700 Subject: [PATCH 8/8] 220Hz tone injection option for easier audio quality checks --- interface/src/Audio.cpp | 24 ++++++++++++++++++++---- interface/src/Audio.h | 3 +++ interface/src/Menu.cpp | 6 ++++++ interface/src/Menu.h | 1 + 4 files changed, 30 insertions(+), 4 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 312a6c5699..9f993e653d 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -66,8 +66,10 @@ Audio::Audio(Oscilloscope* scope, int16_t initialJitterBufferSamples, QObject* p _noiseGateSampleCounter(0), _noiseGateOpen(false), _noiseGateEnabled(true), + _toneInjectionEnabled(false), _noiseGateFramesToClose(0), _totalPacketsReceived(0), + _totalInputAudioSamples(0), _collisionSoundMagnitude(0.0f), _collisionSoundFrequency(0.0f), _collisionSoundNoise(0.0f), @@ -390,7 +392,7 @@ void Audio::handleAudioInput() { inputSamplesRequired, NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL, _inputFormat, _desiredInputFormat); - + // // Impose Noise Gate // @@ -421,13 +423,15 @@ void Audio::handleAudioInput() { const float DC_OFFSET_AVERAGING = 0.99f; const float CLIPPING_THRESHOLD = 0.90f; + // + // Check clipping, adjust DC offset, and check if should open noise gate + // 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; @@ -489,6 +493,16 @@ void Audio::handleAudioInput() { _lastInputLoudness = 0; } } + // + // Add tone injection if enabled + // + const float TONE_FREQ = 220.f / SAMPLE_RATE * TWO_PI; + const float QUARTER_VOLUME = 8192.f; + if (_toneInjectionEnabled) { + for (int i = 0; i < NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL; i++) { + monoAudioSamples[i] = QUARTER_VOLUME * sinf(TONE_FREQ * (float)(i + _proceduralEffectSample)); + } + } // add input data just written to the scope QMetaObject::invokeMethod(_scope, "addSamples", Qt::QueuedConnection, @@ -683,7 +697,9 @@ void Audio::toggleAudioNoiseReduction() { _noiseGateEnabled = !_noiseGateEnabled; } - +void Audio::toggleToneInjection() { + _toneInjectionEnabled = !_toneInjectionEnabled; +} // Take a pointer to the acquired microphone input samples and add procedural sounds void Audio::addProceduralSounds(int16_t* monoInput, int numSamples) { diff --git a/interface/src/Audio.h b/interface/src/Audio.h index f98e18eb0b..170572a4d7 100644 --- a/interface/src/Audio.h +++ b/interface/src/Audio.h @@ -81,6 +81,7 @@ public slots: void reset(); void toggleMute(); void toggleAudioNoiseReduction(); + void toggleToneInjection(); virtual void handleAudioByteArray(const QByteArray& audioByteArray); @@ -135,8 +136,10 @@ private: int _noiseGateSampleCounter; bool _noiseGateOpen; bool _noiseGateEnabled; + bool _toneInjectionEnabled; int _noiseGateFramesToClose; int _totalPacketsReceived; + int _totalInputAudioSamples; float _collisionSoundMagnitude; float _collisionSoundFrequency; diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 4d93016d4e..122d4c5654 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -360,6 +360,12 @@ Menu::Menu() : false, appInstance->getAudio(), SLOT(toggleMute())); + addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::AudioToneInjection, + 0, + false, + appInstance->getAudio(), + SLOT(toggleToneInjection())); + addActionToQMenuAndActionHash(developerMenu, MenuOption::PasteToVoxel, Qt::CTRL | Qt::SHIFT | Qt::Key_V, diff --git a/interface/src/Menu.h b/interface/src/Menu.h index c7c4c6ecea..206593ce80 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -242,6 +242,7 @@ namespace MenuOption { const QString FilterSixense = "Smooth Sixense Movement"; const QString Enable3DTVMode = "Enable 3DTV Mode"; const QString AudioNoiseReduction = "Audio Noise Reduction"; + const QString AudioToneInjection = "Inject Test Tone"; const QString EchoServerAudio = "Echo Server Audio"; const QString EchoLocalAudio = "Echo Local Audio"; const QString MuteAudio = "Mute Microphone";