Add Audio Noise Reduction

This commit is contained in:
Philip Rosedale 2014-02-08 16:35:37 -08:00
parent f5bbdc2c65
commit 03bc5adf64
5 changed files with 53 additions and 6 deletions

View file

@ -65,6 +65,10 @@ Audio::Audio(Oscilloscope* scope, int16_t initialJitterBufferSamples, QObject* p
_measuredJitter(0), _measuredJitter(0),
_jitterBufferSamples(initialJitterBufferSamples), _jitterBufferSamples(initialJitterBufferSamples),
_lastInputLoudness(0), _lastInputLoudness(0),
_averageInputLoudness(0),
_noiseGateOpen(false),
_noiseGateEnabled(true),
_noiseGateFramesToClose(0),
_lastVelocity(0), _lastVelocity(0),
_lastAcceleration(0), _lastAcceleration(0),
_totalPacketsReceived(0), _totalPacketsReceived(0),
@ -348,12 +352,40 @@ void Audio::handleAudioInput() {
_inputFormat, _desiredInputFormat); _inputFormat, _desiredInputFormat);
float loudness = 0; 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++) { 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; _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 // add input data just written to the scope
QMetaObject::invokeMethod(_scope, "addSamples", Qt::QueuedConnection, QMetaObject::invokeMethod(_scope, "addSamples", Qt::QueuedConnection,
@ -524,6 +556,10 @@ void Audio::toggleMute() {
muteToggled(); muteToggled();
} }
void Audio::toggleAudioNoiseReduction() {
_noiseGateEnabled = !_noiseGateEnabled;
}
void Audio::render(int screenWidth, int screenHeight) { void Audio::render(int screenWidth, int screenHeight) {
if (_audioInput && _audioOutput) { if (_audioInput && _audioOutput) {
glLineWidth(2.0); glLineWidth(2.0);

View file

@ -45,7 +45,9 @@ public:
void render(int screenWidth, int screenHeight); 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 setLastAcceleration(const glm::vec3 lastAcceleration) { _lastAcceleration = lastAcceleration; }
void setLastVelocity(const glm::vec3 lastVelocity) { _lastVelocity = lastVelocity; } void setLastVelocity(const glm::vec3 lastVelocity) { _lastVelocity = lastVelocity; }
@ -73,6 +75,7 @@ public slots:
void handleAudioInput(); void handleAudioInput();
void reset(); void reset();
void toggleMute(); void toggleMute();
void toggleAudioNoiseReduction();
virtual void handleAudioByteArray(const QByteArray& audioByteArray); virtual void handleAudioByteArray(const QByteArray& audioByteArray);
@ -106,6 +109,10 @@ private:
float _measuredJitter; float _measuredJitter;
int16_t _jitterBufferSamples; int16_t _jitterBufferSamples;
float _lastInputLoudness; float _lastInputLoudness;
float _averageInputLoudness;
bool _noiseGateOpen;
bool _noiseGateEnabled;
int _noiseGateFramesToClose;
glm::vec3 _lastVelocity; glm::vec3 _lastVelocity;
glm::vec3 _lastAcceleration; glm::vec3 _lastAcceleration;
int _totalPacketsReceived; int _totalPacketsReceived;

View file

@ -457,6 +457,11 @@ Menu::Menu() :
addCheckableActionToQMenuAndActionHash(renderDebugMenu, MenuOption::CoverageMapV2, Qt::SHIFT | Qt::CTRL | Qt::Key_P); addCheckableActionToQMenuAndActionHash(renderDebugMenu, MenuOption::CoverageMapV2, Qt::SHIFT | Qt::CTRL | Qt::Key_P);
QMenu* audioDebugMenu = developerMenu->addMenu("Audio Debugging Tools"); QMenu* audioDebugMenu = developerMenu->addMenu("Audio Debugging Tools");
addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::AudioNoiseReduction,
0,
true,
appInstance->getAudio(),
SLOT(toggleAudioNoiseReduction()));
addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::EchoServerAudio); addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::EchoServerAudio);
addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::EchoLocalAudio); addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::EchoLocalAudio);
addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::MuteAudio, addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::MuteAudio,

View file

@ -187,6 +187,7 @@ namespace MenuOption {
const QString Enable3DTVMode = "Enable 3DTV Mode"; const QString Enable3DTVMode = "Enable 3DTV Mode";
const QString EnableOcclusionCulling = "Enable Occlusion Culling"; const QString EnableOcclusionCulling = "Enable Occlusion Culling";
const QString EnableVoxelPacketCompression = "Enable Voxel Packet Compression"; const QString EnableVoxelPacketCompression = "Enable Voxel Packet Compression";
const QString AudioNoiseReduction = "Audio Noise Reduction";
const QString EchoServerAudio = "Echo Server Audio"; const QString EchoServerAudio = "Echo Server Audio";
const QString EchoLocalAudio = "Echo Local Audio"; const QString EchoLocalAudio = "Echo Local Audio";
const QString MuteAudio = "Mute Microphone"; const QString MuteAudio = "Mute Microphone";

View file

@ -107,7 +107,6 @@ QByteArray AvatarData::toByteArray() {
destinationBuffer += sizeof(_headData->_lookAtPosition); destinationBuffer += sizeof(_headData->_lookAtPosition);
// Instantaneous audio loudness (used to drive facial animation) // 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)); memcpy(destinationBuffer, &_headData->_audioLoudness, sizeof(float));
destinationBuffer += sizeof(float); destinationBuffer += sizeof(float);
@ -215,7 +214,6 @@ int AvatarData::parseData(const QByteArray& packet) {
sourceBuffer += sizeof(_headData->_lookAtPosition); sourceBuffer += sizeof(_headData->_lookAtPosition);
// Instantaneous audio loudness (used to drive facial animation) // Instantaneous audio loudness (used to drive facial animation)
//sourceBuffer += unpackFloatFromByte(sourceBuffer, _audioLoudness, MAX_AUDIO_LOUDNESS);
memcpy(&_headData->_audioLoudness, sourceBuffer, sizeof(float)); memcpy(&_headData->_audioLoudness, sourceBuffer, sizeof(float));
sourceBuffer += sizeof(float); sourceBuffer += sizeof(float);