Make AgcManagerDirect clipping parameters configurable
Bug: webrtc:12774 Change-Id: I99824b5aabe6f921a5db425dd1c1c1d4c606186c Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/219681 Commit-Queue: Hanna Silen <silen@webrtc.org> Reviewed-by: Alessio Bazzica <alessiob@webrtc.org> Cr-Commit-Position: refs/heads/master@{#34069}
This commit is contained in:

committed by
WebRTC LUCI CQ

parent
e2b9fc6909
commit
b8dc7fa5a6
@ -27,33 +27,26 @@ namespace webrtc {
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
// Amount the microphone level is lowered with every clipping event.
|
|
||||||
const int kClippedLevelStep = 15;
|
|
||||||
// Proportion of clipped samples required to declare a clipping event.
|
|
||||||
const float kClippedRatioThreshold = 0.1f;
|
|
||||||
// Time in frames to wait after a clipping event before checking again.
|
|
||||||
const int kClippedWaitFrames = 300;
|
|
||||||
|
|
||||||
// Amount of error we tolerate in the microphone level (presumably due to OS
|
// Amount of error we tolerate in the microphone level (presumably due to OS
|
||||||
// quantization) before we assume the user has manually adjusted the microphone.
|
// quantization) before we assume the user has manually adjusted the microphone.
|
||||||
const int kLevelQuantizationSlack = 25;
|
constexpr int kLevelQuantizationSlack = 25;
|
||||||
|
|
||||||
const int kDefaultCompressionGain = 7;
|
constexpr int kDefaultCompressionGain = 7;
|
||||||
const int kMaxCompressionGain = 12;
|
constexpr int kMaxCompressionGain = 12;
|
||||||
const int kMinCompressionGain = 2;
|
constexpr int kMinCompressionGain = 2;
|
||||||
// Controls the rate of compression changes towards the target.
|
// Controls the rate of compression changes towards the target.
|
||||||
const float kCompressionGainStep = 0.05f;
|
constexpr float kCompressionGainStep = 0.05f;
|
||||||
|
|
||||||
const int kMaxMicLevel = 255;
|
constexpr int kMaxMicLevel = 255;
|
||||||
static_assert(kGainMapSize > kMaxMicLevel, "gain map too small");
|
static_assert(kGainMapSize > kMaxMicLevel, "gain map too small");
|
||||||
const int kMinMicLevel = 12;
|
constexpr int kMinMicLevel = 12;
|
||||||
|
|
||||||
// Prevent very large microphone level changes.
|
// Prevent very large microphone level changes.
|
||||||
const int kMaxResidualGainChange = 15;
|
constexpr int kMaxResidualGainChange = 15;
|
||||||
|
|
||||||
// Maximum additional gain allowed to compensate for microphone level
|
// Maximum additional gain allowed to compensate for microphone level
|
||||||
// restrictions from clipping events.
|
// restrictions from clipping events.
|
||||||
const int kSurplusCompressionGain = 6;
|
constexpr int kSurplusCompressionGain = 6;
|
||||||
|
|
||||||
// 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.
|
||||||
@ -182,19 +175,19 @@ void MonoAgc::Process(const int16_t* audio,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MonoAgc::HandleClipping() {
|
void MonoAgc::HandleClipping(int clipped_level_step) {
|
||||||
// Always decrease the maximum level, even if the current level is below
|
// Always decrease the maximum level, even if the current level is below
|
||||||
// threshold.
|
// threshold.
|
||||||
SetMaxLevel(std::max(clipped_level_min_, max_level_ - kClippedLevelStep));
|
SetMaxLevel(std::max(clipped_level_min_, max_level_ - clipped_level_step));
|
||||||
if (log_to_histograms_) {
|
if (log_to_histograms_) {
|
||||||
RTC_HISTOGRAM_BOOLEAN("WebRTC.Audio.AgcClippingAdjustmentAllowed",
|
RTC_HISTOGRAM_BOOLEAN("WebRTC.Audio.AgcClippingAdjustmentAllowed",
|
||||||
level_ - kClippedLevelStep >= clipped_level_min_);
|
level_ - clipped_level_step >= clipped_level_min_);
|
||||||
}
|
}
|
||||||
if (level_ > clipped_level_min_) {
|
if (level_ > clipped_level_min_) {
|
||||||
// Don't try to adjust the level if we're already below the limit. As
|
// Don't try to adjust the level if we're already below the limit. As
|
||||||
// a consequence, if the user has brought the level above the limit, we
|
// a consequence, if the user has brought the level above the limit, we
|
||||||
// will still not react until the postproc updates the level.
|
// will still not react until the postproc updates the level.
|
||||||
SetLevel(std::max(clipped_level_min_, level_ - kClippedLevelStep));
|
SetLevel(std::max(clipped_level_min_, level_ - clipped_level_step));
|
||||||
// Reset the AGCs for all channels since the level has changed.
|
// Reset the AGCs for all channels since the level has changed.
|
||||||
agc_->Reset();
|
agc_->Reset();
|
||||||
}
|
}
|
||||||
@ -404,12 +397,18 @@ int AgcManagerDirect::instance_counter_ = 0;
|
|||||||
AgcManagerDirect::AgcManagerDirect(Agc* agc,
|
AgcManagerDirect::AgcManagerDirect(Agc* agc,
|
||||||
int startup_min_level,
|
int startup_min_level,
|
||||||
int clipped_level_min,
|
int clipped_level_min,
|
||||||
int sample_rate_hz)
|
int sample_rate_hz,
|
||||||
|
int clipped_level_step,
|
||||||
|
float clipped_ratio_threshold,
|
||||||
|
int clipped_wait_frames)
|
||||||
: AgcManagerDirect(/*num_capture_channels*/ 1,
|
: AgcManagerDirect(/*num_capture_channels*/ 1,
|
||||||
startup_min_level,
|
startup_min_level,
|
||||||
clipped_level_min,
|
clipped_level_min,
|
||||||
/*disable_digital_adaptive*/ false,
|
/*disable_digital_adaptive*/ false,
|
||||||
sample_rate_hz) {
|
sample_rate_hz,
|
||||||
|
clipped_level_step,
|
||||||
|
clipped_ratio_threshold,
|
||||||
|
clipped_wait_frames) {
|
||||||
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);
|
||||||
@ -419,15 +418,21 @@ AgcManagerDirect::AgcManagerDirect(int num_capture_channels,
|
|||||||
int startup_min_level,
|
int startup_min_level,
|
||||||
int clipped_level_min,
|
int clipped_level_min,
|
||||||
bool disable_digital_adaptive,
|
bool disable_digital_adaptive,
|
||||||
int sample_rate_hz)
|
int sample_rate_hz,
|
||||||
|
int clipped_level_step,
|
||||||
|
float clipped_ratio_threshold,
|
||||||
|
int clipped_wait_frames)
|
||||||
: data_dumper_(
|
: data_dumper_(
|
||||||
new ApmDataDumper(rtc::AtomicOps::Increment(&instance_counter_))),
|
new ApmDataDumper(rtc::AtomicOps::Increment(&instance_counter_))),
|
||||||
use_min_channel_level_(!UseMaxAnalogChannelLevel()),
|
use_min_channel_level_(!UseMaxAnalogChannelLevel()),
|
||||||
sample_rate_hz_(sample_rate_hz),
|
sample_rate_hz_(sample_rate_hz),
|
||||||
num_capture_channels_(num_capture_channels),
|
num_capture_channels_(num_capture_channels),
|
||||||
disable_digital_adaptive_(disable_digital_adaptive),
|
disable_digital_adaptive_(disable_digital_adaptive),
|
||||||
frames_since_clipped_(kClippedWaitFrames),
|
frames_since_clipped_(clipped_wait_frames),
|
||||||
capture_output_used_(true),
|
capture_output_used_(true),
|
||||||
|
clipped_level_step_(clipped_level_step),
|
||||||
|
clipped_ratio_threshold_(clipped_ratio_threshold),
|
||||||
|
clipped_wait_frames_(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) {
|
||||||
const int min_mic_level = GetMinMicLevel();
|
const int min_mic_level = GetMinMicLevel();
|
||||||
@ -438,7 +443,13 @@ AgcManagerDirect::AgcManagerDirect(int num_capture_channels,
|
|||||||
data_dumper_ch, startup_min_level, clipped_level_min,
|
data_dumper_ch, startup_min_level, clipped_level_min,
|
||||||
disable_digital_adaptive_, min_mic_level);
|
disable_digital_adaptive_, min_mic_level);
|
||||||
}
|
}
|
||||||
RTC_DCHECK_LT(0, channel_agcs_.size());
|
RTC_DCHECK(!channel_agcs_.empty());
|
||||||
|
RTC_DCHECK_GT(clipped_level_step, 0);
|
||||||
|
RTC_DCHECK_LE(clipped_level_step, 255);
|
||||||
|
RTC_DCHECK_GT(clipped_ratio_threshold, 0.f);
|
||||||
|
RTC_DCHECK_LT(clipped_ratio_threshold, 1.f);
|
||||||
|
RTC_DCHECK_GT(clipped_wait_frames, 0);
|
||||||
|
|
||||||
channel_agcs_[0]->ActivateLogging();
|
channel_agcs_[0]->ActivateLogging();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -489,7 +500,7 @@ void AgcManagerDirect::AnalyzePreProcess(const float* const* audio,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frames_since_clipped_ < kClippedWaitFrames) {
|
if (frames_since_clipped_ < clipped_wait_frames_) {
|
||||||
++frames_since_clipped_;
|
++frames_since_clipped_;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -506,11 +517,11 @@ void AgcManagerDirect::AnalyzePreProcess(const float* const* audio,
|
|||||||
float clipped_ratio =
|
float clipped_ratio =
|
||||||
ComputeClippedRatio(audio, num_capture_channels_, samples_per_channel);
|
ComputeClippedRatio(audio, num_capture_channels_, samples_per_channel);
|
||||||
|
|
||||||
if (clipped_ratio > kClippedRatioThreshold) {
|
if (clipped_ratio > clipped_ratio_threshold_) {
|
||||||
RTC_DLOG(LS_INFO) << "[agc] Clipping detected. clipped_ratio="
|
RTC_DLOG(LS_INFO) << "[agc] Clipping detected. clipped_ratio="
|
||||||
<< clipped_ratio;
|
<< clipped_ratio;
|
||||||
for (auto& state_ch : channel_agcs_) {
|
for (auto& state_ch : channel_agcs_) {
|
||||||
state_ch->HandleClipping();
|
state_ch->HandleClipping(clipped_level_step_);
|
||||||
}
|
}
|
||||||
frames_since_clipped_ = 0;
|
frames_since_clipped_ = 0;
|
||||||
}
|
}
|
||||||
|
@ -34,12 +34,20 @@ class AgcManagerDirect final {
|
|||||||
// AgcManagerDirect will configure GainControl internally. The user is
|
// AgcManagerDirect will configure GainControl internally. The user is
|
||||||
// responsible for processing the audio using it after the call to Process.
|
// responsible for processing the audio using it after the call to Process.
|
||||||
// The operating range of startup_min_level is [12, 255] and any input value
|
// The operating range of startup_min_level is [12, 255] and any input value
|
||||||
// outside that range will be clamped.
|
// 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(int num_capture_channels,
|
AgcManagerDirect(int num_capture_channels,
|
||||||
int startup_min_level,
|
int startup_min_level,
|
||||||
int clipped_level_min,
|
int clipped_level_min,
|
||||||
bool disable_digital_adaptive,
|
bool disable_digital_adaptive,
|
||||||
int sample_rate_hz);
|
int sample_rate_hz,
|
||||||
|
int clipped_level_step,
|
||||||
|
float clipped_ratio_threshold,
|
||||||
|
int clipped_wait_frames);
|
||||||
|
|
||||||
~AgcManagerDirect();
|
~AgcManagerDirect();
|
||||||
AgcManagerDirect(const AgcManagerDirect&) = delete;
|
AgcManagerDirect(const AgcManagerDirect&) = delete;
|
||||||
@ -81,13 +89,18 @@ class AgcManagerDirect final {
|
|||||||
AgcMinMicLevelExperimentEnabled50);
|
AgcMinMicLevelExperimentEnabled50);
|
||||||
FRIEND_TEST_ALL_PREFIXES(AgcManagerDirectStandaloneTest,
|
FRIEND_TEST_ALL_PREFIXES(AgcManagerDirectStandaloneTest,
|
||||||
AgcMinMicLevelExperimentEnabledAboveStartupLevel);
|
AgcMinMicLevelExperimentEnabledAboveStartupLevel);
|
||||||
|
FRIEND_TEST_ALL_PREFIXES(AgcManagerDirectStandaloneTest,
|
||||||
|
ClippingParametersVerified);
|
||||||
|
|
||||||
// Dependency injection for testing. Don't delete |agc| as the memory is owned
|
// Dependency injection for testing. Don't delete |agc| as the memory is owned
|
||||||
// by the manager.
|
// by the manager.
|
||||||
AgcManagerDirect(Agc* agc,
|
AgcManagerDirect(Agc* agc,
|
||||||
int startup_min_level,
|
int startup_min_level,
|
||||||
int clipped_level_min,
|
int clipped_level_min,
|
||||||
int sample_rate_hz);
|
int sample_rate_hz,
|
||||||
|
int clipped_level_step,
|
||||||
|
float clipped_ratio_threshold,
|
||||||
|
int clipped_wait_frames);
|
||||||
|
|
||||||
void AnalyzePreProcess(const float* const* audio, size_t samples_per_channel);
|
void AnalyzePreProcess(const float* const* audio, size_t samples_per_channel);
|
||||||
|
|
||||||
@ -105,6 +118,10 @@ class AgcManagerDirect final {
|
|||||||
bool capture_output_used_;
|
bool capture_output_used_;
|
||||||
int channel_controlling_gain_ = 0;
|
int channel_controlling_gain_ = 0;
|
||||||
|
|
||||||
|
const int clipped_level_step_;
|
||||||
|
const float clipped_ratio_threshold_;
|
||||||
|
const int clipped_wait_frames_;
|
||||||
|
|
||||||
std::vector<std::unique_ptr<MonoAgc>> channel_agcs_;
|
std::vector<std::unique_ptr<MonoAgc>> channel_agcs_;
|
||||||
std::vector<absl::optional<int>> new_compressions_to_set_;
|
std::vector<absl::optional<int>> new_compressions_to_set_;
|
||||||
};
|
};
|
||||||
@ -123,7 +140,7 @@ class MonoAgc {
|
|||||||
void Initialize();
|
void Initialize();
|
||||||
void HandleCaptureOutputUsedChange(bool capture_output_used);
|
void HandleCaptureOutputUsedChange(bool capture_output_used);
|
||||||
|
|
||||||
void HandleClipping();
|
void HandleClipping(int clipped_level_step);
|
||||||
|
|
||||||
void Process(const int16_t* audio,
|
void Process(const int16_t* audio,
|
||||||
size_t samples_per_channel,
|
size_t samples_per_channel,
|
||||||
|
@ -26,13 +26,16 @@ using ::testing::SetArgPointee;
|
|||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
const int kSampleRateHz = 32000;
|
constexpr int kSampleRateHz = 32000;
|
||||||
const int kNumChannels = 1;
|
constexpr int kNumChannels = 1;
|
||||||
const int kSamplesPerChannel = kSampleRateHz / 100;
|
constexpr int kSamplesPerChannel = kSampleRateHz / 100;
|
||||||
const int kInitialVolume = 128;
|
constexpr int kInitialVolume = 128;
|
||||||
constexpr int kClippedMin = 165; // Arbitrary, but different from the default.
|
constexpr int kClippedMin = 165; // Arbitrary, but different from the default.
|
||||||
const float kAboveClippedThreshold = 0.2f;
|
constexpr float kAboveClippedThreshold = 0.2f;
|
||||||
const int kMinMicLevel = 12;
|
constexpr int kMinMicLevel = 12;
|
||||||
|
constexpr int kClippedLevelStep = 15;
|
||||||
|
constexpr float kClippedRatioThreshold = 0.1f;
|
||||||
|
constexpr int kClippedWaitFrames = 300;
|
||||||
|
|
||||||
class MockGainControl : public GainControl {
|
class MockGainControl : public GainControl {
|
||||||
public:
|
public:
|
||||||
@ -57,10 +60,14 @@ class MockGainControl : public GainControl {
|
|||||||
};
|
};
|
||||||
|
|
||||||
std::unique_ptr<AgcManagerDirect> CreateAgcManagerDirect(
|
std::unique_ptr<AgcManagerDirect> CreateAgcManagerDirect(
|
||||||
int startup_min_level) {
|
int startup_min_level,
|
||||||
|
int clipped_level_step,
|
||||||
|
float clipped_ratio_threshold,
|
||||||
|
int clipped_wait_frames) {
|
||||||
return std::make_unique<AgcManagerDirect>(
|
return std::make_unique<AgcManagerDirect>(
|
||||||
/*num_capture_channels=*/1, startup_min_level, kClippedMin,
|
/*num_capture_channels=*/1, startup_min_level, kClippedMin,
|
||||||
/*disable_digital_adaptive=*/true, kSampleRateHz);
|
/*disable_digital_adaptive=*/true, kSampleRateHz, clipped_level_step,
|
||||||
|
clipped_ratio_threshold, clipped_wait_frames);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
@ -69,7 +76,13 @@ class AgcManagerDirectTest : public ::testing::Test {
|
|||||||
protected:
|
protected:
|
||||||
AgcManagerDirectTest()
|
AgcManagerDirectTest()
|
||||||
: agc_(new MockAgc),
|
: agc_(new MockAgc),
|
||||||
manager_(agc_, kInitialVolume, kClippedMin, kSampleRateHz),
|
manager_(agc_,
|
||||||
|
kInitialVolume,
|
||||||
|
kClippedMin,
|
||||||
|
kSampleRateHz,
|
||||||
|
kClippedLevelStep,
|
||||||
|
kClippedRatioThreshold,
|
||||||
|
kClippedWaitFrames),
|
||||||
audio(kNumChannels),
|
audio(kNumChannels),
|
||||||
audio_data(kNumChannels * kSamplesPerChannel, 0.f) {
|
audio_data(kNumChannels * kSamplesPerChannel, 0.f) {
|
||||||
ExpectInitialize();
|
ExpectInitialize();
|
||||||
@ -705,14 +718,16 @@ TEST(AgcManagerDirectStandaloneTest, DisableDigitalDisablesDigital) {
|
|||||||
EXPECT_CALL(gctrl, enable_limiter(false));
|
EXPECT_CALL(gctrl, enable_limiter(false));
|
||||||
|
|
||||||
std::unique_ptr<AgcManagerDirect> manager =
|
std::unique_ptr<AgcManagerDirect> manager =
|
||||||
CreateAgcManagerDirect(kInitialVolume);
|
CreateAgcManagerDirect(kInitialVolume, kClippedLevelStep,
|
||||||
|
kClippedRatioThreshold, kClippedWaitFrames);
|
||||||
manager->Initialize();
|
manager->Initialize();
|
||||||
manager->SetupDigitalGainControl(&gctrl);
|
manager->SetupDigitalGainControl(&gctrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(AgcManagerDirectStandaloneTest, AgcMinMicLevelExperiment) {
|
TEST(AgcManagerDirectStandaloneTest, AgcMinMicLevelExperiment) {
|
||||||
std::unique_ptr<AgcManagerDirect> manager =
|
std::unique_ptr<AgcManagerDirect> manager =
|
||||||
CreateAgcManagerDirect(kInitialVolume);
|
CreateAgcManagerDirect(kInitialVolume, kClippedLevelStep,
|
||||||
|
kClippedRatioThreshold, kClippedWaitFrames);
|
||||||
EXPECT_EQ(manager->channel_agcs_[0]->min_mic_level(), kMinMicLevel);
|
EXPECT_EQ(manager->channel_agcs_[0]->min_mic_level(), kMinMicLevel);
|
||||||
EXPECT_EQ(manager->channel_agcs_[0]->startup_min_level(), kInitialVolume);
|
EXPECT_EQ(manager->channel_agcs_[0]->startup_min_level(), kInitialVolume);
|
||||||
}
|
}
|
||||||
@ -721,7 +736,8 @@ TEST(AgcManagerDirectStandaloneTest, AgcMinMicLevelExperimentDisabled) {
|
|||||||
test::ScopedFieldTrials field_trial(
|
test::ScopedFieldTrials field_trial(
|
||||||
"WebRTC-Audio-AgcMinMicLevelExperiment/Disabled/");
|
"WebRTC-Audio-AgcMinMicLevelExperiment/Disabled/");
|
||||||
std::unique_ptr<AgcManagerDirect> manager =
|
std::unique_ptr<AgcManagerDirect> manager =
|
||||||
CreateAgcManagerDirect(kInitialVolume);
|
CreateAgcManagerDirect(kInitialVolume, kClippedLevelStep,
|
||||||
|
kClippedRatioThreshold, kClippedWaitFrames);
|
||||||
EXPECT_EQ(manager->channel_agcs_[0]->min_mic_level(), kMinMicLevel);
|
EXPECT_EQ(manager->channel_agcs_[0]->min_mic_level(), kMinMicLevel);
|
||||||
EXPECT_EQ(manager->channel_agcs_[0]->startup_min_level(), kInitialVolume);
|
EXPECT_EQ(manager->channel_agcs_[0]->startup_min_level(), kInitialVolume);
|
||||||
}
|
}
|
||||||
@ -732,7 +748,8 @@ TEST(AgcManagerDirectStandaloneTest, AgcMinMicLevelExperimentOutOfRangeAbove) {
|
|||||||
test::ScopedFieldTrials field_trial(
|
test::ScopedFieldTrials field_trial(
|
||||||
"WebRTC-Audio-AgcMinMicLevelExperiment/Enabled-256/");
|
"WebRTC-Audio-AgcMinMicLevelExperiment/Enabled-256/");
|
||||||
std::unique_ptr<AgcManagerDirect> manager =
|
std::unique_ptr<AgcManagerDirect> manager =
|
||||||
CreateAgcManagerDirect(kInitialVolume);
|
CreateAgcManagerDirect(kInitialVolume, kClippedLevelStep,
|
||||||
|
kClippedRatioThreshold, kClippedWaitFrames);
|
||||||
EXPECT_EQ(manager->channel_agcs_[0]->min_mic_level(), kMinMicLevel);
|
EXPECT_EQ(manager->channel_agcs_[0]->min_mic_level(), kMinMicLevel);
|
||||||
EXPECT_EQ(manager->channel_agcs_[0]->startup_min_level(), kInitialVolume);
|
EXPECT_EQ(manager->channel_agcs_[0]->startup_min_level(), kInitialVolume);
|
||||||
}
|
}
|
||||||
@ -743,7 +760,8 @@ TEST(AgcManagerDirectStandaloneTest, AgcMinMicLevelExperimentOutOfRangeBelow) {
|
|||||||
test::ScopedFieldTrials field_trial(
|
test::ScopedFieldTrials field_trial(
|
||||||
"WebRTC-Audio-AgcMinMicLevelExperiment/Enabled--1/");
|
"WebRTC-Audio-AgcMinMicLevelExperiment/Enabled--1/");
|
||||||
std::unique_ptr<AgcManagerDirect> manager =
|
std::unique_ptr<AgcManagerDirect> manager =
|
||||||
CreateAgcManagerDirect(kInitialVolume);
|
CreateAgcManagerDirect(kInitialVolume, kClippedLevelStep,
|
||||||
|
kClippedRatioThreshold, kClippedWaitFrames);
|
||||||
EXPECT_EQ(manager->channel_agcs_[0]->min_mic_level(), kMinMicLevel);
|
EXPECT_EQ(manager->channel_agcs_[0]->min_mic_level(), kMinMicLevel);
|
||||||
EXPECT_EQ(manager->channel_agcs_[0]->startup_min_level(), kInitialVolume);
|
EXPECT_EQ(manager->channel_agcs_[0]->startup_min_level(), kInitialVolume);
|
||||||
}
|
}
|
||||||
@ -755,7 +773,8 @@ TEST(AgcManagerDirectStandaloneTest, AgcMinMicLevelExperimentEnabled50) {
|
|||||||
test::ScopedFieldTrials field_trial(
|
test::ScopedFieldTrials field_trial(
|
||||||
"WebRTC-Audio-AgcMinMicLevelExperiment/Enabled-50/");
|
"WebRTC-Audio-AgcMinMicLevelExperiment/Enabled-50/");
|
||||||
std::unique_ptr<AgcManagerDirect> manager =
|
std::unique_ptr<AgcManagerDirect> manager =
|
||||||
CreateAgcManagerDirect(kInitialVolume);
|
CreateAgcManagerDirect(kInitialVolume, kClippedLevelStep,
|
||||||
|
kClippedRatioThreshold, kClippedWaitFrames);
|
||||||
EXPECT_EQ(manager->channel_agcs_[0]->min_mic_level(), 50);
|
EXPECT_EQ(manager->channel_agcs_[0]->min_mic_level(), 50);
|
||||||
EXPECT_EQ(manager->channel_agcs_[0]->startup_min_level(), kInitialVolume);
|
EXPECT_EQ(manager->channel_agcs_[0]->startup_min_level(), kInitialVolume);
|
||||||
}
|
}
|
||||||
@ -768,9 +787,33 @@ TEST(AgcManagerDirectStandaloneTest,
|
|||||||
test::ScopedFieldTrials field_trial(
|
test::ScopedFieldTrials field_trial(
|
||||||
"WebRTC-Audio-AgcMinMicLevelExperiment/Enabled-50/");
|
"WebRTC-Audio-AgcMinMicLevelExperiment/Enabled-50/");
|
||||||
std::unique_ptr<AgcManagerDirect> manager =
|
std::unique_ptr<AgcManagerDirect> manager =
|
||||||
CreateAgcManagerDirect(/*startup_min_level=*/30);
|
CreateAgcManagerDirect(/*startup_min_level=*/30, kClippedLevelStep,
|
||||||
|
kClippedRatioThreshold, kClippedWaitFrames);
|
||||||
EXPECT_EQ(manager->channel_agcs_[0]->min_mic_level(), 50);
|
EXPECT_EQ(manager->channel_agcs_[0]->min_mic_level(), 50);
|
||||||
EXPECT_EQ(manager->channel_agcs_[0]->startup_min_level(), 50);
|
EXPECT_EQ(manager->channel_agcs_[0]->startup_min_level(), 50);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(bugs.webrtc.org/12774): Test the bahavior of `clipped_level_step`.
|
||||||
|
// TODO(bugs.webrtc.org/12774): Test the bahavior of `clipped_ratio_threshold`.
|
||||||
|
// TODO(bugs.webrtc.org/12774): Test the bahavior of `clipped_wait_frames`.
|
||||||
|
// Verifies that configurable clipping parameters are initialized as intended.
|
||||||
|
TEST(AgcManagerDirectStandaloneTest, ClippingParametersVerified) {
|
||||||
|
std::unique_ptr<AgcManagerDirect> manager =
|
||||||
|
CreateAgcManagerDirect(kInitialVolume, kClippedLevelStep,
|
||||||
|
kClippedRatioThreshold, kClippedWaitFrames);
|
||||||
|
manager->Initialize();
|
||||||
|
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(kInitialVolume,
|
||||||
|
/*clipped_level_step*/ 10,
|
||||||
|
/*clipped_ratio_threshold*/ 0.2f,
|
||||||
|
/*clipped_wait_frames*/ 50);
|
||||||
|
manager_custom->Initialize();
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -1918,7 +1918,10 @@ void AudioProcessingImpl::InitializeGainController1() {
|
|||||||
config_.gain_controller1.analog_gain_controller.clipped_level_min,
|
config_.gain_controller1.analog_gain_controller.clipped_level_min,
|
||||||
!config_.gain_controller1.analog_gain_controller
|
!config_.gain_controller1.analog_gain_controller
|
||||||
.enable_digital_adaptive,
|
.enable_digital_adaptive,
|
||||||
capture_nonlocked_.split_rate));
|
capture_nonlocked_.split_rate,
|
||||||
|
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));
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
@ -77,7 +77,11 @@ bool Agc1Config::operator==(const Agc1Config& rhs) const {
|
|||||||
analog_lhs.startup_min_volume == analog_rhs.startup_min_volume &&
|
analog_lhs.startup_min_volume == analog_rhs.startup_min_volume &&
|
||||||
analog_lhs.clipped_level_min == analog_rhs.clipped_level_min &&
|
analog_lhs.clipped_level_min == analog_rhs.clipped_level_min &&
|
||||||
analog_lhs.enable_digital_adaptive ==
|
analog_lhs.enable_digital_adaptive ==
|
||||||
analog_rhs.enable_digital_adaptive;
|
analog_rhs.enable_digital_adaptive &&
|
||||||
|
analog_lhs.clipped_level_step == analog_rhs.clipped_level_step &&
|
||||||
|
analog_lhs.clipped_ratio_threshold ==
|
||||||
|
analog_rhs.clipped_ratio_threshold &&
|
||||||
|
analog_lhs.clipped_wait_frames == analog_rhs.clipped_wait_frames;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Agc2Config::AdaptiveDigital::operator==(
|
bool Agc2Config::AdaptiveDigital::operator==(
|
||||||
@ -157,6 +161,12 @@ std::string AudioProcessing::Config::ToString() const {
|
|||||||
<< gain_controller1.analog_gain_controller.clipped_level_min
|
<< gain_controller1.analog_gain_controller.clipped_level_min
|
||||||
<< ", enable_digital_adaptive: "
|
<< ", enable_digital_adaptive: "
|
||||||
<< gain_controller1.analog_gain_controller.enable_digital_adaptive
|
<< gain_controller1.analog_gain_controller.enable_digital_adaptive
|
||||||
|
<< ", clipped_level_step: "
|
||||||
|
<< gain_controller1.analog_gain_controller.clipped_level_step
|
||||||
|
<< ", clipped_ratio_threshold: "
|
||||||
|
<< gain_controller1.analog_gain_controller.clipped_ratio_threshold
|
||||||
|
<< ", clipped_wait_frames: "
|
||||||
|
<< gain_controller1.analog_gain_controller.clipped_wait_frames
|
||||||
<< " }}, gain_controller2: { enabled: " << gain_controller2.enabled
|
<< " }}, gain_controller2: { enabled: " << gain_controller2.enabled
|
||||||
<< ", fixed_digital: { gain_db: "
|
<< ", fixed_digital: { gain_db: "
|
||||||
<< gain_controller2.fixed_digital.gain_db
|
<< gain_controller2.fixed_digital.gain_db
|
||||||
|
@ -59,9 +59,9 @@ class CustomProcessing;
|
|||||||
//
|
//
|
||||||
// Must be provided through AudioProcessingBuilder().Create(config).
|
// Must be provided through AudioProcessingBuilder().Create(config).
|
||||||
#if defined(WEBRTC_CHROMIUM_BUILD)
|
#if defined(WEBRTC_CHROMIUM_BUILD)
|
||||||
static const int kAgcStartupMinVolume = 85;
|
static constexpr int kAgcStartupMinVolume = 85;
|
||||||
#else
|
#else
|
||||||
static const int kAgcStartupMinVolume = 0;
|
static constexpr int kAgcStartupMinVolume = 0;
|
||||||
#endif // defined(WEBRTC_CHROMIUM_BUILD)
|
#endif // defined(WEBRTC_CHROMIUM_BUILD)
|
||||||
static constexpr int kClippedLevelMin = 70;
|
static constexpr int kClippedLevelMin = 70;
|
||||||
|
|
||||||
@ -334,6 +334,15 @@ class RTC_EXPORT AudioProcessing : public rtc::RefCountInterface {
|
|||||||
// clipping.
|
// clipping.
|
||||||
int clipped_level_min = kClippedLevelMin;
|
int clipped_level_min = kClippedLevelMin;
|
||||||
bool enable_digital_adaptive = true;
|
bool enable_digital_adaptive = true;
|
||||||
|
// Amount the microphone level is lowered with every clipping event.
|
||||||
|
// Limited to (0, 255].
|
||||||
|
int clipped_level_step = 15;
|
||||||
|
// Proportion of clipped samples required to declare a clipping event.
|
||||||
|
// Limited to (0.f, 1.f).
|
||||||
|
float clipped_ratio_threshold = 0.1f;
|
||||||
|
// Time in frames to wait after a clipping event before checking again.
|
||||||
|
// Limited to values higher than 0.
|
||||||
|
int clipped_wait_frames = 300;
|
||||||
} analog_gain_controller;
|
} analog_gain_controller;
|
||||||
} gain_controller1;
|
} gain_controller1;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user