diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index 84022d0fb9..aea4d66cae 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -786,6 +786,11 @@ void AudioClient::handleAudioInput() { delete[] inputAudioSamples; + // Remove DC offset + if (!_isStereoInput && !_audioSourceInjectEnabled) { + _inputGate.removeDCOffset(networkAudioSamples, numNetworkSamples); + } + // only impose the noise gate and perform tone injection if we are sending mono audio if (!_isStereoInput && !_audioSourceInjectEnabled && _isNoiseGateEnabled) { _inputGate.gateSamples(networkAudioSamples, numNetworkSamples); diff --git a/libraries/audio-client/src/AudioNoiseGate.cpp b/libraries/audio-client/src/AudioNoiseGate.cpp index 77f230809f..062d21fb96 100644 --- a/libraries/audio-client/src/AudioNoiseGate.cpp +++ b/libraries/audio-client/src/AudioNoiseGate.cpp @@ -33,6 +33,33 @@ AudioNoiseGate::AudioNoiseGate() : } +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. + // This causes the noise background measurements and server muting to be more accurate. Many off-board + // ADC's have a noticeable DC offset. + // + const float DC_OFFSET_AVERAGING = 0.99f; + float measuredDcOffset = 0.0f; + // Remove trailing DC offset from samples + for (int i = 0; i < numSamples; i++) { + measuredDcOffset += samples[i]; + samples[i] -= (int16_t) _dcOffset; + //samples[i] = 0; + } + // Update measured DC offset + measuredDcOffset /= numSamples; + if (_dcOffset == 0.0f) { + // On first frame, copy over measured offset + _dcOffset = measuredDcOffset; + } else { + _dcOffset = DC_OFFSET_AVERAGING * _dcOffset + (1.0f - DC_OFFSET_AVERAGING) * measuredDcOffset; + } +} + + void AudioNoiseGate::gateSamples(int16_t* samples, int numSamples) { // // Impose Noise Gate @@ -61,17 +88,12 @@ void AudioNoiseGate::gateSamples(int16_t* samples, int numSamples) { const int NOISE_GATE_WIDTH = 5; const int NOISE_GATE_CLOSE_FRAME_DELAY = 5; const int NOISE_GATE_FRAMES_TO_AVERAGE = 5; - const float DC_OFFSET_AVERAGING = 0.99f; - - // Check clipping, adjust DC offset, and check if should open noise gate - float measuredDcOffset = 0.0f; + + // Check clipping, and check if should open noise gate _didClipInLastFrame = false; for (int i = 0; i < numSamples; i++) { - measuredDcOffset += samples[i]; - samples[i] -= (int16_t) _dcOffset; thisSample = std::abs(samples[i]); - if (thisSample >= ((float) AudioConstants::MAX_SAMPLE_VALUE * CLIPPING_THRESHOLD)) { _didClipInLastFrame = true; } @@ -83,14 +105,6 @@ void AudioNoiseGate::gateSamples(int16_t* samples, int numSamples) { } } - measuredDcOffset /= numSamples; - if (_dcOffset == 0.0f) { - // On first frame, copy over measured offset - _dcOffset = measuredDcOffset; - } else { - _dcOffset = DC_OFFSET_AVERAGING * _dcOffset + (1.0f - DC_OFFSET_AVERAGING) * measuredDcOffset; - } - _lastLoudness = fabs(loudness / numSamples); if (_quietestFrame > _lastLoudness) { diff --git a/libraries/audio-client/src/AudioNoiseGate.h b/libraries/audio-client/src/AudioNoiseGate.h index bfb9ec28d5..8cb1155938 100644 --- a/libraries/audio-client/src/AudioNoiseGate.h +++ b/libraries/audio-client/src/AudioNoiseGate.h @@ -21,6 +21,7 @@ public: AudioNoiseGate(); void gateSamples(int16_t* samples, int numSamples); + void removeDCOffset(int16_t* samples, int numSamples); bool clippedInLastFrame() const { return _didClipInLastFrame; } float getMeasuredFloor() const { return _measuredFloor; }