AEC3: Adding a configurable render signal gain

Bug: webrtc:8671
Change-Id: I405d669517382ce195065caa3147eabace5ec18a
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/158669
Commit-Queue: Per Åhgren <peah@webrtc.org>
Reviewed-by: Gustaf Ullberg <gustaf@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#29647}
diff --git a/api/audio/echo_canceller3_config.h b/api/audio/echo_canceller3_config.h
index efd6bb5..3387526 100644
--- a/api/audio/echo_canceller3_config.h
+++ b/api/audio/echo_canceller3_config.h
@@ -113,6 +113,7 @@
     float active_render_limit = 100.f;
     float poor_excitation_render_limit = 150.f;
     float poor_excitation_render_limit_ds8 = 20.f;
+    float render_power_gain_db = 0.f;
   } render_levels;
 
   struct EchoRemovalControl {
diff --git a/api/audio/echo_canceller3_config_json.cc b/api/audio/echo_canceller3_config_json.cc
index f7f115d..c6ee708 100644
--- a/api/audio/echo_canceller3_config_json.cc
+++ b/api/audio/echo_canceller3_config_json.cc
@@ -237,6 +237,8 @@
               &cfg.render_levels.poor_excitation_render_limit);
     ReadParam(section, "poor_excitation_render_limit_ds8",
               &cfg.render_levels.poor_excitation_render_limit_ds8);
+    ReadParam(section, "render_power_gain_db",
+              &cfg.render_levels.render_power_gain_db);
   }
 
   if (rtc::GetValueFromJsonObject(aec3_root, "echo_removal_control",
@@ -459,7 +461,9 @@
   ost << "\"poor_excitation_render_limit\": "
       << config.render_levels.poor_excitation_render_limit << ",";
   ost << "\"poor_excitation_render_limit_ds8\": "
-      << config.render_levels.poor_excitation_render_limit_ds8;
+      << config.render_levels.poor_excitation_render_limit_ds8 << ",";
+  ost << "\"render_power_gain_db\": "
+      << config.render_levels.render_power_gain_db;
   ost << "},";
 
   ost << "\"echo_removal_control\": {";
diff --git a/modules/audio_processing/aec3/render_delay_buffer.cc b/modules/audio_processing/aec3/render_delay_buffer.cc
index fb32035..091704c 100644
--- a/modules/audio_processing/aec3/render_delay_buffer.cc
+++ b/modules/audio_processing/aec3/render_delay_buffer.cc
@@ -13,6 +13,7 @@
 #include <string.h>
 
 #include <algorithm>
+#include <cmath>
 #include <memory>
 #include <numeric>
 #include <vector>
@@ -70,6 +71,7 @@
   std::unique_ptr<ApmDataDumper> data_dumper_;
   const Aec3Optimization optimization_;
   const EchoCanceller3Config config_;
+  const float render_linear_amplitude_gain_;
   const rtc::LoggingSeverity delay_log_level_;
   size_t down_sampling_factor_;
   const int sub_block_size_;
@@ -118,6 +120,8 @@
           new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
       optimization_(DetectOptimization()),
       config_(config),
+      render_linear_amplitude_gain_(
+          std::pow(10.0f, config_.render_levels.render_power_gain_db / 20.f)),
       delay_log_level_(config_.delay.log_warning_on_delay_changes
                            ? rtc::LS_WARNING
                            : rtc::LS_INFO),
@@ -377,19 +381,37 @@
   auto& ds = render_ds_;
   auto& f = ffts_;
   auto& s = spectra_;
+  const size_t num_bands = b.buffer[b.write].size();
+  const size_t num_render_channels = b.buffer[b.write][0].size();
   RTC_DCHECK_EQ(block.size(), b.buffer[b.write].size());
-  for (size_t k = 0; k < block.size(); ++k) {
-    RTC_DCHECK_EQ(block[k].size(), b.buffer[b.write][k].size());
-    std::copy(block[k].begin(), block[k].end(), b.buffer[b.write][k].begin());
+  for (size_t band = 0; band < num_bands; ++band) {
+    RTC_DCHECK_EQ(block[band].size(), num_render_channels);
+    RTC_DCHECK_EQ(b.buffer[b.write][band].size(), num_render_channels);
+    for (size_t ch = 0; ch < num_render_channels; ++ch) {
+      RTC_DCHECK_EQ(block[band][ch].size(), b.buffer[b.write][band][ch].size());
+      std::copy(block[band][ch].begin(), block[band][ch].end(),
+                b.buffer[b.write][band][ch].begin());
+    }
   }
 
-  render_decimator_.Decimate(block[0],
+  if (render_linear_amplitude_gain_ != 1.f) {
+    for (size_t band = 0; band < num_bands; ++band) {
+      for (size_t ch = 0; ch < num_render_channels; ++ch) {
+        for (size_t k = 0; k < 64; ++k) {
+          b.buffer[b.write][band][ch][k] *= render_linear_amplitude_gain_;
+        }
+      }
+    }
+  }
+
+  render_decimator_.Decimate(b.buffer[b.write][0],
                              config_.delay.downmix_before_delay_estimation, ds);
   data_dumper_->DumpWav("aec3_render_decimator_output", ds.size(), ds.data(),
                         16000 / down_sampling_factor_, 1);
   std::copy(ds.rbegin(), ds.rend(), lr.buffer.begin() + lr.write);
-  for (size_t channel = 0; channel < block[0].size(); ++channel) {
-    fft_.PaddedFft(block[0][channel], b.buffer[previous_write][0][channel],
+  for (size_t channel = 0; channel < b.buffer[b.write][0].size(); ++channel) {
+    fft_.PaddedFft(b.buffer[b.write][0][channel],
+                   b.buffer[previous_write][0][channel],
                    &f.buffer[f.write][channel]);
     f.buffer[f.write][channel].Spectrum(optimization_,
                                         s.buffer[s.write][channel]);