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