From 0e3198e4344b093e66ed9196412961d14c50d4ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Per=20=C3=85hgren?= Date: Mon, 18 Nov 2019 08:52:22 +0100 Subject: [PATCH] Refactoring of the analog AGC functionality to add multichannel support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This CL refactors the analog AGC functionality. In particular it: -Breaks then tight dependency between the analog AGC and the digital AGC implementation. -Removes the complicated callback interface for reporting the analog level and replaces it with an int. Bug: webrtc:10859 Change-Id: I3572d60ab98edebbcffa25af64cc74c66f9868fc Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/159039 Reviewed-by: Sam Zackrisson Commit-Queue: Per Ã…hgren Cr-Commit-Position: refs/heads/master@{#29838} --- modules/audio_processing/BUILD.gn | 2 - modules/audio_processing/agc/BUILD.gn | 1 + .../agc/agc_manager_direct.cc | 84 ++++----- .../audio_processing/agc/agc_manager_direct.h | 34 ++-- .../agc/agc_manager_direct_unittest.cc | 174 ++++++++---------- .../audio_processing/audio_processing_impl.cc | 140 +++++++------- .../audio_processing/audio_processing_impl.h | 42 ++--- .../gain_control_for_experimental_agc.cc | 117 ------------ .../gain_control_for_experimental_agc.h | 77 -------- modules/audio_processing/gain_control_impl.h | 15 +- 10 files changed, 222 insertions(+), 464 deletions(-) delete mode 100644 modules/audio_processing/gain_control_for_experimental_agc.cc delete mode 100644 modules/audio_processing/gain_control_for_experimental_agc.h diff --git a/modules/audio_processing/BUILD.gn b/modules/audio_processing/BUILD.gn index 57b49b2fd8..9e6ee75451 100644 --- a/modules/audio_processing/BUILD.gn +++ b/modules/audio_processing/BUILD.gn @@ -124,8 +124,6 @@ rtc_library("audio_processing") { "echo_detector/moving_max.h", "echo_detector/normalized_covariance_estimator.cc", "echo_detector/normalized_covariance_estimator.h", - "gain_control_for_experimental_agc.cc", - "gain_control_for_experimental_agc.h", "gain_control_impl.cc", "gain_control_impl.h", "gain_controller2.cc", diff --git a/modules/audio_processing/agc/BUILD.gn b/modules/audio_processing/agc/BUILD.gn index 05eb42d143..dc93ebe8ee 100644 --- a/modules/audio_processing/agc/BUILD.gn +++ b/modules/audio_processing/agc/BUILD.gn @@ -36,6 +36,7 @@ rtc_library("agc") { "../../../system_wrappers:metrics", "../agc2:level_estimation_agc", "../vad", + "//third_party/abseil-cpp/absl/types:optional", ] } diff --git a/modules/audio_processing/agc/agc_manager_direct.cc b/modules/audio_processing/agc/agc_manager_direct.cc index 13b902f17f..2f453f4a69 100644 --- a/modules/audio_processing/agc/agc_manager_direct.cc +++ b/modules/audio_processing/agc/agc_manager_direct.cc @@ -116,31 +116,6 @@ int LevelFromGainError(int gain_error, int level, int min_mic_level) { return new_level; } -int InitializeGainControl(GainControl* gain_control, - bool disable_digital_adaptive) { - if (gain_control->set_mode(GainControl::kFixedDigital) != 0) { - RTC_LOG(LS_ERROR) << "set_mode(GainControl::kFixedDigital) failed."; - return -1; - } - const int target_level_dbfs = disable_digital_adaptive ? 0 : 2; - if (gain_control->set_target_level_dbfs(target_level_dbfs) != 0) { - RTC_LOG(LS_ERROR) << "set_target_level_dbfs() failed."; - return -1; - } - const int compression_gain_db = - disable_digital_adaptive ? 0 : kDefaultCompressionGain; - if (gain_control->set_compression_gain_db(compression_gain_db) != 0) { - RTC_LOG(LS_ERROR) << "set_compression_gain_db() failed."; - return -1; - } - const bool enable_limiter = !disable_digital_adaptive; - if (gain_control->enable_limiter(enable_limiter) != 0) { - RTC_LOG(LS_ERROR) << "enable_limiter() failed."; - return -1; - } - return 0; -} - // Returns the proportion of samples in the buffer which are at full-scale // (and presumably clipped). float ComputeClippedRatio(const float* const* audio, @@ -164,29 +139,18 @@ float ComputeClippedRatio(const float* const* audio, } // namespace AgcManagerDirect::AgcManagerDirect(Agc* agc, - GainControl* gctrl, - VolumeCallbacks* volume_callbacks, int startup_min_level, int clipped_level_min) - : AgcManagerDirect(gctrl, - volume_callbacks, - startup_min_level, - clipped_level_min, - false, - false) { + : AgcManagerDirect(startup_min_level, clipped_level_min, false, false) { RTC_DCHECK(agc_); agc_.reset(agc); } -AgcManagerDirect::AgcManagerDirect(GainControl* gctrl, - VolumeCallbacks* volume_callbacks, - int startup_min_level, +AgcManagerDirect::AgcManagerDirect(int startup_min_level, int clipped_level_min, bool use_agc2_level_estimation, bool disable_digital_adaptive) : data_dumper_(new ApmDataDumper(instance_counter_)), - gctrl_(gctrl), - volume_callbacks_(volume_callbacks), frames_since_clipped_(kClippedWaitFrames), level_(0), max_level_(kMaxMicLevel), @@ -211,7 +175,7 @@ AgcManagerDirect::AgcManagerDirect(GainControl* gctrl, AgcManagerDirect::~AgcManagerDirect() {} -int AgcManagerDirect::Initialize() { +void AgcManagerDirect::Initialize() { RTC_DLOG(LS_INFO) << "AgcManagerDirect::Initialize"; max_level_ = kMaxMicLevel; max_compression_gain_ = kMaxCompressionGain; @@ -224,8 +188,25 @@ int AgcManagerDirect::Initialize() { // example, what happens when we change devices. data_dumper_->InitiateNewSetOfRecordings(); +} - return InitializeGainControl(gctrl_, disable_digital_adaptive_); +void AgcManagerDirect::ConfigureGainControl(GainControl* gain_control) const { + if (gain_control->set_mode(GainControl::kFixedDigital) != 0) { + RTC_LOG(LS_ERROR) << "set_mode(GainControl::kFixedDigital) failed."; + } + const int target_level_dbfs = disable_digital_adaptive_ ? 0 : 2; + if (gain_control->set_target_level_dbfs(target_level_dbfs) != 0) { + RTC_LOG(LS_ERROR) << "set_target_level_dbfs() failed."; + } + const int compression_gain_db = + disable_digital_adaptive_ ? 0 : kDefaultCompressionGain; + if (gain_control->set_compression_gain_db(compression_gain_db) != 0) { + RTC_LOG(LS_ERROR) << "set_compression_gain_db() failed."; + } + const bool enable_limiter = !disable_digital_adaptive_; + if (gain_control->enable_limiter(enable_limiter) != 0) { + RTC_LOG(LS_ERROR) << "enable_limiter() failed."; + } } void AgcManagerDirect::AnalyzePreProcess(const float* const* audio, @@ -274,7 +255,8 @@ void AgcManagerDirect::AnalyzePreProcess(const float* const* audio, void AgcManagerDirect::Process(const float* audio, size_t length, - int sample_rate_hz) { + int sample_rate_hz, + GainControl* gain_control) { if (capture_muted_) { return; } @@ -305,12 +287,19 @@ void AgcManagerDirect::Process(const float* audio, UpdateCompressor(); } + if (new_compression_to_set_) { + if (gain_control->set_compression_gain_db(*new_compression_to_set_) != 0) { + RTC_LOG(LS_ERROR) << "set_compression_gain_db(" << compression_ + << ") failed."; + } + } + new_compression_to_set_ = absl::nullopt; data_dumper_->DumpRaw("experimental_gain_control_compression_gain_db", 1, &compression_); } void AgcManagerDirect::SetLevel(int new_level) { - int voe_level = volume_callbacks_->GetMicVolume(); + int voe_level = stream_analog_level_; if (voe_level == 0) { RTC_DLOG(LS_INFO) << "[agc] VolumeCallbacks returned level=0, taking no action."; @@ -344,7 +333,7 @@ void AgcManagerDirect::SetLevel(int new_level) { return; } - volume_callbacks_->SetMicVolume(new_level); + stream_analog_level_ = new_level; RTC_DLOG(LS_INFO) << "[agc] voe_level=" << voe_level << ", " << "level_=" << level_ << ", " << "new_level=" << new_level; @@ -382,7 +371,7 @@ float AgcManagerDirect::voice_probability() { } int AgcManagerDirect::CheckVolumeAndReset() { - int level = volume_callbacks_->GetMicVolume(); + int level = stream_analog_level_; // Reasons for taking action at startup: // 1) A person starting a call is expected to be heard. // 2) Independent of interpretation of |level| == 0 we should raise it so the @@ -403,7 +392,7 @@ int AgcManagerDirect::CheckVolumeAndReset() { if (level < minLevel) { level = minLevel; RTC_DLOG(LS_INFO) << "[agc] Initial volume too low, raising to " << level; - volume_callbacks_->SetMicVolume(level); + stream_analog_level_ = level; } agc_->Reset(); level_ = level; @@ -508,10 +497,7 @@ void AgcManagerDirect::UpdateCompressor() { kMaxCompressionGain + 1); compression_ = new_compression; compression_accumulator_ = new_compression; - if (gctrl_->set_compression_gain_db(compression_) != 0) { - RTC_LOG(LS_ERROR) << "set_compression_gain_db(" << compression_ - << ") failed."; - } + new_compression_to_set_ = compression_; } } diff --git a/modules/audio_processing/agc/agc_manager_direct.h b/modules/audio_processing/agc/agc_manager_direct.h index 505ad15b29..05f72ea8a5 100644 --- a/modules/audio_processing/agc/agc_manager_direct.h +++ b/modules/audio_processing/agc/agc_manager_direct.h @@ -13,6 +13,7 @@ #include +#include "absl/types/optional.h" #include "modules/audio_processing/agc/agc.h" #include "modules/audio_processing/logging/apm_data_dumper.h" #include "rtc_base/constructor_magic.h" @@ -23,17 +24,6 @@ namespace webrtc { class AudioFrame; class GainControl; -// Callbacks that need to be injected into AgcManagerDirect to read and control -// the volume values. This is done to remove the VoiceEngine dependency in -// AgcManagerDirect. -// TODO(aluebs): Remove VolumeCallbacks. -class VolumeCallbacks { - public: - virtual ~VolumeCallbacks() {} - virtual void SetMicVolume(int volume) = 0; - virtual int GetMicVolume() = 0; -}; - // Direct interface to use AGC to set volume and compression values. // AudioProcessing uses this interface directly to integrate the callback-less // AGC. @@ -45,20 +35,23 @@ class AgcManagerDirect final { // responsible for processing the audio using it after the call to Process. // The operating range of startup_min_level is [12, 255] and any input value // outside that range will be clamped. - AgcManagerDirect(GainControl* gctrl, - VolumeCallbacks* volume_callbacks, - int startup_min_level, + AgcManagerDirect(int startup_min_level, int clipped_level_min, bool use_agc2_level_estimation, bool disable_digital_adaptive); ~AgcManagerDirect(); - int Initialize(); + void Initialize(); + void ConfigureGainControl(GainControl* gain_control) const; + void AnalyzePreProcess(const float* const* audio, int num_channels, size_t samples_per_channel); - void Process(const float* audio, size_t length, int sample_rate_hz); + void Process(const float* audio, + size_t length, + int sample_rate_hz, + GainControl* gain_control); // Call when the capture stream has been muted/unmuted. This causes the // manager to disregard all incoming audio; chances are good it's background @@ -68,6 +61,9 @@ class AgcManagerDirect final { float voice_probability(); + int stream_analog_level() const { return stream_analog_level_; } + void set_stream_analog_level(int level) { stream_analog_level_ = level; } + private: friend class AgcManagerDirectTest; @@ -79,8 +75,6 @@ class AgcManagerDirect final { // Dependency injection for testing. Don't delete |agc| as the memory is owned // by the manager. AgcManagerDirect(Agc* agc, - GainControl* gctrl, - VolumeCallbacks* volume_callbacks, int startup_min_level, int clipped_level_min); @@ -104,8 +98,6 @@ class AgcManagerDirect final { static int instance_counter_; std::unique_ptr agc_; - GainControl* gctrl_; - VolumeCallbacks* volume_callbacks_; int frames_since_clipped_; int level_; @@ -122,6 +114,8 @@ class AgcManagerDirect final { int startup_min_level_; const int clipped_level_min_; int calls_since_last_gain_log_ = 0; + int stream_analog_level_ = 0; + absl::optional new_compression_to_set_; RTC_DISALLOW_COPY_AND_ASSIGN(AgcManagerDirect); }; diff --git a/modules/audio_processing/agc/agc_manager_direct_unittest.cc b/modules/audio_processing/agc/agc_manager_direct_unittest.cc index bc8309e983..43f5d2df04 100644 --- a/modules/audio_processing/agc/agc_manager_direct_unittest.cc +++ b/modules/audio_processing/agc/agc_manager_direct_unittest.cc @@ -55,27 +55,18 @@ class MockGainControl : public GainControl { MOCK_CONST_METHOD0(stream_is_saturated, bool()); }; -class TestVolumeCallbacks : public VolumeCallbacks { - public: - TestVolumeCallbacks() : volume_(0) {} - void SetMicVolume(int volume) override { volume_ = volume; } - int GetMicVolume() override { return volume_; } - - private: - int volume_; -}; - } // namespace class AgcManagerDirectTest : public ::testing::Test { protected: AgcManagerDirectTest() : agc_(new MockAgc), - manager_(agc_, &gctrl_, &volume_, kInitialVolume, kClippedMin), + manager_(agc_, kInitialVolume, kClippedMin), audio(kNumChannels), audio_data(kNumChannels * kSamplesPerChannel, 0.f) { ExpectInitialize(); manager_.Initialize(); + manager_.ConfigureGainControl(&gctrl_); for (size_t ch = 0; ch < kNumChannels; ++ch) { audio[ch] = &audio_data[ch * kSamplesPerChannel]; } @@ -88,12 +79,12 @@ class AgcManagerDirectTest : public ::testing::Test { } void SetVolumeAndProcess(int volume) { - volume_.SetMicVolume(volume); + manager_.set_stream_analog_level(volume); FirstProcess(); } void ExpectCheckVolumeAndReset(int volume) { - volume_.SetMicVolume(volume); + manager_.set_stream_analog_level(volume); EXPECT_CALL(*agc_, Reset()); } @@ -107,7 +98,7 @@ class AgcManagerDirectTest : public ::testing::Test { void CallProcess(int num_calls) { for (int i = 0; i < num_calls; ++i) { EXPECT_CALL(*agc_, Process(_, _, _)).WillOnce(Return()); - manager_.Process(nullptr, kSamplesPerChannel, kSampleRateHz); + manager_.Process(nullptr, kSamplesPerChannel, kSampleRateHz, &gctrl_); } } @@ -129,7 +120,6 @@ class AgcManagerDirectTest : public ::testing::Test { MockAgc* agc_; MockGainControl gctrl_; - TestVolumeCallbacks volume_; AgcManagerDirect manager_; std::vector audio; std::vector audio_data; @@ -137,7 +127,7 @@ class AgcManagerDirectTest : public ::testing::Test { TEST_F(AgcManagerDirectTest, StartupMinVolumeConfigurationIsRespected) { FirstProcess(); - EXPECT_EQ(kInitialVolume, volume_.GetMicVolume()); + EXPECT_EQ(kInitialVolume, manager_.stream_analog_level()); } TEST_F(AgcManagerDirectTest, MicVolumeResponseToRmsError) { @@ -157,12 +147,12 @@ TEST_F(AgcManagerDirectTest, MicVolumeResponseToRmsError) { EXPECT_CALL(*agc_, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(11), Return(true))); CallProcess(1); - EXPECT_EQ(130, volume_.GetMicVolume()); + EXPECT_EQ(130, manager_.stream_analog_level()); EXPECT_CALL(*agc_, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(20), Return(true))); CallProcess(1); - EXPECT_EQ(168, volume_.GetMicVolume()); + EXPECT_EQ(168, manager_.stream_analog_level()); // Inside the compressor's window; no change of volume. EXPECT_CALL(*agc_, GetRmsErrorDb(_)) @@ -176,17 +166,17 @@ TEST_F(AgcManagerDirectTest, MicVolumeResponseToRmsError) { EXPECT_CALL(*agc_, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(-1), Return(true))); CallProcess(1); - EXPECT_EQ(167, volume_.GetMicVolume()); + EXPECT_EQ(167, manager_.stream_analog_level()); EXPECT_CALL(*agc_, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(-1), Return(true))); CallProcess(1); - EXPECT_EQ(163, volume_.GetMicVolume()); + EXPECT_EQ(163, manager_.stream_analog_level()); EXPECT_CALL(*agc_, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(-9), Return(true))); CallProcess(1); - EXPECT_EQ(129, volume_.GetMicVolume()); + EXPECT_EQ(129, manager_.stream_analog_level()); } TEST_F(AgcManagerDirectTest, MicVolumeIsLimited) { @@ -196,60 +186,60 @@ TEST_F(AgcManagerDirectTest, MicVolumeIsLimited) { EXPECT_CALL(*agc_, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(30), Return(true))); CallProcess(1); - EXPECT_EQ(183, volume_.GetMicVolume()); + EXPECT_EQ(183, manager_.stream_analog_level()); EXPECT_CALL(*agc_, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(30), Return(true))); CallProcess(1); - EXPECT_EQ(243, volume_.GetMicVolume()); + EXPECT_EQ(243, manager_.stream_analog_level()); // Won't go higher than the maximum. EXPECT_CALL(*agc_, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(30), Return(true))); CallProcess(1); - EXPECT_EQ(255, volume_.GetMicVolume()); + EXPECT_EQ(255, manager_.stream_analog_level()); EXPECT_CALL(*agc_, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(-1), Return(true))); CallProcess(1); - EXPECT_EQ(254, volume_.GetMicVolume()); + EXPECT_EQ(254, manager_.stream_analog_level()); // Maximum downwards change is limited. EXPECT_CALL(*agc_, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(-40), Return(true))); CallProcess(1); - EXPECT_EQ(194, volume_.GetMicVolume()); + EXPECT_EQ(194, manager_.stream_analog_level()); EXPECT_CALL(*agc_, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(-40), Return(true))); CallProcess(1); - EXPECT_EQ(137, volume_.GetMicVolume()); + EXPECT_EQ(137, manager_.stream_analog_level()); EXPECT_CALL(*agc_, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(-40), Return(true))); CallProcess(1); - EXPECT_EQ(88, volume_.GetMicVolume()); + EXPECT_EQ(88, manager_.stream_analog_level()); EXPECT_CALL(*agc_, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(-40), Return(true))); CallProcess(1); - EXPECT_EQ(54, volume_.GetMicVolume()); + EXPECT_EQ(54, manager_.stream_analog_level()); EXPECT_CALL(*agc_, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(-40), Return(true))); CallProcess(1); - EXPECT_EQ(33, volume_.GetMicVolume()); + EXPECT_EQ(33, manager_.stream_analog_level()); EXPECT_CALL(*agc_, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(-40), Return(true))); CallProcess(1); - EXPECT_EQ(18, volume_.GetMicVolume()); + EXPECT_EQ(18, manager_.stream_analog_level()); // Won't go lower than the minimum. EXPECT_CALL(*agc_, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(-40), Return(true))); CallProcess(1); - EXPECT_EQ(12, volume_.GetMicVolume()); + EXPECT_EQ(12, manager_.stream_analog_level()); } TEST_F(AgcManagerDirectTest, CompressorStepsTowardsTarget) { @@ -374,7 +364,7 @@ TEST_F(AgcManagerDirectTest, CompressorReachesMinimum) { TEST_F(AgcManagerDirectTest, NoActionWhileMuted) { manager_.SetCaptureMuted(true); - manager_.Process(nullptr, kSamplesPerChannel, kSampleRateHz); + manager_.Process(nullptr, kSamplesPerChannel, kSampleRateHz, &gctrl_); } TEST_F(AgcManagerDirectTest, UnmutingChecksVolumeWithoutRaising) { @@ -386,7 +376,7 @@ TEST_F(AgcManagerDirectTest, UnmutingChecksVolumeWithoutRaising) { // SetMicVolume should not be called. EXPECT_CALL(*agc_, GetRmsErrorDb(_)).WillOnce(Return(false)); CallProcess(1); - EXPECT_EQ(127, volume_.GetMicVolume()); + EXPECT_EQ(127, manager_.stream_analog_level()); } TEST_F(AgcManagerDirectTest, UnmutingRaisesTooLowVolume) { @@ -397,7 +387,7 @@ TEST_F(AgcManagerDirectTest, UnmutingRaisesTooLowVolume) { ExpectCheckVolumeAndReset(11); EXPECT_CALL(*agc_, GetRmsErrorDb(_)).WillOnce(Return(false)); CallProcess(1); - EXPECT_EQ(12, volume_.GetMicVolume()); + EXPECT_EQ(12, manager_.stream_analog_level()); } TEST_F(AgcManagerDirectTest, ManualLevelChangeResultsInNoSetMicCall) { @@ -413,24 +403,24 @@ TEST_F(AgcManagerDirectTest, ManualLevelChangeResultsInNoSetMicCall) { // GetMicVolume returns a value outside of the quantization slack, indicating // a manual volume change. - ASSERT_NE(volume_.GetMicVolume(), 154); - volume_.SetMicVolume(154); + ASSERT_NE(manager_.stream_analog_level(), 154); + manager_.set_stream_analog_level(154); CallProcess(1); - EXPECT_EQ(154, volume_.GetMicVolume()); + EXPECT_EQ(154, manager_.stream_analog_level()); // Do the same thing, except downwards now. EXPECT_CALL(*agc_, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(-1), Return(true))); - volume_.SetMicVolume(100); + manager_.set_stream_analog_level(100); EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1)); CallProcess(1); - EXPECT_EQ(100, volume_.GetMicVolume()); + EXPECT_EQ(100, manager_.stream_analog_level()); // And finally verify the AGC continues working without a manual change. EXPECT_CALL(*agc_, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(-1), Return(true))); CallProcess(1); - EXPECT_EQ(99, volume_.GetMicVolume()); + EXPECT_EQ(99, manager_.stream_analog_level()); } TEST_F(AgcManagerDirectTest, RecoveryAfterManualLevelChangeFromMax) { @@ -441,25 +431,25 @@ TEST_F(AgcManagerDirectTest, RecoveryAfterManualLevelChangeFromMax) { EXPECT_CALL(*agc_, GetRmsErrorDb(_)) .WillRepeatedly(DoAll(SetArgPointee<0>(30), Return(true))); CallProcess(1); - EXPECT_EQ(183, volume_.GetMicVolume()); + EXPECT_EQ(183, manager_.stream_analog_level()); CallProcess(1); - EXPECT_EQ(243, volume_.GetMicVolume()); + EXPECT_EQ(243, manager_.stream_analog_level()); CallProcess(1); - EXPECT_EQ(255, volume_.GetMicVolume()); + EXPECT_EQ(255, manager_.stream_analog_level()); // Manual change does not result in SetMicVolume call. EXPECT_CALL(*agc_, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(-1), Return(true))); - volume_.SetMicVolume(50); + manager_.set_stream_analog_level(50); EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1)); CallProcess(1); - EXPECT_EQ(50, volume_.GetMicVolume()); + EXPECT_EQ(50, manager_.stream_analog_level()); // Continues working as usual afterwards. EXPECT_CALL(*agc_, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(20), Return(true))); CallProcess(1); - EXPECT_EQ(69, volume_.GetMicVolume()); + EXPECT_EQ(69, manager_.stream_analog_level()); } TEST_F(AgcManagerDirectTest, RecoveryAfterManualLevelChangeBelowMin) { @@ -469,40 +459,40 @@ TEST_F(AgcManagerDirectTest, RecoveryAfterManualLevelChangeBelowMin) { EXPECT_CALL(*agc_, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(-1), Return(true))); // Don't set to zero, which will cause AGC to take no action. - volume_.SetMicVolume(1); + manager_.set_stream_analog_level(1); EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1)); CallProcess(1); - EXPECT_EQ(1, volume_.GetMicVolume()); + EXPECT_EQ(1, manager_.stream_analog_level()); // Continues working as usual afterwards. EXPECT_CALL(*agc_, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(11), Return(true))); CallProcess(1); - EXPECT_EQ(2, volume_.GetMicVolume()); + EXPECT_EQ(2, manager_.stream_analog_level()); EXPECT_CALL(*agc_, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(30), Return(true))); CallProcess(1); - EXPECT_EQ(11, volume_.GetMicVolume()); + EXPECT_EQ(11, manager_.stream_analog_level()); EXPECT_CALL(*agc_, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(20), Return(true))); CallProcess(1); - EXPECT_EQ(18, volume_.GetMicVolume()); + EXPECT_EQ(18, manager_.stream_analog_level()); } TEST_F(AgcManagerDirectTest, NoClippingHasNoImpact) { FirstProcess(); CallPreProc(100, 0); - EXPECT_EQ(128, volume_.GetMicVolume()); + EXPECT_EQ(128, manager_.stream_analog_level()); } TEST_F(AgcManagerDirectTest, ClippingUnderThresholdHasNoImpact) { FirstProcess(); CallPreProc(1, 0.099); - EXPECT_EQ(128, volume_.GetMicVolume()); + EXPECT_EQ(128, manager_.stream_analog_level()); } TEST_F(AgcManagerDirectTest, ClippingLowersVolume) { @@ -510,7 +500,7 @@ TEST_F(AgcManagerDirectTest, ClippingLowersVolume) { EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1)); CallPreProc(1, 0.2); - EXPECT_EQ(240, volume_.GetMicVolume()); + EXPECT_EQ(240, manager_.stream_analog_level()); } TEST_F(AgcManagerDirectTest, WaitingPeriodBetweenClippingChecks) { @@ -518,15 +508,15 @@ TEST_F(AgcManagerDirectTest, WaitingPeriodBetweenClippingChecks) { EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1)); CallPreProc(1, kAboveClippedThreshold); - EXPECT_EQ(240, volume_.GetMicVolume()); + EXPECT_EQ(240, manager_.stream_analog_level()); EXPECT_CALL(*agc_, Reset()).Times(0); CallPreProc(300, kAboveClippedThreshold); - EXPECT_EQ(240, volume_.GetMicVolume()); + EXPECT_EQ(240, manager_.stream_analog_level()); EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1)); CallPreProc(1, kAboveClippedThreshold); - EXPECT_EQ(225, volume_.GetMicVolume()); + EXPECT_EQ(225, manager_.stream_analog_level()); } TEST_F(AgcManagerDirectTest, ClippingLoweringIsLimited) { @@ -534,11 +524,11 @@ TEST_F(AgcManagerDirectTest, ClippingLoweringIsLimited) { EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1)); CallPreProc(1, kAboveClippedThreshold); - EXPECT_EQ(kClippedMin, volume_.GetMicVolume()); + EXPECT_EQ(kClippedMin, manager_.stream_analog_level()); EXPECT_CALL(*agc_, Reset()).Times(0); CallPreProc(1000, kAboveClippedThreshold); - EXPECT_EQ(kClippedMin, volume_.GetMicVolume()); + EXPECT_EQ(kClippedMin, manager_.stream_analog_level()); } TEST_F(AgcManagerDirectTest, ClippingMaxIsRespectedWhenEqualToLevel) { @@ -546,12 +536,12 @@ TEST_F(AgcManagerDirectTest, ClippingMaxIsRespectedWhenEqualToLevel) { EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1)); CallPreProc(1, kAboveClippedThreshold); - EXPECT_EQ(240, volume_.GetMicVolume()); + EXPECT_EQ(240, manager_.stream_analog_level()); EXPECT_CALL(*agc_, GetRmsErrorDb(_)) .WillRepeatedly(DoAll(SetArgPointee<0>(30), Return(true))); CallProcess(10); - EXPECT_EQ(240, volume_.GetMicVolume()); + EXPECT_EQ(240, manager_.stream_analog_level()); } TEST_F(AgcManagerDirectTest, ClippingMaxIsRespectedWhenHigherThanLevel) { @@ -559,14 +549,14 @@ TEST_F(AgcManagerDirectTest, ClippingMaxIsRespectedWhenHigherThanLevel) { EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1)); CallPreProc(1, kAboveClippedThreshold); - EXPECT_EQ(185, volume_.GetMicVolume()); + EXPECT_EQ(185, manager_.stream_analog_level()); EXPECT_CALL(*agc_, GetRmsErrorDb(_)) .WillRepeatedly(DoAll(SetArgPointee<0>(40), Return(true))); CallProcess(1); - EXPECT_EQ(240, volume_.GetMicVolume()); + EXPECT_EQ(240, manager_.stream_analog_level()); CallProcess(10); - EXPECT_EQ(240, volume_.GetMicVolume()); + EXPECT_EQ(240, manager_.stream_analog_level()); } TEST_F(AgcManagerDirectTest, MaxCompressionIsIncreasedAfterClipping) { @@ -574,7 +564,7 @@ TEST_F(AgcManagerDirectTest, MaxCompressionIsIncreasedAfterClipping) { EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1)); CallPreProc(1, kAboveClippedThreshold); - EXPECT_EQ(195, volume_.GetMicVolume()); + EXPECT_EQ(195, manager_.stream_analog_level()); EXPECT_CALL(*agc_, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(11), Return(true))) @@ -601,12 +591,12 @@ TEST_F(AgcManagerDirectTest, MaxCompressionIsIncreasedAfterClipping) { CallPreProc(300, kAboveClippedThreshold); EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1)); CallPreProc(1, kAboveClippedThreshold); - EXPECT_EQ(180, volume_.GetMicVolume()); + EXPECT_EQ(180, manager_.stream_analog_level()); CallPreProc(300, kAboveClippedThreshold); EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1)); CallPreProc(1, kAboveClippedThreshold); - EXPECT_EQ(kClippedMin, volume_.GetMicVolume()); + EXPECT_EQ(kClippedMin, manager_.stream_analog_level()); // Current level is now at the minimum, but the maximum allowed level still // has more to decrease. @@ -643,41 +633,41 @@ TEST_F(AgcManagerDirectTest, UserCanRaiseVolumeAfterClipping) { EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1)); CallPreProc(1, kAboveClippedThreshold); - EXPECT_EQ(210, volume_.GetMicVolume()); + EXPECT_EQ(210, manager_.stream_analog_level()); // High enough error to trigger a volume check. EXPECT_CALL(*agc_, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(14), Return(true))); // User changed the volume. - volume_.SetMicVolume(250); + manager_.set_stream_analog_level(250); EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1)); CallProcess(1); - EXPECT_EQ(250, volume_.GetMicVolume()); + EXPECT_EQ(250, manager_.stream_analog_level()); // Move down... EXPECT_CALL(*agc_, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(-10), Return(true))); CallProcess(1); - EXPECT_EQ(210, volume_.GetMicVolume()); + EXPECT_EQ(210, manager_.stream_analog_level()); // And back up to the new max established by the user. EXPECT_CALL(*agc_, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(40), Return(true))); CallProcess(1); - EXPECT_EQ(250, volume_.GetMicVolume()); + EXPECT_EQ(250, manager_.stream_analog_level()); // Will not move above new maximum. EXPECT_CALL(*agc_, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(30), Return(true))); CallProcess(1); - EXPECT_EQ(250, volume_.GetMicVolume()); + EXPECT_EQ(250, manager_.stream_analog_level()); } TEST_F(AgcManagerDirectTest, ClippingDoesNotPullLowVolumeBackUp) { SetVolumeAndProcess(80); EXPECT_CALL(*agc_, Reset()).Times(0); - int initial_volume = volume_.GetMicVolume(); + int initial_volume = manager_.stream_analog_level(); CallPreProc(1, kAboveClippedThreshold); - EXPECT_EQ(initial_volume, volume_.GetMicVolume()); + EXPECT_EQ(initial_volume, manager_.stream_analog_level()); } TEST_F(AgcManagerDirectTest, TakesNoActionOnZeroMicVolume) { @@ -685,17 +675,15 @@ TEST_F(AgcManagerDirectTest, TakesNoActionOnZeroMicVolume) { EXPECT_CALL(*agc_, GetRmsErrorDb(_)) .WillRepeatedly(DoAll(SetArgPointee<0>(30), Return(true))); - volume_.SetMicVolume(0); + manager_.set_stream_analog_level(0); CallProcess(10); - EXPECT_EQ(0, volume_.GetMicVolume()); + EXPECT_EQ(0, manager_.stream_analog_level()); } TEST(AgcManagerDirectStandaloneTest, DisableDigitalDisablesDigital) { auto agc = std::unique_ptr(new ::testing::NiceMock()); MockGainControl gctrl; - TestVolumeCallbacks volume; - - AgcManagerDirect manager(&gctrl, &volume, kInitialVolume, kClippedMin, + AgcManagerDirect manager(kInitialVolume, kClippedMin, /* use agc2 level estimation */ false, /* disable digital adaptive */ true); @@ -705,18 +693,19 @@ TEST(AgcManagerDirectStandaloneTest, DisableDigitalDisablesDigital) { EXPECT_CALL(gctrl, enable_limiter(false)); manager.Initialize(); + manager.ConfigureGainControl(&gctrl); } TEST(AgcManagerDirectStandaloneTest, AgcMinMicLevelExperiment) { - auto agc_man = std::unique_ptr(new AgcManagerDirect( - nullptr, nullptr, kInitialVolume, kClippedMin, true, true)); + auto agc_man = std::unique_ptr( + new AgcManagerDirect(kInitialVolume, kClippedMin, true, true)); EXPECT_EQ(agc_man->min_mic_level(), kMinMicLevel); EXPECT_EQ(agc_man->startup_min_level(), kInitialVolume); { test::ScopedFieldTrials field_trial( "WebRTC-Audio-AgcMinMicLevelExperiment/Disabled/"); - agc_man.reset(new AgcManagerDirect(nullptr, nullptr, kInitialVolume, - kClippedMin, true, true)); + agc_man.reset( + new AgcManagerDirect(kInitialVolume, kClippedMin, true, true)); EXPECT_EQ(agc_man->min_mic_level(), kMinMicLevel); EXPECT_EQ(agc_man->startup_min_level(), kInitialVolume); } @@ -724,16 +713,16 @@ TEST(AgcManagerDirectStandaloneTest, AgcMinMicLevelExperiment) { // Valid range of field-trial parameter is [0,255]. test::ScopedFieldTrials field_trial( "WebRTC-Audio-AgcMinMicLevelExperiment/Enabled-256/"); - agc_man.reset(new AgcManagerDirect(nullptr, nullptr, kInitialVolume, - kClippedMin, true, true)); + agc_man.reset( + new AgcManagerDirect(kInitialVolume, kClippedMin, true, true)); EXPECT_EQ(agc_man->min_mic_level(), kMinMicLevel); EXPECT_EQ(agc_man->startup_min_level(), kInitialVolume); } { test::ScopedFieldTrials field_trial( "WebRTC-Audio-AgcMinMicLevelExperiment/Enabled--1/"); - agc_man.reset(new AgcManagerDirect(nullptr, nullptr, kInitialVolume, - kClippedMin, true, true)); + agc_man.reset( + new AgcManagerDirect(kInitialVolume, kClippedMin, true, true)); EXPECT_EQ(agc_man->min_mic_level(), kMinMicLevel); EXPECT_EQ(agc_man->startup_min_level(), kInitialVolume); } @@ -743,8 +732,8 @@ TEST(AgcManagerDirectStandaloneTest, AgcMinMicLevelExperiment) { // be changed. test::ScopedFieldTrials field_trial( "WebRTC-Audio-AgcMinMicLevelExperiment/Enabled-50/"); - agc_man.reset(new AgcManagerDirect(nullptr, nullptr, kInitialVolume, - kClippedMin, true, true)); + agc_man.reset( + new AgcManagerDirect(kInitialVolume, kClippedMin, true, true)); EXPECT_EQ(agc_man->min_mic_level(), 50); EXPECT_EQ(agc_man->startup_min_level(), kInitialVolume); } @@ -754,8 +743,7 @@ TEST(AgcManagerDirectStandaloneTest, AgcMinMicLevelExperiment) { // level set by the experiment. test::ScopedFieldTrials field_trial( "WebRTC-Audio-AgcMinMicLevelExperiment/Enabled-50/"); - agc_man.reset( - new AgcManagerDirect(nullptr, nullptr, 30, kClippedMin, true, true)); + agc_man.reset(new AgcManagerDirect(30, kClippedMin, true, true)); EXPECT_EQ(agc_man->min_mic_level(), 50); EXPECT_EQ(agc_man->startup_min_level(), 50); } diff --git a/modules/audio_processing/audio_processing_impl.cc b/modules/audio_processing/audio_processing_impl.cc index fad02a038f..bfa2e0dc9d 100644 --- a/modules/audio_processing/audio_processing_impl.cc +++ b/modules/audio_processing/audio_processing_impl.cc @@ -323,18 +323,20 @@ AudioProcessingImpl::AudioProcessingImpl( submodules_(std::move(capture_post_processor), std::move(render_pre_processor), std::move(echo_detector), - std::move(capture_analyzer)), - constants_(config.Get().startup_min_volume, - config.Get().clipped_level_min, + std::move(capture_analyzer), + config.Get().startup_min_volume, + config.Get().clipped_level_min, #if defined(WEBRTC_ANDROID) || defined(WEBRTC_IOS) - /* enabled= */ false, - /* enabled_agc2_level_estimator= */ false, - /* digital_adaptive_disabled= */ false, + /* enabled= */ false, + /* enabled_agc2_level_estimator= */ false, + /* digital_adaptive_disabled= */ false #else - config.Get().enabled, - config.Get().enabled_agc2_level_estimator, - config.Get().digital_adaptive_disabled, + config.Get().enabled, + config.Get().enabled_agc2_level_estimator, + config.Get().digital_adaptive_disabled #endif + ), + constants_(config.Get().clipped_level_min, !field_trial::IsEnabled( "WebRTC-ApmExperimentalMultiChannelRenderKillSwitch"), !field_trial::IsEnabled( @@ -359,8 +361,6 @@ AudioProcessingImpl::AudioProcessingImpl( static_cast(echo_control_factory_); submodules_.gain_control.reset(new GainControlImpl()); - submodules_.gain_control_for_experimental_agc.reset( - new GainControlForExperimentalAgc(submodules_.gain_control.get())); // If no echo detector is injected, use the ResidualEchoDetector. if (!submodules_.echo_detector) { @@ -375,13 +375,7 @@ AudioProcessingImpl::AudioProcessingImpl( SetExtraOptions(config); } -AudioProcessingImpl::~AudioProcessingImpl() { - // Depends on gain_control_ and - // submodules_.gain_control_for_experimental_agc. - submodules_.agc_manager.reset(); - // Depends on gain_control_. - submodules_.gain_control_for_experimental_agc.reset(); -} +AudioProcessingImpl::~AudioProcessingImpl() = default; int AudioProcessingImpl::Initialize() { // Run in a single-threaded manner during initialization. @@ -484,18 +478,11 @@ int AudioProcessingImpl::InitializeLocked() { submodules_.gain_control->Initialize(num_proc_channels(), proc_sample_rate_hz()); - if (constants_.use_experimental_agc) { - if (!submodules_.agc_manager.get()) { - submodules_.agc_manager.reset(new AgcManagerDirect( - submodules_.gain_control.get(), - submodules_.gain_control_for_experimental_agc.get(), - constants_.agc_startup_min_volume, constants_.agc_clipped_level_min, - constants_.use_experimental_agc_agc2_level_estimation, - constants_.use_experimental_agc_agc2_digital_adaptive)); - } + if (submodules_.agc_manager) { submodules_.agc_manager->Initialize(); + submodules_.agc_manager->ConfigureGainControl( + submodules_.gain_control.get()); submodules_.agc_manager->SetCaptureMuted(capture_.output_will_be_muted); - submodules_.gain_control_for_experimental_agc->Initialize(); } InitializeTransient(); InitializeHighPassFilter(); @@ -695,34 +682,25 @@ void AudioProcessingImpl::ApplyConfig(const AudioProcessing::Config& config) { void AudioProcessingImpl::ApplyAgc1Config( const Config::GainController1& config) { - GainControl* agc = agc1(); - int error = agc->Enable(config.enabled); + int error = submodules_.gain_control->Enable(config.enabled); RTC_DCHECK_EQ(kNoError, error); - error = agc->set_mode(Agc1ConfigModeToInterfaceMode(config.mode)); - RTC_DCHECK_EQ(kNoError, error); - error = agc->set_target_level_dbfs(config.target_level_dbfs); - RTC_DCHECK_EQ(kNoError, error); - error = agc->set_compression_gain_db(config.compression_gain_db); - RTC_DCHECK_EQ(kNoError, error); - error = agc->enable_limiter(config.enable_limiter); - RTC_DCHECK_EQ(kNoError, error); - error = agc->set_analog_level_limits(config.analog_level_minimum, - config.analog_level_maximum); - RTC_DCHECK_EQ(kNoError, error); -} -GainControl* AudioProcessingImpl::agc1() { - if (constants_.use_experimental_agc) { - return submodules_.gain_control_for_experimental_agc.get(); + if (!submodules_.agc_manager) { + error = submodules_.gain_control->set_mode( + Agc1ConfigModeToInterfaceMode(config.mode)); + RTC_DCHECK_EQ(kNoError, error); + error = submodules_.gain_control->set_target_level_dbfs( + config.target_level_dbfs); + RTC_DCHECK_EQ(kNoError, error); + error = submodules_.gain_control->set_compression_gain_db( + config.compression_gain_db); + RTC_DCHECK_EQ(kNoError, error); + error = submodules_.gain_control->enable_limiter(config.enable_limiter); + RTC_DCHECK_EQ(kNoError, error); + error = submodules_.gain_control->set_analog_level_limits( + config.analog_level_minimum, config.analog_level_maximum); + RTC_DCHECK_EQ(kNoError, error); } - return submodules_.gain_control.get(); -} - -const GainControl* AudioProcessingImpl::agc1() const { - if (constants_.use_experimental_agc) { - return submodules_.gain_control_for_experimental_agc.get(); - } - return submodules_.gain_control.get(); } void AudioProcessingImpl::SetExtraOptions(const webrtc::Config& config) { @@ -926,12 +904,15 @@ void AudioProcessingImpl::HandleCaptureRuntimeSettings() { // TODO(bugs.chromium.org/9138): Log setting handling by Aec Dump. break; case RuntimeSetting::Type::kCaptureCompressionGain: { - float value; - setting.GetFloat(&value); - int int_value = static_cast(value + .5f); - config_.gain_controller1.compression_gain_db = int_value; - int error = agc1()->set_compression_gain_db(int_value); - RTC_DCHECK_EQ(kNoError, error); + if (!submodules_.agc_manager) { + float value; + setting.GetFloat(&value); + int int_value = static_cast(value + .5f); + config_.gain_controller1.compression_gain_db = int_value; + int error = + submodules_.gain_control->set_compression_gain_db(int_value); + RTC_DCHECK_EQ(kNoError, error); + } break; } case RuntimeSetting::Type::kCaptureFixedPostGain: { @@ -1023,7 +1004,7 @@ void AudioProcessingImpl::QueueBandedRenderAudio(AudioBuffer* audio) { } } - if (!constants_.use_experimental_agc) { + if (!submodules_.agc_manager) { GainControlImpl::PackRenderAudioBuffer(audio, &agc_render_queue_buffer_); // Insert the samples into the queue. if (!agc_render_signal_queue_->Insert(&agc_render_queue_buffer_)) { @@ -1255,7 +1236,7 @@ int AudioProcessingImpl::ProcessCaptureStreamLocked() { if (submodules_.echo_controller) { // Detect and flag any change in the analog gain. - int analog_mic_level = agc1()->stream_analog_level(); + int analog_mic_level = recommended_stream_analog_level(); capture_.echo_path_gain_change = capture_.prev_analog_mic_level != analog_mic_level && capture_.prev_analog_mic_level != -1; @@ -1281,8 +1262,7 @@ int AudioProcessingImpl::ProcessCaptureStreamLocked() { submodules_.echo_controller->AnalyzeCapture(capture_buffer); } - if (constants_.use_experimental_agc && - submodules_.gain_control->is_enabled()) { + if (submodules_.agc_manager && submodules_.gain_control->is_enabled()) { submodules_.agc_manager->AnalyzePreProcess( capture_buffer->channels_const(), capture_buffer->num_channels(), capture_nonlocked_.capture_processing_format.num_frames()); @@ -1370,11 +1350,11 @@ int AudioProcessingImpl::ProcessCaptureStreamLocked() { capture_.stats.voice_detected = absl::nullopt; } - if (constants_.use_experimental_agc && - submodules_.gain_control->is_enabled()) { + if (submodules_.agc_manager && submodules_.gain_control->is_enabled()) { submodules_.agc_manager->Process( capture_buffer->split_bands_const_f(0)[kBand0To8kHz], - capture_buffer->num_frames_per_band(), capture_nonlocked_.split_rate); + capture_buffer->num_frames_per_band(), capture_nonlocked_.split_rate, + submodules_.gain_control.get()); } // TODO(peah): Add reporting from AEC3 whether there is echo. RETURN_ON_ERR(submodules_.gain_control->ProcessCaptureAudio( @@ -1428,7 +1408,7 @@ int AudioProcessingImpl::ProcessCaptureStreamLocked() { if (config_.gain_controller2.enabled) { submodules_.gain_controller2->NotifyAnalogLevel( - agc1()->stream_analog_level()); + recommended_stream_analog_level()); submodules_.gain_controller2->Process(capture_buffer); } @@ -1455,6 +1435,12 @@ int AudioProcessingImpl::ProcessCaptureStreamLocked() { levels.peak, 1, RmsLevel::kMinLevelDb, 64); } + if (submodules_.agc_manager) { + int level = recommended_stream_analog_level(); + data_dumper_->DumpRaw("experimental_gain_control_stream_analog_level", 1, + &level); + } + capture_.was_stream_delay_set = false; return kNoError; } @@ -1678,13 +1664,23 @@ int AudioProcessingImpl::delay_offset_ms() const { void AudioProcessingImpl::set_stream_analog_level(int level) { rtc::CritScope cs_capture(&crit_capture_); - int error = agc1()->set_stream_analog_level(level); - RTC_DCHECK_EQ(kNoError, error); + + if (submodules_.agc_manager) { + submodules_.agc_manager->set_stream_analog_level(level); + data_dumper_->DumpRaw("experimental_gain_control_set_stream_analog_level", + 1, &level); + } else { + int error = submodules_.gain_control->set_stream_analog_level(level); + RTC_DCHECK_EQ(kNoError, error); + } } int AudioProcessingImpl::recommended_stream_analog_level() const { rtc::CritScope cs_capture(&crit_capture_); - return agc1()->stream_analog_level(); + if (submodules_.agc_manager) { + return submodules_.agc_manager->stream_analog_level(); + } + return submodules_.gain_control->stream_analog_level(); } void AudioProcessingImpl::AttachAecDump(std::unique_ptr aec_dump) { @@ -2050,7 +2046,7 @@ void AudioProcessingImpl::WriteAecDumpConfigMessage(bool forced) { apm_config.agc_mode = static_cast(submodules_.gain_control->mode()); apm_config.agc_limiter_enabled = submodules_.gain_control->is_limiter_enabled(); - apm_config.noise_robust_agc_enabled = constants_.use_experimental_agc; + apm_config.noise_robust_agc_enabled = !!submodules_.agc_manager; apm_config.hpf_enabled = config_.high_pass_filter.enabled; @@ -2120,7 +2116,7 @@ void AudioProcessingImpl::RecordAudioProcessingState() { submodules_.echo_cancellation ? submodules_.echo_cancellation->stream_drift_samples() : 0; - audio_proc_state.level = agc1()->stream_analog_level(); + audio_proc_state.level = recommended_stream_analog_level(); audio_proc_state.keypress = capture_.key_pressed; aec_dump_->AddAudioProcessingState(audio_proc_state); } diff --git a/modules/audio_processing/audio_processing_impl.h b/modules/audio_processing/audio_processing_impl.h index f7320ac469..a5717d363f 100644 --- a/modules/audio_processing/audio_processing_impl.h +++ b/modules/audio_processing/audio_processing_impl.h @@ -22,7 +22,6 @@ #include "modules/audio_processing/audio_buffer.h" #include "modules/audio_processing/echo_cancellation_impl.h" #include "modules/audio_processing/echo_control_mobile_impl.h" -#include "modules/audio_processing/gain_control_for_experimental_agc.h" #include "modules/audio_processing/gain_control_impl.h" #include "modules/audio_processing/gain_controller2.h" #include "modules/audio_processing/high_pass_filter.h" @@ -254,11 +253,6 @@ class AudioProcessingImpl : public AudioProcessing { void ApplyAgc1Config(const Config::GainController1& agc_config) RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_capture_); - // Returns a direct pointer to the AGC1 submodule: either a GainControlImpl - // or GainControlForExperimentalAgc instance. - GainControl* agc1(); - const GainControl* agc1() const; - void EmptyQueuedRenderAudio(); void AllocateRenderQueue() RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_render_, crit_capture_); @@ -331,16 +325,26 @@ class AudioProcessingImpl : public AudioProcessing { Submodules(std::unique_ptr capture_post_processor, std::unique_ptr render_pre_processor, rtc::scoped_refptr echo_detector, - std::unique_ptr capture_analyzer) + std::unique_ptr capture_analyzer, + int agc_startup_min_volume, + int agc_clipped_level_min, + bool use_experimental_agc, + bool use_experimental_agc_agc2_level_estimation, + bool use_experimental_agc_agc2_digital_adaptive) : echo_detector(std::move(echo_detector)), capture_post_processor(std::move(capture_post_processor)), render_pre_processor(std::move(render_pre_processor)), - capture_analyzer(std::move(capture_analyzer)) {} + capture_analyzer(std::move(capture_analyzer)) { + if (use_experimental_agc) { + agc_manager = std::make_unique( + agc_startup_min_volume, agc_clipped_level_min, + use_experimental_agc_agc2_level_estimation, + use_experimental_agc_agc2_digital_adaptive); + } + } // Accessed internally from capture or during initialization. std::unique_ptr agc_manager; std::unique_ptr gain_control; - std::unique_ptr - gain_control_for_experimental_agc; std::unique_ptr gain_controller2; std::unique_ptr high_pass_filter; rtc::scoped_refptr echo_detector; @@ -377,29 +381,15 @@ class AudioProcessingImpl : public AudioProcessing { // APM constants. const struct ApmConstants { - ApmConstants(int agc_startup_min_volume, - int agc_clipped_level_min, - bool use_experimental_agc, - bool use_experimental_agc_agc2_level_estimation, - bool use_experimental_agc_agc2_digital_adaptive, + ApmConstants(int agc_clipped_level_min, bool experimental_multi_channel_render_support, bool experimental_multi_channel_capture_support) - : agc_startup_min_volume(agc_startup_min_volume), - agc_clipped_level_min(agc_clipped_level_min), - use_experimental_agc(use_experimental_agc), - use_experimental_agc_agc2_level_estimation( - use_experimental_agc_agc2_level_estimation), - use_experimental_agc_agc2_digital_adaptive( - use_experimental_agc_agc2_digital_adaptive), + : agc_clipped_level_min(agc_clipped_level_min), experimental_multi_channel_render_support( experimental_multi_channel_render_support), experimental_multi_channel_capture_support( experimental_multi_channel_capture_support) {} - int agc_startup_min_volume; int agc_clipped_level_min; - bool use_experimental_agc; - bool use_experimental_agc_agc2_level_estimation; - bool use_experimental_agc_agc2_digital_adaptive; bool experimental_multi_channel_render_support; bool experimental_multi_channel_capture_support; } constants_; diff --git a/modules/audio_processing/gain_control_for_experimental_agc.cc b/modules/audio_processing/gain_control_for_experimental_agc.cc deleted file mode 100644 index 9e4d4f52d0..0000000000 --- a/modules/audio_processing/gain_control_for_experimental_agc.cc +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "modules/audio_processing/gain_control_for_experimental_agc.h" - -#include "modules/audio_processing/include/audio_processing.h" -#include "modules/audio_processing/logging/apm_data_dumper.h" -#include "rtc_base/atomic_ops.h" -#include "rtc_base/critical_section.h" - -namespace webrtc { - -int GainControlForExperimentalAgc::instance_counter_ = 0; - -GainControlForExperimentalAgc::GainControlForExperimentalAgc( - GainControl* gain_control) - : data_dumper_( - new ApmDataDumper(rtc::AtomicOps::Increment(&instance_counter_))), - real_gain_control_(gain_control), - volume_(0) {} - -GainControlForExperimentalAgc::~GainControlForExperimentalAgc() = default; - -int GainControlForExperimentalAgc::Enable(bool enable) { - return real_gain_control_->Enable(enable); -} - -bool GainControlForExperimentalAgc::is_enabled() const { - return real_gain_control_->is_enabled(); -} - -int GainControlForExperimentalAgc::set_stream_analog_level(int level) { - data_dumper_->DumpRaw("experimental_gain_control_set_stream_analog_level", 1, - &level); - do_log_level_ = true; - volume_ = level; - return AudioProcessing::kNoError; -} - -int GainControlForExperimentalAgc::stream_analog_level() const { - if (do_log_level_) { - data_dumper_->DumpRaw("experimental_gain_control_stream_analog_level", 1, - &volume_); - do_log_level_ = false; - } - return volume_; -} - -int GainControlForExperimentalAgc::set_mode(Mode mode) { - return AudioProcessing::kNoError; -} - -GainControl::Mode GainControlForExperimentalAgc::mode() const { - return GainControl::kAdaptiveAnalog; -} - -int GainControlForExperimentalAgc::set_target_level_dbfs(int level) { - return AudioProcessing::kNoError; -} - -int GainControlForExperimentalAgc::target_level_dbfs() const { - return real_gain_control_->target_level_dbfs(); -} - -int GainControlForExperimentalAgc::set_compression_gain_db(int gain) { - return AudioProcessing::kNoError; -} - -int GainControlForExperimentalAgc::compression_gain_db() const { - return real_gain_control_->compression_gain_db(); -} - -int GainControlForExperimentalAgc::enable_limiter(bool enable) { - return AudioProcessing::kNoError; -} - -bool GainControlForExperimentalAgc::is_limiter_enabled() const { - return real_gain_control_->is_limiter_enabled(); -} - -int GainControlForExperimentalAgc::set_analog_level_limits(int minimum, - int maximum) { - return AudioProcessing::kNoError; -} - -int GainControlForExperimentalAgc::analog_level_minimum() const { - return real_gain_control_->analog_level_minimum(); -} - -int GainControlForExperimentalAgc::analog_level_maximum() const { - return real_gain_control_->analog_level_maximum(); -} - -bool GainControlForExperimentalAgc::stream_is_saturated() const { - return real_gain_control_->stream_is_saturated(); -} - -void GainControlForExperimentalAgc::SetMicVolume(int volume) { - volume_ = volume; -} - -int GainControlForExperimentalAgc::GetMicVolume() { - return volume_; -} - -void GainControlForExperimentalAgc::Initialize() { - data_dumper_->InitiateNewSetOfRecordings(); -} - -} // namespace webrtc diff --git a/modules/audio_processing/gain_control_for_experimental_agc.h b/modules/audio_processing/gain_control_for_experimental_agc.h deleted file mode 100644 index a8bc808390..0000000000 --- a/modules/audio_processing/gain_control_for_experimental_agc.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef MODULES_AUDIO_PROCESSING_GAIN_CONTROL_FOR_EXPERIMENTAL_AGC_H_ -#define MODULES_AUDIO_PROCESSING_GAIN_CONTROL_FOR_EXPERIMENTAL_AGC_H_ - -#include "modules/audio_processing/agc/agc_manager_direct.h" -#include "modules/audio_processing/agc/gain_control.h" -#include "rtc_base/thread_checker.h" - -namespace webrtc { - -class ApmDataDumper; - -// This class has two main purposes: -// -// 1) It is returned instead of the real GainControl after the new AGC has been -// enabled in order to prevent an outside user from overriding compression -// settings. It doesn't do anything in its implementation, except for -// delegating the const methods and Enable calls to the real GainControl, so -// AGC can still be disabled. -// -// 2) It is injected into AgcManagerDirect and implements volume callbacks for -// getting and setting the volume level. It just caches this value to be used -// in VoiceEngine later. -class GainControlForExperimentalAgc : public GainControl, - public VolumeCallbacks { - public: - explicit GainControlForExperimentalAgc(GainControl* gain_control); - GainControlForExperimentalAgc(const GainControlForExperimentalAgc&) = delete; - GainControlForExperimentalAgc& operator=( - const GainControlForExperimentalAgc&) = delete; - - ~GainControlForExperimentalAgc() override; - - // GainControl implementation. - int Enable(bool enable) override; - bool is_enabled() const override; - int set_stream_analog_level(int level) override; - int stream_analog_level() const override; - int set_mode(Mode mode) override; - Mode mode() const override; - int set_target_level_dbfs(int level) override; - int target_level_dbfs() const override; - int set_compression_gain_db(int gain) override; - int compression_gain_db() const override; - int enable_limiter(bool enable) override; - bool is_limiter_enabled() const override; - int set_analog_level_limits(int minimum, int maximum) override; - int analog_level_minimum() const override; - int analog_level_maximum() const override; - bool stream_is_saturated() const override; - - // VolumeCallbacks implementation. - void SetMicVolume(int volume) override; - int GetMicVolume() override; - - void Initialize(); - - private: - std::unique_ptr data_dumper_; - GainControl* real_gain_control_; - int volume_; - mutable bool do_log_level_ = true; - static int instance_counter_; -}; - -} // namespace webrtc - -#endif // MODULES_AUDIO_PROCESSING_GAIN_CONTROL_FOR_EXPERIMENTAL_AGC_H_ diff --git a/modules/audio_processing/gain_control_impl.h b/modules/audio_processing/gain_control_impl.h index 4ec194140a..7976613876 100644 --- a/modules/audio_processing/gain_control_impl.h +++ b/modules/audio_processing/gain_control_impl.h @@ -49,21 +49,20 @@ class GainControlImpl : public GainControl { int stream_analog_level() const override; bool is_limiter_enabled() const override; Mode mode() const override; - + int Enable(bool enable) override; + int set_mode(Mode mode) override; int compression_gain_db() const override; + int set_analog_level_limits(int minimum, int maximum) override; + int set_compression_gain_db(int gain) override; + int set_target_level_dbfs(int level) override; + int enable_limiter(bool enable) override; + int set_stream_analog_level(int level) override; private: class GainController; // GainControl implementation. - int Enable(bool enable) override; - int set_stream_analog_level(int level) override; - int set_mode(Mode mode) override; - int set_target_level_dbfs(int level) override; int target_level_dbfs() const override; - int set_compression_gain_db(int gain) override; - int enable_limiter(bool enable) override; - int set_analog_level_limits(int minimum, int maximum) override; int analog_level_minimum() const override; int analog_level_maximum() const override; bool stream_is_saturated() const override;