From 95141d91d8abf32df95d938d9e4e44e6a09cb003 Mon Sep 17 00:00:00 2001 From: Alex Loiko Date: Fri, 20 Apr 2018 15:28:45 +0200 Subject: [PATCH] Set a positive initial gain in the Adaptive Digital GC. If the adaptive gain is too low, we raise it slowly and only during speech. The CL gives better behavior at the start of a call. If the gain is too high, the fixed-digital limits it. The gain is also quickly reduced by the AdaptiveGainApplier. Bug: webrtc:7494 Change-Id: I683f1e3e463cddec2d91f6c7f15c73e744430034 Reviewed-on: https://webrtc-review.googlesource.com/71484 Commit-Queue: Alex Loiko Reviewed-by: Alessio Bazzica Cr-Commit-Position: refs/heads/master@{#23053} --- .../agc2/adaptive_digital_gain_applier.cc | 3 +-- .../agc2/adaptive_digital_gain_applier.h | 3 ++- .../adaptive_digital_gain_applier_unittest.cc | 19 ++++++++++++------- modules/audio_processing/agc2/agc2_common.h | 1 + .../gain_controller2_unittest.cc | 6 ------ 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/modules/audio_processing/agc2/adaptive_digital_gain_applier.cc b/modules/audio_processing/agc2/adaptive_digital_gain_applier.cc index 74facc6dd2..20b5a27282 100644 --- a/modules/audio_processing/agc2/adaptive_digital_gain_applier.cc +++ b/modules/audio_processing/agc2/adaptive_digital_gain_applier.cc @@ -68,8 +68,7 @@ float ComputeGainChangeThisFrameDb(float target_gain_db, AdaptiveDigitalGainApplier::AdaptiveDigitalGainApplier( ApmDataDumper* apm_data_dumper) - : gain_applier_(false, 1.f), // Initial gain is 1, and we do not - // clip after gain. + : gain_applier_(false, DbToRatio(last_gain_db_)), apm_data_dumper_(apm_data_dumper) {} void AdaptiveDigitalGainApplier::Process( diff --git a/modules/audio_processing/agc2/adaptive_digital_gain_applier.h b/modules/audio_processing/agc2/adaptive_digital_gain_applier.h index b33ccbac66..b06c65b97d 100644 --- a/modules/audio_processing/agc2/adaptive_digital_gain_applier.h +++ b/modules/audio_processing/agc2/adaptive_digital_gain_applier.h @@ -11,6 +11,7 @@ #ifndef MODULES_AUDIO_PROCESSING_AGC2_ADAPTIVE_DIGITAL_GAIN_APPLIER_H_ #define MODULES_AUDIO_PROCESSING_AGC2_ADAPTIVE_DIGITAL_GAIN_APPLIER_H_ +#include "modules/audio_processing/agc2/agc2_common.h" #include "modules/audio_processing/agc2/gain_applier.h" #include "modules/audio_processing/include/audio_frame_view.h" #include "modules/audio_processing/vad/vad_with_level.h" @@ -30,7 +31,7 @@ class AdaptiveDigitalGainApplier { AudioFrameView float_frame); private: - float last_gain_db_ = 0.f; + float last_gain_db_ = kInitialAdaptiveDigitalGainDb; GainApplier gain_applier_; // For some combinations of noise and speech probability, increasing diff --git a/modules/audio_processing/agc2/adaptive_digital_gain_applier_unittest.cc b/modules/audio_processing/agc2/adaptive_digital_gain_applier_unittest.cc index 8715e904ad..ebb040eb34 100644 --- a/modules/audio_processing/agc2/adaptive_digital_gain_applier_unittest.cc +++ b/modules/audio_processing/agc2/adaptive_digital_gain_applier_unittest.cc @@ -145,7 +145,7 @@ TEST(AutomaticGainController2AdaptiveGainApplier, GainIsRampedInAFrame) { rtc::ArrayView(&kVadSpeech, 1), fake_audio.float_frame_view()); float maximal_difference = 0.f; - float current_value = 1.f; + float current_value = 1.f * DbToRatio(kInitialAdaptiveDigitalGainDb); for (const auto& x : fake_audio.float_frame_view().channel(0)) { const float difference = std::abs(x - current_value); maximal_difference = std::max(maximal_difference, difference); @@ -164,22 +164,27 @@ TEST(AutomaticGainController2AdaptiveGainApplier, NoiseLimitsGain) { constexpr float initial_level_dbfs = -25.f; constexpr int num_samples = 480; - constexpr int num_frames = 100; + constexpr int num_initial_frames = + kInitialAdaptiveDigitalGainDb / kMaxGainChangePerFrameDb; + constexpr int num_frames = 50; ASSERT_GT(kWithNoiseDbfs, kMaxNoiseLevelDbfs) << "kWithNoiseDbfs is too low"; - for (int i = 0; i < num_frames; ++i) { + for (int i = 0; i < num_initial_frames + num_frames; ++i) { VectorFloatFrame fake_audio(1, num_samples, 1.f); gain_applier.Process( initial_level_dbfs, kWithNoiseDbfs, rtc::ArrayView(&kVadSpeech, 1), fake_audio.float_frame_view()); - const float maximal_ratio = - *std::max_element(fake_audio.float_frame_view().channel(0).begin(), - fake_audio.float_frame_view().channel(0).end()); + // Wait so that the adaptive gain applier has time to lower the gain. + if (i > num_initial_frames) { + const float maximal_ratio = + *std::max_element(fake_audio.float_frame_view().channel(0).begin(), + fake_audio.float_frame_view().channel(0).end()); - EXPECT_NEAR(maximal_ratio, 1.f, 0.001f); + EXPECT_NEAR(maximal_ratio, 1.f, 0.001f); + } } } } // namespace webrtc diff --git a/modules/audio_processing/agc2/agc2_common.h b/modules/audio_processing/agc2/agc2_common.h index a6f5fbd82d..3a499d98a2 100644 --- a/modules/audio_processing/agc2/agc2_common.h +++ b/modules/audio_processing/agc2/agc2_common.h @@ -33,6 +33,7 @@ constexpr float kMaxGainChangePerFrameDb = kMaxGainChangePerSecondDb * kFrameDurationMs / 1000.f; constexpr float kHeadroomDbfs = 1.f; constexpr float kMaxGainDb = 30.f; +constexpr float kInitialAdaptiveDigitalGainDb = 8.f; // This parameter must be tuned together with the noise estimator. constexpr float kMaxNoiseLevelDbfs = -50.f; diff --git a/modules/audio_processing/gain_controller2_unittest.cc b/modules/audio_processing/gain_controller2_unittest.cc index 5b5bd03b16..5bedccd64a 100644 --- a/modules/audio_processing/gain_controller2_unittest.cc +++ b/modules/audio_processing/gain_controller2_unittest.cc @@ -80,12 +80,6 @@ TEST(GainController2, Usage) { SetAudioBufferSamples(sample_value, &ab); AudioProcessing::Config::GainController2 config; - // Check that samples are not modified when the fixed gain is 0 dB. - config.fixed_gain_db = 0.f; - gain_controller2->ApplyConfig(config); - gain_controller2->Process(&ab); - EXPECT_EQ(ab.channels_f()[0][0], sample_value); - // Check that samples are amplified when the fixed gain is greater than 0 dB. config.fixed_gain_db = 5.f; gain_controller2->ApplyConfig(config);