From 03bc5adf64b88e870405185c579d5bf31211b425 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Sat, 8 Feb 2014 16:35:37 -0800 Subject: [PATCH] Add Audio Noise Reduction --- interface/src/Audio.cpp | 42 ++++++++++++++++++++++++++-- interface/src/Audio.h | 9 +++++- interface/src/Menu.cpp | 5 ++++ interface/src/Menu.h | 1 + libraries/avatars/src/AvatarData.cpp | 2 -- 5 files changed, 53 insertions(+), 6 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 9dd3c0377f..6eee4453d4 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -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); diff --git a/interface/src/Audio.h b/interface/src/Audio.h index fa4fb62adf..88e2731006 100644 --- a/interface/src/Audio.h +++ b/interface/src/Audio.h @@ -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; diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 6640df3468..af41e583b9 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -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, diff --git a/interface/src/Menu.h b/interface/src/Menu.h index fcd2d74940..edc6035f60 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -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"; diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index ca57fff587..b2cd1cf076 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -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);