audio_processing/agc: Adds config to set minimum microphone volume at startup
The AGC is currently bumping up the mic volume to 33% at startup if it is below that level. This is to avoid getting stuck in a poor state from which the AGC can not move, simply a too low input audio level. For some users, 33% is instead too loud.
This CL gives the user the possibility to set that level at create time.
- Extends the Config ExperimentalAgc with a startup_mic_volume for the user to set if desired. Note that the bump up does not apply to the legacy AGC and the "regular" AGC is controlled by ExperimentalAgc.
- Without any actions, the same default value as previously is used.
- In addition I removed a return value from InitializeExperimentalAgc() and InitializeTransient()
This has been tested by building Chromium on Mac and verify through apprtc that
1) startup_mic_volume = 128 bumps up to 50%.
2) startup_mic_volume = 500 (out of range) bumps up to 100%.
3) startup_mic_volume = 0 bumps up to 4%, the AGC min level.
BUG=4529
TESTED=locally
R=andrew@webrtc.org, kwiberg@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/43109004
Cr-Commit-Position: refs/heads/master@{#9004}
diff --git a/webrtc/modules/audio_processing/agc/agc_manager_direct.cc b/webrtc/modules/audio_processing/agc/agc_manager_direct.cc
index 24fbd56..573d48c 100644
--- a/webrtc/modules/audio_processing/agc/agc_manager_direct.cc
+++ b/webrtc/modules/audio_processing/agc/agc_manager_direct.cc
@@ -48,7 +48,6 @@
const int kMaxMicLevel = 255;
static_assert(kGainMapSize > kMaxMicLevel, "gain map too small");
const int kMinMicLevel = 12;
-const int kMinInitMicLevel = 85;
// Prevent very large microphone level changes.
const int kMaxResidualGainChange = 15;
@@ -57,6 +56,10 @@
// restrictions from clipping events.
const int kSurplusCompressionGain = 6;
+int ClampLevel(int mic_level) {
+ return std::min(std::max(kMinMicLevel, mic_level), kMaxMicLevel);
+}
+
int LevelFromGainError(int gain_error, int level) {
assert(level >= 0 && level <= kMaxMicLevel);
if (gain_error == 0) {
@@ -109,7 +112,8 @@
};
AgcManagerDirect::AgcManagerDirect(GainControl* gctrl,
- VolumeCallbacks* volume_callbacks)
+ VolumeCallbacks* volume_callbacks,
+ int startup_min_level)
: agc_(new Agc()),
gctrl_(gctrl),
volume_callbacks_(volume_callbacks),
@@ -123,13 +127,15 @@
capture_muted_(false),
check_volume_on_next_process_(true), // Check at startup.
startup_(true),
+ startup_min_level_(ClampLevel(startup_min_level)),
file_preproc_(new DebugFile("agc_preproc.pcm")),
file_postproc_(new DebugFile("agc_postproc.pcm")) {
}
AgcManagerDirect::AgcManagerDirect(Agc* agc,
GainControl* gctrl,
- VolumeCallbacks* volume_callbacks)
+ VolumeCallbacks* volume_callbacks,
+ int startup_min_level)
: agc_(agc),
gctrl_(gctrl),
volume_callbacks_(volume_callbacks),
@@ -143,6 +149,7 @@
capture_muted_(false),
check_volume_on_next_process_(true), // Check at startup.
startup_(true),
+ startup_min_level_(ClampLevel(startup_min_level)),
file_preproc_(new DebugFile("agc_preproc.pcm")),
file_postproc_(new DebugFile("agc_postproc.pcm")) {
}
@@ -336,7 +343,7 @@
}
LOG(LS_INFO) << "[agc] Initial GetMicVolume()=" << level;
- int minLevel = startup_ ? kMinInitMicLevel : kMinMicLevel;
+ int minLevel = startup_ ? startup_min_level_ : kMinMicLevel;
if (level < minLevel) {
level = minLevel;
LOG(LS_INFO) << "[agc] Initial volume too low, raising to " << level;
diff --git a/webrtc/modules/audio_processing/agc/agc_manager_direct.h b/webrtc/modules/audio_processing/agc/agc_manager_direct.h
index 05b7701..d12acf3 100644
--- a/webrtc/modules/audio_processing/agc/agc_manager_direct.h
+++ b/webrtc/modules/audio_processing/agc/agc_manager_direct.h
@@ -41,12 +41,17 @@
public:
// AgcManagerDirect will configure GainControl internally. The user is
// responsible for processing the audio using it after the call to Process.
- AgcManagerDirect(GainControl* gctrl, VolumeCallbacks* volume_callbacks);
+ // The operating range of startup_min_level is [12, 255] and any input value
+ // outside that range will be clamped.
+ AgcManagerDirect(GainControl* gctrl,
+ VolumeCallbacks* volume_callbacks,
+ int startup_min_level);
// Dependency injection for testing. Don't delete |agc| as the memory is owned
// by the manager.
AgcManagerDirect(Agc* agc,
GainControl* gctrl,
- VolumeCallbacks* volume_callbacks);
+ VolumeCallbacks* volume_callbacks,
+ int startup_min_level);
~AgcManagerDirect();
int Initialize();
@@ -88,6 +93,7 @@
bool capture_muted_;
bool check_volume_on_next_process_;
bool startup_;
+ int startup_min_level_;
rtc::scoped_ptr<DebugFile> file_preproc_;
rtc::scoped_ptr<DebugFile> file_postproc_;
diff --git a/webrtc/modules/audio_processing/audio_processing_impl.cc b/webrtc/modules/audio_processing/audio_processing_impl.cc
index 1074b61..e8210c9 100644
--- a/webrtc/modules/audio_processing/audio_processing_impl.cc
+++ b/webrtc/modules/audio_processing/audio_processing_impl.cc
@@ -177,6 +177,7 @@
#else
use_new_agc_(config.Get<ExperimentalAgc>().enabled),
#endif
+ agc_startup_min_volume_(config.Get<ExperimentalAgc>().startup_min_volume),
transient_suppressor_enabled_(config.Get<ExperimentalNs>().enabled),
beamformer_enabled_(config.Get<Beamforming>().enabled),
beamformer_(beamformer),
@@ -285,15 +286,9 @@
}
}
- int err = InitializeExperimentalAgc();
- if (err != kNoError) {
- return err;
- }
+ InitializeExperimentalAgc();
- err = InitializeTransient();
- if (err != kNoError) {
- return err;
- }
+ InitializeTransient();
InitializeBeamformer();
@@ -959,19 +954,19 @@
return false;
}
-int AudioProcessingImpl::InitializeExperimentalAgc() {
+void AudioProcessingImpl::InitializeExperimentalAgc() {
if (use_new_agc_) {
if (!agc_manager_.get()) {
- agc_manager_.reset(
- new AgcManagerDirect(gain_control_, gain_control_for_new_agc_.get()));
+ agc_manager_.reset(new AgcManagerDirect(gain_control_,
+ gain_control_for_new_agc_.get(),
+ agc_startup_min_volume_));
}
agc_manager_->Initialize();
agc_manager_->SetCaptureMuted(output_will_be_muted_);
}
- return kNoError;
}
-int AudioProcessingImpl::InitializeTransient() {
+void AudioProcessingImpl::InitializeTransient() {
if (transient_suppressor_enabled_) {
if (!transient_suppressor_.get()) {
transient_suppressor_.reset(new TransientSuppressor());
@@ -980,7 +975,6 @@
split_rate_,
fwd_out_format_.num_channels());
}
- return kNoError;
}
void AudioProcessingImpl::InitializeBeamformer() {
diff --git a/webrtc/modules/audio_processing/audio_processing_impl.h b/webrtc/modules/audio_processing/audio_processing_impl.h
index 500f08e..dbc1f25 100644
--- a/webrtc/modules/audio_processing/audio_processing_impl.h
+++ b/webrtc/modules/audio_processing/audio_processing_impl.h
@@ -170,8 +170,8 @@
bool output_copy_needed(bool is_data_processed) const;
bool synthesis_needed(bool is_data_processed) const;
bool analysis_needed(bool is_data_processed) const;
- int InitializeExperimentalAgc() EXCLUSIVE_LOCKS_REQUIRED(crit_);
- int InitializeTransient() EXCLUSIVE_LOCKS_REQUIRED(crit_);
+ void InitializeExperimentalAgc() EXCLUSIVE_LOCKS_REQUIRED(crit_);
+ void InitializeTransient() EXCLUSIVE_LOCKS_REQUIRED(crit_);
void InitializeBeamformer() EXCLUSIVE_LOCKS_REQUIRED(crit_);
EchoCancellationImpl* echo_cancellation_;
@@ -217,6 +217,7 @@
// Only set through the constructor's Config parameter.
const bool use_new_agc_;
rtc::scoped_ptr<AgcManagerDirect> agc_manager_ GUARDED_BY(crit_);
+ int agc_startup_min_volume_;
bool transient_suppressor_enabled_;
rtc::scoped_ptr<TransientSuppressor> transient_suppressor_;
diff --git a/webrtc/modules/audio_processing/include/audio_processing.h b/webrtc/modules/audio_processing/include/audio_processing.h
index 72553ff..f91d53a 100644
--- a/webrtc/modules/audio_processing/include/audio_processing.h
+++ b/webrtc/modules/audio_processing/include/audio_processing.h
@@ -72,12 +72,21 @@
bool enabled;
};
-// Must be provided through AudioProcessing::Create(Confg&). It will have no
-// impact if used with AudioProcessing::SetExtraOptions().
+// Use to enable experimental gain control (AGC). At startup the experimental
+// AGC moves the microphone volume up to |startup_min_volume| if the current
+// microphone volume is set too low. The value is clamped to its operating range
+// [12, 255]. Here, 255 maps to 100%.
+//
+// Must be provided through AudioProcessing::Create(Confg&).
+static const int kAgcStartupMinVolume = 85;
struct ExperimentalAgc {
- ExperimentalAgc() : enabled(true) {}
- explicit ExperimentalAgc(bool enabled) : enabled(enabled) {}
+ ExperimentalAgc() : enabled(true), startup_min_volume(kAgcStartupMinVolume) {}
+ ExperimentalAgc(bool enabled)
+ : enabled(enabled), startup_min_volume(kAgcStartupMinVolume) {}
+ ExperimentalAgc(bool enabled, int startup_min_volume)
+ : enabled(enabled), startup_min_volume(startup_min_volume) {}
bool enabled;
+ int startup_min_volume;
};
// Use to enable experimental noise suppression. It can be set in the