Propagate field trials into AgcManagerDirect

Bug: webrtc:369904700
Change-Id: I8389627f46494f825bcdcb59022ddfa992f74639
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/372381
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Reviewed-by: Sam Zackrisson <saza@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#43722}
This commit is contained in:
Danil Chapovalov 2024-12-20 16:14:22 +01:00 committed by WebRTC LUCI CQ
parent 83861d5649
commit bf4c1bcd94
5 changed files with 164 additions and 207 deletions

View File

@ -25,7 +25,9 @@ rtc_library("agc") {
"..:audio_buffer",
"..:audio_frame_view",
"../../../api:array_view",
"../../../api:field_trials_view",
"../../../api/audio:audio_processing",
"../../../api/environment",
"../../../common_audio",
"../../../common_audio:common_audio_c",
"../../../rtc_base:checks",
@ -106,13 +108,15 @@ if (rtc_include_tests) {
":level_estimation",
"..:mocks",
"../../../api:array_view",
"../../../api:field_trials",
"../../../api/environment",
"../../../api/environment:environment_factory",
"../../../rtc_base:checks",
"../../../rtc_base:random",
"../../../rtc_base:safe_conversions",
"../../../rtc_base:safe_minmax",
"../../../rtc_base:stringutils",
"../../../system_wrappers:metrics",
"../../../test:field_trial",
"../../../test:fileutils",
"../../../test:test_support",
"//testing/gtest",

View File

@ -14,6 +14,8 @@
#include <cmath>
#include "api/array_view.h"
#include "api/environment/environment.h"
#include "api/field_trials_view.h"
#include "common_audio/include/audio_util.h"
#include "modules/audio_processing/agc/gain_control.h"
#include "modules/audio_processing/agc2/gain_map_internal.h"
@ -22,7 +24,6 @@
#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 {
@ -69,14 +70,13 @@ using AnalogAgcConfig =
// string. Returns an unspecified value if the field trial is not specified, if
// disabled or if it cannot be parsed. Example:
// 'WebRTC-Audio-2ndAgcMinMicLevelExperiment/Enabled-80' => returns 80.
std::optional<int> GetMinMicLevelOverride() {
std::optional<int> GetMinMicLevelOverride(const FieldTrialsView& field_trials) {
constexpr char kMinMicLevelFieldTrial[] =
"WebRTC-Audio-2ndAgcMinMicLevelExperiment";
if (!webrtc::field_trial::IsEnabled(kMinMicLevelFieldTrial)) {
if (!field_trials.IsEnabled(kMinMicLevelFieldTrial)) {
return std::nullopt;
}
const auto field_trial_string =
webrtc::field_trial::FindFullName(kMinMicLevelFieldTrial);
const auto field_trial_string = field_trials.Lookup(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) {
@ -447,19 +447,21 @@ void MonoAgc::UpdateCompressor() {
std::atomic<int> AgcManagerDirect::instance_counter_(0);
AgcManagerDirect::AgcManagerDirect(
const Environment& env,
const AudioProcessing::Config::GainController1::AnalogGainController&
analog_config,
Agc* agc)
: AgcManagerDirect(/*num_capture_channels=*/1, analog_config) {
: AgcManagerDirect(env, /*num_capture_channels=*/1, analog_config) {
RTC_DCHECK(channel_agcs_[0]);
RTC_DCHECK(agc);
channel_agcs_[0]->set_agc(agc);
}
AgcManagerDirect::AgcManagerDirect(int num_capture_channels,
AgcManagerDirect::AgcManagerDirect(const Environment& env,
int num_capture_channels,
const AnalogAgcConfig& analog_config)
: analog_controller_enabled_(analog_config.enabled),
min_mic_level_override_(GetMinMicLevelOverride()),
min_mic_level_override_(GetMinMicLevelOverride(env.field_trials())),
data_dumper_(new ApmDataDumper(instance_counter_.fetch_add(1) + 1)),
num_capture_channels_(num_capture_channels),
disable_digital_adaptive_(!analog_config.enable_digital_adaptive),

View File

@ -17,6 +17,7 @@
#include "api/array_view.h"
#include "api/audio/audio_processing.h"
#include "api/environment/environment.h"
#include "modules/audio_processing/agc/agc.h"
#include "modules/audio_processing/agc2/clipping_predictor.h"
#include "modules/audio_processing/audio_buffer.h"
@ -42,6 +43,7 @@ class AgcManagerDirect final {
// passed to `AnalyzePreProcess()` and `Process()`. Clamps
// `analog_config.startup_min_level` in the [12, 255] range.
AgcManagerDirect(
const Environment& env,
int num_capture_channels,
const AudioProcessing::Config::GainController1::AnalogGainController&
analog_config);
@ -142,6 +144,7 @@ class AgcManagerDirect final {
// Ctor that creates a single channel AGC and by injecting `agc`.
// `agc` will be owned by this class; hence, do not delete it.
AgcManagerDirect(
const Environment& env,
const AudioProcessing::Config::GainController1::AnalogGainController&
analog_config,
Agc* agc);

View File

@ -15,12 +15,14 @@
#include <tuple>
#include <vector>
#include "api/environment/environment.h"
#include "api/environment/environment_factory.h"
#include "api/field_trials.h"
#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 "rtc_base/numerics/safe_minmax.h"
#include "rtc_base/strings/string_builder.h"
#include "test/field_trial.h"
#include "test/gmock.h"
#include "test/gtest.h"
#include "test/testsupport/file_utils.h"
@ -78,24 +80,32 @@ class MockGainControl : public GainControl {
MOCK_METHOD(bool, stream_is_saturated, (), (const, override));
};
// TODO(bugs.webrtc.org/12874): Remove and use designated initializers once
// fixed.
// Construction parameters that tests may explicitely specify.
struct AgcManagerDirectTestParams {
std::string field_trials;
int clipped_level_min = kClippedMin;
bool enable_digital_adaptive = false;
int clipped_level_step = kClippedLevelStep;
float clipped_ratio_threshold = kClippedRatioThreshold;
int clipped_wait_frames = kClippedWaitFrames;
AnalogAgcConfig::ClippingPredictor clipping_predictor;
};
std::unique_ptr<AgcManagerDirect> CreateAgcManagerDirect(
int startup_min_volume,
int clipped_level_step,
float clipped_ratio_threshold,
int clipped_wait_frames,
const ClippingPredictorConfig& clipping_predictor_config =
kDefaultAnalogConfig.clipping_predictor) {
AnalogAgcConfig config;
config.startup_min_volume = startup_min_volume;
config.clipped_level_min = kClippedMin;
config.enable_digital_adaptive = false;
config.clipped_level_step = clipped_level_step;
config.clipped_ratio_threshold = clipped_ratio_threshold;
config.clipped_wait_frames = clipped_wait_frames;
config.clipping_predictor = clipping_predictor_config;
return std::make_unique<AgcManagerDirect>(/*num_capture_channels=*/1, config);
AgcManagerDirectTestParams p = {}) {
auto manager = std::make_unique<AgcManagerDirect>(
CreateEnvironment(FieldTrials::CreateNoGlobal(p.field_trials)),
kNumChannels,
AnalogAgcConfig{.startup_min_volume = kInitialInputVolume,
.clipped_level_min = p.clipped_level_min,
.enable_digital_adaptive = p.enable_digital_adaptive,
.clipped_level_step = p.clipped_level_step,
.clipped_ratio_threshold = p.clipped_ratio_threshold,
.clipped_wait_frames = p.clipped_wait_frames,
.clipping_predictor = p.clipping_predictor});
manager->Initialize();
manager->set_stream_analog_level(kInitialInputVolume);
return manager;
}
// Deprecated.
@ -329,7 +339,7 @@ constexpr AnalogAgcConfig GetDisabledAnalogAgcConfig() {
class AgcManagerDirectTestHelper {
public:
// Ctor. Initializes `audio_buffer` with zeros.
AgcManagerDirectTestHelper()
explicit AgcManagerDirectTestHelper(const Environment& env)
: audio_buffer(kSampleRateHz,
kNumChannels,
kSampleRateHz,
@ -337,7 +347,7 @@ class AgcManagerDirectTestHelper {
kSampleRateHz,
kNumChannels),
mock_agc(new ::testing::NiceMock<MockAgc>()),
manager(GetAnalogAgcTestConfig(), mock_agc) {
manager(env, GetAnalogAgcTestConfig(), mock_agc) {
manager.Initialize();
manager.SetupDigitalGainControl(mock_gain_control);
WriteAudioBufferSamples(/*samples_value=*/0.0f, /*clipped_ratio=*/0.0f,
@ -438,8 +448,8 @@ class AgcManagerDirectParametrizedTest
: public ::testing::TestWithParam<std::tuple<std::optional<int>, bool>> {
protected:
AgcManagerDirectParametrizedTest()
: field_trials_(
GetAgcMinMicLevelExperimentFieldTrial(std::get<0>(GetParam()))) {}
: env_(CreateEnvironment(FieldTrials::CreateNoGlobal(
GetAgcMinMicLevelExperimentFieldTrial(std::get<0>(GetParam()))))) {}
bool IsMinMicLevelOverridden() const {
return std::get<0>(GetParam()).has_value();
@ -453,8 +463,7 @@ class AgcManagerDirectParametrizedTest
return IsRmsErrorOverridden() ? std::optional<float>(value) : std::nullopt;
}
private:
test::ScopedFieldTrials field_trials_;
const Environment env_;
};
INSTANTIATE_TEST_SUITE_P(
@ -469,10 +478,10 @@ INSTANTIATE_TEST_SUITE_P(
// differs.
TEST_P(AgcManagerDirectParametrizedTest,
DisabledAnalogAgcDoesNotAdaptDownwards) {
AgcManagerDirect manager_no_analog_agc(kNumChannels,
AgcManagerDirect manager_no_analog_agc(env_, kNumChannels,
GetDisabledAnalogAgcConfig());
manager_no_analog_agc.Initialize();
AgcManagerDirect manager_with_analog_agc(kNumChannels,
AgcManagerDirect manager_with_analog_agc(env_, kNumChannels,
GetAnalogAgcTestConfig());
manager_with_analog_agc.Initialize();
@ -523,10 +532,10 @@ TEST_P(AgcManagerDirectParametrizedTest,
// frames to APM config. The test passes but internally the gain update timing
// differs.
TEST_P(AgcManagerDirectParametrizedTest, DisabledAnalogAgcDoesNotAdaptUpwards) {
AgcManagerDirect manager_no_analog_agc(kNumChannels,
AgcManagerDirect manager_no_analog_agc(env_, kNumChannels,
GetDisabledAnalogAgcConfig());
manager_no_analog_agc.Initialize();
AgcManagerDirect manager_with_analog_agc(kNumChannels,
AgcManagerDirect manager_with_analog_agc(env_, kNumChannels,
GetAnalogAgcTestConfig());
manager_with_analog_agc.Initialize();
@ -552,7 +561,7 @@ TEST_P(AgcManagerDirectParametrizedTest, DisabledAnalogAgcDoesNotAdaptUpwards) {
TEST_P(AgcManagerDirectParametrizedTest,
StartupMinVolumeConfigurationIsRespected) {
AgcManagerDirectTestHelper helper;
AgcManagerDirectTestHelper helper(env_);
helper.CallAgcSequence(kInitialInputVolume,
GetOverrideOrEmpty(kHighSpeechProbability),
GetOverrideOrEmpty(kSpeechLevelDbfs));
@ -563,7 +572,7 @@ TEST_P(AgcManagerDirectParametrizedTest, MicVolumeResponseToRmsError) {
const auto speech_probability_override =
GetOverrideOrEmpty(kHighSpeechProbability);
AgcManagerDirectTestHelper helper;
AgcManagerDirectTestHelper helper(env_);
helper.CallAgcSequence(kInitialInputVolume, speech_probability_override,
GetOverrideOrEmpty(kSpeechLevelDbfs));
@ -626,7 +635,7 @@ TEST_P(AgcManagerDirectParametrizedTest, MicVolumeIsLimited) {
const auto speech_probability_override =
GetOverrideOrEmpty(kHighSpeechProbability);
AgcManagerDirectTestHelper helper;
AgcManagerDirectTestHelper helper(env_);
helper.CallAgcSequence(kInitialInputVolume, speech_probability_override,
GetOverrideOrEmpty(kSpeechLevelDbfs));
@ -708,7 +717,7 @@ TEST_P(AgcManagerDirectParametrizedTest, CompressorStepsTowardsTarget) {
const auto speech_probability_override =
GetOverrideOrEmpty(kHighSpeechProbability);
AgcManagerDirectTestHelper helper;
AgcManagerDirectTestHelper helper(env_);
helper.CallAgcSequence(kInitialInputVolume, speech_probability_override,
GetOverrideOrEmpty(kSpeechLevelDbfs));
@ -780,7 +789,7 @@ TEST_P(AgcManagerDirectParametrizedTest, CompressorErrorIsDeemphasized) {
const auto speech_probability_override =
GetOverrideOrEmpty(kHighSpeechProbability);
AgcManagerDirectTestHelper helper;
AgcManagerDirectTestHelper helper(env_);
helper.CallAgcSequence(kInitialInputVolume, speech_probability_override,
GetOverrideOrEmpty(kSpeechLevelDbfs));
@ -825,7 +834,7 @@ TEST_P(AgcManagerDirectParametrizedTest, CompressorReachesMaximum) {
const auto speech_probability_override =
GetOverrideOrEmpty(kHighSpeechProbability);
AgcManagerDirectTestHelper helper;
AgcManagerDirectTestHelper helper(env_);
helper.CallAgcSequence(kInitialInputVolume, speech_probability_override,
GetOverrideOrEmpty(kSpeechLevelDbfs));
@ -862,7 +871,7 @@ TEST_P(AgcManagerDirectParametrizedTest, CompressorReachesMinimum) {
const auto speech_probability_override =
GetOverrideOrEmpty(kHighSpeechProbability);
AgcManagerDirectTestHelper helper;
AgcManagerDirectTestHelper helper(env_);
helper.CallAgcSequence(kInitialInputVolume, speech_probability_override,
GetOverrideOrEmpty(kSpeechLevelDbfs));
@ -895,7 +904,7 @@ TEST_P(AgcManagerDirectParametrizedTest, CompressorReachesMinimum) {
}
TEST_P(AgcManagerDirectParametrizedTest, NoActionWhileMuted) {
AgcManagerDirectTestHelper helper;
AgcManagerDirectTestHelper helper(env_);
helper.CallAgcSequence(kInitialInputVolume,
GetOverrideOrEmpty(kHighSpeechProbability),
GetOverrideOrEmpty(kSpeechLevelDbfs));
@ -913,7 +922,7 @@ TEST_P(AgcManagerDirectParametrizedTest, NoActionWhileMuted) {
}
TEST_P(AgcManagerDirectParametrizedTest, UnmutingChecksVolumeWithoutRaising) {
AgcManagerDirectTestHelper helper;
AgcManagerDirectTestHelper helper(env_);
helper.CallAgcSequence(kInitialInputVolume,
GetOverrideOrEmpty(kHighSpeechProbability),
GetOverrideOrEmpty(kSpeechLevelDbfs));
@ -934,7 +943,7 @@ TEST_P(AgcManagerDirectParametrizedTest, UnmutingChecksVolumeWithoutRaising) {
}
TEST_P(AgcManagerDirectParametrizedTest, UnmutingRaisesTooLowVolume) {
AgcManagerDirectTestHelper helper;
AgcManagerDirectTestHelper helper(env_);
helper.CallAgcSequence(kInitialInputVolume,
GetOverrideOrEmpty(kHighSpeechProbability),
GetOverrideOrEmpty(kSpeechLevelDbfs));
@ -958,7 +967,7 @@ TEST_P(AgcManagerDirectParametrizedTest,
const auto speech_probability_override =
GetOverrideOrEmpty(kHighSpeechProbability);
AgcManagerDirectTestHelper helper;
AgcManagerDirectTestHelper helper(env_);
helper.CallAgcSequence(kInitialInputVolume, speech_probability_override,
GetOverrideOrEmpty(kSpeechLevelDbfs));
@ -1000,7 +1009,7 @@ TEST_P(AgcManagerDirectParametrizedTest,
const auto speech_probability_override =
GetOverrideOrEmpty(kHighSpeechProbability);
AgcManagerDirectTestHelper helper;
AgcManagerDirectTestHelper helper(env_);
helper.CallAgcSequence(kInitialInputVolume, speech_probability_override,
GetOverrideOrEmpty(kSpeechLevelDbfs));
@ -1048,7 +1057,7 @@ TEST_P(AgcManagerDirectParametrizedTest,
const auto speech_probability_override =
GetOverrideOrEmpty(kHighSpeechProbability);
AgcManagerDirectTestHelper helper;
AgcManagerDirectTestHelper helper(env_);
helper.CallAgcSequence(kInitialInputVolume, speech_probability_override,
GetOverrideOrEmpty(kSpeechLevelDbfs));
@ -1094,7 +1103,7 @@ TEST_P(AgcManagerDirectParametrizedTest,
const auto speech_probability_override =
GetOverrideOrEmpty(kHighSpeechProbability);
AgcManagerDirectTestHelper helper;
AgcManagerDirectTestHelper helper(env_);
helper.CallAgcSequence(kInitialInputVolume, speech_probability_override,
GetOverrideOrEmpty(kSpeechLevelDbfs));
@ -1110,7 +1119,7 @@ TEST_P(AgcManagerDirectParametrizedTest,
}
TEST_P(AgcManagerDirectParametrizedTest, NoClippingHasNoImpact) {
AgcManagerDirectTestHelper helper;
AgcManagerDirectTestHelper helper(env_);
helper.CallAgcSequence(kInitialInputVolume,
GetOverrideOrEmpty(kHighSpeechProbability),
GetOverrideOrEmpty(kSpeechLevelDbfs));
@ -1120,7 +1129,7 @@ TEST_P(AgcManagerDirectParametrizedTest, NoClippingHasNoImpact) {
}
TEST_P(AgcManagerDirectParametrizedTest, ClippingUnderThresholdHasNoImpact) {
AgcManagerDirectTestHelper helper;
AgcManagerDirectTestHelper helper(env_);
helper.CallAgcSequence(kInitialInputVolume,
GetOverrideOrEmpty(kHighSpeechProbability),
GetOverrideOrEmpty(kSpeechLevelDbfs));
@ -1130,7 +1139,7 @@ TEST_P(AgcManagerDirectParametrizedTest, ClippingUnderThresholdHasNoImpact) {
}
TEST_P(AgcManagerDirectParametrizedTest, ClippingLowersVolume) {
AgcManagerDirectTestHelper helper;
AgcManagerDirectTestHelper helper(env_);
helper.CallAgcSequence(/*applied_input_volume=*/255,
GetOverrideOrEmpty(kHighSpeechProbability),
GetOverrideOrEmpty(kSpeechLevelDbfs));
@ -1141,7 +1150,7 @@ TEST_P(AgcManagerDirectParametrizedTest, ClippingLowersVolume) {
}
TEST_P(AgcManagerDirectParametrizedTest, WaitingPeriodBetweenClippingChecks) {
AgcManagerDirectTestHelper helper;
AgcManagerDirectTestHelper helper(env_);
helper.CallAgcSequence(/*applied_input_volume=*/255,
GetOverrideOrEmpty(kHighSpeechProbability),
GetOverrideOrEmpty(kSpeechLevelDbfs));
@ -1161,7 +1170,7 @@ TEST_P(AgcManagerDirectParametrizedTest, WaitingPeriodBetweenClippingChecks) {
}
TEST_P(AgcManagerDirectParametrizedTest, ClippingLoweringIsLimited) {
AgcManagerDirectTestHelper helper;
AgcManagerDirectTestHelper helper(env_);
helper.CallAgcSequence(/*applied_input_volume=*/180,
GetOverrideOrEmpty(kHighSpeechProbability),
GetOverrideOrEmpty(kSpeechLevelDbfs));
@ -1181,7 +1190,7 @@ TEST_P(AgcManagerDirectParametrizedTest,
const auto speech_probability_override =
GetOverrideOrEmpty(kHighSpeechProbability);
AgcManagerDirectTestHelper helper;
AgcManagerDirectTestHelper helper(env_);
helper.CallAgcSequence(/*applied_input_volume=*/255,
speech_probability_override,
GetOverrideOrEmpty(kSpeechLevelDbfs));
@ -1202,7 +1211,7 @@ TEST_P(AgcManagerDirectParametrizedTest,
const auto speech_probability_override =
GetOverrideOrEmpty(kHighSpeechProbability);
AgcManagerDirectTestHelper helper;
AgcManagerDirectTestHelper helper(env_);
helper.CallAgcSequence(/*applied_input_volume=*/200,
speech_probability_override,
GetOverrideOrEmpty(kSpeechLevelDbfs));
@ -1227,7 +1236,7 @@ TEST_P(AgcManagerDirectParametrizedTest,
const auto speech_probability_override =
GetOverrideOrEmpty(kHighSpeechProbability);
AgcManagerDirectTestHelper helper;
AgcManagerDirectTestHelper helper(env_);
helper.CallAgcSequence(/*applied_input_volume=*/210,
speech_probability_override,
GetOverrideOrEmpty(kSpeechLevelDbfs));
@ -1324,7 +1333,7 @@ TEST_P(AgcManagerDirectParametrizedTest, UserCanRaiseVolumeAfterClipping) {
const auto speech_probability_override =
GetOverrideOrEmpty(kHighSpeechProbability);
AgcManagerDirectTestHelper helper;
AgcManagerDirectTestHelper helper(env_);
helper.CallAgcSequence(/*applied_input_volume=*/225,
speech_probability_override,
GetOverrideOrEmpty(kSpeechLevelDbfs));
@ -1364,7 +1373,7 @@ TEST_P(AgcManagerDirectParametrizedTest, UserCanRaiseVolumeAfterClipping) {
}
TEST_P(AgcManagerDirectParametrizedTest, ClippingDoesNotPullLowVolumeBackUp) {
AgcManagerDirectTestHelper helper;
AgcManagerDirectTestHelper helper(env_);
helper.CallAgcSequence(/*applied_input_volume=*/80,
GetOverrideOrEmpty(kHighSpeechProbability),
GetOverrideOrEmpty(kSpeechLevelDbfs));
@ -1376,7 +1385,7 @@ TEST_P(AgcManagerDirectParametrizedTest, ClippingDoesNotPullLowVolumeBackUp) {
}
TEST_P(AgcManagerDirectParametrizedTest, TakesNoActionOnZeroMicVolume) {
AgcManagerDirectTestHelper helper;
AgcManagerDirectTestHelper helper(env_);
helper.CallAgcSequence(kInitialInputVolume,
GetOverrideOrEmpty(kHighSpeechProbability),
GetOverrideOrEmpty(kSpeechLevelDbfs));
@ -1391,7 +1400,7 @@ TEST_P(AgcManagerDirectParametrizedTest, TakesNoActionOnZeroMicVolume) {
}
TEST_P(AgcManagerDirectParametrizedTest, ClippingDetectionLowersVolume) {
AgcManagerDirectTestHelper helper;
AgcManagerDirectTestHelper helper(env_);
helper.CallAgcSequence(/*applied_input_volume=*/255,
GetOverrideOrEmpty(kHighSpeechProbability),
GetOverrideOrEmpty(kSpeechLevelDbfs));
@ -1405,7 +1414,7 @@ TEST_P(AgcManagerDirectParametrizedTest, ClippingDetectionLowersVolume) {
TEST_P(AgcManagerDirectParametrizedTest,
DisabledClippingPredictorDoesNotLowerVolume) {
AgcManagerDirectTestHelper helper;
AgcManagerDirectTestHelper helper(env_);
helper.CallAgcSequence(/*applied_input_volume=*/255,
GetOverrideOrEmpty(kHighSpeechProbability),
GetOverrideOrEmpty(kSpeechLevelDbfs));
@ -1432,25 +1441,21 @@ TEST_P(AgcManagerDirectParametrizedTest, DisableDigitalDisablesDigital) {
AnalogAgcConfig config;
config.enable_digital_adaptive = false;
auto manager = std::make_unique<AgcManagerDirect>(kNumChannels, config);
auto manager = std::make_unique<AgcManagerDirect>(env_, kNumChannels, config);
manager->Initialize();
manager->SetupDigitalGainControl(mock_gain_control);
}
TEST(AgcManagerDirectTest, AgcMinMicLevelExperimentDefault) {
std::unique_ptr<AgcManagerDirect> manager =
CreateAgcManagerDirect(kInitialInputVolume, kClippedLevelStep,
kClippedRatioThreshold, kClippedWaitFrames);
std::unique_ptr<AgcManagerDirect> manager = CreateAgcManagerDirect();
EXPECT_EQ(manager->channel_agcs_[0]->min_mic_level(), kMinMicLevel);
}
TEST(AgcManagerDirectTest, AgcMinMicLevelExperimentDisabled) {
for (const std::string& field_trial_suffix : {"", "_20220210"}) {
test::ScopedFieldTrials field_trial(
GetAgcMinMicLevelExperimentFieldTrial("Disabled" + field_trial_suffix));
std::unique_ptr<AgcManagerDirect> manager =
CreateAgcManagerDirect(kInitialInputVolume, kClippedLevelStep,
kClippedRatioThreshold, kClippedWaitFrames);
std::unique_ptr<AgcManagerDirect> manager = CreateAgcManagerDirect(
{.field_trials = GetAgcMinMicLevelExperimentFieldTrial(
"Disabled" + field_trial_suffix)});
EXPECT_EQ(manager->channel_agcs_[0]->min_mic_level(), kMinMicLevel);
}
}
@ -1458,22 +1463,16 @@ TEST(AgcManagerDirectTest, AgcMinMicLevelExperimentDisabled) {
// Checks that a field-trial parameter outside of the valid range [0,255] is
// ignored.
TEST(AgcManagerDirectTest, AgcMinMicLevelExperimentOutOfRangeAbove) {
test::ScopedFieldTrials field_trial(
GetAgcMinMicLevelExperimentFieldTrial("Enabled-256"));
std::unique_ptr<AgcManagerDirect> manager =
CreateAgcManagerDirect(kInitialInputVolume, kClippedLevelStep,
kClippedRatioThreshold, kClippedWaitFrames);
std::unique_ptr<AgcManagerDirect> manager = CreateAgcManagerDirect(
{.field_trials = GetAgcMinMicLevelExperimentFieldTrial("Enabled-256")});
EXPECT_EQ(manager->channel_agcs_[0]->min_mic_level(), kMinMicLevel);
}
// Checks that a field-trial parameter outside of the valid range [0,255] is
// ignored.
TEST(AgcManagerDirectTest, AgcMinMicLevelExperimentOutOfRangeBelow) {
test::ScopedFieldTrials field_trial(
GetAgcMinMicLevelExperimentFieldTrial("Enabled--1"));
std::unique_ptr<AgcManagerDirect> manager =
CreateAgcManagerDirect(kInitialInputVolume, kClippedLevelStep,
kClippedRatioThreshold, kClippedWaitFrames);
std::unique_ptr<AgcManagerDirect> manager = CreateAgcManagerDirect(
{.field_trials = GetAgcMinMicLevelExperimentFieldTrial("Enabled--1")});
EXPECT_EQ(manager->channel_agcs_[0]->min_mic_level(), kMinMicLevel);
}
@ -1484,12 +1483,11 @@ TEST(AgcManagerDirectTest, AgcMinMicLevelExperimentEnabled50) {
constexpr int kMinMicLevelOverride = 50;
for (const std::string& field_trial_suffix : {"", "_20220210"}) {
SCOPED_TRACE(field_trial_suffix);
test::ScopedFieldTrials field_trial(
GetAgcMinMicLevelExperimentFieldTrialEnabled(kMinMicLevelOverride,
field_trial_suffix));
std::unique_ptr<AgcManagerDirect> manager =
CreateAgcManagerDirect(kInitialInputVolume, kClippedLevelStep,
kClippedRatioThreshold, kClippedWaitFrames);
std::unique_ptr<AgcManagerDirect> manager = CreateAgcManagerDirect(
{.field_trials = GetAgcMinMicLevelExperimentFieldTrialEnabled(
kMinMicLevelOverride, field_trial_suffix)});
EXPECT_EQ(manager->channel_agcs_[0]->min_mic_level(), kMinMicLevelOverride);
}
}
@ -1502,21 +1500,11 @@ TEST(AgcManagerDirectTest, AgcMinMicLevelExperimentCheckMinLevelWithClipping) {
// Create and initialize two AGCs by specifying and leaving unspecified the
// relevant field trial.
const auto factory = []() {
std::unique_ptr<AgcManagerDirect> manager =
CreateAgcManagerDirect(kInitialInputVolume, kClippedLevelStep,
kClippedRatioThreshold, kClippedWaitFrames);
manager->Initialize();
manager->set_stream_analog_level(kInitialInputVolume);
return manager;
};
std::unique_ptr<AgcManagerDirect> manager = factory();
std::unique_ptr<AgcManagerDirect> manager_with_override;
{
test::ScopedFieldTrials field_trial(
GetAgcMinMicLevelExperimentFieldTrialEnabled(kMinMicLevelOverride));
manager_with_override = factory();
}
std::unique_ptr<AgcManagerDirect> manager = CreateAgcManagerDirect();
std::unique_ptr<AgcManagerDirect> manager_with_override =
CreateAgcManagerDirect(
{.field_trials = GetAgcMinMicLevelExperimentFieldTrialEnabled(
kMinMicLevelOverride)});
// Create a test input signal which containts 80% of clipped samples.
AudioBuffer audio_buffer(kSampleRateHz, 1, kSampleRateHz, 1, kSampleRateHz,
@ -1559,21 +1547,11 @@ TEST(AgcManagerDirectTest,
// Create and initialize two AGCs by specifying and leaving unspecified the
// relevant field trial.
const auto factory = []() {
std::unique_ptr<AgcManagerDirect> manager =
CreateAgcManagerDirect(kInitialInputVolume, kClippedLevelStep,
kClippedRatioThreshold, kClippedWaitFrames);
manager->Initialize();
manager->set_stream_analog_level(kInitialInputVolume);
return manager;
};
std::unique_ptr<AgcManagerDirect> manager = factory();
std::unique_ptr<AgcManagerDirect> manager_with_override;
{
test::ScopedFieldTrials field_trial(
GetAgcMinMicLevelExperimentFieldTrialEnabled(kMinMicLevelOverride));
manager_with_override = factory();
}
std::unique_ptr<AgcManagerDirect> manager = CreateAgcManagerDirect();
std::unique_ptr<AgcManagerDirect> manager_with_override =
CreateAgcManagerDirect(
{.field_trials = GetAgcMinMicLevelExperimentFieldTrialEnabled(
kMinMicLevelOverride)});
// Create a test input signal which containts 80% of clipped samples.
AudioBuffer audio_buffer(kSampleRateHz, 1, kSampleRateHz, 1, kSampleRateHz,
@ -1614,32 +1592,25 @@ TEST(AgcManagerDirectTest,
AgcMinMicLevelExperimentCompareMicLevelWithClipping) {
// Create and initialize two AGCs by specifying and leaving unspecified the
// relevant field trial.
const auto factory = []() {
// Use a large clipped level step to more quickly decrease the analog gain
// with clipping.
AnalogAgcConfig config = kDefaultAnalogConfig;
config.startup_min_volume = kInitialInputVolume;
config.enable_digital_adaptive = false;
config.clipped_level_step = 64;
config.clipped_ratio_threshold = kClippedRatioThreshold;
config.clipped_wait_frames = kClippedWaitFrames;
auto controller =
std::make_unique<AgcManagerDirect>(/*num_capture_channels=*/1, config);
controller->Initialize();
controller->set_stream_analog_level(kInitialInputVolume);
return controller;
};
std::unique_ptr<AgcManagerDirect> manager = factory();
std::unique_ptr<AgcManagerDirect> manager_with_override;
{
std::unique_ptr<AgcManagerDirect> manager = CreateAgcManagerDirect({
.clipped_level_min = kDefaultAnalogConfig.clipped_level_min,
.enable_digital_adaptive = false,
.clipped_level_step = 64,
});
constexpr int kMinMicLevelOverride = 20;
static_assert(
kDefaultAnalogConfig.clipped_level_min >= kMinMicLevelOverride,
static_assert(kDefaultAnalogConfig.clipped_level_min >= kMinMicLevelOverride,
"Use a lower override value.");
test::ScopedFieldTrials field_trial(
GetAgcMinMicLevelExperimentFieldTrialEnabled(kMinMicLevelOverride));
manager_with_override = factory();
}
std::unique_ptr<AgcManagerDirect> manager_with_override =
CreateAgcManagerDirect({
.field_trials = GetAgcMinMicLevelExperimentFieldTrialEnabled(
kMinMicLevelOverride),
.clipped_level_min = kDefaultAnalogConfig.clipped_level_min,
.enable_digital_adaptive = false,
.clipped_level_step = 64,
});
// Create a test input signal which containts 80% of clipped samples.
AudioBuffer audio_buffer(kSampleRateHz, 1, kSampleRateHz, 1, kSampleRateHz,
@ -1681,32 +1652,23 @@ TEST(AgcManagerDirectTest,
AgcMinMicLevelExperimentCompareMicLevelWithClippingWithRmsErrorOverride) {
// Create and initialize two AGCs by specifying and leaving unspecified the
// relevant field trial.
const auto factory = []() {
// Use a large clipped level step to more quickly decrease the analog gain
// with clipping.
AnalogAgcConfig config = kDefaultAnalogConfig;
config.startup_min_volume = kInitialInputVolume;
config.enable_digital_adaptive = false;
config.clipped_level_step = 64;
config.clipped_ratio_threshold = kClippedRatioThreshold;
config.clipped_wait_frames = kClippedWaitFrames;
auto controller =
std::make_unique<AgcManagerDirect>(/*num_capture_channels=*/1, config);
controller->Initialize();
controller->set_stream_analog_level(kInitialInputVolume);
return controller;
};
std::unique_ptr<AgcManagerDirect> manager = factory();
std::unique_ptr<AgcManagerDirect> manager_with_override;
{
std::unique_ptr<AgcManagerDirect> manager = CreateAgcManagerDirect({
.clipped_level_min = kDefaultAnalogConfig.clipped_level_min,
.enable_digital_adaptive = false,
.clipped_level_step = 64,
});
constexpr int kMinMicLevelOverride = 20;
static_assert(
kDefaultAnalogConfig.clipped_level_min >= kMinMicLevelOverride,
static_assert(kDefaultAnalogConfig.clipped_level_min >= kMinMicLevelOverride,
"Use a lower override value.");
test::ScopedFieldTrials field_trial(
GetAgcMinMicLevelExperimentFieldTrialEnabled(kMinMicLevelOverride));
manager_with_override = factory();
}
std::unique_ptr<AgcManagerDirect> manager_with_override =
CreateAgcManagerDirect({
.field_trials = GetAgcMinMicLevelExperimentFieldTrialEnabled(
kMinMicLevelOverride),
.clipped_level_min = kDefaultAnalogConfig.clipped_level_min,
.enable_digital_adaptive = false,
.clipped_level_step = 64,
});
// Create a test input signal which containts 80% of clipped samples.
AudioBuffer audio_buffer(kSampleRateHz, 1, kSampleRateHz, 1, kSampleRateHz,
@ -1746,19 +1708,15 @@ TEST_P(AgcManagerDirectParametrizedTest, ClippingParametersVerified) {
GTEST_SKIP() << "Skipped. RMS error override does not affect the test.";
}
std::unique_ptr<AgcManagerDirect> manager =
CreateAgcManagerDirect(kInitialInputVolume, kClippedLevelStep,
kClippedRatioThreshold, kClippedWaitFrames);
manager->Initialize();
std::unique_ptr<AgcManagerDirect> manager = CreateAgcManagerDirect();
EXPECT_EQ(manager->clipped_level_step_, kClippedLevelStep);
EXPECT_EQ(manager->clipped_ratio_threshold_, kClippedRatioThreshold);
EXPECT_EQ(manager->clipped_wait_frames_, kClippedWaitFrames);
std::unique_ptr<AgcManagerDirect> manager_custom =
CreateAgcManagerDirect(kInitialInputVolume,
/*clipped_level_step=*/10,
/*clipped_ratio_threshold=*/0.2f,
/*clipped_wait_frames=*/50);
manager_custom->Initialize();
CreateAgcManagerDirect({.clipped_level_step = 10,
.clipped_ratio_threshold = 0.2f,
.clipped_wait_frames = 50});
EXPECT_EQ(manager_custom->clipped_level_step_, 10);
EXPECT_EQ(manager_custom->clipped_ratio_threshold_, 0.2f);
EXPECT_EQ(manager_custom->clipped_wait_frames_, 50);
@ -1770,14 +1728,9 @@ TEST_P(AgcManagerDirectParametrizedTest,
GTEST_SKIP() << "Skipped. RMS error override does not affect the test.";
}
// TODO(bugs.webrtc.org/12874): Use designated initializers once fixed.
ClippingPredictorConfig config;
config.enabled = false;
std::unique_ptr<AgcManagerDirect> manager =
CreateAgcManagerDirect({.clipping_predictor = {.enabled = false}});
std::unique_ptr<AgcManagerDirect> manager = CreateAgcManagerDirect(
kInitialInputVolume, kClippedLevelStep, kClippedRatioThreshold,
kClippedWaitFrames, config);
manager->Initialize();
EXPECT_FALSE(manager->clipping_predictor_enabled());
EXPECT_FALSE(manager->use_clipping_predictor_step());
}
@ -1797,15 +1750,9 @@ TEST_P(AgcManagerDirectParametrizedTest,
GTEST_SKIP() << "Skipped. RMS error override does not affect the test.";
}
// TODO(bugs.webrtc.org/12874): Use designated initializers once fixed.
ClippingPredictorConfig config;
config.enabled = true;
config.use_predicted_step = true;
std::unique_ptr<AgcManagerDirect> manager = CreateAgcManagerDirect(
kInitialInputVolume, kClippedLevelStep, kClippedRatioThreshold,
kClippedWaitFrames, config);
manager->Initialize();
{.clipping_predictor = {.enabled = true, .use_predicted_step = true}});
EXPECT_TRUE(manager->clipping_predictor_enabled());
EXPECT_TRUE(manager->use_clipping_predictor_step());
}
@ -1817,7 +1764,7 @@ TEST_P(AgcManagerDirectParametrizedTest,
AnalogAgcConfig config = GetAnalogAgcTestConfig();
config.clipping_predictor.enabled = false;
AgcManagerDirect manager(config, new ::testing::NiceMock<MockAgc>());
AgcManagerDirect manager(env_, config, new ::testing::NiceMock<MockAgc>());
manager.Initialize();
manager.set_stream_analog_level(/*level=*/255);
EXPECT_FALSE(manager.clipping_predictor_enabled());
@ -1843,10 +1790,10 @@ TEST_P(AgcManagerDirectParametrizedTest,
config_with_prediction.clipping_predictor.use_predicted_step = true;
AnalogAgcConfig config_without_prediction = GetAnalogAgcTestConfig();
config_without_prediction.clipping_predictor.enabled = false;
AgcManagerDirect manager_with_prediction(config_with_prediction,
AgcManagerDirect manager_with_prediction(env_, config_with_prediction,
new ::testing::NiceMock<MockAgc>());
AgcManagerDirect manager_without_prediction(
config_without_prediction, new ::testing::NiceMock<MockAgc>());
env_, config_without_prediction, new ::testing::NiceMock<MockAgc>());
manager_with_prediction.Initialize();
manager_without_prediction.Initialize();
@ -1951,10 +1898,10 @@ TEST_P(AgcManagerDirectParametrizedTest,
config_with_prediction.clipping_predictor.use_predicted_step = false;
AnalogAgcConfig config_without_prediction = GetAnalogAgcTestConfig();
config_without_prediction.clipping_predictor.enabled = false;
AgcManagerDirect manager_with_prediction(config_with_prediction,
AgcManagerDirect manager_with_prediction(env_, config_with_prediction,
new ::testing::NiceMock<MockAgc>());
AgcManagerDirect manager_without_prediction(
config_without_prediction, new ::testing::NiceMock<MockAgc>());
env_, config_without_prediction, new ::testing::NiceMock<MockAgc>());
constexpr int kInitialLevel = 255;
constexpr float kClippingPeakRatio = 1.0f;
@ -2038,8 +1985,8 @@ TEST_P(AgcManagerDirectParametrizedTest,
// Checks that passing an empty speech level and probability overrides to
// `Process()` has the same effect as passing no overrides.
TEST_P(AgcManagerDirectParametrizedTest, EmptyRmsErrorOverrideHasNoEffect) {
AgcManagerDirect manager_1(kNumChannels, GetAnalogAgcTestConfig());
AgcManagerDirect manager_2(kNumChannels, GetAnalogAgcTestConfig());
AgcManagerDirect manager_1(env_, kNumChannels, GetAnalogAgcTestConfig());
AgcManagerDirect manager_2(env_, kNumChannels, GetAnalogAgcTestConfig());
manager_1.Initialize();
manager_2.Initialize();
@ -2080,8 +2027,8 @@ TEST_P(AgcManagerDirectParametrizedTest, EmptyRmsErrorOverrideHasNoEffect) {
// Checks that passing a non-empty speech level and probability overrides to
// `Process()` has an effect.
TEST_P(AgcManagerDirectParametrizedTest, NonEmptyRmsErrorOverrideHasEffect) {
AgcManagerDirect manager_1(kNumChannels, GetAnalogAgcTestConfig());
AgcManagerDirect manager_2(kNumChannels, GetAnalogAgcTestConfig());
AgcManagerDirect manager_1(env_, kNumChannels, GetAnalogAgcTestConfig());
AgcManagerDirect manager_2(env_, kNumChannels, GetAnalogAgcTestConfig());
manager_1.Initialize();
manager_2.Initialize();
@ -2125,7 +2072,7 @@ TEST_P(AgcManagerDirectChannelSampleRateTest, CheckIsAlive) {
constexpr AnalogAgcConfig kConfig{.enabled = true,
.clipping_predictor{.enabled = true}};
AgcManagerDirect manager(num_channels, kConfig);
AgcManagerDirect manager(CreateEnvironment(), num_channels, kConfig);
manager.Initialize();
AudioBuffer buffer(sample_rate_hz, num_channels, sample_rate_hz, num_channels,
sample_rate_hz, num_channels);

View File

@ -2017,8 +2017,9 @@ void AudioProcessingImpl::InitializeGainController1() {
if (re_creation) {
stream_analog_level = submodules_.agc_manager->recommended_analog_level();
}
submodules_.agc_manager.reset(new AgcManagerDirect(
num_proc_channels(), config_.gain_controller1.analog_gain_controller));
submodules_.agc_manager = std::make_unique<AgcManagerDirect>(
env_, num_proc_channels(),
config_.gain_controller1.analog_gain_controller);
if (re_creation) {
submodules_.agc_manager->set_stream_analog_level(stream_analog_level);
}