AgcManagerDirect ctor API and doc string improved

Bug: chromium:1275566
Change-Id: Iedc8f5cbbf65fbf018da9df1aaa1f8ade1bbc063
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/268840
Reviewed-by: Hanna Silen <silen@webrtc.org>
Commit-Queue: Alessio Bazzica <alessiob@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#37569}
This commit is contained in:
Alessio Bazzica 2022-07-19 12:18:38 +02:00 committed by WebRTC LUCI CQ
parent ba5700171f
commit 866caeb62c
6 changed files with 137 additions and 162 deletions

View File

@ -24,6 +24,7 @@ rtc_library("agc") {
":gain_control_interface", ":gain_control_interface",
":gain_map", ":gain_map",
":level_estimation", ":level_estimation",
"..:api",
"..:apm_logging", "..:apm_logging",
"..:audio_buffer", "..:audio_buffer",
"..:audio_frame_view", "..:audio_frame_view",

View File

@ -53,8 +53,8 @@ constexpr int kSurplusCompressionGain = 6;
// frames). // frames).
constexpr int kClippingPredictorEvaluatorHistorySize = 500; constexpr int kClippingPredictorEvaluatorHistorySize = 500;
using ClippingPredictorConfig = AudioProcessing::Config::GainController1:: using AnalogAgcConfig =
AnalogGainController::ClippingPredictor; AudioProcessing::Config::GainController1::AnalogGainController;
// Returns whether a fall-back solution to choose the maximum level should be // Returns whether a fall-back solution to choose the maximum level should be
// chosen. // chosen.
@ -441,51 +441,35 @@ void MonoAgc::UpdateCompressor() {
std::atomic<int> AgcManagerDirect::instance_counter_(0); std::atomic<int> AgcManagerDirect::instance_counter_(0);
AgcManagerDirect::AgcManagerDirect( AgcManagerDirect::AgcManagerDirect(
Agc* agc, const AudioProcessing::Config::GainController1::AnalogGainController&
int startup_min_level, analog_config,
int clipped_level_min, Agc* agc)
int clipped_level_step, : AgcManagerDirect(/*num_capture_channels=*/1, analog_config) {
float clipped_ratio_threshold,
int clipped_wait_frames,
const ClippingPredictorConfig& clipping_config)
: AgcManagerDirect(/*num_capture_channels=*/1,
startup_min_level,
clipped_level_min,
/*disable_digital_adaptive=*/false,
clipped_level_step,
clipped_ratio_threshold,
clipped_wait_frames,
clipping_config) {
RTC_DCHECK(channel_agcs_[0]); RTC_DCHECK(channel_agcs_[0]);
RTC_DCHECK(agc); RTC_DCHECK(agc);
channel_agcs_[0]->set_agc(agc); channel_agcs_[0]->set_agc(agc);
} }
AgcManagerDirect::AgcManagerDirect( AgcManagerDirect::AgcManagerDirect(int num_capture_channels,
int num_capture_channels, const AnalogAgcConfig& analog_config)
int startup_min_level,
int clipped_level_min,
bool disable_digital_adaptive,
int clipped_level_step,
float clipped_ratio_threshold,
int clipped_wait_frames,
const ClippingPredictorConfig& clipping_config)
: min_mic_level_override_(GetMinMicLevelOverride()), : min_mic_level_override_(GetMinMicLevelOverride()),
data_dumper_(new ApmDataDumper(instance_counter_.fetch_add(1) + 1)), data_dumper_(new ApmDataDumper(instance_counter_.fetch_add(1) + 1)),
use_min_channel_level_(!UseMaxAnalogChannelLevel()), use_min_channel_level_(!UseMaxAnalogChannelLevel()),
num_capture_channels_(num_capture_channels), num_capture_channels_(num_capture_channels),
disable_digital_adaptive_(disable_digital_adaptive), disable_digital_adaptive_(!analog_config.enable_digital_adaptive),
frames_since_clipped_(clipped_wait_frames), frames_since_clipped_(analog_config.clipped_wait_frames),
capture_output_used_(true), capture_output_used_(true),
clipped_level_step_(clipped_level_step), clipped_level_step_(analog_config.clipped_level_step),
clipped_ratio_threshold_(clipped_ratio_threshold), clipped_ratio_threshold_(analog_config.clipped_ratio_threshold),
clipped_wait_frames_(clipped_wait_frames), clipped_wait_frames_(analog_config.clipped_wait_frames),
channel_agcs_(num_capture_channels), channel_agcs_(num_capture_channels),
new_compressions_to_set_(num_capture_channels), new_compressions_to_set_(num_capture_channels),
clipping_predictor_( clipping_predictor_(
CreateClippingPredictor(num_capture_channels, clipping_config)), CreateClippingPredictor(num_capture_channels,
use_clipping_predictor_step_(!!clipping_predictor_ && analog_config.clipping_predictor)),
clipping_config.use_predicted_step), use_clipping_predictor_step_(
!!clipping_predictor_ &&
analog_config.clipping_predictor.use_predicted_step),
clipping_predictor_evaluator_(kClippingPredictorEvaluatorHistorySize), clipping_predictor_evaluator_(kClippingPredictorEvaluatorHistorySize),
clipping_predictor_log_counter_(0), clipping_predictor_log_counter_(0),
clipping_rate_log_(0.0f), clipping_rate_log_(0.0f),
@ -499,15 +483,16 @@ AgcManagerDirect::AgcManagerDirect(
ApmDataDumper* data_dumper_ch = ch == 0 ? data_dumper_.get() : nullptr; ApmDataDumper* data_dumper_ch = ch == 0 ? data_dumper_.get() : nullptr;
channel_agcs_[ch] = std::make_unique<MonoAgc>( channel_agcs_[ch] = std::make_unique<MonoAgc>(
data_dumper_ch, startup_min_level, clipped_level_min, data_dumper_ch, analog_config.startup_min_volume,
disable_digital_adaptive_, min_mic_level); analog_config.clipped_level_min, disable_digital_adaptive_,
min_mic_level);
} }
RTC_DCHECK(!channel_agcs_.empty()); RTC_DCHECK(!channel_agcs_.empty());
RTC_DCHECK_GT(clipped_level_step, 0); RTC_DCHECK_GT(clipped_level_step_, 0);
RTC_DCHECK_LE(clipped_level_step, 255); RTC_DCHECK_LE(clipped_level_step_, 255);
RTC_DCHECK_GT(clipped_ratio_threshold, 0.f); RTC_DCHECK_GT(clipped_ratio_threshold_, 0.0f);
RTC_DCHECK_LT(clipped_ratio_threshold, 1.f); RTC_DCHECK_LT(clipped_ratio_threshold_, 1.0f);
RTC_DCHECK_GT(clipped_wait_frames, 0); RTC_DCHECK_GT(clipped_wait_frames_, 0);
channel_agcs_[0]->ActivateLogging(); channel_agcs_[0]->ActivateLogging();
} }
@ -529,22 +514,21 @@ void AgcManagerDirect::Initialize() {
} }
void AgcManagerDirect::SetupDigitalGainControl( void AgcManagerDirect::SetupDigitalGainControl(
GainControl* gain_control) const { GainControl& gain_control) const {
RTC_DCHECK(gain_control); if (gain_control.set_mode(GainControl::kFixedDigital) != 0) {
if (gain_control->set_mode(GainControl::kFixedDigital) != 0) {
RTC_LOG(LS_ERROR) << "set_mode(GainControl::kFixedDigital) failed."; RTC_LOG(LS_ERROR) << "set_mode(GainControl::kFixedDigital) failed.";
} }
const int target_level_dbfs = disable_digital_adaptive_ ? 0 : 2; const int target_level_dbfs = disable_digital_adaptive_ ? 0 : 2;
if (gain_control->set_target_level_dbfs(target_level_dbfs) != 0) { if (gain_control.set_target_level_dbfs(target_level_dbfs) != 0) {
RTC_LOG(LS_ERROR) << "set_target_level_dbfs() failed."; RTC_LOG(LS_ERROR) << "set_target_level_dbfs() failed.";
} }
const int compression_gain_db = const int compression_gain_db =
disable_digital_adaptive_ ? 0 : kDefaultCompressionGain; disable_digital_adaptive_ ? 0 : kDefaultCompressionGain;
if (gain_control->set_compression_gain_db(compression_gain_db) != 0) { if (gain_control.set_compression_gain_db(compression_gain_db) != 0) {
RTC_LOG(LS_ERROR) << "set_compression_gain_db() failed."; RTC_LOG(LS_ERROR) << "set_compression_gain_db() failed.";
} }
const bool enable_limiter = !disable_digital_adaptive_; const bool enable_limiter = !disable_digital_adaptive_;
if (gain_control->enable_limiter(enable_limiter) != 0) { if (gain_control.enable_limiter(enable_limiter) != 0) {
RTC_LOG(LS_ERROR) << "enable_limiter() failed."; RTC_LOG(LS_ERROR) << "enable_limiter() failed.";
} }
} }

