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/agc2/input_volume_controller.h"
12
13 #include <algorithm>
14 #include <fstream>
15 #include <limits>
16 #include <string>
17 #include <vector>
18
19 #include "rtc_base/numerics/safe_minmax.h"
20 #include "rtc_base/strings/string_builder.h"
21 #include "test/field_trial.h"
22 #include "test/gmock.h"
23 #include "test/gtest.h"
24 #include "test/testsupport/file_utils.h"
25
26 using ::testing::_;
27 using ::testing::AtLeast;
28 using ::testing::DoAll;
29 using ::testing::Return;
30 using ::testing::SetArgPointee;
31
32 namespace webrtc {
33 namespace {
34
35 constexpr int kSampleRateHz = 32000;
36 constexpr int kNumChannels = 1;
37 constexpr int kInitialInputVolume = 128;
38 constexpr int kClippedMin = 165; // Arbitrary, but different from the default.
39 constexpr float kAboveClippedThreshold = 0.2f;
40 constexpr int kMinMicLevel = 12;
41 constexpr int kClippedLevelStep = 15;
42 constexpr float kClippedRatioThreshold = 0.1f;
43 constexpr int kClippedWaitFrames = 300;
44 constexpr float kHighSpeechProbability = 0.7f;
45 constexpr float kLowSpeechProbability = 0.1f;
46 constexpr float kSpeechLevel = -25.0f;
47 constexpr float kSpeechProbabilityThreshold = 0.5f;
48 constexpr float kSpeechRatioThreshold = 0.8f;
49
50 constexpr float kMinSample = std::numeric_limits<int16_t>::min();
51 constexpr float kMaxSample = std::numeric_limits<int16_t>::max();
52
53 using ClippingPredictorConfig = AudioProcessing::Config::GainController1::
54 AnalogGainController::ClippingPredictor;
55
56 using InputVolumeControllerConfig = InputVolumeController::Config;
57
58 constexpr InputVolumeControllerConfig kDefaultInputVolumeControllerConfig{};
59 constexpr ClippingPredictorConfig kDefaultClippingPredictorConfig{};
60
CreateInputVolumeController(int clipped_level_step,float clipped_ratio_threshold,int clipped_wait_frames,bool enable_clipping_predictor=false,int update_input_volume_wait_frames=0)61 std::unique_ptr<InputVolumeController> CreateInputVolumeController(
62 int clipped_level_step,
63 float clipped_ratio_threshold,
64 int clipped_wait_frames,
65 bool enable_clipping_predictor = false,
66 int update_input_volume_wait_frames = 0) {
67 InputVolumeControllerConfig config{
68 .clipped_level_min = kClippedMin,
69 .clipped_level_step = clipped_level_step,
70 .clipped_ratio_threshold = clipped_ratio_threshold,
71 .clipped_wait_frames = clipped_wait_frames,
72 .enable_clipping_predictor = enable_clipping_predictor,
73 .target_range_max_dbfs = -18,
74 .target_range_min_dbfs = -30,
75 .update_input_volume_wait_frames = update_input_volume_wait_frames,
76 .speech_probability_threshold = kSpeechProbabilityThreshold,
77 .speech_ratio_threshold = kSpeechRatioThreshold,
78 };
79
80 return std::make_unique<InputVolumeController>(/*num_capture_channels=*/1,
81 config);
82 }
83
84 // Deprecated.
85 // TODO(bugs.webrtc.org/7494): Delete this helper, use
86 // `InputVolumeControllerTestHelper::CallAgcSequence()` instead.
87 // Calls `AnalyzePreProcess()` on `controller` `num_calls` times. `peak_ratio`
88 // is a value in [0, 1] which determines the amplitude of the samples (1 maps to
89 // full scale). The first half of the calls is made on frames which are half
90 // filled with zeros in order to simulate a signal with different crest factors.
CallPreProcessAudioBuffer(int num_calls,float peak_ratio,InputVolumeController & controller)91 void CallPreProcessAudioBuffer(int num_calls,
92 float peak_ratio,
93 InputVolumeController& controller) {
94 RTC_DCHECK_LE(peak_ratio, 1.0f);
95 AudioBuffer audio_buffer(kSampleRateHz, kNumChannels, kSampleRateHz,
96 kNumChannels, kSampleRateHz, kNumChannels);
97 const int num_channels = audio_buffer.num_channels();
98 const int num_frames = audio_buffer.num_frames();
99
100 // Make half of the calls with half zeroed frames.
101 for (int ch = 0; ch < num_channels; ++ch) {
102 // 50% of the samples in one frame are zero.
103 for (int i = 0; i < num_frames; i += 2) {
104 audio_buffer.channels()[ch][i] = peak_ratio * 32767.0f;
105 audio_buffer.channels()[ch][i + 1] = 0.0f;
106 }
107 }
108 for (int n = 0; n < num_calls / 2; ++n) {
109 controller.AnalyzePreProcess(audio_buffer);
110 }
111
112 // Make the remaining half of the calls with frames whose samples are all set.
113 for (int ch = 0; ch < num_channels; ++ch) {
114 for (int i = 0; i < num_frames; ++i) {
115 audio_buffer.channels()[ch][i] = peak_ratio * 32767.0f;
116 }
117 }
118 for (int n = 0; n < num_calls - num_calls / 2; ++n) {
119 controller.AnalyzePreProcess(audio_buffer);
120 }
121 }
122
123 constexpr char kMinInputVolumeFieldTrial[] = "WebRTC-Audio-Agc2-MinInputVolume";
124
GetAgcMinInputVolumeFieldTrial(const std::string & value)125 std::string GetAgcMinInputVolumeFieldTrial(const std::string& value) {
126 char field_trial_buffer[64];
127 rtc::SimpleStringBuilder builder(field_trial_buffer);
128 builder << kMinInputVolumeFieldTrial << "/" << value << "/";
129 return builder.str();
130 }
131
GetAgcMinInputVolumeFieldTrialEnabled(int enabled_value,const std::string & suffix="")132 std::string GetAgcMinInputVolumeFieldTrialEnabled(
133 int enabled_value,
134 const std::string& suffix = "") {
135 RTC_DCHECK_GE(enabled_value, 0);
136 RTC_DCHECK_LE(enabled_value, 255);
137 char field_trial_buffer[64];
138 rtc::SimpleStringBuilder builder(field_trial_buffer);
139 builder << kMinInputVolumeFieldTrial << "/Enabled-" << enabled_value << suffix
140 << "/";
141 return builder.str();
142 }
143
GetAgcMinInputVolumeFieldTrial(absl::optional<int> volume)144 std::string GetAgcMinInputVolumeFieldTrial(absl::optional<int> volume) {
145 if (volume.has_value()) {
146 return GetAgcMinInputVolumeFieldTrialEnabled(*volume);
147 }
148 return GetAgcMinInputVolumeFieldTrial("Disabled");
149 }
150
151 // (Over)writes `samples_value` for the samples in `audio_buffer`.
152 // When `clipped_ratio`, a value in [0, 1], is greater than 0, the corresponding
153 // fraction of the frame is set to a full scale value to simulate clipping.
WriteAudioBufferSamples(float samples_value,float clipped_ratio,AudioBuffer & audio_buffer)154 void WriteAudioBufferSamples(float samples_value,
155 float clipped_ratio,
156 AudioBuffer& audio_buffer) {
157 RTC_DCHECK_GE(samples_value, kMinSample);
158 RTC_DCHECK_LE(samples_value, kMaxSample);
159 RTC_DCHECK_GE(clipped_ratio, 0.0f);
160 RTC_DCHECK_LE(clipped_ratio, 1.0f);
161 int num_channels = audio_buffer.num_channels();
162 int num_samples = audio_buffer.num_frames();
163 int num_clipping_samples = clipped_ratio * num_samples;
164 for (int ch = 0; ch < num_channels; ++ch) {
165 int i = 0;
166 for (; i < num_clipping_samples; ++i) {
167 audio_buffer.channels()[ch][i] = 32767.0f;
168 }
169 for (; i < num_samples; ++i) {
170 audio_buffer.channels()[ch][i] = samples_value;
171 }
172 }
173 }
174
175 // Deprecated.
176 // TODO(bugs.webrtc.org/7494): Delete this helper, use
177 // `InputVolumeControllerTestHelper::CallAgcSequence()` instead.
CallPreProcessAndProcess(int num_calls,const AudioBuffer & audio_buffer,float speech_probability,absl::optional<float> speech_level,InputVolumeController & controller)178 void CallPreProcessAndProcess(int num_calls,
179 const AudioBuffer& audio_buffer,
180 float speech_probability,
181 absl::optional<float> speech_level,
182 InputVolumeController& controller) {
183 for (int n = 0; n < num_calls; ++n) {
184 controller.AnalyzePreProcess(audio_buffer);
185 controller.Process(speech_probability, speech_level);
186 }
187 }
188
189 // Reads a given number of 10 ms chunks from a PCM file and feeds them to
190 // `InputVolumeController`.
191 class SpeechSamplesReader {
192 private:
193 // Recording properties.
194 static constexpr int kPcmSampleRateHz = 16000;
195 static constexpr int kPcmNumChannels = 1;
196 static constexpr int kPcmBytesPerSamples = sizeof(int16_t);
197
198 public:
SpeechSamplesReader()199 SpeechSamplesReader()
200 : is_(test::ResourcePath("audio_processing/agc/agc_audio", "pcm"),
201 std::ios::binary | std::ios::ate),
202 audio_buffer_(kPcmSampleRateHz,
203 kPcmNumChannels,
204 kPcmSampleRateHz,
205 kPcmNumChannels,
206 kPcmSampleRateHz,
207 kPcmNumChannels),
208 buffer_(audio_buffer_.num_frames()),
209 buffer_num_bytes_(buffer_.size() * kPcmBytesPerSamples) {
210 RTC_CHECK(is_);
211 }
212
213 // Reads `num_frames` 10 ms frames from the beginning of the PCM file, applies
214 // `gain_db` and feeds the frames into `controller` by calling
215 // `AnalyzePreProcess()` and `Process()` for each frame. Reads the number of
216 // 10 ms frames available in the PCM file if `num_frames` is too large - i.e.,
217 // does not loop. `speech_probability` and `speech_level` are passed to
218 // `Process()`.
Feed(int num_frames,int gain_db,float speech_probability,absl::optional<float> speech_level,InputVolumeController & controller)219 void Feed(int num_frames,
220 int gain_db,
221 float speech_probability,
222 absl::optional<float> speech_level,
223 InputVolumeController& controller) {
224 float gain = std::pow(10.0f, gain_db / 20.0f); // From dB to linear gain.
225 is_.seekg(0, is_.beg); // Start from the beginning of the PCM file.
226
227 // Read and feed frames.
228 for (int i = 0; i < num_frames; ++i) {
229 is_.read(reinterpret_cast<char*>(buffer_.data()), buffer_num_bytes_);
230 if (is_.gcount() < buffer_num_bytes_) {
231 // EOF reached. Stop.
232 break;
233 }
234 // Apply gain and copy samples into `audio_buffer_`.
235 std::transform(buffer_.begin(), buffer_.end(),
236 audio_buffer_.channels()[0], [gain](int16_t v) -> float {
237 return rtc::SafeClamp(static_cast<float>(v) * gain,
238 kMinSample, kMaxSample);
239 });
240
241 controller.AnalyzePreProcess(audio_buffer_);
242 controller.Process(speech_probability, speech_level);
243 }
244 }
245
246 private:
247 std::ifstream is_;
248 AudioBuffer audio_buffer_;
249 std::vector<int16_t> buffer_;
250 const std::streamsize buffer_num_bytes_;
251 };
252
253 // Runs the MonoInputVolumeControl processing sequence following the API
254 // contract. Returns the updated recommended input volume.
UpdateRecommendedInputVolume(MonoInputVolumeController & controller,int applied_input_volume,float speech_probability,const absl::optional<float> rms_error_dbfs)255 float UpdateRecommendedInputVolume(MonoInputVolumeController& controller,
256 int applied_input_volume,
257 float speech_probability,
258 const absl::optional<float> rms_error_dbfs) {
259 controller.set_stream_analog_level(applied_input_volume);
260 EXPECT_EQ(controller.recommended_analog_level(), applied_input_volume);
261 controller.Process(rms_error_dbfs, speech_probability);
262 return controller.recommended_analog_level();
263 }
264
265 } // namespace
266
267 // TODO(bugs.webrtc.org/12874): Use constexpr struct with designated
268 // initializers once fixed.
GetInputVolumeControllerTestConfig()269 constexpr InputVolumeControllerConfig GetInputVolumeControllerTestConfig() {
270 InputVolumeControllerConfig config{
271 .clipped_level_min = kClippedMin,
272 .clipped_level_step = kClippedLevelStep,
273 .clipped_ratio_threshold = kClippedRatioThreshold,
274 .clipped_wait_frames = kClippedWaitFrames,
275 .enable_clipping_predictor = kDefaultClippingPredictorConfig.enabled,
276 .target_range_max_dbfs = -18,
277 .target_range_min_dbfs = -30,
278 .update_input_volume_wait_frames = 0,
279 .speech_probability_threshold = 0.5f,
280 .speech_ratio_threshold = 1.0f,
281 };
282 return config;
283 }
284
285 // Helper class that provides an `InputVolumeController` instance with an
286 // `AudioBuffer` instance and `CallAgcSequence()`, a helper method that runs the
287 // `InputVolumeController` instance on the `AudioBuffer` one by sticking to the
288 // API contract.
289 class InputVolumeControllerTestHelper {
290 public:
291 // Ctor. Initializes `audio_buffer` with zeros.
InputVolumeControllerTestHelper()292 InputVolumeControllerTestHelper()
293 : audio_buffer(kSampleRateHz,
294 kNumChannels,
295 kSampleRateHz,
296 kNumChannels,
297 kSampleRateHz,
298 kNumChannels),
299 controller(/*num_capture_channels=*/1,
300 GetInputVolumeControllerTestConfig()) {
301 controller.Initialize();
302 WriteAudioBufferSamples(/*samples_value=*/0.0f, /*clipped_ratio=*/0.0f,
303 audio_buffer);
304 }
305
306 // Calls the sequence of `InputVolumeController` methods according to the API
307 // contract, namely:
308 // - Sets the applied input volume;
309 // - Uses `audio_buffer` to call `AnalyzePreProcess()` and `Process()`;
310 // Returns the recommended input volume.
CallAgcSequence(int applied_input_volume,float speech_probability,absl::optional<float> speech_level)311 int CallAgcSequence(int applied_input_volume,
312 float speech_probability,
313 absl::optional<float> speech_level) {
314 controller.set_stream_analog_level(applied_input_volume);
315 controller.AnalyzePreProcess(audio_buffer);
316 controller.Process(speech_probability, speech_level);
317
318 return controller.recommended_analog_level();
319 }
320
321 // Deprecated.
322 // TODO(bugs.webrtc.org/7494): Let the caller write `audio_buffer` and use
323 // `CallAgcSequence()`.
CallProcess(int num_calls,float speech_probability,absl::optional<float> speech_level)324 void CallProcess(int num_calls,
325 float speech_probability,
326 absl::optional<float> speech_level) {
327 for (int i = 0; i < num_calls; ++i) {
328 controller.Process(speech_probability, speech_level);
329 }
330 }
331
332 // Deprecated.
333 // TODO(bugs.webrtc.org/7494): Let the caller write `audio_buffer` and use
334 // `CallAgcSequence()`.
CallPreProc(int num_calls,float clipped_ratio)335 void CallPreProc(int num_calls, float clipped_ratio) {
336 RTC_DCHECK_GE(clipped_ratio, 0.0f);
337 RTC_DCHECK_LE(clipped_ratio, 1.0f);
338 WriteAudioBufferSamples(/*samples_value=*/0.0f, clipped_ratio,
339 audio_buffer);
340 for (int i = 0; i < num_calls; ++i) {
341 controller.AnalyzePreProcess(audio_buffer);
342 }
343 }
344
345 // Deprecated.
346 // TODO(bugs.webrtc.org/7494): Let the caller write `audio_buffer` and use
347 // `CallAgcSequence()`.
CallPreProcForChangingAudio(int num_calls,float peak_ratio)348 void CallPreProcForChangingAudio(int num_calls, float peak_ratio) {
349 RTC_DCHECK_GE(peak_ratio, 0.0f);
350 RTC_DCHECK_LE(peak_ratio, 1.0f);
351 const float samples_value = peak_ratio * 32767.0f;
352
353 // Make half of the calls on a frame where the samples alternate
354 // `sample_values` and zeros.
355 WriteAudioBufferSamples(samples_value, /*clipped_ratio=*/0.0f,
356 audio_buffer);
357 for (size_t ch = 0; ch < audio_buffer.num_channels(); ++ch) {
358 for (size_t k = 1; k < audio_buffer.num_frames(); k += 2) {
359 audio_buffer.channels()[ch][k] = 0.0f;
360 }
361 }
362 for (int i = 0; i < num_calls / 2; ++i) {
363 controller.AnalyzePreProcess(audio_buffer);
364 }
365
366 // Make half of thecalls on a frame where all the samples equal
367 // `sample_values`.
368 WriteAudioBufferSamples(samples_value, /*clipped_ratio=*/0.0f,
369 audio_buffer);
370 for (int i = 0; i < num_calls - num_calls / 2; ++i) {
371 controller.AnalyzePreProcess(audio_buffer);
372 }
373 }
374
375 AudioBuffer audio_buffer;
376 InputVolumeController controller;
377 };
378
379 class InputVolumeControllerParametrizedTest
380 : public ::testing::TestWithParam<absl::optional<int>> {
381 protected:
InputVolumeControllerParametrizedTest()382 InputVolumeControllerParametrizedTest()
383 : field_trials_(GetAgcMinInputVolumeFieldTrial(GetParam())) {}
384
GetMinInputVolume() const385 int GetMinInputVolume() const { return GetParam().value_or(kMinMicLevel); }
386
387 private:
388 test::ScopedFieldTrials field_trials_;
389 };
390
391 INSTANTIATE_TEST_SUITE_P(,
392 InputVolumeControllerParametrizedTest,
393 ::testing::Values(absl::nullopt, 12, 20));
394
TEST_P(InputVolumeControllerParametrizedTest,StartupMinVolumeConfigurationIsRespected)395 TEST_P(InputVolumeControllerParametrizedTest,
396 StartupMinVolumeConfigurationIsRespected) {
397 InputVolumeControllerTestHelper helper;
398
399 helper.CallAgcSequence(kInitialInputVolume, kHighSpeechProbability,
400 kSpeechLevel);
401
402 EXPECT_EQ(kInitialInputVolume, helper.controller.recommended_analog_level());
403 }
404
TEST_P(InputVolumeControllerParametrizedTest,MicVolumeResponseToRmsError)405 TEST_P(InputVolumeControllerParametrizedTest, MicVolumeResponseToRmsError) {
406 InputVolumeControllerTestHelper helper;
407 helper.CallAgcSequence(kInitialInputVolume, kHighSpeechProbability,
408 kSpeechLevel);
409
410 // Inside the digital gain's window; no change of volume.
411 helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -23.0f);
412
413 // Inside the digital gain's window; no change of volume.
414 helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -28.0f);
415
416 // Above the digital gain's window; volume should be increased.
417 helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -29.0f);
418 EXPECT_EQ(helper.controller.recommended_analog_level(), 128);
419
420 helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -38.0f);
421 EXPECT_EQ(helper.controller.recommended_analog_level(), 156);
422
423 // Inside the digital gain's window; no change of volume.
424 helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -23.0f);
425 helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -18.0f);
426
427 // Below the digial gain's window; volume should be decreased.
428 helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -17.0f);
429 EXPECT_EQ(helper.controller.recommended_analog_level(), 155);
430
431 helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -17.0f);
432 EXPECT_EQ(helper.controller.recommended_analog_level(), 151);
433
434 helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -9.0f);
435 EXPECT_EQ(helper.controller.recommended_analog_level(), 119);
436 }
437
TEST_P(InputVolumeControllerParametrizedTest,MicVolumeIsLimited)438 TEST_P(InputVolumeControllerParametrizedTest, MicVolumeIsLimited) {
439 InputVolumeControllerTestHelper helper;
440 helper.CallAgcSequence(kInitialInputVolume, kHighSpeechProbability,
441 kSpeechLevel);
442
443 // Maximum upwards change is limited.
444 helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -48.0f);
445 EXPECT_EQ(helper.controller.recommended_analog_level(), 183);
446
447 helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -48.0f);
448 EXPECT_EQ(helper.controller.recommended_analog_level(), 243);
449
450 // Won't go higher than the maximum.
451 helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -48.0f);
452 EXPECT_EQ(helper.controller.recommended_analog_level(), 255);
453
454 helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -17.0f);
455 EXPECT_EQ(helper.controller.recommended_analog_level(), 254);
456
457 // Maximum downwards change is limited.
458 helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, 22.0f);
459 EXPECT_EQ(helper.controller.recommended_analog_level(), 194);
460
461 helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, 22.0f);
462 EXPECT_EQ(helper.controller.recommended_analog_level(), 137);
463
464 helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, 22.0f);
465 EXPECT_EQ(helper.controller.recommended_analog_level(), 88);
466
467 helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, 22.0f);
468 EXPECT_EQ(helper.controller.recommended_analog_level(), 54);
469
470 helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, 22.0f);
471 EXPECT_EQ(helper.controller.recommended_analog_level(), 33);
472
473 // Won't go lower than the minimum.
474 helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, 22.0f);
475 EXPECT_EQ(helper.controller.recommended_analog_level(),
476 std::max(18, GetMinInputVolume()));
477
478 helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, 22.0f);
479 EXPECT_EQ(helper.controller.recommended_analog_level(),
480 std::max(12, GetMinInputVolume()));
481 }
482
TEST_P(InputVolumeControllerParametrizedTest,NoActionWhileMuted)483 TEST_P(InputVolumeControllerParametrizedTest, NoActionWhileMuted) {
484 InputVolumeControllerTestHelper helper;
485 helper.CallAgcSequence(kInitialInputVolume, kHighSpeechProbability,
486 kSpeechLevel);
487
488 helper.controller.HandleCaptureOutputUsedChange(false);
489 helper.controller.Process(kHighSpeechProbability, kSpeechLevel);
490 }
491
TEST_P(InputVolumeControllerParametrizedTest,UnmutingChecksVolumeWithoutRaising)492 TEST_P(InputVolumeControllerParametrizedTest,
493 UnmutingChecksVolumeWithoutRaising) {
494 InputVolumeControllerTestHelper helper;
495 helper.CallAgcSequence(kInitialInputVolume, kHighSpeechProbability,
496 kSpeechLevel);
497
498 helper.controller.HandleCaptureOutputUsedChange(false);
499 helper.controller.HandleCaptureOutputUsedChange(true);
500
501 constexpr int kInputVolume = 127;
502 helper.controller.set_stream_analog_level(kInputVolume);
503
504 // SetMicVolume should not be called.
505 helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, kSpeechLevel);
506 EXPECT_EQ(helper.controller.recommended_analog_level(), 127);
507 }
508
TEST_P(InputVolumeControllerParametrizedTest,UnmutingRaisesTooLowVolume)509 TEST_P(InputVolumeControllerParametrizedTest, UnmutingRaisesTooLowVolume) {
510 InputVolumeControllerTestHelper helper;
511 helper.CallAgcSequence(kInitialInputVolume, kHighSpeechProbability,
512 kSpeechLevel);
513
514 helper.controller.HandleCaptureOutputUsedChange(false);
515 helper.controller.HandleCaptureOutputUsedChange(true);
516
517 constexpr int kInputVolume = 11;
518 helper.controller.set_stream_analog_level(kInputVolume);
519
520 helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, kSpeechLevel);
521 EXPECT_EQ(helper.controller.recommended_analog_level(), GetMinInputVolume());
522 }
523
TEST_P(InputVolumeControllerParametrizedTest,ManualLevelChangeResultsInNoSetMicCall)524 TEST_P(InputVolumeControllerParametrizedTest,
525 ManualLevelChangeResultsInNoSetMicCall) {
526 InputVolumeControllerTestHelper helper;
527 helper.CallAgcSequence(kInitialInputVolume, kHighSpeechProbability,
528 kSpeechLevel);
529
530 // GetMicVolume returns a value outside of the quantization slack, indicating
531 // a manual volume change.
532 ASSERT_NE(helper.controller.recommended_analog_level(), 154);
533 helper.controller.set_stream_analog_level(154);
534 helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -29.0f);
535 EXPECT_EQ(helper.controller.recommended_analog_level(), 154);
536
537 // Do the same thing, except downwards now.
538 helper.controller.set_stream_analog_level(100);
539 helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -17.0f);
540 EXPECT_EQ(helper.controller.recommended_analog_level(), 100);
541
542 // And finally verify the AGC continues working without a manual change.
543 helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -17.0f);
544 EXPECT_EQ(helper.controller.recommended_analog_level(), 99);
545 }
546
TEST_P(InputVolumeControllerParametrizedTest,RecoveryAfterManualLevelChangeFromMax)547 TEST_P(InputVolumeControllerParametrizedTest,
548 RecoveryAfterManualLevelChangeFromMax) {
549 InputVolumeControllerTestHelper helper;
550 helper.CallAgcSequence(kInitialInputVolume, kHighSpeechProbability,
551 kSpeechLevel);
552
553 // Force the mic up to max volume. Takes a few steps due to the residual
554 // gain limitation.
555 helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -48.0f);
556 EXPECT_EQ(helper.controller.recommended_analog_level(), 183);
557 helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -48.0f);
558 EXPECT_EQ(helper.controller.recommended_analog_level(), 243);
559 helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -48.0f);
560 EXPECT_EQ(helper.controller.recommended_analog_level(), 255);
561
562 // Manual change does not result in SetMicVolume call.
563 helper.controller.set_stream_analog_level(50);
564 helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -17.0f);
565 EXPECT_EQ(helper.controller.recommended_analog_level(), 50);
566
567 // Continues working as usual afterwards.
568 helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -38.0f);
569
570 EXPECT_EQ(helper.controller.recommended_analog_level(), 65);
571 }
572
573 // Checks that the minimum input volume is enforced during the upward adjustment
574 // of the input volume.
TEST_P(InputVolumeControllerParametrizedTest,EnforceMinInputVolumeDuringUpwardsAdjustment)575 TEST_P(InputVolumeControllerParametrizedTest,
576 EnforceMinInputVolumeDuringUpwardsAdjustment) {
577 InputVolumeControllerTestHelper helper;
578 helper.CallAgcSequence(kInitialInputVolume, kHighSpeechProbability,
579 kSpeechLevel);
580
581 // Manual change below min, but strictly positive, otherwise no action will be
582 // taken.
583 helper.controller.set_stream_analog_level(1);
584 helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -17.0f);
585
586 // Trigger an upward adjustment of the input volume.
587 EXPECT_EQ(helper.controller.recommended_analog_level(), GetMinInputVolume());
588 helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -29.0f);
589 EXPECT_EQ(helper.controller.recommended_analog_level(), GetMinInputVolume());
590 helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -48.0f);
591 EXPECT_EQ(helper.controller.recommended_analog_level(), GetMinInputVolume());
592
593 // After a number of consistently low speech level observations, the input
594 // volume is eventually raised above the minimum.
595 helper.CallProcess(/*num_calls=*/10, kHighSpeechProbability, -38.0f);
596 EXPECT_GT(helper.controller.recommended_analog_level(), GetMinInputVolume());
597 }
598
599 // Checks that, when the min mic level override is specified, AGC immediately
600 // applies the minimum mic level after the mic level is manually set below the
601 // minimum gain to enforce.
TEST_P(InputVolumeControllerParametrizedTest,RecoveryAfterManualLevelChangeBelowMin)602 TEST_P(InputVolumeControllerParametrizedTest,
603 RecoveryAfterManualLevelChangeBelowMin) {
604 InputVolumeControllerTestHelper helper;
605 helper.CallAgcSequence(kInitialInputVolume, kHighSpeechProbability,
606 kSpeechLevel);
607
608 // Manual change below min, but strictly positive, otherwise
609 // AGC won't take any action.
610 helper.controller.set_stream_analog_level(1);
611 helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -17.0f);
612 EXPECT_EQ(GetMinInputVolume(), helper.controller.recommended_analog_level());
613 }
614
TEST_P(InputVolumeControllerParametrizedTest,NoClippingHasNoImpact)615 TEST_P(InputVolumeControllerParametrizedTest, NoClippingHasNoImpact) {
616 InputVolumeControllerTestHelper helper;
617 helper.CallAgcSequence(kInitialInputVolume, kHighSpeechProbability,
618 kSpeechLevel);
619
620 helper.CallPreProc(/*num_calls=*/100, /*clipped_ratio=*/0);
621 EXPECT_EQ(helper.controller.recommended_analog_level(), 128);
622 }
623
TEST_P(InputVolumeControllerParametrizedTest,ClippingUnderThresholdHasNoImpact)624 TEST_P(InputVolumeControllerParametrizedTest,
625 ClippingUnderThresholdHasNoImpact) {
626 InputVolumeControllerTestHelper helper;
627 helper.CallAgcSequence(kInitialInputVolume, kHighSpeechProbability,
628 kSpeechLevel);
629
630 helper.CallPreProc(/*num_calls=*/1, /*clipped_ratio=*/0.099);
631 EXPECT_EQ(helper.controller.recommended_analog_level(), 128);
632 }
633
TEST_P(InputVolumeControllerParametrizedTest,ClippingLowersVolume)634 TEST_P(InputVolumeControllerParametrizedTest, ClippingLowersVolume) {
635 InputVolumeControllerTestHelper helper;
636 helper.CallAgcSequence(/*applied_input_volume=*/255, kHighSpeechProbability,
637 kSpeechLevel);
638
639 helper.CallPreProc(/*num_calls=*/1, /*clipped_ratio=*/0.2);
640 EXPECT_EQ(helper.controller.recommended_analog_level(), 240);
641 }
642
TEST_P(InputVolumeControllerParametrizedTest,WaitingPeriodBetweenClippingChecks)643 TEST_P(InputVolumeControllerParametrizedTest,
644 WaitingPeriodBetweenClippingChecks) {
645 InputVolumeControllerTestHelper helper;
646 helper.CallAgcSequence(/*applied_input_volume=*/255, kHighSpeechProbability,
647 kSpeechLevel);
648
649 helper.CallPreProc(/*num_calls=*/1, /*clipped_ratio=*/kAboveClippedThreshold);
650 EXPECT_EQ(helper.controller.recommended_analog_level(), 240);
651
652 helper.CallPreProc(/*num_calls=*/300,
653 /*clipped_ratio=*/kAboveClippedThreshold);
654 EXPECT_EQ(helper.controller.recommended_analog_level(), 240);
655
656 helper.CallPreProc(/*num_calls=*/1, /*clipped_ratio=*/kAboveClippedThreshold);
657 EXPECT_EQ(helper.controller.recommended_analog_level(), 225);
658 }
659
TEST_P(InputVolumeControllerParametrizedTest,ClippingLoweringIsLimited)660 TEST_P(InputVolumeControllerParametrizedTest, ClippingLoweringIsLimited) {
661 InputVolumeControllerTestHelper helper;
662 helper.CallAgcSequence(/*applied_input_volume=*/180, kHighSpeechProbability,
663 kSpeechLevel);
664
665 helper.CallPreProc(/*num_calls=*/1, /*clipped_ratio=*/kAboveClippedThreshold);
666 EXPECT_EQ(helper.controller.recommended_analog_level(), kClippedMin);
667
668 helper.CallPreProc(/*num_calls=*/1000,
669 /*clipped_ratio=*/kAboveClippedThreshold);
670 EXPECT_EQ(helper.controller.recommended_analog_level(), kClippedMin);
671 }
672
TEST_P(InputVolumeControllerParametrizedTest,ClippingMaxIsRespectedWhenEqualToLevel)673 TEST_P(InputVolumeControllerParametrizedTest,
674 ClippingMaxIsRespectedWhenEqualToLevel) {
675 InputVolumeControllerTestHelper helper;
676 helper.CallAgcSequence(/*applied_input_volume=*/255, kHighSpeechProbability,
677 kSpeechLevel);
678
679 helper.CallPreProc(/*num_calls=*/1, /*clipped_ratio=*/kAboveClippedThreshold);
680 EXPECT_EQ(helper.controller.recommended_analog_level(), 240);
681
682 helper.CallProcess(/*num_calls=*/10, kHighSpeechProbability, -48.0f);
683 EXPECT_EQ(helper.controller.recommended_analog_level(), 240);
684 }
685
TEST_P(InputVolumeControllerParametrizedTest,ClippingMaxIsRespectedWhenHigherThanLevel)686 TEST_P(InputVolumeControllerParametrizedTest,
687 ClippingMaxIsRespectedWhenHigherThanLevel) {
688 InputVolumeControllerTestHelper helper;
689 helper.CallAgcSequence(/*applied_input_volume=*/200, kHighSpeechProbability,
690 kSpeechLevel);
691
692 helper.CallPreProc(/*num_calls=*/1, /*clipped_ratio=*/kAboveClippedThreshold);
693 EXPECT_EQ(helper.controller.recommended_analog_level(), 185);
694
695 helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -58.0f);
696 EXPECT_EQ(helper.controller.recommended_analog_level(), 240);
697 helper.CallProcess(/*num_calls=*/10, kHighSpeechProbability, -58.0f);
698 EXPECT_EQ(helper.controller.recommended_analog_level(), 240);
699 }
700
TEST_P(InputVolumeControllerParametrizedTest,UserCanRaiseVolumeAfterClipping)701 TEST_P(InputVolumeControllerParametrizedTest, UserCanRaiseVolumeAfterClipping) {
702 InputVolumeControllerTestHelper helper;
703 helper.CallAgcSequence(/*applied_input_volume=*/225, kHighSpeechProbability,
704 kSpeechLevel);
705
706 helper.CallPreProc(/*num_calls=*/1, /*clipped_ratio=*/kAboveClippedThreshold);
707 EXPECT_EQ(helper.controller.recommended_analog_level(), 210);
708
709 // User changed the volume.
710 helper.controller.set_stream_analog_level(250);
711 helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -32.0f);
712 EXPECT_EQ(helper.controller.recommended_analog_level(), 250);
713
714 // Move down...
715 helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -8.0f);
716 EXPECT_EQ(helper.controller.recommended_analog_level(), 210);
717 // And back up to the new max established by the user.
718 helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -58.0f);
719 EXPECT_EQ(helper.controller.recommended_analog_level(), 250);
720 // Will not move above new maximum.
721 helper.CallProcess(/*num_calls=*/1, kHighSpeechProbability, -48.0f);
722 EXPECT_EQ(helper.controller.recommended_analog_level(), 250);
723 }
724
TEST_P(InputVolumeControllerParametrizedTest,ClippingDoesNotPullLowVolumeBackUp)725 TEST_P(InputVolumeControllerParametrizedTest,
726 ClippingDoesNotPullLowVolumeBackUp) {
727 InputVolumeControllerTestHelper helper;
728 helper.CallAgcSequence(/*applied_input_volume=*/80, kHighSpeechProbability,
729 kSpeechLevel);
730
731 int initial_volume = helper.controller.recommended_analog_level();
732 helper.CallPreProc(/*num_calls=*/1, /*clipped_ratio=*/kAboveClippedThreshold);
733 EXPECT_EQ(initial_volume, helper.controller.recommended_analog_level());
734 }
735
TEST_P(InputVolumeControllerParametrizedTest,TakesNoActionOnZeroMicVolume)736 TEST_P(InputVolumeControllerParametrizedTest, TakesNoActionOnZeroMicVolume) {
737 InputVolumeControllerTestHelper helper;
738 helper.CallAgcSequence(kInitialInputVolume, kHighSpeechProbability,
739 kSpeechLevel);
740
741 helper.controller.set_stream_analog_level(0);
742 helper.CallProcess(/*num_calls=*/10, kHighSpeechProbability, -48.0f);
743 EXPECT_EQ(helper.controller.recommended_analog_level(), 0);
744 }
745
TEST_P(InputVolumeControllerParametrizedTest,ClippingDetectionLowersVolume)746 TEST_P(InputVolumeControllerParametrizedTest, ClippingDetectionLowersVolume) {
747 InputVolumeControllerTestHelper helper;
748 helper.CallAgcSequence(/*applied_input_volume=*/255, kHighSpeechProbability,
749 kSpeechLevel);
750
751 EXPECT_EQ(helper.controller.recommended_analog_level(), 255);
752 helper.CallPreProcForChangingAudio(/*num_calls=*/100, /*peak_ratio=*/0.99f);
753 EXPECT_EQ(helper.controller.recommended_analog_level(), 255);
754 helper.CallPreProcForChangingAudio(/*num_calls=*/100, /*peak_ratio=*/1.0f);
755 EXPECT_EQ(helper.controller.recommended_analog_level(), 240);
756 }
757
TEST_P(InputVolumeControllerParametrizedTest,DisabledClippingPredictorDoesNotLowerVolume)758 TEST_P(InputVolumeControllerParametrizedTest,
759 DisabledClippingPredictorDoesNotLowerVolume) {
760 InputVolumeControllerTestHelper helper;
761 helper.CallAgcSequence(/*applied_input_volume=*/255, kHighSpeechProbability,
762 kSpeechLevel);
763
764 EXPECT_FALSE(helper.controller.clipping_predictor_enabled());
765 EXPECT_EQ(helper.controller.recommended_analog_level(), 255);
766 helper.CallPreProcForChangingAudio(/*num_calls=*/100, /*peak_ratio=*/0.99f);
767 EXPECT_EQ(helper.controller.recommended_analog_level(), 255);
768 helper.CallPreProcForChangingAudio(/*num_calls=*/100, /*peak_ratio=*/0.99f);
769 EXPECT_EQ(helper.controller.recommended_analog_level(), 255);
770 }
771
TEST(InputVolumeControllerTest,MinInputVolumeDefault)772 TEST(InputVolumeControllerTest, MinInputVolumeDefault) {
773 std::unique_ptr<InputVolumeController> controller =
774 CreateInputVolumeController(kClippedLevelStep, kClippedRatioThreshold,
775 kClippedWaitFrames);
776 EXPECT_EQ(controller->channel_controllers_[0]->min_input_volume(),
777 kMinMicLevel);
778 }
779
TEST(InputVolumeControllerTest,MinInputVolumeDisabled)780 TEST(InputVolumeControllerTest, MinInputVolumeDisabled) {
781 for (const std::string& field_trial_suffix : {"", "_20220210"}) {
782 test::ScopedFieldTrials field_trial(
783 GetAgcMinInputVolumeFieldTrial("Disabled" + field_trial_suffix));
784 std::unique_ptr<InputVolumeController> controller =
785 CreateInputVolumeController(kClippedLevelStep, kClippedRatioThreshold,
786 kClippedWaitFrames);
787
788 EXPECT_EQ(controller->channel_controllers_[0]->min_input_volume(),
789 kMinMicLevel);
790 }
791 }
792
793 // Checks that a field-trial parameter outside of the valid range [0,255] is
794 // ignored.
TEST(InputVolumeControllerTest,MinInputVolumeOutOfRangeAbove)795 TEST(InputVolumeControllerTest, MinInputVolumeOutOfRangeAbove) {
796 test::ScopedFieldTrials field_trial(
797 GetAgcMinInputVolumeFieldTrial("Enabled-256"));
798 std::unique_ptr<InputVolumeController> controller =
799 CreateInputVolumeController(kClippedLevelStep, kClippedRatioThreshold,
800 kClippedWaitFrames);
801 EXPECT_EQ(controller->channel_controllers_[0]->min_input_volume(),
802 kMinMicLevel);
803 }
804
805 // Checks that a field-trial parameter outside of the valid range [0,255] is
806 // ignored.
TEST(InputVolumeControllerTest,MinInputVolumeOutOfRangeBelow)807 TEST(InputVolumeControllerTest, MinInputVolumeOutOfRangeBelow) {
808 test::ScopedFieldTrials field_trial(
809 GetAgcMinInputVolumeFieldTrial("Enabled--1"));
810 std::unique_ptr<InputVolumeController> controller =
811 CreateInputVolumeController(kClippedLevelStep, kClippedRatioThreshold,
812 kClippedWaitFrames);
813 EXPECT_EQ(controller->channel_controllers_[0]->min_input_volume(),
814 kMinMicLevel);
815 }
816
817 // Verifies that a valid experiment changes the minimum microphone level. The
818 // start volume is larger than the min level and should therefore not be
819 // changed.
TEST(InputVolumeControllerTest,MinInputVolumeEnabled50)820 TEST(InputVolumeControllerTest, MinInputVolumeEnabled50) {
821 constexpr int kMinInputVolume = 50;
822 for (const std::string& field_trial_suffix : {"", "_20220210"}) {
823 SCOPED_TRACE(field_trial_suffix);
824 test::ScopedFieldTrials field_trial(GetAgcMinInputVolumeFieldTrialEnabled(
825 kMinInputVolume, field_trial_suffix));
826 std::unique_ptr<InputVolumeController> controller =
827 CreateInputVolumeController(kClippedLevelStep, kClippedRatioThreshold,
828 kClippedWaitFrames);
829
830 EXPECT_EQ(controller->channel_controllers_[0]->min_input_volume(),
831 kMinInputVolume);
832 }
833 }
834
835 // Checks that, when the "WebRTC-Audio-Agc2-MinInputVolume" field trial is
836 // specified with a valid value, the mic level never gets lowered beyond the
837 // override value in the presence of clipping.
TEST(InputVolumeControllerTest,MinInputVolumeCheckMinLevelWithClipping)838 TEST(InputVolumeControllerTest, MinInputVolumeCheckMinLevelWithClipping) {
839 constexpr int kMinInputVolume = 250;
840
841 // Create and initialize two AGCs by specifying and leaving unspecified the
842 // relevant field trial.
843 const auto factory = []() {
844 std::unique_ptr<InputVolumeController> controller =
845 CreateInputVolumeController(kClippedLevelStep, kClippedRatioThreshold,
846 kClippedWaitFrames);
847 controller->Initialize();
848 controller->set_stream_analog_level(kInitialInputVolume);
849 return controller;
850 };
851 std::unique_ptr<InputVolumeController> controller = factory();
852 std::unique_ptr<InputVolumeController> manager_with_override;
853 {
854 test::ScopedFieldTrials field_trial(
855 GetAgcMinInputVolumeFieldTrialEnabled(kMinInputVolume));
856 manager_with_override = factory();
857 }
858
859 // Create a test input signal which containts 80% of clipped samples.
860 AudioBuffer audio_buffer(kSampleRateHz, 1, kSampleRateHz, 1, kSampleRateHz,
861 1);
862 WriteAudioBufferSamples(/*samples_value=*/4000.0f, /*clipped_ratio=*/0.8f,
863 audio_buffer);
864
865 // Simulate 4 seconds of clipping; it is expected to trigger a downward
866 // adjustment of the analog gain. Use low speech probability to limit the
867 // volume changes to clipping handling.
868 CallPreProcessAndProcess(/*num_calls=*/400, audio_buffer,
869 kLowSpeechProbability, /*speech_level=*/-42.0f,
870 *controller);
871 CallPreProcessAndProcess(/*num_calls=*/400, audio_buffer,
872 kLowSpeechProbability, /*speech_level=*/-42.0f,
873 *manager_with_override);
874
875 // Make sure that an adaptation occurred.
876 ASSERT_GT(controller->recommended_analog_level(), 0);
877
878 // Check that the test signal triggers a larger downward adaptation for
879 // `controller`, which is allowed to reach a lower gain.
880 EXPECT_GT(manager_with_override->recommended_analog_level(),
881 controller->recommended_analog_level());
882 // Check that the gain selected by `manager_with_override` equals the
883 // minimum value overridden via field trial.
884 EXPECT_EQ(manager_with_override->recommended_analog_level(), kMinInputVolume);
885 }
886
887 // Checks that, when the "WebRTC-Audio-Agc2-MinInputVolume" field trial is
888 // specified with a valid value, the mic level never gets lowered beyond the
889 // override value in the presence of clipping when RMS error is not empty.
890 // TODO(webrtc:7494): Revisit the test after moving the number of update wait
891 // frames to APM config. The test passes but internally the gain update timing
892 // differs.
TEST(InputVolumeControllerTest,MinInputVolumeCheckMinLevelWithClippingWithRmsError)893 TEST(InputVolumeControllerTest,
894 MinInputVolumeCheckMinLevelWithClippingWithRmsError) {
895 constexpr int kMinInputVolume = 250;
896
897 // Create and initialize two AGCs by specifying and leaving unspecified the
898 // relevant field trial.
899 const auto factory = []() {
900 std::unique_ptr<InputVolumeController> controller =
901 CreateInputVolumeController(kClippedLevelStep, kClippedRatioThreshold,
902 kClippedWaitFrames);
903 controller->Initialize();
904 controller->set_stream_analog_level(kInitialInputVolume);
905 return controller;
906 };
907 std::unique_ptr<InputVolumeController> controller = factory();
908 std::unique_ptr<InputVolumeController> manager_with_override;
909 {
910 test::ScopedFieldTrials field_trial(
911 GetAgcMinInputVolumeFieldTrialEnabled(kMinInputVolume));
912 manager_with_override = factory();
913 }
914
915 // Create a test input signal which containts 80% of clipped samples.
916 AudioBuffer audio_buffer(kSampleRateHz, 1, kSampleRateHz, 1, kSampleRateHz,
917 1);
918 WriteAudioBufferSamples(/*samples_value=*/4000.0f, /*clipped_ratio=*/0.8f,
919 audio_buffer);
920
921 // Simulate 4 seconds of clipping; it is expected to trigger a downward
922 // adjustment of the analog gain.
923 CallPreProcessAndProcess(
924 /*num_calls=*/400, audio_buffer, kHighSpeechProbability,
925 /*speech_level=*/-18.0f, *controller);
926 CallPreProcessAndProcess(
927 /*num_calls=*/400, audio_buffer, kHighSpeechProbability,
928 /*speech_level=*/-18.0f, *manager_with_override);
929
930 // Make sure that an adaptation occurred.
931 ASSERT_GT(controller->recommended_analog_level(), 0);
932
933 // Check that the test signal triggers a larger downward adaptation for
934 // `controller`, which is allowed to reach a lower gain.
935 EXPECT_GT(manager_with_override->recommended_analog_level(),
936 controller->recommended_analog_level());
937 // Check that the gain selected by `manager_with_override` equals the minimum
938 // value overridden via field trial.
939 EXPECT_EQ(manager_with_override->recommended_analog_level(), kMinInputVolume);
940 }
941
942 // Checks that, when the "WebRTC-Audio-Agc2-MinInputVolume" field trial is
943 // specified with a value lower than the `clipped_level_min`, the behavior of
944 // the analog gain controller is the same as that obtained when the field trial
945 // is not specified.
TEST(InputVolumeControllerTest,MinInputVolumeCompareMicLevelWithClipping)946 TEST(InputVolumeControllerTest, MinInputVolumeCompareMicLevelWithClipping) {
947 // Create and initialize two AGCs by specifying and leaving unspecified the
948 // relevant field trial.
949 const auto factory = []() {
950 // Use a large clipped level step to more quickly decrease the analog gain
951 // with clipping.
952 InputVolumeControllerConfig config = kDefaultInputVolumeControllerConfig;
953 config.clipped_level_step = 64;
954 config.clipped_ratio_threshold = kClippedRatioThreshold;
955 config.clipped_wait_frames = kClippedWaitFrames;
956 auto controller = std::make_unique<InputVolumeController>(
957 /*num_capture_channels=*/1, config);
958 controller->Initialize();
959 controller->set_stream_analog_level(kInitialInputVolume);
960 return controller;
961 };
962 std::unique_ptr<InputVolumeController> controller = factory();
963 std::unique_ptr<InputVolumeController> manager_with_override;
964 {
965 constexpr int kMinInputVolume = 20;
966 static_assert(kDefaultInputVolumeControllerConfig.clipped_level_min >=
967 kMinInputVolume,
968 "Use a lower override value.");
969 test::ScopedFieldTrials field_trial(
970 GetAgcMinInputVolumeFieldTrialEnabled(kMinInputVolume));
971 manager_with_override = factory();
972 }
973
974 // Create a test input signal which containts 80% of clipped samples.
975 AudioBuffer audio_buffer(kSampleRateHz, 1, kSampleRateHz, 1, kSampleRateHz,
976 1);
977 WriteAudioBufferSamples(/*samples_value=*/4000.0f, /*clipped_ratio=*/0.8f,
978 audio_buffer);
979
980 // Simulate 4 seconds of clipping; it is expected to trigger a downward
981 // adjustment of the analog gain. Use low speech probability to limit the
982 // volume changes to clipping handling.
983 CallPreProcessAndProcess(/*num_calls=*/400, audio_buffer,
984 kLowSpeechProbability, /*speech_level=*/-18,
985 *controller);
986 CallPreProcessAndProcess(/*num_calls=*/400, audio_buffer,
987 kLowSpeechProbability, /*speech_level=*/-18,
988 *manager_with_override);
989
990 // Make sure that an adaptation occurred.
991 ASSERT_GT(controller->recommended_analog_level(), 0);
992
993 // Check that the selected analog gain is the same for both controllers and
994 // that it equals the minimum level reached when clipping is handled. That is
995 // expected because the minimum microphone level override is less than the
996 // minimum level used when clipping is detected.
997 EXPECT_EQ(controller->recommended_analog_level(),
998 manager_with_override->recommended_analog_level());
999 EXPECT_EQ(manager_with_override->recommended_analog_level(),
1000 kDefaultInputVolumeControllerConfig.clipped_level_min);
1001 }
1002
1003 // Checks that, when the "WebRTC-Audio-Agc2-MinInputVolume" field trial is
1004 // specified with a value lower than the `clipped_level_min`, the behavior of
1005 // the analog gain controller is the same as that obtained when the field trial
1006 // is not specified.
1007 // TODO(webrtc:7494): Revisit the test after moving the number of update wait
1008 // frames to APM config. The test passes but internally the gain update timing
1009 // differs.
TEST(InputVolumeControllerTest,MinInputVolumeCompareMicLevelWithClippingWithRmsError)1010 TEST(InputVolumeControllerTest,
1011 MinInputVolumeCompareMicLevelWithClippingWithRmsError) {
1012 // Create and initialize two AGCs by specifying and leaving unspecified the
1013 // relevant field trial.
1014 const auto factory = []() {
1015 // Use a large clipped level step to more quickly decrease the analog gain
1016 // with clipping.
1017 InputVolumeControllerConfig config = kDefaultInputVolumeControllerConfig;
1018 config.clipped_level_step = 64;
1019 config.clipped_ratio_threshold = kClippedRatioThreshold;
1020 config.clipped_wait_frames = kClippedWaitFrames;
1021 auto controller = std::make_unique<InputVolumeController>(
1022 /*num_capture_channels=*/1, config);
1023 controller->Initialize();
1024 controller->set_stream_analog_level(kInitialInputVolume);
1025 return controller;
1026 };
1027 std::unique_ptr<InputVolumeController> controller = factory();
1028 std::unique_ptr<InputVolumeController> manager_with_override;
1029 {
1030 constexpr int kMinInputVolume = 20;
1031 static_assert(kDefaultInputVolumeControllerConfig.clipped_level_min >=
1032 kMinInputVolume,
1033 "Use a lower override value.");
1034 test::ScopedFieldTrials field_trial(
1035 GetAgcMinInputVolumeFieldTrialEnabled(kMinInputVolume));
1036 manager_with_override = factory();
1037 }
1038
1039 // Create a test input signal which containts 80% of clipped samples.
1040 AudioBuffer audio_buffer(kSampleRateHz, 1, kSampleRateHz, 1, kSampleRateHz,
1041 1);
1042 WriteAudioBufferSamples(/*samples_value=*/4000.0f, /*clipped_ratio=*/0.8f,
1043 audio_buffer);
1044
1045 CallPreProcessAndProcess(
1046 /*num_calls=*/400, audio_buffer,
1047 /*speech_probability=*/0.7f,
1048 /*speech_level=*/-18.0f, *controller);
1049 CallPreProcessAndProcess(
1050 /*num_calls=*/400, audio_buffer,
1051 /*speech_probability=*/0.7f,
1052 /*speech_level=*/-18.0f, *manager_with_override);
1053
1054 // Make sure that an adaptation occurred.
1055 ASSERT_GT(controller->recommended_analog_level(), 0);
1056
1057 // Check that the selected analog gain is the same for both controllers and
1058 // that it equals the minimum level reached when clipping is handled. That is
1059 // expected because the minimum microphone level override is less than the
1060 // minimum level used when clipping is detected.
1061 EXPECT_EQ(controller->recommended_analog_level(),
1062 manager_with_override->recommended_analog_level());
1063 EXPECT_EQ(manager_with_override->recommended_analog_level(),
1064 kDefaultInputVolumeControllerConfig.clipped_level_min);
1065 }
1066
1067 // TODO(bugs.webrtc.org/12774): Test the bahavior of `clipped_level_step`.
1068 // TODO(bugs.webrtc.org/12774): Test the bahavior of `clipped_ratio_threshold`.
1069 // TODO(bugs.webrtc.org/12774): Test the bahavior of `clipped_wait_frames`.
1070 // Verifies that configurable clipping parameters are initialized as intended.
TEST_P(InputVolumeControllerParametrizedTest,ClippingParametersVerified)1071 TEST_P(InputVolumeControllerParametrizedTest, ClippingParametersVerified) {
1072 std::unique_ptr<InputVolumeController> controller =
1073 CreateInputVolumeController(kClippedLevelStep, kClippedRatioThreshold,
1074 kClippedWaitFrames);
1075 controller->Initialize();
1076 EXPECT_EQ(controller->clipped_level_step_, kClippedLevelStep);
1077 EXPECT_EQ(controller->clipped_ratio_threshold_, kClippedRatioThreshold);
1078 EXPECT_EQ(controller->clipped_wait_frames_, kClippedWaitFrames);
1079 std::unique_ptr<InputVolumeController> manager_custom =
1080 CreateInputVolumeController(/*clipped_level_step=*/10,
1081 /*clipped_ratio_threshold=*/0.2f,
1082 /*clipped_wait_frames=*/50);
1083 manager_custom->Initialize();
1084 EXPECT_EQ(manager_custom->clipped_level_step_, 10);
1085 EXPECT_EQ(manager_custom->clipped_ratio_threshold_, 0.2f);
1086 EXPECT_EQ(manager_custom->clipped_wait_frames_, 50);
1087 }
1088
TEST_P(InputVolumeControllerParametrizedTest,DisableClippingPredictorDisablesClippingPredictor)1089 TEST_P(InputVolumeControllerParametrizedTest,
1090 DisableClippingPredictorDisablesClippingPredictor) {
1091 std::unique_ptr<InputVolumeController> controller =
1092 CreateInputVolumeController(kClippedLevelStep, kClippedRatioThreshold,
1093 kClippedWaitFrames,
1094 /*enable_clipping_predictor=*/false);
1095 controller->Initialize();
1096
1097 EXPECT_FALSE(controller->clipping_predictor_enabled());
1098 EXPECT_FALSE(controller->use_clipping_predictor_step());
1099 }
1100
TEST_P(InputVolumeControllerParametrizedTest,EnableClippingPredictorEnablesClippingPredictor)1101 TEST_P(InputVolumeControllerParametrizedTest,
1102 EnableClippingPredictorEnablesClippingPredictor) {
1103 std::unique_ptr<InputVolumeController> controller =
1104 CreateInputVolumeController(kClippedLevelStep, kClippedRatioThreshold,
1105 kClippedWaitFrames,
1106 /*enable_clipping_predictor=*/true);
1107 controller->Initialize();
1108
1109 EXPECT_TRUE(controller->clipping_predictor_enabled());
1110 EXPECT_TRUE(controller->use_clipping_predictor_step());
1111 }
1112
TEST_P(InputVolumeControllerParametrizedTest,DisableClippingPredictorDoesNotLowerVolume)1113 TEST_P(InputVolumeControllerParametrizedTest,
1114 DisableClippingPredictorDoesNotLowerVolume) {
1115 AudioBuffer audio_buffer(kSampleRateHz, kNumChannels, kSampleRateHz,
1116 kNumChannels, kSampleRateHz, kNumChannels);
1117
1118 InputVolumeControllerConfig config = GetInputVolumeControllerTestConfig();
1119 config.enable_clipping_predictor = false;
1120 InputVolumeController controller(/*num_capture_channels=*/1, config);
1121 controller.Initialize();
1122 controller.set_stream_analog_level(/*level=*/255);
1123 EXPECT_FALSE(controller.clipping_predictor_enabled());
1124 EXPECT_FALSE(controller.use_clipping_predictor_step());
1125 EXPECT_EQ(controller.recommended_analog_level(), 255);
1126 controller.Process(kHighSpeechProbability, kSpeechLevel);
1127 CallPreProcessAudioBuffer(/*num_calls=*/10, /*peak_ratio=*/0.99f, controller);
1128 EXPECT_EQ(controller.recommended_analog_level(), 255);
1129 CallPreProcessAudioBuffer(/*num_calls=*/300, /*peak_ratio=*/0.99f,
1130 controller);
1131 EXPECT_EQ(controller.recommended_analog_level(), 255);
1132 CallPreProcessAudioBuffer(/*num_calls=*/10, /*peak_ratio=*/0.99f, controller);
1133 EXPECT_EQ(controller.recommended_analog_level(), 255);
1134 }
1135
TEST_P(InputVolumeControllerParametrizedTest,UsedClippingPredictionsProduceLowerAnalogLevels)1136 TEST_P(InputVolumeControllerParametrizedTest,
1137 UsedClippingPredictionsProduceLowerAnalogLevels) {
1138 AudioBuffer audio_buffer(kSampleRateHz, kNumChannels, kSampleRateHz,
1139 kNumChannels, kSampleRateHz, kNumChannels);
1140
1141 InputVolumeControllerConfig config_with_prediction =
1142 GetInputVolumeControllerTestConfig();
1143 config_with_prediction.enable_clipping_predictor = true;
1144
1145 InputVolumeControllerConfig config_without_prediction =
1146 GetInputVolumeControllerTestConfig();
1147
1148 config_without_prediction.enable_clipping_predictor = false;
1149 InputVolumeController manager_without_prediction(/*num_capture_channels=*/1,
1150 config_without_prediction);
1151 InputVolumeController manager_with_prediction(/*num_capture_channels=*/1,
1152 config_with_prediction);
1153
1154 manager_with_prediction.Initialize();
1155 manager_without_prediction.Initialize();
1156
1157 constexpr int kInitialLevel = 255;
1158 constexpr float kClippingPeakRatio = 1.0f;
1159 constexpr float kCloseToClippingPeakRatio = 0.99f;
1160 constexpr float kZeroPeakRatio = 0.0f;
1161 manager_with_prediction.set_stream_analog_level(kInitialLevel);
1162 manager_without_prediction.set_stream_analog_level(kInitialLevel);
1163
1164 manager_with_prediction.Process(kHighSpeechProbability, kSpeechLevel);
1165 manager_without_prediction.Process(kHighSpeechProbability, kSpeechLevel);
1166
1167 EXPECT_TRUE(manager_with_prediction.clipping_predictor_enabled());
1168 EXPECT_FALSE(manager_without_prediction.clipping_predictor_enabled());
1169 EXPECT_TRUE(manager_with_prediction.use_clipping_predictor_step());
1170 EXPECT_EQ(manager_with_prediction.recommended_analog_level(), kInitialLevel);
1171 EXPECT_EQ(manager_without_prediction.recommended_analog_level(),
1172 kInitialLevel);
1173
1174 // Expect a change in the analog level when the prediction step is used.
1175 CallPreProcessAudioBuffer(/*num_calls=*/10, kCloseToClippingPeakRatio,
1176 manager_with_prediction);
1177 CallPreProcessAudioBuffer(/*num_calls=*/10, kCloseToClippingPeakRatio,
1178 manager_without_prediction);
1179 EXPECT_EQ(manager_with_prediction.recommended_analog_level(),
1180 kInitialLevel - kClippedLevelStep);
1181 EXPECT_EQ(manager_without_prediction.recommended_analog_level(),
1182 kInitialLevel);
1183
1184 // Expect no change during waiting.
1185 CallPreProcessAudioBuffer(kClippedWaitFrames, kCloseToClippingPeakRatio,
1186 manager_with_prediction);
1187 CallPreProcessAudioBuffer(kClippedWaitFrames, kCloseToClippingPeakRatio,
1188 manager_without_prediction);
1189 EXPECT_EQ(manager_with_prediction.recommended_analog_level(),
1190 kInitialLevel - kClippedLevelStep);
1191 EXPECT_EQ(manager_without_prediction.recommended_analog_level(),
1192 kInitialLevel);
1193
1194 // Expect a change when the prediction step is used.
1195 CallPreProcessAudioBuffer(/*num_calls=*/10, kCloseToClippingPeakRatio,
1196 manager_with_prediction);
1197 CallPreProcessAudioBuffer(/*num_calls=*/10, kCloseToClippingPeakRatio,
1198 manager_without_prediction);
1199 EXPECT_EQ(manager_with_prediction.recommended_analog_level(),
1200 kInitialLevel - 2 * kClippedLevelStep);
1201 EXPECT_EQ(manager_without_prediction.recommended_analog_level(),
1202 kInitialLevel);
1203
1204 // Expect no change when clipping is not detected or predicted.
1205 CallPreProcessAudioBuffer(2 * kClippedWaitFrames, kZeroPeakRatio,
1206 manager_with_prediction);
1207 CallPreProcessAudioBuffer(2 * kClippedWaitFrames, kZeroPeakRatio,
1208 manager_without_prediction);
1209 EXPECT_EQ(manager_with_prediction.recommended_analog_level(),
1210 kInitialLevel - 2 * kClippedLevelStep);
1211 EXPECT_EQ(manager_without_prediction.recommended_analog_level(),
1212 kInitialLevel);
1213
1214 // Expect a change for clipping frames.
1215 CallPreProcessAudioBuffer(/*num_calls=*/1, kClippingPeakRatio,
1216 manager_with_prediction);
1217 CallPreProcessAudioBuffer(/*num_calls=*/1, kClippingPeakRatio,
1218 manager_without_prediction);
1219 EXPECT_EQ(manager_with_prediction.recommended_analog_level(),
1220 kInitialLevel - 3 * kClippedLevelStep);
1221 EXPECT_EQ(manager_without_prediction.recommended_analog_level(),
1222 kInitialLevel - kClippedLevelStep);
1223
1224 // Expect no change during waiting.
1225 CallPreProcessAudioBuffer(kClippedWaitFrames, kClippingPeakRatio,
1226 manager_with_prediction);
1227 CallPreProcessAudioBuffer(kClippedWaitFrames, kClippingPeakRatio,
1228 manager_without_prediction);
1229 EXPECT_EQ(manager_with_prediction.recommended_analog_level(),
1230 kInitialLevel - 3 * kClippedLevelStep);
1231 EXPECT_EQ(manager_without_prediction.recommended_analog_level(),
1232 kInitialLevel - kClippedLevelStep);
1233
1234 // Expect a change for clipping frames.
1235 CallPreProcessAudioBuffer(/*num_calls=*/1, kClippingPeakRatio,
1236 manager_with_prediction);
1237 CallPreProcessAudioBuffer(/*num_calls=*/1, kClippingPeakRatio,
1238 manager_without_prediction);
1239 EXPECT_EQ(manager_with_prediction.recommended_analog_level(),
1240 kInitialLevel - 4 * kClippedLevelStep);
1241 EXPECT_EQ(manager_without_prediction.recommended_analog_level(),
1242 kInitialLevel - 2 * kClippedLevelStep);
1243 }
1244
1245 // Checks that passing an empty speech level has no effect on the input volume.
TEST_P(InputVolumeControllerParametrizedTest,EmptyRmsErrorHasNoEffect)1246 TEST_P(InputVolumeControllerParametrizedTest, EmptyRmsErrorHasNoEffect) {
1247 InputVolumeController controller(kNumChannels,
1248 GetInputVolumeControllerTestConfig());
1249 controller.Initialize();
1250
1251 constexpr int kInputVolume = kInitialInputVolume;
1252 controller.set_stream_analog_level(kInputVolume);
1253
1254 // Feed speech with low energy that would trigger an upward adapation of
1255 // the analog level if an speech level was not low and the RMS level empty.
1256 constexpr int kNumFrames = 125;
1257 constexpr int kGainDb = -20;
1258 SpeechSamplesReader reader;
1259 reader.Feed(kNumFrames, kGainDb, kLowSpeechProbability, absl::nullopt,
1260 controller);
1261
1262 // Check that no adaptation occurs.
1263 ASSERT_EQ(controller.recommended_analog_level(), kInputVolume);
1264 }
1265
1266 // Checks that the recommended input volume is not updated unless enough
1267 // frames have been processed after the previous update.
TEST(InputVolumeControllerTest,UpdateInputVolumeWaitFramesIsEffective)1268 TEST(InputVolumeControllerTest, UpdateInputVolumeWaitFramesIsEffective) {
1269 constexpr int kInputVolume = kInitialInputVolume;
1270 std::unique_ptr<InputVolumeController> controller_wait_0 =
1271 CreateInputVolumeController(kClippedLevelStep, kClippedRatioThreshold,
1272 kClippedWaitFrames,
1273 /*enable_clipping_predictor=*/false,
1274 /*update_input_volume_wait_frames=*/0);
1275 std::unique_ptr<InputVolumeController> controller_wait_100 =
1276 CreateInputVolumeController(kClippedLevelStep, kClippedRatioThreshold,
1277 kClippedWaitFrames,
1278 /*enable_clipping_predictor=*/false,
1279 /*update_input_volume_wait_frames=*/100);
1280 controller_wait_0->Initialize();
1281 controller_wait_100->Initialize();
1282 controller_wait_0->set_stream_analog_level(kInputVolume);
1283 controller_wait_100->set_stream_analog_level(kInputVolume);
1284
1285 SpeechSamplesReader reader_1;
1286 SpeechSamplesReader reader_2;
1287 reader_1.Feed(/*num_frames=*/99, /*gain_db=*/0, kHighSpeechProbability,
1288 /*speech_level=*/-42.0f, *controller_wait_0);
1289 reader_2.Feed(/*num_frames=*/99, /*gain_db=*/0, kHighSpeechProbability,
1290 /*speech_level=*/-42.0f, *controller_wait_100);
1291
1292 // Check that adaptation only occurs if enough frames have been processed.
1293 ASSERT_GT(controller_wait_0->recommended_analog_level(), kInputVolume);
1294 ASSERT_EQ(controller_wait_100->recommended_analog_level(), kInputVolume);
1295
1296 reader_1.Feed(/*num_frames=*/1, /*gain_db=*/0, kHighSpeechProbability,
1297 /*speech_level=*/-42.0f, *controller_wait_0);
1298 reader_2.Feed(/*num_frames=*/1, /*gain_db=*/0, kHighSpeechProbability,
1299 /*speech_level=*/-42.0f, *controller_wait_100);
1300
1301 // Check that adaptation only occurs when enough frames have been processed.
1302 ASSERT_GT(controller_wait_0->recommended_analog_level(), kInputVolume);
1303 ASSERT_GT(controller_wait_100->recommended_analog_level(), kInputVolume);
1304 }
1305
TEST(InputVolumeControllerTest,SpeechRatioThresholdIsEffective)1306 TEST(InputVolumeControllerTest, SpeechRatioThresholdIsEffective) {
1307 constexpr int kInputVolume = kInitialInputVolume;
1308 // Create two input volume controllers with 10 frames between volume updates
1309 // and the minimum speech ratio of 0.8 and speech probability threshold 0.5.
1310 std::unique_ptr<InputVolumeController> controller_1 =
1311 CreateInputVolumeController(kClippedLevelStep, kClippedRatioThreshold,
1312 kClippedWaitFrames,
1313 /*enable_clipping_predictor=*/false,
1314 /*update_input_volume_wait_frames=*/10);
1315 std::unique_ptr<InputVolumeController> controller_2 =
1316 CreateInputVolumeController(kClippedLevelStep, kClippedRatioThreshold,
1317 kClippedWaitFrames,
1318 /*enable_clipping_predictor=*/false,
1319 /*update_input_volume_wait_frames=*/10);
1320 controller_1->Initialize();
1321 controller_2->Initialize();
1322 controller_1->set_stream_analog_level(kInputVolume);
1323 controller_2->set_stream_analog_level(kInputVolume);
1324
1325 SpeechSamplesReader reader_1;
1326 SpeechSamplesReader reader_2;
1327
1328 reader_1.Feed(/*num_frames=*/1, /*gain_db=*/0,
1329 /*speech_probability=*/0.7f, /*speech_level=*/-42.0f,
1330 *controller_1);
1331 reader_2.Feed(/*num_frames=*/1, /*gain_db=*/0,
1332 /*speech_probability=*/0.4f, /*speech_level=*/-42.0f,
1333 *controller_2);
1334
1335 ASSERT_EQ(controller_1->recommended_analog_level(), kInputVolume);
1336 ASSERT_EQ(controller_2->recommended_analog_level(), kInputVolume);
1337
1338 reader_1.Feed(/*num_frames=*/2, /*gain_db=*/0,
1339 /*speech_probability=*/0.4f, /*speech_level=*/-42.0f,
1340 *controller_1);
1341 reader_2.Feed(/*num_frames=*/2, /*gain_db=*/0,
1342 /*speech_probability=*/0.4f, /*speech_level=*/-42.0f,
1343 *controller_2);
1344
1345 ASSERT_EQ(controller_1->recommended_analog_level(), kInputVolume);
1346 ASSERT_EQ(controller_2->recommended_analog_level(), kInputVolume);
1347
1348 reader_1.Feed(/*num_frames=*/7, /*gain_db=*/0,
1349 /*speech_probability=*/0.7f, /*speech_level=*/-42.0f,
1350 *controller_1);
1351 reader_2.Feed(/*num_frames=*/7, /*gain_db=*/0,
1352 /*speech_probability=*/0.7f, /*speech_level=*/-42.0f,
1353 *controller_2);
1354
1355 ASSERT_GT(controller_1->recommended_analog_level(), kInputVolume);
1356 ASSERT_EQ(controller_2->recommended_analog_level(), kInputVolume);
1357 }
1358
TEST(InputVolumeControllerTest,SpeechProbabilityThresholdIsEffective)1359 TEST(InputVolumeControllerTest, SpeechProbabilityThresholdIsEffective) {
1360 constexpr int kInputVolume = kInitialInputVolume;
1361 // Create two input volume controllers with the exact same settings and
1362 // 10 frames between volume updates.
1363 std::unique_ptr<InputVolumeController> controller_1 =
1364 CreateInputVolumeController(kClippedLevelStep, kClippedRatioThreshold,
1365 kClippedWaitFrames,
1366 /*enable_clipping_predictor=*/false,
1367 /*update_input_volume_wait_frames=*/10);
1368 std::unique_ptr<InputVolumeController> controller_2 =
1369 CreateInputVolumeController(kClippedLevelStep, kClippedRatioThreshold,
1370 kClippedWaitFrames,
1371 /*enable_clipping_predictor=*/false,
1372 /*update_input_volume_wait_frames=*/10);
1373 controller_1->Initialize();
1374 controller_2->Initialize();
1375 controller_1->set_stream_analog_level(kInputVolume);
1376 controller_2->set_stream_analog_level(kInputVolume);
1377
1378 SpeechSamplesReader reader_1;
1379 SpeechSamplesReader reader_2;
1380
1381 // Process with two sets of inputs: Use `reader_1` to process inputs
1382 // that make the volume to be adjusted after enough frames have been
1383 // processsed and `reader_2` to process inputs that won't make the volume
1384 // to be adjusted.
1385 reader_1.Feed(/*num_frames=*/1, /*gain_db=*/0,
1386 /*speech_probability=*/0.5f, /*speech_level=*/-42.0f,
1387 *controller_1);
1388 reader_2.Feed(/*num_frames=*/1, /*gain_db=*/0,
1389 /*speech_probability=*/0.49f, /*speech_level=*/-42.0f,
1390 *controller_2);
1391
1392 ASSERT_EQ(controller_1->recommended_analog_level(), kInputVolume);
1393 ASSERT_EQ(controller_2->recommended_analog_level(), kInputVolume);
1394
1395 reader_1.Feed(/*num_frames=*/2, /*gain_db=*/0,
1396 /*speech_probability=*/0.49f, /*speech_level=*/-42.0f,
1397 *controller_1);
1398 reader_2.Feed(/*num_frames=*/2, /*gain_db=*/0,
1399 /*speech_probability=*/0.49f, /*speech_level=*/-42.0f,
1400 *controller_2);
1401
1402 ASSERT_EQ(controller_1->recommended_analog_level(), kInputVolume);
1403 ASSERT_EQ(controller_2->recommended_analog_level(), kInputVolume);
1404
1405 reader_1.Feed(/*num_frames=*/7, /*gain_db=*/0,
1406 /*speech_probability=*/0.5f, /*speech_level=*/-42.0f,
1407 *controller_1);
1408 reader_2.Feed(/*num_frames=*/7, /*gain_db=*/0,
1409 /*speech_probability=*/0.5f, /*speech_level=*/-42.0f,
1410 *controller_2);
1411
1412 ASSERT_GT(controller_1->recommended_analog_level(), kInputVolume);
1413 ASSERT_EQ(controller_2->recommended_analog_level(), kInputVolume);
1414 }
1415
TEST(MonoInputVolumeControllerTest,CheckHandleClippingLowersVolume)1416 TEST(MonoInputVolumeControllerTest, CheckHandleClippingLowersVolume) {
1417 constexpr int kInitialInputVolume = 100;
1418 constexpr int kInputVolumeStep = 29;
1419 MonoInputVolumeController mono_controller(
1420 /*clipped_level_min=*/70,
1421 /*min_mic_level=*/32,
1422 /*update_input_volume_wait_frames=*/3, kHighSpeechProbability,
1423 kSpeechRatioThreshold);
1424 mono_controller.Initialize();
1425
1426 UpdateRecommendedInputVolume(mono_controller, kInitialInputVolume,
1427 kLowSpeechProbability,
1428 /*rms_error_dbfs*/ -10.0f);
1429
1430 mono_controller.HandleClipping(kInputVolumeStep);
1431
1432 EXPECT_EQ(mono_controller.recommended_analog_level(),
1433 kInitialInputVolume - kInputVolumeStep);
1434 }
1435
TEST(MonoInputVolumeControllerTest,CheckProcessNegativeRmsErrorDecreasesInputVolume)1436 TEST(MonoInputVolumeControllerTest,
1437 CheckProcessNegativeRmsErrorDecreasesInputVolume) {
1438 constexpr int kInitialInputVolume = 100;
1439 MonoInputVolumeController mono_controller(
1440 /*clipped_level_min=*/64,
1441 /*min_mic_level=*/32,
1442 /*update_input_volume_wait_frames=*/3, kHighSpeechProbability,
1443 kSpeechRatioThreshold);
1444 mono_controller.Initialize();
1445
1446 int volume = UpdateRecommendedInputVolume(
1447 mono_controller, kInitialInputVolume, kHighSpeechProbability, -10.0f);
1448 volume = UpdateRecommendedInputVolume(mono_controller, volume,
1449 kHighSpeechProbability, -10.0f);
1450 volume = UpdateRecommendedInputVolume(mono_controller, volume,
1451 kHighSpeechProbability, -10.0f);
1452
1453 EXPECT_LT(volume, kInitialInputVolume);
1454 }
1455
TEST(MonoInputVolumeControllerTest,CheckProcessPositiveRmsErrorIncreasesInputVolume)1456 TEST(MonoInputVolumeControllerTest,
1457 CheckProcessPositiveRmsErrorIncreasesInputVolume) {
1458 constexpr int kInitialInputVolume = 100;
1459 MonoInputVolumeController mono_controller(
1460 /*clipped_level_min=*/64,
1461 /*min_mic_level=*/32,
1462 /*update_input_volume_wait_frames=*/3, kHighSpeechProbability,
1463 kSpeechRatioThreshold);
1464 mono_controller.Initialize();
1465
1466 int volume = UpdateRecommendedInputVolume(
1467 mono_controller, kInitialInputVolume, kHighSpeechProbability, 10.0f);
1468 volume = UpdateRecommendedInputVolume(mono_controller, volume,
1469 kHighSpeechProbability, 10.0f);
1470 volume = UpdateRecommendedInputVolume(mono_controller, volume,
1471 kHighSpeechProbability, 10.0f);
1472
1473 EXPECT_GT(volume, kInitialInputVolume);
1474 }
1475
TEST(MonoInputVolumeControllerTest,CheckProcessNegativeRmsErrorDecreasesInputVolumeWithLimit)1476 TEST(MonoInputVolumeControllerTest,
1477 CheckProcessNegativeRmsErrorDecreasesInputVolumeWithLimit) {
1478 constexpr int kInitialInputVolume = 100;
1479 MonoInputVolumeController mono_controller_1(
1480 /*clipped_level_min=*/64,
1481 /*min_mic_level=*/32,
1482 /*update_input_volume_wait_frames=*/2, kHighSpeechProbability,
1483 kSpeechRatioThreshold);
1484 MonoInputVolumeController mono_controller_2(
1485 /*clipped_level_min=*/64,
1486 /*min_mic_level=*/32,
1487 /*update_input_volume_wait_frames=*/2, kHighSpeechProbability,
1488 kSpeechRatioThreshold);
1489 MonoInputVolumeController mono_controller_3(
1490 /*clipped_level_min=*/64,
1491 /*min_mic_level=*/32,
1492 /*update_input_volume_wait_frames=*/2,
1493 /*speech_probability_threshold=*/0.7,
1494 /*speech_ratio_threshold=*/0.8);
1495 mono_controller_1.Initialize();
1496 mono_controller_2.Initialize();
1497 mono_controller_3.Initialize();
1498
1499 // Process RMS errors in the range
1500 // [`-kMaxResidualGainChange`, `kMaxResidualGainChange`].
1501 int volume_1 = UpdateRecommendedInputVolume(
1502 mono_controller_1, kInitialInputVolume, kHighSpeechProbability, -14.0f);
1503 volume_1 = UpdateRecommendedInputVolume(mono_controller_1, volume_1,
1504 kHighSpeechProbability, -14.0f);
1505 // Process RMS errors outside the range
1506 // [`-kMaxResidualGainChange`, `kMaxResidualGainChange`].
1507 int volume_2 = UpdateRecommendedInputVolume(
1508 mono_controller_2, kInitialInputVolume, kHighSpeechProbability, -15.0f);
1509 int volume_3 = UpdateRecommendedInputVolume(
1510 mono_controller_3, kInitialInputVolume, kHighSpeechProbability, -30.0f);
1511 volume_2 = UpdateRecommendedInputVolume(mono_controller_2, volume_2,
1512 kHighSpeechProbability, -15.0f);
1513 volume_3 = UpdateRecommendedInputVolume(mono_controller_3, volume_3,
1514 kHighSpeechProbability, -30.0f);
1515
1516 EXPECT_LT(volume_1, kInitialInputVolume);
1517 EXPECT_LT(volume_2, volume_1);
1518 EXPECT_EQ(volume_2, volume_3);
1519 }
1520
TEST(MonoInputVolumeControllerTest,CheckProcessPositiveRmsErrorIncreasesInputVolumeWithLimit)1521 TEST(MonoInputVolumeControllerTest,
1522 CheckProcessPositiveRmsErrorIncreasesInputVolumeWithLimit) {
1523 constexpr int kInitialInputVolume = 100;
1524 MonoInputVolumeController mono_controller_1(
1525 /*clipped_level_min=*/64,
1526 /*min_mic_level=*/32,
1527 /*update_input_volume_wait_frames=*/2, kHighSpeechProbability,
1528 kSpeechRatioThreshold);
1529 MonoInputVolumeController mono_controller_2(
1530 /*clipped_level_min=*/64,
1531 /*min_mic_level=*/32,
1532 /*update_input_volume_wait_frames=*/2, kHighSpeechProbability,
1533 kSpeechRatioThreshold);
1534 MonoInputVolumeController mono_controller_3(
1535 /*clipped_level_min=*/64,
1536 /*min_mic_level=*/32,
1537 /*update_input_volume_wait_frames=*/2, kHighSpeechProbability,
1538 kSpeechRatioThreshold);
1539 mono_controller_1.Initialize();
1540 mono_controller_2.Initialize();
1541 mono_controller_3.Initialize();
1542
1543 // Process RMS errors in the range
1544 // [`-kMaxResidualGainChange`, `kMaxResidualGainChange`].
1545 int volume_1 = UpdateRecommendedInputVolume(
1546 mono_controller_1, kInitialInputVolume, kHighSpeechProbability, 14.0f);
1547 volume_1 = UpdateRecommendedInputVolume(mono_controller_1, volume_1,
1548 kHighSpeechProbability, 14.0f);
1549 // Process RMS errors outside the range
1550 // [`-kMaxResidualGainChange`, `kMaxResidualGainChange`].
1551 int volume_2 = UpdateRecommendedInputVolume(
1552 mono_controller_2, kInitialInputVolume, kHighSpeechProbability, 15.0f);
1553 int volume_3 = UpdateRecommendedInputVolume(
1554 mono_controller_3, kInitialInputVolume, kHighSpeechProbability, 30.0f);
1555 volume_2 = UpdateRecommendedInputVolume(mono_controller_2, volume_2,
1556 kHighSpeechProbability, 15.0f);
1557 volume_3 = UpdateRecommendedInputVolume(mono_controller_3, volume_3,
1558 kHighSpeechProbability, 30.0f);
1559
1560 EXPECT_GT(volume_1, kInitialInputVolume);
1561 EXPECT_GT(volume_2, volume_1);
1562 EXPECT_EQ(volume_2, volume_3);
1563 }
1564
TEST(MonoInputVolumeControllerTest,CheckProcessRmsErrorDecreasesInputVolumeRepeatedly)1565 TEST(MonoInputVolumeControllerTest,
1566 CheckProcessRmsErrorDecreasesInputVolumeRepeatedly) {
1567 constexpr int kInitialInputVolume = 100;
1568 MonoInputVolumeController mono_controller(
1569 /*clipped_level_min=*/64,
1570 /*min_mic_level=*/32,
1571 /*update_input_volume_wait_frames=*/2, kHighSpeechProbability,
1572 kSpeechRatioThreshold);
1573 mono_controller.Initialize();
1574
1575 int volume_before = UpdateRecommendedInputVolume(
1576 mono_controller, kInitialInputVolume, kHighSpeechProbability, -10.0f);
1577 volume_before = UpdateRecommendedInputVolume(mono_controller, volume_before,
1578 kHighSpeechProbability, -10.0f);
1579
1580 EXPECT_LT(volume_before, kInitialInputVolume);
1581
1582 int volume_after = UpdateRecommendedInputVolume(
1583 mono_controller, volume_before, kHighSpeechProbability, -10.0f);
1584 volume_after = UpdateRecommendedInputVolume(mono_controller, volume_after,
1585 kHighSpeechProbability, -10.0f);
1586
1587 EXPECT_LT(volume_after, volume_before);
1588 }
1589
TEST(MonoInputVolumeControllerTest,CheckProcessPositiveRmsErrorIncreasesInputVolumeRepeatedly)1590 TEST(MonoInputVolumeControllerTest,
1591 CheckProcessPositiveRmsErrorIncreasesInputVolumeRepeatedly) {
1592 constexpr int kInitialInputVolume = 100;
1593 MonoInputVolumeController mono_controller(
1594 /*clipped_level_min=*/64,
1595 /*min_mic_level=*/32,
1596 /*update_input_volume_wait_frames=*/2, kHighSpeechProbability,
1597 kSpeechRatioThreshold);
1598 mono_controller.Initialize();
1599
1600 int volume_before = UpdateRecommendedInputVolume(
1601 mono_controller, kInitialInputVolume, kHighSpeechProbability, 10.0f);
1602 volume_before = UpdateRecommendedInputVolume(mono_controller, volume_before,
1603 kHighSpeechProbability, 10.0f);
1604
1605 EXPECT_GT(volume_before, kInitialInputVolume);
1606
1607 int volume_after = UpdateRecommendedInputVolume(
1608 mono_controller, volume_before, kHighSpeechProbability, 10.0f);
1609 volume_after = UpdateRecommendedInputVolume(mono_controller, volume_after,
1610 kHighSpeechProbability, 10.0f);
1611
1612 EXPECT_GT(volume_after, volume_before);
1613 }
1614
TEST(MonoInputVolumeControllerTest,CheckClippedLevelMinIsEffective)1615 TEST(MonoInputVolumeControllerTest, CheckClippedLevelMinIsEffective) {
1616 constexpr int kInitialInputVolume = 100;
1617 constexpr int kClippedLevelMin = 70;
1618 MonoInputVolumeController mono_controller_1(
1619 kClippedLevelMin,
1620 /*min_mic_level=*/84,
1621 /*update_input_volume_wait_frames=*/2, kHighSpeechProbability,
1622 kSpeechRatioThreshold);
1623 MonoInputVolumeController mono_controller_2(
1624 kClippedLevelMin,
1625 /*min_mic_level=*/84,
1626 /*update_input_volume_wait_frames=*/2, kHighSpeechProbability,
1627 kSpeechRatioThreshold);
1628 mono_controller_1.Initialize();
1629 mono_controller_2.Initialize();
1630
1631 // Process one frame to reset the state for `HandleClipping()`.
1632 EXPECT_EQ(UpdateRecommendedInputVolume(mono_controller_1, kInitialInputVolume,
1633 kLowSpeechProbability, -10.0f),
1634 kInitialInputVolume);
1635 EXPECT_EQ(UpdateRecommendedInputVolume(mono_controller_2, kInitialInputVolume,
1636 kLowSpeechProbability, -10.0f),
1637 kInitialInputVolume);
1638
1639 mono_controller_1.HandleClipping(29);
1640 mono_controller_2.HandleClipping(31);
1641
1642 EXPECT_EQ(mono_controller_2.recommended_analog_level(), kClippedLevelMin);
1643 EXPECT_LT(mono_controller_2.recommended_analog_level(),
1644 mono_controller_1.recommended_analog_level());
1645 }
1646
TEST(MonoInputVolumeControllerTest,CheckMinMicLevelIsEffective)1647 TEST(MonoInputVolumeControllerTest, CheckMinMicLevelIsEffective) {
1648 constexpr int kInitialInputVolume = 100;
1649 constexpr int kMinMicLevel = 64;
1650 MonoInputVolumeController mono_controller_1(
1651 /*clipped_level_min=*/64, kMinMicLevel,
1652 /*update_input_volume_wait_frames=*/2, kHighSpeechProbability,
1653 kSpeechRatioThreshold);
1654 MonoInputVolumeController mono_controller_2(
1655 /*clipped_level_min=*/64, kMinMicLevel,
1656 /*update_input_volume_wait_frames=*/2, kHighSpeechProbability,
1657 kSpeechRatioThreshold);
1658 mono_controller_1.Initialize();
1659 mono_controller_2.Initialize();
1660
1661 int volume_1 = UpdateRecommendedInputVolume(
1662 mono_controller_1, kInitialInputVolume, kHighSpeechProbability, -10.0f);
1663 int volume_2 = UpdateRecommendedInputVolume(
1664 mono_controller_2, kInitialInputVolume, kHighSpeechProbability, -10.0f);
1665
1666 EXPECT_EQ(volume_1, kInitialInputVolume);
1667 EXPECT_EQ(volume_2, kInitialInputVolume);
1668
1669 volume_1 = UpdateRecommendedInputVolume(mono_controller_1, volume_1,
1670 kHighSpeechProbability, -10.0f);
1671 volume_2 = UpdateRecommendedInputVolume(mono_controller_2, volume_2,
1672 kHighSpeechProbability, -30.0f);
1673
1674 EXPECT_LT(volume_1, kInitialInputVolume);
1675 EXPECT_LT(volume_2, volume_1);
1676 EXPECT_EQ(volume_2, kMinMicLevel);
1677 }
1678
TEST(MonoInputVolumeControllerTest,CheckUpdateInputVolumeWaitFramesIsEffective)1679 TEST(MonoInputVolumeControllerTest,
1680 CheckUpdateInputVolumeWaitFramesIsEffective) {
1681 constexpr int kInitialInputVolume = 100;
1682 MonoInputVolumeController mono_controller_1(
1683 /*clipped_level_min=*/64,
1684 /*min_mic_level=*/84,
1685 /*update_input_volume_wait_frames=*/1, kHighSpeechProbability,
1686 kSpeechRatioThreshold);
1687 MonoInputVolumeController mono_controller_2(
1688 /*clipped_level_min=*/64,
1689 /*min_mic_level=*/84,
1690 /*update_input_volume_wait_frames=*/3, kHighSpeechProbability,
1691 kSpeechRatioThreshold);
1692 mono_controller_1.Initialize();
1693 mono_controller_2.Initialize();
1694
1695 int volume_1 = UpdateRecommendedInputVolume(
1696 mono_controller_1, kInitialInputVolume, kHighSpeechProbability, -10.0f);
1697 int volume_2 = UpdateRecommendedInputVolume(
1698 mono_controller_2, kInitialInputVolume, kHighSpeechProbability, -10.0f);
1699
1700 EXPECT_EQ(volume_1, kInitialInputVolume);
1701 EXPECT_EQ(volume_2, kInitialInputVolume);
1702
1703 volume_1 = UpdateRecommendedInputVolume(mono_controller_1, volume_1,
1704 kHighSpeechProbability, -10.0f);
1705 volume_2 = UpdateRecommendedInputVolume(mono_controller_2, volume_2,
1706 kHighSpeechProbability, -10.0f);
1707
1708 EXPECT_LT(volume_1, kInitialInputVolume);
1709 EXPECT_EQ(volume_2, kInitialInputVolume);
1710
1711 volume_2 = UpdateRecommendedInputVolume(mono_controller_2, volume_2,
1712 kHighSpeechProbability, -10.0f);
1713
1714 EXPECT_LT(volume_2, kInitialInputVolume);
1715 }
1716
TEST(MonoInputVolumeControllerTest,CheckSpeechProbabilityThresholdIsEffective)1717 TEST(MonoInputVolumeControllerTest,
1718 CheckSpeechProbabilityThresholdIsEffective) {
1719 constexpr int kInitialInputVolume = 100;
1720 constexpr float kSpeechProbabilityThreshold = 0.8f;
1721 MonoInputVolumeController mono_controller_1(
1722 /*clipped_level_min=*/64,
1723 /*min_mic_level=*/84,
1724 /*update_input_volume_wait_frames=*/2, kSpeechProbabilityThreshold,
1725 kSpeechRatioThreshold);
1726 MonoInputVolumeController mono_controller_2(
1727 /*clipped_level_min=*/64,
1728 /*min_mic_level=*/84,
1729 /*update_input_volume_wait_frames=*/2, kSpeechProbabilityThreshold,
1730 kSpeechRatioThreshold);
1731 mono_controller_1.Initialize();
1732 mono_controller_2.Initialize();
1733
1734 int volume_1 =
1735 UpdateRecommendedInputVolume(mono_controller_1, kInitialInputVolume,
1736 kSpeechProbabilityThreshold, -10.0f);
1737 int volume_2 =
1738 UpdateRecommendedInputVolume(mono_controller_2, kInitialInputVolume,
1739 kSpeechProbabilityThreshold, -10.0f);
1740
1741 EXPECT_EQ(volume_1, kInitialInputVolume);
1742 EXPECT_EQ(volume_2, kInitialInputVolume);
1743
1744 volume_1 = UpdateRecommendedInputVolume(
1745 mono_controller_1, volume_1, kSpeechProbabilityThreshold - 0.1f, -10.0f);
1746 volume_2 = UpdateRecommendedInputVolume(mono_controller_2, volume_2,
1747 kSpeechProbabilityThreshold, -10.0f);
1748
1749 EXPECT_EQ(volume_1, kInitialInputVolume);
1750 EXPECT_LT(volume_2, volume_1);
1751 }
1752
TEST(MonoInputVolumeControllerTest,CheckSpeechRatioThresholdIsEffective)1753 TEST(MonoInputVolumeControllerTest, CheckSpeechRatioThresholdIsEffective) {
1754 constexpr int kInitialInputVolume = 100;
1755 MonoInputVolumeController mono_controller_1(
1756 /*clipped_level_min=*/64,
1757 /*min_mic_level=*/84,
1758 /*update_input_volume_wait_frames=*/4, kHighSpeechProbability,
1759 /*speech_ratio_threshold=*/0.75f);
1760 MonoInputVolumeController mono_controller_2(
1761 /*clipped_level_min=*/64,
1762 /*min_mic_level=*/84,
1763 /*update_input_volume_wait_frames=*/4, kHighSpeechProbability,
1764 /*speech_ratio_threshold=*/0.75f);
1765 mono_controller_1.Initialize();
1766 mono_controller_2.Initialize();
1767
1768 int volume_1 = UpdateRecommendedInputVolume(
1769 mono_controller_1, kInitialInputVolume, kHighSpeechProbability, -10.0f);
1770 int volume_2 = UpdateRecommendedInputVolume(
1771 mono_controller_2, kInitialInputVolume, kHighSpeechProbability, -10.0f);
1772
1773 volume_1 = UpdateRecommendedInputVolume(mono_controller_1, volume_1,
1774 kHighSpeechProbability, -10.0f);
1775 volume_2 = UpdateRecommendedInputVolume(mono_controller_2, volume_2,
1776 kHighSpeechProbability, -10.0f);
1777
1778 volume_1 = UpdateRecommendedInputVolume(mono_controller_1, volume_1,
1779 kLowSpeechProbability, -10.0f);
1780 volume_2 = UpdateRecommendedInputVolume(mono_controller_2, volume_2,
1781 kLowSpeechProbability, -10.0f);
1782
1783 EXPECT_EQ(volume_1, kInitialInputVolume);
1784 EXPECT_EQ(volume_2, kInitialInputVolume);
1785
1786 volume_1 = UpdateRecommendedInputVolume(mono_controller_1, volume_1,
1787 kLowSpeechProbability, -10.0f);
1788 volume_2 = UpdateRecommendedInputVolume(mono_controller_2, volume_2,
1789 kHighSpeechProbability, -10.0f);
1790
1791 EXPECT_EQ(volume_1, kInitialInputVolume);
1792 EXPECT_LT(volume_2, volume_1);
1793 }
1794
TEST(MonoInputVolumeControllerTest,CheckProcessEmptyRmsErrorDoesNotLowerVolume)1795 TEST(MonoInputVolumeControllerTest,
1796 CheckProcessEmptyRmsErrorDoesNotLowerVolume) {
1797 constexpr int kInitialInputVolume = 100;
1798 MonoInputVolumeController mono_controller_1(
1799 /*clipped_level_min=*/64,
1800 /*min_mic_level=*/84,
1801 /*update_input_volume_wait_frames=*/2, kHighSpeechProbability,
1802 kSpeechRatioThreshold);
1803 MonoInputVolumeController mono_controller_2(
1804 /*clipped_level_min=*/64,
1805 /*min_mic_level=*/84,
1806 /*update_input_volume_wait_frames=*/2, kHighSpeechProbability,
1807 kSpeechRatioThreshold);
1808 mono_controller_1.Initialize();
1809 mono_controller_2.Initialize();
1810
1811 int volume_1 = UpdateRecommendedInputVolume(
1812 mono_controller_1, kInitialInputVolume, kHighSpeechProbability, -10.0f);
1813 int volume_2 = UpdateRecommendedInputVolume(
1814 mono_controller_2, kInitialInputVolume, kHighSpeechProbability, -10.0f);
1815
1816 EXPECT_EQ(volume_1, kInitialInputVolume);
1817 EXPECT_EQ(volume_2, kInitialInputVolume);
1818
1819 volume_1 = UpdateRecommendedInputVolume(
1820 mono_controller_1, volume_1, kHighSpeechProbability, absl::nullopt);
1821 volume_2 = UpdateRecommendedInputVolume(mono_controller_2, volume_2,
1822 kHighSpeechProbability, -10.0f);
1823
1824 EXPECT_EQ(volume_1, kInitialInputVolume);
1825 EXPECT_LT(volume_2, volume_1);
1826 }
1827
1828 } // namespace webrtc
1829