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