blob: c379d2d5b03c66e7ef69ccfd351d627740a2fe61 [file] [log] [blame]
/*
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/tools/agc/agc_manager.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/common_types.h"
#include "webrtc/modules/audio_processing/agc/mock_agc.h"
#include "webrtc/modules/audio_processing/include/mock_audio_processing.h"
#include "webrtc/system_wrappers/interface/trace.h"
#include "webrtc/voice_engine/mock/fake_voe_external_media.h"
#include "webrtc/voice_engine/mock/mock_voe_volume_control.h"
#include "webrtc/test/testsupport/trace_to_stderr.h"
using ::testing::_;
using ::testing::DoAll;
using ::testing::Eq;
using ::testing::Mock;
using ::testing::Return;
using ::testing::SetArgPointee;
using ::testing::SetArgReferee;
namespace webrtc {
namespace {
const int kSampleRateHz = 32000;
const int kNumChannels = 1;
const int kSamplesPerChannel = kSampleRateHz / 100;
const float kAboveClippedThreshold = 0.2f;
} // namespace
class AgcManagerUnitTest : public ::testing::Test {
protected:
AgcManagerUnitTest()
: media_(),
volume_(),
agc_(new MockAgc),
audioproc_(new MockAudioProcessing),
gctrl_(audioproc_->gain_control()),
manager_(&media_, &volume_, agc_, audioproc_) {
EXPECT_CALL(*gctrl_, Enable(true));
ExpectInitialize();
manager_.Enable(true);
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(Return(false));
// TODO(bjornv): Find a better solution that adds an initial volume here
// instead of applying SetVolumeAndProcess(128u) in each test, but at the
// same time can test a too low initial value.
}
void SetInitialVolume(unsigned int volume) {
ExpectInitialize();
manager_.CaptureDeviceChanged();
ExpectCheckVolumeAndReset(volume);
EXPECT_CALL(*agc_, GetRmsErrorDb(_)).WillOnce(Return(false));
PostProcCallback(1);
}
void SetVolumeAndProcess(unsigned int volume) {
// Volume is checked on first process call.
ExpectCheckVolumeAndReset(volume);
PostProcCallback(1);
}
void ExpectCheckVolumeAndReset(unsigned int volume) {
EXPECT_CALL(volume_, GetMicVolume(_))
.WillOnce(DoAll(SetArgReferee<0>(volume), Return(0)));
EXPECT_CALL(*agc_, Reset());
}
void ExpectVolumeChange(unsigned int current_volume,
unsigned int new_volume) {
EXPECT_CALL(volume_, GetMicVolume(_))
.WillOnce(DoAll(SetArgReferee<0>(current_volume), Return(0)));
EXPECT_CALL(volume_, SetMicVolume(Eq(new_volume))).WillOnce(Return(0));
}
void ExpectInitialize() {
EXPECT_CALL(*gctrl_, set_mode(GainControl::kFixedDigital));
EXPECT_CALL(*gctrl_, set_target_level_dbfs(2));
EXPECT_CALL(*gctrl_, set_compression_gain_db(7));
EXPECT_CALL(*gctrl_, enable_limiter(true));
}
void PreProcCallback(int num_calls) {
for (int i = 0; i < num_calls; ++i) {
media_.CallProcess(kRecordingPreprocessing, NULL, kSamplesPerChannel,
kSampleRateHz, kNumChannels);
}
}
void PostProcCallback(int num_calls) {
for (int i = 0; i < num_calls; ++i) {
EXPECT_CALL(*agc_, Process(_, _, _)).WillOnce(Return(0));
EXPECT_CALL(*audioproc_, ProcessStream(_)).WillOnce(Return(0));
media_.CallProcess(kRecordingAllChannelsMixed, NULL, kSamplesPerChannel,
kSampleRateHz, kNumChannels);
}
}
~AgcManagerUnitTest() {
EXPECT_CALL(volume_, Release()).WillOnce(Return(0));
}
FakeVoEExternalMedia media_;
MockVoEVolumeControl volume_;
MockAgc* agc_;
MockAudioProcessing* audioproc_;
MockGainControl* gctrl_;
AgcManager manager_;
test::TraceToStderr trace_to_stderr;
};
TEST_F(AgcManagerUnitTest, MicVolumeResponseToRmsError) {
SetVolumeAndProcess(128u);
// Compressor default; no residual error.
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(DoAll(SetArgPointee<0>(5), Return(true)));
PostProcCallback(1);
// Inside the compressor's window; no change of volume.
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(DoAll(SetArgPointee<0>(10), Return(true)));
PostProcCallback(1);
// Above the compressor's window; volume should be increased.
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(DoAll(SetArgPointee<0>(11), Return(true)));
ExpectVolumeChange(128u, 130u);
PostProcCallback(1);
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(DoAll(SetArgPointee<0>(20), Return(true)));
ExpectVolumeChange(130u, 168u);
PostProcCallback(1);
// Inside the compressor's window; no change of volume.
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(DoAll(SetArgPointee<0>(5), Return(true)));
PostProcCallback(1);
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(DoAll(SetArgPointee<0>(0), Return(true)));
PostProcCallback(1);
// Below the compressor's window; volume should be decreased.
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(DoAll(SetArgPointee<0>(-1), Return(true)));
ExpectVolumeChange(168u, 167u);
PostProcCallback(1);
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(DoAll(SetArgPointee<0>(-1), Return(true)));
ExpectVolumeChange(167u, 163u);
PostProcCallback(1);
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(DoAll(SetArgPointee<0>(-9), Return(true)));
ExpectVolumeChange(163u, 129u);
PostProcCallback(1);
}
TEST_F(AgcManagerUnitTest, MicVolumeIsLimited) {
SetVolumeAndProcess(128u);
// Maximum upwards change is limited.
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(DoAll(SetArgPointee<0>(30), Return(true)));
ExpectVolumeChange(128u, 183u);
PostProcCallback(1);
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(DoAll(SetArgPointee<0>(30), Return(true)));
ExpectVolumeChange(183u, 243u);
PostProcCallback(1);
// Won't go higher than the maximum.
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(DoAll(SetArgPointee<0>(30), Return(true)));
ExpectVolumeChange(243u, 255u);
PostProcCallback(1);
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(DoAll(SetArgPointee<0>(-1), Return(true)));
ExpectVolumeChange(255u, 254u);
PostProcCallback(1);
// Maximum downwards change is limited.
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(DoAll(SetArgPointee<0>(-40), Return(true)));
ExpectVolumeChange(254u, 194u);
PostProcCallback(1);
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(DoAll(SetArgPointee<0>(-40), Return(true)));
ExpectVolumeChange(194u, 137u);
PostProcCallback(1);
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(DoAll(SetArgPointee<0>(-40), Return(true)));
ExpectVolumeChange(137u, 88u);
PostProcCallback(1);
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(DoAll(SetArgPointee<0>(-40), Return(true)));
ExpectVolumeChange(88u, 54u);
PostProcCallback(1);
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(DoAll(SetArgPointee<0>(-40), Return(true)));
ExpectVolumeChange(54u, 33u);
PostProcCallback(1);
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(DoAll(SetArgPointee<0>(-40), Return(true)));
ExpectVolumeChange(33u, 18u);
PostProcCallback(1);
// Won't go lower than the minimum.
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(DoAll(SetArgPointee<0>(-40), Return(true)));
ExpectVolumeChange(18u, 12u);
PostProcCallback(1);
}
TEST_F(AgcManagerUnitTest, CompressorStepsTowardsTarget) {
SetVolumeAndProcess(128u);
// Compressor default; no call to set_compression_gain_db.
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(DoAll(SetArgPointee<0>(5), Return(true)))
.WillRepeatedly(Return(false));
EXPECT_CALL(*gctrl_, set_compression_gain_db(_)).Times(0);
PostProcCallback(20);
// Moves slowly upwards.
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(DoAll(SetArgPointee<0>(9), Return(true)))
.WillRepeatedly(Return(false));
EXPECT_CALL(*gctrl_, set_compression_gain_db(_)).Times(0);
PostProcCallback(19);
EXPECT_CALL(*gctrl_, set_compression_gain_db(8)).WillOnce(Return(0));
PostProcCallback(1);
EXPECT_CALL(*gctrl_, set_compression_gain_db(_)).Times(0);
PostProcCallback(19);
EXPECT_CALL(*gctrl_, set_compression_gain_db(9)).WillOnce(Return(0));
PostProcCallback(1);
EXPECT_CALL(*gctrl_, set_compression_gain_db(_)).Times(0);
PostProcCallback(20);
// Moves slowly downward, then reverses before reaching the original target.
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(DoAll(SetArgPointee<0>(5), Return(true)))
.WillRepeatedly(Return(false));
EXPECT_CALL(*gctrl_, set_compression_gain_db(_)).Times(0);
PostProcCallback(19);
EXPECT_CALL(*gctrl_, set_compression_gain_db(8)).WillOnce(Return(0));
PostProcCallback(1);
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(DoAll(SetArgPointee<0>(9), Return(true)))
.WillRepeatedly(Return(false));
EXPECT_CALL(*gctrl_, set_compression_gain_db(_)).Times(0);
PostProcCallback(19);
EXPECT_CALL(*gctrl_, set_compression_gain_db(9)).WillOnce(Return(0));
PostProcCallback(1);
EXPECT_CALL(*gctrl_, set_compression_gain_db(_)).Times(0);
PostProcCallback(20);
}
TEST_F(AgcManagerUnitTest, CompressorErrorIsDeemphasized) {
SetVolumeAndProcess(128u);
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(DoAll(SetArgPointee<0>(10), Return(true)))
.WillRepeatedly(Return(false));
PostProcCallback(19);
EXPECT_CALL(*gctrl_, set_compression_gain_db(8)).WillOnce(Return(0));
PostProcCallback(20);
EXPECT_CALL(*gctrl_, set_compression_gain_db(9)).WillOnce(Return(0));
PostProcCallback(1);
EXPECT_CALL(*gctrl_, set_compression_gain_db(_)).Times(0);
PostProcCallback(20);
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(DoAll(SetArgPointee<0>(0), Return(true)))
.WillRepeatedly(Return(false));
PostProcCallback(19);
EXPECT_CALL(*gctrl_, set_compression_gain_db(8)).WillOnce(Return(0));
PostProcCallback(20);
EXPECT_CALL(*gctrl_, set_compression_gain_db(7)).WillOnce(Return(0));
PostProcCallback(20);
EXPECT_CALL(*gctrl_, set_compression_gain_db(6)).WillOnce(Return(0));
PostProcCallback(1);
EXPECT_CALL(*gctrl_, set_compression_gain_db(_)).Times(0);
PostProcCallback(20);
}
TEST_F(AgcManagerUnitTest, CompressorReachesMaximum) {
SetVolumeAndProcess(128u);
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(DoAll(SetArgPointee<0>(10), Return(true)))
.WillOnce(DoAll(SetArgPointee<0>(10), Return(true)))
.WillOnce(DoAll(SetArgPointee<0>(10), Return(true)))
.WillOnce(DoAll(SetArgPointee<0>(10), Return(true)))
.WillRepeatedly(Return(false));
PostProcCallback(19);
EXPECT_CALL(*gctrl_, set_compression_gain_db(8)).WillOnce(Return(0));
PostProcCallback(20);
EXPECT_CALL(*gctrl_, set_compression_gain_db(9)).WillOnce(Return(0));
PostProcCallback(20);
EXPECT_CALL(*gctrl_, set_compression_gain_db(10)).WillOnce(Return(0));
PostProcCallback(20);
EXPECT_CALL(*gctrl_, set_compression_gain_db(11)).WillOnce(Return(0));
PostProcCallback(20);
EXPECT_CALL(*gctrl_, set_compression_gain_db(12)).WillOnce(Return(0));
PostProcCallback(1);
}
TEST_F(AgcManagerUnitTest, CompressorReachesMinimum) {
SetVolumeAndProcess(128u);
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(DoAll(SetArgPointee<0>(0), Return(true)))
.WillOnce(DoAll(SetArgPointee<0>(0), Return(true)))
.WillOnce(DoAll(SetArgPointee<0>(0), Return(true)))
.WillOnce(DoAll(SetArgPointee<0>(0), Return(true)))
.WillRepeatedly(Return(false));
PostProcCallback(19);
EXPECT_CALL(*gctrl_, set_compression_gain_db(6)).WillOnce(Return(0));
PostProcCallback(20);
EXPECT_CALL(*gctrl_, set_compression_gain_db(5)).WillOnce(Return(0));
PostProcCallback(20);
EXPECT_CALL(*gctrl_, set_compression_gain_db(4)).WillOnce(Return(0));
PostProcCallback(20);
EXPECT_CALL(*gctrl_, set_compression_gain_db(3)).WillOnce(Return(0));
PostProcCallback(20);
EXPECT_CALL(*gctrl_, set_compression_gain_db(2)).WillOnce(Return(0));
PostProcCallback(1);
}
TEST_F(AgcManagerUnitTest, NoActionWhileMuted) {
SetVolumeAndProcess(128u);
manager_.SetCaptureMuted(true);
media_.CallProcess(kRecordingAllChannelsMixed, NULL, kSamplesPerChannel,
kSampleRateHz, kNumChannels);
}
TEST_F(AgcManagerUnitTest, UnmutingChecksVolumeWithoutRaising) {
SetVolumeAndProcess(128u);
manager_.SetCaptureMuted(true);
manager_.SetCaptureMuted(false);
ExpectCheckVolumeAndReset(127u);
// SetMicVolume should not be called.
EXPECT_CALL(volume_, SetMicVolume(_)).Times(0);
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(Return(false));
PostProcCallback(1);
}
TEST_F(AgcManagerUnitTest, UnmutingRaisesTooLowVolume) {
SetVolumeAndProcess(128u);
manager_.SetCaptureMuted(true);
manager_.SetCaptureMuted(false);
ExpectCheckVolumeAndReset(11u);
EXPECT_CALL(volume_, SetMicVolume(Eq(12u))).WillOnce(Return(0));
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(Return(false));
PostProcCallback(1);
}
TEST_F(AgcManagerUnitTest, ChangingDevicesChecksVolume) {
SetVolumeAndProcess(128u);
ExpectInitialize();
manager_.CaptureDeviceChanged();
ExpectCheckVolumeAndReset(128u);
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(Return(false));
PostProcCallback(1);
}
TEST_F(AgcManagerUnitTest, LowInitialVolumeIsRaised) {
ExpectCheckVolumeAndReset(11u);
#if defined(WEBRTC_CHROMIUM_BUILD)
// Should set MicVolume to kMinInitMicLevel = 85 if built with Chromium.
EXPECT_CALL(volume_, SetMicVolume(Eq(85u))).WillOnce(Return(0));
#else
// Otherwise it will raise to the kMinMicLevel = 12.
EXPECT_CALL(volume_, SetMicVolume(Eq(12u))).WillOnce(Return(0));
#endif
PostProcCallback(1);
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(Return(false));
PostProcCallback(1);
}
TEST_F(AgcManagerUnitTest, ManualLevelChangeResultsInNoSetMicCall) {
SetVolumeAndProcess(128u);
// Change outside of compressor's range, which would normally trigger a call
// to SetMicVolume.
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(DoAll(SetArgPointee<0>(11), Return(true)));
// GetMicVolume returns a value outside of the quantization slack, indicating
// a manual volume change.
EXPECT_CALL(volume_, GetMicVolume(_))
.WillOnce(DoAll(SetArgReferee<0>(154u), Return(0)));
// SetMicVolume should not be called.
EXPECT_CALL(volume_, SetMicVolume(_)).Times(0);
EXPECT_CALL(*agc_, Reset()).Times(1);
PostProcCallback(1);
// Do the same thing, except downwards now.
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(DoAll(SetArgPointee<0>(-1), Return(true)));
EXPECT_CALL(volume_, GetMicVolume(_))
.WillOnce(DoAll(SetArgReferee<0>(100u), Return(0)));
EXPECT_CALL(volume_, SetMicVolume(_)).Times(0);
EXPECT_CALL(*agc_, Reset()).Times(1);
PostProcCallback(1);
// And finally verify the AGC continues working without a manual change.
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(DoAll(SetArgPointee<0>(-1), Return(true)));
ExpectVolumeChange(100u, 99u);
PostProcCallback(1);
}
TEST_F(AgcManagerUnitTest, RecoveryAfterManualLevelChangeFromMax) {
SetVolumeAndProcess(128u);
// Force the mic up to max volume. Takes a few steps due to the residual
// gain limitation.
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillRepeatedly(DoAll(SetArgPointee<0>(30), Return(true)));
ExpectVolumeChange(128u, 183u);
PostProcCallback(1);
ExpectVolumeChange(183u, 243u);
PostProcCallback(1);
ExpectVolumeChange(243u, 255u);
PostProcCallback(1);
// Manual change does not result in SetMicVolume call.
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(DoAll(SetArgPointee<0>(-1), Return(true)));
EXPECT_CALL(volume_, GetMicVolume(_))
.WillOnce(DoAll(SetArgReferee<0>(50u), Return(0)));
EXPECT_CALL(volume_, SetMicVolume(_)).Times(0);
EXPECT_CALL(*agc_, Reset()).Times(1);
PostProcCallback(1);
// Continues working as usual afterwards.
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(DoAll(SetArgPointee<0>(20), Return(true)));
ExpectVolumeChange(50u, 69u);
PostProcCallback(1);
}
TEST_F(AgcManagerUnitTest, RecoveryAfterManualLevelChangeBelowMin) {
SetVolumeAndProcess(128u);
// Manual change below min.
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(DoAll(SetArgPointee<0>(-1), Return(true)));
// Don't set to zero, which will cause AGC to take no action.
EXPECT_CALL(volume_, GetMicVolume(_))
.WillOnce(DoAll(SetArgReferee<0>(1u), Return(0)));
EXPECT_CALL(volume_, SetMicVolume(_)).Times(0);
EXPECT_CALL(*agc_, Reset()).Times(1);
PostProcCallback(1);
// Continues working as usual afterwards.
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(DoAll(SetArgPointee<0>(11), Return(true)));
ExpectVolumeChange(1u, 2u);
PostProcCallback(1);
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(DoAll(SetArgPointee<0>(30), Return(true)));
ExpectVolumeChange(2u, 11u);
PostProcCallback(1);
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(DoAll(SetArgPointee<0>(20), Return(true)));
ExpectVolumeChange(11u, 18u);
PostProcCallback(1);
}
TEST_F(AgcManagerUnitTest, NoClippingHasNoImpact) {
SetVolumeAndProcess(128u);
EXPECT_CALL(volume_, GetMicVolume(_)).Times(0);
EXPECT_CALL(volume_, SetMicVolume(_)).Times(0);
EXPECT_CALL(*agc_, Reset()).Times(0);
EXPECT_CALL(*agc_, AnalyzePreproc(_, _)).WillRepeatedly(Return(0));
PreProcCallback(100);
}
TEST_F(AgcManagerUnitTest, ClippingUnderThresholdHasNoImpact) {
SetVolumeAndProcess(128u);
EXPECT_CALL(volume_, GetMicVolume(_)).Times(0);
EXPECT_CALL(volume_, SetMicVolume(_)).Times(0);
EXPECT_CALL(*agc_, Reset()).Times(0);
EXPECT_CALL(*agc_, AnalyzePreproc(_, _)).WillOnce(Return(0.099));
PreProcCallback(1);
}
TEST_F(AgcManagerUnitTest, ClippingLowersVolume) {
SetVolumeAndProcess(128u);
SetInitialVolume(255u);
EXPECT_CALL(*agc_, AnalyzePreproc(_, _)).WillOnce(Return(0.101));
EXPECT_CALL(*agc_, Reset()).Times(1);
ExpectVolumeChange(255u, 240u);
PreProcCallback(1);
}
TEST_F(AgcManagerUnitTest, WaitingPeriodBetweenClippingChecks) {
SetVolumeAndProcess(128u);
SetInitialVolume(255u);
EXPECT_CALL(*agc_, AnalyzePreproc(_, _))
.WillOnce(Return(kAboveClippedThreshold));
EXPECT_CALL(*agc_, Reset()).Times(1);
ExpectVolumeChange(255u, 240u);
PreProcCallback(1);
EXPECT_CALL(*agc_, AnalyzePreproc(_, _))
.WillRepeatedly(Return(kAboveClippedThreshold));
EXPECT_CALL(volume_, GetMicVolume(_)).Times(0);
EXPECT_CALL(volume_, SetMicVolume(_)).Times(0);
EXPECT_CALL(*agc_, Reset()).Times(0);
PreProcCallback(300);
EXPECT_CALL(*agc_, AnalyzePreproc(_, _))
.WillOnce(Return(kAboveClippedThreshold));
EXPECT_CALL(*agc_, Reset()).Times(1);
ExpectVolumeChange(240u, 225u);
PreProcCallback(1);
}
TEST_F(AgcManagerUnitTest, ClippingLoweringIsLimited) {
SetVolumeAndProcess(128u);
SetInitialVolume(180u);
EXPECT_CALL(*agc_, AnalyzePreproc(_, _))
.WillOnce(Return(kAboveClippedThreshold));
EXPECT_CALL(*agc_, Reset()).Times(1);
ExpectVolumeChange(180u, 170u);
PreProcCallback(1);
EXPECT_CALL(*agc_, AnalyzePreproc(_, _))
.WillRepeatedly(Return(kAboveClippedThreshold));
EXPECT_CALL(volume_, GetMicVolume(_)).Times(0);
EXPECT_CALL(volume_, SetMicVolume(_)).Times(0);
EXPECT_CALL(*agc_, Reset()).Times(0);
PreProcCallback(1000);
}
TEST_F(AgcManagerUnitTest, ClippingMaxIsRespectedWhenEqualToLevel) {
SetVolumeAndProcess(128u);
SetInitialVolume(255u);
EXPECT_CALL(*agc_, AnalyzePreproc(_, _))
.WillOnce(Return(kAboveClippedThreshold));
EXPECT_CALL(*agc_, Reset()).Times(1);
ExpectVolumeChange(255u, 240u);
PreProcCallback(1);
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillRepeatedly(DoAll(SetArgPointee<0>(30), Return(true)));
EXPECT_CALL(volume_, GetMicVolume(_))
.WillRepeatedly(DoAll(SetArgReferee<0>(240u), Return(0)));
EXPECT_CALL(volume_, SetMicVolume(_)).Times(0);
PostProcCallback(10);
}
TEST_F(AgcManagerUnitTest, ClippingMaxIsRespectedWhenHigherThanLevel) {
SetVolumeAndProcess(128u);
SetInitialVolume(200u);
EXPECT_CALL(*agc_, AnalyzePreproc(_, _))
.WillOnce(Return(kAboveClippedThreshold));
EXPECT_CALL(*agc_, Reset()).Times(1);
ExpectVolumeChange(200u, 185u);
PreProcCallback(1);
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillRepeatedly(DoAll(SetArgPointee<0>(40), Return(true)));
ExpectVolumeChange(185u, 240u);
PostProcCallback(1);
EXPECT_CALL(volume_, GetMicVolume(_))
.WillRepeatedly(DoAll(SetArgReferee<0>(240u), Return(0)));
EXPECT_CALL(volume_, SetMicVolume(_)).Times(0);
PostProcCallback(10);
}
TEST_F(AgcManagerUnitTest, MaxCompressionIsIncreasedAfterClipping) {
SetVolumeAndProcess(128u);
SetInitialVolume(210u);
EXPECT_CALL(*agc_, AnalyzePreproc(_, _))
.WillOnce(Return(kAboveClippedThreshold));
EXPECT_CALL(*agc_, Reset()).Times(1);
ExpectVolumeChange(210u, 195u);
PreProcCallback(1);
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(DoAll(SetArgPointee<0>(11), Return(true)))
.WillOnce(DoAll(SetArgPointee<0>(11), Return(true)))
.WillOnce(DoAll(SetArgPointee<0>(11), Return(true)))
.WillOnce(DoAll(SetArgPointee<0>(11), Return(true)))
.WillOnce(DoAll(SetArgPointee<0>(11), Return(true)))
.WillRepeatedly(Return(false));
PostProcCallback(19);
EXPECT_CALL(*gctrl_, set_compression_gain_db(8)).WillOnce(Return(0));
PostProcCallback(20);
EXPECT_CALL(*gctrl_, set_compression_gain_db(9)).WillOnce(Return(0));
PostProcCallback(20);
EXPECT_CALL(*gctrl_, set_compression_gain_db(10)).WillOnce(Return(0));
PostProcCallback(20);
EXPECT_CALL(*gctrl_, set_compression_gain_db(11)).WillOnce(Return(0));
PostProcCallback(20);
EXPECT_CALL(*gctrl_, set_compression_gain_db(12)).WillOnce(Return(0));
PostProcCallback(20);
EXPECT_CALL(*gctrl_, set_compression_gain_db(13)).WillOnce(Return(0));
PostProcCallback(1);
// Continue clipping until we hit the maximum surplus compression.
PreProcCallback(300);
EXPECT_CALL(*agc_, AnalyzePreproc(_, _))
.WillOnce(Return(kAboveClippedThreshold));
EXPECT_CALL(*agc_, Reset()).Times(1);
ExpectVolumeChange(195u, 180u);
PreProcCallback(1);
PreProcCallback(300);
EXPECT_CALL(*agc_, AnalyzePreproc(_, _))
.WillOnce(Return(kAboveClippedThreshold));
EXPECT_CALL(*agc_, Reset()).Times(1);
ExpectVolumeChange(180u, 170u);
PreProcCallback(1);
// Current level is now at the minimum, but the maximum allowed level still
// has more to decrease.
PreProcCallback(300);
EXPECT_CALL(*agc_, AnalyzePreproc(_, _))
.WillOnce(Return(kAboveClippedThreshold));
PreProcCallback(1);
PreProcCallback(300);
EXPECT_CALL(*agc_, AnalyzePreproc(_, _))
.WillOnce(Return(kAboveClippedThreshold));
PreProcCallback(1);
PreProcCallback(300);
EXPECT_CALL(*agc_, AnalyzePreproc(_, _))
.WillOnce(Return(kAboveClippedThreshold));
PreProcCallback(1);
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(DoAll(SetArgPointee<0>(16), Return(true)))
.WillOnce(DoAll(SetArgPointee<0>(16), Return(true)))
.WillOnce(DoAll(SetArgPointee<0>(16), Return(true)))
.WillOnce(DoAll(SetArgPointee<0>(16), Return(true)))
.WillRepeatedly(Return(false));
PostProcCallback(19);
EXPECT_CALL(*gctrl_, set_compression_gain_db(14)).WillOnce(Return(0));
PostProcCallback(20);
EXPECT_CALL(*gctrl_, set_compression_gain_db(15)).WillOnce(Return(0));
PostProcCallback(20);
EXPECT_CALL(*gctrl_, set_compression_gain_db(16)).WillOnce(Return(0));
PostProcCallback(20);
EXPECT_CALL(*gctrl_, set_compression_gain_db(17)).WillOnce(Return(0));
PostProcCallback(20);
EXPECT_CALL(*gctrl_, set_compression_gain_db(18)).WillOnce(Return(0));
PostProcCallback(1);
}
TEST_F(AgcManagerUnitTest, UserCanRaiseVolumeAfterClipping) {
SetVolumeAndProcess(128u);
SetInitialVolume(225u);
EXPECT_CALL(*agc_, AnalyzePreproc(_, _))
.WillOnce(Return(kAboveClippedThreshold));
EXPECT_CALL(*agc_, Reset()).Times(1);
ExpectVolumeChange(225u, 210u);
PreProcCallback(1);
// High enough error to trigger a volume check.
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(DoAll(SetArgPointee<0>(14), Return(true)));
// User changed the volume.
EXPECT_CALL(volume_, GetMicVolume(_))
.WillOnce(DoAll(SetArgReferee<0>(250u), Return(0)));
EXPECT_CALL(volume_, SetMicVolume(_)).Times(0);
EXPECT_CALL(*agc_, Reset()).Times(1);
PostProcCallback(1);
// Move down...
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(DoAll(SetArgPointee<0>(-10), Return(true)));
ExpectVolumeChange(250u, 210u);
PostProcCallback(1);
// And back up to the new max established by the user.
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(DoAll(SetArgPointee<0>(40), Return(true)));
ExpectVolumeChange(210u, 250u);
PostProcCallback(1);
// Will not move above new maximum.
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillOnce(DoAll(SetArgPointee<0>(30), Return(true)));
EXPECT_CALL(volume_, GetMicVolume(_))
.WillRepeatedly(DoAll(SetArgReferee<0>(250u), Return(0)));
EXPECT_CALL(volume_, SetMicVolume(_)).Times(0);
PostProcCallback(1);
}
TEST_F(AgcManagerUnitTest, ClippingDoesNotPullLowVolumeBackUp) {
SetVolumeAndProcess(128u);
SetInitialVolume(80u);
EXPECT_CALL(*agc_, AnalyzePreproc(_, _))
.WillOnce(Return(kAboveClippedThreshold));
EXPECT_CALL(volume_, GetMicVolume(_)).Times(0);
EXPECT_CALL(volume_, SetMicVolume(_)).Times(0);
EXPECT_CALL(*agc_, Reset()).Times(0);
PreProcCallback(1);
}
TEST_F(AgcManagerUnitTest, TakesNoActionOnZeroMicVolume) {
SetVolumeAndProcess(128u);
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
.WillRepeatedly(DoAll(SetArgPointee<0>(30), Return(true)));
EXPECT_CALL(volume_, GetMicVolume(_))
.WillRepeatedly(DoAll(SetArgReferee<0>(0), Return(0)));
EXPECT_CALL(volume_, SetMicVolume(_)).Times(0);
PostProcCallback(10);
}
} // namespace webrtc