From e00147440758c12688db81ca164745f3fb74da84 Mon Sep 17 00:00:00 2001 From: Alessio Bazzica Date: Thu, 1 Dec 2022 16:45:52 +0100 Subject: [PATCH] InputVolumeController: readability improvements - use the new naming convention 'input volume' - fix Yoda-style expressions in the unit tests - clarify how the gain map values are generated Bug: webrtc:7494 Change-Id: I4d6ee897a93cdefa6735733b053c57326d01a528 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/285467 Commit-Queue: Alessio Bazzica Reviewed-by: Hanna Silen Cr-Commit-Position: refs/heads/main@{#38795} --- .../agc2/clipping_predictor.cc | 47 +-- .../audio_processing/agc2/gain_map_internal.h | 10 +- .../agc2/input_volume_controller.cc | 273 +++++++++--------- .../agc2/input_volume_controller.h | 35 +-- .../agc2/input_volume_controller_unittest.cc | 179 ++++++------ 5 files changed, 281 insertions(+), 263 deletions(-) diff --git a/modules/audio_processing/agc2/clipping_predictor.cc b/modules/audio_processing/agc2/clipping_predictor.cc index 2bf5fb2e32..fd759c63e8 100644 --- a/modules/audio_processing/agc2/clipping_predictor.cc +++ b/modules/audio_processing/agc2/clipping_predictor.cc @@ -25,30 +25,31 @@ namespace { constexpr int kClippingPredictorMaxGainChange = 15; -// Estimates the new level from the gain error; a copy of the function -// `LevelFromGainError` in agc_manager_direct.cc. -int LevelFromGainError(int gain_error, - int level, - int min_mic_level, - int max_mic_level) { - RTC_DCHECK_GE(level, 0); - RTC_DCHECK_LE(level, max_mic_level); - if (gain_error == 0) { - return level; +// Returns an input volume in the [`min_input_volume`, `max_input_volume`] range +// that reduces `gain_error_db`, which is a gain error estimated when +// `input_volume` was applied, according to a fixed gain map. +int ComputeVolumeUpdate(int gain_error_db, + int input_volume, + int min_input_volume, + int max_input_volume) { + RTC_DCHECK_GE(input_volume, 0); + RTC_DCHECK_LE(input_volume, max_input_volume); + if (gain_error_db == 0) { + return input_volume; } - int new_level = level; - if (gain_error > 0) { - while (kGainMap[new_level] - kGainMap[level] < gain_error && - new_level < max_mic_level) { - ++new_level; + int new_volume = input_volume; + if (gain_error_db > 0) { + while (kGainMap[new_volume] - kGainMap[input_volume] < gain_error_db && + new_volume < max_input_volume) { + ++new_volume; } } else { - while (kGainMap[new_level] - kGainMap[level] > gain_error && - new_level > min_mic_level) { - --new_level; + while (kGainMap[new_volume] - kGainMap[input_volume] > gain_error_db && + new_volume > min_input_volume) { + --new_volume; } } - return new_level; + return new_volume; } float ComputeCrestFactor(const ClippingPredictorLevelBuffer::Level& level) { @@ -298,8 +299,8 @@ class ClippingPeakPredictor : public ClippingPredictor { rtc::SafeClamp(-static_cast(std::ceil(estimate_db.value())), -kClippingPredictorMaxGainChange, 0); step = - std::max(level - LevelFromGainError(estimated_gain_change, level, - min_mic_level, max_mic_level), + std::max(level - ComputeVolumeUpdate(estimated_gain_change, level, + min_mic_level, max_mic_level), default_step); } const int new_level = @@ -354,10 +355,10 @@ std::unique_ptr CreateClippingPredictor( const AudioProcessing::Config::GainController1::AnalogGainController:: ClippingPredictor& config) { if (!config.enabled) { - RTC_LOG(LS_INFO) << "[agc] Clipping prediction disabled."; + RTC_LOG(LS_INFO) << "[AGC2] Clipping prediction disabled."; return nullptr; } - RTC_LOG(LS_INFO) << "[agc] Clipping prediction enabled."; + RTC_LOG(LS_INFO) << "[AGC2] Clipping prediction enabled."; using ClippingPredictorMode = AudioProcessing::Config::GainController1:: AnalogGainController::ClippingPredictor::Mode; switch (config.mode) { diff --git a/modules/audio_processing/agc2/gain_map_internal.h b/modules/audio_processing/agc2/gain_map_internal.h index 75e421899f..7c669fc9dd 100644 --- a/modules/audio_processing/agc2/gain_map_internal.h +++ b/modules/audio_processing/agc2/gain_map_internal.h @@ -13,8 +13,14 @@ namespace webrtc { -static const int kGainMapSize = 256; -// Uses parameters: si = 2, sf = 0.25, D = 8/256 +static constexpr int kGainMapSize = 256; +// Maps input volumes, which are values in the [0, 255] range, to gains in dB. +// The values below are generated with numpy as follows: +// SI = 2 # Initial slope. +// SF = 0.25 # Final slope. +// D = 8/256 # Quantization factor. +// x = np.linspace(0, 255, 256) # Input volumes. +// y = (SF * x + (SI - SF) * (1 - np.exp(-D*x)) / D - 56).round() static const int kGainMap[kGainMapSize] = { -56, -54, -52, -50, -48, -47, -45, -43, -42, -40, -38, -37, -35, -34, -33, -31, -30, -29, -27, -26, -25, -24, -23, -22, -20, -19, -18, -17, -16, -15, diff --git a/modules/audio_processing/agc2/input_volume_controller.cc b/modules/audio_processing/agc2/input_volume_controller.cc index d82d15c342..61b26bb3f1 100644 --- a/modules/audio_processing/agc2/input_volume_controller.cc +++ b/modules/audio_processing/agc2/input_volume_controller.cc @@ -26,15 +26,16 @@ namespace webrtc { namespace { -// Amount of error we tolerate in the microphone level (presumably due to OS -// quantization) before we assume the user has manually adjusted the microphone. -constexpr int kLevelQuantizationSlack = 25; +// Amount of error we tolerate in the microphone input volume (presumably due to +// OS quantization) before we assume the user has manually adjusted the volume. +constexpr int kVolumeQuantizationSlack = 25; -constexpr int kMaxMicLevel = 255; -static_assert(kGainMapSize > kMaxMicLevel, "gain map too small"); +constexpr int kMaxInputVolume = 255; +static_assert(kGainMapSize > kMaxInputVolume, "gain map too small"); -// Prevent very large microphone level changes. -constexpr int kMaxResidualGainChange = 15; +// Maximum absolute RMS error. +constexpr int KMaxAbsRmsErrorDbfs = 15; +static_assert(KMaxAbsRmsErrorDbfs > 0, ""); using Agc1ClippingPredictorConfig = AudioProcessing::Config::GainController1:: AnalogGainController::ClippingPredictor; @@ -66,30 +67,36 @@ int GetMinInputVolume() { if (min_input_volume >= 0 && min_input_volume <= 255) { return min_input_volume; } - RTC_LOG(LS_WARNING) << "Invalid volume for " << kFieldTrial << ", ignored."; + RTC_LOG(LS_WARNING) << "[AGC2] Invalid volume for " << kFieldTrial + << ", ignored."; return kDefaultMinInputVolume; } -int LevelFromGainError(int gain_error, int level, int min_input_volume) { - RTC_DCHECK_GE(level, 0); - RTC_DCHECK_LE(level, kMaxMicLevel); - if (gain_error == 0) { - return level; +// Returns an input volume in the [`min_input_volume`, `kMaxInputVolume`] range +// that reduces `gain_error_db`, which is a gain error estimated when +// `input_volume` was applied, according to a fixed gain map. +int ComputeVolumeUpdate(int gain_error_db, + int input_volume, + int min_input_volume) { + RTC_DCHECK_GE(input_volume, 0); + RTC_DCHECK_LE(input_volume, kMaxInputVolume); + if (gain_error_db == 0) { + return input_volume; } - int new_level = level; - if (gain_error > 0) { - while (kGainMap[new_level] - kGainMap[level] < gain_error && - new_level < kMaxMicLevel) { - ++new_level; + int new_volume = input_volume; + if (gain_error_db > 0) { + while (kGainMap[new_volume] - kGainMap[input_volume] < gain_error_db && + new_volume < kMaxInputVolume) { + ++new_volume; } } else { - while (kGainMap[new_level] - kGainMap[level] > gain_error && - new_level > min_input_volume) { - --new_level; + while (kGainMap[new_volume] - kGainMap[input_volume] > gain_error_db && + new_volume > min_input_volume) { + --new_volume; } } - return new_level; + return new_volume; } // Returns the proportion of samples in the buffer which are at full-scale @@ -113,59 +120,58 @@ float ComputeClippedRatio(const float* const* audio, } void LogClippingMetrics(int clipping_rate) { - RTC_LOG(LS_INFO) << "Input clipping rate: " << clipping_rate << "%"; + RTC_LOG(LS_INFO) << "[AGC2] Input clipping rate: " << clipping_rate << "%"; RTC_HISTOGRAM_COUNTS_LINEAR(/*name=*/"WebRTC.Audio.Agc.InputClippingRate", /*sample=*/clipping_rate, /*min=*/0, /*max=*/100, /*bucket_count=*/50); } -// Computes the speech level error in dB. The value of `speech_level_dbfs` is -// required to be in the range [-90.0f, 30.0f]. Returns a positive value when -// the speech level is below the target range and a negative value when the -// speech level is above the target range. -int GetSpeechLevelErrorDb(float speech_level_dbfs, - int target_range_min_dbfs, - int target_range_max_dbfs) { +// Compares `speech_level_dbfs` to the [`target_range_min_dbfs`, +// `target_range_max_dbfs`] range and returns the error to be compensated via +// input volume adjustment. Returns a positive value when the level is below +// the range, a negative value when the level is above the range, zero +// otherwise. +int GetSpeechLevelRmsErrorDb(float speech_level_dbfs, + int target_range_min_dbfs, + int target_range_max_dbfs) { constexpr float kMinSpeechLevelDbfs = -90.0f; constexpr float kMaxSpeechLevelDbfs = 30.0f; RTC_DCHECK_GE(speech_level_dbfs, kMinSpeechLevelDbfs); RTC_DCHECK_LE(speech_level_dbfs, kMaxSpeechLevelDbfs); - - // Ensure the speech level is in the range [-90.0f, 30.0f]. speech_level_dbfs = rtc::SafeClamp( speech_level_dbfs, kMinSpeechLevelDbfs, kMaxSpeechLevelDbfs); - // Compute the speech level distance to the target range - // [`target_range_min_dbfs`, `target_range_max_dbfs`]. - int rms_error_dbfs = 0; + int rms_error_db = 0; if (speech_level_dbfs > target_range_max_dbfs) { - rms_error_dbfs = std::round(target_range_max_dbfs - speech_level_dbfs); + rms_error_db = std::round(target_range_max_dbfs - speech_level_dbfs); } else if (speech_level_dbfs < target_range_min_dbfs) { - rms_error_dbfs = std::round(target_range_min_dbfs - speech_level_dbfs); + rms_error_db = std::round(target_range_min_dbfs - speech_level_dbfs); } - return rms_error_dbfs; + return rms_error_db; } } // namespace MonoInputVolumeController::MonoInputVolumeController( - int clipped_level_min, + int min_input_volume_after_clipping, int min_input_volume, int update_input_volume_wait_frames, float speech_probability_threshold, float speech_ratio_threshold) : min_input_volume_(min_input_volume), - max_level_(kMaxMicLevel), - clipped_level_min_(clipped_level_min), + min_input_volume_after_clipping_(min_input_volume_after_clipping), + max_input_volume_(kMaxInputVolume), update_input_volume_wait_frames_( std::max(update_input_volume_wait_frames, 1)), speech_probability_threshold_(speech_probability_threshold), speech_ratio_threshold_(speech_ratio_threshold) { - RTC_DCHECK_GE(clipped_level_min_, 0); - RTC_DCHECK_LE(clipped_level_min_, 255); RTC_DCHECK_GE(min_input_volume_, 0); RTC_DCHECK_LE(min_input_volume_, 255); + RTC_DCHECK_GE(min_input_volume_after_clipping_, 0); + RTC_DCHECK_LE(min_input_volume_after_clipping_, 255); + RTC_DCHECK_GE(max_input_volume_, 0); + RTC_DCHECK_LE(max_input_volume_, 255); RTC_DCHECK_GE(update_input_volume_wait_frames_, 0); RTC_DCHECK_GE(speech_probability_threshold_, 0.0f); RTC_DCHECK_LE(speech_probability_threshold_, 1.0f); @@ -176,7 +182,7 @@ MonoInputVolumeController::MonoInputVolumeController( MonoInputVolumeController::~MonoInputVolumeController() = default; void MonoInputVolumeController::Initialize() { - max_level_ = kMaxMicLevel; + max_input_volume_ = kMaxInputVolume; capture_output_used_ = true; check_volume_on_next_process_ = true; frames_since_update_input_volume_ = 0; @@ -189,7 +195,7 @@ void MonoInputVolumeController::Initialize() { // previous update and the ratio of non-silence frames (i.e., frames with a // `speech_probability` higher than `speech_probability_threshold_`) is at least // `speech_ratio_threshold_`. -void MonoInputVolumeController::Process(absl::optional rms_error_dbfs, +void MonoInputVolumeController::Process(absl::optional rms_error_db, float speech_probability) { if (check_volume_on_next_process_) { check_volume_on_next_process_ = false; @@ -216,8 +222,8 @@ void MonoInputVolumeController::Process(absl::optional rms_error_dbfs, // Update the input volume if allowed. if (!is_first_frame_ && speech_ratio >= speech_ratio_threshold_) { - if (rms_error_dbfs.has_value()) { - UpdateInputVolume(*rms_error_dbfs); + if (rms_error_db.has_value()) { + UpdateInputVolume(*rms_error_db); } } } @@ -227,50 +233,53 @@ void MonoInputVolumeController::Process(absl::optional rms_error_dbfs, void MonoInputVolumeController::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)); + // Always decrease the maximum input volume, even if the current input volume + // is below threshold. + SetMaxLevel(std::max(min_input_volume_after_clipping_, + max_input_volume_ - clipped_level_step)); if (log_to_histograms_) { - RTC_HISTOGRAM_BOOLEAN("WebRTC.Audio.AgcClippingAdjustmentAllowed", - level_ - clipped_level_step >= clipped_level_min_); + RTC_HISTOGRAM_BOOLEAN( + "WebRTC.Audio.AgcClippingAdjustmentAllowed", + input_volume_ - clipped_level_step >= min_input_volume_after_clipping_); } - if (level_ > clipped_level_min_) { - // Don't try to adjust the level if we're already below the limit. As - // a consequence, if the user has brought the level above the limit, we - // will still not react until the postproc updates the level. - SetLevel(std::max(clipped_level_min_, level_ - clipped_level_step)); + if (input_volume_ > min_input_volume_after_clipping_) { + // Don't try to adjust the input volume if we're already below the limit. As + // a consequence, if the user has brought the input volume above the limit, + // we will still not react until the postproc updates the input volume. + SetInputVolume(std::max(min_input_volume_after_clipping_, + input_volume_ - clipped_level_step)); frames_since_update_input_volume_ = 0; speech_frames_since_update_input_volume_ = 0; is_first_frame_ = false; } } -void MonoInputVolumeController::SetLevel(int new_level) { - int voe_level = recommended_input_volume_; - if (voe_level == 0) { +void MonoInputVolumeController::SetInputVolume(int new_volume) { + int applied_input_volume = recommended_input_volume_; + if (applied_input_volume == 0) { RTC_DLOG(LS_INFO) - << "[agc] VolumeCallbacks returned level=0, taking no action."; + << "[AGC2] The applied input volume is zero, taking no action."; return; } - if (voe_level < 0 || voe_level > kMaxMicLevel) { - RTC_LOG(LS_ERROR) << "VolumeCallbacks returned an invalid level=" - << voe_level; + if (applied_input_volume < 0 || applied_input_volume > kMaxInputVolume) { + RTC_LOG(LS_ERROR) << "[AGC2] Invalid value for the applied input volume: " + << applied_input_volume; return; } - // Detect manual input volume adjustments by checking if the current level - // `voe_level` is outside of the `[level_ - kLevelQuantizationSlack, level_ + - // kLevelQuantizationSlack]` range where `level_` is the last input volume - // known by this gain controller. - if (voe_level > level_ + kLevelQuantizationSlack || - voe_level < level_ - kLevelQuantizationSlack) { - RTC_DLOG(LS_INFO) << "[agc] Mic volume was manually adjusted. Updating " - "stored level from " - << level_ << " to " << voe_level; - level_ = voe_level; + // Detect manual input volume adjustments by checking if the + // `applied_input_volume` is outside of the `[input_volume_ - + // kVolumeQuantizationSlack, input_volume_ + kVolumeQuantizationSlack]` range. + if (applied_input_volume > input_volume_ + kVolumeQuantizationSlack || + applied_input_volume < input_volume_ - kVolumeQuantizationSlack) { + RTC_DLOG(LS_INFO) + << "[AGC2] The input volume was manually adjusted. Updating " + "stored input volume from " + << input_volume_ << " to " << applied_input_volume; + input_volume_ = applied_input_volume; // Always allow the user to increase the volume. - if (level_ > max_level_) { - SetMaxLevel(level_); + if (input_volume_ > max_input_volume_) { + SetMaxLevel(input_volume_); } // Take no action in this case, since we can't be sure when the volume // was manually adjusted. @@ -280,21 +289,23 @@ void MonoInputVolumeController::SetLevel(int new_level) { return; } - new_level = std::min(new_level, max_level_); - if (new_level == level_) { + new_volume = std::min(new_volume, max_input_volume_); + if (new_volume == input_volume_) { return; } - recommended_input_volume_ = new_level; - RTC_DLOG(LS_INFO) << "[agc] voe_level=" << voe_level << ", level_=" << level_ - << ", new_level=" << new_level; - level_ = new_level; + recommended_input_volume_ = new_volume; + RTC_DLOG(LS_INFO) << "[AGC2] Applied input volume: " << applied_input_volume + << " | last recommended input volume: " << input_volume_ + << " | newly recommended input volume: " << new_volume; + input_volume_ = new_volume; } -void MonoInputVolumeController::SetMaxLevel(int level) { - RTC_DCHECK_GE(level, clipped_level_min_); - max_level_ = level; - RTC_DLOG(LS_INFO) << "[agc] max_level_=" << max_level_; +void MonoInputVolumeController::SetMaxLevel(int input_volume) { + RTC_DCHECK_GE(input_volume, min_input_volume_after_clipping_); + max_input_volume_ = input_volume; + RTC_DLOG(LS_INFO) << "[AGC2] Maximum input volume updated: " + << max_input_volume_; } void MonoInputVolumeController::HandleCaptureOutputUsedChange( @@ -311,30 +322,32 @@ void MonoInputVolumeController::HandleCaptureOutputUsedChange( } int MonoInputVolumeController::CheckVolumeAndReset() { - int level = recommended_input_volume_; + int input_volume = 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 - // AGC can do its job properly. - if (level == 0 && !startup_) { + // 2) Independent of interpretation of `input_volume` == 0 we should raise it + // so the AGC can do its job properly. + if (input_volume == 0 && !startup_) { RTC_DLOG(LS_INFO) - << "[agc] VolumeCallbacks returned level=0, taking no action."; + << "[AGC2] The applied input volume is zero, taking no action."; return 0; } - if (level < 0 || level > kMaxMicLevel) { - RTC_LOG(LS_ERROR) << "[agc] VolumeCallbacks returned an invalid level=" - << level; + if (input_volume < 0 || input_volume > kMaxInputVolume) { + RTC_LOG(LS_ERROR) << "[AGC2] Invalid value for the applied input volume: " + << input_volume; return -1; } - RTC_DLOG(LS_INFO) << "[agc] Initial GetMicVolume()=" << level; + RTC_DLOG(LS_INFO) << "[AGC2] Initial input volume: " << input_volume; - if (level < min_input_volume_) { - level = min_input_volume_; - RTC_DLOG(LS_INFO) << "[agc] Initial volume too low, raising to " << level; - recommended_input_volume_ = level; + if (input_volume < min_input_volume_) { + input_volume = min_input_volume_; + RTC_DLOG(LS_INFO) + << "[AGC2] The initial input volume is too low, raising to " + << input_volume; + recommended_input_volume_ = input_volume; } - level_ = level; + input_volume_ = input_volume; startup_ = false; frames_since_update_input_volume_ = 0; speech_frames_since_update_input_volume_ = 0; @@ -343,18 +356,17 @@ int MonoInputVolumeController::CheckVolumeAndReset() { return 0; } -void MonoInputVolumeController::UpdateInputVolume(int rms_error_dbfs) { - const int residual_gain = rtc::SafeClamp( - rms_error_dbfs, -kMaxResidualGainChange, kMaxResidualGainChange); - - RTC_DLOG(LS_INFO) << "[agc] rms_error_dbfs=" << rms_error_dbfs - << ", residual_gain=" << residual_gain; - - if (residual_gain == 0) { +void MonoInputVolumeController::UpdateInputVolume(int rms_error_db) { + RTC_DLOG(LS_INFO) << "[AGC2] RMS error: " << rms_error_db << " dB"; + // Prevent too large microphone input volume changes by clamping the RMS + // error. + rms_error_db = + rtc::SafeClamp(rms_error_db, -KMaxAbsRmsErrorDbfs, KMaxAbsRmsErrorDbfs); + if (rms_error_db == 0) { return; } - - SetLevel(LevelFromGainError(residual_gain, level_, min_input_volume_)); + SetInputVolume( + ComputeVolumeUpdate(rms_error_db, input_volume_, min_input_volume_)); } InputVolumeController::InputVolumeController(int num_capture_channels, @@ -379,8 +391,9 @@ InputVolumeController::InputVolumeController(int num_capture_channels, target_range_min_dbfs_(config.target_range_min_dbfs), channel_controllers_(num_capture_channels) { RTC_LOG(LS_INFO) - << "[agc] Input volume controller enabled (min input volume: " - << min_input_volume_ << ")"; + << "[AGC2] Input volume controller enabled. Minimum input volume: " + << min_input_volume_; + for (auto& controller : channel_controllers_) { controller = std::make_unique( config.clipped_level_min, min_input_volume_, @@ -400,7 +413,6 @@ InputVolumeController::InputVolumeController(int num_capture_channels, InputVolumeController::~InputVolumeController() {} void InputVolumeController::Initialize() { - RTC_DLOG(LS_INFO) << "InputVolumeController::Initialize"; for (auto& controller : channel_controllers_) { controller->Initialize(); } @@ -430,10 +442,10 @@ void InputVolumeController::AnalyzePreProcess(const AudioBuffer& audio_buffer) { // Check for clipped samples. We do this in the preprocessing phase in order // to catch clipped echo as well. // - // If we find a sufficiently clipped frame, drop the current microphone level - // and enforce a new maximum level, dropped the same amount from the current - // maximum. This harsh treatment is an effort to avoid repeated clipped echo - // events. + // If we find a sufficiently clipped frame, drop the current microphone + // input volume and enforce a new maximum input volume, dropped the same + // amount from the current maximum. This harsh treatment is an effort to avoid + // repeated clipped echo events. float clipped_ratio = ComputeClippedRatio(audio, num_capture_channels_, samples_per_channel); clipping_rate_log_ = std::max(clipped_ratio, clipping_rate_log_); @@ -457,7 +469,8 @@ void InputVolumeController::AnalyzePreProcess(const AudioBuffer& audio_buffer) { for (int channel = 0; channel < num_capture_channels_; ++channel) { const auto step = clipping_predictor_->EstimateClippedLevelStep( channel, recommended_input_volume_, clipped_level_step_, - channel_controllers_[channel]->clipped_level_min(), kMaxMicLevel); + channel_controllers_[channel]->min_input_volume_after_clipping(), + kMaxInputVolume); if (step.has_value()) { predicted_step = std::max(predicted_step, step.value()); clipping_predicted = true; @@ -466,14 +479,15 @@ void InputVolumeController::AnalyzePreProcess(const AudioBuffer& audio_buffer) { } if (clipping_detected) { - RTC_DLOG(LS_INFO) << "[agc] Clipping detected. clipped_ratio=" - << clipped_ratio; + RTC_DLOG(LS_INFO) << "[AGC2] Clipping detected (ratio: " << clipped_ratio + << ")"; } int step = clipped_level_step_; if (clipping_predicted) { predicted_step = std::max(predicted_step, clipped_level_step_); - RTC_DLOG(LS_INFO) << "[agc] Clipping predicted. step=" << predicted_step; + RTC_DLOG(LS_INFO) << "[AGC2] Clipping predicted (volume down step: " + << predicted_step << ")"; if (use_clipping_predictor_step_) { step = predicted_step; } @@ -501,15 +515,15 @@ void InputVolumeController::Process(float speech_probability, return; } - absl::optional rms_error_dbfs; + absl::optional rms_error_db; if (speech_level_dbfs.has_value()) { // Compute the error for all frames (both speech and non-speech frames). - rms_error_dbfs = GetSpeechLevelErrorDb( + rms_error_db = GetSpeechLevelRmsErrorDb( *speech_level_dbfs, target_range_min_dbfs_, target_range_max_dbfs_); } for (auto& controller : channel_controllers_) { - controller->Process(rms_error_dbfs, speech_probability); + controller->Process(rms_error_db, speech_probability); } AggregateChannelLevels(); @@ -524,9 +538,9 @@ void InputVolumeController::HandleCaptureOutputUsedChange( capture_output_used_ = capture_output_used; } -void InputVolumeController::set_stream_analog_level(int level) { +void InputVolumeController::set_stream_analog_level(int input_volume) { for (auto& controller : channel_controllers_) { - controller->set_stream_analog_level(level); + controller->set_stream_analog_level(input_volume); } AggregateChannelLevels(); @@ -537,13 +551,14 @@ void InputVolumeController::AggregateChannelLevels() { channel_controllers_[0]->recommended_analog_level(); channel_controlling_gain_ = 0; for (size_t ch = 1; ch < channel_controllers_.size(); ++ch) { - int level = channel_controllers_[ch]->recommended_analog_level(); - if (level < new_recommended_input_volume) { - new_recommended_input_volume = level; + int input_volume = channel_controllers_[ch]->recommended_analog_level(); + if (input_volume < new_recommended_input_volume) { + new_recommended_input_volume = input_volume; channel_controlling_gain_ = static_cast(ch); } } + // Enforce the minimum input volume when a recommendation is made. if (new_recommended_input_volume > 0) { new_recommended_input_volume = std::max(new_recommended_input_volume, min_input_volume_); diff --git a/modules/audio_processing/agc2/input_volume_controller.h b/modules/audio_processing/agc2/input_volume_controller.h index e898ba0e34..6f836d4834 100644 --- a/modules/audio_processing/agc2/input_volume_controller.h +++ b/modules/audio_processing/agc2/input_volume_controller.h @@ -126,16 +126,13 @@ class InputVolumeController final { private: friend class InputVolumeControllerTestHelper; + FRIEND_TEST_ALL_PREFIXES(InputVolumeControllerTest, MinInputVolumeDefault); + FRIEND_TEST_ALL_PREFIXES(InputVolumeControllerTest, MinInputVolumeDisabled); FRIEND_TEST_ALL_PREFIXES(InputVolumeControllerTest, - AgcMinMicLevelExperimentDefault); + MinInputVolumeOutOfRangeAbove); FRIEND_TEST_ALL_PREFIXES(InputVolumeControllerTest, - AgcMinMicLevelExperimentDisabled); - FRIEND_TEST_ALL_PREFIXES(InputVolumeControllerTest, - AgcMinMicLevelExperimentOutOfRangeAbove); - FRIEND_TEST_ALL_PREFIXES(InputVolumeControllerTest, - AgcMinMicLevelExperimentOutOfRangeBelow); - FRIEND_TEST_ALL_PREFIXES(InputVolumeControllerTest, - AgcMinMicLevelExperimentEnabled50); + MinInputVolumeOutOfRangeBelow); + FRIEND_TEST_ALL_PREFIXES(InputVolumeControllerTest, MinInputVolumeEnabled50); FRIEND_TEST_ALL_PREFIXES(InputVolumeControllerParametrizedTest, ClippingParametersVerified); @@ -184,8 +181,8 @@ class InputVolumeController final { // convention. class MonoInputVolumeController { public: - MonoInputVolumeController(int clipped_level_min, - int min_mic_level, + MonoInputVolumeController(int min_input_volume_after_clipping, + int min_input_volume, int update_input_volume_wait_frames, float speech_probability_threshold, float speech_ratio_threshold); @@ -198,7 +195,9 @@ class MonoInputVolumeController { void HandleCaptureOutputUsedChange(bool capture_output_used); // Sets the current input volume. - void set_stream_analog_level(int level) { recommended_input_volume_ = level; } + void set_stream_analog_level(int input_volume) { + recommended_input_volume_ = input_volume; + } // Lowers the recommended input volume in response to clipping based on the // suggested reduction `clipped_level_step`. Must be called after @@ -217,7 +216,9 @@ class MonoInputVolumeController { void ActivateLogging() { log_to_histograms_ = true; } - int clipped_level_min() const { return clipped_level_min_; } + int min_input_volume_after_clipping() const { + return min_input_volume_after_clipping_; + } // Only used for testing. int min_input_volume() const { return min_input_volume_; } @@ -225,7 +226,7 @@ class MonoInputVolumeController { private: // 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); + void SetInputVolume(int new_volume); // Sets the maximum input volume that the input volume controller is allowed // to apply. The volume must be at least `kClippedLevelMin`. @@ -239,9 +240,11 @@ class MonoInputVolumeController { void UpdateInputVolume(int rms_error_dbfs); const int min_input_volume_; + const int min_input_volume_after_clipping_; + int max_input_volume_; - int level_ = 0; - int max_level_; + // Last recommended input volume. + int input_volume_ = 0; bool capture_output_used_ = true; bool check_volume_on_next_process_ = true; @@ -257,8 +260,6 @@ class MonoInputVolumeController { bool log_to_histograms_ = false; - const int clipped_level_min_; - // Counters for frames and speech frames since the last update in the // recommended input volume. const int update_input_volume_wait_frames_; diff --git a/modules/audio_processing/agc2/input_volume_controller_unittest.cc b/modules/audio_processing/agc2/input_volume_controller_unittest.cc index f950e611de..7a2191a838 100644 --- a/modules/audio_processing/agc2/input_volume_controller_unittest.cc +++ b/modules/audio_processing/agc2/input_volume_controller_unittest.cc @@ -382,8 +382,7 @@ class InputVolumeControllerParametrizedTest InputVolumeControllerParametrizedTest() : field_trials_(GetAgcMinInputVolumeFieldTrial(GetParam())) {} - bool IsMinMicLevelOverridden() const { return GetParam().has_value(); } - int GetMinMicLevel() const { return GetParam().value_or(kMinMicLevel); } + int GetMinInputVolume() const { return GetParam().value_or(kMinMicLevel); } private: test::ScopedFieldTrials field_trials_; @@ -416,10 +415,10 @@ TEST_P(InputVolumeControllerParametrizedTest, MicVolumeResponseToRmsError) { // Above the digital gain's window; volume should be increased. helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -29.0f); - EXPECT_EQ(128, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 128); helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -38.0f); - EXPECT_EQ(156, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 156); // Inside the digital gain's window; no change of volume. helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -23.0f); @@ -427,13 +426,13 @@ TEST_P(InputVolumeControllerParametrizedTest, MicVolumeResponseToRmsError) { // Below the digial gain's window; volume should be decreased. helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -17.0f); - EXPECT_EQ(155, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 155); helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -17.0f); - EXPECT_EQ(151, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 151); helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -9.0f); - EXPECT_EQ(119, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 119); } TEST_P(InputVolumeControllerParametrizedTest, MicVolumeIsLimited) { @@ -443,42 +442,42 @@ TEST_P(InputVolumeControllerParametrizedTest, MicVolumeIsLimited) { // Maximum upwards change is limited. helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -48.0f); - EXPECT_EQ(183, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 183); helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -48.0f); - EXPECT_EQ(243, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 243); // Won't go higher than the maximum. helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -48.0f); - EXPECT_EQ(255, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 255); helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -17.0f); - EXPECT_EQ(254, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 254); // Maximum downwards change is limited. helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, 22.0f); - EXPECT_EQ(194, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 194); helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, 22.0f); - EXPECT_EQ(137, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 137); helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, 22.0f); - EXPECT_EQ(88, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 88); helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, 22.0f); - EXPECT_EQ(54, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 54); helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, 22.0f); - EXPECT_EQ(33, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 33); // Won't go lower than the minimum. helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, 22.0f); - EXPECT_EQ(std::max(18, GetMinMicLevel()), - helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), + std::max(18, GetMinInputVolume())); helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, 22.0f); - EXPECT_EQ(std::max(12, GetMinMicLevel()), - helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), + std::max(12, GetMinInputVolume())); } TEST_P(InputVolumeControllerParametrizedTest, NoActionWhileMuted) { @@ -504,7 +503,7 @@ TEST_P(InputVolumeControllerParametrizedTest, // SetMicVolume should not be called. helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, kSpeechLevel); - EXPECT_EQ(127, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 127); } TEST_P(InputVolumeControllerParametrizedTest, UnmutingRaisesTooLowVolume) { @@ -519,7 +518,7 @@ TEST_P(InputVolumeControllerParametrizedTest, UnmutingRaisesTooLowVolume) { helper.manager.set_stream_analog_level(kInputVolume); helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, kSpeechLevel); - EXPECT_EQ(GetMinMicLevel(), helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), GetMinInputVolume()); } TEST_P(InputVolumeControllerParametrizedTest, @@ -533,16 +532,16 @@ TEST_P(InputVolumeControllerParametrizedTest, ASSERT_NE(helper.manager.recommended_analog_level(), 154); helper.manager.set_stream_analog_level(154); helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -29.0f); - EXPECT_EQ(154, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 154); // Do the same thing, except downwards now. helper.manager.set_stream_analog_level(100); helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -17.0f); - EXPECT_EQ(100, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 100); // And finally verify the AGC continues working without a manual change. helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -17.0f); - EXPECT_EQ(99, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 99); } TEST_P(InputVolumeControllerParametrizedTest, @@ -554,21 +553,21 @@ TEST_P(InputVolumeControllerParametrizedTest, // Force the mic up to max volume. Takes a few steps due to the residual // gain limitation. helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -48.0f); - EXPECT_EQ(183, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 183); helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -48.0f); - EXPECT_EQ(243, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 243); helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -48.0f); - EXPECT_EQ(255, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 255); // Manual change does not result in SetMicVolume call. helper.manager.set_stream_analog_level(50); helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -17.0f); - EXPECT_EQ(50, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 50); // Continues working as usual afterwards. helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -38.0f); - EXPECT_EQ(65, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 65); } // Checks that the minimum input volume is enforced during the upward adjustment @@ -585,16 +584,16 @@ TEST_P(InputVolumeControllerParametrizedTest, helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -17.0f); // Trigger an upward adjustment of the input volume. - EXPECT_EQ(helper.manager.recommended_analog_level(), GetMinMicLevel()); + EXPECT_EQ(helper.manager.recommended_analog_level(), GetMinInputVolume()); helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -29.0f); - EXPECT_EQ(helper.manager.recommended_analog_level(), GetMinMicLevel()); + EXPECT_EQ(helper.manager.recommended_analog_level(), GetMinInputVolume()); helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -48.0f); - EXPECT_EQ(helper.manager.recommended_analog_level(), GetMinMicLevel()); + EXPECT_EQ(helper.manager.recommended_analog_level(), GetMinInputVolume()); // After a number of consistently low speech level observations, the input // volume is eventually raised above the minimum. helper.CallProcess(/*num_calls=*/10, kHighSpeechProbability, -38.0f); - EXPECT_GT(helper.manager.recommended_analog_level(), GetMinMicLevel()); + EXPECT_GT(helper.manager.recommended_analog_level(), GetMinInputVolume()); } // Checks that, when the min mic level override is specified, AGC immediately @@ -610,7 +609,7 @@ TEST_P(InputVolumeControllerParametrizedTest, // AGC won't take any action. helper.manager.set_stream_analog_level(1); helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -17.0f); - EXPECT_EQ(GetMinMicLevel(), helper.manager.recommended_analog_level()); + EXPECT_EQ(GetMinInputVolume(), helper.manager.recommended_analog_level()); } TEST_P(InputVolumeControllerParametrizedTest, NoClippingHasNoImpact) { @@ -619,7 +618,7 @@ TEST_P(InputVolumeControllerParametrizedTest, NoClippingHasNoImpact) { kSpeechLevel); helper.CallPreProc(/*num_calls=*/100, /*clipped_ratio=*/0); - EXPECT_EQ(128, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 128); } TEST_P(InputVolumeControllerParametrizedTest, @@ -629,7 +628,7 @@ TEST_P(InputVolumeControllerParametrizedTest, kSpeechLevel); helper.CallPreProc(/*num_calls=*/1, /*clipped_ratio=*/0.099); - EXPECT_EQ(128, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 128); } TEST_P(InputVolumeControllerParametrizedTest, ClippingLowersVolume) { @@ -638,7 +637,7 @@ TEST_P(InputVolumeControllerParametrizedTest, ClippingLowersVolume) { kSpeechLevel); helper.CallPreProc(/*num_calls=*/1, /*clipped_ratio=*/0.2); - EXPECT_EQ(240, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 240); } TEST_P(InputVolumeControllerParametrizedTest, @@ -648,14 +647,14 @@ TEST_P(InputVolumeControllerParametrizedTest, kSpeechLevel); helper.CallPreProc(/*num_calls=*/1, /*clipped_ratio=*/kAboveClippedThreshold); - EXPECT_EQ(240, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 240); helper.CallPreProc(/*num_calls=*/300, /*clipped_ratio=*/kAboveClippedThreshold); - EXPECT_EQ(240, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 240); helper.CallPreProc(/*num_calls=*/1, /*clipped_ratio=*/kAboveClippedThreshold); - EXPECT_EQ(225, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 225); } TEST_P(InputVolumeControllerParametrizedTest, ClippingLoweringIsLimited) { @@ -664,11 +663,11 @@ TEST_P(InputVolumeControllerParametrizedTest, ClippingLoweringIsLimited) { kSpeechLevel); helper.CallPreProc(/*num_calls=*/1, /*clipped_ratio=*/kAboveClippedThreshold); - EXPECT_EQ(kClippedMin, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), kClippedMin); helper.CallPreProc(/*num_calls=*/1000, /*clipped_ratio=*/kAboveClippedThreshold); - EXPECT_EQ(kClippedMin, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), kClippedMin); } TEST_P(InputVolumeControllerParametrizedTest, @@ -678,10 +677,10 @@ TEST_P(InputVolumeControllerParametrizedTest, kSpeechLevel); helper.CallPreProc(/*num_calls=*/1, /*clipped_ratio=*/kAboveClippedThreshold); - EXPECT_EQ(240, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 240); helper.CallProcess(/*num_calls=*/10, kHighSpeechProbability, -48.0f); - EXPECT_EQ(240, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 240); } TEST_P(InputVolumeControllerParametrizedTest, @@ -691,12 +690,12 @@ TEST_P(InputVolumeControllerParametrizedTest, kSpeechLevel); helper.CallPreProc(/*num_calls=*/1, /*clipped_ratio=*/kAboveClippedThreshold); - EXPECT_EQ(185, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 185); helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -58.0f); - EXPECT_EQ(240, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 240); helper.CallProcess(/*num_calls=*/10, kHighSpeechProbability, -58.0f); - EXPECT_EQ(240, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 240); } TEST_P(InputVolumeControllerParametrizedTest, UserCanRaiseVolumeAfterClipping) { @@ -705,22 +704,22 @@ TEST_P(InputVolumeControllerParametrizedTest, UserCanRaiseVolumeAfterClipping) { kSpeechLevel); helper.CallPreProc(/*num_calls=*/1, /*clipped_ratio=*/kAboveClippedThreshold); - EXPECT_EQ(210, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 210); // User changed the volume. helper.manager.set_stream_analog_level(250); helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -32.0f); - EXPECT_EQ(250, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 250); // Move down... helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -8.0f); - EXPECT_EQ(210, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 210); // And back up to the new max established by the user. helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -58.0f); - EXPECT_EQ(250, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 250); // Will not move above new maximum. helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -48.0f); - EXPECT_EQ(250, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 250); } TEST_P(InputVolumeControllerParametrizedTest, @@ -741,7 +740,7 @@ TEST_P(InputVolumeControllerParametrizedTest, TakesNoActionOnZeroMicVolume) { helper.manager.set_stream_analog_level(0); helper.CallProcess(/*num_calls=*/10, kHighSpeechProbability, -48.0f); - EXPECT_EQ(0, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 0); } TEST_P(InputVolumeControllerParametrizedTest, ClippingDetectionLowersVolume) { @@ -749,11 +748,11 @@ TEST_P(InputVolumeControllerParametrizedTest, ClippingDetectionLowersVolume) { helper.CallAgcSequence(/*applied_input_volume=*/255, kHighSpeechProbability, kSpeechLevel); - EXPECT_EQ(255, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 255); helper.CallPreProcForChangingAudio(/*num_calls=*/100, /*peak_ratio=*/0.99f); - EXPECT_EQ(255, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 255); helper.CallPreProcForChangingAudio(/*num_calls=*/100, /*peak_ratio=*/1.0f); - EXPECT_EQ(240, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 240); } TEST_P(InputVolumeControllerParametrizedTest, @@ -763,20 +762,20 @@ TEST_P(InputVolumeControllerParametrizedTest, kSpeechLevel); EXPECT_FALSE(helper.manager.clipping_predictor_enabled()); - EXPECT_EQ(255, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 255); helper.CallPreProcForChangingAudio(/*num_calls=*/100, /*peak_ratio=*/0.99f); - EXPECT_EQ(255, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 255); helper.CallPreProcForChangingAudio(/*num_calls=*/100, /*peak_ratio=*/0.99f); - EXPECT_EQ(255, helper.manager.recommended_analog_level()); + EXPECT_EQ(helper.manager.recommended_analog_level(), 255); } -TEST(InputVolumeControllerTest, AgcMinMicLevelExperimentDefault) { +TEST(InputVolumeControllerTest, MinInputVolumeDefault) { std::unique_ptr manager = CreateInputVolumeController( kClippedLevelStep, kClippedRatioThreshold, kClippedWaitFrames); EXPECT_EQ(manager->channel_controllers_[0]->min_input_volume(), kMinMicLevel); } -TEST(InputVolumeControllerTest, AgcMinMicLevelExperimentDisabled) { +TEST(InputVolumeControllerTest, MinInputVolumeDisabled) { for (const std::string& field_trial_suffix : {"", "_20220210"}) { test::ScopedFieldTrials field_trial( GetAgcMinInputVolumeFieldTrial("Disabled" + field_trial_suffix)); @@ -791,7 +790,7 @@ TEST(InputVolumeControllerTest, AgcMinMicLevelExperimentDisabled) { // Checks that a field-trial parameter outside of the valid range [0,255] is // ignored. -TEST(InputVolumeControllerTest, AgcMinMicLevelExperimentOutOfRangeAbove) { +TEST(InputVolumeControllerTest, MinInputVolumeOutOfRangeAbove) { test::ScopedFieldTrials field_trial( GetAgcMinInputVolumeFieldTrial("Enabled-256")); std::unique_ptr manager = CreateInputVolumeController( @@ -801,7 +800,7 @@ TEST(InputVolumeControllerTest, AgcMinMicLevelExperimentOutOfRangeAbove) { // Checks that a field-trial parameter outside of the valid range [0,255] is // ignored. -TEST(InputVolumeControllerTest, AgcMinMicLevelExperimentOutOfRangeBelow) { +TEST(InputVolumeControllerTest, MinInputVolumeOutOfRangeBelow) { test::ScopedFieldTrials field_trial( GetAgcMinInputVolumeFieldTrial("Enabled--1")); std::unique_ptr manager = CreateInputVolumeController( @@ -812,27 +811,26 @@ TEST(InputVolumeControllerTest, AgcMinMicLevelExperimentOutOfRangeBelow) { // Verifies that a valid experiment changes the minimum microphone level. The // start volume is larger than the min level and should therefore not be // changed. -TEST(InputVolumeControllerTest, AgcMinMicLevelExperimentEnabled50) { - constexpr int kMinMicLevelOverride = 50; +TEST(InputVolumeControllerTest, MinInputVolumeEnabled50) { + constexpr int kMinInputVolume = 50; for (const std::string& field_trial_suffix : {"", "_20220210"}) { SCOPED_TRACE(field_trial_suffix); test::ScopedFieldTrials field_trial(GetAgcMinInputVolumeFieldTrialEnabled( - kMinMicLevelOverride, field_trial_suffix)); + kMinInputVolume, field_trial_suffix)); std::unique_ptr manager = CreateInputVolumeController(kClippedLevelStep, kClippedRatioThreshold, kClippedWaitFrames); EXPECT_EQ(manager->channel_controllers_[0]->min_input_volume(), - kMinMicLevelOverride); + kMinInputVolume); } } -// Checks that, when the "WebRTC-Audio-AgcMinMicLevelExperiment" field trial is +// Checks that, when the "WebRTC-Audio-Agc2-MinInputVolume" field trial is // specified with a valid value, the mic level never gets lowered beyond the // override value in the presence of clipping. -TEST(InputVolumeControllerTest, - AgcMinMicLevelExperimentCheckMinLevelWithClipping) { - constexpr int kMinMicLevelOverride = 250; +TEST(InputVolumeControllerTest, MinInputVolumeCheckMinLevelWithClipping) { + constexpr int kMinInputVolume = 250; // Create and initialize two AGCs by specifying and leaving unspecified the // relevant field trial. @@ -848,7 +846,7 @@ TEST(InputVolumeControllerTest, std::unique_ptr manager_with_override; { test::ScopedFieldTrials field_trial( - GetAgcMinInputVolumeFieldTrialEnabled(kMinMicLevelOverride)); + GetAgcMinInputVolumeFieldTrialEnabled(kMinInputVolume)); manager_with_override = factory(); } @@ -877,19 +875,18 @@ TEST(InputVolumeControllerTest, 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->recommended_analog_level(), - kMinMicLevelOverride); + EXPECT_EQ(manager_with_override->recommended_analog_level(), kMinInputVolume); } -// Checks that, when the "WebRTC-Audio-AgcMinMicLevelExperiment" field trial is +// Checks that, when the "WebRTC-Audio-Agc2-MinInputVolume" field trial is // specified with a valid value, the mic level never gets lowered beyond the // override value in the presence of clipping when RMS error is not empty. // TODO(webrtc:7494): Revisit the test after moving the number of update wait // frames to APM config. The test passes but internally the gain update timing // differs. TEST(InputVolumeControllerTest, - AgcMinMicLevelExperimentCheckMinLevelWithClippingWithRmsError) { - constexpr int kMinMicLevelOverride = 250; + MinInputVolumeCheckMinLevelWithClippingWithRmsError) { + constexpr int kMinInputVolume = 250; // Create and initialize two AGCs by specifying and leaving unspecified the // relevant field trial. @@ -905,7 +902,7 @@ TEST(InputVolumeControllerTest, std::unique_ptr manager_with_override; { test::ScopedFieldTrials field_trial( - GetAgcMinInputVolumeFieldTrialEnabled(kMinMicLevelOverride)); + GetAgcMinInputVolumeFieldTrialEnabled(kMinInputVolume)); manager_with_override = factory(); } @@ -933,16 +930,14 @@ TEST(InputVolumeControllerTest, 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->recommended_analog_level(), - kMinMicLevelOverride); + EXPECT_EQ(manager_with_override->recommended_analog_level(), kMinInputVolume); } -// Checks that, when the "WebRTC-Audio-AgcMinMicLevelExperiment" field trial is +// Checks that, when the "WebRTC-Audio-Agc2-MinInputVolume" field trial is // specified with a value lower than the `clipped_level_min`, the behavior of // the analog gain controller is the same as that obtained when the field trial // is not specified. -TEST(InputVolumeControllerTest, - AgcMinMicLevelExperimentCompareMicLevelWithClipping) { +TEST(InputVolumeControllerTest, MinInputVolumeCompareMicLevelWithClipping) { // Create and initialize two AGCs by specifying and leaving unspecified the // relevant field trial. const auto factory = []() { @@ -961,12 +956,12 @@ TEST(InputVolumeControllerTest, std::unique_ptr manager = factory(); std::unique_ptr manager_with_override; { - constexpr int kMinMicLevelOverride = 20; + constexpr int kMinInputVolume = 20; static_assert(kDefaultInputVolumeControllerConfig.clipped_level_min >= - kMinMicLevelOverride, + kMinInputVolume, "Use a lower override value."); test::ScopedFieldTrials field_trial( - GetAgcMinInputVolumeFieldTrialEnabled(kMinMicLevelOverride)); + GetAgcMinInputVolumeFieldTrialEnabled(kMinInputVolume)); manager_with_override = factory(); } @@ -999,7 +994,7 @@ TEST(InputVolumeControllerTest, kDefaultInputVolumeControllerConfig.clipped_level_min); } -// Checks that, when the "WebRTC-Audio-AgcMinMicLevelExperiment" field trial is +// Checks that, when the "WebRTC-Audio-Agc2-MinInputVolume" field trial is // specified with a value lower than the `clipped_level_min`, the behavior of // the analog gain controller is the same as that obtained when the field trial // is not specified. @@ -1007,7 +1002,7 @@ TEST(InputVolumeControllerTest, // frames to APM config. The test passes but internally the gain update timing // differs. TEST(InputVolumeControllerTest, - AgcMinMicLevelExperimentCompareMicLevelWithClippingWithRmsError) { + MinInputVolumeCompareMicLevelWithClippingWithRmsError) { // Create and initialize two AGCs by specifying and leaving unspecified the // relevant field trial. const auto factory = []() { @@ -1026,12 +1021,12 @@ TEST(InputVolumeControllerTest, std::unique_ptr manager = factory(); std::unique_ptr manager_with_override; { - constexpr int kMinMicLevelOverride = 20; + constexpr int kMinInputVolume = 20; static_assert(kDefaultInputVolumeControllerConfig.clipped_level_min >= - kMinMicLevelOverride, + kMinInputVolume, "Use a lower override value."); test::ScopedFieldTrials field_trial( - GetAgcMinInputVolumeFieldTrialEnabled(kMinMicLevelOverride)); + GetAgcMinInputVolumeFieldTrialEnabled(kMinInputVolume)); manager_with_override = factory(); }