diff --git a/modules/audio_processing/agc/BUILD.gn b/modules/audio_processing/agc/BUILD.gn index 70190cf818..a0cbd7a988 100644 --- a/modules/audio_processing/agc/BUILD.gn +++ b/modules/audio_processing/agc/BUILD.gn @@ -178,6 +178,7 @@ if (rtc_include_tests) { "../../../rtc_base:checks", "../../../rtc_base:random", "../../../rtc_base:safe_conversions", + "../../../rtc_base:safe_minmax", "../../../rtc_base:stringutils", "../../../system_wrappers:metrics", "../../../test:field_trial", diff --git a/modules/audio_processing/agc/agc_manager_direct.cc b/modules/audio_processing/agc/agc_manager_direct.cc index 5e8fb325bd..912cf8f752 100644 --- a/modules/audio_processing/agc/agc_manager_direct.cc +++ b/modules/audio_processing/agc/agc_manager_direct.cc @@ -222,6 +222,7 @@ void MonoAgc::Process(rtc::ArrayView audio) { } void MonoAgc::HandleClipping(int clipped_level_step) { + RTC_DCHECK_GT(clipped_level_step, 0); // Always decrease the maximum level, even if the current level is below // threshold. SetMaxLevel(std::max(clipped_level_min_, max_level_ - clipped_level_step)); @@ -240,7 +241,7 @@ void MonoAgc::HandleClipping(int clipped_level_step) { } void MonoAgc::SetLevel(int new_level) { - int voe_level = stream_analog_level_; + int voe_level = recommended_input_volume_; if (voe_level == 0) { RTC_DLOG(LS_INFO) << "[agc] VolumeCallbacks returned level=0, taking no action."; @@ -279,7 +280,7 @@ void MonoAgc::SetLevel(int new_level) { return; } - stream_analog_level_ = new_level; + recommended_input_volume_ = new_level; RTC_DLOG(LS_INFO) << "[agc] voe_level=" << voe_level << ", level_=" << level_ << ", new_level=" << new_level; level_ = new_level; @@ -312,7 +313,7 @@ void MonoAgc::HandleCaptureOutputUsedChange(bool capture_output_used) { } int MonoAgc::CheckVolumeAndReset() { - int level = stream_analog_level_; + int level = recommended_input_volume_; // 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 @@ -333,7 +334,7 @@ int MonoAgc::CheckVolumeAndReset() { if (level < minLevel) { level = minLevel; RTC_DLOG(LS_INFO) << "[agc] Initial volume too low, raising to " << level; - stream_analog_level_ = level; + recommended_input_volume_ = level; } agc_->Reset(); level_ = level; @@ -456,7 +457,8 @@ AgcManagerDirect::AgcManagerDirect( AgcManagerDirect::AgcManagerDirect(int num_capture_channels, const AnalogAgcConfig& analog_config) - : min_mic_level_override_(GetMinMicLevelOverride()), + : analog_controller_enabled_(analog_config.enabled), + min_mic_level_override_(GetMinMicLevelOverride()), data_dumper_(new ApmDataDumper(instance_counter_.fetch_add(1) + 1)), use_min_channel_level_(!UseMaxAnalogChannelLevel()), num_capture_channels_(num_capture_channels), @@ -478,6 +480,8 @@ AgcManagerDirect::AgcManagerDirect(int num_capture_channels, clipping_predictor_log_counter_(0), clipping_rate_log_(0.0f), clipping_rate_log_counter_(0) { + RTC_LOG(LS_INFO) << "[agc] analog controller enabled: " + << (analog_controller_enabled_ ? "yes" : "no"); const int min_mic_level = min_mic_level_override_.value_or(kMinMicLevel); RTC_LOG(LS_INFO) << "[agc] Min mic level: " << min_mic_level << " (overridden: " @@ -589,7 +593,7 @@ void AgcManagerDirect::AnalyzePreProcess(const float* const* audio, if (!!clipping_predictor_) { for (int channel = 0; channel < num_capture_channels_; ++channel) { const auto step = clipping_predictor_->EstimateClippedLevelStep( - channel, stream_analog_level_, clipped_level_step_, + channel, recommended_input_volume_, clipped_level_step_, channel_agcs_[channel]->min_mic_level(), kMaxMicLevel); if (step.has_value()) { predicted_step = std::max(predicted_step, step.value()); @@ -685,6 +689,10 @@ float AgcManagerDirect::voice_probability() const { } void AgcManagerDirect::set_stream_analog_level(int level) { + if (!analog_controller_enabled_) { + recommended_input_volume_ = level; + } + for (size_t ch = 0; ch < channel_agcs_.size(); ++ch) { channel_agcs_[ch]->set_stream_analog_level(level); } @@ -693,29 +701,34 @@ void AgcManagerDirect::set_stream_analog_level(int level) { } void AgcManagerDirect::AggregateChannelLevels() { - stream_analog_level_ = channel_agcs_[0]->stream_analog_level(); + int new_recommended_input_volume = + channel_agcs_[0]->recommended_analog_level(); channel_controlling_gain_ = 0; if (use_min_channel_level_) { for (size_t ch = 1; ch < channel_agcs_.size(); ++ch) { - int level = channel_agcs_[ch]->stream_analog_level(); - if (level < stream_analog_level_) { - stream_analog_level_ = level; + int level = channel_agcs_[ch]->recommended_analog_level(); + if (level < new_recommended_input_volume) { + new_recommended_input_volume = level; channel_controlling_gain_ = static_cast(ch); } } } else { for (size_t ch = 1; ch < channel_agcs_.size(); ++ch) { - int level = channel_agcs_[ch]->stream_analog_level(); - if (level > stream_analog_level_) { - stream_analog_level_ = level; + int level = channel_agcs_[ch]->recommended_analog_level(); + if (level > new_recommended_input_volume) { + new_recommended_input_volume = level; channel_controlling_gain_ = static_cast(ch); } } } - if (min_mic_level_override_.has_value() && stream_analog_level_ > 0) { - stream_analog_level_ = - std::max(stream_analog_level_, *min_mic_level_override_); + if (min_mic_level_override_.has_value() && new_recommended_input_volume > 0) { + new_recommended_input_volume = + std::max(new_recommended_input_volume, *min_mic_level_override_); + } + + if (analog_controller_enabled_) { + recommended_input_volume_ = new_recommended_input_volume; } } diff --git a/modules/audio_processing/agc/agc_manager_direct.h b/modules/audio_processing/agc/agc_manager_direct.h index 6a3fb2a5b4..b70e5a7298 100644 --- a/modules/audio_processing/agc/agc_manager_direct.h +++ b/modules/audio_processing/agc/agc_manager_direct.h @@ -29,12 +29,14 @@ namespace webrtc { class MonoAgc; class GainControl; -// Adaptive Gain Controller (AGC) that combines an analog and digital gain -// controller. The digital controller determines and applies the digital -// compression gain. The analog controller recommends what input volume (a.k.a., -// analog level) to use, handles input volume changes and input clipping. In -// particular, it handles input volume changes triggered by the user (e.g., -// input volume set to zero by a HW mute button). This class is not thread-safe. +// Adaptive Gain Controller (AGC) that controls the input volume and a digital +// gain. The input volume controller recommends what volume to use, handles +// volume changes and clipping. In particular, it handles changes triggered by +// the user (e.g., volume set to zero by a HW mute button). The digital +// controller chooses and applies the digital compression gain. +// This class is not thread-safe. +// TODO(bugs.webrtc.org/7494): Use applied/recommended input volume naming +// convention. class AgcManagerDirect final { public: // Ctor. `num_capture_channels` specifies the number of channels for the audio @@ -56,39 +58,45 @@ class AgcManagerDirect final { // `gain_control` is also used to avoid the side-effects of running two AGCs. void SetupDigitalGainControl(GainControl& gain_control) const; + // Sets the applied input volume. + void set_stream_analog_level(int level); + + // TODO(bugs.webrtc.org/7494): Add argument for the applied input volume and + // remove `set_stream_analog_level()`. // Analyzes `audio` before `Process()` is called so that the analysis can be // performed before external digital processing operations take place (e.g., // echo cancellation). The analysis consists of input clipping detection and - // prediction (if enabled). + // prediction (if enabled). Must be called after `set_stream_analog_level()`. void AnalyzePreProcess(const AudioBuffer* audio); - // Processes `audio`. Chooses and applies a digital compression gain on each - // channel and chooses the new input volume to recommend. Undefined behavior - // if `AnalyzePreProcess()` is not called beforehand. + // Processes `audio`. Chooses a digital compression gain and the new input + // volume to recommend. Must be called after `AnalyzePreProcess()`. void Process(const AudioBuffer* audio); + // TODO(bugs.webrtc.org/7494): Return recommended input volume and remove + // `recommended_analog_level()`. + // Returns the recommended input volume. If the input volume contoller is + // disabled, returns the input volume set via the latest + // `set_stream_analog_level()` call. Must be called after + // `AnalyzePreProcess()` and `Process()`. + int recommended_analog_level() const { return recommended_input_volume_; } + // Call when the capture stream output has been flagged to be used/not-used. // If unused, the manager disregards all incoming audio. void HandleCaptureOutputUsedChange(bool capture_output_used); float voice_probability() const; - // Returns the recommended input volume. - int stream_analog_level() const { return stream_analog_level_; } - - // Sets the current input volume. - void set_stream_analog_level(int level); - int num_channels() const { return num_capture_channels_; } // If available, returns the latest digital compression gain that has been - // applied. + // chosen. absl::optional GetDigitalComressionGain(); // Returns true if clipping prediction is enabled. bool clipping_predictor_enabled() const { return !!clipping_predictor_; } - // Returns true if clipping prediction is used to adjust the analog gain. + // Returns true if clipping prediction is used to adjust the input volume. bool use_clipping_predictor_step() const { return use_clipping_predictor_step_; } @@ -129,6 +137,8 @@ class AgcManagerDirect final { void AggregateChannelLevels(); + const bool analog_controller_enabled_; + const absl::optional min_mic_level_override_; std::unique_ptr data_dumper_; static std::atomic instance_counter_; @@ -137,7 +147,17 @@ class AgcManagerDirect final { const bool disable_digital_adaptive_; int frames_since_clipped_; - int stream_analog_level_ = 0; + + // TODO(bugs.webrtc.org/7494): Create a separate member for the applied input + // volume. + // TODO(bugs.webrtc.org/7494): Once + // `AudioProcessingImpl::recommended_stream_analog_level()` becomes a trivial + // getter, leave uninitialized. + // Recommended input volume. After `set_stream_analog_level()` is called it + // holds the observed input volume. Possibly updated by `AnalyzePreProcess()` + // and `Process()`; after these calls, holds the recommended input volume. + int recommended_input_volume_ = 0; + bool capture_output_used_; int channel_controlling_gain_ = 0; @@ -156,6 +176,8 @@ class AgcManagerDirect final { int clipping_rate_log_counter_; }; +// TODO(bugs.webrtc.org/7494): Use applied/recommended input volume naming +// convention. class MonoAgc { public: MonoAgc(ApmDataDumper* data_dumper, @@ -170,12 +192,22 @@ class MonoAgc { void Initialize(); void HandleCaptureOutputUsedChange(bool capture_output_used); + // Sets the current input volume. + void set_stream_analog_level(int level) { recommended_input_volume_ = level; } + + // Lowers the recommended input volume in response to clipping based on the + // suggested reduction `clipped_level_step`. Must be called after + // `set_stream_analog_level()`. void HandleClipping(int clipped_level_step); + // Analyzes `audio`, updates the recommended input volume based on the + // estimated speech level and, if enabled, updates the (digital) compression + // gain to be applied by `agc_`. Must be called after `HandleClipping()`. void Process(rtc::ArrayView audio); - void set_stream_analog_level(int level) { stream_analog_level_ = level; } - int stream_analog_level() const { return stream_analog_level_; } + // Returns the recommended input volume. Must be called after `Process()`. + int recommended_analog_level() const { return recommended_input_volume_; } + float voice_probability() const { return agc_->voice_probability(); } void ActivateLogging() { log_to_histograms_ = true; } absl::optional new_compression() const { @@ -188,12 +220,12 @@ class MonoAgc { int startup_min_level() const { return startup_min_level_; } private: - // Sets a new microphone level, after first checking that it hasn't been - // updated by the user, in which case no action is taken. + // Sets a new input volume, after first checking that it hasn't been updated + // by the user, in which case no action is taken. void SetLevel(int new_level); - // Set the maximum level the AGC is allowed to apply. Also updates the - // maximum compression gain to compensate. The level must be at least + // Set the maximum input volume the AGC is allowed to apply. Also updates the + // maximum compression gain to compensate. The volume must be at least // `kClippedLevelMin`. void SetMaxLevel(int level); @@ -215,7 +247,15 @@ class MonoAgc { bool startup_ = true; int startup_min_level_; int calls_since_last_gain_log_ = 0; - int stream_analog_level_ = 0; + + // TODO(bugs.webrtc.org/7494): Create a separate member for the applied + // input volume. + // Recommended input volume. After `set_stream_analog_level()` is + // called, it holds the observed applied input volume. Possibly updated by + // `HandleClipping()` and `Process()`; after these calls, holds the + // recommended input volume. + int recommended_input_volume_ = 0; + absl::optional new_compression_to_set_; bool log_to_histograms_ = false; const int clipped_level_min_; diff --git a/modules/audio_processing/agc/agc_manager_direct_unittest.cc b/modules/audio_processing/agc/agc_manager_direct_unittest.cc index 4a0bef19ed..8db5cfde70 100644 --- a/modules/audio_processing/agc/agc_manager_direct_unittest.cc +++ b/modules/audio_processing/agc/agc_manager_direct_unittest.cc @@ -10,15 +10,19 @@ #include "modules/audio_processing/agc/agc_manager_direct.h" +#include #include +#include #include "modules/audio_processing/agc/gain_control.h" #include "modules/audio_processing/agc/mock_agc.h" #include "modules/audio_processing/include/mock_audio_processing.h" +#include "rtc_base/numerics/safe_minmax.h" #include "rtc_base/strings/string_builder.h" #include "test/field_trial.h" #include "test/gmock.h" #include "test/gtest.h" +#include "test/testsupport/file_utils.h" using ::testing::_; using ::testing::AtLeast; @@ -40,6 +44,9 @@ constexpr int kClippedLevelStep = 15; constexpr float kClippedRatioThreshold = 0.1f; constexpr int kClippedWaitFrames = 300; +constexpr float kMinSample = std::numeric_limits::min(); +constexpr float kMaxSample = std::numeric_limits::max(); + using AnalogAgcConfig = AudioProcessing::Config::GainController1::AnalogGainController; using ClippingPredictorConfig = AudioProcessing::Config::GainController1:: @@ -96,8 +103,8 @@ void CallPreProcessAudioBuffer(int num_calls, float peak_ratio, AgcManagerDirect& manager) { RTC_DCHECK_LE(peak_ratio, 1.0f); - AudioBuffer audio_buffer(kSampleRateHz, 1, kSampleRateHz, 1, kSampleRateHz, - 1); + AudioBuffer audio_buffer(kSampleRateHz, kNumChannels, kSampleRateHz, + kNumChannels, kSampleRateHz, kNumChannels); const int num_channels = audio_buffer.num_channels(); const int num_frames = audio_buffer.num_frames(); @@ -160,8 +167,8 @@ std::string GetAgcMinMicLevelExperimentFieldTrial( void WriteAudioBufferSamples(float samples_value, float clipped_ratio, AudioBuffer& audio_buffer) { - RTC_DCHECK_GE(samples_value, std::numeric_limits::min()); - RTC_DCHECK_LE(samples_value, std::numeric_limits::max()); + RTC_DCHECK_GE(samples_value, kMinSample); + RTC_DCHECK_LE(samples_value, kMaxSample); RTC_DCHECK_GE(clipped_ratio, 0.0f); RTC_DCHECK_LE(clipped_ratio, 1.0f); int num_channels = audio_buffer.num_channels(); @@ -187,12 +194,71 @@ void CallPreProcessAndProcess(int num_calls, } } +// Reads a given number of 10 ms chunks from a PCM file and feeds them to +// `AgcManagerDirect`. +class SpeechSamplesReader { + private: + // Recording properties. + static constexpr int kPcmSampleRateHz = 16000; + static constexpr int kPcmNumChannels = 1; + static constexpr int kPcmBytesPerSamples = sizeof(int16_t); + + public: + SpeechSamplesReader() + : is_(test::ResourcePath("audio_processing/agc/agc_audio", "pcm"), + std::ios::binary | std::ios::ate), + audio_buffer_(kPcmSampleRateHz, + kPcmNumChannels, + kPcmSampleRateHz, + kPcmNumChannels, + kPcmSampleRateHz, + kPcmNumChannels), + buffer_(audio_buffer_.num_frames()), + buffer_num_bytes_(buffer_.size() * kPcmBytesPerSamples) { + RTC_CHECK(is_); + } + + // Reads `num_frames` 10 ms frames from the beginning of the PCM file, applies + // `gain_db` and feeds the frames into `agc` by calling `AnalyzePreProcess()` + // and `Process()` for each frame. Reads the number of 10 ms frames available + // in the PCM file if `num_frames` is too large - i.e., does not loop. + void Feed(int num_frames, int gain_db, AgcManagerDirect& agc) { + float gain = std::pow(10.0f, gain_db / 20.0f); // From dB to linear gain. + is_.seekg(0, is_.beg); // Start from the beginning of the PCM file. + + // Read and feed frames. + for (int i = 0; i < num_frames; ++i) { + is_.read(reinterpret_cast(buffer_.data()), buffer_num_bytes_); + if (is_.gcount() < buffer_num_bytes_) { + // EOF reached. Stop. + break; + } + // Apply gain and copy samples into `audio_buffer_`. + std::transform(buffer_.begin(), buffer_.end(), + audio_buffer_.channels()[0], [gain](int16_t v) -> float { + return rtc::SafeClamp(static_cast(v) * gain, + kMinSample, kMaxSample); + }); + + agc.AnalyzePreProcess(&audio_buffer_); + agc.Process(&audio_buffer_); + } + } + + private: + std::ifstream is_; + AudioBuffer audio_buffer_; + std::vector buffer_; + const std::streamsize buffer_num_bytes_; +}; + } // namespace // TODO(bugs.webrtc.org/12874): Use constexpr struct with designated // initializers once fixed. constexpr AnalogAgcConfig GetAnalogAgcTestConfig() { AnalogAgcConfig config; + config.enabled = true; config.startup_min_volume = kInitialVolume; config.clipped_level_min = kClippedMin; config.enable_digital_adaptive = true; @@ -203,6 +269,12 @@ constexpr AnalogAgcConfig GetAnalogAgcTestConfig() { return config; } +constexpr AnalogAgcConfig GetDisabledAnalogAgcConfig() { + AnalogAgcConfig config = GetAnalogAgcTestConfig(); + config.enabled = false; + return config; +} + class AgcManagerDirectTestHelper { public: AgcManagerDirectTestHelper() @@ -322,11 +394,83 @@ INSTANTIATE_TEST_SUITE_P(, AgcManagerDirectParametrizedTest, testing::Values(absl::nullopt, 12, 20)); +// Checks that when the analog controller is disabled, no downward adaptation +// takes place. +TEST_P(AgcManagerDirectParametrizedTest, + DisabledAnalogAgcDoesNotAdaptDownwards) { + AgcManagerDirect manager_no_analog_agc(kNumChannels, + GetDisabledAnalogAgcConfig()); + manager_no_analog_agc.Initialize(); + AgcManagerDirect manager_with_analog_agc(kNumChannels, + GetAnalogAgcTestConfig()); + manager_with_analog_agc.Initialize(); + + AudioBuffer audio_buffer(kSampleRateHz, kNumChannels, kSampleRateHz, + kNumChannels, kSampleRateHz, kNumChannels); + + constexpr int kAnalogLevel = 250; + static_assert(kAnalogLevel > kInitialVolume, "Increase `kAnalogLevel`."); + manager_no_analog_agc.set_stream_analog_level(kAnalogLevel); + manager_with_analog_agc.set_stream_analog_level(kAnalogLevel); + + // Make a first call with input that doesn't clip in order to let the + // controller read the input volume. That is needed because clipping input + // causes the controller to stay in idle state for + // `AnalogAgcConfig::clipped_wait_frames` frames. + WriteAudioBufferSamples(/*samples_value=*/0.0f, /*clipping_ratio=*/0.0f, + audio_buffer); + manager_no_analog_agc.AnalyzePreProcess(&audio_buffer); + manager_with_analog_agc.AnalyzePreProcess(&audio_buffer); + manager_no_analog_agc.Process(&audio_buffer); + manager_with_analog_agc.Process(&audio_buffer); + + // Feed clipping input to trigger a downward adapation of the analog level. + WriteAudioBufferSamples(/*samples_value=*/0.0f, /*clipping_ratio=*/0.2f, + audio_buffer); + manager_no_analog_agc.AnalyzePreProcess(&audio_buffer); + manager_with_analog_agc.AnalyzePreProcess(&audio_buffer); + manager_no_analog_agc.Process(&audio_buffer); + manager_with_analog_agc.Process(&audio_buffer); + + // Check that no adaptation occurs when the analog controller is disabled + // and make sure that the test triggers a downward adaptation otherwise. + EXPECT_EQ(manager_no_analog_agc.recommended_analog_level(), kAnalogLevel); + ASSERT_LT(manager_with_analog_agc.recommended_analog_level(), kAnalogLevel); +} + +// Checks that when the analog controller is disabled, no upward adaptation +// takes place. +TEST_P(AgcManagerDirectParametrizedTest, DisabledAnalogAgcDoesNotAdaptUpwards) { + AgcManagerDirect manager_no_analog_agc(kNumChannels, + GetDisabledAnalogAgcConfig()); + manager_no_analog_agc.Initialize(); + AgcManagerDirect manager_with_analog_agc(kNumChannels, + GetAnalogAgcTestConfig()); + manager_with_analog_agc.Initialize(); + + constexpr int kAnalogLevel = kInitialVolume; + manager_no_analog_agc.set_stream_analog_level(kAnalogLevel); + manager_with_analog_agc.set_stream_analog_level(kAnalogLevel); + + // Feed speech with low energy to trigger an upward adapation of the analog + // level. + constexpr int kNumFrames = 125; + constexpr int kGainDb = -20; + SpeechSamplesReader reader; + reader.Feed(kNumFrames, kGainDb, manager_no_analog_agc); + reader.Feed(kNumFrames, kGainDb, manager_with_analog_agc); + + // Check that no adaptation occurs when the analog controller is disabled + // and make sure that the test triggers an upward adaptation otherwise. + EXPECT_EQ(manager_no_analog_agc.recommended_analog_level(), kAnalogLevel); + ASSERT_GT(manager_with_analog_agc.recommended_analog_level(), kAnalogLevel); +} + TEST_P(AgcManagerDirectParametrizedTest, StartupMinVolumeConfigurationIsRespected) { AgcManagerDirectTestHelper helper; helper.FirstProcess(); - EXPECT_EQ(kInitialVolume, helper.manager.stream_analog_level()); + EXPECT_EQ(kInitialVolume, helper.manager.recommended_analog_level()); } TEST_P(AgcManagerDirectParametrizedTest, MicVolumeResponseToRmsError) { @@ -347,12 +491,12 @@ TEST_P(AgcManagerDirectParametrizedTest, MicVolumeResponseToRmsError) { EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(11), Return(true))); helper.CallProcess(/*num_calls=*/1); - EXPECT_EQ(130, helper.manager.stream_analog_level()); + EXPECT_EQ(130, helper.manager.recommended_analog_level()); EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(20), Return(true))); helper.CallProcess(/*num_calls=*/1); - EXPECT_EQ(168, helper.manager.stream_analog_level()); + EXPECT_EQ(168, helper.manager.recommended_analog_level()); // Inside the compressor's window; no change of volume. EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) @@ -366,17 +510,17 @@ TEST_P(AgcManagerDirectParametrizedTest, MicVolumeResponseToRmsError) { EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(-1), Return(true))); helper.CallProcess(/*num_calls=*/1); - EXPECT_EQ(167, helper.manager.stream_analog_level()); + EXPECT_EQ(167, helper.manager.recommended_analog_level()); EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(-1), Return(true))); helper.CallProcess(/*num_calls=*/1); - EXPECT_EQ(163, helper.manager.stream_analog_level()); + EXPECT_EQ(163, helper.manager.recommended_analog_level()); EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(-9), Return(true))); helper.CallProcess(/*num_calls=*/1); - EXPECT_EQ(129, helper.manager.stream_analog_level()); + EXPECT_EQ(129, helper.manager.recommended_analog_level()); } TEST_P(AgcManagerDirectParametrizedTest, MicVolumeIsLimited) { @@ -387,62 +531,62 @@ TEST_P(AgcManagerDirectParametrizedTest, MicVolumeIsLimited) { EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(30), Return(true))); helper.CallProcess(/*num_calls=*/1); - EXPECT_EQ(183, helper.manager.stream_analog_level()); + EXPECT_EQ(183, helper.manager.recommended_analog_level()); EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(30), Return(true))); helper.CallProcess(/*num_calls=*/1); - EXPECT_EQ(243, helper.manager.stream_analog_level()); + EXPECT_EQ(243, helper.manager.recommended_analog_level()); // Won't go higher than the maximum. EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(30), Return(true))); helper.CallProcess(/*num_calls=*/1); - EXPECT_EQ(255, helper.manager.stream_analog_level()); + EXPECT_EQ(255, helper.manager.recommended_analog_level()); EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(-1), Return(true))); helper.CallProcess(/*num_calls=*/1); - EXPECT_EQ(254, helper.manager.stream_analog_level()); + EXPECT_EQ(254, helper.manager.recommended_analog_level()); // Maximum downwards change is limited. EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(-40), Return(true))); helper.CallProcess(/*num_calls=*/1); - EXPECT_EQ(194, helper.manager.stream_analog_level()); + EXPECT_EQ(194, helper.manager.recommended_analog_level()); EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(-40), Return(true))); helper.CallProcess(/*num_calls=*/1); - EXPECT_EQ(137, helper.manager.stream_analog_level()); + EXPECT_EQ(137, helper.manager.recommended_analog_level()); EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(-40), Return(true))); helper.CallProcess(/*num_calls=*/1); - EXPECT_EQ(88, helper.manager.stream_analog_level()); + EXPECT_EQ(88, helper.manager.recommended_analog_level()); EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(-40), Return(true))); helper.CallProcess(/*num_calls=*/1); - EXPECT_EQ(54, helper.manager.stream_analog_level()); + EXPECT_EQ(54, helper.manager.recommended_analog_level()); EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(-40), Return(true))); helper.CallProcess(/*num_calls=*/1); - EXPECT_EQ(33, helper.manager.stream_analog_level()); + EXPECT_EQ(33, helper.manager.recommended_analog_level()); // Won't go lower than the minimum. EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(-40), Return(true))); helper.CallProcess(/*num_calls=*/1); EXPECT_EQ(std::max(18, GetMinMicLevel()), - helper.manager.stream_analog_level()); + helper.manager.recommended_analog_level()); EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(-40), Return(true))); helper.CallProcess(/*num_calls=*/1); EXPECT_EQ(std::max(12, GetMinMicLevel()), - helper.manager.stream_analog_level()); + helper.manager.recommended_analog_level()); } TEST_P(AgcManagerDirectParametrizedTest, CompressorStepsTowardsTarget) { @@ -609,7 +753,7 @@ TEST_P(AgcManagerDirectParametrizedTest, UnmutingChecksVolumeWithoutRaising) { // SetMicVolume should not be called. EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)).WillOnce(Return(false)); helper.CallProcess(/*num_calls=*/1); - EXPECT_EQ(127, helper.manager.stream_analog_level()); + EXPECT_EQ(127, helper.manager.recommended_analog_level()); } TEST_P(AgcManagerDirectParametrizedTest, UnmutingRaisesTooLowVolume) { @@ -621,7 +765,7 @@ TEST_P(AgcManagerDirectParametrizedTest, UnmutingRaisesTooLowVolume) { helper.ExpectCheckVolumeAndReset(/*volume=*/11); EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)).WillOnce(Return(false)); helper.CallProcess(/*num_calls=*/1); - EXPECT_EQ(GetMinMicLevel(), helper.manager.stream_analog_level()); + EXPECT_EQ(GetMinMicLevel(), helper.manager.recommended_analog_level()); } TEST_P(AgcManagerDirectParametrizedTest, @@ -639,10 +783,10 @@ TEST_P(AgcManagerDirectParametrizedTest, // GetMicVolume returns a value outside of the quantization slack, indicating // a manual volume change. - ASSERT_NE(helper.manager.stream_analog_level(), 154); + ASSERT_NE(helper.manager.recommended_analog_level(), 154); helper.manager.set_stream_analog_level(154); helper.CallProcess(/*num_calls=*/1); - EXPECT_EQ(154, helper.manager.stream_analog_level()); + EXPECT_EQ(154, helper.manager.recommended_analog_level()); // Do the same thing, except downwards now. EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) @@ -650,13 +794,13 @@ TEST_P(AgcManagerDirectParametrizedTest, helper.manager.set_stream_analog_level(100); EXPECT_CALL(*helper.mock_agc, Reset()).Times(AtLeast(1)); helper.CallProcess(/*num_calls=*/1); - EXPECT_EQ(100, helper.manager.stream_analog_level()); + EXPECT_EQ(100, helper.manager.recommended_analog_level()); // And finally verify the AGC continues working without a manual change. EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(-1), Return(true))); helper.CallProcess(/*num_calls=*/1); - EXPECT_EQ(99, helper.manager.stream_analog_level()); + EXPECT_EQ(99, helper.manager.recommended_analog_level()); } TEST_P(AgcManagerDirectParametrizedTest, @@ -669,11 +813,11 @@ TEST_P(AgcManagerDirectParametrizedTest, EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) .WillRepeatedly(DoAll(SetArgPointee<0>(30), Return(true))); helper.CallProcess(/*num_calls=*/1); - EXPECT_EQ(183, helper.manager.stream_analog_level()); + EXPECT_EQ(183, helper.manager.recommended_analog_level()); helper.CallProcess(/*num_calls=*/1); - EXPECT_EQ(243, helper.manager.stream_analog_level()); + EXPECT_EQ(243, helper.manager.recommended_analog_level()); helper.CallProcess(/*num_calls=*/1); - EXPECT_EQ(255, helper.manager.stream_analog_level()); + EXPECT_EQ(255, helper.manager.recommended_analog_level()); // Manual change does not result in SetMicVolume call. EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) @@ -681,13 +825,13 @@ TEST_P(AgcManagerDirectParametrizedTest, helper.manager.set_stream_analog_level(50); EXPECT_CALL(*helper.mock_agc, Reset()).Times(AtLeast(1)); helper.CallProcess(/*num_calls=*/1); - EXPECT_EQ(50, helper.manager.stream_analog_level()); + EXPECT_EQ(50, helper.manager.recommended_analog_level()); // Continues working as usual afterwards. EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(20), Return(true))); helper.CallProcess(/*num_calls=*/1); - EXPECT_EQ(69, helper.manager.stream_analog_level()); + EXPECT_EQ(69, helper.manager.recommended_analog_level()); } // Checks that, when the min mic level override is not specified, AGC ramps up @@ -704,23 +848,23 @@ TEST(AgcManagerDirectTest, RecoveryAfterManualLevelChangeBelowMin) { helper.manager.set_stream_analog_level(1); EXPECT_CALL(*helper.mock_agc, Reset()).Times(AtLeast(1)); helper.CallProcess(/*num_calls=*/1); - EXPECT_EQ(1, helper.manager.stream_analog_level()); + EXPECT_EQ(1, helper.manager.recommended_analog_level()); // Continues working as usual afterwards. EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(11), Return(true))); helper.CallProcess(/*num_calls=*/1); - EXPECT_EQ(2, helper.manager.stream_analog_level()); + EXPECT_EQ(2, helper.manager.recommended_analog_level()); EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(30), Return(true))); helper.CallProcess(/*num_calls=*/1); - EXPECT_EQ(11, helper.manager.stream_analog_level()); + EXPECT_EQ(11, helper.manager.recommended_analog_level()); EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(20), Return(true))); helper.CallProcess(/*num_calls=*/1); - EXPECT_EQ(18, helper.manager.stream_analog_level()); + EXPECT_EQ(18, helper.manager.recommended_analog_level()); } // Checks that, when the min mic level override is specified, AGC immediately @@ -742,7 +886,7 @@ TEST_P(AgcManagerDirectParametrizedTest, helper.manager.set_stream_analog_level(1); EXPECT_CALL(*helper.mock_agc, Reset()).Times(AtLeast(1)); helper.CallProcess(/*num_calls=*/1); - EXPECT_EQ(GetMinMicLevel(), helper.manager.stream_analog_level()); + EXPECT_EQ(GetMinMicLevel(), helper.manager.recommended_analog_level()); } TEST_P(AgcManagerDirectParametrizedTest, NoClippingHasNoImpact) { @@ -750,7 +894,7 @@ TEST_P(AgcManagerDirectParametrizedTest, NoClippingHasNoImpact) { helper.FirstProcess(); helper.CallPreProc(/*num_calls=*/100, /*clipped_ratio=*/0); - EXPECT_EQ(128, helper.manager.stream_analog_level()); + EXPECT_EQ(128, helper.manager.recommended_analog_level()); } TEST_P(AgcManagerDirectParametrizedTest, ClippingUnderThresholdHasNoImpact) { @@ -758,7 +902,7 @@ TEST_P(AgcManagerDirectParametrizedTest, ClippingUnderThresholdHasNoImpact) { helper.FirstProcess(); helper.CallPreProc(/*num_calls=*/1, /*clipped_ratio=*/0.099); - EXPECT_EQ(128, helper.manager.stream_analog_level()); + EXPECT_EQ(128, helper.manager.recommended_analog_level()); } TEST_P(AgcManagerDirectParametrizedTest, ClippingLowersVolume) { @@ -767,7 +911,7 @@ TEST_P(AgcManagerDirectParametrizedTest, ClippingLowersVolume) { EXPECT_CALL(*helper.mock_agc, Reset()).Times(AtLeast(1)); helper.CallPreProc(/*num_calls=*/1, /*clipped_ratio=*/0.2); - EXPECT_EQ(240, helper.manager.stream_analog_level()); + EXPECT_EQ(240, helper.manager.recommended_analog_level()); } TEST_P(AgcManagerDirectParametrizedTest, WaitingPeriodBetweenClippingChecks) { @@ -776,16 +920,16 @@ TEST_P(AgcManagerDirectParametrizedTest, WaitingPeriodBetweenClippingChecks) { EXPECT_CALL(*helper.mock_agc, Reset()).Times(AtLeast(1)); helper.CallPreProc(/*num_calls=*/1, /*clipped_ratio=*/kAboveClippedThreshold); - EXPECT_EQ(240, helper.manager.stream_analog_level()); + EXPECT_EQ(240, helper.manager.recommended_analog_level()); EXPECT_CALL(*helper.mock_agc, Reset()).Times(0); helper.CallPreProc(/*num_calls=*/300, /*clipped_ratio=*/kAboveClippedThreshold); - EXPECT_EQ(240, helper.manager.stream_analog_level()); + EXPECT_EQ(240, helper.manager.recommended_analog_level()); EXPECT_CALL(*helper.mock_agc, Reset()).Times(AtLeast(1)); helper.CallPreProc(/*num_calls=*/1, /*clipped_ratio=*/kAboveClippedThreshold); - EXPECT_EQ(225, helper.manager.stream_analog_level()); + EXPECT_EQ(225, helper.manager.recommended_analog_level()); } TEST_P(AgcManagerDirectParametrizedTest, ClippingLoweringIsLimited) { @@ -794,12 +938,12 @@ TEST_P(AgcManagerDirectParametrizedTest, ClippingLoweringIsLimited) { EXPECT_CALL(*helper.mock_agc, Reset()).Times(AtLeast(1)); helper.CallPreProc(/*num_calls=*/1, /*clipped_ratio=*/kAboveClippedThreshold); - EXPECT_EQ(kClippedMin, helper.manager.stream_analog_level()); + EXPECT_EQ(kClippedMin, helper.manager.recommended_analog_level()); EXPECT_CALL(*helper.mock_agc, Reset()).Times(0); helper.CallPreProc(/*num_calls=*/1000, /*clipped_ratio=*/kAboveClippedThreshold); - EXPECT_EQ(kClippedMin, helper.manager.stream_analog_level()); + EXPECT_EQ(kClippedMin, helper.manager.recommended_analog_level()); } TEST_P(AgcManagerDirectParametrizedTest, @@ -809,12 +953,12 @@ TEST_P(AgcManagerDirectParametrizedTest, EXPECT_CALL(*helper.mock_agc, Reset()).Times(AtLeast(1)); helper.CallPreProc(/*num_calls=*/1, /*clipped_ratio=*/kAboveClippedThreshold); - EXPECT_EQ(240, helper.manager.stream_analog_level()); + EXPECT_EQ(240, helper.manager.recommended_analog_level()); EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) .WillRepeatedly(DoAll(SetArgPointee<0>(30), Return(true))); helper.CallProcess(/*num_calls=*/10); - EXPECT_EQ(240, helper.manager.stream_analog_level()); + EXPECT_EQ(240, helper.manager.recommended_analog_level()); } TEST_P(AgcManagerDirectParametrizedTest, @@ -824,14 +968,14 @@ TEST_P(AgcManagerDirectParametrizedTest, EXPECT_CALL(*helper.mock_agc, Reset()).Times(AtLeast(1)); helper.CallPreProc(/*num_calls=*/1, /*clipped_ratio=*/kAboveClippedThreshold); - EXPECT_EQ(185, helper.manager.stream_analog_level()); + EXPECT_EQ(185, helper.manager.recommended_analog_level()); EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) .WillRepeatedly(DoAll(SetArgPointee<0>(40), Return(true))); helper.CallProcess(/*num_calls=*/1); - EXPECT_EQ(240, helper.manager.stream_analog_level()); + EXPECT_EQ(240, helper.manager.recommended_analog_level()); helper.CallProcess(/*num_calls=*/10); - EXPECT_EQ(240, helper.manager.stream_analog_level()); + EXPECT_EQ(240, helper.manager.recommended_analog_level()); } TEST_P(AgcManagerDirectParametrizedTest, @@ -841,7 +985,7 @@ TEST_P(AgcManagerDirectParametrizedTest, EXPECT_CALL(*helper.mock_agc, Reset()).Times(AtLeast(1)); helper.CallPreProc(/*num_calls=*/1, kAboveClippedThreshold); - EXPECT_EQ(195, helper.manager.stream_analog_level()); + EXPECT_EQ(195, helper.manager.recommended_analog_level()); EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(11), Return(true))) @@ -875,13 +1019,13 @@ TEST_P(AgcManagerDirectParametrizedTest, /*clipped_ratio=*/kAboveClippedThreshold); EXPECT_CALL(*helper.mock_agc, Reset()).Times(AtLeast(1)); helper.CallPreProc(/*num_calls=*/1, /*clipped_ratio=*/kAboveClippedThreshold); - EXPECT_EQ(180, helper.manager.stream_analog_level()); + EXPECT_EQ(180, helper.manager.recommended_analog_level()); helper.CallPreProc(/*num_calls=*/300, /*clipped_ratio=*/kAboveClippedThreshold); EXPECT_CALL(*helper.mock_agc, Reset()).Times(AtLeast(1)); helper.CallPreProc(1, kAboveClippedThreshold); - EXPECT_EQ(kClippedMin, helper.manager.stream_analog_level()); + EXPECT_EQ(kClippedMin, helper.manager.recommended_analog_level()); // Current level is now at the minimum, but the maximum allowed level still // has more to decrease. @@ -927,7 +1071,7 @@ TEST_P(AgcManagerDirectParametrizedTest, UserCanRaiseVolumeAfterClipping) { EXPECT_CALL(*helper.mock_agc, Reset()).Times(AtLeast(1)); helper.CallPreProc(/*num_calls=*/1, /*clipped_ratio=*/kAboveClippedThreshold); - EXPECT_EQ(210, helper.manager.stream_analog_level()); + EXPECT_EQ(210, helper.manager.recommended_analog_level()); // High enough error to trigger a volume check. EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) @@ -936,23 +1080,23 @@ TEST_P(AgcManagerDirectParametrizedTest, UserCanRaiseVolumeAfterClipping) { helper.manager.set_stream_analog_level(250); EXPECT_CALL(*helper.mock_agc, Reset()).Times(AtLeast(1)); helper.CallProcess(/*num_calls=*/1); - EXPECT_EQ(250, helper.manager.stream_analog_level()); + EXPECT_EQ(250, helper.manager.recommended_analog_level()); // Move down... EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(-10), Return(true))); helper.CallProcess(/*num_calls=*/1); - EXPECT_EQ(210, helper.manager.stream_analog_level()); + EXPECT_EQ(210, helper.manager.recommended_analog_level()); // And back up to the new max established by the user. EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(40), Return(true))); helper.CallProcess(/*num_calls=*/1); - EXPECT_EQ(250, helper.manager.stream_analog_level()); + EXPECT_EQ(250, helper.manager.recommended_analog_level()); // Will not move above new maximum. EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) .WillOnce(DoAll(SetArgPointee<0>(30), Return(true))); helper.CallProcess(/*num_calls=*/1); - EXPECT_EQ(250, helper.manager.stream_analog_level()); + EXPECT_EQ(250, helper.manager.recommended_analog_level()); } TEST_P(AgcManagerDirectParametrizedTest, ClippingDoesNotPullLowVolumeBackUp) { @@ -960,9 +1104,9 @@ TEST_P(AgcManagerDirectParametrizedTest, ClippingDoesNotPullLowVolumeBackUp) { helper.SetVolumeAndProcess(/*volume=*/80); EXPECT_CALL(*helper.mock_agc, Reset()).Times(0); - int initial_volume = helper.manager.stream_analog_level(); + int initial_volume = helper.manager.recommended_analog_level(); helper.CallPreProc(/*num_calls=*/1, /*clipped_ratio=*/kAboveClippedThreshold); - EXPECT_EQ(initial_volume, helper.manager.stream_analog_level()); + EXPECT_EQ(initial_volume, helper.manager.recommended_analog_level()); } TEST_P(AgcManagerDirectParametrizedTest, TakesNoActionOnZeroMicVolume) { @@ -973,17 +1117,17 @@ TEST_P(AgcManagerDirectParametrizedTest, TakesNoActionOnZeroMicVolume) { .WillRepeatedly(DoAll(SetArgPointee<0>(30), Return(true))); helper.manager.set_stream_analog_level(0); helper.CallProcess(/*num_calls=*/10); - EXPECT_EQ(0, helper.manager.stream_analog_level()); + EXPECT_EQ(0, helper.manager.recommended_analog_level()); } TEST_P(AgcManagerDirectParametrizedTest, ClippingDetectionLowersVolume) { AgcManagerDirectTestHelper helper; helper.SetVolumeAndProcess(/*volume=*/255); - EXPECT_EQ(255, helper.manager.stream_analog_level()); + EXPECT_EQ(255, helper.manager.recommended_analog_level()); helper.CallPreProcForChangingAudio(/*num_calls=*/100, /*peak_ratio=*/0.99f); - EXPECT_EQ(255, helper.manager.stream_analog_level()); + EXPECT_EQ(255, helper.manager.recommended_analog_level()); helper.CallPreProcForChangingAudio(/*num_calls=*/100, /*peak_ratio=*/1.0f); - EXPECT_EQ(240, helper.manager.stream_analog_level()); + EXPECT_EQ(240, helper.manager.recommended_analog_level()); } TEST_P(AgcManagerDirectParametrizedTest, @@ -991,11 +1135,11 @@ TEST_P(AgcManagerDirectParametrizedTest, AgcManagerDirectTestHelper helper; helper.SetVolumeAndProcess(/*volume=*/255); EXPECT_FALSE(helper.manager.clipping_predictor_enabled()); - EXPECT_EQ(255, helper.manager.stream_analog_level()); + EXPECT_EQ(255, helper.manager.recommended_analog_level()); helper.CallPreProcForChangingAudio(/*num_calls=*/100, /*peak_ratio=*/0.99f); - EXPECT_EQ(255, helper.manager.stream_analog_level()); + EXPECT_EQ(255, helper.manager.recommended_analog_level()); helper.CallPreProcForChangingAudio(/*num_calls=*/100, /*peak_ratio=*/0.99f); - EXPECT_EQ(255, helper.manager.stream_analog_level()); + EXPECT_EQ(255, helper.manager.recommended_analog_level()); } TEST_P(AgcManagerDirectParametrizedTest, DisableDigitalDisablesDigital) { @@ -1112,15 +1256,16 @@ TEST(AgcManagerDirectTest, AgcMinMicLevelExperimentCheckMinLevelWithClipping) { *manager_with_override); // Make sure that an adaptation occurred. - ASSERT_GT(manager->stream_analog_level(), 0); + ASSERT_GT(manager->recommended_analog_level(), 0); // Check that the test signal triggers a larger downward adaptation for // `manager`, which is allowed to reach a lower gain. - EXPECT_GT(manager_with_override->stream_analog_level(), - manager->stream_analog_level()); + EXPECT_GT(manager_with_override->recommended_analog_level(), + manager->recommended_analog_level()); // Check that the gain selected by `manager_with_override` equals the minimum // value overridden via field trial. - EXPECT_EQ(manager_with_override->stream_analog_level(), kMinMicLevelOverride); + EXPECT_EQ(manager_with_override->recommended_analog_level(), + kMinMicLevelOverride); } // Checks that, when the "WebRTC-Audio-AgcMinMicLevelExperiment" field trial is @@ -1171,15 +1316,15 @@ TEST(AgcManagerDirectTest, *manager_with_override); // Make sure that an adaptation occurred. - ASSERT_GT(manager->stream_analog_level(), 0); + ASSERT_GT(manager->recommended_analog_level(), 0); // Check that the selected analog gain is the same for both controllers and // that it equals the minimum level reached when clipping is handled. That is // expected because the minimum microphone level override is less than the // minimum level used when clipping is detected. - EXPECT_EQ(manager->stream_analog_level(), - manager_with_override->stream_analog_level()); - EXPECT_EQ(manager_with_override->stream_analog_level(), + EXPECT_EQ(manager->recommended_analog_level(), + manager_with_override->recommended_analog_level()); + EXPECT_EQ(manager_with_override->recommended_analog_level(), kDefaultAnalogConfig.clipped_level_min); } @@ -1252,14 +1397,14 @@ TEST_P(AgcManagerDirectParametrizedTest, manager.set_stream_analog_level(/*level=*/255); EXPECT_FALSE(manager.clipping_predictor_enabled()); EXPECT_FALSE(manager.use_clipping_predictor_step()); - EXPECT_EQ(manager.stream_analog_level(), 255); + EXPECT_EQ(manager.recommended_analog_level(), 255); manager.Process(&audio_buffer); CallPreProcessAudioBuffer(/*num_calls=*/10, /*peak_ratio=*/0.99f, manager); - EXPECT_EQ(manager.stream_analog_level(), 255); + EXPECT_EQ(manager.recommended_analog_level(), 255); CallPreProcessAudioBuffer(/*num_calls=*/300, /*peak_ratio=*/0.99f, manager); - EXPECT_EQ(manager.stream_analog_level(), 255); + EXPECT_EQ(manager.recommended_analog_level(), 255); CallPreProcessAudioBuffer(/*num_calls=*/10, /*peak_ratio=*/0.99f, manager); - EXPECT_EQ(manager.stream_analog_level(), 255); + EXPECT_EQ(manager.recommended_analog_level(), 255); } TEST_P(AgcManagerDirectParametrizedTest, @@ -1291,53 +1436,58 @@ TEST_P(AgcManagerDirectParametrizedTest, EXPECT_TRUE(manager_with_prediction.clipping_predictor_enabled()); EXPECT_FALSE(manager_without_prediction.clipping_predictor_enabled()); EXPECT_TRUE(manager_with_prediction.use_clipping_predictor_step()); - EXPECT_EQ(manager_with_prediction.stream_analog_level(), kInitialLevel); - EXPECT_EQ(manager_without_prediction.stream_analog_level(), kInitialLevel); + EXPECT_EQ(manager_with_prediction.recommended_analog_level(), kInitialLevel); + EXPECT_EQ(manager_without_prediction.recommended_analog_level(), + kInitialLevel); // Expect a change in the analog level when the prediction step is used. CallPreProcessAudioBuffer(/*num_calls=*/10, kCloseToClippingPeakRatio, manager_with_prediction); CallPreProcessAudioBuffer(/*num_calls=*/10, kCloseToClippingPeakRatio, manager_without_prediction); - EXPECT_EQ(manager_with_prediction.stream_analog_level(), + EXPECT_EQ(manager_with_prediction.recommended_analog_level(), kInitialLevel - kClippedLevelStep); - EXPECT_EQ(manager_without_prediction.stream_analog_level(), kInitialLevel); + EXPECT_EQ(manager_without_prediction.recommended_analog_level(), + kInitialLevel); // Expect no change during waiting. CallPreProcessAudioBuffer(kClippedWaitFrames, kCloseToClippingPeakRatio, manager_with_prediction); CallPreProcessAudioBuffer(kClippedWaitFrames, kCloseToClippingPeakRatio, manager_without_prediction); - EXPECT_EQ(manager_with_prediction.stream_analog_level(), + EXPECT_EQ(manager_with_prediction.recommended_analog_level(), kInitialLevel - kClippedLevelStep); - EXPECT_EQ(manager_without_prediction.stream_analog_level(), kInitialLevel); + EXPECT_EQ(manager_without_prediction.recommended_analog_level(), + kInitialLevel); // Expect a change when the prediction step is used. CallPreProcessAudioBuffer(/*num_calls=*/10, kCloseToClippingPeakRatio, manager_with_prediction); CallPreProcessAudioBuffer(/*num_calls=*/10, kCloseToClippingPeakRatio, manager_without_prediction); - EXPECT_EQ(manager_with_prediction.stream_analog_level(), + EXPECT_EQ(manager_with_prediction.recommended_analog_level(), kInitialLevel - 2 * kClippedLevelStep); - EXPECT_EQ(manager_without_prediction.stream_analog_level(), kInitialLevel); + EXPECT_EQ(manager_without_prediction.recommended_analog_level(), + kInitialLevel); // Expect no change when clipping is not detected or predicted. CallPreProcessAudioBuffer(2 * kClippedWaitFrames, kZeroPeakRatio, manager_with_prediction); CallPreProcessAudioBuffer(2 * kClippedWaitFrames, kZeroPeakRatio, manager_without_prediction); - EXPECT_EQ(manager_with_prediction.stream_analog_level(), + EXPECT_EQ(manager_with_prediction.recommended_analog_level(), kInitialLevel - 2 * kClippedLevelStep); - EXPECT_EQ(manager_without_prediction.stream_analog_level(), kInitialLevel); + EXPECT_EQ(manager_without_prediction.recommended_analog_level(), + kInitialLevel); // Expect a change for clipping frames. CallPreProcessAudioBuffer(/*num_calls=*/1, kClippingPeakRatio, manager_with_prediction); CallPreProcessAudioBuffer(/*num_calls=*/1, kClippingPeakRatio, manager_without_prediction); - EXPECT_EQ(manager_with_prediction.stream_analog_level(), + EXPECT_EQ(manager_with_prediction.recommended_analog_level(), kInitialLevel - 3 * kClippedLevelStep); - EXPECT_EQ(manager_without_prediction.stream_analog_level(), + EXPECT_EQ(manager_without_prediction.recommended_analog_level(), kInitialLevel - kClippedLevelStep); // Expect no change during waiting. @@ -1345,9 +1495,9 @@ TEST_P(AgcManagerDirectParametrizedTest, manager_with_prediction); CallPreProcessAudioBuffer(kClippedWaitFrames, kClippingPeakRatio, manager_without_prediction); - EXPECT_EQ(manager_with_prediction.stream_analog_level(), + EXPECT_EQ(manager_with_prediction.recommended_analog_level(), kInitialLevel - 3 * kClippedLevelStep); - EXPECT_EQ(manager_without_prediction.stream_analog_level(), + EXPECT_EQ(manager_without_prediction.recommended_analog_level(), kInitialLevel - kClippedLevelStep); // Expect a change for clipping frames. @@ -1355,9 +1505,9 @@ TEST_P(AgcManagerDirectParametrizedTest, manager_with_prediction); CallPreProcessAudioBuffer(/*num_calls=*/1, kClippingPeakRatio, manager_without_prediction); - EXPECT_EQ(manager_with_prediction.stream_analog_level(), + EXPECT_EQ(manager_with_prediction.recommended_analog_level(), kInitialLevel - 4 * kClippedLevelStep); - EXPECT_EQ(manager_without_prediction.stream_analog_level(), + EXPECT_EQ(manager_without_prediction.recommended_analog_level(), kInitialLevel - 2 * kClippedLevelStep); } @@ -1389,64 +1539,65 @@ TEST_P(AgcManagerDirectParametrizedTest, EXPECT_TRUE(manager_with_prediction.clipping_predictor_enabled()); EXPECT_FALSE(manager_without_prediction.clipping_predictor_enabled()); EXPECT_FALSE(manager_with_prediction.use_clipping_predictor_step()); - EXPECT_EQ(manager_with_prediction.stream_analog_level(), kInitialLevel); - EXPECT_EQ(manager_without_prediction.stream_analog_level(), kInitialLevel); + EXPECT_EQ(manager_with_prediction.recommended_analog_level(), kInitialLevel); + EXPECT_EQ(manager_without_prediction.recommended_analog_level(), + kInitialLevel); // Expect no change in the analog level for non-clipping frames. CallPreProcessAudioBuffer(/*num_calls=*/10, kCloseToClippingPeakRatio, manager_with_prediction); CallPreProcessAudioBuffer(/*num_calls=*/10, kCloseToClippingPeakRatio, manager_without_prediction); - EXPECT_EQ(manager_with_prediction.stream_analog_level(), - manager_without_prediction.stream_analog_level()); + EXPECT_EQ(manager_with_prediction.recommended_analog_level(), + manager_without_prediction.recommended_analog_level()); // Expect no change for non-clipping frames. CallPreProcessAudioBuffer(kClippedWaitFrames, kCloseToClippingPeakRatio, manager_with_prediction); CallPreProcessAudioBuffer(kClippedWaitFrames, kCloseToClippingPeakRatio, manager_without_prediction); - EXPECT_EQ(manager_with_prediction.stream_analog_level(), - manager_without_prediction.stream_analog_level()); + EXPECT_EQ(manager_with_prediction.recommended_analog_level(), + manager_without_prediction.recommended_analog_level()); // Expect no change for non-clipping frames. CallPreProcessAudioBuffer(/*num_calls=*/10, kCloseToClippingPeakRatio, manager_with_prediction); CallPreProcessAudioBuffer(/*num_calls=*/10, kCloseToClippingPeakRatio, manager_without_prediction); - EXPECT_EQ(manager_with_prediction.stream_analog_level(), - manager_without_prediction.stream_analog_level()); + EXPECT_EQ(manager_with_prediction.recommended_analog_level(), + manager_without_prediction.recommended_analog_level()); // Expect no change when clipping is not detected or predicted. CallPreProcessAudioBuffer(2 * kClippedWaitFrames, kZeroPeakRatio, manager_with_prediction); CallPreProcessAudioBuffer(2 * kClippedWaitFrames, kZeroPeakRatio, manager_without_prediction); - EXPECT_EQ(manager_with_prediction.stream_analog_level(), - manager_without_prediction.stream_analog_level()); + EXPECT_EQ(manager_with_prediction.recommended_analog_level(), + manager_without_prediction.recommended_analog_level()); // Expect a change for clipping frames. CallPreProcessAudioBuffer(/*num_calls=*/1, kClippingPeakRatio, manager_with_prediction); CallPreProcessAudioBuffer(/*num_calls=*/1, kClippingPeakRatio, manager_without_prediction); - EXPECT_EQ(manager_with_prediction.stream_analog_level(), - manager_without_prediction.stream_analog_level()); + EXPECT_EQ(manager_with_prediction.recommended_analog_level(), + manager_without_prediction.recommended_analog_level()); // Expect no change during waiting. CallPreProcessAudioBuffer(kClippedWaitFrames, kClippingPeakRatio, manager_with_prediction); CallPreProcessAudioBuffer(kClippedWaitFrames, kClippingPeakRatio, manager_without_prediction); - EXPECT_EQ(manager_with_prediction.stream_analog_level(), - manager_without_prediction.stream_analog_level()); + EXPECT_EQ(manager_with_prediction.recommended_analog_level(), + manager_without_prediction.recommended_analog_level()); // Expect a change for clipping frames. CallPreProcessAudioBuffer(/*num_calls=*/1, kClippingPeakRatio, manager_with_prediction); CallPreProcessAudioBuffer(/*num_calls=*/1, kClippingPeakRatio, manager_without_prediction); - EXPECT_EQ(manager_with_prediction.stream_analog_level(), - manager_without_prediction.stream_analog_level()); + EXPECT_EQ(manager_with_prediction.recommended_analog_level(), + manager_without_prediction.recommended_analog_level()); } } // namespace webrtc diff --git a/modules/audio_processing/audio_processing_impl.cc b/modules/audio_processing/audio_processing_impl.cc index 57d51a2a65..5256f9fecc 100644 --- a/modules/audio_processing/audio_processing_impl.cc +++ b/modules/audio_processing/audio_processing_impl.cc @@ -1374,7 +1374,7 @@ int AudioProcessingImpl::ProcessCaptureStreamLocked() { if (config_.capture_level_adjustment.analog_mic_gain_emulation.enabled) { if (submodules_.agc_manager) { submodules_.capture_levels_adjuster->SetAnalogMicGainLevel( - submodules_.agc_manager->stream_analog_level()); + submodules_.agc_manager->recommended_analog_level()); } else if (submodules_.gain_control) { submodules_.capture_levels_adjuster->SetAnalogMicGainLevel( submodules_.gain_control->stream_analog_level()); @@ -1641,7 +1641,7 @@ int AudioProcessingImpl::recommended_stream_analog_level_locked() const { } if (submodules_.agc_manager) { - return submodules_.agc_manager->stream_analog_level(); + return submodules_.agc_manager->recommended_analog_level(); } if (submodules_.gain_control) { @@ -1852,6 +1852,10 @@ void AudioProcessingImpl::InitializeGainController1() { return; } + RTC_HISTOGRAM_BOOLEAN( + "WebRTC.Audio.GainController.Analog.Enabled", + config_.gain_controller1.analog_gain_controller.enabled); + if (!submodules_.gain_control) { submodules_.gain_control.reset(new GainControlImpl()); } @@ -1887,7 +1891,7 @@ void AudioProcessingImpl::InitializeGainController1() { int stream_analog_level = -1; const bool re_creation = !!submodules_.agc_manager; if (re_creation) { - stream_analog_level = submodules_.agc_manager->stream_analog_level(); + stream_analog_level = submodules_.agc_manager->recommended_analog_level(); } submodules_.agc_manager.reset(new AgcManagerDirect( num_proc_channels(), config_.gain_controller1.analog_gain_controller));