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