agc_manager_direct_unittest.cc (97777B)
1 /* 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "modules/audio_processing/agc/agc_manager_direct.h" 12 13 #include <algorithm> 14 #include <cmath> 15 #include <cstddef> 16 #include <cstdint> 17 #include <fstream> 18 #include <ios> 19 #include <limits> 20 #include <memory> 21 #include <optional> 22 #include <string> 23 #include <tuple> 24 #include <vector> 25 26 #include "api/audio/audio_processing.h" 27 #include "api/environment/environment.h" 28 #include "api/environment/environment_factory.h" 29 #include "modules/audio_processing/agc/agc.h" 30 #include "modules/audio_processing/agc/gain_control.h" 31 #include "modules/audio_processing/agc/mock_agc.h" 32 #include "modules/audio_processing/audio_buffer.h" 33 #include "rtc_base/checks.h" 34 #include "rtc_base/numerics/safe_minmax.h" 35 #include "rtc_base/strings/string_builder.h" 36 #include "test/create_test_field_trials.h" 37 #include "test/gmock.h" 38 #include "test/gtest.h" 39 #include "test/testsupport/file_utils.h" 40 41 using ::testing::_; 42 using ::testing::AtLeast; 43 using ::testing::DoAll; 44 using ::testing::Return; 45 using ::testing::SetArgPointee; 46 47 namespace webrtc { 48 namespace { 49 50 constexpr int kSampleRateHz = 32000; 51 constexpr int kNumChannels = 1; 52 constexpr int kInitialInputVolume = 128; 53 constexpr int kClippedMin = 165; // Arbitrary, but different from the default. 54 constexpr float kAboveClippedThreshold = 0.2f; 55 constexpr int kMinMicLevel = 12; 56 constexpr int kClippedLevelStep = 15; 57 constexpr float kClippedRatioThreshold = 0.1f; 58 constexpr int kClippedWaitFrames = 300; 59 constexpr float kLowSpeechProbability = 0.1f; 60 constexpr float kHighSpeechProbability = 0.7f; 61 constexpr float kSpeechLevelDbfs = -25.0f; 62 63 constexpr float kMinSample = std::numeric_limits<int16_t>::min(); 64 constexpr float kMaxSample = std::numeric_limits<int16_t>::max(); 65 66 using AnalogAgcConfig = 67 AudioProcessing::Config::GainController1::AnalogGainController; 68 using ClippingPredictorConfig = AudioProcessing::Config::GainController1:: 69 AnalogGainController::ClippingPredictor; 70 constexpr AnalogAgcConfig kDefaultAnalogConfig{}; 71 72 class MockGainControl : public GainControl { 73 public: 74 ~MockGainControl() override {} 75 MOCK_METHOD(int, set_stream_analog_level, (int level), (override)); 76 MOCK_METHOD(int, stream_analog_level, (), (const, override)); 77 MOCK_METHOD(int, set_mode, (Mode mode), (override)); 78 MOCK_METHOD(Mode, mode, (), (const, override)); 79 MOCK_METHOD(int, set_target_level_dbfs, (int level), (override)); 80 MOCK_METHOD(int, target_level_dbfs, (), (const, override)); 81 MOCK_METHOD(int, set_compression_gain_db, (int gain), (override)); 82 MOCK_METHOD(int, compression_gain_db, (), (const, override)); 83 MOCK_METHOD(int, enable_limiter, (bool enable), (override)); 84 MOCK_METHOD(bool, is_limiter_enabled, (), (const, override)); 85 MOCK_METHOD(int, 86 set_analog_level_limits, 87 (int minimum, int maximum), 88 (override)); 89 MOCK_METHOD(int, analog_level_minimum, (), (const, override)); 90 MOCK_METHOD(int, analog_level_maximum, (), (const, override)); 91 MOCK_METHOD(bool, stream_is_saturated, (), (const, override)); 92 }; 93 94 // Construction parameters that tests may explicitely specify. 95 struct AgcManagerDirectTestParams { 96 std::string field_trials; 97 int clipped_level_min = kClippedMin; 98 bool enable_digital_adaptive = false; 99 int clipped_level_step = kClippedLevelStep; 100 float clipped_ratio_threshold = kClippedRatioThreshold; 101 int clipped_wait_frames = kClippedWaitFrames; 102 AnalogAgcConfig::ClippingPredictor clipping_predictor; 103 }; 104 105 std::unique_ptr<AgcManagerDirect> CreateAgcManagerDirect( 106 AgcManagerDirectTestParams p = {}) { 107 auto manager = std::make_unique<AgcManagerDirect>( 108 CreateEnvironment(CreateTestFieldTrialsPtr(p.field_trials)), kNumChannels, 109 AnalogAgcConfig{.startup_min_volume = kInitialInputVolume, 110 .clipped_level_min = p.clipped_level_min, 111 .enable_digital_adaptive = p.enable_digital_adaptive, 112 .clipped_level_step = p.clipped_level_step, 113 .clipped_ratio_threshold = p.clipped_ratio_threshold, 114 .clipped_wait_frames = p.clipped_wait_frames, 115 .clipping_predictor = p.clipping_predictor}); 116 manager->Initialize(); 117 manager->set_stream_analog_level(kInitialInputVolume); 118 return manager; 119 } 120 121 // Deprecated. 122 // TODO(bugs.webrtc.org/7494): Delete this helper, use 123 // `AgcManagerDirectTestHelper::CallAgcSequence()` instead. 124 // Calls `AnalyzePreProcess()` on `manager` `num_calls` times. `peak_ratio` is a 125 // value in [0, 1] which determines the amplitude of the samples (1 maps to full 126 // scale). The first half of the calls is made on frames which are half filled 127 // with zeros in order to simulate a signal with different crest factors. 128 void CallPreProcessAudioBuffer(int num_calls, 129 float peak_ratio, 130 AgcManagerDirect& manager) { 131 RTC_DCHECK_LE(peak_ratio, 1.0f); 132 AudioBuffer audio_buffer(kSampleRateHz, kNumChannels, kSampleRateHz, 133 kNumChannels, kSampleRateHz, kNumChannels); 134 const int num_channels = audio_buffer.num_channels(); 135 const int num_frames = audio_buffer.num_frames(); 136 137 // Make half of the calls with half zeroed frames. 138 for (int ch = 0; ch < num_channels; ++ch) { 139 // 50% of the samples in one frame are zero. 140 for (int i = 0; i < num_frames; i += 2) { 141 audio_buffer.channels()[ch][i] = peak_ratio * 32767.0f; 142 audio_buffer.channels()[ch][i + 1] = 0.0f; 143 } 144 } 145 for (int n = 0; n < num_calls / 2; ++n) { 146 manager.AnalyzePreProcess(audio_buffer); 147 } 148 149 // Make the remaining half of the calls with frames whose samples are all set. 150 for (int ch = 0; ch < num_channels; ++ch) { 151 for (int i = 0; i < num_frames; ++i) { 152 audio_buffer.channels()[ch][i] = peak_ratio * 32767.0f; 153 } 154 } 155 for (int n = 0; n < num_calls - num_calls / 2; ++n) { 156 manager.AnalyzePreProcess(audio_buffer); 157 } 158 } 159 160 constexpr char kMinMicLevelFieldTrial[] = 161 "WebRTC-Audio-2ndAgcMinMicLevelExperiment"; 162 163 std::string GetAgcMinMicLevelExperimentFieldTrial(const std::string& value) { 164 char field_trial_buffer[64]; 165 SimpleStringBuilder builder(field_trial_buffer); 166 builder << kMinMicLevelFieldTrial << "/" << value << "/"; 167 return builder.str(); 168 } 169 170 std::string GetAgcMinMicLevelExperimentFieldTrialEnabled( 171 int enabled_value, 172 const std::string& suffix = "") { 173 RTC_DCHECK_GE(enabled_value, 0); 174 RTC_DCHECK_LE(enabled_value, 255); 175 char field_trial_buffer[64]; 176 SimpleStringBuilder builder(field_trial_buffer); 177 builder << kMinMicLevelFieldTrial << "/Enabled-" << enabled_value << suffix 178 << "/"; 179 return builder.str(); 180 } 181 182 std::string GetAgcMinMicLevelExperimentFieldTrial( 183 std::optional<int> min_mic_level) { 184 if (min_mic_level.has_value()) { 185 return GetAgcMinMicLevelExperimentFieldTrialEnabled(*min_mic_level); 186 } 187 return GetAgcMinMicLevelExperimentFieldTrial("Disabled"); 188 } 189 190 // (Over)writes `samples_value` for the samples in `audio_buffer`. 191 // When `clipped_ratio`, a value in [0, 1], is greater than 0, the corresponding 192 // fraction of the frame is set to a full scale value to simulate clipping. 193 void WriteAudioBufferSamples(float samples_value, 194 float clipped_ratio, 195 AudioBuffer& audio_buffer) { 196 RTC_DCHECK_GE(samples_value, kMinSample); 197 RTC_DCHECK_LE(samples_value, kMaxSample); 198 RTC_DCHECK_GE(clipped_ratio, 0.0f); 199 RTC_DCHECK_LE(clipped_ratio, 1.0f); 200 int num_channels = audio_buffer.num_channels(); 201 int num_samples = audio_buffer.num_frames(); 202 int num_clipping_samples = clipped_ratio * num_samples; 203 for (int ch = 0; ch < num_channels; ++ch) { 204 int i = 0; 205 for (; i < num_clipping_samples; ++i) { 206 audio_buffer.channels()[ch][i] = 32767.0f; 207 } 208 for (; i < num_samples; ++i) { 209 audio_buffer.channels()[ch][i] = samples_value; 210 } 211 } 212 } 213 214 // Deprecated. 215 // TODO(bugs.webrtc.org/7494): Delete this helper, use 216 // `AgcManagerDirectTestHelper::CallAgcSequence()` instead. 217 void CallPreProcessAndProcess(int num_calls, 218 const AudioBuffer& audio_buffer, 219 std::optional<float> speech_probability_override, 220 std::optional<float> speech_level_override, 221 AgcManagerDirect& manager) { 222 for (int n = 0; n < num_calls; ++n) { 223 manager.AnalyzePreProcess(audio_buffer); 224 manager.Process(audio_buffer, speech_probability_override, 225 speech_level_override); 226 } 227 } 228 229 // Reads a given number of 10 ms chunks from a PCM file and feeds them to 230 // `AgcManagerDirect`. 231 class SpeechSamplesReader { 232 private: 233 // Recording properties. 234 static constexpr int kPcmSampleRateHz = 16000; 235 static constexpr int kPcmNumChannels = 1; 236 static constexpr int kPcmBytesPerSamples = sizeof(int16_t); 237 238 public: 239 SpeechSamplesReader() 240 : is_(test::ResourcePath("audio_processing/agc/agc_audio", "pcm"), 241 std::ios::binary | std::ios::ate), 242 audio_buffer_(kPcmSampleRateHz, 243 kPcmNumChannels, 244 kPcmSampleRateHz, 245 kPcmNumChannels, 246 kPcmSampleRateHz, 247 kPcmNumChannels), 248 buffer_(audio_buffer_.num_frames()), 249 buffer_num_bytes_(buffer_.size() * kPcmBytesPerSamples) { 250 RTC_CHECK(is_); 251 } 252 253 // Reads `num_frames` 10 ms frames from the beginning of the PCM file, applies 254 // `gain_db` and feeds the frames into `agc` by calling `AnalyzePreProcess()` 255 // and `Process()` for each frame. Reads the number of 10 ms frames available 256 // in the PCM file if `num_frames` is too large - i.e., does not loop. 257 void Feed(int num_frames, int gain_db, AgcManagerDirect& agc) { 258 float gain = std::pow(10.0f, gain_db / 20.0f); // From dB to linear gain. 259 is_.seekg(0, 260 std::ifstream::beg); // Start from the beginning of the PCM file. 261 262 // Read and feed frames. 263 for (int i = 0; i < num_frames; ++i) { 264 is_.read(reinterpret_cast<char*>(buffer_.data()), buffer_num_bytes_); 265 if (is_.gcount() < buffer_num_bytes_) { 266 // EOF reached. Stop. 267 break; 268 } 269 // Apply gain and copy samples into `audio_buffer_`. 270 std::transform(buffer_.begin(), buffer_.end(), 271 audio_buffer_.channels()[0], [gain](int16_t v) -> float { 272 return SafeClamp(static_cast<float>(v) * gain, 273 kMinSample, kMaxSample); 274 }); 275 276 agc.AnalyzePreProcess(audio_buffer_); 277 agc.Process(audio_buffer_); 278 } 279 } 280 281 // Reads `num_frames` 10 ms frames from the beginning of the PCM file, applies 282 // `gain_db` and feeds the frames into `agc` by calling `AnalyzePreProcess()` 283 // and `Process()` for each frame. Reads the number of 10 ms frames available 284 // in the PCM file if `num_frames` is too large - i.e., does not loop. 285 // `speech_probability_override` and `speech_level_override` are passed to 286 // `Process()` where they are used to override the `agc` RMS error if they 287 // have a value. 288 void Feed(int num_frames, 289 int gain_db, 290 std::optional<float> speech_probability_override, 291 std::optional<float> speech_level_override, 292 AgcManagerDirect& agc) { 293 float gain = std::pow(10.0f, gain_db / 20.0f); // From dB to linear gain. 294 is_.seekg(0, 295 std::ifstream::beg); // Start from the beginning of the PCM file. 296 297 // Read and feed frames. 298 for (int i = 0; i < num_frames; ++i) { 299 is_.read(reinterpret_cast<char*>(buffer_.data()), buffer_num_bytes_); 300 if (is_.gcount() < buffer_num_bytes_) { 301 // EOF reached. Stop. 302 break; 303 } 304 // Apply gain and copy samples into `audio_buffer_`. 305 std::transform(buffer_.begin(), buffer_.end(), 306 audio_buffer_.channels()[0], [gain](int16_t v) -> float { 307 return SafeClamp(static_cast<float>(v) * gain, 308 kMinSample, kMaxSample); 309 }); 310 311 agc.AnalyzePreProcess(audio_buffer_); 312 agc.Process(audio_buffer_, speech_probability_override, 313 speech_level_override); 314 } 315 } 316 317 private: 318 std::ifstream is_; 319 AudioBuffer audio_buffer_; 320 std::vector<int16_t> buffer_; 321 const std::streamsize buffer_num_bytes_; 322 }; 323 324 } // namespace 325 326 // TODO(bugs.webrtc.org/12874): Use constexpr struct with designated 327 // initializers once fixed. 328 constexpr AnalogAgcConfig GetAnalogAgcTestConfig() { 329 AnalogAgcConfig config; 330 config.enabled = true; 331 config.startup_min_volume = kInitialInputVolume; 332 config.clipped_level_min = kClippedMin; 333 config.enable_digital_adaptive = true; 334 config.clipped_level_step = kClippedLevelStep; 335 config.clipped_ratio_threshold = kClippedRatioThreshold; 336 config.clipped_wait_frames = kClippedWaitFrames; 337 config.clipping_predictor = kDefaultAnalogConfig.clipping_predictor; 338 return config; 339 } 340 341 constexpr AnalogAgcConfig GetDisabledAnalogAgcConfig() { 342 AnalogAgcConfig config = GetAnalogAgcTestConfig(); 343 config.enabled = false; 344 return config; 345 } 346 347 // Helper class that provides an `AgcManagerDirect` instance with an injected 348 // `Agc` mock, an `AudioBuffer` instance and `CallAgcSequence()`, a helper 349 // method that runs the `AgcManagerDirect` instance on the `AudioBuffer` one by 350 // sticking to the API contract. 351 class AgcManagerDirectTestHelper { 352 public: 353 // Ctor. Initializes `audio_buffer` with zeros. 354 explicit AgcManagerDirectTestHelper(const Environment& env) 355 : audio_buffer(kSampleRateHz, 356 kNumChannels, 357 kSampleRateHz, 358 kNumChannels, 359 kSampleRateHz, 360 kNumChannels), 361 mock_agc(new ::testing::NiceMock<MockAgc>()), 362 manager(env, GetAnalogAgcTestConfig(), mock_agc) { 363 manager.Initialize(); 364 manager.SetupDigitalGainControl(mock_gain_control); 365 WriteAudioBufferSamples(/*samples_value=*/0.0f, /*clipped_ratio=*/0.0f, 366 audio_buffer); 367 } 368 369 // Calls the sequence of `AgcManagerDirect` methods according to the API 370 // contract, namely: 371 // - Sets the applied input volume; 372 // - Uses `audio_buffer` to call `AnalyzePreProcess()` and `Process()`; 373 // - Sets the digital compression gain, if specified, on the injected 374 // `mock_agc`. Returns the recommended input volume. The RMS error from 375 // AGC is replaced by an override value if `speech_probability_override` 376 // and `speech_level_override` have a value. 377 int CallAgcSequence(int applied_input_volume, 378 std::optional<float> speech_probability_override, 379 std::optional<float> speech_level_override) { 380 manager.set_stream_analog_level(applied_input_volume); 381 manager.AnalyzePreProcess(audio_buffer); 382 manager.Process(audio_buffer, speech_probability_override, 383 speech_level_override); 384 std::optional<int> digital_gain = manager.GetDigitalComressionGain(); 385 if (digital_gain) { 386 mock_gain_control.set_compression_gain_db(*digital_gain); 387 } 388 return manager.recommended_analog_level(); 389 } 390 391 // Deprecated. 392 // TODO(bugs.webrtc.org/7494): Let the caller write `audio_buffer` and use 393 // `CallAgcSequence()`. The RMS error from AGC is replaced by an override 394 // value if `speech_probability_override` and `speech_level_override` have 395 // a value. 396 void CallProcess(int num_calls, 397 std::optional<float> speech_probability_override, 398 std::optional<float> speech_level_override) { 399 for (int i = 0; i < num_calls; ++i) { 400 EXPECT_CALL(*mock_agc, Process(_)).WillOnce(Return()); 401 manager.Process(audio_buffer, speech_probability_override, 402 speech_level_override); 403 std::optional<int> new_digital_gain = manager.GetDigitalComressionGain(); 404 if (new_digital_gain) { 405 mock_gain_control.set_compression_gain_db(*new_digital_gain); 406 } 407 } 408 } 409 410 // Deprecated. 411 // TODO(bugs.webrtc.org/7494): Let the caller write `audio_buffer` and use 412 // `CallAgcSequence()`. 413 void CallPreProc(int num_calls, float clipped_ratio) { 414 RTC_DCHECK_GE(clipped_ratio, 0.0f); 415 RTC_DCHECK_LE(clipped_ratio, 1.0f); 416 WriteAudioBufferSamples(/*samples_value=*/0.0f, clipped_ratio, 417 audio_buffer); 418 for (int i = 0; i < num_calls; ++i) { 419 manager.AnalyzePreProcess(audio_buffer); 420 } 421 } 422 423 // Deprecated. 424 // TODO(bugs.webrtc.org/7494): Let the caller write `audio_buffer` and use 425 // `CallAgcSequence()`. 426 void CallPreProcForChangingAudio(int num_calls, float peak_ratio) { 427 RTC_DCHECK_GE(peak_ratio, 0.0f); 428 RTC_DCHECK_LE(peak_ratio, 1.0f); 429 const float samples_value = peak_ratio * 32767.0f; 430 431 // Make half of the calls on a frame where the samples alternate 432 // `sample_values` and zeros. 433 WriteAudioBufferSamples(samples_value, /*clipped_ratio=*/0.0f, 434 audio_buffer); 435 for (size_t ch = 0; ch < audio_buffer.num_channels(); ++ch) { 436 for (size_t k = 1; k < audio_buffer.num_frames(); k += 2) { 437 audio_buffer.channels()[ch][k] = 0.0f; 438 } 439 } 440 for (int i = 0; i < num_calls / 2; ++i) { 441 manager.AnalyzePreProcess(audio_buffer); 442 } 443 444 // Make half of thecalls on a frame where all the samples equal 445 // `sample_values`. 446 WriteAudioBufferSamples(samples_value, /*clipped_ratio=*/0.0f, 447 audio_buffer); 448 for (int i = 0; i < num_calls - num_calls / 2; ++i) { 449 manager.AnalyzePreProcess(audio_buffer); 450 } 451 } 452 453 AudioBuffer audio_buffer; 454 MockAgc* mock_agc; 455 AgcManagerDirect manager; 456 MockGainControl mock_gain_control; 457 }; 458 459 class AgcManagerDirectParametrizedTest 460 : public ::testing::TestWithParam<std::tuple<std::optional<int>, bool>> { 461 protected: 462 AgcManagerDirectParametrizedTest() 463 : env_(CreateEnvironment(CreateTestFieldTrialsPtr( 464 GetAgcMinMicLevelExperimentFieldTrial(std::get<0>(GetParam()))))) {} 465 466 bool IsMinMicLevelOverridden() const { 467 return std::get<0>(GetParam()).has_value(); 468 } 469 int GetMinMicLevel() const { 470 return std::get<0>(GetParam()).value_or(kMinMicLevel); 471 } 472 473 bool IsRmsErrorOverridden() const { return std::get<1>(GetParam()); } 474 std::optional<float> GetOverrideOrEmpty(float value) const { 475 return IsRmsErrorOverridden() ? std::optional<float>(value) : std::nullopt; 476 } 477 478 const Environment env_; 479 }; 480 481 INSTANTIATE_TEST_SUITE_P( 482 , 483 AgcManagerDirectParametrizedTest, 484 ::testing::Combine(testing::Values(std::nullopt, 12, 20), testing::Bool())); 485 486 // Checks that when the analog controller is disabled, no downward adaptation 487 // takes place. 488 // TODO(webrtc:7494): Revisit the test after moving the number of override wait 489 // frames to AMP config. The test passes but internally the gain update timing 490 // differs. 491 TEST_P(AgcManagerDirectParametrizedTest, 492 DisabledAnalogAgcDoesNotAdaptDownwards) { 493 AgcManagerDirect manager_no_analog_agc(env_, kNumChannels, 494 GetDisabledAnalogAgcConfig()); 495 manager_no_analog_agc.Initialize(); 496 AgcManagerDirect manager_with_analog_agc(env_, kNumChannels, 497 GetAnalogAgcTestConfig()); 498 manager_with_analog_agc.Initialize(); 499 500 AudioBuffer audio_buffer(kSampleRateHz, kNumChannels, kSampleRateHz, 501 kNumChannels, kSampleRateHz, kNumChannels); 502 503 constexpr int kAnalogLevel = 250; 504 static_assert(kAnalogLevel > kInitialInputVolume, "Increase `kAnalogLevel`."); 505 manager_no_analog_agc.set_stream_analog_level(kAnalogLevel); 506 manager_with_analog_agc.set_stream_analog_level(kAnalogLevel); 507 508 // Make a first call with input that doesn't clip in order to let the 509 // controller read the input volume. That is needed because clipping input 510 // causes the controller to stay in idle state for 511 // `AnalogAgcConfig::clipped_wait_frames` frames. 512 WriteAudioBufferSamples(/*samples_value=*/0.0f, /*clipped_ratio=*/0.0f, 513 audio_buffer); 514 manager_no_analog_agc.AnalyzePreProcess(audio_buffer); 515 manager_with_analog_agc.AnalyzePreProcess(audio_buffer); 516 manager_no_analog_agc.Process(audio_buffer, 517 GetOverrideOrEmpty(kHighSpeechProbability), 518 GetOverrideOrEmpty(-18.0f)); 519 manager_with_analog_agc.Process(audio_buffer, 520 GetOverrideOrEmpty(kHighSpeechProbability), 521 GetOverrideOrEmpty(-18.0f)); 522 523 // Feed clipping input to trigger a downward adapation of the analog level. 524 WriteAudioBufferSamples(/*samples_value=*/0.0f, /*clipped_ratio=*/0.2f, 525 audio_buffer); 526 manager_no_analog_agc.AnalyzePreProcess(audio_buffer); 527 manager_with_analog_agc.AnalyzePreProcess(audio_buffer); 528 manager_no_analog_agc.Process(audio_buffer, 529 GetOverrideOrEmpty(kHighSpeechProbability), 530 GetOverrideOrEmpty(-10.0f)); 531 manager_with_analog_agc.Process(audio_buffer, 532 GetOverrideOrEmpty(kHighSpeechProbability), 533 GetOverrideOrEmpty(-10.0f)); 534 535 // Check that no adaptation occurs when the analog controller is disabled 536 // and make sure that the test triggers a downward adaptation otherwise. 537 EXPECT_EQ(manager_no_analog_agc.recommended_analog_level(), kAnalogLevel); 538 ASSERT_LT(manager_with_analog_agc.recommended_analog_level(), kAnalogLevel); 539 } 540 541 // Checks that when the analog controller is disabled, no upward adaptation 542 // takes place. 543 // TODO(webrtc:7494): Revisit the test after moving the number of override wait 544 // frames to APM config. The test passes but internally the gain update timing 545 // differs. 546 TEST_P(AgcManagerDirectParametrizedTest, DisabledAnalogAgcDoesNotAdaptUpwards) { 547 AgcManagerDirect manager_no_analog_agc(env_, kNumChannels, 548 GetDisabledAnalogAgcConfig()); 549 manager_no_analog_agc.Initialize(); 550 AgcManagerDirect manager_with_analog_agc(env_, kNumChannels, 551 GetAnalogAgcTestConfig()); 552 manager_with_analog_agc.Initialize(); 553 554 constexpr int kAnalogLevel = kInitialInputVolume; 555 manager_no_analog_agc.set_stream_analog_level(kAnalogLevel); 556 manager_with_analog_agc.set_stream_analog_level(kAnalogLevel); 557 558 // Feed speech with low energy to trigger an upward adapation of the analog 559 // level. 560 constexpr int kNumFrames = 125; 561 constexpr int kGainDb = -20; 562 SpeechSamplesReader reader; 563 reader.Feed(kNumFrames, kGainDb, GetOverrideOrEmpty(kHighSpeechProbability), 564 GetOverrideOrEmpty(-42.0f), manager_no_analog_agc); 565 reader.Feed(kNumFrames, kGainDb, GetOverrideOrEmpty(kHighSpeechProbability), 566 GetOverrideOrEmpty(-42.0f), manager_with_analog_agc); 567 568 // Check that no adaptation occurs when the analog controller is disabled 569 // and make sure that the test triggers an upward adaptation otherwise. 570 EXPECT_EQ(manager_no_analog_agc.recommended_analog_level(), kAnalogLevel); 571 ASSERT_GT(manager_with_analog_agc.recommended_analog_level(), kAnalogLevel); 572 } 573 574 TEST_P(AgcManagerDirectParametrizedTest, 575 StartupMinVolumeConfigurationIsRespected) { 576 AgcManagerDirectTestHelper helper(env_); 577 helper.CallAgcSequence(kInitialInputVolume, 578 GetOverrideOrEmpty(kHighSpeechProbability), 579 GetOverrideOrEmpty(kSpeechLevelDbfs)); 580 EXPECT_EQ(kInitialInputVolume, helper.manager.recommended_analog_level()); 581 } 582 583 TEST_P(AgcManagerDirectParametrizedTest, MicVolumeResponseToRmsError) { 584 const auto speech_probability_override = 585 GetOverrideOrEmpty(kHighSpeechProbability); 586 587 AgcManagerDirectTestHelper helper(env_); 588 helper.CallAgcSequence(kInitialInputVolume, speech_probability_override, 589 GetOverrideOrEmpty(kSpeechLevelDbfs)); 590 591 // Compressor default; no residual error. 592 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 593 .WillOnce(DoAll(SetArgPointee<0>(5), Return(true))); 594 helper.CallProcess(/*num_calls=*/1, speech_probability_override, 595 GetOverrideOrEmpty(-23.0f)); 596 597 // Inside the compressor's window; no change of volume. 598 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 599 .WillOnce(DoAll(SetArgPointee<0>(10), Return(true))); 600 helper.CallProcess(/*num_calls=*/1, speech_probability_override, 601 GetOverrideOrEmpty(-28.0f)); 602 603 // Above the compressor's window; volume should be increased. 604 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 605 .WillOnce(DoAll(SetArgPointee<0>(11), Return(true))); 606 helper.CallProcess(/*num_calls=*/1, speech_probability_override, 607 GetOverrideOrEmpty(-29.0f)); 608 EXPECT_EQ(130, helper.manager.recommended_analog_level()); 609 610 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 611 .WillOnce(DoAll(SetArgPointee<0>(20), Return(true))); 612 helper.CallProcess(/*num_calls=*/1, speech_probability_override, 613 GetOverrideOrEmpty(-38.0f)); 614 EXPECT_EQ(168, helper.manager.recommended_analog_level()); 615 616 // Inside the compressor's window; no change of volume. 617 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 618 .WillOnce(DoAll(SetArgPointee<0>(5), Return(true))); 619 helper.CallProcess(/*num_calls=*/1, speech_probability_override, 620 GetOverrideOrEmpty(-23.0f)); 621 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 622 .WillOnce(DoAll(SetArgPointee<0>(0), Return(true))); 623 helper.CallProcess(/*num_calls=*/1, speech_probability_override, 624 GetOverrideOrEmpty(-18.0f)); 625 626 // Below the compressor's window; volume should be decreased. 627 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 628 .WillOnce(DoAll(SetArgPointee<0>(-1), Return(true))); 629 helper.CallProcess(/*num_calls=*/1, speech_probability_override, 630 GetOverrideOrEmpty(-17.0f)); 631 EXPECT_EQ(167, helper.manager.recommended_analog_level()); 632 633 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 634 .WillOnce(DoAll(SetArgPointee<0>(-1), Return(true))); 635 helper.CallProcess(/*num_calls=*/1, speech_probability_override, 636 GetOverrideOrEmpty(-17.0f)); 637 EXPECT_EQ(163, helper.manager.recommended_analog_level()); 638 639 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 640 .WillOnce(DoAll(SetArgPointee<0>(-9), Return(true))); 641 helper.CallProcess(/*num_calls=*/1, speech_probability_override, 642 GetOverrideOrEmpty(-9.0f)); 643 EXPECT_EQ(129, helper.manager.recommended_analog_level()); 644 } 645 646 TEST_P(AgcManagerDirectParametrizedTest, MicVolumeIsLimited) { 647 const auto speech_probability_override = 648 GetOverrideOrEmpty(kHighSpeechProbability); 649 650 AgcManagerDirectTestHelper helper(env_); 651 helper.CallAgcSequence(kInitialInputVolume, speech_probability_override, 652 GetOverrideOrEmpty(kSpeechLevelDbfs)); 653 654 // Maximum upwards change is limited. 655 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 656 .WillOnce(DoAll(SetArgPointee<0>(30), Return(true))); 657 helper.CallProcess(/*num_calls=*/1, speech_probability_override, 658 GetOverrideOrEmpty(-48.0f)); 659 EXPECT_EQ(183, helper.manager.recommended_analog_level()); 660 661 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 662 .WillOnce(DoAll(SetArgPointee<0>(30), Return(true))); 663 helper.CallProcess(/*num_calls=*/1, speech_probability_override, 664 GetOverrideOrEmpty(-48.0f)); 665 EXPECT_EQ(243, helper.manager.recommended_analog_level()); 666 667 // Won't go higher than the maximum. 668 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 669 .WillOnce(DoAll(SetArgPointee<0>(30), Return(true))); 670 helper.CallProcess(/*num_calls=*/1, speech_probability_override, 671 GetOverrideOrEmpty(-48.0f)); 672 EXPECT_EQ(255, helper.manager.recommended_analog_level()); 673 674 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 675 .WillOnce(DoAll(SetArgPointee<0>(-1), Return(true))); 676 helper.CallProcess(/*num_calls=*/1, speech_probability_override, 677 GetOverrideOrEmpty(-17.0f)); 678 EXPECT_EQ(254, helper.manager.recommended_analog_level()); 679 680 // Maximum downwards change is limited. 681 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 682 .WillOnce(DoAll(SetArgPointee<0>(-40), Return(true))); 683 helper.CallProcess(/*num_calls=*/1, speech_probability_override, 684 GetOverrideOrEmpty(22.0f)); 685 EXPECT_EQ(194, helper.manager.recommended_analog_level()); 686 687 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 688 .WillOnce(DoAll(SetArgPointee<0>(-40), Return(true))); 689 helper.CallProcess(/*num_calls=*/1, speech_probability_override, 690 GetOverrideOrEmpty(22.0f)); 691 EXPECT_EQ(137, helper.manager.recommended_analog_level()); 692 693 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 694 .WillOnce(DoAll(SetArgPointee<0>(-40), Return(true))); 695 helper.CallProcess(/*num_calls=*/1, speech_probability_override, 696 GetOverrideOrEmpty(22.0f)); 697 EXPECT_EQ(88, helper.manager.recommended_analog_level()); 698 699 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 700 .WillOnce(DoAll(SetArgPointee<0>(-40), Return(true))); 701 helper.CallProcess(/*num_calls=*/1, speech_probability_override, 702 GetOverrideOrEmpty(22.0f)); 703 EXPECT_EQ(54, helper.manager.recommended_analog_level()); 704 705 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 706 .WillOnce(DoAll(SetArgPointee<0>(-40), Return(true))); 707 helper.CallProcess(/*num_calls=*/1, speech_probability_override, 708 GetOverrideOrEmpty(22.0f)); 709 EXPECT_EQ(33, helper.manager.recommended_analog_level()); 710 711 // Won't go lower than the minimum. 712 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 713 .WillOnce(DoAll(SetArgPointee<0>(-40), Return(true))); 714 helper.CallProcess(/*num_calls=*/1, speech_probability_override, 715 GetOverrideOrEmpty(22.0f)); 716 EXPECT_EQ(std::max(18, GetMinMicLevel()), 717 helper.manager.recommended_analog_level()); 718 719 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 720 .WillOnce(DoAll(SetArgPointee<0>(-40), Return(true))); 721 helper.CallProcess(/*num_calls=*/1, speech_probability_override, 722 GetOverrideOrEmpty(22.0f)); 723 EXPECT_EQ(std::max(12, GetMinMicLevel()), 724 helper.manager.recommended_analog_level()); 725 } 726 727 TEST_P(AgcManagerDirectParametrizedTest, CompressorStepsTowardsTarget) { 728 constexpr std::optional<float> kNoOverride = std::nullopt; 729 const auto speech_probability_override = 730 GetOverrideOrEmpty(kHighSpeechProbability); 731 732 AgcManagerDirectTestHelper helper(env_); 733 helper.CallAgcSequence(kInitialInputVolume, speech_probability_override, 734 GetOverrideOrEmpty(kSpeechLevelDbfs)); 735 736 // Compressor default; no call to set_compression_gain_db. 737 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 738 .WillOnce(DoAll(SetArgPointee<0>(5), Return(true))) 739 .WillRepeatedly(Return(false)); 740 EXPECT_CALL(helper.mock_gain_control, set_compression_gain_db(_)).Times(0); 741 helper.CallProcess(/*num_calls=*/1, speech_probability_override, 742 GetOverrideOrEmpty(-23.0f)); 743 EXPECT_CALL(helper.mock_gain_control, set_compression_gain_db(_)).Times(0); 744 // The mock `GetRmsErrorDb()` returns false; mimic this by passing 745 // std::nullopt as an override. 746 helper.CallProcess(/*num_calls=*/19, kNoOverride, kNoOverride); 747 748 // Moves slowly upwards. 749 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 750 .WillOnce(DoAll(SetArgPointee<0>(9), Return(true))) 751 .WillRepeatedly(Return(false)); 752 EXPECT_CALL(helper.mock_gain_control, set_compression_gain_db(_)).Times(0); 753 helper.CallProcess(/*num_calls=*/1, speech_probability_override, 754 GetOverrideOrEmpty(-27.0f)); 755 EXPECT_CALL(helper.mock_gain_control, set_compression_gain_db(_)).Times(0); 756 helper.CallProcess(/*num_calls=*/18, kNoOverride, kNoOverride); 757 EXPECT_CALL(helper.mock_gain_control, set_compression_gain_db(8)) 758 .WillOnce(Return(0)); 759 helper.CallProcess(/*num_calls=*/1, kNoOverride, kNoOverride); 760 761 EXPECT_CALL(helper.mock_gain_control, set_compression_gain_db(_)).Times(0); 762 helper.CallProcess(/*num_calls=*/19, kNoOverride, kNoOverride); 763 EXPECT_CALL(helper.mock_gain_control, set_compression_gain_db(9)) 764 .WillOnce(Return(0)); 765 helper.CallProcess(/*num_calls=*/1, kNoOverride, kNoOverride); 766 767 EXPECT_CALL(helper.mock_gain_control, set_compression_gain_db(_)).Times(0); 768 helper.CallProcess(/*num_calls=*/20, kNoOverride, kNoOverride); 769 770 // Moves slowly downward, then reverses before reaching the original target. 771 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 772 .WillOnce(DoAll(SetArgPointee<0>(5), Return(true))) 773 .WillRepeatedly(Return(false)); 774 EXPECT_CALL(helper.mock_gain_control, set_compression_gain_db(_)).Times(0); 775 helper.CallProcess(/*num_calls=*/1, speech_probability_override, 776 GetOverrideOrEmpty(-23.0f)); 777 EXPECT_CALL(helper.mock_gain_control, set_compression_gain_db(_)).Times(0); 778 helper.CallProcess(/*num_calls=*/18, kNoOverride, kNoOverride); 779 EXPECT_CALL(helper.mock_gain_control, set_compression_gain_db(8)) 780 .WillOnce(Return(0)); 781 helper.CallProcess(/*num_calls=*/1, kNoOverride, kNoOverride); 782 783 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 784 .WillOnce(DoAll(SetArgPointee<0>(9), Return(true))) 785 .WillRepeatedly(Return(false)); 786 EXPECT_CALL(helper.mock_gain_control, set_compression_gain_db(_)).Times(0); 787 helper.CallProcess(/*num_calls=*/1, speech_probability_override, 788 GetOverrideOrEmpty(-27.0f)); 789 EXPECT_CALL(helper.mock_gain_control, set_compression_gain_db(_)).Times(0); 790 helper.CallProcess(/*num_calls=*/18, kNoOverride, kNoOverride); 791 EXPECT_CALL(helper.mock_gain_control, set_compression_gain_db(9)) 792 .WillOnce(Return(0)); 793 helper.CallProcess(/*num_calls=*/1, kNoOverride, kNoOverride); 794 795 EXPECT_CALL(helper.mock_gain_control, set_compression_gain_db(_)).Times(0); 796 helper.CallProcess(/*num_calls=*/20, kNoOverride, kNoOverride); 797 } 798 799 TEST_P(AgcManagerDirectParametrizedTest, CompressorErrorIsDeemphasized) { 800 constexpr std::optional<float> kNoOverride = std::nullopt; 801 const auto speech_probability_override = 802 GetOverrideOrEmpty(kHighSpeechProbability); 803 804 AgcManagerDirectTestHelper helper(env_); 805 helper.CallAgcSequence(kInitialInputVolume, speech_probability_override, 806 GetOverrideOrEmpty(kSpeechLevelDbfs)); 807 808 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 809 .WillOnce(DoAll(SetArgPointee<0>(10), Return(true))) 810 .WillRepeatedly(Return(false)); 811 helper.CallProcess(/*num_calls=*/1, speech_probability_override, 812 GetOverrideOrEmpty(-28.0f)); 813 // The mock `GetRmsErrorDb()` returns false; mimic this by passing 814 // std::nullopt as an override. 815 helper.CallProcess(/*num_calls=*/18, kNoOverride, kNoOverride); 816 EXPECT_CALL(helper.mock_gain_control, set_compression_gain_db(8)) 817 .WillOnce(Return(0)); 818 helper.CallProcess(/*num_calls=*/20, kNoOverride, kNoOverride); 819 EXPECT_CALL(helper.mock_gain_control, set_compression_gain_db(9)) 820 .WillOnce(Return(0)); 821 helper.CallProcess(/*num_calls=*/1, kNoOverride, kNoOverride); 822 EXPECT_CALL(helper.mock_gain_control, set_compression_gain_db(_)).Times(0); 823 helper.CallProcess(/*num_calls=*/20, kNoOverride, kNoOverride); 824 825 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 826 .WillOnce(DoAll(SetArgPointee<0>(0), Return(true))) 827 .WillRepeatedly(Return(false)); 828 helper.CallProcess(/*num_calls=*/1, speech_probability_override, 829 GetOverrideOrEmpty(-18.0f)); 830 helper.CallProcess(/*num_calls=*/18, kNoOverride, kNoOverride); 831 EXPECT_CALL(helper.mock_gain_control, set_compression_gain_db(8)) 832 .WillOnce(Return(0)); 833 helper.CallProcess(/*num_calls=*/20, kNoOverride, kNoOverride); 834 EXPECT_CALL(helper.mock_gain_control, set_compression_gain_db(7)) 835 .WillOnce(Return(0)); 836 helper.CallProcess(/*num_calls=*/20, kNoOverride, kNoOverride); 837 EXPECT_CALL(helper.mock_gain_control, set_compression_gain_db(6)) 838 .WillOnce(Return(0)); 839 helper.CallProcess(/*num_calls=*/1, kNoOverride, kNoOverride); 840 EXPECT_CALL(helper.mock_gain_control, set_compression_gain_db(_)).Times(0); 841 helper.CallProcess(/*num_calls=*/20, kNoOverride, kNoOverride); 842 } 843 844 TEST_P(AgcManagerDirectParametrizedTest, CompressorReachesMaximum) { 845 constexpr std::optional<float> kNoOverride = std::nullopt; 846 const auto speech_probability_override = 847 GetOverrideOrEmpty(kHighSpeechProbability); 848 849 AgcManagerDirectTestHelper helper(env_); 850 helper.CallAgcSequence(kInitialInputVolume, speech_probability_override, 851 GetOverrideOrEmpty(kSpeechLevelDbfs)); 852 853 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 854 .WillOnce(DoAll(SetArgPointee<0>(10), Return(true))) 855 .WillOnce(DoAll(SetArgPointee<0>(10), Return(true))) 856 .WillOnce(DoAll(SetArgPointee<0>(10), Return(true))) 857 .WillOnce(DoAll(SetArgPointee<0>(10), Return(true))) 858 .WillRepeatedly(Return(false)); 859 helper.CallProcess(/*num_calls=*/4, speech_probability_override, 860 GetOverrideOrEmpty(-28.0f)); 861 // The mock `GetRmsErrorDb()` returns false; mimic this by passing 862 // std::nullopt as an override. 863 helper.CallProcess(/*num_calls=*/15, kNoOverride, kNoOverride); 864 EXPECT_CALL(helper.mock_gain_control, set_compression_gain_db(8)) 865 .WillOnce(Return(0)); 866 helper.CallProcess(/*num_calls=*/20, kNoOverride, kNoOverride); 867 EXPECT_CALL(helper.mock_gain_control, set_compression_gain_db(9)) 868 .WillOnce(Return(0)); 869 helper.CallProcess(/*num_calls=*/20, kNoOverride, kNoOverride); 870 EXPECT_CALL(helper.mock_gain_control, set_compression_gain_db(10)) 871 .WillOnce(Return(0)); 872 helper.CallProcess(/*num_calls=*/20, kNoOverride, kNoOverride); 873 EXPECT_CALL(helper.mock_gain_control, set_compression_gain_db(11)) 874 .WillOnce(Return(0)); 875 helper.CallProcess(/*num_calls=*/20, kNoOverride, kNoOverride); 876 EXPECT_CALL(helper.mock_gain_control, set_compression_gain_db(12)) 877 .WillOnce(Return(0)); 878 helper.CallProcess(/*num_calls=*/1, kNoOverride, kNoOverride); 879 } 880 881 TEST_P(AgcManagerDirectParametrizedTest, CompressorReachesMinimum) { 882 constexpr std::optional<float> kNoOverride = std::nullopt; 883 const auto speech_probability_override = 884 GetOverrideOrEmpty(kHighSpeechProbability); 885 886 AgcManagerDirectTestHelper helper(env_); 887 helper.CallAgcSequence(kInitialInputVolume, speech_probability_override, 888 GetOverrideOrEmpty(kSpeechLevelDbfs)); 889 890 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 891 .WillOnce(DoAll(SetArgPointee<0>(0), Return(true))) 892 .WillOnce(DoAll(SetArgPointee<0>(0), Return(true))) 893 .WillOnce(DoAll(SetArgPointee<0>(0), Return(true))) 894 .WillOnce(DoAll(SetArgPointee<0>(0), Return(true))) 895 .WillRepeatedly(Return(false)); 896 helper.CallProcess(/*num_calls=*/4, speech_probability_override, 897 GetOverrideOrEmpty(-18.0f)); 898 // The mock `GetRmsErrorDb()` returns false; mimic this by passing 899 // std::nullopt as an override. 900 helper.CallProcess(/*num_calls=*/15, kNoOverride, kNoOverride); 901 EXPECT_CALL(helper.mock_gain_control, set_compression_gain_db(6)) 902 .WillOnce(Return(0)); 903 helper.CallProcess(/*num_calls=*/20, kNoOverride, kNoOverride); 904 EXPECT_CALL(helper.mock_gain_control, set_compression_gain_db(5)) 905 .WillOnce(Return(0)); 906 helper.CallProcess(/*num_calls=*/20, kNoOverride, kNoOverride); 907 EXPECT_CALL(helper.mock_gain_control, set_compression_gain_db(4)) 908 .WillOnce(Return(0)); 909 helper.CallProcess(/*num_calls=*/20, kNoOverride, kNoOverride); 910 EXPECT_CALL(helper.mock_gain_control, set_compression_gain_db(3)) 911 .WillOnce(Return(0)); 912 helper.CallProcess(/*num_calls=*/20, kNoOverride, kNoOverride); 913 EXPECT_CALL(helper.mock_gain_control, set_compression_gain_db(2)) 914 .WillOnce(Return(0)); 915 helper.CallProcess(/*num_calls=*/1, kNoOverride, kNoOverride); 916 } 917 918 TEST_P(AgcManagerDirectParametrizedTest, NoActionWhileMuted) { 919 AgcManagerDirectTestHelper helper(env_); 920 helper.CallAgcSequence(kInitialInputVolume, 921 GetOverrideOrEmpty(kHighSpeechProbability), 922 GetOverrideOrEmpty(kSpeechLevelDbfs)); 923 924 helper.manager.HandleCaptureOutputUsedChange(false); 925 helper.manager.Process(helper.audio_buffer, 926 GetOverrideOrEmpty(kHighSpeechProbability), 927 GetOverrideOrEmpty(kSpeechLevelDbfs)); 928 929 std::optional<int> new_digital_gain = 930 helper.manager.GetDigitalComressionGain(); 931 if (new_digital_gain) { 932 helper.mock_gain_control.set_compression_gain_db(*new_digital_gain); 933 } 934 } 935 936 TEST_P(AgcManagerDirectParametrizedTest, UnmutingChecksVolumeWithoutRaising) { 937 AgcManagerDirectTestHelper helper(env_); 938 helper.CallAgcSequence(kInitialInputVolume, 939 GetOverrideOrEmpty(kHighSpeechProbability), 940 GetOverrideOrEmpty(kSpeechLevelDbfs)); 941 942 helper.manager.HandleCaptureOutputUsedChange(false); 943 helper.manager.HandleCaptureOutputUsedChange(true); 944 945 constexpr int kInputVolume = 127; 946 helper.manager.set_stream_analog_level(kInputVolume); 947 EXPECT_CALL(*helper.mock_agc, Reset()); 948 949 // SetMicVolume should not be called. 950 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)).WillOnce(Return(false)); 951 helper.CallProcess(/*num_calls=*/1, 952 GetOverrideOrEmpty(kHighSpeechProbability), 953 GetOverrideOrEmpty(kSpeechLevelDbfs)); 954 EXPECT_EQ(127, helper.manager.recommended_analog_level()); 955 } 956 957 TEST_P(AgcManagerDirectParametrizedTest, UnmutingRaisesTooLowVolume) { 958 AgcManagerDirectTestHelper helper(env_); 959 helper.CallAgcSequence(kInitialInputVolume, 960 GetOverrideOrEmpty(kHighSpeechProbability), 961 GetOverrideOrEmpty(kSpeechLevelDbfs)); 962 963 helper.manager.HandleCaptureOutputUsedChange(false); 964 helper.manager.HandleCaptureOutputUsedChange(true); 965 966 constexpr int kInputVolume = 11; 967 helper.manager.set_stream_analog_level(kInputVolume); 968 EXPECT_CALL(*helper.mock_agc, Reset()); 969 970 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)).WillOnce(Return(false)); 971 helper.CallProcess(/*num_calls=*/1, 972 GetOverrideOrEmpty(kHighSpeechProbability), 973 GetOverrideOrEmpty(kSpeechLevelDbfs)); 974 EXPECT_EQ(GetMinMicLevel(), helper.manager.recommended_analog_level()); 975 } 976 977 TEST_P(AgcManagerDirectParametrizedTest, 978 ManualLevelChangeResultsInNoSetMicCall) { 979 const auto speech_probability_override = 980 GetOverrideOrEmpty(kHighSpeechProbability); 981 982 AgcManagerDirectTestHelper helper(env_); 983 helper.CallAgcSequence(kInitialInputVolume, speech_probability_override, 984 GetOverrideOrEmpty(kSpeechLevelDbfs)); 985 986 // Change outside of compressor's range, which would normally trigger a call 987 // to `SetMicVolume()`. 988 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 989 .WillOnce(DoAll(SetArgPointee<0>(11), Return(true))); 990 991 // When the analog volume changes, the gain controller is reset. 992 EXPECT_CALL(*helper.mock_agc, Reset()).Times(AtLeast(1)); 993 994 // GetMicVolume returns a value outside of the quantization slack, indicating 995 // a manual volume change. 996 ASSERT_NE(helper.manager.recommended_analog_level(), 154); 997 helper.manager.set_stream_analog_level(154); 998 helper.CallProcess(/*num_calls=*/1, speech_probability_override, 999 GetOverrideOrEmpty(-29.0f)); 1000 EXPECT_EQ(154, helper.manager.recommended_analog_level()); 1001 1002 // Do the same thing, except downwards now. 1003 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 1004 .WillOnce(DoAll(SetArgPointee<0>(-1), Return(true))); 1005 helper.manager.set_stream_analog_level(100); 1006 EXPECT_CALL(*helper.mock_agc, Reset()).Times(AtLeast(1)); 1007 helper.CallProcess(/*num_calls=*/1, speech_probability_override, 1008 GetOverrideOrEmpty(-17.0f)); 1009 EXPECT_EQ(100, helper.manager.recommended_analog_level()); 1010 1011 // And finally verify the AGC continues working without a manual change. 1012 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 1013 .WillOnce(DoAll(SetArgPointee<0>(-1), Return(true))); 1014 helper.CallProcess(/*num_calls=*/1, speech_probability_override, 1015 GetOverrideOrEmpty(-17.0f)); 1016 EXPECT_EQ(99, helper.manager.recommended_analog_level()); 1017 } 1018 1019 TEST_P(AgcManagerDirectParametrizedTest, 1020 RecoveryAfterManualLevelChangeFromMax) { 1021 const auto speech_probability_override = 1022 GetOverrideOrEmpty(kHighSpeechProbability); 1023 1024 AgcManagerDirectTestHelper helper(env_); 1025 helper.CallAgcSequence(kInitialInputVolume, speech_probability_override, 1026 GetOverrideOrEmpty(kSpeechLevelDbfs)); 1027 1028 // Force the mic up to max volume. Takes a few steps due to the residual 1029 // gain limitation. 1030 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 1031 .WillRepeatedly(DoAll(SetArgPointee<0>(30), Return(true))); 1032 helper.CallProcess(/*num_calls=*/1, speech_probability_override, 1033 GetOverrideOrEmpty(-48.0f)); 1034 EXPECT_EQ(183, helper.manager.recommended_analog_level()); 1035 helper.CallProcess(/*num_calls=*/1, speech_probability_override, 1036 GetOverrideOrEmpty(-48.0f)); 1037 EXPECT_EQ(243, helper.manager.recommended_analog_level()); 1038 helper.CallProcess(/*num_calls=*/1, speech_probability_override, 1039 GetOverrideOrEmpty(-48.0f)); 1040 EXPECT_EQ(255, helper.manager.recommended_analog_level()); 1041 1042 // Manual change does not result in SetMicVolume call. 1043 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 1044 .WillOnce(DoAll(SetArgPointee<0>(-1), Return(true))); 1045 helper.manager.set_stream_analog_level(50); 1046 EXPECT_CALL(*helper.mock_agc, Reset()).Times(AtLeast(1)); 1047 helper.CallProcess(/*num_calls=*/1, speech_probability_override, 1048 GetOverrideOrEmpty(-17.0f)); 1049 EXPECT_EQ(50, helper.manager.recommended_analog_level()); 1050 1051 // Continues working as usual afterwards. 1052 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 1053 .WillOnce(DoAll(SetArgPointee<0>(20), Return(true))); 1054 helper.CallProcess(/*num_calls=*/1, speech_probability_override, 1055 GetOverrideOrEmpty(-38.0f)); 1056 1057 EXPECT_EQ(69, helper.manager.recommended_analog_level()); 1058 } 1059 1060 // Checks that, when the min mic level override is not specified, AGC ramps up 1061 // towards the minimum mic level after the mic level is manually set below the 1062 // minimum gain to enforce. 1063 TEST_P(AgcManagerDirectParametrizedTest, 1064 RecoveryAfterManualLevelChangeBelowMinWithoutMiMicLevelnOverride) { 1065 if (IsMinMicLevelOverridden()) { 1066 GTEST_SKIP() << "Skipped. Min mic level overridden."; 1067 } 1068 1069 const auto speech_probability_override = 1070 GetOverrideOrEmpty(kHighSpeechProbability); 1071 1072 AgcManagerDirectTestHelper helper(env_); 1073 helper.CallAgcSequence(kInitialInputVolume, speech_probability_override, 1074 GetOverrideOrEmpty(kSpeechLevelDbfs)); 1075 1076 // Manual change below min, but strictly positive, otherwise AGC won't take 1077 // any action. 1078 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 1079 .WillOnce(DoAll(SetArgPointee<0>(-1), Return(true))); 1080 helper.manager.set_stream_analog_level(1); 1081 EXPECT_CALL(*helper.mock_agc, Reset()).Times(AtLeast(1)); 1082 helper.CallProcess(/*num_calls=*/1, speech_probability_override, 1083 GetOverrideOrEmpty(-17.0f)); 1084 EXPECT_EQ(1, helper.manager.recommended_analog_level()); 1085 1086 // Continues working as usual afterwards. 1087 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 1088 .WillOnce(DoAll(SetArgPointee<0>(11), Return(true))); 1089 helper.CallProcess(/*num_calls=*/1, speech_probability_override, 1090 GetOverrideOrEmpty(-29.0f)); 1091 EXPECT_EQ(2, helper.manager.recommended_analog_level()); 1092 1093 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 1094 .WillOnce(DoAll(SetArgPointee<0>(30), Return(true))); 1095 helper.CallProcess(/*num_calls=*/1, speech_probability_override, 1096 GetOverrideOrEmpty(-48.0f)); 1097 EXPECT_EQ(11, helper.manager.recommended_analog_level()); 1098 1099 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 1100 .WillOnce(DoAll(SetArgPointee<0>(20), Return(true))); 1101 helper.CallProcess(/*num_calls=*/1, speech_probability_override, 1102 GetOverrideOrEmpty(-38.0f)); 1103 EXPECT_EQ(18, helper.manager.recommended_analog_level()); 1104 } 1105 1106 // Checks that, when the min mic level override is specified, AGC immediately 1107 // applies the minimum mic level after the mic level is manually set below the 1108 // minimum gain to enforce. 1109 TEST_P(AgcManagerDirectParametrizedTest, 1110 RecoveryAfterManualLevelChangeBelowMin) { 1111 if (!IsMinMicLevelOverridden()) { 1112 GTEST_SKIP() << "Skipped. Min mic level not overridden."; 1113 } 1114 1115 const auto speech_probability_override = 1116 GetOverrideOrEmpty(kHighSpeechProbability); 1117 1118 AgcManagerDirectTestHelper helper(env_); 1119 helper.CallAgcSequence(kInitialInputVolume, speech_probability_override, 1120 GetOverrideOrEmpty(kSpeechLevelDbfs)); 1121 1122 // Manual change below min, but strictly positive, otherwise 1123 // AGC won't take any action. 1124 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 1125 .WillOnce(DoAll(SetArgPointee<0>(-1), Return(true))); 1126 helper.manager.set_stream_analog_level(1); 1127 EXPECT_CALL(*helper.mock_agc, Reset()).Times(AtLeast(1)); 1128 helper.CallProcess(/*num_calls=*/1, speech_probability_override, 1129 GetOverrideOrEmpty(-17.0f)); 1130 EXPECT_EQ(GetMinMicLevel(), helper.manager.recommended_analog_level()); 1131 } 1132 1133 TEST_P(AgcManagerDirectParametrizedTest, NoClippingHasNoImpact) { 1134 AgcManagerDirectTestHelper helper(env_); 1135 helper.CallAgcSequence(kInitialInputVolume, 1136 GetOverrideOrEmpty(kHighSpeechProbability), 1137 GetOverrideOrEmpty(kSpeechLevelDbfs)); 1138 1139 helper.CallPreProc(/*num_calls=*/100, /*clipped_ratio=*/0); 1140 EXPECT_EQ(128, helper.manager.recommended_analog_level()); 1141 } 1142 1143 TEST_P(AgcManagerDirectParametrizedTest, ClippingUnderThresholdHasNoImpact) { 1144 AgcManagerDirectTestHelper helper(env_); 1145 helper.CallAgcSequence(kInitialInputVolume, 1146 GetOverrideOrEmpty(kHighSpeechProbability), 1147 GetOverrideOrEmpty(kSpeechLevelDbfs)); 1148 1149 helper.CallPreProc(/*num_calls=*/1, /*clipped_ratio=*/0.099); 1150 EXPECT_EQ(128, helper.manager.recommended_analog_level()); 1151 } 1152 1153 TEST_P(AgcManagerDirectParametrizedTest, ClippingLowersVolume) { 1154 AgcManagerDirectTestHelper helper(env_); 1155 helper.CallAgcSequence(/*applied_input_volume=*/255, 1156 GetOverrideOrEmpty(kHighSpeechProbability), 1157 GetOverrideOrEmpty(kSpeechLevelDbfs)); 1158 1159 EXPECT_CALL(*helper.mock_agc, Reset()).Times(AtLeast(1)); 1160 helper.CallPreProc(/*num_calls=*/1, /*clipped_ratio=*/0.2); 1161 EXPECT_EQ(240, helper.manager.recommended_analog_level()); 1162 } 1163 1164 TEST_P(AgcManagerDirectParametrizedTest, WaitingPeriodBetweenClippingChecks) { 1165 AgcManagerDirectTestHelper helper(env_); 1166 helper.CallAgcSequence(/*applied_input_volume=*/255, 1167 GetOverrideOrEmpty(kHighSpeechProbability), 1168 GetOverrideOrEmpty(kSpeechLevelDbfs)); 1169 1170 EXPECT_CALL(*helper.mock_agc, Reset()).Times(AtLeast(1)); 1171 helper.CallPreProc(/*num_calls=*/1, /*clipped_ratio=*/kAboveClippedThreshold); 1172 EXPECT_EQ(240, helper.manager.recommended_analog_level()); 1173 1174 EXPECT_CALL(*helper.mock_agc, Reset()).Times(0); 1175 helper.CallPreProc(/*num_calls=*/300, 1176 /*clipped_ratio=*/kAboveClippedThreshold); 1177 EXPECT_EQ(240, helper.manager.recommended_analog_level()); 1178 1179 EXPECT_CALL(*helper.mock_agc, Reset()).Times(AtLeast(1)); 1180 helper.CallPreProc(/*num_calls=*/1, /*clipped_ratio=*/kAboveClippedThreshold); 1181 EXPECT_EQ(225, helper.manager.recommended_analog_level()); 1182 } 1183 1184 TEST_P(AgcManagerDirectParametrizedTest, ClippingLoweringIsLimited) { 1185 AgcManagerDirectTestHelper helper(env_); 1186 helper.CallAgcSequence(/*applied_input_volume=*/180, 1187 GetOverrideOrEmpty(kHighSpeechProbability), 1188 GetOverrideOrEmpty(kSpeechLevelDbfs)); 1189 1190 EXPECT_CALL(*helper.mock_agc, Reset()).Times(AtLeast(1)); 1191 helper.CallPreProc(/*num_calls=*/1, /*clipped_ratio=*/kAboveClippedThreshold); 1192 EXPECT_EQ(kClippedMin, helper.manager.recommended_analog_level()); 1193 1194 EXPECT_CALL(*helper.mock_agc, Reset()).Times(0); 1195 helper.CallPreProc(/*num_calls=*/1000, 1196 /*clipped_ratio=*/kAboveClippedThreshold); 1197 EXPECT_EQ(kClippedMin, helper.manager.recommended_analog_level()); 1198 } 1199 1200 TEST_P(AgcManagerDirectParametrizedTest, 1201 ClippingMaxIsRespectedWhenEqualToLevel) { 1202 const auto speech_probability_override = 1203 GetOverrideOrEmpty(kHighSpeechProbability); 1204 1205 AgcManagerDirectTestHelper helper(env_); 1206 helper.CallAgcSequence(/*applied_input_volume=*/255, 1207 speech_probability_override, 1208 GetOverrideOrEmpty(kSpeechLevelDbfs)); 1209 1210 EXPECT_CALL(*helper.mock_agc, Reset()).Times(AtLeast(1)); 1211 helper.CallPreProc(/*num_calls=*/1, /*clipped_ratio=*/kAboveClippedThreshold); 1212 EXPECT_EQ(240, helper.manager.recommended_analog_level()); 1213 1214 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 1215 .WillRepeatedly(DoAll(SetArgPointee<0>(30), Return(true))); 1216 helper.CallProcess(/*num_calls=*/10, speech_probability_override, 1217 GetOverrideOrEmpty(-48.0f)); 1218 EXPECT_EQ(240, helper.manager.recommended_analog_level()); 1219 } 1220 1221 TEST_P(AgcManagerDirectParametrizedTest, 1222 ClippingMaxIsRespectedWhenHigherThanLevel) { 1223 const auto speech_probability_override = 1224 GetOverrideOrEmpty(kHighSpeechProbability); 1225 1226 AgcManagerDirectTestHelper helper(env_); 1227 helper.CallAgcSequence(/*applied_input_volume=*/200, 1228 speech_probability_override, 1229 GetOverrideOrEmpty(kSpeechLevelDbfs)); 1230 1231 EXPECT_CALL(*helper.mock_agc, Reset()).Times(AtLeast(1)); 1232 helper.CallPreProc(/*num_calls=*/1, /*clipped_ratio=*/kAboveClippedThreshold); 1233 EXPECT_EQ(185, helper.manager.recommended_analog_level()); 1234 1235 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 1236 .WillRepeatedly(DoAll(SetArgPointee<0>(40), Return(true))); 1237 helper.CallProcess(/*num_calls=*/1, speech_probability_override, 1238 GetOverrideOrEmpty(-58.0f)); 1239 EXPECT_EQ(240, helper.manager.recommended_analog_level()); 1240 helper.CallProcess(/*num_calls=*/10, speech_probability_override, 1241 GetOverrideOrEmpty(-58.0f)); 1242 EXPECT_EQ(240, helper.manager.recommended_analog_level()); 1243 } 1244 1245 TEST_P(AgcManagerDirectParametrizedTest, 1246 MaxCompressionIsIncreasedAfterClipping) { 1247 constexpr std::optional<float> kNoOverride = std::nullopt; 1248 const auto speech_probability_override = 1249 GetOverrideOrEmpty(kHighSpeechProbability); 1250 1251 AgcManagerDirectTestHelper helper(env_); 1252 helper.CallAgcSequence(/*applied_input_volume=*/210, 1253 speech_probability_override, 1254 GetOverrideOrEmpty(kSpeechLevelDbfs)); 1255 1256 EXPECT_CALL(*helper.mock_agc, Reset()).Times(AtLeast(1)); 1257 helper.CallPreProc(/*num_calls=*/1, kAboveClippedThreshold); 1258 EXPECT_EQ(195, helper.manager.recommended_analog_level()); 1259 1260 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 1261 .WillOnce(DoAll(SetArgPointee<0>(11), Return(true))) 1262 .WillOnce(DoAll(SetArgPointee<0>(11), Return(true))) 1263 .WillOnce(DoAll(SetArgPointee<0>(11), Return(true))) 1264 .WillOnce(DoAll(SetArgPointee<0>(11), Return(true))) 1265 .WillOnce(DoAll(SetArgPointee<0>(11), Return(true))) 1266 .WillRepeatedly(Return(false)); 1267 helper.CallProcess(/*num_calls=*/5, speech_probability_override, 1268 GetOverrideOrEmpty(-29.0f)); 1269 // The mock `GetRmsErrorDb()` returns false; mimic this by passing 1270 // std::nullopt as an override. 1271 helper.CallProcess(/*num_calls=*/14, kNoOverride, kNoOverride); 1272 EXPECT_CALL(helper.mock_gain_control, set_compression_gain_db(8)) 1273 .WillOnce(Return(0)); 1274 helper.CallProcess(/*num_calls=*/20, kNoOverride, kNoOverride); 1275 EXPECT_CALL(helper.mock_gain_control, set_compression_gain_db(9)) 1276 .WillOnce(Return(0)); 1277 helper.CallProcess(/*num_calls=*/20, kNoOverride, kNoOverride); 1278 EXPECT_CALL(helper.mock_gain_control, set_compression_gain_db(10)) 1279 .WillOnce(Return(0)); 1280 helper.CallProcess(/*num_calls=*/20, kNoOverride, kNoOverride); 1281 EXPECT_CALL(helper.mock_gain_control, set_compression_gain_db(11)) 1282 .WillOnce(Return(0)); 1283 helper.CallProcess(/*num_calls=*/20, kNoOverride, kNoOverride); 1284 EXPECT_CALL(helper.mock_gain_control, set_compression_gain_db(12)) 1285 .WillOnce(Return(0)); 1286 helper.CallProcess(/*num_calls=*/20, kNoOverride, kNoOverride); 1287 EXPECT_CALL(helper.mock_gain_control, set_compression_gain_db(13)) 1288 .WillOnce(Return(0)); 1289 helper.CallProcess(/*num_calls=*/1, kNoOverride, kNoOverride); 1290 1291 // Continue clipping until we hit the maximum surplus compression. 1292 helper.CallPreProc(/*num_calls=*/300, 1293 /*clipped_ratio=*/kAboveClippedThreshold); 1294 EXPECT_CALL(*helper.mock_agc, Reset()).Times(AtLeast(1)); 1295 helper.CallPreProc(/*num_calls=*/1, /*clipped_ratio=*/kAboveClippedThreshold); 1296 EXPECT_EQ(180, helper.manager.recommended_analog_level()); 1297 1298 helper.CallPreProc(/*num_calls=*/300, 1299 /*clipped_ratio=*/kAboveClippedThreshold); 1300 EXPECT_CALL(*helper.mock_agc, Reset()).Times(AtLeast(1)); 1301 helper.CallPreProc(1, kAboveClippedThreshold); 1302 EXPECT_EQ(kClippedMin, helper.manager.recommended_analog_level()); 1303 1304 // Current level is now at the minimum, but the maximum allowed level still 1305 // has more to decrease. 1306 helper.CallPreProc(/*num_calls=*/300, 1307 /*clipped_ratio=*/kAboveClippedThreshold); 1308 helper.CallPreProc(/*num_calls=*/1, /*clipped_ratio=*/kAboveClippedThreshold); 1309 1310 helper.CallPreProc(/*num_calls=*/300, 1311 /*clipped_ratio=*/kAboveClippedThreshold); 1312 helper.CallPreProc(/*num_calls=*/1, /*clipped_ratio=*/kAboveClippedThreshold); 1313 1314 helper.CallPreProc(/*num_calls=*/300, 1315 /*clipped_ratio=*/kAboveClippedThreshold); 1316 helper.CallPreProc(/*num_calls=*/1, /*clipped_ratio=*/kAboveClippedThreshold); 1317 1318 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 1319 .WillOnce(DoAll(SetArgPointee<0>(16), Return(true))) 1320 .WillOnce(DoAll(SetArgPointee<0>(16), Return(true))) 1321 .WillOnce(DoAll(SetArgPointee<0>(16), Return(true))) 1322 .WillOnce(DoAll(SetArgPointee<0>(16), Return(true))) 1323 .WillRepeatedly(Return(false)); 1324 helper.CallProcess(/*num_calls=*/4, speech_probability_override, 1325 GetOverrideOrEmpty(-34.0f)); 1326 helper.CallProcess(/*num_calls=*/15, kNoOverride, kNoOverride); 1327 EXPECT_CALL(helper.mock_gain_control, set_compression_gain_db(14)) 1328 .WillOnce(Return(0)); 1329 helper.CallProcess(/*num_calls=*/20, kNoOverride, kNoOverride); 1330 EXPECT_CALL(helper.mock_gain_control, set_compression_gain_db(15)) 1331 .WillOnce(Return(0)); 1332 helper.CallProcess(/*num_calls=*/20, kNoOverride, kNoOverride); 1333 EXPECT_CALL(helper.mock_gain_control, set_compression_gain_db(16)) 1334 .WillOnce(Return(0)); 1335 helper.CallProcess(/*num_calls=*/20, kNoOverride, kNoOverride); 1336 EXPECT_CALL(helper.mock_gain_control, set_compression_gain_db(17)) 1337 .WillOnce(Return(0)); 1338 helper.CallProcess(/*num_calls=*/20, kNoOverride, kNoOverride); 1339 EXPECT_CALL(helper.mock_gain_control, set_compression_gain_db(18)) 1340 .WillOnce(Return(0)); 1341 helper.CallProcess(/*num_calls=*/1, kNoOverride, kNoOverride); 1342 } 1343 1344 TEST_P(AgcManagerDirectParametrizedTest, UserCanRaiseVolumeAfterClipping) { 1345 const auto speech_probability_override = 1346 GetOverrideOrEmpty(kHighSpeechProbability); 1347 1348 AgcManagerDirectTestHelper helper(env_); 1349 helper.CallAgcSequence(/*applied_input_volume=*/225, 1350 speech_probability_override, 1351 GetOverrideOrEmpty(kSpeechLevelDbfs)); 1352 1353 EXPECT_CALL(*helper.mock_agc, Reset()).Times(AtLeast(1)); 1354 helper.CallPreProc(/*num_calls=*/1, /*clipped_ratio=*/kAboveClippedThreshold); 1355 EXPECT_EQ(210, helper.manager.recommended_analog_level()); 1356 1357 // High enough error to trigger a volume check. 1358 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 1359 .WillOnce(DoAll(SetArgPointee<0>(14), Return(true))); 1360 // User changed the volume. 1361 helper.manager.set_stream_analog_level(250); 1362 EXPECT_CALL(*helper.mock_agc, Reset()).Times(AtLeast(1)); 1363 helper.CallProcess(/*num_calls=*/1, speech_probability_override, 1364 GetOverrideOrEmpty(-32.0f)); 1365 EXPECT_EQ(250, helper.manager.recommended_analog_level()); 1366 1367 // Move down... 1368 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 1369 .WillOnce(DoAll(SetArgPointee<0>(-10), Return(true))); 1370 helper.CallProcess(/*num_calls=*/1, speech_probability_override, 1371 GetOverrideOrEmpty(-8.0f)); 1372 EXPECT_EQ(210, helper.manager.recommended_analog_level()); 1373 // And back up to the new max established by the user. 1374 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 1375 .WillOnce(DoAll(SetArgPointee<0>(40), Return(true))); 1376 helper.CallProcess(/*num_calls=*/1, speech_probability_override, 1377 GetOverrideOrEmpty(-58.0f)); 1378 EXPECT_EQ(250, helper.manager.recommended_analog_level()); 1379 // Will not move above new maximum. 1380 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 1381 .WillOnce(DoAll(SetArgPointee<0>(30), Return(true))); 1382 helper.CallProcess(/*num_calls=*/1, speech_probability_override, 1383 GetOverrideOrEmpty(-48.0f)); 1384 EXPECT_EQ(250, helper.manager.recommended_analog_level()); 1385 } 1386 1387 TEST_P(AgcManagerDirectParametrizedTest, ClippingDoesNotPullLowVolumeBackUp) { 1388 AgcManagerDirectTestHelper helper(env_); 1389 helper.CallAgcSequence(/*applied_input_volume=*/80, 1390 GetOverrideOrEmpty(kHighSpeechProbability), 1391 GetOverrideOrEmpty(kSpeechLevelDbfs)); 1392 1393 EXPECT_CALL(*helper.mock_agc, Reset()).Times(0); 1394 int initial_volume = helper.manager.recommended_analog_level(); 1395 helper.CallPreProc(/*num_calls=*/1, /*clipped_ratio=*/kAboveClippedThreshold); 1396 EXPECT_EQ(initial_volume, helper.manager.recommended_analog_level()); 1397 } 1398 1399 TEST_P(AgcManagerDirectParametrizedTest, TakesNoActionOnZeroMicVolume) { 1400 AgcManagerDirectTestHelper helper(env_); 1401 helper.CallAgcSequence(kInitialInputVolume, 1402 GetOverrideOrEmpty(kHighSpeechProbability), 1403 GetOverrideOrEmpty(kSpeechLevelDbfs)); 1404 1405 EXPECT_CALL(*helper.mock_agc, GetRmsErrorDb(_)) 1406 .WillRepeatedly(DoAll(SetArgPointee<0>(30), Return(true))); 1407 helper.manager.set_stream_analog_level(0); 1408 helper.CallProcess(/*num_calls=*/10, 1409 GetOverrideOrEmpty(kHighSpeechProbability), 1410 GetOverrideOrEmpty(-48.0f)); 1411 EXPECT_EQ(0, helper.manager.recommended_analog_level()); 1412 } 1413 1414 TEST_P(AgcManagerDirectParametrizedTest, ClippingDetectionLowersVolume) { 1415 AgcManagerDirectTestHelper helper(env_); 1416 helper.CallAgcSequence(/*applied_input_volume=*/255, 1417 GetOverrideOrEmpty(kHighSpeechProbability), 1418 GetOverrideOrEmpty(kSpeechLevelDbfs)); 1419 1420 EXPECT_EQ(255, helper.manager.recommended_analog_level()); 1421 helper.CallPreProcForChangingAudio(/*num_calls=*/100, /*peak_ratio=*/0.99f); 1422 EXPECT_EQ(255, helper.manager.recommended_analog_level()); 1423 helper.CallPreProcForChangingAudio(/*num_calls=*/100, /*peak_ratio=*/1.0f); 1424 EXPECT_EQ(240, helper.manager.recommended_analog_level()); 1425 } 1426 1427 TEST_P(AgcManagerDirectParametrizedTest, 1428 DisabledClippingPredictorDoesNotLowerVolume) { 1429 AgcManagerDirectTestHelper helper(env_); 1430 helper.CallAgcSequence(/*applied_input_volume=*/255, 1431 GetOverrideOrEmpty(kHighSpeechProbability), 1432 GetOverrideOrEmpty(kSpeechLevelDbfs)); 1433 1434 EXPECT_FALSE(helper.manager.clipping_predictor_enabled()); 1435 EXPECT_EQ(255, helper.manager.recommended_analog_level()); 1436 helper.CallPreProcForChangingAudio(/*num_calls=*/100, /*peak_ratio=*/0.99f); 1437 EXPECT_EQ(255, helper.manager.recommended_analog_level()); 1438 helper.CallPreProcForChangingAudio(/*num_calls=*/100, /*peak_ratio=*/0.99f); 1439 EXPECT_EQ(255, helper.manager.recommended_analog_level()); 1440 } 1441 1442 TEST_P(AgcManagerDirectParametrizedTest, DisableDigitalDisablesDigital) { 1443 if (IsRmsErrorOverridden()) { 1444 GTEST_SKIP() << "Skipped. RMS error override does not affect the test."; 1445 } 1446 1447 auto agc = std::unique_ptr<Agc>(new ::testing::NiceMock<MockAgc>()); 1448 MockGainControl mock_gain_control; 1449 EXPECT_CALL(mock_gain_control, set_mode(GainControl::kFixedDigital)); 1450 EXPECT_CALL(mock_gain_control, set_target_level_dbfs(0)); 1451 EXPECT_CALL(mock_gain_control, set_compression_gain_db(0)); 1452 EXPECT_CALL(mock_gain_control, enable_limiter(false)); 1453 1454 AnalogAgcConfig config; 1455 config.enable_digital_adaptive = false; 1456 auto manager = std::make_unique<AgcManagerDirect>(env_, kNumChannels, config); 1457 manager->Initialize(); 1458 manager->SetupDigitalGainControl(mock_gain_control); 1459 } 1460 1461 TEST(AgcManagerDirectTest, AgcMinMicLevelExperimentDefault) { 1462 std::unique_ptr<AgcManagerDirect> manager = CreateAgcManagerDirect(); 1463 EXPECT_EQ(manager->channel_agcs_[0]->min_mic_level(), kMinMicLevel); 1464 } 1465 1466 TEST(AgcManagerDirectTest, AgcMinMicLevelExperimentDisabled) { 1467 for (const std::string& field_trial_suffix : {"", "_20220210"}) { 1468 std::unique_ptr<AgcManagerDirect> manager = CreateAgcManagerDirect( 1469 {.field_trials = GetAgcMinMicLevelExperimentFieldTrial( 1470 "Disabled" + field_trial_suffix)}); 1471 EXPECT_EQ(manager->channel_agcs_[0]->min_mic_level(), kMinMicLevel); 1472 } 1473 } 1474 1475 // Checks that a field-trial parameter outside of the valid range [0,255] is 1476 // ignored. 1477 TEST(AgcManagerDirectTest, AgcMinMicLevelExperimentOutOfRangeAbove) { 1478 std::unique_ptr<AgcManagerDirect> manager = CreateAgcManagerDirect( 1479 {.field_trials = GetAgcMinMicLevelExperimentFieldTrial("Enabled-256")}); 1480 EXPECT_EQ(manager->channel_agcs_[0]->min_mic_level(), kMinMicLevel); 1481 } 1482 1483 // Checks that a field-trial parameter outside of the valid range [0,255] is 1484 // ignored. 1485 TEST(AgcManagerDirectTest, AgcMinMicLevelExperimentOutOfRangeBelow) { 1486 std::unique_ptr<AgcManagerDirect> manager = CreateAgcManagerDirect( 1487 {.field_trials = GetAgcMinMicLevelExperimentFieldTrial("Enabled--1")}); 1488 EXPECT_EQ(manager->channel_agcs_[0]->min_mic_level(), kMinMicLevel); 1489 } 1490 1491 // Verifies that a valid experiment changes the minimum microphone level. The 1492 // start volume is larger than the min level and should therefore not be 1493 // changed. 1494 TEST(AgcManagerDirectTest, AgcMinMicLevelExperimentEnabled50) { 1495 constexpr int kMinMicLevelOverride = 50; 1496 for (const std::string& field_trial_suffix : {"", "_20220210"}) { 1497 SCOPED_TRACE(field_trial_suffix); 1498 1499 std::unique_ptr<AgcManagerDirect> manager = CreateAgcManagerDirect( 1500 {.field_trials = GetAgcMinMicLevelExperimentFieldTrialEnabled( 1501 kMinMicLevelOverride, field_trial_suffix)}); 1502 1503 EXPECT_EQ(manager->channel_agcs_[0]->min_mic_level(), kMinMicLevelOverride); 1504 } 1505 } 1506 1507 // Checks that, when the "WebRTC-Audio-AgcMinMicLevelExperiment" field trial is 1508 // specified with a valid value, the mic level never gets lowered beyond the 1509 // override value in the presence of clipping. 1510 TEST(AgcManagerDirectTest, AgcMinMicLevelExperimentCheckMinLevelWithClipping) { 1511 constexpr int kMinMicLevelOverride = 250; 1512 1513 // Create and initialize two AGCs by specifying and leaving unspecified the 1514 // relevant field trial. 1515 std::unique_ptr<AgcManagerDirect> manager = CreateAgcManagerDirect(); 1516 std::unique_ptr<AgcManagerDirect> manager_with_override = 1517 CreateAgcManagerDirect( 1518 {.field_trials = GetAgcMinMicLevelExperimentFieldTrialEnabled( 1519 kMinMicLevelOverride)}); 1520 1521 // Create a test input signal which containts 80% of clipped samples. 1522 AudioBuffer audio_buffer(kSampleRateHz, 1, kSampleRateHz, 1, kSampleRateHz, 1523 1); 1524 WriteAudioBufferSamples(/*samples_value=*/4000.0f, /*clipped_ratio=*/0.8f, 1525 audio_buffer); 1526 1527 // Simulate 4 seconds of clipping; it is expected to trigger a downward 1528 // adjustment of the analog gain. 1529 CallPreProcessAndProcess(/*num_calls=*/400, audio_buffer, 1530 /*speech_probability_override=*/std::nullopt, 1531 /*speech_level_override=*/std::nullopt, *manager); 1532 CallPreProcessAndProcess(/*num_calls=*/400, audio_buffer, 1533 /*speech_probability_override=*/std::nullopt, 1534 /*speech_level_override=*/std::nullopt, 1535 *manager_with_override); 1536 1537 // Make sure that an adaptation occurred. 1538 ASSERT_GT(manager->recommended_analog_level(), 0); 1539 1540 // Check that the test signal triggers a larger downward adaptation for 1541 // `manager`, which is allowed to reach a lower gain. 1542 EXPECT_GT(manager_with_override->recommended_analog_level(), 1543 manager->recommended_analog_level()); 1544 // Check that the gain selected by `manager_with_override` equals the minimum 1545 // value overridden via field trial. 1546 EXPECT_EQ(manager_with_override->recommended_analog_level(), 1547 kMinMicLevelOverride); 1548 } 1549 1550 // Checks that, when the "WebRTC-Audio-AgcMinMicLevelExperiment" field trial is 1551 // specified with a valid value, the mic level never gets lowered beyond the 1552 // override value in the presence of clipping when RMS error override is used. 1553 // TODO(webrtc:7494): Revisit the test after moving the number of override wait 1554 // frames to APM config. The test passes but internally the gain update timing 1555 // differs. 1556 TEST(AgcManagerDirectTest, 1557 AgcMinMicLevelExperimentCheckMinLevelWithClippingWithRmsErrorOverride) { 1558 constexpr int kMinMicLevelOverride = 250; 1559 1560 // Create and initialize two AGCs by specifying and leaving unspecified the 1561 // relevant field trial. 1562 std::unique_ptr<AgcManagerDirect> manager = CreateAgcManagerDirect(); 1563 std::unique_ptr<AgcManagerDirect> manager_with_override = 1564 CreateAgcManagerDirect( 1565 {.field_trials = GetAgcMinMicLevelExperimentFieldTrialEnabled( 1566 kMinMicLevelOverride)}); 1567 1568 // Create a test input signal which containts 80% of clipped samples. 1569 AudioBuffer audio_buffer(kSampleRateHz, 1, kSampleRateHz, 1, kSampleRateHz, 1570 1); 1571 WriteAudioBufferSamples(/*samples_value=*/4000.0f, /*clipped_ratio=*/0.8f, 1572 audio_buffer); 1573 1574 // Simulate 4 seconds of clipping; it is expected to trigger a downward 1575 // adjustment of the analog gain. 1576 CallPreProcessAndProcess( 1577 /*num_calls=*/400, audio_buffer, 1578 /*speech_probability_override=*/0.7f, 1579 /*speech_probability_level=*/-18.0f, *manager); 1580 CallPreProcessAndProcess( 1581 /*num_calls=*/400, audio_buffer, 1582 /*speech_probability_override=*/std::optional<float>(0.7f), 1583 /*speech_probability_level=*/std::optional<float>(-18.0f), 1584 *manager_with_override); 1585 1586 // Make sure that an adaptation occurred. 1587 ASSERT_GT(manager->recommended_analog_level(), 0); 1588 1589 // Check that the test signal triggers a larger downward adaptation for 1590 // `manager`, which is allowed to reach a lower gain. 1591 EXPECT_GT(manager_with_override->recommended_analog_level(), 1592 manager->recommended_analog_level()); 1593 // Check that the gain selected by `manager_with_override` equals the minimum 1594 // value overridden via field trial. 1595 EXPECT_EQ(manager_with_override->recommended_analog_level(), 1596 kMinMicLevelOverride); 1597 } 1598 1599 // Checks that, when the "WebRTC-Audio-AgcMinMicLevelExperiment" field trial is 1600 // specified with a value lower than the `clipped_level_min`, the behavior of 1601 // the analog gain controller is the same as that obtained when the field trial 1602 // is not specified. 1603 TEST(AgcManagerDirectTest, 1604 AgcMinMicLevelExperimentCompareMicLevelWithClipping) { 1605 // Create and initialize two AGCs by specifying and leaving unspecified the 1606 // relevant field trial. 1607 // Use a large clipped level step to more quickly decrease the analog gain 1608 // with clipping. 1609 std::unique_ptr<AgcManagerDirect> manager = CreateAgcManagerDirect({ 1610 .clipped_level_min = kDefaultAnalogConfig.clipped_level_min, 1611 .enable_digital_adaptive = false, 1612 .clipped_level_step = 64, 1613 }); 1614 1615 constexpr int kMinMicLevelOverride = 20; 1616 static_assert(kDefaultAnalogConfig.clipped_level_min >= kMinMicLevelOverride, 1617 "Use a lower override value."); 1618 std::unique_ptr<AgcManagerDirect> manager_with_override = 1619 CreateAgcManagerDirect({ 1620 .field_trials = GetAgcMinMicLevelExperimentFieldTrialEnabled( 1621 kMinMicLevelOverride), 1622 .clipped_level_min = kDefaultAnalogConfig.clipped_level_min, 1623 .enable_digital_adaptive = false, 1624 .clipped_level_step = 64, 1625 }); 1626 1627 // Create a test input signal which containts 80% of clipped samples. 1628 AudioBuffer audio_buffer(kSampleRateHz, 1, kSampleRateHz, 1, kSampleRateHz, 1629 1); 1630 WriteAudioBufferSamples(/*samples_value=*/4000.0f, /*clipped_ratio=*/0.8f, 1631 audio_buffer); 1632 1633 // Simulate 4 seconds of clipping; it is expected to trigger a downward 1634 // adjustment of the analog gain. 1635 CallPreProcessAndProcess(/*num_calls=*/400, audio_buffer, 1636 /*speech_probability_override=*/std::nullopt, 1637 /*speech_level_override=*/std::nullopt, *manager); 1638 CallPreProcessAndProcess(/*num_calls=*/400, audio_buffer, 1639 /*speech_probability_override=*/std::nullopt, 1640 /*speech_level_override=*/std::nullopt, 1641 *manager_with_override); 1642 1643 // Make sure that an adaptation occurred. 1644 ASSERT_GT(manager->recommended_analog_level(), 0); 1645 1646 // Check that the selected analog gain is the same for both controllers and 1647 // that it equals the minimum level reached when clipping is handled. That is 1648 // expected because the minimum microphone level override is less than the 1649 // minimum level used when clipping is detected. 1650 EXPECT_EQ(manager->recommended_analog_level(), 1651 manager_with_override->recommended_analog_level()); 1652 EXPECT_EQ(manager_with_override->recommended_analog_level(), 1653 kDefaultAnalogConfig.clipped_level_min); 1654 } 1655 1656 // Checks that, when the "WebRTC-Audio-AgcMinMicLevelExperiment" field trial is 1657 // specified with a value lower than the `clipped_level_min`, the behavior of 1658 // the analog gain controller is the same as that obtained when the field trial 1659 // is not specified. 1660 // TODO(webrtc:7494): Revisit the test after moving the number of override wait 1661 // frames to APM config. The test passes but internally the gain update timing 1662 // differs. 1663 TEST(AgcManagerDirectTest, 1664 AgcMinMicLevelExperimentCompareMicLevelWithClippingWithRmsErrorOverride) { 1665 // Create and initialize two AGCs by specifying and leaving unspecified the 1666 // relevant field trial. 1667 std::unique_ptr<AgcManagerDirect> manager = CreateAgcManagerDirect({ 1668 .clipped_level_min = kDefaultAnalogConfig.clipped_level_min, 1669 .enable_digital_adaptive = false, 1670 .clipped_level_step = 64, 1671 }); 1672 1673 constexpr int kMinMicLevelOverride = 20; 1674 static_assert(kDefaultAnalogConfig.clipped_level_min >= kMinMicLevelOverride, 1675 "Use a lower override value."); 1676 std::unique_ptr<AgcManagerDirect> manager_with_override = 1677 CreateAgcManagerDirect({ 1678 .field_trials = GetAgcMinMicLevelExperimentFieldTrialEnabled( 1679 kMinMicLevelOverride), 1680 .clipped_level_min = kDefaultAnalogConfig.clipped_level_min, 1681 .enable_digital_adaptive = false, 1682 .clipped_level_step = 64, 1683 }); 1684 1685 // Create a test input signal which containts 80% of clipped samples. 1686 AudioBuffer audio_buffer(kSampleRateHz, 1, kSampleRateHz, 1, kSampleRateHz, 1687 1); 1688 WriteAudioBufferSamples(/*samples_value=*/4000.0f, /*clipped_ratio=*/0.8f, 1689 audio_buffer); 1690 1691 CallPreProcessAndProcess( 1692 /*num_calls=*/400, audio_buffer, 1693 /*speech_probability_override=*/std::optional<float>(0.7f), 1694 /*speech_level_override=*/std::optional<float>(-18.0f), *manager); 1695 CallPreProcessAndProcess( 1696 /*num_calls=*/400, audio_buffer, 1697 /*speech_probability_override=*/std::optional<float>(0.7f), 1698 /*speech_level_override=*/std::optional<float>(-18.0f), 1699 *manager_with_override); 1700 1701 // Make sure that an adaptation occurred. 1702 ASSERT_GT(manager->recommended_analog_level(), 0); 1703 1704 // Check that the selected analog gain is the same for both controllers and 1705 // that it equals the minimum level reached when clipping is handled. That is 1706 // expected because the minimum microphone level override is less than the 1707 // minimum level used when clipping is detected. 1708 EXPECT_EQ(manager->recommended_analog_level(), 1709 manager_with_override->recommended_analog_level()); 1710 EXPECT_EQ(manager_with_override->recommended_analog_level(), 1711 kDefaultAnalogConfig.clipped_level_min); 1712 } 1713 1714 // TODO(bugs.webrtc.org/12774): Test the bahavior of `clipped_level_step`. 1715 // TODO(bugs.webrtc.org/12774): Test the bahavior of `clipped_ratio_threshold`. 1716 // TODO(bugs.webrtc.org/12774): Test the bahavior of `clipped_wait_frames`. 1717 // Verifies that configurable clipping parameters are initialized as intended. 1718 TEST_P(AgcManagerDirectParametrizedTest, ClippingParametersVerified) { 1719 if (IsRmsErrorOverridden()) { 1720 GTEST_SKIP() << "Skipped. RMS error override does not affect the test."; 1721 } 1722 1723 std::unique_ptr<AgcManagerDirect> manager = CreateAgcManagerDirect(); 1724 EXPECT_EQ(manager->clipped_level_step_, kClippedLevelStep); 1725 EXPECT_EQ(manager->clipped_ratio_threshold_, kClippedRatioThreshold); 1726 EXPECT_EQ(manager->clipped_wait_frames_, kClippedWaitFrames); 1727 1728 std::unique_ptr<AgcManagerDirect> manager_custom = 1729 CreateAgcManagerDirect({.clipped_level_step = 10, 1730 .clipped_ratio_threshold = 0.2f, 1731 .clipped_wait_frames = 50}); 1732 EXPECT_EQ(manager_custom->clipped_level_step_, 10); 1733 EXPECT_EQ(manager_custom->clipped_ratio_threshold_, 0.2f); 1734 EXPECT_EQ(manager_custom->clipped_wait_frames_, 50); 1735 } 1736 1737 TEST_P(AgcManagerDirectParametrizedTest, 1738 DisableClippingPredictorDisablesClippingPredictor) { 1739 if (IsRmsErrorOverridden()) { 1740 GTEST_SKIP() << "Skipped. RMS error override does not affect the test."; 1741 } 1742 1743 std::unique_ptr<AgcManagerDirect> manager = 1744 CreateAgcManagerDirect({.clipping_predictor = {.enabled = false}}); 1745 1746 EXPECT_FALSE(manager->clipping_predictor_enabled()); 1747 EXPECT_FALSE(manager->use_clipping_predictor_step()); 1748 } 1749 1750 TEST_P(AgcManagerDirectParametrizedTest, ClippingPredictorDisabledByDefault) { 1751 if (IsRmsErrorOverridden()) { 1752 GTEST_SKIP() << "Skipped. RMS error override does not affect the test."; 1753 } 1754 1755 constexpr ClippingPredictorConfig kDefaultConfig; 1756 EXPECT_FALSE(kDefaultConfig.enabled); 1757 } 1758 1759 TEST_P(AgcManagerDirectParametrizedTest, 1760 EnableClippingPredictorEnablesClippingPredictor) { 1761 if (IsRmsErrorOverridden()) { 1762 GTEST_SKIP() << "Skipped. RMS error override does not affect the test."; 1763 } 1764 1765 std::unique_ptr<AgcManagerDirect> manager = CreateAgcManagerDirect( 1766 {.clipping_predictor = {.enabled = true, .use_predicted_step = true}}); 1767 1768 EXPECT_TRUE(manager->clipping_predictor_enabled()); 1769 EXPECT_TRUE(manager->use_clipping_predictor_step()); 1770 } 1771 1772 TEST_P(AgcManagerDirectParametrizedTest, 1773 DisableClippingPredictorDoesNotLowerVolume) { 1774 AudioBuffer audio_buffer(kSampleRateHz, kNumChannels, kSampleRateHz, 1775 kNumChannels, kSampleRateHz, kNumChannels); 1776 1777 AnalogAgcConfig config = GetAnalogAgcTestConfig(); 1778 config.clipping_predictor.enabled = false; 1779 AgcManagerDirect manager(env_, config, new ::testing::NiceMock<MockAgc>()); 1780 manager.Initialize(); 1781 manager.set_stream_analog_level(/*level=*/255); 1782 EXPECT_FALSE(manager.clipping_predictor_enabled()); 1783 EXPECT_FALSE(manager.use_clipping_predictor_step()); 1784 EXPECT_EQ(manager.recommended_analog_level(), 255); 1785 manager.Process(audio_buffer, GetOverrideOrEmpty(kHighSpeechProbability), 1786 GetOverrideOrEmpty(kSpeechLevelDbfs)); 1787 CallPreProcessAudioBuffer(/*num_calls=*/10, /*peak_ratio=*/0.99f, manager); 1788 EXPECT_EQ(manager.recommended_analog_level(), 255); 1789 CallPreProcessAudioBuffer(/*num_calls=*/300, /*peak_ratio=*/0.99f, manager); 1790 EXPECT_EQ(manager.recommended_analog_level(), 255); 1791 CallPreProcessAudioBuffer(/*num_calls=*/10, /*peak_ratio=*/0.99f, manager); 1792 EXPECT_EQ(manager.recommended_analog_level(), 255); 1793 } 1794 1795 TEST_P(AgcManagerDirectParametrizedTest, 1796 UsedClippingPredictionsProduceLowerAnalogLevels) { 1797 AudioBuffer audio_buffer(kSampleRateHz, kNumChannels, kSampleRateHz, 1798 kNumChannels, kSampleRateHz, kNumChannels); 1799 1800 AnalogAgcConfig config_with_prediction = GetAnalogAgcTestConfig(); 1801 config_with_prediction.clipping_predictor.enabled = true; 1802 config_with_prediction.clipping_predictor.use_predicted_step = true; 1803 AnalogAgcConfig config_without_prediction = GetAnalogAgcTestConfig(); 1804 config_without_prediction.clipping_predictor.enabled = false; 1805 AgcManagerDirect manager_with_prediction(env_, config_with_prediction, 1806 new ::testing::NiceMock<MockAgc>()); 1807 AgcManagerDirect manager_without_prediction( 1808 env_, config_without_prediction, new ::testing::NiceMock<MockAgc>()); 1809 1810 manager_with_prediction.Initialize(); 1811 manager_without_prediction.Initialize(); 1812 1813 constexpr int kInitialLevel = 255; 1814 constexpr float kClippingPeakRatio = 1.0f; 1815 constexpr float kCloseToClippingPeakRatio = 0.99f; 1816 constexpr float kZeroPeakRatio = 0.0f; 1817 manager_with_prediction.set_stream_analog_level(kInitialLevel); 1818 manager_without_prediction.set_stream_analog_level(kInitialLevel); 1819 manager_with_prediction.Process(audio_buffer, 1820 GetOverrideOrEmpty(kHighSpeechProbability), 1821 GetOverrideOrEmpty(kSpeechLevelDbfs)); 1822 manager_without_prediction.Process(audio_buffer, 1823 GetOverrideOrEmpty(kHighSpeechProbability), 1824 GetOverrideOrEmpty(kSpeechLevelDbfs)); 1825 EXPECT_TRUE(manager_with_prediction.clipping_predictor_enabled()); 1826 EXPECT_FALSE(manager_without_prediction.clipping_predictor_enabled()); 1827 EXPECT_TRUE(manager_with_prediction.use_clipping_predictor_step()); 1828 EXPECT_EQ(manager_with_prediction.recommended_analog_level(), kInitialLevel); 1829 EXPECT_EQ(manager_without_prediction.recommended_analog_level(), 1830 kInitialLevel); 1831 1832 // Expect a change in the analog level when the prediction step is used. 1833 CallPreProcessAudioBuffer(/*num_calls=*/10, kCloseToClippingPeakRatio, 1834 manager_with_prediction); 1835 CallPreProcessAudioBuffer(/*num_calls=*/10, kCloseToClippingPeakRatio, 1836 manager_without_prediction); 1837 EXPECT_EQ(manager_with_prediction.recommended_analog_level(), 1838 kInitialLevel - kClippedLevelStep); 1839 EXPECT_EQ(manager_without_prediction.recommended_analog_level(), 1840 kInitialLevel); 1841 1842 // Expect no change during waiting. 1843 CallPreProcessAudioBuffer(kClippedWaitFrames, kCloseToClippingPeakRatio, 1844 manager_with_prediction); 1845 CallPreProcessAudioBuffer(kClippedWaitFrames, kCloseToClippingPeakRatio, 1846 manager_without_prediction); 1847 EXPECT_EQ(manager_with_prediction.recommended_analog_level(), 1848 kInitialLevel - kClippedLevelStep); 1849 EXPECT_EQ(manager_without_prediction.recommended_analog_level(), 1850 kInitialLevel); 1851 1852 // Expect a change when the prediction step is used. 1853 CallPreProcessAudioBuffer(/*num_calls=*/10, kCloseToClippingPeakRatio, 1854 manager_with_prediction); 1855 CallPreProcessAudioBuffer(/*num_calls=*/10, kCloseToClippingPeakRatio, 1856 manager_without_prediction); 1857 EXPECT_EQ(manager_with_prediction.recommended_analog_level(), 1858 kInitialLevel - 2 * kClippedLevelStep); 1859 EXPECT_EQ(manager_without_prediction.recommended_analog_level(), 1860 kInitialLevel); 1861 1862 // Expect no change when clipping is not detected or predicted. 1863 CallPreProcessAudioBuffer(2 * kClippedWaitFrames, kZeroPeakRatio, 1864 manager_with_prediction); 1865 CallPreProcessAudioBuffer(2 * kClippedWaitFrames, kZeroPeakRatio, 1866 manager_without_prediction); 1867 EXPECT_EQ(manager_with_prediction.recommended_analog_level(), 1868 kInitialLevel - 2 * kClippedLevelStep); 1869 EXPECT_EQ(manager_without_prediction.recommended_analog_level(), 1870 kInitialLevel); 1871 1872 // Expect a change for clipping frames. 1873 CallPreProcessAudioBuffer(/*num_calls=*/1, kClippingPeakRatio, 1874 manager_with_prediction); 1875 CallPreProcessAudioBuffer(/*num_calls=*/1, kClippingPeakRatio, 1876 manager_without_prediction); 1877 EXPECT_EQ(manager_with_prediction.recommended_analog_level(), 1878 kInitialLevel - 3 * kClippedLevelStep); 1879 EXPECT_EQ(manager_without_prediction.recommended_analog_level(), 1880 kInitialLevel - kClippedLevelStep); 1881 1882 // Expect no change during waiting. 1883 CallPreProcessAudioBuffer(kClippedWaitFrames, kClippingPeakRatio, 1884 manager_with_prediction); 1885 CallPreProcessAudioBuffer(kClippedWaitFrames, kClippingPeakRatio, 1886 manager_without_prediction); 1887 EXPECT_EQ(manager_with_prediction.recommended_analog_level(), 1888 kInitialLevel - 3 * kClippedLevelStep); 1889 EXPECT_EQ(manager_without_prediction.recommended_analog_level(), 1890 kInitialLevel - kClippedLevelStep); 1891 1892 // Expect a change for clipping frames. 1893 CallPreProcessAudioBuffer(/*num_calls=*/1, kClippingPeakRatio, 1894 manager_with_prediction); 1895 CallPreProcessAudioBuffer(/*num_calls=*/1, kClippingPeakRatio, 1896 manager_without_prediction); 1897 EXPECT_EQ(manager_with_prediction.recommended_analog_level(), 1898 kInitialLevel - 4 * kClippedLevelStep); 1899 EXPECT_EQ(manager_without_prediction.recommended_analog_level(), 1900 kInitialLevel - 2 * kClippedLevelStep); 1901 } 1902 1903 TEST_P(AgcManagerDirectParametrizedTest, 1904 UnusedClippingPredictionsProduceEqualAnalogLevels) { 1905 AudioBuffer audio_buffer(kSampleRateHz, kNumChannels, kSampleRateHz, 1906 kNumChannels, kSampleRateHz, kNumChannels); 1907 1908 AnalogAgcConfig config_with_prediction = GetAnalogAgcTestConfig(); 1909 config_with_prediction.clipping_predictor.enabled = true; 1910 config_with_prediction.clipping_predictor.use_predicted_step = false; 1911 AnalogAgcConfig config_without_prediction = GetAnalogAgcTestConfig(); 1912 config_without_prediction.clipping_predictor.enabled = false; 1913 AgcManagerDirect manager_with_prediction(env_, config_with_prediction, 1914 new ::testing::NiceMock<MockAgc>()); 1915 AgcManagerDirect manager_without_prediction( 1916 env_, config_without_prediction, new ::testing::NiceMock<MockAgc>()); 1917 1918 constexpr int kInitialLevel = 255; 1919 constexpr float kClippingPeakRatio = 1.0f; 1920 constexpr float kCloseToClippingPeakRatio = 0.99f; 1921 constexpr float kZeroPeakRatio = 0.0f; 1922 manager_with_prediction.Initialize(); 1923 manager_without_prediction.Initialize(); 1924 manager_with_prediction.set_stream_analog_level(kInitialLevel); 1925 manager_without_prediction.set_stream_analog_level(kInitialLevel); 1926 manager_with_prediction.Process(audio_buffer, 1927 GetOverrideOrEmpty(kHighSpeechProbability), 1928 GetOverrideOrEmpty(kSpeechLevelDbfs)); 1929 manager_without_prediction.Process(audio_buffer, 1930 GetOverrideOrEmpty(kHighSpeechProbability), 1931 GetOverrideOrEmpty(kSpeechLevelDbfs)); 1932 1933 EXPECT_TRUE(manager_with_prediction.clipping_predictor_enabled()); 1934 EXPECT_FALSE(manager_without_prediction.clipping_predictor_enabled()); 1935 EXPECT_FALSE(manager_with_prediction.use_clipping_predictor_step()); 1936 EXPECT_EQ(manager_with_prediction.recommended_analog_level(), kInitialLevel); 1937 EXPECT_EQ(manager_without_prediction.recommended_analog_level(), 1938 kInitialLevel); 1939 1940 // Expect no change in the analog level for non-clipping frames. 1941 CallPreProcessAudioBuffer(/*num_calls=*/10, kCloseToClippingPeakRatio, 1942 manager_with_prediction); 1943 CallPreProcessAudioBuffer(/*num_calls=*/10, kCloseToClippingPeakRatio, 1944 manager_without_prediction); 1945 EXPECT_EQ(manager_with_prediction.recommended_analog_level(), 1946 manager_without_prediction.recommended_analog_level()); 1947 1948 // Expect no change for non-clipping frames. 1949 CallPreProcessAudioBuffer(kClippedWaitFrames, kCloseToClippingPeakRatio, 1950 manager_with_prediction); 1951 CallPreProcessAudioBuffer(kClippedWaitFrames, kCloseToClippingPeakRatio, 1952 manager_without_prediction); 1953 EXPECT_EQ(manager_with_prediction.recommended_analog_level(), 1954 manager_without_prediction.recommended_analog_level()); 1955 1956 // Expect no change for non-clipping frames. 1957 CallPreProcessAudioBuffer(/*num_calls=*/10, kCloseToClippingPeakRatio, 1958 manager_with_prediction); 1959 CallPreProcessAudioBuffer(/*num_calls=*/10, kCloseToClippingPeakRatio, 1960 manager_without_prediction); 1961 EXPECT_EQ(manager_with_prediction.recommended_analog_level(), 1962 manager_without_prediction.recommended_analog_level()); 1963 1964 // Expect no change when clipping is not detected or predicted. 1965 CallPreProcessAudioBuffer(2 * kClippedWaitFrames, kZeroPeakRatio, 1966 manager_with_prediction); 1967 CallPreProcessAudioBuffer(2 * kClippedWaitFrames, kZeroPeakRatio, 1968 manager_without_prediction); 1969 EXPECT_EQ(manager_with_prediction.recommended_analog_level(), 1970 manager_without_prediction.recommended_analog_level()); 1971 1972 // Expect a change for clipping frames. 1973 CallPreProcessAudioBuffer(/*num_calls=*/1, kClippingPeakRatio, 1974 manager_with_prediction); 1975 CallPreProcessAudioBuffer(/*num_calls=*/1, kClippingPeakRatio, 1976 manager_without_prediction); 1977 EXPECT_EQ(manager_with_prediction.recommended_analog_level(), 1978 manager_without_prediction.recommended_analog_level()); 1979 1980 // Expect no change during waiting. 1981 CallPreProcessAudioBuffer(kClippedWaitFrames, kClippingPeakRatio, 1982 manager_with_prediction); 1983 CallPreProcessAudioBuffer(kClippedWaitFrames, kClippingPeakRatio, 1984 manager_without_prediction); 1985 EXPECT_EQ(manager_with_prediction.recommended_analog_level(), 1986 manager_without_prediction.recommended_analog_level()); 1987 1988 // Expect a change for clipping frames. 1989 CallPreProcessAudioBuffer(/*num_calls=*/1, kClippingPeakRatio, 1990 manager_with_prediction); 1991 CallPreProcessAudioBuffer(/*num_calls=*/1, kClippingPeakRatio, 1992 manager_without_prediction); 1993 EXPECT_EQ(manager_with_prediction.recommended_analog_level(), 1994 manager_without_prediction.recommended_analog_level()); 1995 } 1996 1997 // Checks that passing an empty speech level and probability overrides to 1998 // `Process()` has the same effect as passing no overrides. 1999 TEST_P(AgcManagerDirectParametrizedTest, EmptyRmsErrorOverrideHasNoEffect) { 2000 AgcManagerDirect manager_1(env_, kNumChannels, GetAnalogAgcTestConfig()); 2001 AgcManagerDirect manager_2(env_, kNumChannels, GetAnalogAgcTestConfig()); 2002 manager_1.Initialize(); 2003 manager_2.Initialize(); 2004 2005 constexpr int kAnalogLevel = 50; 2006 manager_1.set_stream_analog_level(kAnalogLevel); 2007 manager_2.set_stream_analog_level(kAnalogLevel); 2008 2009 // Feed speech with low energy to trigger an upward adapation of the analog 2010 // level. 2011 constexpr int kNumFrames = 125; 2012 constexpr int kGainDb = -20; 2013 SpeechSamplesReader reader; 2014 2015 // Check the initial input volume. 2016 ASSERT_EQ(manager_1.recommended_analog_level(), kAnalogLevel); 2017 ASSERT_EQ(manager_2.recommended_analog_level(), kAnalogLevel); 2018 2019 reader.Feed(kNumFrames, kGainDb, std::nullopt, std::nullopt, manager_1); 2020 reader.Feed(kNumFrames, kGainDb, manager_2); 2021 2022 // Check that the states are the same and adaptation occurs. 2023 EXPECT_EQ(manager_1.recommended_analog_level(), 2024 manager_2.recommended_analog_level()); 2025 ASSERT_GT(manager_1.recommended_analog_level(), kAnalogLevel); 2026 EXPECT_EQ(manager_1.voice_probability(), manager_2.voice_probability()); 2027 EXPECT_EQ(manager_1.frames_since_clipped_, manager_2.frames_since_clipped_); 2028 2029 // Check that the states of the channel AGCs are the same. 2030 EXPECT_EQ(manager_1.num_channels(), manager_2.num_channels()); 2031 for (int i = 0; i < manager_1.num_channels(); ++i) { 2032 EXPECT_EQ(manager_1.channel_agcs_[i]->recommended_analog_level(), 2033 manager_2.channel_agcs_[i]->recommended_analog_level()); 2034 EXPECT_EQ(manager_1.channel_agcs_[i]->voice_probability(), 2035 manager_2.channel_agcs_[i]->voice_probability()); 2036 } 2037 } 2038 2039 // Checks that passing a non-empty speech level and probability overrides to 2040 // `Process()` has an effect. 2041 TEST_P(AgcManagerDirectParametrizedTest, NonEmptyRmsErrorOverrideHasEffect) { 2042 AgcManagerDirect manager_1(env_, kNumChannels, GetAnalogAgcTestConfig()); 2043 AgcManagerDirect manager_2(env_, kNumChannels, GetAnalogAgcTestConfig()); 2044 manager_1.Initialize(); 2045 manager_2.Initialize(); 2046 2047 constexpr int kInputVolume = 128; 2048 manager_1.set_stream_analog_level(kInputVolume); 2049 manager_2.set_stream_analog_level(kInputVolume); 2050 2051 // Feed speech with low energy to trigger an upward adapation of the input 2052 // volume. 2053 constexpr int kNumFrames = 125; 2054 constexpr int kGainDb = -20; 2055 SpeechSamplesReader reader; 2056 2057 // Make sure that the feeding samples triggers an adaptation when no override 2058 // is specified. 2059 reader.Feed(kNumFrames, kGainDb, manager_1); 2060 ASSERT_GT(manager_1.recommended_analog_level(), kInputVolume); 2061 2062 // Expect that feeding samples triggers an adaptation when the speech 2063 // probability and speech level overrides are specified. 2064 reader.Feed(kNumFrames, kGainDb, 2065 /*speech_probability_override=*/kHighSpeechProbability, 2066 /*speech_level_override=*/-45.0f, manager_2); 2067 EXPECT_GT(manager_2.recommended_analog_level(), kInputVolume); 2068 2069 // The voice probability override does not affect the `voice_probability()` 2070 // getter. 2071 EXPECT_EQ(manager_1.voice_probability(), manager_2.voice_probability()); 2072 } 2073 2074 class AgcManagerDirectChannelSampleRateTest 2075 : public ::testing::TestWithParam<std::tuple<int, int>> { 2076 protected: 2077 int GetNumChannels() const { return std::get<0>(GetParam()); } 2078 int GetSampleRateHz() const { return std::get<1>(GetParam()); } 2079 }; 2080 2081 TEST_P(AgcManagerDirectChannelSampleRateTest, CheckIsAlive) { 2082 const int num_channels = GetNumChannels(); 2083 const int sample_rate_hz = GetSampleRateHz(); 2084 2085 constexpr AnalogAgcConfig kConfig{.enabled = true, 2086 .clipping_predictor{.enabled = true}}; 2087 AgcManagerDirect manager(CreateEnvironment(), num_channels, kConfig); 2088 manager.Initialize(); 2089 AudioBuffer buffer(sample_rate_hz, num_channels, sample_rate_hz, num_channels, 2090 sample_rate_hz, num_channels); 2091 2092 constexpr int kStartupVolume = 100; 2093 int applied_initial_volume = kStartupVolume; 2094 2095 // Trigger a downward adaptation with clipping. 2096 WriteAudioBufferSamples(/*samples_value=*/0.0f, /*clipped_ratio=*/0.5f, 2097 buffer); 2098 const int initial_volume1 = applied_initial_volume; 2099 for (int i = 0; i < 400; ++i) { 2100 manager.set_stream_analog_level(applied_initial_volume); 2101 manager.AnalyzePreProcess(buffer); 2102 manager.Process(buffer, kLowSpeechProbability, 2103 /*speech_level_dbfs=*/-20.0f); 2104 applied_initial_volume = manager.recommended_analog_level(); 2105 } 2106 ASSERT_LT(manager.recommended_analog_level(), initial_volume1); 2107 2108 // Fill in audio that does not clip. 2109 WriteAudioBufferSamples(/*samples_value=*/1234.5f, /*clipped_ratio=*/0.0f, 2110 buffer); 2111 2112 // Trigger an upward adaptation. 2113 const int initial_volume2 = manager.recommended_analog_level(); 2114 for (int i = 0; i < kConfig.clipped_wait_frames; ++i) { 2115 manager.set_stream_analog_level(applied_initial_volume); 2116 manager.AnalyzePreProcess(buffer); 2117 manager.Process(buffer, kHighSpeechProbability, 2118 /*speech_level_dbfs=*/-65.0f); 2119 applied_initial_volume = manager.recommended_analog_level(); 2120 } 2121 EXPECT_GT(manager.recommended_analog_level(), initial_volume2); 2122 2123 // Trigger a downward adaptation. 2124 const int initial_volume = manager.recommended_analog_level(); 2125 for (int i = 0; i < 100; ++i) { 2126 manager.set_stream_analog_level(applied_initial_volume); 2127 manager.AnalyzePreProcess(buffer); 2128 manager.Process(buffer, kHighSpeechProbability, 2129 /*speech_level_dbfs=*/-5.0f); 2130 applied_initial_volume = manager.recommended_analog_level(); 2131 } 2132 EXPECT_LT(manager.recommended_analog_level(), initial_volume); 2133 } 2134 2135 INSTANTIATE_TEST_SUITE_P( 2136 , 2137 AgcManagerDirectChannelSampleRateTest, 2138 ::testing::Combine(::testing::Values(1, 2, 3, 6), 2139 ::testing::Values(8000, 16000, 32000, 48000))); 2140 2141 } // namespace webrtc