View File

@ -20,6 +20,7 @@
#include "modules/audio_processing/agc/clipping_predictor.h" #include "modules/audio_processing/agc/clipping_predictor.h"
#include "modules/audio_processing/agc/clipping_predictor_evaluator.h" #include "modules/audio_processing/agc/clipping_predictor_evaluator.h"
#include "modules/audio_processing/audio_buffer.h" #include "modules/audio_processing/audio_buffer.h"
#include "modules/audio_processing/include/audio_processing.h"
#include "modules/audio_processing/logging/apm_data_dumper.h" #include "modules/audio_processing/logging/apm_data_dumper.h"
#include "rtc_base/gtest_prod_util.h" #include "rtc_base/gtest_prod_util.h"
@ -28,53 +29,60 @@ namespace webrtc {
class MonoAgc; class MonoAgc;
class GainControl; class GainControl;
// Direct interface to use AGC to set volume and compression values. // Adaptive Gain Controller (AGC) that combines an analog and digital gain
// AudioProcessing uses this interface directly to integrate the callback-less // controller. The digital controller determines and applies the digital
// AGC. // compression gain. The analog controller recommends what input volume (a.k.a.,
// // analog level) to use, handles input volume changes and input clipping. In
// This class is not thread-safe. // particular, it handles input volume changes triggered by the user (e.g.,
// input volume set to zero by a HW mute button). This class is not thread-safe.
class AgcManagerDirect final { class AgcManagerDirect final {
public: public:
// AgcManagerDirect will configure GainControl internally. The user is // Ctor. `num_capture_channels` specifies the number of channels for the audio
// responsible for processing the audio using it after the call to Process. // passed to `AnalyzePreProcess()` and `Process()`. Clamps
// The operating range of startup_min_level is [12, 255] and any input value // `analog_config.startup_min_level` in the [12, 255] range.
// outside that range will be clamped. `clipped_level_step` is the amount
// the microphone level is lowered with every clipping event, limited to
// (0, 255]. `clipped_ratio_threshold` is the proportion of clipped
// samples required to declare a clipping event, limited to (0.f, 1.f).
// `clipped_wait_frames` is the time in frames to wait after a clipping event
// before checking again, limited to values higher than 0.
AgcManagerDirect( AgcManagerDirect(
int num_capture_channels, int num_capture_channels,
int startup_min_level, const AudioProcessing::Config::GainController1::AnalogGainController&
int clipped_level_min, analog_config);
bool disable_digital_adaptive,
int clipped_level_step,
float clipped_ratio_threshold,
int clipped_wait_frames,
const AudioProcessing::Config::GainController1::AnalogGainController::
ClippingPredictor& clipping_config);
~AgcManagerDirect(); ~AgcManagerDirect();
AgcManagerDirect(const AgcManagerDirect&) = delete; AgcManagerDirect(const AgcManagerDirect&) = delete;
AgcManagerDirect& operator=(const AgcManagerDirect&) = delete; AgcManagerDirect& operator=(const AgcManagerDirect&) = delete;
void Initialize(); void Initialize();
void SetupDigitalGainControl(GainControl* gain_control) const;
// Configures `gain_control` to work as a fixed digital controller so that the
// adaptive part is only handled by this gain controller. Must be called if
// `gain_control` is also used to avoid the side-effects of running two AGCs.
void SetupDigitalGainControl(GainControl& gain_control) const;
// Analyzes `audio` before `Process()` is called so that the analysis can be
// performed before external digital processing operations take place (e.g.,
// echo cancellation). The analysis consists of input clipping detection and
// prediction (if enabled).
void AnalyzePreProcess(const AudioBuffer* audio); void AnalyzePreProcess(const AudioBuffer* audio);
// Processes `audio`. Chooses and applies a digital compression gain on each
// channel and chooses the new input volume to recommend. Undefined behavior
// if `AnalyzePreProcess()` is not called beforehand.
void Process(const AudioBuffer* audio); void Process(const AudioBuffer* audio);
// Call when the capture stream output has been flagged to be used/not-used. // Call when the capture stream output has been flagged to be used/not-used.
// If unused, the manager disregards all incoming audio. // If unused, the manager disregards all incoming audio.
void HandleCaptureOutputUsedChange(bool capture_output_used); void HandleCaptureOutputUsedChange(bool capture_output_used);
float voice_probability() const; float voice_probability() const;
// Returns the recommended input volume.
int stream_analog_level() const { return stream_analog_level_; } int stream_analog_level() const { return stream_analog_level_; }
// Sets the current input volume.
void set_stream_analog_level(int level); void set_stream_analog_level(int level);
int num_channels() const { return num_capture_channels_; } int num_channels() const { return num_capture_channels_; }
// If available, returns a new compression gain for the digital gain control. // If available, returns the latest digital compression gain that has been
// applied.
absl::optional<int> GetDigitalComressionGain(); absl::optional<int> GetDigitalComressionGain();
// Returns true if clipping prediction is enabled. // Returns true if clipping prediction is enabled.
@ -109,17 +117,12 @@ class AgcManagerDirect final {
FRIEND_TEST_ALL_PREFIXES(AgcManagerDirectTest, FRIEND_TEST_ALL_PREFIXES(AgcManagerDirectTest,
UnusedClippingPredictionsProduceEqualAnalogLevels); UnusedClippingPredictionsProduceEqualAnalogLevels);
// Dependency injection for testing. Don't delete `agc` as the memory is owned // Ctor that creates a single channel AGC and by injecting `agc`.
// by the manager. // `agc` will be owned by this class; hence, do not delete it.
AgcManagerDirect( AgcManagerDirect(
Agc* agc, const AudioProcessing::Config::GainController1::AnalogGainController&
int startup_min_level, analog_config,
int clipped_level_min, Agc* agc);
int clipped_level_step,
float clipped_ratio_threshold,
int clipped_wait_frames,
const AudioProcessing::Config::GainController1::AnalogGainController::
ClippingPredictor& clipping_config);
void AnalyzePreProcess(const float* const* audio, size_t samples_per_channel); void AnalyzePreProcess(const float* const* audio, size_t samples_per_channel);

View File

@ -40,11 +40,11 @@ constexpr int kClippedLevelStep = 15;
constexpr float kClippedRatioThreshold = 0.1f; constexpr float kClippedRatioThreshold = 0.1f;
constexpr int kClippedWaitFrames = 300; constexpr int kClippedWaitFrames = 300;
constexpr AudioProcessing::Config::GainController1::AnalogGainController using AnalogAgcConfig =
kDefaultAnalogConfig{}; AudioProcessing::Config::GainController1::AnalogGainController;
using ClippingPredictorConfig = AudioProcessing::Config::GainController1:: using ClippingPredictorConfig = AudioProcessing::Config::GainController1::
AnalogGainController::ClippingPredictor; AnalogGainController::ClippingPredictor;
constexpr AnalogAgcConfig kDefaultAnalogConfig{};
class MockGainControl : public GainControl { class MockGainControl : public GainControl {
public: public:
@ -68,28 +68,24 @@ class MockGainControl : public GainControl {
MOCK_METHOD(bool, stream_is_saturated, (), (const, override)); MOCK_METHOD(bool, stream_is_saturated, (), (const, override));
}; };
// TODO(bugs.webrtc.org/12874): Remove and use designated initializers once
// fixed.
std::unique_ptr<AgcManagerDirect> CreateAgcManagerDirect( std::unique_ptr<AgcManagerDirect> CreateAgcManagerDirect(
int startup_min_level, int startup_min_volume,
int clipped_level_step,
float clipped_ratio_threshold,
int clipped_wait_frames) {
return std::make_unique<AgcManagerDirect>(
/*num_capture_channels=*/1, startup_min_level, kClippedMin,
/*disable_digital_adaptive=*/true, clipped_level_step,
clipped_ratio_threshold, clipped_wait_frames,
kDefaultAnalogConfig.clipping_predictor);
}
std::unique_ptr<AgcManagerDirect> CreateAgcManagerDirect(
int startup_min_level,
int clipped_level_step, int clipped_level_step,
float clipped_ratio_threshold, float clipped_ratio_threshold,
int clipped_wait_frames, int clipped_wait_frames,
const ClippingPredictorConfig& clipping_cfg) { const ClippingPredictorConfig& clipping_predictor_config =
return std::make_unique<AgcManagerDirect>( kDefaultAnalogConfig.clipping_predictor) {
/*num_capture_channels=*/1, startup_min_level, kClippedMin, AnalogAgcConfig config;
/*disable_digital_adaptive=*/true, clipped_level_step, config.startup_min_volume = startup_min_volume;
clipped_ratio_threshold, clipped_wait_frames, clipping_cfg); 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);
} }
// Calls `AnalyzePreProcess()` on `manager` `num_calls` times. `peak_ratio` is a // Calls `AnalyzePreProcess()` on `manager` `num_calls` times. `peak_ratio` is a
@ -185,6 +181,20 @@ void CallPreProcessAndProcess(int num_calls,
} // namespace } // namespace
// TODO(bugs.webrtc.org/12874): Use constexpr struct with designated
// initializers once fixed.
constexpr AnalogAgcConfig GetAnalogAgcTestConfig() {
AnalogAgcConfig config;
config.startup_min_volume = kInitialVolume;
config.clipped_level_min = kClippedMin;
config.enable_digital_adaptive = true;
config.clipped_level_step = kClippedLevelStep;
config.clipped_ratio_threshold = kClippedRatioThreshold;
config.clipped_wait_frames = kClippedWaitFrames;
config.clipping_predictor = kDefaultAnalogConfig.clipping_predictor;
return config;
};
class AgcManagerDirectTestHelper { class AgcManagerDirectTestHelper {
public: public:
AgcManagerDirectTestHelper() AgcManagerDirectTestHelper()
@ -197,16 +207,10 @@ class AgcManagerDirectTestHelper {
audio(kNumChannels), audio(kNumChannels),
audio_data(kNumChannels * kSamplesPerChannel, 0.0f), audio_data(kNumChannels * kSamplesPerChannel, 0.0f),
mock_agc(new MockAgc()), mock_agc(new MockAgc()),
manager(mock_agc, manager(GetAnalogAgcTestConfig(), mock_agc) {
kInitialVolume,
kClippedMin,
kClippedLevelStep,
kClippedRatioThreshold,
kClippedWaitFrames,
kDefaultAnalogConfig.clipping_predictor) {
ExpectInitialize(); ExpectInitialize();
manager.Initialize(); manager.Initialize();
manager.SetupDigitalGainControl(&mock_gain_control); manager.SetupDigitalGainControl(mock_gain_control);
for (size_t ch = 0; ch < kNumChannels; ++ch) { for (size_t ch = 0; ch < kNumChannels; ++ch) {
audio[ch] = &audio_data[ch * kSamplesPerChannel]; audio[ch] = &audio_data[ch * kSamplesPerChannel];
} }
@ -947,11 +951,11 @@ TEST(AgcManagerDirectTest, DisableDigitalDisablesDigital) {
EXPECT_CALL(mock_gain_control, set_compression_gain_db(0)); EXPECT_CALL(mock_gain_control, set_compression_gain_db(0));
EXPECT_CALL(mock_gain_control, enable_limiter(false)); EXPECT_CALL(mock_gain_control, enable_limiter(false));
std::unique_ptr<AgcManagerDirect> manager = AnalogAgcConfig config;
CreateAgcManagerDirect(kInitialVolume, kClippedLevelStep, config.enable_digital_adaptive = false;
kClippedRatioThreshold, kClippedWaitFrames); auto manager = std::make_unique<AgcManagerDirect>(kNumChannels, config);
manager->Initialize(); manager->Initialize();
manager->SetupDigitalGainControl(&mock_gain_control); manager->SetupDigitalGainControl(mock_gain_control);
} }
TEST(AgcManagerDirectTest, AgcMinMicLevelExperimentDefault) { TEST(AgcManagerDirectTest, AgcMinMicLevelExperimentDefault) {
@ -1075,12 +1079,14 @@ TEST(AgcManagerDirectTest,
const auto factory = []() { const auto factory = []() {
// Use a large clipped level step to more quickly decrease the analog gain // Use a large clipped level step to more quickly decrease the analog gain
// with clipping. // with clipping.
auto controller = std::make_unique<AgcManagerDirect>( AnalogAgcConfig config = kDefaultAnalogConfig;
/*num_capture_channels=*/1, kInitialVolume, config.startup_min_volume = kInitialVolume;
kDefaultAnalogConfig.clipped_level_min, config.enable_digital_adaptive = false;
/*disable_digital_adaptive=*/true, /*clipped_level_step=*/64, config.clipped_level_step = 64;
kClippedRatioThreshold, kClippedWaitFrames, config.clipped_ratio_threshold = kClippedRatioThreshold;
kDefaultAnalogConfig.clipping_predictor); config.clipped_wait_frames = kClippedWaitFrames;
auto controller =
std::make_unique<AgcManagerDirect>(/*num_capture_channels=*/1, config);
controller->Initialize(); controller->Initialize();
controller->set_stream_analog_level(kInitialVolume); controller->set_stream_analog_level(kInitialVolume);
return controller; return controller;
@ -1181,11 +1187,9 @@ TEST(AgcManagerDirectTest, DisableClippingPredictorDoesNotLowerVolume) {
AudioBuffer audio_buffer(kSampleRateHz, kNumChannels, kSampleRateHz, AudioBuffer audio_buffer(kSampleRateHz, kNumChannels, kSampleRateHz,
kNumChannels, kSampleRateHz, kNumChannels); kNumChannels, kSampleRateHz, kNumChannels);
// TODO(bugs.webrtc.org/12874): Use designated initializers once fixed. AnalogAgcConfig config = GetAnalogAgcTestConfig();
constexpr ClippingPredictorConfig kConfig{/*enabled=*/false}; config.clipping_predictor.enabled = false;
AgcManagerDirect manager(new ::testing::NiceMock<MockAgc>(), kInitialVolume, AgcManagerDirect manager(config, new ::testing::NiceMock<MockAgc>());
kClippedMin, kClippedLevelStep,
kClippedRatioThreshold, kClippedWaitFrames, kConfig);
manager.Initialize(); manager.Initialize();
manager.set_stream_analog_level(/*level=*/255); manager.set_stream_analog_level(/*level=*/255);
EXPECT_FALSE(manager.clipping_predictor_enabled()); EXPECT_FALSE(manager.clipping_predictor_enabled());
@ -1204,20 +1208,15 @@ TEST(AgcManagerDirectTest, UsedClippingPredictionsProduceLowerAnalogLevels) {
AudioBuffer audio_buffer(kSampleRateHz, kNumChannels, kSampleRateHz, AudioBuffer audio_buffer(kSampleRateHz, kNumChannels, kSampleRateHz,
kNumChannels, kSampleRateHz, kNumChannels); kNumChannels, kSampleRateHz, kNumChannels);
// TODO(bugs.webrtc.org/12874): Use designated initializers once fixed. AnalogAgcConfig config_with_prediction = GetAnalogAgcTestConfig();
ClippingPredictorConfig config_with_prediction; config_with_prediction.clipping_predictor.enabled = true;
config_with_prediction.enabled = true; config_with_prediction.clipping_predictor.use_predicted_step = true;
config_with_prediction.use_predicted_step = true; AnalogAgcConfig config_without_prediction = GetAnalogAgcTestConfig();
ClippingPredictorConfig config_without_prediction; config_without_prediction.clipping_predictor.enabled = false;
config_without_prediction.enabled = false; AgcManagerDirect manager_with_prediction(config_with_prediction,
AgcManagerDirect manager_with_prediction( new ::testing::NiceMock<MockAgc>());
new ::testing::NiceMock<MockAgc>(), kInitialVolume, kClippedMin,
kClippedLevelStep, kClippedRatioThreshold, kClippedWaitFrames,
config_with_prediction);
AgcManagerDirect manager_without_prediction( AgcManagerDirect manager_without_prediction(
new ::testing::NiceMock<MockAgc>(), kInitialVolume, kClippedMin, config_without_prediction, new ::testing::NiceMock<MockAgc>());
kClippedLevelStep, kClippedRatioThreshold, kClippedWaitFrames,
config_without_prediction);
manager_with_prediction.Initialize(); manager_with_prediction.Initialize();
manager_without_prediction.Initialize(); manager_without_prediction.Initialize();
@ -1307,20 +1306,15 @@ TEST(AgcManagerDirectTest, UnusedClippingPredictionsProduceEqualAnalogLevels) {
AudioBuffer audio_buffer(kSampleRateHz, kNumChannels, kSampleRateHz, AudioBuffer audio_buffer(kSampleRateHz, kNumChannels, kSampleRateHz,
kNumChannels, kSampleRateHz, kNumChannels); kNumChannels, kSampleRateHz, kNumChannels);
// TODO(bugs.webrtc.org/12874): Use designated initializers once fixed. AnalogAgcConfig config_with_prediction = GetAnalogAgcTestConfig();
ClippingPredictorConfig config_with_prediction; config_with_prediction.clipping_predictor.enabled = true;
config_with_prediction.enabled = true; config_with_prediction.clipping_predictor.use_predicted_step = false;
config_with_prediction.use_predicted_step = false; AnalogAgcConfig config_without_prediction = GetAnalogAgcTestConfig();
ClippingPredictorConfig config_without_prediction; config_without_prediction.clipping_predictor.enabled = false;
config_without_prediction.enabled = false; AgcManagerDirect manager_with_prediction(config_with_prediction,
AgcManagerDirect manager_with_prediction( new ::testing::NiceMock<MockAgc>());
new ::testing::NiceMock<MockAgc>(), kInitialVolume, kClippedMin,
kClippedLevelStep, kClippedRatioThreshold, kClippedWaitFrames,
config_with_prediction);
AgcManagerDirect manager_without_prediction( AgcManagerDirect manager_without_prediction(
new ::testing::NiceMock<MockAgc>(), kInitialVolume, kClippedMin, config_without_prediction, new ::testing::NiceMock<MockAgc>());
kClippedLevelStep, kClippedRatioThreshold, kClippedWaitFrames,
config_without_prediction);
constexpr int kInitialLevel = 255; constexpr int kInitialLevel = 255;
constexpr float kClippingPeakRatio = 1.0f; constexpr float kClippingPeakRatio = 1.0f;

View File

@ -1889,22 +1889,13 @@ void AudioProcessingImpl::InitializeGainController1() {
stream_analog_level = submodules_.agc_manager->stream_analog_level(); stream_analog_level = submodules_.agc_manager->stream_analog_level();
} }
submodules_.agc_manager.reset(new AgcManagerDirect( submodules_.agc_manager.reset(new AgcManagerDirect(
num_proc_channels(), num_proc_channels(), config_.gain_controller1.analog_gain_controller));
config_.gain_controller1.analog_gain_controller.startup_min_volume,
config_.gain_controller1.analog_gain_controller.clipped_level_min,
!config_.gain_controller1.analog_gain_controller
.enable_digital_adaptive,
config_.gain_controller1.analog_gain_controller.clipped_level_step,
config_.gain_controller1.analog_gain_controller.clipped_ratio_threshold,
config_.gain_controller1.analog_gain_controller.clipped_wait_frames,
config_.gain_controller1.analog_gain_controller.clipping_predictor));
if (re_creation) { if (re_creation) {
submodules_.agc_manager->set_stream_analog_level(stream_analog_level); submodules_.agc_manager->set_stream_analog_level(stream_analog_level);
} }
} }
submodules_.agc_manager->Initialize(); submodules_.agc_manager->Initialize();
submodules_.agc_manager->SetupDigitalGainControl( submodules_.agc_manager->SetupDigitalGainControl(*submodules_.gain_control);
submodules_.gain_control.get());
submodules_.agc_manager->HandleCaptureOutputUsedChange( submodules_.agc_manager->HandleCaptureOutputUsedChange(
capture_.capture_output_used); capture_.capture_output_used);
} }

View File

@ -286,10 +286,12 @@ class RTC_EXPORT AudioProcessing : public rtc::RefCountInterface {
// Enables the analog gain controller functionality. // Enables the analog gain controller functionality.
struct AnalogGainController { struct AnalogGainController {
bool enabled = true; bool enabled = true;
// TODO(bugs.webrtc.org/1275566): Describe `startup_min_volume`.
int startup_min_volume = kAgcStartupMinVolume; int startup_min_volume = kAgcStartupMinVolume;
// Lowest analog microphone level that will be applied in response to // Lowest analog microphone level that will be applied in response to
// clipping. // clipping.
int clipped_level_min = kClippedLevelMin; int clipped_level_min = kClippedLevelMin;
// If true, an adaptive digital gain is applied.
bool enable_digital_adaptive = true; bool enable_digital_adaptive = true;
// Amount the microphone level is lowered with every clipping event. // Amount the microphone level is lowered with every clipping event.
// Limited to (0, 255]. // Limited to (0, 255].