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:
@ -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",
|
||||
|
@ -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,
|
||||
|
@ -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_;
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user