Adds WebRTC-Audio-AgcMinMicLevelExperiment to AGC1

Bug: webrtc:11065
Change-Id: Id07ebab7bfa12980187a5847d4f11c8a57450147
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/158784
Commit-Queue: Henrik Andreassson <henrika@webrtc.org>
Reviewed-by: Minyue Li <minyue@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#29681}
This commit is contained in:
henrika
2019-11-04 13:59:21 +01:00
committed by Commit Bot
parent 2b9317ad76
commit ebf4552c8f
4 changed files with 100 additions and 8 deletions

View File

@ -32,6 +32,7 @@ rtc_library("agc") {
"../../../rtc_base:logging",
"../../../rtc_base:macromagic",
"../../../rtc_base:safe_minmax",
"../../../system_wrappers:field_trial",
"../../../system_wrappers:metrics",
"../agc2:level_estimation_agc",
"../vad",
@ -109,6 +110,7 @@ if (rtc_include_tests) {
":gain_control_interface",
":level_estimation",
"..:mocks",
"../../../test:field_trial",
"../../../test:fileutils",
"../../../test:test_support",
"//testing/gtest",

View File

@ -24,6 +24,7 @@
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "rtc_base/numerics/safe_minmax.h"
#include "system_wrappers/include/field_trial.h"
#include "system_wrappers/include/metrics.h"
namespace webrtc {
@ -64,17 +65,42 @@ const int kSurplusCompressionGain = 6;
constexpr size_t kMaxNumSamplesPerChannel = 1920;
constexpr size_t kMaxNumChannels = 4;
int ClampLevel(int mic_level) {
return rtc::SafeClamp(mic_level, kMinMicLevel, kMaxMicLevel);
// Returns kMinMicLevel if no field trial exists or if it has been disabled.
// Returns a value between 0 and 255 depending on the field-trial string.
// Example: 'WebRTC-Audio-AgcMinMicLevelExperiment/Enabled-80' => returns 80.
int GetMinMicLevel() {
RTC_LOG(LS_INFO) << "[agc] GetMinMicLevel";
constexpr char kMinMicLevelFieldTrial[] =
"WebRTC-Audio-AgcMinMicLevelExperiment";
if (!webrtc::field_trial::IsEnabled(kMinMicLevelFieldTrial)) {
RTC_LOG(LS_INFO) << "[agc] Using default min mic level: " << kMinMicLevel;
return kMinMicLevel;
}
const auto field_trial_string =
webrtc::field_trial::FindFullName(kMinMicLevelFieldTrial);
int min_mic_level = -1;
sscanf(field_trial_string.c_str(), "Enabled-%d", &min_mic_level);
if (min_mic_level >= 0 && min_mic_level <= 255) {
RTC_LOG(LS_INFO) << "[agc] Experimental min mic level: " << min_mic_level;
return min_mic_level;
} else {
RTC_LOG(LS_WARNING) << "[agc] Invalid parameter for "
<< kMinMicLevelFieldTrial << ", ignored.";
return kMinMicLevel;
}
}
int LevelFromGainError(int gain_error, int level) {
int ClampLevel(int mic_level, int min_mic_level) {
return rtc::SafeClamp(mic_level, min_mic_level, kMaxMicLevel);
}
int LevelFromGainError(int gain_error, int level, int min_mic_level) {
RTC_DCHECK_GE(level, 0);
RTC_DCHECK_LE(level, kMaxMicLevel);
if (gain_error == 0) {
return level;
}
// TODO(ajm): Could be made more efficient with a binary search.
int new_level = level;
if (gain_error > 0) {
while (kGainMap[new_level] - kGainMap[level] < gain_error &&
@ -83,7 +109,7 @@ int LevelFromGainError(int gain_error, int level) {
}
} else {
while (kGainMap[new_level] - kGainMap[level] > gain_error &&
new_level > kMinMicLevel) {
new_level > min_mic_level) {
--new_level;
}
}
@ -192,9 +218,10 @@ AgcManagerDirect::AgcManagerDirect(Agc* agc,
capture_muted_(false),
check_volume_on_next_process_(true), // Check at startup.
startup_(true),
min_mic_level_(GetMinMicLevel()),
use_agc2_level_estimation_(use_agc2_level_estimation),
disable_digital_adaptive_(disable_digital_adaptive),
startup_min_level_(ClampLevel(startup_min_level)),
startup_min_level_(ClampLevel(startup_min_level, min_mic_level_)),
clipped_level_min_(clipped_level_min),
file_preproc_(new DebugFile("agc_preproc.pcm")),
file_postproc_(new DebugFile("agc_postproc.pcm")) {
@ -210,6 +237,7 @@ AgcManagerDirect::AgcManagerDirect(Agc* agc,
AgcManagerDirect::~AgcManagerDirect() {}
int AgcManagerDirect::Initialize() {
RTC_DLOG(LS_INFO) << "AgcManagerDirect::Initialize";
max_level_ = kMaxMicLevel;
max_compression_gain_ = kMaxCompressionGain;
target_compression_ = disable_digital_adaptive_ ? 0 : kDefaultCompressionGain;
@ -415,7 +443,7 @@ int AgcManagerDirect::CheckVolumeAndReset() {
}
RTC_DLOG(LS_INFO) << "[agc] Initial GetMicVolume()=" << level;
int minLevel = startup_ ? startup_min_level_ : kMinMicLevel;
int minLevel = startup_ ? startup_min_level_ : min_mic_level_;
if (level < minLevel) {
level = minLevel;
RTC_DLOG(LS_INFO) << "[agc] Initial volume too low, raising to " << level;
@ -477,7 +505,7 @@ void AgcManagerDirect::UpdateGain() {
return;
int old_level = level_;
SetLevel(LevelFromGainError(residual_gain, level_));
SetLevel(LevelFromGainError(residual_gain, level_, min_mic_level_));
if (old_level != level_) {
// level_ was updated by SetLevel; log the new value.
RTC_HISTOGRAM_COUNTS_LINEAR("WebRTC.Audio.AgcSetLevel", level_, 1,

View File

@ -74,6 +74,8 @@ class AgcManagerDirect final {
FRIEND_TEST_ALL_PREFIXES(AgcManagerDirectStandaloneTest,
DisableDigitalDisablesDigital);
FRIEND_TEST_ALL_PREFIXES(AgcManagerDirectStandaloneTest,
AgcMinMicLevelExperiment);
// Dependency injection for testing. Don't delete |agc| as the memory is owned
// by the manager.
@ -92,6 +94,9 @@ class AgcManagerDirect final {
bool use_agc2_level_estimation,
bool disable_digital_adaptive);
int min_mic_level() const { return min_mic_level_; }
int startup_min_level() const { return startup_min_level_; }
// Sets a new microphone level, after first checking that it hasn't been
// updated by the user, in which case no action is taken.
void SetLevel(int new_level);
@ -122,6 +127,7 @@ class AgcManagerDirect final {
bool capture_muted_;
bool check_volume_on_next_process_;
bool startup_;
const int min_mic_level_;
const bool use_agc2_level_estimation_;
const bool disable_digital_adaptive_;
int startup_min_level_;

View File

@ -13,6 +13,7 @@
#include "modules/audio_processing/agc/gain_control.h"
#include "modules/audio_processing/agc/mock_agc.h"
#include "modules/audio_processing/include/mock_audio_processing.h"
#include "test/field_trial.h"
#include "test/gmock.h"
#include "test/gtest.h"
@ -31,6 +32,7 @@ const int kSamplesPerChannel = kSampleRateHz / 100;
const int kInitialVolume = 128;
constexpr int kClippedMin = 165; // Arbitrary, but different from the default.
const float kAboveClippedThreshold = 0.2f;
const int kMinMicLevel = 12;
class MockGainControl : public GainControl {
public:
@ -722,4 +724,58 @@ TEST(AgcManagerDirectStandaloneTest, DisableDigitalDisablesDigital) {
manager.Initialize();
}
TEST(AgcManagerDirectStandaloneTest, AgcMinMicLevelExperiment) {
auto agc_man = std::unique_ptr<AgcManagerDirect>(new AgcManagerDirect(
nullptr, nullptr, nullptr, kInitialVolume, kClippedMin, true, true));
EXPECT_EQ(agc_man->min_mic_level(), kMinMicLevel);
EXPECT_EQ(agc_man->startup_min_level(), kInitialVolume);
{
test::ScopedFieldTrials field_trial(
"WebRTC-Audio-AgcMinMicLevelExperiment/Disabled/");
agc_man.reset(new AgcManagerDirect(
nullptr, nullptr, nullptr, kInitialVolume, kClippedMin, true, true));
EXPECT_EQ(agc_man->min_mic_level(), kMinMicLevel);
EXPECT_EQ(agc_man->startup_min_level(), kInitialVolume);
}
{
// Valid range of field-trial parameter is [0,255].
test::ScopedFieldTrials field_trial(
"WebRTC-Audio-AgcMinMicLevelExperiment/Enabled-256/");
agc_man.reset(new AgcManagerDirect(
nullptr, nullptr, nullptr, kInitialVolume, kClippedMin, true, true));
EXPECT_EQ(agc_man->min_mic_level(), kMinMicLevel);
EXPECT_EQ(agc_man->startup_min_level(), kInitialVolume);
}
{
test::ScopedFieldTrials field_trial(
"WebRTC-Audio-AgcMinMicLevelExperiment/Enabled--1/");
agc_man.reset(new AgcManagerDirect(
nullptr, nullptr, nullptr, kInitialVolume, kClippedMin, true, true));
EXPECT_EQ(agc_man->min_mic_level(), kMinMicLevel);
EXPECT_EQ(agc_man->startup_min_level(), kInitialVolume);
}
{
// Verify that a valid experiment changes the minimum microphone level.
// The start volume is larger than the min level and should therefore not
// be changed.
test::ScopedFieldTrials field_trial(
"WebRTC-Audio-AgcMinMicLevelExperiment/Enabled-50/");
agc_man.reset(new AgcManagerDirect(
nullptr, nullptr, nullptr, kInitialVolume, kClippedMin, true, true));
EXPECT_EQ(agc_man->min_mic_level(), 50);
EXPECT_EQ(agc_man->startup_min_level(), kInitialVolume);
}
{
// Use experiment to reduce the default minimum microphone level, start at
// a lower level and ensure that the startup level is increased to the min
// level set by the experiment.
test::ScopedFieldTrials field_trial(
"WebRTC-Audio-AgcMinMicLevelExperiment/Enabled-50/");
agc_man.reset(new AgcManagerDirect(nullptr, nullptr, nullptr, 30,
kClippedMin, true, true));
EXPECT_EQ(agc_man->min_mic_level(), 50);
EXPECT_EQ(agc_man->startup_min_level(), 50);
}
}
} // namespace webrtc