WebRTC AGC Hybrid experiment: wire-up AGC2 params (+ refactoring)
ConfigAutomaticGainControl now supports more AGC2 params that are
needed for experimentation.
The CL includes a refactoring to avoid base::Optional boilerplate and
it improves the docstring for `ConfigAutomaticGainControl()`.
Tested: checked feature activation via AECdump using appr.tc
$ out/Default/Chromium.app/Contents/MacOS/Chromium \
--enable-features=WebrtcHybridAgc
(cherry picked from commit bdf52e4e5685e5c71668f05d5dee1b4d394587b6)
Bug: chromium:1135177
Change-Id: I0d226b9e7e6f17acb8408af8ded80d80db7cabe0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2446149
Commit-Queue: Ale Bzk <[email protected]>
Reviewed-by: Henrik Boström <[email protected]>
Cr-Original-Commit-Position: refs/heads/master@{#813736}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2462082
Cr-Commit-Position: refs/branch-heads/4280@{#186}
Cr-Branched-From: ea420fb963f9658c9969b6513c56b8f47efa1a2a-refs/heads/master@{#812852}
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_audio_processor.cc b/third_party/blink/renderer/modules/mediastream/media_stream_audio_processor.cc
index 8b1962f..baa1e425 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream_audio_processor.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_audio_processor.cc
@@ -581,24 +581,37 @@
if (properties.goog_auto_gain_control ||
properties.goog_experimental_auto_gain_control) {
- bool use_hybrid_agc = false;
- base::Optional<bool> use_peaks_not_rms;
- base::Optional<int> saturation_margin;
- if (properties.goog_experimental_auto_gain_control) {
- use_hybrid_agc = base::FeatureList::IsEnabled(features::kWebRtcHybridAgc);
- if (use_hybrid_agc) {
- DCHECK(properties.goog_auto_gain_control)
- << "Cannot enable hybrid AGC when AGC is disabled.";
- }
- use_peaks_not_rms = base::GetFieldTrialParamByFeatureAsBool(
- features::kWebRtcHybridAgc, "use_peaks_not_rms", false);
- saturation_margin = base::GetFieldTrialParamByFeatureAsInt(
- features::kWebRtcHybridAgc, "saturation_margin", -1);
+ base::Optional<blink::AdaptiveGainController2Properties> agc2_properties;
+ if (properties.goog_experimental_auto_gain_control &&
+ base::FeatureList::IsEnabled(features::kWebRtcHybridAgc)) {
+ DCHECK(properties.goog_auto_gain_control)
+ << "Cannot enable hybrid AGC when AGC is disabled.";
+ agc2_properties = blink::AdaptiveGainController2Properties{};
+ agc2_properties->vad_probability_attack =
+ base::GetFieldTrialParamByFeatureAsDouble(
+ features::kWebRtcHybridAgc, "vad_probability_attack", 1.0);
+ agc2_properties->use_peaks_not_rms =
+ base::GetFieldTrialParamByFeatureAsBool(features::kWebRtcHybridAgc,
+ "use_peaks_not_rms", false);
+ agc2_properties->level_estimator_speech_frames_threshold =
+ base::GetFieldTrialParamByFeatureAsInt(
+ features::kWebRtcHybridAgc,
+ "level_estimator_speech_frames_threshold", 1);
+ agc2_properties->initial_saturation_margin_db =
+ base::GetFieldTrialParamByFeatureAsInt(
+ features::kWebRtcHybridAgc, "initial_saturation_margin", 20);
+ agc2_properties->extra_saturation_margin_db =
+ base::GetFieldTrialParamByFeatureAsInt(features::kWebRtcHybridAgc,
+ "extra_saturation_margin", 5);
+ agc2_properties->gain_applier_speech_frames_threshold =
+ base::GetFieldTrialParamByFeatureAsInt(
+ features::kWebRtcHybridAgc,
+ "gain_applier_speech_frames_threshold", 1);
}
blink::ConfigAutomaticGainControl(
- &apm_config, properties.goog_auto_gain_control,
- properties.goog_experimental_auto_gain_control, use_hybrid_agc,
- use_peaks_not_rms, saturation_margin, gain_control_compression_gain_db);
+ properties.goog_auto_gain_control,
+ properties.goog_experimental_auto_gain_control, agc2_properties,
+ gain_control_compression_gain_db, apm_config);
}
if (goog_typing_detection) {
diff --git a/third_party/blink/renderer/platform/mediastream/media_stream_audio_processor_options.cc b/third_party/blink/renderer/platform/mediastream/media_stream_audio_processor_options.cc
index 32b1d40..1f7ad74 100644
--- a/third_party/blink/renderer/platform/mediastream/media_stream_audio_processor_options.cc
+++ b/third_party/blink/renderer/platform/mediastream/media_stream_audio_processor_options.cc
@@ -185,23 +185,22 @@
}
void ConfigAutomaticGainControl(
- AudioProcessing::Config* apm_config,
bool agc_enabled,
bool experimental_agc_enabled,
- bool use_hybrid_agc,
- base::Optional<bool> hybrid_agc_use_peaks_not_rms,
- base::Optional<int> hybrid_agc_saturation_margin,
- base::Optional<double> compression_gain_db) {
+ base::Optional<AdaptiveGainController2Properties> agc2_properties,
+ base::Optional<double> compression_gain_db,
+ AudioProcessing::Config& apm_config) {
const bool use_fixed_digital_agc2 = agc_enabled &&
!experimental_agc_enabled &&
compression_gain_db.has_value();
+ const bool use_hybrid_agc = agc2_properties.has_value();
const bool agc1_enabled =
agc_enabled && (use_hybrid_agc || !use_fixed_digital_agc2);
// Configure AGC1.
if (agc1_enabled) {
- apm_config->gain_controller1.enabled = true;
- apm_config->gain_controller1.mode =
+ apm_config.gain_controller1.enabled = true;
+ apm_config.gain_controller1.mode =
#if defined(OS_ANDROID)
AudioProcessing::Config::GainController1::Mode::kFixedDigital;
#else
@@ -211,32 +210,44 @@
// Configure AGC2.
if (experimental_agc_enabled) {
- DCHECK(hybrid_agc_use_peaks_not_rms.has_value() &&
- hybrid_agc_saturation_margin.has_value());
// Experimental AGC is enabled. Hybrid AGC may or may not be enabled. Config
// AGC2 with adaptive mode and the given options, while ignoring
// |use_fixed_digital_agc2|.
- apm_config->gain_controller2.enabled = use_hybrid_agc;
- apm_config->gain_controller2.fixed_digital.gain_db = 0.f;
- apm_config->gain_controller2.adaptive_digital.enabled = true;
+ apm_config.gain_controller2.enabled = use_hybrid_agc;
+ apm_config.gain_controller2.fixed_digital.gain_db = 0.f;
+ apm_config.gain_controller2.adaptive_digital.enabled = true;
- using LevelEstimator =
- AudioProcessing::Config::GainController2::LevelEstimator;
- apm_config->gain_controller2.adaptive_digital.level_estimator =
- hybrid_agc_use_peaks_not_rms.value() ? LevelEstimator::kPeak
+ if (use_hybrid_agc) {
+ auto& adaptive_digital = apm_config.gain_controller2.adaptive_digital;
+
+ adaptive_digital.vad_probability_attack =
+ agc2_properties->vad_probability_attack;
+
+ using LevelEstimator =
+ AudioProcessing::Config::GainController2::LevelEstimator;
+ adaptive_digital.level_estimator = agc2_properties->use_peaks_not_rms
+ ? LevelEstimator::kPeak
: LevelEstimator::kRms;
- if (hybrid_agc_saturation_margin.value() != -1) {
- apm_config->gain_controller2.adaptive_digital.extra_saturation_margin_db =
- hybrid_agc_saturation_margin.value();
+ adaptive_digital.level_estimator_adjacent_speech_frames_threshold =
+ agc2_properties->level_estimator_speech_frames_threshold;
+
+ adaptive_digital.initial_saturation_margin_db =
+ agc2_properties->initial_saturation_margin_db;
+
+ adaptive_digital.extra_saturation_margin_db =
+ agc2_properties->extra_saturation_margin_db;
+
+ adaptive_digital.gain_applier_adjacent_speech_frames_threshold =
+ agc2_properties->gain_applier_speech_frames_threshold;
}
} else if (use_fixed_digital_agc2) {
// Experimental AGC is disabled, thus hybrid AGC is disabled. Config AGC2
// with fixed gain mode.
- apm_config->gain_controller2.enabled = true;
- apm_config->gain_controller2.fixed_digital.gain_db =
+ apm_config.gain_controller2.enabled = true;
+ apm_config.gain_controller2.fixed_digital.gain_db =
compression_gain_db.value();
- apm_config->gain_controller2.adaptive_digital.enabled = false;
+ apm_config.gain_controller2.adaptive_digital.enabled = false;
}
}
diff --git a/third_party/blink/renderer/platform/mediastream/media_stream_audio_processor_options.h b/third_party/blink/renderer/platform/mediastream/media_stream_audio_processor_options.h
index f25d1e2..15779e8c 100644
--- a/third_party/blink/renderer/platform/mediastream/media_stream_audio_processor_options.h
+++ b/third_party/blink/renderer/platform/mediastream/media_stream_audio_processor_options.h
@@ -115,15 +115,27 @@
PLATFORM_EXPORT void StopEchoCancellationDump(
AudioProcessing* audio_processing);
-// Enables automatic gain control with flags and optional configures.
+// Adaptive Gain Controller 2 (aka AGC2) properties.
+struct PLATFORM_EXPORT AdaptiveGainController2Properties {
+ float vad_probability_attack;
+ bool use_peaks_not_rms;
+ int level_estimator_speech_frames_threshold;
+ int initial_saturation_margin_db;
+ int extra_saturation_margin_db;
+ int gain_applier_speech_frames_threshold;
+};
+
+// Configures automatic gain control in `apm_config`. If `agc_enabled` is true
+// and `agc2_properties` is specified, the AGC2 adaptive digital replaces the
+// adaptive digital controller of AGC1 - i.e., hybrid configuration (AGC1 analog
+// plus AGC2 adaptive digital).
+// TODO(crbug.com/webrtc/7494): Clean up once hybrid AGC experiment finalized.
PLATFORM_EXPORT void ConfigAutomaticGainControl(
- AudioProcessing::Config* apm_config,
bool agc_enabled,
bool experimental_agc_enabled,
- bool use_hybrid_agc,
- base::Optional<bool> hybrid_agc_use_peaks_not_rms,
- base::Optional<int> hybrid_agc_saturation_margin,
- base::Optional<double> compression_gain_db);
+ base::Optional<AdaptiveGainController2Properties> agc2_properties,
+ base::Optional<double> compression_gain_db,
+ AudioProcessing::Config& apm_config);
PLATFORM_EXPORT void PopulateApmConfig(
AudioProcessing::Config* apm_config,
diff --git a/third_party/blink/renderer/platform/mediastream/media_stream_audio_processor_options_test.cc b/third_party/blink/renderer/platform/mediastream/media_stream_audio_processor_options_test.cc
index 8dcdcd482..84d942f 100644
--- a/third_party/blink/renderer/platform/mediastream/media_stream_audio_processor_options_test.cc
+++ b/third_party/blink/renderer/platform/mediastream/media_stream_audio_processor_options_test.cc
@@ -11,11 +11,11 @@
TEST(ConfigAutomaticGainControlTest, EnableDefaultAGC1) {
webrtc::AudioProcessing::Config apm_config;
- ConfigAutomaticGainControl(&apm_config,
- true, // |agc_enabled|.
- false, // |experimental_agc_enabled|.
- false, // |use_hybrid_agc|.
- base::nullopt, base::nullopt, base::nullopt);
+ ConfigAutomaticGainControl(
+ /*agc_enabled=*/true,
+ /*experimental_agc_enabled=*/false,
+ /*agc2_properties=*/base::nullopt,
+ /*compression_gain_db=*/base::nullopt, apm_config);
EXPECT_TRUE(apm_config.gain_controller1.enabled);
EXPECT_EQ(
apm_config.gain_controller1.mode,
@@ -29,11 +29,10 @@
TEST(ConfigAutomaticGainControlTest, EnableFixedDigitalAGC2) {
webrtc::AudioProcessing::Config apm_config;
const double compression_gain_db = 10.0;
- ConfigAutomaticGainControl(&apm_config,
- true, // |agc_enabled|.
- false, // |experimental_agc_enabled|.
- false, // |use_hybrid_agc|.
- base::nullopt, base::nullopt, compression_gain_db);
+ ConfigAutomaticGainControl(
+ /*agc_enabled=*/true,
+ /*experimental_agc_enabled=*/false,
+ /*agc2_properties=*/base::nullopt, compression_gain_db, apm_config);
EXPECT_FALSE(apm_config.gain_controller1.enabled);
EXPECT_TRUE(apm_config.gain_controller2.enabled);
EXPECT_FALSE(apm_config.gain_controller2.adaptive_digital.enabled);
@@ -43,15 +42,19 @@
TEST(ConfigAutomaticGainControlTest, EnableHybridAGC) {
webrtc::AudioProcessing::Config apm_config;
- const bool use_peaks_not_rms = true;
- const int saturation_margin = 10;
- const double compression_gain_db = 10.0; // Will test that it has no effect.
- ConfigAutomaticGainControl(&apm_config,
- true, // |agc_enabled|.
- true, // |experimental_agc_enabled|.
- true, // |use_hybrid_agc|.
- use_peaks_not_rms, saturation_margin,
- compression_gain_db);
+ blink::AdaptiveGainController2Properties agc2_properties;
+ agc2_properties.vad_probability_attack = 0.2f;
+ agc2_properties.use_peaks_not_rms = true;
+ agc2_properties.level_estimator_speech_frames_threshold = 3;
+ agc2_properties.initial_saturation_margin_db = 10;
+ agc2_properties.extra_saturation_margin_db = 10;
+ agc2_properties.gain_applier_speech_frames_threshold = 5;
+ const double compression_gain_db = 10.0;
+
+ ConfigAutomaticGainControl(
+ /*agc_enabled=*/true,
+ /*experimental_agc_enabled=*/true, agc2_properties, compression_gain_db,
+ apm_config);
EXPECT_TRUE(apm_config.gain_controller1.enabled);
EXPECT_EQ(
apm_config.gain_controller1.mode,
@@ -61,14 +64,24 @@
webrtc::AudioProcessing::Config::GainController1::Mode::kAdaptiveAnalog);
#endif // defined(OS_ANDROID)
EXPECT_TRUE(apm_config.gain_controller2.enabled);
+ // `compression_gain_db` has no effect when hybrid AGC is active.
EXPECT_EQ(apm_config.gain_controller2.fixed_digital.gain_db, 0);
- EXPECT_TRUE(apm_config.gain_controller2.adaptive_digital.enabled);
+
+ const auto& adaptive_digital = apm_config.gain_controller2.adaptive_digital;
+ EXPECT_TRUE(adaptive_digital.enabled);
+ EXPECT_FLOAT_EQ(adaptive_digital.vad_probability_attack,
+ agc2_properties.vad_probability_attack);
EXPECT_EQ(
- apm_config.gain_controller2.adaptive_digital.level_estimator,
+ adaptive_digital.level_estimator,
webrtc::AudioProcessing::Config::GainController2::LevelEstimator::kPeak);
- EXPECT_EQ(
- apm_config.gain_controller2.adaptive_digital.extra_saturation_margin_db,
- saturation_margin);
+ EXPECT_EQ(adaptive_digital.level_estimator_adjacent_speech_frames_threshold,
+ agc2_properties.level_estimator_speech_frames_threshold);
+ EXPECT_FLOAT_EQ(adaptive_digital.initial_saturation_margin_db,
+ agc2_properties.initial_saturation_margin_db);
+ EXPECT_FLOAT_EQ(adaptive_digital.extra_saturation_margin_db,
+ agc2_properties.extra_saturation_margin_db);
+ EXPECT_EQ(adaptive_digital.gain_applier_adjacent_speech_frames_threshold,
+ agc2_properties.gain_applier_speech_frames_threshold);
}
TEST(PopulateApmConfigTest, DefaultWithoutConfigJson) {