mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 19:04:32 +02:00
Merge pull request #1944 from PhilipRosedale/master
Audio Noise Reduction, Edit voxels with script
This commit is contained in:
commit
3f4af9f363
9 changed files with 256 additions and 88 deletions
170
examples/editVoxels.js
Normal file
170
examples/editVoxels.js
Normal file
|
@ -0,0 +1,170 @@
|
|||
//
|
||||
// editVoxels.js
|
||||
// hifi
|
||||
//
|
||||
// Created by Philip Rosedale on February 8, 2014
|
||||
// Copyright (c) 2014 HighFidelity, Inc. All rights reserved.
|
||||
//
|
||||
// Captures mouse clicks and edits voxels accordingly.
|
||||
//
|
||||
// click = create a new voxel on this face, same color as old
|
||||
// Alt + click = delete this voxel
|
||||
// shift + click = recolor this voxel
|
||||
//
|
||||
// Click and drag to create more new voxels in the same direction
|
||||
//
|
||||
|
||||
function vLength(v) {
|
||||
return Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
|
||||
}
|
||||
|
||||
var key_alt = false;
|
||||
var key_shift = false;
|
||||
var isAdding = false;
|
||||
|
||||
var lastVoxelPosition = { x: 0, y: 0, z: 0 };
|
||||
var lastVoxelColor = { red: 0, green: 0, blue: 0 };
|
||||
var lastVoxelScale = 0;
|
||||
var dragStart = { x: 0, y: 0 };
|
||||
|
||||
// Create a table of the different colors you can choose
|
||||
var colors = new Array();
|
||||
colors[0] = { red: 237, green: 175, blue: 0 };
|
||||
colors[1] = { red: 61, green: 211, blue: 72 };
|
||||
colors[2] = { red: 51, green: 204, blue: 204 };
|
||||
colors[3] = { red: 63, green: 169, blue: 245 };
|
||||
colors[4] = { red: 193, green: 99, blue: 122 };
|
||||
colors[5] = { red: 255, green: 54, blue: 69 };
|
||||
colors[6] = { red: 124, green: 36, blue: 36 };
|
||||
colors[7] = { red: 63, green: 35, blue: 19 };
|
||||
var numColors = 6;
|
||||
var whichColor = 0;
|
||||
|
||||
// Create sounds for adding, deleting, recoloring voxels
|
||||
var addSound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Electronic/ElectronicBurst1.raw");
|
||||
var deleteSound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Bubbles/bubbles1.raw");
|
||||
var changeColorSound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Electronic/ElectronicBurst6.raw");
|
||||
var audioOptions = new AudioInjectionOptions();
|
||||
|
||||
function mousePressEvent(event) {
|
||||
var pickRay = Camera.computePickRay(event.x, event.y);
|
||||
var intersection = Voxels.findRayIntersection(pickRay);
|
||||
audioOptions.volume = 1.0;
|
||||
audioOptions.position = { x: intersection.voxel.x, y: intersection.voxel.y, z: intersection.voxel.z };
|
||||
|
||||
if (intersection.intersects) {
|
||||
if (key_alt) {
|
||||
// Delete voxel
|
||||
Voxels.eraseVoxel(intersection.voxel.x, intersection.voxel.y, intersection.voxel.z, intersection.voxel.s);
|
||||
Audio.playSound(deleteSound, audioOptions);
|
||||
|
||||
} else if (key_shift) {
|
||||
// Recolor Voxel
|
||||
whichColor++;
|
||||
if (whichColor == numColors) whichColor = 0;
|
||||
Voxels.setVoxel(intersection.voxel.x,
|
||||
intersection.voxel.y,
|
||||
intersection.voxel.z,
|
||||
intersection.voxel.s,
|
||||
colors[whichColor].red, colors[whichColor].green, colors[whichColor].blue);
|
||||
Audio.playSound(changeColorSound, audioOptions);
|
||||
} else {
|
||||
// Add voxel on face
|
||||
var newVoxel = {
|
||||
x: intersection.voxel.x,
|
||||
y: intersection.voxel.y,
|
||||
z: intersection.voxel.z,
|
||||
s: intersection.voxel.s,
|
||||
red: intersection.voxel.red,
|
||||
green: intersection.voxel.green,
|
||||
blue: intersection.voxel.blue };
|
||||
|
||||
if (intersection.face == "MIN_X_FACE") {
|
||||
newVoxel.x -= newVoxel.s;
|
||||
} else if (intersection.face == "MAX_X_FACE") {
|
||||
newVoxel.x += newVoxel.s;
|
||||
} else if (intersection.face == "MIN_Y_FACE") {
|
||||
newVoxel.y -= newVoxel.s;
|
||||
} else if (intersection.face == "MAX_Y_FACE") {
|
||||
newVoxel.y += newVoxel.s;
|
||||
} else if (intersection.face == "MIN_Z_FACE") {
|
||||
newVoxel.z -= newVoxel.s;
|
||||
} else if (intersection.face == "MAX_Z_FACE") {
|
||||
newVoxel.z += newVoxel.s;
|
||||
}
|
||||
|
||||
Voxels.setVoxel(newVoxel.x, newVoxel.y, newVoxel.z, newVoxel.s, newVoxel.red, newVoxel.green, newVoxel.blue);
|
||||
lastVoxelPosition = { x: newVoxel.x, y: newVoxel.y, z: newVoxel.z };
|
||||
lastVoxelColor = { red: newVoxel.red, green: newVoxel.green, blue: newVoxel.blue };
|
||||
lastVoxelScale = newVoxel.s;
|
||||
|
||||
Audio.playSound(addSound, audioOptions);
|
||||
dragStart = { x: event.x, y: event.y };
|
||||
isAdding = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function keyPressEvent(event) {
|
||||
key_alt = event.isAlt;
|
||||
key_shift = event.isShifted;
|
||||
}
|
||||
function keyReleaseEvent(event) {
|
||||
key_alt = false;
|
||||
key_shift = false;
|
||||
}
|
||||
function mouseMoveEvent(event) {
|
||||
if (isAdding) {
|
||||
var pickRay = Camera.computePickRay(event.x, event.y);
|
||||
var lastVoxelDistance = { x: pickRay.origin.x - lastVoxelPosition.x,
|
||||
y: pickRay.origin.y - lastVoxelPosition.y,
|
||||
z: pickRay.origin.z - lastVoxelPosition.z };
|
||||
var distance = vLength(lastVoxelDistance);
|
||||
var mouseSpot = { x: pickRay.direction.x * distance, y: pickRay.direction.y * distance, z: pickRay.direction.z * distance };
|
||||
mouseSpot.x += pickRay.origin.x;
|
||||
mouseSpot.y += pickRay.origin.y;
|
||||
mouseSpot.z += pickRay.origin.z;
|
||||
var dx = mouseSpot.x - lastVoxelPosition.x;
|
||||
var dy = mouseSpot.y - lastVoxelPosition.y;
|
||||
var dz = mouseSpot.z - lastVoxelPosition.z;
|
||||
if (dx > lastVoxelScale) {
|
||||
lastVoxelPosition.x += lastVoxelScale;
|
||||
Voxels.setVoxel(lastVoxelPosition.x, lastVoxelPosition.y, lastVoxelPosition.z,
|
||||
lastVoxelScale, lastVoxelColor.red, lastVoxelColor.green, lastVoxelColor.blue);
|
||||
} else if (dx < -lastVoxelScale) {
|
||||
lastVoxelPosition.x -= lastVoxelScale;
|
||||
Voxels.setVoxel(lastVoxelPosition.x, lastVoxelPosition.y, lastVoxelPosition.z,
|
||||
lastVoxelScale, lastVoxelColor.red, lastVoxelColor.green, lastVoxelColor.blue);
|
||||
} else if (dy > lastVoxelScale) {
|
||||
lastVoxelPosition.y += lastVoxelScale;
|
||||
Voxels.setVoxel(lastVoxelPosition.x, lastVoxelPosition.y, lastVoxelPosition.z,
|
||||
lastVoxelScale, lastVoxelColor.red, lastVoxelColor.green, lastVoxelColor.blue);
|
||||
} else if (dy < -lastVoxelScale) {
|
||||
lastVoxelPosition.y -= lastVoxelScale;
|
||||
Voxels.setVoxel(lastVoxelPosition.x, lastVoxelPosition.y, lastVoxelPosition.z,
|
||||
lastVoxelScale, lastVoxelColor.red, lastVoxelColor.green, lastVoxelColor.blue);
|
||||
} else if (dz > lastVoxelScale) {
|
||||
lastVoxelPosition.z += lastVoxelScale;
|
||||
Voxels.setVoxel(lastVoxelPosition.x, lastVoxelPosition.y, lastVoxelPosition.z,
|
||||
lastVoxelScale, lastVoxelColor.red, lastVoxelColor.green, lastVoxelColor.blue);
|
||||
} else if (dz < -lastVoxelScale) {
|
||||
lastVoxelPosition.z -= lastVoxelScale;
|
||||
Voxels.setVoxel(lastVoxelPosition.x, lastVoxelPosition.y, lastVoxelPosition.z,
|
||||
lastVoxelScale, lastVoxelColor.red, lastVoxelColor.green, lastVoxelColor.blue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function mouseReleaseEvent(event) {
|
||||
isAdding = false;
|
||||
}
|
||||
|
||||
Controller.mousePressEvent.connect(mousePressEvent);
|
||||
Controller.mouseReleaseEvent.connect(mouseReleaseEvent);
|
||||
Controller.mouseMoveEvent.connect(mouseMoveEvent);
|
||||
Controller.keyPressEvent.connect(keyPressEvent);
|
||||
Controller.keyReleaseEvent.connect(keyReleaseEvent);
|
||||
|
||||
function scriptEnding() {
|
||||
}
|
||||
Script.scriptEnding.connect(scriptEnding);
|
|
@ -4,6 +4,7 @@
|
|||
//
|
||||
// This sample script moves a voxel around like a bird and sometimes makes tweeting noises
|
||||
//
|
||||
|
||||
function vLength(v) {
|
||||
return Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
|
||||
}
|
||||
|
@ -15,20 +16,24 @@ function randVector(a, b) {
|
|||
var rval = { x: a + Math.random() * (b - a), y: a + Math.random() * (b - a), z: a + Math.random() * (b - a) };
|
||||
return rval;
|
||||
}
|
||||
|
||||
function vMinus(a, b) {
|
||||
var rval = { x: a.x - b.x, y: a.y - b.y, z: a.z - b.z };
|
||||
return rval;
|
||||
}
|
||||
|
||||
function vPlus(a, b) {
|
||||
var rval = { x: a.x + b.x, y: a.y + b.y, z: a.z + b.z };
|
||||
return rval;
|
||||
}
|
||||
|
||||
function vCopy(a, b) {
|
||||
a.x = b.x;
|
||||
a.y = b.y;
|
||||
a.z = b.z;
|
||||
return;
|
||||
}
|
||||
|
||||
// Returns a vector which is fraction of the way between a and b
|
||||
function vInterpolate(a, b, fraction) {
|
||||
var rval = { x: a.x + (b.x - a.x) * fraction, y: a.y + (b.y - a.y) * fraction, z: a.z + (b.z - a.z) * fraction };
|
||||
|
@ -62,6 +67,7 @@ if (which < 0.2) {
|
|||
size = 0.15;
|
||||
}
|
||||
|
||||
|
||||
var startTimeInSeconds = new Date().getTime() / 1000;
|
||||
|
||||
var birdLifetime = 20; // lifetime of the bird in seconds!
|
||||
|
@ -72,15 +78,19 @@ var frame = 0;
|
|||
var moving = false;
|
||||
var tweeting = 0;
|
||||
var moved = false;
|
||||
var CHANCE_OF_MOVING = 0.05;
|
||||
|
||||
var CHANCE_OF_MOVING = 0.00;
|
||||
var CHANCE_OF_FLAPPING = 0.05;
|
||||
var CHANCE_OF_TWEETING = 0.05;
|
||||
var START_HEIGHT_ABOVE_ME = 1.5;
|
||||
var BIRD_GRAVITY = -0.1;
|
||||
var BIRD_FLAP = 1.0;
|
||||
var myPosition = MyAvatar.position;
|
||||
var properties = {
|
||||
lifetime: birdLifetime,
|
||||
position: { x: myPosition.x, y: myPosition.y + START_HEIGHT_ABOVE_ME, z: myPosition.z },
|
||||
velocity: { x: 0, y: 0, z: 0 },
|
||||
gravity: { x: 0, y: 0, z: 0 },
|
||||
velocity: { x: 0, y: Math.random() * BIRD_FLAP, z: 0 },
|
||||
gravity: { x: 0, y: BIRD_GRAVITY, z: 0 },
|
||||
radius : 0.1,
|
||||
color: { red: 0,
|
||||
green: 255,
|
||||
|
@ -94,6 +104,7 @@ function moveBird() {
|
|||
// check to see if we've been running long enough that our bird is dead
|
||||
var nowTimeInSeconds = new Date().getTime() / 1000;
|
||||
if ((nowTimeInSeconds - startTimeInSeconds) >= birdLifetime) {
|
||||
|
||||
print("our bird is dying, stop our script");
|
||||
Script.stop();
|
||||
return;
|
||||
|
@ -115,11 +126,22 @@ function moveBird() {
|
|||
} else {
|
||||
tweeting -= 1;
|
||||
}
|
||||
if (Math.random() < CHANCE_OF_FLAPPING) {
|
||||
// Add a little upward impulse to our bird
|
||||
// TODO: Get velocity
|
||||
//
|
||||
var newProperties = {
|
||||
velocity: { x:0.0, y: Math.random() * BIRD_FLAP, z: 0.0 }
|
||||
};
|
||||
Particles.editParticle(particleID, newProperties);
|
||||
print("flap!");
|
||||
}
|
||||
// Moving behavior
|
||||
if (moving == false) {
|
||||
if (Math.random() < CHANCE_OF_MOVING) {
|
||||
targetPosition = randVector(- range, range);
|
||||
targetPosition = randVector(-range, range);
|
||||
targetPosition = vPlus(targetPosition, myPosition);
|
||||
|
||||
if (targetPosition.x < 0) {
|
||||
targetPosition.x = 0;
|
||||
}
|
||||
|
@ -170,5 +192,6 @@ function moveBird() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// register the call back so it fires before each data send
|
||||
Script.willSendVisualDataCallback.connect(moveBird);
|
||||
|
|
|
@ -135,7 +135,6 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
|
|||
_isTouchPressed(false),
|
||||
_mousePressed(false),
|
||||
_isHoverVoxel(false),
|
||||
_isHoverVoxelSounding(false),
|
||||
_mouseVoxelScale(1.0f / 1024.0f),
|
||||
_mouseVoxelScaleInitialized(false),
|
||||
_justEditedVoxel(false),
|
||||
|
@ -1199,7 +1198,7 @@ void Application::mouseMoveEvent(QMouseEvent* event) {
|
|||
return;
|
||||
}
|
||||
if (_isHoverVoxel) {
|
||||
_myAvatar->orbit(getMouseVoxelWorldCoordinates(_hoverVoxel), deltaX, deltaY);
|
||||
//_myAvatar->orbit(getMouseVoxelWorldCoordinates(_hoverVoxel), deltaX, deltaY);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1219,11 +1218,6 @@ void Application::mouseMoveEvent(QMouseEvent* event) {
|
|||
}
|
||||
}
|
||||
|
||||
const bool MAKE_SOUND_ON_VOXEL_HOVER = false;
|
||||
const bool MAKE_SOUND_ON_VOXEL_CLICK = true;
|
||||
const float HOVER_VOXEL_FREQUENCY = 7040.f;
|
||||
const float HOVER_VOXEL_DECAY = 0.999f;
|
||||
|
||||
void Application::mousePressEvent(QMouseEvent* event) {
|
||||
_controllerScriptingInterface.emitMousePressEvent(event); // send events to any registered scripts
|
||||
|
||||
|
@ -1263,37 +1257,6 @@ void Application::mousePressEvent(QMouseEvent* event) {
|
|||
pasteVoxels();
|
||||
}
|
||||
|
||||
if (!Menu::getInstance()->isOptionChecked(MenuOption::VoxelDeleteMode) &&
|
||||
MAKE_SOUND_ON_VOXEL_CLICK && _isHoverVoxel && !_isHoverVoxelSounding) {
|
||||
_hoverVoxelOriginalColor[0] = _hoverVoxel.red;
|
||||
_hoverVoxelOriginalColor[1] = _hoverVoxel.green;
|
||||
_hoverVoxelOriginalColor[2] = _hoverVoxel.blue;
|
||||
_hoverVoxelOriginalColor[3] = 1;
|
||||
const float RED_CLICK_FREQUENCY = 1000.f;
|
||||
const float GREEN_CLICK_FREQUENCY = 1250.f;
|
||||
const float BLUE_CLICK_FREQUENCY = 1330.f;
|
||||
const float MIDDLE_A_FREQUENCY = 440.f;
|
||||
float frequency = MIDDLE_A_FREQUENCY +
|
||||
(_hoverVoxel.red / 255.f * RED_CLICK_FREQUENCY +
|
||||
_hoverVoxel.green / 255.f * GREEN_CLICK_FREQUENCY +
|
||||
_hoverVoxel.blue / 255.f * BLUE_CLICK_FREQUENCY) / 3.f;
|
||||
|
||||
_audio.startCollisionSound(1.0, frequency, 0.0, HOVER_VOXEL_DECAY, false);
|
||||
_isHoverVoxelSounding = true;
|
||||
|
||||
const float PERCENTAGE_TO_MOVE_TOWARD = 0.90f;
|
||||
glm::vec3 newTarget = getMouseVoxelWorldCoordinates(_hoverVoxel);
|
||||
glm::vec3 myPosition = _myAvatar->getPosition();
|
||||
|
||||
// If there is not an action tool set (add, delete, color), move to this voxel
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::ClickToFly) &&
|
||||
!(Menu::getInstance()->isOptionChecked(MenuOption::VoxelAddMode) ||
|
||||
Menu::getInstance()->isOptionChecked(MenuOption::VoxelDeleteMode) ||
|
||||
Menu::getInstance()->isOptionChecked(MenuOption::VoxelColorMode))) {
|
||||
_myAvatar->setMoveTarget(myPosition + (newTarget - myPosition) * PERCENTAGE_TO_MOVE_TOWARD);
|
||||
}
|
||||
}
|
||||
|
||||
} else if (event->button() == Qt::RightButton && Menu::getInstance()->isVoxelModeActionChecked()) {
|
||||
deleteVoxelUnderCursor();
|
||||
}
|
||||
|
@ -2039,44 +2002,11 @@ void Application::updateHoverVoxels(float deltaTime, float& distance, BoxFace& f
|
|||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||
PerformanceWarning warn(showWarnings, "Application::updateHoverVoxels()");
|
||||
|
||||
// If we have clicked on a voxel, update it's color
|
||||
if (_isHoverVoxelSounding) {
|
||||
VoxelTreeElement* hoveredNode = _voxels.getVoxelAt(_hoverVoxel.x, _hoverVoxel.y, _hoverVoxel.z, _hoverVoxel.s);
|
||||
if (hoveredNode) {
|
||||
float bright = _audio.getCollisionSoundMagnitude();
|
||||
nodeColor clickColor = { 255 * bright + _hoverVoxelOriginalColor[0] * (1.f - bright),
|
||||
_hoverVoxelOriginalColor[1] * (1.f - bright),
|
||||
_hoverVoxelOriginalColor[2] * (1.f - bright), 1 };
|
||||
hoveredNode->setColor(clickColor);
|
||||
if (bright < 0.01f) {
|
||||
hoveredNode->setColor(_hoverVoxelOriginalColor);
|
||||
_isHoverVoxelSounding = false;
|
||||
}
|
||||
} else {
|
||||
// Voxel is not found, clear all
|
||||
_isHoverVoxelSounding = false;
|
||||
_isHoverVoxel = false;
|
||||
}
|
||||
} else {
|
||||
// Check for a new hover voxel
|
||||
glm::vec4 oldVoxel(_hoverVoxel.x, _hoverVoxel.y, _hoverVoxel.z, _hoverVoxel.s);
|
||||
// only do this work if MAKE_SOUND_ON_VOXEL_HOVER or MAKE_SOUND_ON_VOXEL_CLICK is enabled,
|
||||
// and make sure the tree is not already busy... because otherwise you'll have to wait.
|
||||
if (!_mousePressed) {
|
||||
{
|
||||
PerformanceWarning warn(showWarnings, "Application::updateHoverVoxels() _voxels.findRayIntersection()");
|
||||
_isHoverVoxel = _voxels.findRayIntersection(_mouseRayOrigin, _mouseRayDirection, _hoverVoxel, distance, face);
|
||||
}
|
||||
if (MAKE_SOUND_ON_VOXEL_HOVER && _isHoverVoxel &&
|
||||
glm::vec4(_hoverVoxel.x, _hoverVoxel.y, _hoverVoxel.z, _hoverVoxel.s) != oldVoxel) {
|
||||
|
||||
_hoverVoxelOriginalColor[0] = _hoverVoxel.red;
|
||||
_hoverVoxelOriginalColor[1] = _hoverVoxel.green;
|
||||
_hoverVoxelOriginalColor[2] = _hoverVoxel.blue;
|
||||
_hoverVoxelOriginalColor[3] = 1;
|
||||
_audio.startCollisionSound(1.0, HOVER_VOXEL_FREQUENCY * _hoverVoxel.s * TREE_SCALE, 0.0, HOVER_VOXEL_DECAY, false);
|
||||
_isHoverVoxelSounding = true;
|
||||
}
|
||||
// Check for a new hover voxel
|
||||
if (!_mousePressed) {
|
||||
{
|
||||
PerformanceWarning warn(showWarnings, "Application::updateHoverVoxels() _voxels.findRayIntersection()");
|
||||
_isHoverVoxel = _voxels.findRayIntersection(_mouseRayOrigin, _mouseRayDirection, _hoverVoxel, distance, face);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -419,8 +419,6 @@ private:
|
|||
|
||||
VoxelDetail _hoverVoxel; // Stuff about the voxel I am hovering or clicking
|
||||
bool _isHoverVoxel;
|
||||
bool _isHoverVoxelSounding;
|
||||
nodeColor _hoverVoxelOriginalColor;
|
||||
|
||||
VoxelDetail _mouseVoxel; // details of the voxel to be edited
|
||||
float _mouseVoxelScale; // the scale for adding/removing voxels
|
||||
|
|
|
@ -65,6 +65,10 @@ Audio::Audio(Oscilloscope* scope, int16_t initialJitterBufferSamples, QObject* p
|
|||
_measuredJitter(0),
|
||||
_jitterBufferSamples(initialJitterBufferSamples),
|
||||
_lastInputLoudness(0),
|
||||
_averageInputLoudness(0),
|
||||
_noiseGateOpen(false),
|
||||
_noiseGateEnabled(true),
|
||||
_noiseGateFramesToClose(0),
|
||||
_lastVelocity(0),
|
||||
_lastAcceleration(0),
|
||||
_totalPacketsReceived(0),
|
||||
|
@ -348,12 +352,40 @@ void Audio::handleAudioInput() {
|
|||
_inputFormat, _desiredInputFormat);
|
||||
|
||||
float loudness = 0;
|
||||
|
||||
float thisSample = 0;
|
||||
int samplesOverNoiseGate = 0;
|
||||
|
||||
const float NOISE_GATE_HEIGHT = 3.f;
|
||||
const int NOISE_GATE_WIDTH = 5;
|
||||
const int NOISE_GATE_CLOSE_FRAME_DELAY = 30;
|
||||
|
||||
for (int i = 0; i < NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL; i++) {
|
||||
loudness += fabsf(monoAudioSamples[i]);
|
||||
thisSample = fabsf(monoAudioSamples[i]);
|
||||
loudness += thisSample;
|
||||
// Noise Reduction: Count peaks above the average loudness
|
||||
if (thisSample > (_averageInputLoudness * NOISE_GATE_HEIGHT)) {
|
||||
samplesOverNoiseGate++;
|
||||
}
|
||||
}
|
||||
|
||||
_lastInputLoudness = loudness / NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL;
|
||||
const float LOUDNESS_AVERAGING_FRAMES = 1000.f; // This will be about 10 seconds
|
||||
_averageInputLoudness = (1.f - 1.f / LOUDNESS_AVERAGING_FRAMES) * _averageInputLoudness + (1.f / LOUDNESS_AVERAGING_FRAMES) * _lastInputLoudness;
|
||||
|
||||
if (_noiseGateEnabled) {
|
||||
if (samplesOverNoiseGate > NOISE_GATE_WIDTH) {
|
||||
_noiseGateOpen = true;
|
||||
_noiseGateFramesToClose = NOISE_GATE_CLOSE_FRAME_DELAY;
|
||||
} else {
|
||||
if (--_noiseGateFramesToClose == 0) {
|
||||
_noiseGateOpen = false;
|
||||
}
|
||||
}
|
||||
if (!_noiseGateOpen) {
|
||||
for (int i = 0; i < NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL; i++) {
|
||||
monoAudioSamples[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add input data just written to the scope
|
||||
QMetaObject::invokeMethod(_scope, "addSamples", Qt::QueuedConnection,
|
||||
|
@ -524,6 +556,10 @@ void Audio::toggleMute() {
|
|||
muteToggled();
|
||||
}
|
||||
|
||||
void Audio::toggleAudioNoiseReduction() {
|
||||
_noiseGateEnabled = !_noiseGateEnabled;
|
||||
}
|
||||
|
||||
void Audio::render(int screenWidth, int screenHeight) {
|
||||
if (_audioInput && _audioOutput) {
|
||||
glLineWidth(2.0);
|
||||
|
|
|
@ -45,7 +45,9 @@ public:
|
|||
|
||||
void render(int screenWidth, int screenHeight);
|
||||
|
||||
float getLastInputLoudness() const { return _lastInputLoudness; }
|
||||
float getLastInputLoudness() const { return glm::max(_lastInputLoudness - _averageInputLoudness, 0.f); }
|
||||
|
||||
void setNoiseGateEnabled(bool noiseGateEnabled) { _noiseGateEnabled = noiseGateEnabled; }
|
||||
|
||||
void setLastAcceleration(const glm::vec3 lastAcceleration) { _lastAcceleration = lastAcceleration; }
|
||||
void setLastVelocity(const glm::vec3 lastVelocity) { _lastVelocity = lastVelocity; }
|
||||
|
@ -73,6 +75,7 @@ public slots:
|
|||
void handleAudioInput();
|
||||
void reset();
|
||||
void toggleMute();
|
||||
void toggleAudioNoiseReduction();
|
||||
|
||||
virtual void handleAudioByteArray(const QByteArray& audioByteArray);
|
||||
|
||||
|
@ -106,6 +109,10 @@ private:
|
|||
float _measuredJitter;
|
||||
int16_t _jitterBufferSamples;
|
||||
float _lastInputLoudness;
|
||||
float _averageInputLoudness;
|
||||
bool _noiseGateOpen;
|
||||
bool _noiseGateEnabled;
|
||||
int _noiseGateFramesToClose;
|
||||
glm::vec3 _lastVelocity;
|
||||
glm::vec3 _lastAcceleration;
|
||||
int _totalPacketsReceived;
|
||||
|
|
|
@ -457,6 +457,11 @@ Menu::Menu() :
|
|||
addCheckableActionToQMenuAndActionHash(renderDebugMenu, MenuOption::CoverageMapV2, Qt::SHIFT | Qt::CTRL | Qt::Key_P);
|
||||
|
||||
QMenu* audioDebugMenu = developerMenu->addMenu("Audio Debugging Tools");
|
||||
addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::AudioNoiseReduction,
|
||||
0,
|
||||
true,
|
||||
appInstance->getAudio(),
|
||||
SLOT(toggleAudioNoiseReduction()));
|
||||
addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::EchoServerAudio);
|
||||
addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::EchoLocalAudio);
|
||||
addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::MuteAudio,
|
||||
|
|
|
@ -187,6 +187,7 @@ namespace MenuOption {
|
|||
const QString Enable3DTVMode = "Enable 3DTV Mode";
|
||||
const QString EnableOcclusionCulling = "Enable Occlusion Culling";
|
||||
const QString EnableVoxelPacketCompression = "Enable Voxel Packet Compression";
|
||||
const QString AudioNoiseReduction = "Audio Noise Reduction";
|
||||
const QString EchoServerAudio = "Echo Server Audio";
|
||||
const QString EchoLocalAudio = "Echo Local Audio";
|
||||
const QString MuteAudio = "Mute Microphone";
|
||||
|
|
|
@ -107,7 +107,6 @@ QByteArray AvatarData::toByteArray() {
|
|||
destinationBuffer += sizeof(_headData->_lookAtPosition);
|
||||
|
||||
// Instantaneous audio loudness (used to drive facial animation)
|
||||
//destinationBuffer += packFloatToByte(destinationBuffer, std::min(MAX_AUDIO_LOUDNESS, _audioLoudness), MAX_AUDIO_LOUDNESS);
|
||||
memcpy(destinationBuffer, &_headData->_audioLoudness, sizeof(float));
|
||||
destinationBuffer += sizeof(float);
|
||||
|
||||
|
@ -215,7 +214,6 @@ int AvatarData::parseData(const QByteArray& packet) {
|
|||
sourceBuffer += sizeof(_headData->_lookAtPosition);
|
||||
|
||||
// Instantaneous audio loudness (used to drive facial animation)
|
||||
//sourceBuffer += unpackFloatFromByte(sourceBuffer, _audioLoudness, MAX_AUDIO_LOUDNESS);
|
||||
memcpy(&_headData->_audioLoudness, sourceBuffer, sizeof(float));
|
||||
sourceBuffer += sizeof(float);
|
||||
|
||||
|
|
Loading…
Reference in a new issue