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