diff --git a/.eslintrc.js b/.eslintrc.js index c708decc51..9635142d1a 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -17,6 +17,7 @@ module.exports = { "Clipboard": false, "Controller": false, "DialogsManager": false, + "DebugDraw": false, "Entities": false, "FaceTracker": false, "GlobalServices": false, diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4bebc80bd1..1bb4c64884 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -608,6 +608,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo } } + // make sure the debug draw singleton is initialized on the main thread. + DebugDraw::getInstance().removeMarker(""); _runningMarker.startRunningMarker(); diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index 9fb8bae6ca..c32b5600d9 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -1028,7 +1028,7 @@ void AudioClient::handleAudioInput() { // if we performed the noise gate we can get values from it instead of enumerating the samples again _lastInputLoudness = _inputGate.getLastLoudness(); - if (_inputGate.clippedInLastFrame()) { + if (_inputGate.clippedInLastBlock()) { _timeSinceLastClip = 0.0f; } @@ -1049,10 +1049,9 @@ void AudioClient::handleAudioInput() { emit inputReceived({ reinterpret_cast(networkAudioSamples), numNetworkBytes }); - if (_inputGate.openedInLastFrame()) { + if (_inputGate.openedInLastBlock()) { emit noiseGateOpened(); - } - if (_inputGate.closedInLastFrame()) { + } else if (_inputGate.closedInLastBlock()) { emit noiseGateClosed(); } @@ -1072,7 +1071,7 @@ void AudioClient::handleAudioInput() { // the output from the input gate (eventually, this could be crossfaded) // and allow the codec to properly encode down to silent/zero. If we still // have _lastInputLoudness of 0 in our NEXT frame, we will send a silent packet - if (_lastInputLoudness == 0 && !_inputGate.closedInLastFrame()) { + if (_lastInputLoudness == 0 && !_inputGate.closedInLastBlock()) { packetType = PacketType::SilentAudioFrame; _silentOutbound.increment(); } else { diff --git a/libraries/audio-client/src/AudioClient.h b/libraries/audio-client/src/AudioClient.h index 512b4bb3c1..7e9acc0586 100644 --- a/libraries/audio-client/src/AudioClient.h +++ b/libraries/audio-client/src/AudioClient.h @@ -45,13 +45,13 @@ #include #include #include +#include #include #include #include "AudioIOStats.h" -#include "AudioNoiseGate.h" #ifdef _WIN32 #pragma warning( push ) diff --git a/libraries/audio-client/src/AudioNoiseGate.cpp b/libraries/audio/src/AudioNoiseGate.cpp similarity index 59% rename from libraries/audio-client/src/AudioNoiseGate.cpp rename to libraries/audio/src/AudioNoiseGate.cpp index 17bbd1a509..604897af8a 100644 --- a/libraries/audio-client/src/AudioNoiseGate.cpp +++ b/libraries/audio/src/AudioNoiseGate.cpp @@ -1,6 +1,6 @@ // // AudioNoiseGate.cpp -// interface/src/audio +// libraries/audio // // Created by Stephen Birarda on 2014-12-16. // Copyright 2014 High Fidelity, Inc. @@ -9,35 +9,29 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "AudioNoiseGate.h" + #include #include -#include - -#include "AudioNoiseGate.h" +#include "AudioConstants.h" const float AudioNoiseGate::CLIPPING_THRESHOLD = 0.90f; AudioNoiseGate::AudioNoiseGate() : - _inputFrameCounter(0), _lastLoudness(0.0f), - _quietestFrame(std::numeric_limits::max()), - _loudestFrame(0.0f), - _didClipInLastFrame(false), + _didClipInLastBlock(false), _dcOffset(0.0f), _measuredFloor(0.0f), _sampleCounter(0), _isOpen(false), - _framesToClose(0) -{ - -} + _blocksToClose(0) {} void AudioNoiseGate::removeDCOffset(int16_t* samples, int numSamples) { // // DC Offset correction // - // Measure the DC offset over a trailing number of frames, and remove it from the input signal. + // Measure the DC offset over a trailing number of blocks, and remove it from the input signal. // This causes the noise background measurements and server muting to be more accurate. Many off-board // ADC's have a noticeable DC offset. // @@ -51,7 +45,7 @@ void AudioNoiseGate::removeDCOffset(int16_t* samples, int numSamples) { // Update measured DC offset measuredDcOffset /= numSamples; if (_dcOffset == 0.0f) { - // On first frame, copy over measured offset + // On first block, copy over measured offset _dcOffset = measuredDcOffset; } else { _dcOffset = DC_OFFSET_AVERAGING * _dcOffset + (1.0f - DC_OFFSET_AVERAGING) * measuredDcOffset; @@ -69,96 +63,85 @@ void AudioNoiseGate::gateSamples(int16_t* samples, int numSamples) { // // NOISE_GATE_HEIGHT: How loud you have to speak relative to noise background to open the gate. // Make this value lower for more sensitivity and less rejection of noise. - // NOISE_GATE_WIDTH: The number of samples in an audio frame for which the height must be exceeded + // NOISE_GATE_WIDTH: The number of samples in an audio block for which the height must be exceeded // to open the gate. - // NOISE_GATE_CLOSE_FRAME_DELAY: Once the noise is below the gate height for the frame, how many frames + // NOISE_GATE_CLOSE_BLOCK_DELAY: Once the noise is below the gate height for the block, how many blocks // will we wait before closing the gate. - // NOISE_GATE_FRAMES_TO_AVERAGE: How many audio frames should we average together to compute noise floor. + // NOISE_GATE_BLOCKS_TO_AVERAGE: How many audio blocks should we average together to compute noise floor. // More means better rejection but also can reject continuous things like singing. - // NUMBER_OF_NOISE_SAMPLE_FRAMES: How often should we re-evaluate the noise floor? + // NUMBER_OF_NOISE_SAMPLE_BLOCKS: How often should we re-evaluate the noise floor? float loudness = 0; int thisSample = 0; int samplesOverNoiseGate = 0; - + const float NOISE_GATE_HEIGHT = 7.0f; const int NOISE_GATE_WIDTH = 5; - const int NOISE_GATE_CLOSE_FRAME_DELAY = 5; - const int NOISE_GATE_FRAMES_TO_AVERAGE = 5; + const int NOISE_GATE_CLOSE_BLOCK_DELAY = 5; + const int NOISE_GATE_BLOCKS_TO_AVERAGE = 5; // Check clipping, and check if should open noise gate - _didClipInLastFrame = false; - + _didClipInLastBlock = false; + for (int i = 0; i < numSamples; i++) { thisSample = std::abs(samples[i]); if (thisSample >= ((float) AudioConstants::MAX_SAMPLE_VALUE * CLIPPING_THRESHOLD)) { - _didClipInLastFrame = true; + _didClipInLastBlock = true; } - + loudness += thisSample; // Noise Reduction: Count peaks above the average loudness if (thisSample > (_measuredFloor * NOISE_GATE_HEIGHT)) { samplesOverNoiseGate++; } } - + _lastLoudness = fabs(loudness / numSamples); - - if (_quietestFrame > _lastLoudness) { - _quietestFrame = _lastLoudness; - } - if (_loudestFrame < _lastLoudness) { - _loudestFrame = _lastLoudness; - } - - const int FRAMES_FOR_NOISE_DETECTION = 400; - if (_inputFrameCounter++ > FRAMES_FOR_NOISE_DETECTION) { - _quietestFrame = std::numeric_limits::max(); - _loudestFrame = 0.0f; - _inputFrameCounter = 0; - } - + // If Noise Gate is enabled, check and turn the gate on and off - float averageOfAllSampleFrames = 0.0f; - _sampleFrames[_sampleCounter++] = _lastLoudness; - if (_sampleCounter == NUMBER_OF_NOISE_SAMPLE_FRAMES) { + float averageOfAllSampleBlocks = 0.0f; + _sampleBlocks[_sampleCounter++] = _lastLoudness; + if (_sampleCounter == NUMBER_OF_NOISE_SAMPLE_BLOCKS) { float smallestSample = std::numeric_limits::max(); - for (int i = 0; i <= NUMBER_OF_NOISE_SAMPLE_FRAMES - NOISE_GATE_FRAMES_TO_AVERAGE; i += NOISE_GATE_FRAMES_TO_AVERAGE) { + for (int i = 0; i <= NUMBER_OF_NOISE_SAMPLE_BLOCKS - NOISE_GATE_BLOCKS_TO_AVERAGE; i += NOISE_GATE_BLOCKS_TO_AVERAGE) { float thisAverage = 0.0f; - for (int j = i; j < i + NOISE_GATE_FRAMES_TO_AVERAGE; j++) { - thisAverage += _sampleFrames[j]; - averageOfAllSampleFrames += _sampleFrames[j]; + for (int j = i; j < i + NOISE_GATE_BLOCKS_TO_AVERAGE; j++) { + thisAverage += _sampleBlocks[j]; + averageOfAllSampleBlocks += _sampleBlocks[j]; } - thisAverage /= NOISE_GATE_FRAMES_TO_AVERAGE; - + thisAverage /= NOISE_GATE_BLOCKS_TO_AVERAGE; + if (thisAverage < smallestSample) { smallestSample = thisAverage; } } - averageOfAllSampleFrames /= NUMBER_OF_NOISE_SAMPLE_FRAMES; + averageOfAllSampleBlocks /= NUMBER_OF_NOISE_SAMPLE_BLOCKS; _measuredFloor = smallestSample; _sampleCounter = 0; - + } - _closedInLastFrame = false; - _openedInLastFrame = false; + _closedInLastBlock = false; + _openedInLastBlock = false; if (samplesOverNoiseGate > NOISE_GATE_WIDTH) { - _openedInLastFrame = !_isOpen; + _openedInLastBlock = !_isOpen; _isOpen = true; - _framesToClose = NOISE_GATE_CLOSE_FRAME_DELAY; + _blocksToClose = NOISE_GATE_CLOSE_BLOCK_DELAY; } else { - if (--_framesToClose == 0) { - _closedInLastFrame = _isOpen; + if (--_blocksToClose == 0) { + _closedInLastBlock = _isOpen; _isOpen = false; } } if (!_isOpen) { - if (_closedInLastFrame) { - // would be nice to do a little crossfade to silence + // First block after being closed gets faded to silence, we fade across + // the entire block on fading out. All subsequent blocks are muted by being slammed + // to zeros + if (_closedInLastBlock) { + float fadeSlope = (1.0f / numSamples); for (int i = 0; i < numSamples; i++) { - float fadedSample = (1.0f - (float)i / (float)numSamples) * (float)samples[i]; + float fadedSample = (1.0f - ((float)i * fadeSlope)) * (float)samples[i]; samples[i] = (int16_t)fadedSample; } } else { @@ -167,10 +150,14 @@ void AudioNoiseGate::gateSamples(int16_t* samples, int numSamples) { _lastLoudness = 0; } - if (_openedInLastFrame) { - // would be nice to do a little crossfade from silence - for (int i = 0; i < numSamples; i++) { - float fadedSample = ((float)i / (float)numSamples) * (float)samples[i]; + if (_openedInLastBlock) { + // would be nice to do a little crossfade from silence, but we only want to fade + // across the first 1/10th of the block, because we don't want to miss early + // transients. + int fadeSamples = numSamples / 10; // fade over 1/10th of the samples + float fadeSlope = (1.0f / fadeSamples); + for (int i = 0; i < fadeSamples; i++) { + float fadedSample = (float)i * fadeSlope * (float)samples[i]; samples[i] = (int16_t)fadedSample; } } diff --git a/libraries/audio-client/src/AudioNoiseGate.h b/libraries/audio/src/AudioNoiseGate.h similarity index 59% rename from libraries/audio-client/src/AudioNoiseGate.h rename to libraries/audio/src/AudioNoiseGate.h index fb31561994..8430f120e5 100644 --- a/libraries/audio-client/src/AudioNoiseGate.h +++ b/libraries/audio/src/AudioNoiseGate.h @@ -1,6 +1,6 @@ // // AudioNoiseGate.h -// interface/src/audio +// libraries/audio // // Created by Stephen Birarda on 2014-12-16. // Copyright 2014 High Fidelity, Inc. @@ -14,38 +14,35 @@ #include -const int NUMBER_OF_NOISE_SAMPLE_FRAMES = 300; +const int NUMBER_OF_NOISE_SAMPLE_BLOCKS = 300; class AudioNoiseGate { public: AudioNoiseGate(); - + void gateSamples(int16_t* samples, int numSamples); void removeDCOffset(int16_t* samples, int numSamples); - - bool clippedInLastFrame() const { return _didClipInLastFrame; } - bool closedInLastFrame() const { return _closedInLastFrame; } - bool openedInLastFrame() const { return _openedInLastFrame; } + + bool clippedInLastBlock() const { return _didClipInLastBlock; } + bool closedInLastBlock() const { return _closedInLastBlock; } + bool openedInLastBlock() const { return _openedInLastBlock; } bool isOpen() const { return _isOpen; } float getMeasuredFloor() const { return _measuredFloor; } float getLastLoudness() const { return _lastLoudness; } - + static const float CLIPPING_THRESHOLD; - + private: - int _inputFrameCounter; float _lastLoudness; - float _quietestFrame; - float _loudestFrame; - bool _didClipInLastFrame; + bool _didClipInLastBlock; float _dcOffset; float _measuredFloor; - float _sampleFrames[NUMBER_OF_NOISE_SAMPLE_FRAMES]; + float _sampleBlocks[NUMBER_OF_NOISE_SAMPLE_BLOCKS]; int _sampleCounter; bool _isOpen; - bool _closedInLastFrame { false }; - bool _openedInLastFrame { false }; - int _framesToClose; + bool _closedInLastBlock { false }; + bool _openedInLastBlock { false }; + int _blocksToClose; }; -#endif // hifi_AudioNoiseGate_h \ No newline at end of file +#endif // hifi_AudioNoiseGate_h diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index f57be4eab3..363887de25 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -143,12 +143,35 @@ void PhysicsEngine::addObjectToDynamicsWorld(ObjectMotionState* motionState) { } void PhysicsEngine::removeObjects(const VectorOfMotionStates& objects) { - // first bump and prune contacts for all objects in the list + // bump and prune contacts for all objects in the list for (auto object : objects) { bumpAndPruneContacts(object); } - // then remove them + if (_activeStaticBodies.size() > 0) { + // _activeStaticBodies was not cleared last frame. + // The only way to get here is if a static object were moved but we did not actually step the simulation last + // frame (because the framerate is faster than our physics simulation rate). When this happens we must scan + // _activeStaticBodies for objects that were recently deleted so we don't try to access a dangling pointer. + for (auto object : objects) { + btRigidBody* body = object->getRigidBody(); + + std::vector::reverse_iterator itr = _activeStaticBodies.rbegin(); + while (itr != _activeStaticBodies.rend()) { + if (body == *itr) { + if (*itr != *(_activeStaticBodies.rbegin())) { + // swap with rbegin + *itr = *(_activeStaticBodies.rbegin()); + } + _activeStaticBodies.pop_back(); + break; + } + ++itr; + } + } + } + + // remove bodies for (auto object : objects) { btRigidBody* body = object->getRigidBody(); if (body) { diff --git a/libraries/render-utils/src/AnimDebugDraw.cpp b/libraries/render-utils/src/AnimDebugDraw.cpp index c8746d5c60..6066385847 100644 --- a/libraries/render-utils/src/AnimDebugDraw.cpp +++ b/libraries/render-utils/src/AnimDebugDraw.cpp @@ -346,7 +346,9 @@ void AnimDebugDraw::update() { numVerts += (int)markerMap.size() * VERTICES_PER_BONE; auto myAvatarMarkerMap = DebugDraw::getInstance().getMyAvatarMarkerMap(); numVerts += (int)myAvatarMarkerMap.size() * VERTICES_PER_BONE; - numVerts += (int)DebugDraw::getInstance().getRays().size() * VERTICES_PER_RAY; + auto rays = DebugDraw::getInstance().getRays(); + DebugDraw::getInstance().clearRays(); + numVerts += (int)rays.size() * VERTICES_PER_RAY; // allocate verts! std::vector vertices; @@ -398,10 +400,9 @@ void AnimDebugDraw::update() { } // draw rays from shared DebugDraw singleton - for (auto& iter : DebugDraw::getInstance().getRays()) { + for (auto& iter : rays) { addLine(std::get<0>(iter), std::get<1>(iter), std::get<2>(iter), v); } - DebugDraw::getInstance().clearRays(); data._vertexBuffer->resize(sizeof(AnimDebugDrawData::Vertex) * numVerts); data._vertexBuffer->setSubData(0, vertices); diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 73a79f1bc6..d721d1c86f 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -142,7 +142,7 @@ QString encodeEntityIdIntoEntityUrl(const QString& url, const QString& entityID) QString ScriptEngine::logException(const QScriptValue& exception) { auto message = formatException(exception); - scriptErrorMessage(qPrintable(message)); + scriptErrorMessage(message); return message; } @@ -453,7 +453,7 @@ void ScriptEngine::loadURL(const QUrl& scriptURL, bool reload) { } void ScriptEngine::scriptErrorMessage(const QString& message) { - qCCritical(scriptengine) << message; + qCCritical(scriptengine) << qPrintable(message); emit errorMessage(message); }