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 "modules/audio_processing/agc/gain_control.h"
14 #include "modules/audio_processing/agc/mock_agc.h"
15 #include "modules/audio_processing/include/mock_audio_processing.h"
16 #include "test/field_trial.h"
17 #include "test/gmock.h"
18 #include "test/gtest.h"
19
20 using ::testing::_;
21 using ::testing::AtLeast;
22 using ::testing::DoAll;
23 using ::testing::Return;
24 using ::testing::SetArgPointee;
25
26 namespace webrtc {
27 namespace {
28
29 const int kSampleRateHz = 32000;
30 const int kNumChannels = 1;
31 const int kSamplesPerChannel = kSampleRateHz / 100;
32 const int kInitialVolume = 128;
33 constexpr int kClippedMin = 165; // Arbitrary, but different from the default.
34 const float kAboveClippedThreshold = 0.2f;
35 const int kMinMicLevel = 12;
36
37 class MockGainControl : public GainControl {
38 public:
~MockGainControl()39 virtual ~MockGainControl() {}
40 MOCK_METHOD(int, set_stream_analog_level, (int level), (override));
41 MOCK_METHOD(int, stream_analog_level, (), (const, override));
42 MOCK_METHOD(int, set_mode, (Mode mode), (override));
43 MOCK_METHOD(Mode, mode, (), (const, override));
44 MOCK_METHOD(int, set_target_level_dbfs, (int level), (override));
45 MOCK_METHOD(int, target_level_dbfs, (), (const, override));
46 MOCK_METHOD(int, set_compression_gain_db, (int gain), (override));
47 MOCK_METHOD(int, compression_gain_db, (), (const, override));
48 MOCK_METHOD(int, enable_limiter, (bool enable), (override));
49 MOCK_METHOD(bool, is_limiter_enabled, (), (const, override));
50 MOCK_METHOD(int,
51 set_analog_level_limits,
52 (int minimum, int maximum),
53 (override));
54 MOCK_METHOD(int, analog_level_minimum, (), (const, override));
55 MOCK_METHOD(int, analog_level_maximum, (), (const, override));
56 MOCK_METHOD(bool, stream_is_saturated, (), (const, override));
57 };
58
59 } // namespace
60
61 class AgcManagerDirectTest : public ::testing::Test {
62 protected:
AgcManagerDirectTest()63 AgcManagerDirectTest()
64 : agc_(new MockAgc),
65 manager_(agc_, kInitialVolume, kClippedMin, kSampleRateHz),
66 audio(kNumChannels),
67 audio_data(kNumChannels * kSamplesPerChannel, 0.f) {
68 ExpectInitialize();
69 manager_.Initialize();
70 manager_.SetupDigitalGainControl(&gctrl_);
71 for (size_t ch = 0; ch < kNumChannels; ++ch) {
72 audio[ch] = &audio_data[ch * kSamplesPerChannel];
73 }
74 }
75
FirstProcess()76 void FirstProcess() {
77 EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
78 EXPECT_CALL(*agc_, GetRmsErrorDb(_)).WillOnce(Return(false));
79 CallProcess(1);
80 }
81
SetVolumeAndProcess(int volume)82 void SetVolumeAndProcess(int volume) {
83 manager_.set_stream_analog_level(volume);
84 FirstProcess();
85 }
86
ExpectCheckVolumeAndReset(int volume)87 void ExpectCheckVolumeAndReset(int volume) {
88 manager_.set_stream_analog_level(volume);
89 EXPECT_CALL(*agc_, Reset());
90 }
91
ExpectInitialize()92 void ExpectInitialize() {
93 EXPECT_CALL(gctrl_, set_mode(GainControl::kFixedDigital));
94 EXPECT_CALL(gctrl_, set_target_level_dbfs(2));
95 EXPECT_CALL(gctrl_, set_compression_gain_db(7));
96 EXPECT_CALL(gctrl_, enable_limiter(true));
97 }
98
CallProcess(int num_calls)99 void CallProcess(int num_calls) {
100 for (int i = 0; i < num_calls; ++i) {
101 EXPECT_CALL(*agc_, Process(_, _, _)).WillOnce(Return());
102 manager_.Process(nullptr);
103 absl::optional<int> new_digital_gain =
104 manager_.GetDigitalComressionGain();
105 if (new_digital_gain) {
106 gctrl_.set_compression_gain_db(*new_digital_gain);
107 }
108 }
109 }
110
CallPreProc(int num_calls,float clipped_ratio)111 void CallPreProc(int num_calls, float clipped_ratio) {
112 RTC_DCHECK_GE(1.f, clipped_ratio);
113 const int num_clipped = kSamplesPerChannel * clipped_ratio;
114 std::fill(audio_data.begin(), audio_data.end(), 0.f);
115 for (size_t ch = 0; ch < kNumChannels; ++ch) {
116 for (int k = 0; k < num_clipped; ++k) {
117 audio[ch][k] = 32767.f;
118 }
119 }
120
121 for (int i = 0; i < num_calls; ++i) {
122 manager_.AnalyzePreProcess(audio.data(), kSamplesPerChannel);
123 }
124 }
125
126 MockAgc* agc_;
127 MockGainControl gctrl_;
128 AgcManagerDirect manager_;
129 std::vector<float*> audio;
130 std::vector<float> audio_data;
131 };
132
TEST_F(AgcManagerDirectTest,StartupMinVolumeConfigurationIsRespected)133 TEST_F(AgcManagerDirectTest, StartupMinVolumeConfigurationIsRespected) {
134 FirstProcess();
135 EXPECT_EQ(kInitialVolume, manager_.stream_analog_level());
136 }
137
TEST_F(AgcManagerDirectTest,MicVolumeResponseToRmsError)138 TEST_F(AgcManagerDirectTest, MicVolumeResponseToRmsError) {
139 FirstProcess();
140
141 // Compressor default; no residual error.
142 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
143 .WillOnce(DoAll(SetArgPointee<0>(5), Return(true)));
144 CallProcess(1);
145
146 // Inside the compressor's window; no change of volume.
147 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
148 .WillOnce(DoAll(SetArgPointee<0>(10), Return(true)));
149 CallProcess(1);
150
151 // Above the compressor's window; volume should be increased.
152 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
153 .WillOnce(DoAll(SetArgPointee<0>(11), Return(true)));
154 CallProcess(1);
155 EXPECT_EQ(130, manager_.stream_analog_level());
156
157 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
158 .WillOnce(DoAll(SetArgPointee<0>(20), Return(true)));
159 CallProcess(1);
160 EXPECT_EQ(168, manager_.stream_analog_level());
161
162 // Inside the compressor's window; no change of volume.
163 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
164 .WillOnce(DoAll(SetArgPointee<0>(5), Return(true)));
165 CallProcess(1);
166 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
167 .WillOnce(DoAll(SetArgPointee<0>(0), Return(true)));
168 CallProcess(1);
169
170 // Below the compressor's window; volume should be decreased.
171 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
172 .WillOnce(DoAll(SetArgPointee<0>(-1), Return(true)));
173 CallProcess(1);
174 EXPECT_EQ(167, manager_.stream_analog_level());
175
176 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
177 .WillOnce(DoAll(SetArgPointee<0>(-1), Return(true)));
178 CallProcess(1);
179 EXPECT_EQ(163, manager_.stream_analog_level());
180
181 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
182 .WillOnce(DoAll(SetArgPointee<0>(-9), Return(true)));
183 CallProcess(1);
184 EXPECT_EQ(129, manager_.stream_analog_level());
185 }
186
TEST_F(AgcManagerDirectTest,MicVolumeIsLimited)187 TEST_F(AgcManagerDirectTest, MicVolumeIsLimited) {
188 FirstProcess();
189
190 // Maximum upwards change is limited.
191 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
192 .WillOnce(DoAll(SetArgPointee<0>(30), Return(true)));
193 CallProcess(1);
194 EXPECT_EQ(183, manager_.stream_analog_level());
195
196 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
197 .WillOnce(DoAll(SetArgPointee<0>(30), Return(true)));
198 CallProcess(1);
199 EXPECT_EQ(243, manager_.stream_analog_level());
200
201 // Won't go higher than the maximum.
202 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
203 .WillOnce(DoAll(SetArgPointee<0>(30), Return(true)));
204 CallProcess(1);
205 EXPECT_EQ(255, manager_.stream_analog_level());
206
207 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
208 .WillOnce(DoAll(SetArgPointee<0>(-1), Return(true)));
209 CallProcess(1);
210 EXPECT_EQ(254, manager_.stream_analog_level());
211
212 // Maximum downwards change is limited.
213 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
214 .WillOnce(DoAll(SetArgPointee<0>(-40), Return(true)));
215 CallProcess(1);
216 EXPECT_EQ(194, manager_.stream_analog_level());
217
218 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
219 .WillOnce(DoAll(SetArgPointee<0>(-40), Return(true)));
220 CallProcess(1);
221 EXPECT_EQ(137, manager_.stream_analog_level());
222
223 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
224 .WillOnce(DoAll(SetArgPointee<0>(-40), Return(true)));
225 CallProcess(1);
226 EXPECT_EQ(88, manager_.stream_analog_level());
227
228 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
229 .WillOnce(DoAll(SetArgPointee<0>(-40), Return(true)));
230 CallProcess(1);
231 EXPECT_EQ(54, manager_.stream_analog_level());
232
233 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
234 .WillOnce(DoAll(SetArgPointee<0>(-40), Return(true)));
235 CallProcess(1);
236 EXPECT_EQ(33, manager_.stream_analog_level());
237
238 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
239 .WillOnce(DoAll(SetArgPointee<0>(-40), Return(true)));
240 CallProcess(1);
241 EXPECT_EQ(18, manager_.stream_analog_level());
242
243 // Won't go lower than the minimum.
244 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
245 .WillOnce(DoAll(SetArgPointee<0>(-40), Return(true)));
246 CallProcess(1);
247 EXPECT_EQ(12, manager_.stream_analog_level());
248 }
249
TEST_F(AgcManagerDirectTest,CompressorStepsTowardsTarget)250 TEST_F(AgcManagerDirectTest, CompressorStepsTowardsTarget) {
251 FirstProcess();
252
253 // Compressor default; no call to set_compression_gain_db.
254 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
255 .WillOnce(DoAll(SetArgPointee<0>(5), Return(true)))
256 .WillRepeatedly(Return(false));
257 EXPECT_CALL(gctrl_, set_compression_gain_db(_)).Times(0);
258 CallProcess(20);
259
260 // Moves slowly upwards.
261 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
262 .WillOnce(DoAll(SetArgPointee<0>(9), Return(true)))
263 .WillRepeatedly(Return(false));
264 EXPECT_CALL(gctrl_, set_compression_gain_db(_)).Times(0);
265 CallProcess(19);
266 EXPECT_CALL(gctrl_, set_compression_gain_db(8)).WillOnce(Return(0));
267 CallProcess(1);
268
269 EXPECT_CALL(gctrl_, set_compression_gain_db(_)).Times(0);
270 CallProcess(19);
271 EXPECT_CALL(gctrl_, set_compression_gain_db(9)).WillOnce(Return(0));
272 CallProcess(1);
273
274 EXPECT_CALL(gctrl_, set_compression_gain_db(_)).Times(0);
275 CallProcess(20);
276
277 // Moves slowly downward, then reverses before reaching the original target.
278 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
279 .WillOnce(DoAll(SetArgPointee<0>(5), Return(true)))
280 .WillRepeatedly(Return(false));
281 EXPECT_CALL(gctrl_, set_compression_gain_db(_)).Times(0);
282 CallProcess(19);
283 EXPECT_CALL(gctrl_, set_compression_gain_db(8)).WillOnce(Return(0));
284 CallProcess(1);
285
286 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
287 .WillOnce(DoAll(SetArgPointee<0>(9), Return(true)))
288 .WillRepeatedly(Return(false));
289 EXPECT_CALL(gctrl_, set_compression_gain_db(_)).Times(0);
290 CallProcess(19);
291 EXPECT_CALL(gctrl_, set_compression_gain_db(9)).WillOnce(Return(0));
292 CallProcess(1);
293
294 EXPECT_CALL(gctrl_, set_compression_gain_db(_)).Times(0);
295 CallProcess(20);
296 }
297
TEST_F(AgcManagerDirectTest,CompressorErrorIsDeemphasized)298 TEST_F(AgcManagerDirectTest, CompressorErrorIsDeemphasized) {
299 FirstProcess();
300
301 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
302 .WillOnce(DoAll(SetArgPointee<0>(10), Return(true)))
303 .WillRepeatedly(Return(false));
304 CallProcess(19);
305 EXPECT_CALL(gctrl_, set_compression_gain_db(8)).WillOnce(Return(0));
306 CallProcess(20);
307 EXPECT_CALL(gctrl_, set_compression_gain_db(9)).WillOnce(Return(0));
308 CallProcess(1);
309 EXPECT_CALL(gctrl_, set_compression_gain_db(_)).Times(0);
310 CallProcess(20);
311
312 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
313 .WillOnce(DoAll(SetArgPointee<0>(0), Return(true)))
314 .WillRepeatedly(Return(false));
315 CallProcess(19);
316 EXPECT_CALL(gctrl_, set_compression_gain_db(8)).WillOnce(Return(0));
317 CallProcess(20);
318 EXPECT_CALL(gctrl_, set_compression_gain_db(7)).WillOnce(Return(0));
319 CallProcess(20);
320 EXPECT_CALL(gctrl_, set_compression_gain_db(6)).WillOnce(Return(0));
321 CallProcess(1);
322 EXPECT_CALL(gctrl_, set_compression_gain_db(_)).Times(0);
323 CallProcess(20);
324 }
325
TEST_F(AgcManagerDirectTest,CompressorReachesMaximum)326 TEST_F(AgcManagerDirectTest, CompressorReachesMaximum) {
327 FirstProcess();
328
329 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
330 .WillOnce(DoAll(SetArgPointee<0>(10), Return(true)))
331 .WillOnce(DoAll(SetArgPointee<0>(10), Return(true)))
332 .WillOnce(DoAll(SetArgPointee<0>(10), Return(true)))
333 .WillOnce(DoAll(SetArgPointee<0>(10), Return(true)))
334 .WillRepeatedly(Return(false));
335 CallProcess(19);
336 EXPECT_CALL(gctrl_, set_compression_gain_db(8)).WillOnce(Return(0));
337 CallProcess(20);
338 EXPECT_CALL(gctrl_, set_compression_gain_db(9)).WillOnce(Return(0));
339 CallProcess(20);
340 EXPECT_CALL(gctrl_, set_compression_gain_db(10)).WillOnce(Return(0));
341 CallProcess(20);
342 EXPECT_CALL(gctrl_, set_compression_gain_db(11)).WillOnce(Return(0));
343 CallProcess(20);
344 EXPECT_CALL(gctrl_, set_compression_gain_db(12)).WillOnce(Return(0));
345 CallProcess(1);
346 }
347
TEST_F(AgcManagerDirectTest,CompressorReachesMinimum)348 TEST_F(AgcManagerDirectTest, CompressorReachesMinimum) {
349 FirstProcess();
350
351 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
352 .WillOnce(DoAll(SetArgPointee<0>(0), Return(true)))
353 .WillOnce(DoAll(SetArgPointee<0>(0), Return(true)))
354 .WillOnce(DoAll(SetArgPointee<0>(0), Return(true)))
355 .WillOnce(DoAll(SetArgPointee<0>(0), Return(true)))
356 .WillRepeatedly(Return(false));
357 CallProcess(19);
358 EXPECT_CALL(gctrl_, set_compression_gain_db(6)).WillOnce(Return(0));
359 CallProcess(20);
360 EXPECT_CALL(gctrl_, set_compression_gain_db(5)).WillOnce(Return(0));
361 CallProcess(20);
362 EXPECT_CALL(gctrl_, set_compression_gain_db(4)).WillOnce(Return(0));
363 CallProcess(20);
364 EXPECT_CALL(gctrl_, set_compression_gain_db(3)).WillOnce(Return(0));
365 CallProcess(20);
366 EXPECT_CALL(gctrl_, set_compression_gain_db(2)).WillOnce(Return(0));
367 CallProcess(1);
368 }
369
TEST_F(AgcManagerDirectTest,NoActionWhileMuted)370 TEST_F(AgcManagerDirectTest, NoActionWhileMuted) {
371 manager_.SetCaptureMuted(true);
372 manager_.Process(nullptr);
373 absl::optional<int> new_digital_gain = manager_.GetDigitalComressionGain();
374 if (new_digital_gain) {
375 gctrl_.set_compression_gain_db(*new_digital_gain);
376 }
377 }
378
TEST_F(AgcManagerDirectTest,UnmutingChecksVolumeWithoutRaising)379 TEST_F(AgcManagerDirectTest, UnmutingChecksVolumeWithoutRaising) {
380 FirstProcess();
381
382 manager_.SetCaptureMuted(true);
383 manager_.SetCaptureMuted(false);
384 ExpectCheckVolumeAndReset(127);
385 // SetMicVolume should not be called.
386 EXPECT_CALL(*agc_, GetRmsErrorDb(_)).WillOnce(Return(false));
387 CallProcess(1);
388 EXPECT_EQ(127, manager_.stream_analog_level());
389 }
390
TEST_F(AgcManagerDirectTest,UnmutingRaisesTooLowVolume)391 TEST_F(AgcManagerDirectTest, UnmutingRaisesTooLowVolume) {
392 FirstProcess();
393
394 manager_.SetCaptureMuted(true);
395 manager_.SetCaptureMuted(false);
396 ExpectCheckVolumeAndReset(11);
397 EXPECT_CALL(*agc_, GetRmsErrorDb(_)).WillOnce(Return(false));
398 CallProcess(1);
399 EXPECT_EQ(12, manager_.stream_analog_level());
400 }
401
TEST_F(AgcManagerDirectTest,ManualLevelChangeResultsInNoSetMicCall)402 TEST_F(AgcManagerDirectTest, ManualLevelChangeResultsInNoSetMicCall) {
403 FirstProcess();
404
405 // Change outside of compressor's range, which would normally trigger a call
406 // to SetMicVolume.
407 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
408 .WillOnce(DoAll(SetArgPointee<0>(11), Return(true)));
409
410 // When the analog volume changes, the gain controller is reset.
411 EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
412
413 // GetMicVolume returns a value outside of the quantization slack, indicating
414 // a manual volume change.
415 ASSERT_NE(manager_.stream_analog_level(), 154);
416 manager_.set_stream_analog_level(154);
417 CallProcess(1);
418 EXPECT_EQ(154, manager_.stream_analog_level());
419
420 // Do the same thing, except downwards now.
421 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
422 .WillOnce(DoAll(SetArgPointee<0>(-1), Return(true)));
423 manager_.set_stream_analog_level(100);
424 EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
425 CallProcess(1);
426 EXPECT_EQ(100, manager_.stream_analog_level());
427
428 // And finally verify the AGC continues working without a manual change.
429 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
430 .WillOnce(DoAll(SetArgPointee<0>(-1), Return(true)));
431 CallProcess(1);
432 EXPECT_EQ(99, manager_.stream_analog_level());
433 }
434
TEST_F(AgcManagerDirectTest,RecoveryAfterManualLevelChangeFromMax)435 TEST_F(AgcManagerDirectTest, RecoveryAfterManualLevelChangeFromMax) {
436 FirstProcess();
437
438 // Force the mic up to max volume. Takes a few steps due to the residual
439 // gain limitation.
440 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
441 .WillRepeatedly(DoAll(SetArgPointee<0>(30), Return(true)));
442 CallProcess(1);
443 EXPECT_EQ(183, manager_.stream_analog_level());
444 CallProcess(1);
445 EXPECT_EQ(243, manager_.stream_analog_level());
446 CallProcess(1);
447 EXPECT_EQ(255, manager_.stream_analog_level());
448
449 // Manual change does not result in SetMicVolume call.
450 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
451 .WillOnce(DoAll(SetArgPointee<0>(-1), Return(true)));
452 manager_.set_stream_analog_level(50);
453 EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
454 CallProcess(1);
455 EXPECT_EQ(50, manager_.stream_analog_level());
456
457 // Continues working as usual afterwards.
458 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
459 .WillOnce(DoAll(SetArgPointee<0>(20), Return(true)));
460 CallProcess(1);
461 EXPECT_EQ(69, manager_.stream_analog_level());
462 }
463
TEST_F(AgcManagerDirectTest,RecoveryAfterManualLevelChangeBelowMin)464 TEST_F(AgcManagerDirectTest, RecoveryAfterManualLevelChangeBelowMin) {
465 FirstProcess();
466
467 // Manual change below min.
468 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
469 .WillOnce(DoAll(SetArgPointee<0>(-1), Return(true)));
470 // Don't set to zero, which will cause AGC to take no action.
471 manager_.set_stream_analog_level(1);
472 EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
473 CallProcess(1);
474 EXPECT_EQ(1, manager_.stream_analog_level());
475
476 // Continues working as usual afterwards.
477 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
478 .WillOnce(DoAll(SetArgPointee<0>(11), Return(true)));
479 CallProcess(1);
480 EXPECT_EQ(2, manager_.stream_analog_level());
481
482 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
483 .WillOnce(DoAll(SetArgPointee<0>(30), Return(true)));
484 CallProcess(1);
485 EXPECT_EQ(11, manager_.stream_analog_level());
486
487 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
488 .WillOnce(DoAll(SetArgPointee<0>(20), Return(true)));
489 CallProcess(1);
490 EXPECT_EQ(18, manager_.stream_analog_level());
491 }
492
TEST_F(AgcManagerDirectTest,NoClippingHasNoImpact)493 TEST_F(AgcManagerDirectTest, NoClippingHasNoImpact) {
494 FirstProcess();
495
496 CallPreProc(100, 0);
497 EXPECT_EQ(128, manager_.stream_analog_level());
498 }
499
TEST_F(AgcManagerDirectTest,ClippingUnderThresholdHasNoImpact)500 TEST_F(AgcManagerDirectTest, ClippingUnderThresholdHasNoImpact) {
501 FirstProcess();
502
503 CallPreProc(1, 0.099);
504 EXPECT_EQ(128, manager_.stream_analog_level());
505 }
506
TEST_F(AgcManagerDirectTest,ClippingLowersVolume)507 TEST_F(AgcManagerDirectTest, ClippingLowersVolume) {
508 SetVolumeAndProcess(255);
509
510 EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
511 CallPreProc(1, 0.2);
512 EXPECT_EQ(240, manager_.stream_analog_level());
513 }
514
TEST_F(AgcManagerDirectTest,WaitingPeriodBetweenClippingChecks)515 TEST_F(AgcManagerDirectTest, WaitingPeriodBetweenClippingChecks) {
516 SetVolumeAndProcess(255);
517
518 EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
519 CallPreProc(1, kAboveClippedThreshold);
520 EXPECT_EQ(240, manager_.stream_analog_level());
521
522 EXPECT_CALL(*agc_, Reset()).Times(0);
523 CallPreProc(300, kAboveClippedThreshold);
524 EXPECT_EQ(240, manager_.stream_analog_level());
525
526 EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
527 CallPreProc(1, kAboveClippedThreshold);
528 EXPECT_EQ(225, manager_.stream_analog_level());
529 }
530
TEST_F(AgcManagerDirectTest,ClippingLoweringIsLimited)531 TEST_F(AgcManagerDirectTest, ClippingLoweringIsLimited) {
532 SetVolumeAndProcess(180);
533
534 EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
535 CallPreProc(1, kAboveClippedThreshold);
536 EXPECT_EQ(kClippedMin, manager_.stream_analog_level());
537
538 EXPECT_CALL(*agc_, Reset()).Times(0);
539 CallPreProc(1000, kAboveClippedThreshold);
540 EXPECT_EQ(kClippedMin, manager_.stream_analog_level());
541 }
542
TEST_F(AgcManagerDirectTest,ClippingMaxIsRespectedWhenEqualToLevel)543 TEST_F(AgcManagerDirectTest, ClippingMaxIsRespectedWhenEqualToLevel) {
544 SetVolumeAndProcess(255);
545
546 EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
547 CallPreProc(1, kAboveClippedThreshold);
548 EXPECT_EQ(240, manager_.stream_analog_level());
549
550 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
551 .WillRepeatedly(DoAll(SetArgPointee<0>(30), Return(true)));
552 CallProcess(10);
553 EXPECT_EQ(240, manager_.stream_analog_level());
554 }
555
TEST_F(AgcManagerDirectTest,ClippingMaxIsRespectedWhenHigherThanLevel)556 TEST_F(AgcManagerDirectTest, ClippingMaxIsRespectedWhenHigherThanLevel) {
557 SetVolumeAndProcess(200);
558
559 EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
560 CallPreProc(1, kAboveClippedThreshold);
561 EXPECT_EQ(185, manager_.stream_analog_level());
562
563 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
564 .WillRepeatedly(DoAll(SetArgPointee<0>(40), Return(true)));
565 CallProcess(1);
566 EXPECT_EQ(240, manager_.stream_analog_level());
567 CallProcess(10);
568 EXPECT_EQ(240, manager_.stream_analog_level());
569 }
570
TEST_F(AgcManagerDirectTest,MaxCompressionIsIncreasedAfterClipping)571 TEST_F(AgcManagerDirectTest, MaxCompressionIsIncreasedAfterClipping) {
572 SetVolumeAndProcess(210);
573
574 EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
575 CallPreProc(1, kAboveClippedThreshold);
576 EXPECT_EQ(195, manager_.stream_analog_level());
577
578 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
579 .WillOnce(DoAll(SetArgPointee<0>(11), Return(true)))
580 .WillOnce(DoAll(SetArgPointee<0>(11), Return(true)))
581 .WillOnce(DoAll(SetArgPointee<0>(11), Return(true)))
582 .WillOnce(DoAll(SetArgPointee<0>(11), Return(true)))
583 .WillOnce(DoAll(SetArgPointee<0>(11), Return(true)))
584 .WillRepeatedly(Return(false));
585 CallProcess(19);
586 EXPECT_CALL(gctrl_, set_compression_gain_db(8)).WillOnce(Return(0));
587 CallProcess(20);
588 EXPECT_CALL(gctrl_, set_compression_gain_db(9)).WillOnce(Return(0));
589 CallProcess(20);
590 EXPECT_CALL(gctrl_, set_compression_gain_db(10)).WillOnce(Return(0));
591 CallProcess(20);
592 EXPECT_CALL(gctrl_, set_compression_gain_db(11)).WillOnce(Return(0));
593 CallProcess(20);
594 EXPECT_CALL(gctrl_, set_compression_gain_db(12)).WillOnce(Return(0));
595 CallProcess(20);
596 EXPECT_CALL(gctrl_, set_compression_gain_db(13)).WillOnce(Return(0));
597 CallProcess(1);
598
599 // Continue clipping until we hit the maximum surplus compression.
600 CallPreProc(300, kAboveClippedThreshold);
601 EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
602 CallPreProc(1, kAboveClippedThreshold);
603 EXPECT_EQ(180, manager_.stream_analog_level());
604
605 CallPreProc(300, kAboveClippedThreshold);
606 EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
607 CallPreProc(1, kAboveClippedThreshold);
608 EXPECT_EQ(kClippedMin, manager_.stream_analog_level());
609
610 // Current level is now at the minimum, but the maximum allowed level still
611 // has more to decrease.
612 CallPreProc(300, kAboveClippedThreshold);
613 CallPreProc(1, kAboveClippedThreshold);
614
615 CallPreProc(300, kAboveClippedThreshold);
616 CallPreProc(1, kAboveClippedThreshold);
617
618 CallPreProc(300, kAboveClippedThreshold);
619 CallPreProc(1, kAboveClippedThreshold);
620
621 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
622 .WillOnce(DoAll(SetArgPointee<0>(16), Return(true)))
623 .WillOnce(DoAll(SetArgPointee<0>(16), Return(true)))
624 .WillOnce(DoAll(SetArgPointee<0>(16), Return(true)))
625 .WillOnce(DoAll(SetArgPointee<0>(16), Return(true)))
626 .WillRepeatedly(Return(false));
627 CallProcess(19);
628 EXPECT_CALL(gctrl_, set_compression_gain_db(14)).WillOnce(Return(0));
629 CallProcess(20);
630 EXPECT_CALL(gctrl_, set_compression_gain_db(15)).WillOnce(Return(0));
631 CallProcess(20);
632 EXPECT_CALL(gctrl_, set_compression_gain_db(16)).WillOnce(Return(0));
633 CallProcess(20);
634 EXPECT_CALL(gctrl_, set_compression_gain_db(17)).WillOnce(Return(0));
635 CallProcess(20);
636 EXPECT_CALL(gctrl_, set_compression_gain_db(18)).WillOnce(Return(0));
637 CallProcess(1);
638 }
639
TEST_F(AgcManagerDirectTest,UserCanRaiseVolumeAfterClipping)640 TEST_F(AgcManagerDirectTest, UserCanRaiseVolumeAfterClipping) {
641 SetVolumeAndProcess(225);
642
643 EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
644 CallPreProc(1, kAboveClippedThreshold);
645 EXPECT_EQ(210, manager_.stream_analog_level());
646
647 // High enough error to trigger a volume check.
648 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
649 .WillOnce(DoAll(SetArgPointee<0>(14), Return(true)));
650 // User changed the volume.
651 manager_.set_stream_analog_level(250);
652 EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
653 CallProcess(1);
654 EXPECT_EQ(250, manager_.stream_analog_level());
655
656 // Move down...
657 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
658 .WillOnce(DoAll(SetArgPointee<0>(-10), Return(true)));
659 CallProcess(1);
660 EXPECT_EQ(210, manager_.stream_analog_level());
661 // And back up to the new max established by the user.
662 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
663 .WillOnce(DoAll(SetArgPointee<0>(40), Return(true)));
664 CallProcess(1);
665 EXPECT_EQ(250, manager_.stream_analog_level());
666 // Will not move above new maximum.
667 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
668 .WillOnce(DoAll(SetArgPointee<0>(30), Return(true)));
669 CallProcess(1);
670 EXPECT_EQ(250, manager_.stream_analog_level());
671 }
672
TEST_F(AgcManagerDirectTest,ClippingDoesNotPullLowVolumeBackUp)673 TEST_F(AgcManagerDirectTest, ClippingDoesNotPullLowVolumeBackUp) {
674 SetVolumeAndProcess(80);
675
676 EXPECT_CALL(*agc_, Reset()).Times(0);
677 int initial_volume = manager_.stream_analog_level();
678 CallPreProc(1, kAboveClippedThreshold);
679 EXPECT_EQ(initial_volume, manager_.stream_analog_level());
680 }
681
TEST_F(AgcManagerDirectTest,TakesNoActionOnZeroMicVolume)682 TEST_F(AgcManagerDirectTest, TakesNoActionOnZeroMicVolume) {
683 FirstProcess();
684
685 EXPECT_CALL(*agc_, GetRmsErrorDb(_))
686 .WillRepeatedly(DoAll(SetArgPointee<0>(30), Return(true)));
687 manager_.set_stream_analog_level(0);
688 CallProcess(10);
689 EXPECT_EQ(0, manager_.stream_analog_level());
690 }
691
TEST(AgcManagerDirectStandaloneTest,DisableDigitalDisablesDigital)692 TEST(AgcManagerDirectStandaloneTest, DisableDigitalDisablesDigital) {
693 auto agc = std::unique_ptr<Agc>(new ::testing::NiceMock<MockAgc>());
694 MockGainControl gctrl;
695 AgcManagerDirect manager(/* num_capture_channels */ 1, kInitialVolume,
696 kClippedMin,
697 /* use agc2 level estimation */ false,
698 /* disable digital adaptive */ true, kSampleRateHz);
699
700 EXPECT_CALL(gctrl, set_mode(GainControl::kFixedDigital));
701 EXPECT_CALL(gctrl, set_target_level_dbfs(0));
702 EXPECT_CALL(gctrl, set_compression_gain_db(0));
703 EXPECT_CALL(gctrl, enable_limiter(false));
704
705 manager.Initialize();
706 manager.SetupDigitalGainControl(&gctrl);
707 }
708
TEST(AgcManagerDirectStandaloneTest,AgcMinMicLevelExperiment)709 TEST(AgcManagerDirectStandaloneTest, AgcMinMicLevelExperiment) {
710 auto agc_man = std::unique_ptr<AgcManagerDirect>(new AgcManagerDirect(
711 /* num_capture_channels */ 1, kInitialVolume, kClippedMin, true, true,
712 kSampleRateHz));
713 EXPECT_EQ(agc_man->channel_agcs_[0]->min_mic_level(), kMinMicLevel);
714 EXPECT_EQ(agc_man->channel_agcs_[0]->startup_min_level(), kInitialVolume);
715 {
716 test::ScopedFieldTrials field_trial(
717 "WebRTC-Audio-AgcMinMicLevelExperiment/Disabled/");
718 agc_man.reset(new AgcManagerDirect(
719 /* num_capture_channels */ 1, kInitialVolume, kClippedMin, true, true,
720 kSampleRateHz));
721 EXPECT_EQ(agc_man->channel_agcs_[0]->min_mic_level(), kMinMicLevel);
722 EXPECT_EQ(agc_man->channel_agcs_[0]->startup_min_level(), kInitialVolume);
723 }
724 {
725 // Valid range of field-trial parameter is [0,255].
726 test::ScopedFieldTrials field_trial(
727 "WebRTC-Audio-AgcMinMicLevelExperiment/Enabled-256/");
728 agc_man.reset(new AgcManagerDirect(
729 /* num_capture_channels */ 1, kInitialVolume, kClippedMin, true, true,
730 kSampleRateHz));
731 EXPECT_EQ(agc_man->channel_agcs_[0]->min_mic_level(), kMinMicLevel);
732 EXPECT_EQ(agc_man->channel_agcs_[0]->startup_min_level(), kInitialVolume);
733 }
734 {
735 test::ScopedFieldTrials field_trial(
736 "WebRTC-Audio-AgcMinMicLevelExperiment/Enabled--1/");
737 agc_man.reset(new AgcManagerDirect(
738 /* num_capture_channels */ 1, kInitialVolume, kClippedMin, true, true,
739 kSampleRateHz));
740 EXPECT_EQ(agc_man->channel_agcs_[0]->min_mic_level(), kMinMicLevel);
741 EXPECT_EQ(agc_man->channel_agcs_[0]->startup_min_level(), kInitialVolume);
742 }
743 {
744 // Verify that a valid experiment changes the minimum microphone level.
745 // The start volume is larger than the min level and should therefore not
746 // be changed.
747 test::ScopedFieldTrials field_trial(
748 "WebRTC-Audio-AgcMinMicLevelExperiment/Enabled-50/");
749 agc_man.reset(new AgcManagerDirect(
750 /* num_capture_channels */ 1, kInitialVolume, kClippedMin, true, true,
751 kSampleRateHz));
752 EXPECT_EQ(agc_man->channel_agcs_[0]->min_mic_level(), 50);
753 EXPECT_EQ(agc_man->channel_agcs_[0]->startup_min_level(), kInitialVolume);
754 }
755 {
756 // Use experiment to reduce the default minimum microphone level, start at
757 // a lower level and ensure that the startup level is increased to the min
758 // level set by the experiment.
759 test::ScopedFieldTrials field_trial(
760 "WebRTC-Audio-AgcMinMicLevelExperiment/Enabled-50/");
761 agc_man.reset(new AgcManagerDirect(/* num_capture_channels */ 1, 30,
762 kClippedMin, true, true, kSampleRateHz));
763 EXPECT_EQ(agc_man->channel_agcs_[0]->min_mic_level(), 50);
764 EXPECT_EQ(agc_man->channel_agcs_[0]->startup_min_level(), 50);
765 }
766 }
767
768 } // namespace webrtc
769