mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-14 14:20:45 +01:00

This CL adds a flag to optionally disable the digital gain control in ExperimentalAgc. With the flag, Experimental Agc (henceforth AGC1) only controls the adaptive analog gain. This flag can be combined to that which activates AGC2. That way, one can enable the hybrid AGC configuration AGC1 analog only + AGC2 fixed+adaptive digital. Previously, there was a flag "use_agc2_digital_adaptive" in AgcManagerDirect. Our ambition was that to activate the hybrid mode described above with this flag. The behavior of the flag was not implemented. To activate the hybrid mode after this CL, set ExperimentalAgc::digital_adaptive_disabled=true and AudioProcessing::Config::GainController2::enabled=true. We also add flags for these settings in audioproc_f. Then the required settings are currently audioproc_f --agc2 1 --agc 1 --experimental_agc 1 \ --experimental_agc_disable_digital_adaptive 1 \ -i [INPUT] Bug: webrtc:7494 Change-Id: Iea798dc3899cec83d30ba71caba787262fcaef41 Reviewed-on: https://webrtc-review.googlesource.com/89740 Commit-Queue: Alex Loiko <aleloi@webrtc.org> Reviewed-by: Alessio Bazzica <alessiob@webrtc.org> Cr-Commit-Position: refs/heads/master@{#24249}
704 lines
23 KiB
C++
704 lines
23 KiB
C++
/*
|
|
* 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 "modules/audio_processing/agc/agc_manager_direct.h"
|
|
|
|
#include "common_types.h" // NOLINT(build/include)
|
|
#include "modules/audio_processing/agc/mock_agc.h"
|
|
#include "modules/audio_processing/include/mock_audio_processing.h"
|
|
#include "test/gmock.h"
|
|
#include "test/gtest.h"
|
|
|
|
using ::testing::_;
|
|
using ::testing::AtLeast;
|
|
using ::testing::DoAll;
|
|
using ::testing::Return;
|
|
using ::testing::SetArgPointee;
|
|
|
|
namespace webrtc {
|
|
namespace {
|
|
|
|
const int kSampleRateHz = 32000;
|
|
const int kNumChannels = 1;
|
|
const int kSamplesPerChannel = kSampleRateHz / 100;
|
|
const int kInitialVolume = 128;
|
|
constexpr int kClippedMin = 165; // Arbitrary, but different from the default.
|
|
const float kAboveClippedThreshold = 0.2f;
|
|
|
|
class TestVolumeCallbacks : public VolumeCallbacks {
|
|
public:
|
|
TestVolumeCallbacks() : volume_(0) {}
|
|
void SetMicVolume(int volume) override { volume_ = volume; }
|
|
int GetMicVolume() override { return volume_; }
|
|
|
|
private:
|
|
int volume_;
|
|
};
|
|
|
|
} // namespace
|
|
|
|
class AgcManagerDirectTest : public ::testing::Test {
|
|
protected:
|
|
AgcManagerDirectTest()
|
|
: agc_(new MockAgc),
|
|
manager_(agc_, &gctrl_, &volume_, kInitialVolume, kClippedMin) {
|
|
ExpectInitialize();
|
|
manager_.Initialize();
|
|
}
|
|
|
|
void FirstProcess() {
|
|
EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
|
|
EXPECT_CALL(*agc_, GetRmsErrorDb(_)).WillOnce(Return(false));
|
|
CallProcess(1);
|
|
}
|
|
|
|
void SetVolumeAndProcess(int volume) {
|
|
volume_.SetMicVolume(volume);
|
|
FirstProcess();
|
|
}
|
|
|
|
void ExpectCheckVolumeAndReset(int volume) {
|
|
volume_.SetMicVolume(volume);
|
|
EXPECT_CALL(*agc_, Reset());
|
|
}
|
|
|
|
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 CallProcess(int num_calls) {
|
|
for (int i = 0; i < num_calls; ++i) {
|
|
EXPECT_CALL(*agc_, Process(_, _, _)).WillOnce(Return());
|
|
manager_.Process(nullptr, kSamplesPerChannel, kSampleRateHz);
|
|
}
|
|
}
|
|
|
|
void CallPreProc(int num_calls) {
|
|
for (int i = 0; i < num_calls; ++i) {
|
|
manager_.AnalyzePreProcess(nullptr, kNumChannels, kSamplesPerChannel);
|
|
}
|
|
}
|
|
|
|
MockAgc* agc_;
|
|
test::MockGainControl gctrl_;
|
|
TestVolumeCallbacks volume_;
|
|
AgcManagerDirect manager_;
|
|
};
|
|
|
|
TEST_F(AgcManagerDirectTest, StartupMinVolumeConfigurationIsRespected) {
|
|
FirstProcess();
|
|
EXPECT_EQ(kInitialVolume, volume_.GetMicVolume());
|
|
}
|
|
|
|
TEST_F(AgcManagerDirectTest, MicVolumeResponseToRmsError) {
|
|
FirstProcess();
|
|
|
|
// Compressor default; no residual error.
|
|
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
|
.WillOnce(DoAll(SetArgPointee<0>(5), Return(true)));
|
|
CallProcess(1);
|
|
|
|
// Inside the compressor's window; no change of volume.
|
|
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
|
.WillOnce(DoAll(SetArgPointee<0>(10), Return(true)));
|
|
CallProcess(1);
|
|
|
|
// Above the compressor's window; volume should be increased.
|
|
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
|
.WillOnce(DoAll(SetArgPointee<0>(11), Return(true)));
|
|
CallProcess(1);
|
|
EXPECT_EQ(130, volume_.GetMicVolume());
|
|
|
|
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
|
.WillOnce(DoAll(SetArgPointee<0>(20), Return(true)));
|
|
CallProcess(1);
|
|
EXPECT_EQ(168, volume_.GetMicVolume());
|
|
|
|
// Inside the compressor's window; no change of volume.
|
|
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
|
.WillOnce(DoAll(SetArgPointee<0>(5), Return(true)));
|
|
CallProcess(1);
|
|
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
|
.WillOnce(DoAll(SetArgPointee<0>(0), Return(true)));
|
|
CallProcess(1);
|
|
|
|
// Below the compressor's window; volume should be decreased.
|
|
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
|
.WillOnce(DoAll(SetArgPointee<0>(-1), Return(true)));
|
|
CallProcess(1);
|
|
EXPECT_EQ(167, volume_.GetMicVolume());
|
|
|
|
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
|
.WillOnce(DoAll(SetArgPointee<0>(-1), Return(true)));
|
|
CallProcess(1);
|
|
EXPECT_EQ(163, volume_.GetMicVolume());
|
|
|
|
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
|
.WillOnce(DoAll(SetArgPointee<0>(-9), Return(true)));
|
|
CallProcess(1);
|
|
EXPECT_EQ(129, volume_.GetMicVolume());
|
|
}
|
|
|
|
TEST_F(AgcManagerDirectTest, MicVolumeIsLimited) {
|
|
FirstProcess();
|
|
|
|
// Maximum upwards change is limited.
|
|
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
|
.WillOnce(DoAll(SetArgPointee<0>(30), Return(true)));
|
|
CallProcess(1);
|
|
EXPECT_EQ(183, volume_.GetMicVolume());
|
|
|
|
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
|
.WillOnce(DoAll(SetArgPointee<0>(30), Return(true)));
|
|
CallProcess(1);
|
|
EXPECT_EQ(243, volume_.GetMicVolume());
|
|
|
|
// Won't go higher than the maximum.
|
|
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
|
.WillOnce(DoAll(SetArgPointee<0>(30), Return(true)));
|
|
CallProcess(1);
|
|
EXPECT_EQ(255, volume_.GetMicVolume());
|
|
|
|
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
|
.WillOnce(DoAll(SetArgPointee<0>(-1), Return(true)));
|
|
CallProcess(1);
|
|
EXPECT_EQ(254, volume_.GetMicVolume());
|
|
|
|
// Maximum downwards change is limited.
|
|
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
|
.WillOnce(DoAll(SetArgPointee<0>(-40), Return(true)));
|
|
CallProcess(1);
|
|
EXPECT_EQ(194, volume_.GetMicVolume());
|
|
|
|
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
|
.WillOnce(DoAll(SetArgPointee<0>(-40), Return(true)));
|
|
CallProcess(1);
|
|
EXPECT_EQ(137, volume_.GetMicVolume());
|
|
|
|
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
|
.WillOnce(DoAll(SetArgPointee<0>(-40), Return(true)));
|
|
CallProcess(1);
|
|
EXPECT_EQ(88, volume_.GetMicVolume());
|
|
|
|
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
|
.WillOnce(DoAll(SetArgPointee<0>(-40), Return(true)));
|
|
CallProcess(1);
|
|
EXPECT_EQ(54, volume_.GetMicVolume());
|
|
|
|
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
|
.WillOnce(DoAll(SetArgPointee<0>(-40), Return(true)));
|
|
CallProcess(1);
|
|
EXPECT_EQ(33, volume_.GetMicVolume());
|
|
|
|
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
|
.WillOnce(DoAll(SetArgPointee<0>(-40), Return(true)));
|
|
CallProcess(1);
|
|
EXPECT_EQ(18, volume_.GetMicVolume());
|
|
|
|
// Won't go lower than the minimum.
|
|
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
|
.WillOnce(DoAll(SetArgPointee<0>(-40), Return(true)));
|
|
CallProcess(1);
|
|
EXPECT_EQ(12, volume_.GetMicVolume());
|
|
}
|
|
|
|
TEST_F(AgcManagerDirectTest, CompressorStepsTowardsTarget) {
|
|
FirstProcess();
|
|
|
|
// 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);
|
|
CallProcess(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);
|
|
CallProcess(19);
|
|
EXPECT_CALL(gctrl_, set_compression_gain_db(8)).WillOnce(Return(0));
|
|
CallProcess(1);
|
|
|
|
EXPECT_CALL(gctrl_, set_compression_gain_db(_)).Times(0);
|
|
CallProcess(19);
|
|
EXPECT_CALL(gctrl_, set_compression_gain_db(9)).WillOnce(Return(0));
|
|
CallProcess(1);
|
|
|
|
EXPECT_CALL(gctrl_, set_compression_gain_db(_)).Times(0);
|
|
CallProcess(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);
|
|
CallProcess(19);
|
|
EXPECT_CALL(gctrl_, set_compression_gain_db(8)).WillOnce(Return(0));
|
|
CallProcess(1);
|
|
|
|
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
|
.WillOnce(DoAll(SetArgPointee<0>(9), Return(true)))
|
|
.WillRepeatedly(Return(false));
|
|
EXPECT_CALL(gctrl_, set_compression_gain_db(_)).Times(0);
|
|
CallProcess(19);
|
|
EXPECT_CALL(gctrl_, set_compression_gain_db(9)).WillOnce(Return(0));
|
|
CallProcess(1);
|
|
|
|
EXPECT_CALL(gctrl_, set_compression_gain_db(_)).Times(0);
|
|
CallProcess(20);
|
|
}
|
|
|
|
TEST_F(AgcManagerDirectTest, CompressorErrorIsDeemphasized) {
|
|
FirstProcess();
|
|
|
|
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
|
.WillOnce(DoAll(SetArgPointee<0>(10), Return(true)))
|
|
.WillRepeatedly(Return(false));
|
|
CallProcess(19);
|
|
EXPECT_CALL(gctrl_, set_compression_gain_db(8)).WillOnce(Return(0));
|
|
CallProcess(20);
|
|
EXPECT_CALL(gctrl_, set_compression_gain_db(9)).WillOnce(Return(0));
|
|
CallProcess(1);
|
|
EXPECT_CALL(gctrl_, set_compression_gain_db(_)).Times(0);
|
|
CallProcess(20);
|
|
|
|
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
|
.WillOnce(DoAll(SetArgPointee<0>(0), Return(true)))
|
|
.WillRepeatedly(Return(false));
|
|
CallProcess(19);
|
|
EXPECT_CALL(gctrl_, set_compression_gain_db(8)).WillOnce(Return(0));
|
|
CallProcess(20);
|
|
EXPECT_CALL(gctrl_, set_compression_gain_db(7)).WillOnce(Return(0));
|
|
CallProcess(20);
|
|
EXPECT_CALL(gctrl_, set_compression_gain_db(6)).WillOnce(Return(0));
|
|
CallProcess(1);
|
|
EXPECT_CALL(gctrl_, set_compression_gain_db(_)).Times(0);
|
|
CallProcess(20);
|
|
}
|
|
|
|
TEST_F(AgcManagerDirectTest, CompressorReachesMaximum) {
|
|
FirstProcess();
|
|
|
|
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));
|
|
CallProcess(19);
|
|
EXPECT_CALL(gctrl_, set_compression_gain_db(8)).WillOnce(Return(0));
|
|
CallProcess(20);
|
|
EXPECT_CALL(gctrl_, set_compression_gain_db(9)).WillOnce(Return(0));
|
|
CallProcess(20);
|
|
EXPECT_CALL(gctrl_, set_compression_gain_db(10)).WillOnce(Return(0));
|
|
CallProcess(20);
|
|
EXPECT_CALL(gctrl_, set_compression_gain_db(11)).WillOnce(Return(0));
|
|
CallProcess(20);
|
|
EXPECT_CALL(gctrl_, set_compression_gain_db(12)).WillOnce(Return(0));
|
|
CallProcess(1);
|
|
}
|
|
|
|
TEST_F(AgcManagerDirectTest, CompressorReachesMinimum) {
|
|
FirstProcess();
|
|
|
|
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));
|
|
CallProcess(19);
|
|
EXPECT_CALL(gctrl_, set_compression_gain_db(6)).WillOnce(Return(0));
|
|
CallProcess(20);
|
|
EXPECT_CALL(gctrl_, set_compression_gain_db(5)).WillOnce(Return(0));
|
|
CallProcess(20);
|
|
EXPECT_CALL(gctrl_, set_compression_gain_db(4)).WillOnce(Return(0));
|
|
CallProcess(20);
|
|
EXPECT_CALL(gctrl_, set_compression_gain_db(3)).WillOnce(Return(0));
|
|
CallProcess(20);
|
|
EXPECT_CALL(gctrl_, set_compression_gain_db(2)).WillOnce(Return(0));
|
|
CallProcess(1);
|
|
}
|
|
|
|
TEST_F(AgcManagerDirectTest, NoActionWhileMuted) {
|
|
manager_.SetCaptureMuted(true);
|
|
manager_.Process(nullptr, kSamplesPerChannel, kSampleRateHz);
|
|
}
|
|
|
|
TEST_F(AgcManagerDirectTest, UnmutingChecksVolumeWithoutRaising) {
|
|
FirstProcess();
|
|
|
|
manager_.SetCaptureMuted(true);
|
|
manager_.SetCaptureMuted(false);
|
|
ExpectCheckVolumeAndReset(127);
|
|
// SetMicVolume should not be called.
|
|
EXPECT_CALL(*agc_, GetRmsErrorDb(_)).WillOnce(Return(false));
|
|
CallProcess(1);
|
|
EXPECT_EQ(127, volume_.GetMicVolume());
|
|
}
|
|
|
|
TEST_F(AgcManagerDirectTest, UnmutingRaisesTooLowVolume) {
|
|
FirstProcess();
|
|
|
|
manager_.SetCaptureMuted(true);
|
|
manager_.SetCaptureMuted(false);
|
|
ExpectCheckVolumeAndReset(11);
|
|
EXPECT_CALL(*agc_, GetRmsErrorDb(_)).WillOnce(Return(false));
|
|
CallProcess(1);
|
|
EXPECT_EQ(12, volume_.GetMicVolume());
|
|
}
|
|
|
|
TEST_F(AgcManagerDirectTest, ManualLevelChangeResultsInNoSetMicCall) {
|
|
FirstProcess();
|
|
|
|
// 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)));
|
|
|
|
// When the analog volume changes, the gain controller is reset.
|
|
EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
|
|
|
|
// GetMicVolume returns a value outside of the quantization slack, indicating
|
|
// a manual volume change.
|
|
ASSERT_NE(volume_.GetMicVolume(), 154);
|
|
volume_.SetMicVolume(154);
|
|
CallProcess(1);
|
|
EXPECT_EQ(154, volume_.GetMicVolume());
|
|
|
|
// Do the same thing, except downwards now.
|
|
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
|
.WillOnce(DoAll(SetArgPointee<0>(-1), Return(true)));
|
|
volume_.SetMicVolume(100);
|
|
EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
|
|
CallProcess(1);
|
|
EXPECT_EQ(100, volume_.GetMicVolume());
|
|
|
|
// And finally verify the AGC continues working without a manual change.
|
|
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
|
.WillOnce(DoAll(SetArgPointee<0>(-1), Return(true)));
|
|
CallProcess(1);
|
|
EXPECT_EQ(99, volume_.GetMicVolume());
|
|
}
|
|
|
|
TEST_F(AgcManagerDirectTest, RecoveryAfterManualLevelChangeFromMax) {
|
|
FirstProcess();
|
|
|
|
// 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)));
|
|
CallProcess(1);
|
|
EXPECT_EQ(183, volume_.GetMicVolume());
|
|
CallProcess(1);
|
|
EXPECT_EQ(243, volume_.GetMicVolume());
|
|
CallProcess(1);
|
|
EXPECT_EQ(255, volume_.GetMicVolume());
|
|
|
|
// Manual change does not result in SetMicVolume call.
|
|
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
|
.WillOnce(DoAll(SetArgPointee<0>(-1), Return(true)));
|
|
volume_.SetMicVolume(50);
|
|
EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
|
|
CallProcess(1);
|
|
EXPECT_EQ(50, volume_.GetMicVolume());
|
|
|
|
// Continues working as usual afterwards.
|
|
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
|
.WillOnce(DoAll(SetArgPointee<0>(20), Return(true)));
|
|
CallProcess(1);
|
|
EXPECT_EQ(69, volume_.GetMicVolume());
|
|
}
|
|
|
|
TEST_F(AgcManagerDirectTest, RecoveryAfterManualLevelChangeBelowMin) {
|
|
FirstProcess();
|
|
|
|
// 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.
|
|
volume_.SetMicVolume(1);
|
|
EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
|
|
CallProcess(1);
|
|
EXPECT_EQ(1, volume_.GetMicVolume());
|
|
|
|
// Continues working as usual afterwards.
|
|
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
|
.WillOnce(DoAll(SetArgPointee<0>(11), Return(true)));
|
|
CallProcess(1);
|
|
EXPECT_EQ(2, volume_.GetMicVolume());
|
|
|
|
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
|
.WillOnce(DoAll(SetArgPointee<0>(30), Return(true)));
|
|
CallProcess(1);
|
|
EXPECT_EQ(11, volume_.GetMicVolume());
|
|
|
|
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
|
.WillOnce(DoAll(SetArgPointee<0>(20), Return(true)));
|
|
CallProcess(1);
|
|
EXPECT_EQ(18, volume_.GetMicVolume());
|
|
}
|
|
|
|
TEST_F(AgcManagerDirectTest, NoClippingHasNoImpact) {
|
|
FirstProcess();
|
|
|
|
EXPECT_CALL(*agc_, AnalyzePreproc(_, _)).WillRepeatedly(Return(0));
|
|
CallPreProc(100);
|
|
EXPECT_EQ(128, volume_.GetMicVolume());
|
|
}
|
|
|
|
TEST_F(AgcManagerDirectTest, ClippingUnderThresholdHasNoImpact) {
|
|
FirstProcess();
|
|
|
|
EXPECT_CALL(*agc_, AnalyzePreproc(_, _)).WillOnce(Return(0.099));
|
|
CallPreProc(1);
|
|
EXPECT_EQ(128, volume_.GetMicVolume());
|
|
}
|
|
|
|
TEST_F(AgcManagerDirectTest, ClippingLowersVolume) {
|
|
SetVolumeAndProcess(255);
|
|
|
|
EXPECT_CALL(*agc_, AnalyzePreproc(_, _)).WillOnce(Return(0.101));
|
|
EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
|
|
CallPreProc(1);
|
|
EXPECT_EQ(240, volume_.GetMicVolume());
|
|
}
|
|
|
|
TEST_F(AgcManagerDirectTest, WaitingPeriodBetweenClippingChecks) {
|
|
SetVolumeAndProcess(255);
|
|
|
|
EXPECT_CALL(*agc_, AnalyzePreproc(_, _))
|
|
.WillOnce(Return(kAboveClippedThreshold));
|
|
EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
|
|
CallPreProc(1);
|
|
EXPECT_EQ(240, volume_.GetMicVolume());
|
|
|
|
EXPECT_CALL(*agc_, AnalyzePreproc(_, _))
|
|
.WillRepeatedly(Return(kAboveClippedThreshold));
|
|
EXPECT_CALL(*agc_, Reset()).Times(0);
|
|
CallPreProc(300);
|
|
EXPECT_EQ(240, volume_.GetMicVolume());
|
|
|
|
EXPECT_CALL(*agc_, AnalyzePreproc(_, _))
|
|
.WillOnce(Return(kAboveClippedThreshold));
|
|
EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
|
|
CallPreProc(1);
|
|
EXPECT_EQ(225, volume_.GetMicVolume());
|
|
}
|
|
|
|
TEST_F(AgcManagerDirectTest, ClippingLoweringIsLimited) {
|
|
SetVolumeAndProcess(180);
|
|
|
|
EXPECT_CALL(*agc_, AnalyzePreproc(_, _))
|
|
.WillOnce(Return(kAboveClippedThreshold));
|
|
EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
|
|
CallPreProc(1);
|
|
EXPECT_EQ(kClippedMin, volume_.GetMicVolume());
|
|
|
|
EXPECT_CALL(*agc_, AnalyzePreproc(_, _))
|
|
.WillRepeatedly(Return(kAboveClippedThreshold));
|
|
EXPECT_CALL(*agc_, Reset()).Times(0);
|
|
CallPreProc(1000);
|
|
EXPECT_EQ(kClippedMin, volume_.GetMicVolume());
|
|
}
|
|
|
|
TEST_F(AgcManagerDirectTest, ClippingMaxIsRespectedWhenEqualToLevel) {
|
|
SetVolumeAndProcess(255);
|
|
|
|
EXPECT_CALL(*agc_, AnalyzePreproc(_, _))
|
|
.WillOnce(Return(kAboveClippedThreshold));
|
|
EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
|
|
CallPreProc(1);
|
|
EXPECT_EQ(240, volume_.GetMicVolume());
|
|
|
|
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
|
.WillRepeatedly(DoAll(SetArgPointee<0>(30), Return(true)));
|
|
CallProcess(10);
|
|
EXPECT_EQ(240, volume_.GetMicVolume());
|
|
}
|
|
|
|
TEST_F(AgcManagerDirectTest, ClippingMaxIsRespectedWhenHigherThanLevel) {
|
|
SetVolumeAndProcess(200);
|
|
|
|
EXPECT_CALL(*agc_, AnalyzePreproc(_, _))
|
|
.WillOnce(Return(kAboveClippedThreshold));
|
|
EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
|
|
CallPreProc(1);
|
|
EXPECT_EQ(185, volume_.GetMicVolume());
|
|
|
|
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
|
.WillRepeatedly(DoAll(SetArgPointee<0>(40), Return(true)));
|
|
CallProcess(1);
|
|
EXPECT_EQ(240, volume_.GetMicVolume());
|
|
CallProcess(10);
|
|
EXPECT_EQ(240, volume_.GetMicVolume());
|
|
}
|
|
|
|
TEST_F(AgcManagerDirectTest, MaxCompressionIsIncreasedAfterClipping) {
|
|
SetVolumeAndProcess(210);
|
|
|
|
EXPECT_CALL(*agc_, AnalyzePreproc(_, _))
|
|
.WillOnce(Return(kAboveClippedThreshold));
|
|
EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
|
|
CallPreProc(1);
|
|
EXPECT_EQ(195, volume_.GetMicVolume());
|
|
|
|
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));
|
|
CallProcess(19);
|
|
EXPECT_CALL(gctrl_, set_compression_gain_db(8)).WillOnce(Return(0));
|
|
CallProcess(20);
|
|
EXPECT_CALL(gctrl_, set_compression_gain_db(9)).WillOnce(Return(0));
|
|
CallProcess(20);
|
|
EXPECT_CALL(gctrl_, set_compression_gain_db(10)).WillOnce(Return(0));
|
|
CallProcess(20);
|
|
EXPECT_CALL(gctrl_, set_compression_gain_db(11)).WillOnce(Return(0));
|
|
CallProcess(20);
|
|
EXPECT_CALL(gctrl_, set_compression_gain_db(12)).WillOnce(Return(0));
|
|
CallProcess(20);
|
|
EXPECT_CALL(gctrl_, set_compression_gain_db(13)).WillOnce(Return(0));
|
|
CallProcess(1);
|
|
|
|
// Continue clipping until we hit the maximum surplus compression.
|
|
CallPreProc(300);
|
|
EXPECT_CALL(*agc_, AnalyzePreproc(_, _))
|
|
.WillOnce(Return(kAboveClippedThreshold));
|
|
EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
|
|
CallPreProc(1);
|
|
EXPECT_EQ(180, volume_.GetMicVolume());
|
|
|
|
CallPreProc(300);
|
|
EXPECT_CALL(*agc_, AnalyzePreproc(_, _))
|
|
.WillOnce(Return(kAboveClippedThreshold));
|
|
EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
|
|
CallPreProc(1);
|
|
EXPECT_EQ(kClippedMin, volume_.GetMicVolume());
|
|
|
|
// Current level is now at the minimum, but the maximum allowed level still
|
|
// has more to decrease.
|
|
CallPreProc(300);
|
|
EXPECT_CALL(*agc_, AnalyzePreproc(_, _))
|
|
.WillOnce(Return(kAboveClippedThreshold));
|
|
CallPreProc(1);
|
|
|
|
CallPreProc(300);
|
|
EXPECT_CALL(*agc_, AnalyzePreproc(_, _))
|
|
.WillOnce(Return(kAboveClippedThreshold));
|
|
CallPreProc(1);
|
|
|
|
CallPreProc(300);
|
|
EXPECT_CALL(*agc_, AnalyzePreproc(_, _))
|
|
.WillOnce(Return(kAboveClippedThreshold));
|
|
CallPreProc(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));
|
|
CallProcess(19);
|
|
EXPECT_CALL(gctrl_, set_compression_gain_db(14)).WillOnce(Return(0));
|
|
CallProcess(20);
|
|
EXPECT_CALL(gctrl_, set_compression_gain_db(15)).WillOnce(Return(0));
|
|
CallProcess(20);
|
|
EXPECT_CALL(gctrl_, set_compression_gain_db(16)).WillOnce(Return(0));
|
|
CallProcess(20);
|
|
EXPECT_CALL(gctrl_, set_compression_gain_db(17)).WillOnce(Return(0));
|
|
CallProcess(20);
|
|
EXPECT_CALL(gctrl_, set_compression_gain_db(18)).WillOnce(Return(0));
|
|
CallProcess(1);
|
|
}
|
|
|
|
TEST_F(AgcManagerDirectTest, UserCanRaiseVolumeAfterClipping) {
|
|
SetVolumeAndProcess(225);
|
|
|
|
EXPECT_CALL(*agc_, AnalyzePreproc(_, _))
|
|
.WillOnce(Return(kAboveClippedThreshold));
|
|
EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
|
|
CallPreProc(1);
|
|
EXPECT_EQ(210, volume_.GetMicVolume());
|
|
|
|
// High enough error to trigger a volume check.
|
|
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
|
.WillOnce(DoAll(SetArgPointee<0>(14), Return(true)));
|
|
// User changed the volume.
|
|
volume_.SetMicVolume(250);
|
|
EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
|
|
CallProcess(1);
|
|
EXPECT_EQ(250, volume_.GetMicVolume());
|
|
|
|
// Move down...
|
|
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
|
.WillOnce(DoAll(SetArgPointee<0>(-10), Return(true)));
|
|
CallProcess(1);
|
|
EXPECT_EQ(210, volume_.GetMicVolume());
|
|
// And back up to the new max established by the user.
|
|
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
|
.WillOnce(DoAll(SetArgPointee<0>(40), Return(true)));
|
|
CallProcess(1);
|
|
EXPECT_EQ(250, volume_.GetMicVolume());
|
|
// Will not move above new maximum.
|
|
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
|
.WillOnce(DoAll(SetArgPointee<0>(30), Return(true)));
|
|
CallProcess(1);
|
|
EXPECT_EQ(250, volume_.GetMicVolume());
|
|
}
|
|
|
|
TEST_F(AgcManagerDirectTest, ClippingDoesNotPullLowVolumeBackUp) {
|
|
SetVolumeAndProcess(80);
|
|
|
|
EXPECT_CALL(*agc_, AnalyzePreproc(_, _))
|
|
.WillOnce(Return(kAboveClippedThreshold));
|
|
EXPECT_CALL(*agc_, Reset()).Times(0);
|
|
int initial_volume = volume_.GetMicVolume();
|
|
CallPreProc(1);
|
|
EXPECT_EQ(initial_volume, volume_.GetMicVolume());
|
|
}
|
|
|
|
TEST_F(AgcManagerDirectTest, TakesNoActionOnZeroMicVolume) {
|
|
FirstProcess();
|
|
|
|
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
|
.WillRepeatedly(DoAll(SetArgPointee<0>(30), Return(true)));
|
|
volume_.SetMicVolume(0);
|
|
CallProcess(10);
|
|
EXPECT_EQ(0, volume_.GetMicVolume());
|
|
}
|
|
|
|
TEST(AgcManagerDirectStandaloneTest, DisableDigitalDisablesDigital) {
|
|
auto agc = std::unique_ptr<Agc>(new testing::NiceMock<MockAgc>());
|
|
test::MockGainControl gctrl;
|
|
TestVolumeCallbacks volume;
|
|
|
|
AgcManagerDirect manager(agc.release(), &gctrl, &volume, kInitialVolume,
|
|
kClippedMin,
|
|
/* use agc2 level estimation */ false,
|
|
/* disable digital adaptive */ true);
|
|
|
|
EXPECT_CALL(gctrl, set_mode(GainControl::kFixedDigital));
|
|
EXPECT_CALL(gctrl, set_target_level_dbfs(0));
|
|
EXPECT_CALL(gctrl, set_compression_gain_db(0));
|
|
EXPECT_CALL(gctrl, enable_limiter(false));
|
|
|
|
manager.Initialize();
|
|
}
|
|
|
|
} // namespace webrtc
|