Make the high-pass filter operate in full-band

This CL moves the high-pass filter to run in the full-band domain
instead of the split-band domain.

Bug: webrtc:11193
Change-Id: Ie61f4a80afda11236ecbb1ad544bbd0350c7bbfd
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/161453
Reviewed-by: Gustaf Ullberg <gustaf@webrtc.org>
Commit-Queue: Per Åhgren <peah@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#30112}
diff --git a/modules/audio_processing/aec3/echo_canceller3.cc b/modules/audio_processing/aec3/echo_canceller3.cc
index 632b91b..dafb14f 100644
--- a/modules/audio_processing/aec3/echo_canceller3.cc
+++ b/modules/audio_processing/aec3/echo_canceller3.cc
@@ -248,7 +248,7 @@
     : data_dumper_(data_dumper),
       num_bands_(num_bands),
       num_channels_(num_channels),
-      high_pass_filter_(num_channels),
+      high_pass_filter_(16000, num_channels),
       render_queue_input_frame_(
           num_bands_,
           std::vector<std::vector<float>>(
diff --git a/modules/audio_processing/aec3/echo_canceller3_unittest.cc b/modules/audio_processing/aec3/echo_canceller3_unittest.cc
index 8d9199c..4fc68ff 100644
--- a/modules/audio_processing/aec3/echo_canceller3_unittest.cc
+++ b/modules/audio_processing/aec3/echo_canceller3_unittest.cc
@@ -237,7 +237,7 @@
         capture_output.push_back(capture_buffer_.split_bands(0)[0][k]);
       }
     }
-    HighPassFilter hp_filter(1);
+    HighPassFilter hp_filter(16000, 1);
     hp_filter.Process(&render_input);
 
     EXPECT_TRUE(
@@ -530,7 +530,7 @@
         capture_output.push_back(capture_buffer_.split_bands(0)[0][k]);
       }
     }
-    HighPassFilter hp_filter(1);
+    HighPassFilter hp_filter(16000, 1);
     hp_filter.Process(&render_input);
 
     EXPECT_TRUE(
diff --git a/modules/audio_processing/audio_processing_impl.cc b/modules/audio_processing/audio_processing_impl.cc
index d544304..6d8b209 100644
--- a/modules/audio_processing/audio_processing_impl.cc
+++ b/modules/audio_processing/audio_processing_impl.cc
@@ -75,6 +75,11 @@
   return field_trial::IsEnabled("WebRTC-NewNoiseSuppressionKillSwitch");
 }
 
+// Checks whether the high-pass filter should be done in the full-band.
+bool EnforceSplitBandHpf() {
+  return field_trial::IsEnabled("WebRTC-FullBandHpfKillSwitch");
+}
+
 // Checks whether AEC3 should be allowed to decide what the default
 // configuration should be based on the render and capture channel configuration
 // at hand.
@@ -343,7 +348,8 @@
                  !field_trial::IsEnabled(
                      "WebRTC-ApmExperimentalMultiChannelRenderKillSwitch"),
                  !field_trial::IsEnabled(
-                     "WebRTC-ApmExperimentalMultiChannelCaptureKillSwitch")),
+                     "WebRTC-ApmExperimentalMultiChannelCaptureKillSwitch"),
+                 EnforceSplitBandHpf()),
 #if defined(WEBRTC_ANDROID) || defined(WEBRTC_IOS)
       capture_(false),
 #else
@@ -629,7 +635,9 @@
       config_.pipeline.multi_channel_render !=
           config.pipeline.multi_channel_render ||
       config_.pipeline.multi_channel_capture !=
-          config.pipeline.multi_channel_capture;
+          config.pipeline.multi_channel_capture ||
+      config_.pipeline.maximum_internal_processing_rate !=
+          config.pipeline.maximum_internal_processing_rate;
 
   const bool aec_config_changed =
       config_.echo_canceller.enabled != config.echo_canceller.enabled ||
@@ -1199,6 +1207,13 @@
 
   AudioBuffer* capture_buffer = capture_.capture_audio.get();  // For brevity.
 
+  if (submodules_.high_pass_filter &&
+      config_.high_pass_filter.apply_in_full_band &&
+      !constants_.enforce_split_band_hpf) {
+    submodules_.high_pass_filter->Process(capture_buffer,
+                                          /*use_split_band_data=*/false);
+  }
+
   if (submodules_.pre_amplifier) {
     submodules_.pre_amplifier->ApplyGain(AudioFrameView<float>(
         capture_buffer->channels(), capture_buffer->num_channels(),
@@ -1267,8 +1282,11 @@
     capture_buffer->set_num_channels(1);
   }
 
-  if (submodules_.high_pass_filter) {
-    submodules_.high_pass_filter->Process(capture_buffer);
+  if (submodules_.high_pass_filter &&
+      (!config_.high_pass_filter.apply_in_full_band ||
+       constants_.enforce_split_band_hpf)) {
+    submodules_.high_pass_filter->Process(capture_buffer,
+                                          /*use_split_band_data=*/true);
   }
 
   RETURN_ON_ERR(submodules_.gain_control->AnalyzeCaptureAudio(*capture_buffer));
@@ -1760,7 +1778,14 @@
       !config_.echo_canceller.mobile_mode;
   if (submodule_states_.HighPassFilteringRequired() ||
       high_pass_filter_needed_by_aec) {
-    submodules_.high_pass_filter.reset(new HighPassFilter(num_proc_channels()));
+    bool use_full_band = config_.high_pass_filter.apply_in_full_band &&
+                         !constants_.enforce_split_band_hpf;
+    int rate = use_full_band ? proc_fullband_sample_rate_hz()
+                             : proc_split_sample_rate_hz();
+    size_t num_channels =
+        use_full_band ? num_output_channels() : num_proc_channels();
+
+    submodules_.high_pass_filter.reset(new HighPassFilter(rate, num_channels));
   } else {
     submodules_.high_pass_filter.reset();
   }
diff --git a/modules/audio_processing/audio_processing_impl.h b/modules/audio_processing/audio_processing_impl.h
index 08379ad..29a3c8d 100644
--- a/modules/audio_processing/audio_processing_impl.h
+++ b/modules/audio_processing/audio_processing_impl.h
@@ -372,7 +372,8 @@
                  bool use_experimental_agc_agc2_level_estimation,
                  bool use_experimental_agc_agc2_digital_adaptive,
                  bool multi_channel_render_support,
-                 bool multi_channel_capture_support)
+                 bool multi_channel_capture_support,
+                 bool enforce_split_band_hpf)
         : agc_startup_min_volume(agc_startup_min_volume),
           agc_clipped_level_min(agc_clipped_level_min),
           use_experimental_agc(use_experimental_agc),
@@ -381,7 +382,8 @@
           use_experimental_agc_agc2_digital_adaptive(
               use_experimental_agc_agc2_digital_adaptive),
           multi_channel_render_support(multi_channel_render_support),
-          multi_channel_capture_support(multi_channel_capture_support) {}
+          multi_channel_capture_support(multi_channel_capture_support),
+          enforce_split_band_hpf(enforce_split_band_hpf) {}
     int agc_startup_min_volume;
     int agc_clipped_level_min;
     bool use_experimental_agc;
@@ -389,6 +391,7 @@
     bool use_experimental_agc_agc2_digital_adaptive;
     bool multi_channel_render_support;
     bool multi_channel_capture_support;
+    bool enforce_split_band_hpf;
   } constants_;
 
   struct ApmCaptureState {
diff --git a/modules/audio_processing/audio_processing_unittest.cc b/modules/audio_processing/audio_processing_unittest.cc
index 0fd07bf..9355c11 100644
--- a/modules/audio_processing/audio_processing_unittest.cc
+++ b/modules/audio_processing/audio_processing_unittest.cc
@@ -209,6 +209,7 @@
   apm_config.high_pass_filter.enabled = true;
   apm_config.level_estimation.enabled = true;
   apm_config.voice_detection.enabled = true;
+  apm_config.pipeline.maximum_internal_processing_rate = 48000;
   ap->ApplyConfig(apm_config);
 }
 
@@ -432,6 +433,9 @@
   Config config;
   config.Set<ExperimentalAgc>(new ExperimentalAgc(false));
   apm_.reset(AudioProcessingBuilder().Create(config));
+  AudioProcessing::Config apm_config = apm_->GetConfig();
+  apm_config.pipeline.maximum_internal_processing_rate = 48000;
+  apm_->ApplyConfig(apm_config);
 }
 
 void ApmTest::SetUp() {
@@ -1961,11 +1965,7 @@
       } else {
         ref_rate = 8000;
       }
-#ifdef WEBRTC_ARCH_ARM_FAMILY
-      if (file_direction == kForward) {
-        ref_rate = std::min(ref_rate, 32000);
-      }
-#endif
+
       FILE* out_file = fopen(
           OutputFilePath("out", input_rate_, output_rate_, reverse_input_rate_,
                          reverse_output_rate_, cf[i].num_input,
@@ -2087,9 +2087,9 @@
                       std::make_tuple(44100, 16000, 32000, 16000, 25, 20),
                       std::make_tuple(44100, 16000, 16000, 16000, 25, 0),
 
-                      std::make_tuple(32000, 48000, 48000, 48000, 30, 0),
-                      std::make_tuple(32000, 48000, 32000, 48000, 32, 30),
-                      std::make_tuple(32000, 48000, 16000, 48000, 30, 20),
+                      std::make_tuple(32000, 48000, 48000, 48000, 15, 0),
+                      std::make_tuple(32000, 48000, 32000, 48000, 15, 30),
+                      std::make_tuple(32000, 48000, 16000, 48000, 15, 20),
                       std::make_tuple(32000, 44100, 48000, 44100, 19, 20),
                       std::make_tuple(32000, 44100, 32000, 44100, 19, 15),
                       std::make_tuple(32000, 44100, 16000, 44100, 19, 15),
@@ -2100,9 +2100,9 @@
                       std::make_tuple(32000, 16000, 32000, 16000, 25, 20),
                       std::make_tuple(32000, 16000, 16000, 16000, 25, 0),
 
-                      std::make_tuple(16000, 48000, 48000, 48000, 23, 0),
-                      std::make_tuple(16000, 48000, 32000, 48000, 24, 30),
-                      std::make_tuple(16000, 48000, 16000, 48000, 24, 20),
+                      std::make_tuple(16000, 48000, 48000, 48000, 9, 0),
+                      std::make_tuple(16000, 48000, 32000, 48000, 9, 30),
+                      std::make_tuple(16000, 48000, 16000, 48000, 9, 20),
                       std::make_tuple(16000, 44100, 48000, 44100, 15, 20),
                       std::make_tuple(16000, 44100, 32000, 44100, 15, 15),
                       std::make_tuple(16000, 44100, 16000, 44100, 15, 15),
@@ -2143,9 +2143,9 @@
                       std::make_tuple(44100, 16000, 32000, 16000, 19, 20),
                       std::make_tuple(44100, 16000, 16000, 16000, 19, 0),
 
-                      std::make_tuple(32000, 48000, 48000, 48000, 27, 0),
-                      std::make_tuple(32000, 48000, 32000, 48000, 65, 30),
-                      std::make_tuple(32000, 48000, 16000, 48000, 30, 20),
+                      std::make_tuple(32000, 48000, 48000, 48000, 17, 0),
+                      std::make_tuple(32000, 48000, 32000, 48000, 17, 30),
+                      std::make_tuple(32000, 48000, 16000, 48000, 17, 20),
                       std::make_tuple(32000, 44100, 48000, 44100, 20, 20),
                       std::make_tuple(32000, 44100, 32000, 44100, 20, 15),
                       std::make_tuple(32000, 44100, 16000, 44100, 20, 15),
@@ -2156,9 +2156,9 @@
                       std::make_tuple(32000, 16000, 32000, 16000, 20, 20),
                       std::make_tuple(32000, 16000, 16000, 16000, 20, 0),
 
-                      std::make_tuple(16000, 48000, 48000, 48000, 23, 0),
-                      std::make_tuple(16000, 48000, 32000, 48000, 24, 30),
-                      std::make_tuple(16000, 48000, 16000, 48000, 25, 20),
+                      std::make_tuple(16000, 48000, 48000, 48000, 11, 0),
+                      std::make_tuple(16000, 48000, 32000, 48000, 11, 30),
+                      std::make_tuple(16000, 48000, 16000, 48000, 11, 20),
                       std::make_tuple(16000, 44100, 48000, 44100, 15, 20),
                       std::make_tuple(16000, 44100, 32000, 44100, 15, 15),
                       std::make_tuple(16000, 44100, 16000, 44100, 15, 15),
diff --git a/modules/audio_processing/high_pass_filter.cc b/modules/audio_processing/high_pass_filter.cc
index bd953e3..bff7209 100644
--- a/modules/audio_processing/high_pass_filter.cc
+++ b/modules/audio_processing/high_pass_filter.cc
@@ -18,30 +18,67 @@
 
 namespace {
 // [B,A] = butter(2,100/8000,'high')
-constexpr CascadedBiQuadFilter::BiQuadCoefficients kHighPassFilterCoefficients =
-    {{0.97261f, -1.94523f, 0.97261f}, {-1.94448f, 0.94598f}};
+constexpr CascadedBiQuadFilter::BiQuadCoefficients
+    kHighPassFilterCoefficients16kHz = {{0.97261f, -1.94523f, 0.97261f},
+                                        {-1.94448f, 0.94598f}};
+
+// [B,A] = butter(2,100/16000,'high')
+constexpr CascadedBiQuadFilter::BiQuadCoefficients
+    kHighPassFilterCoefficients32kHz = {{0.98621f, -1.97242f, 0.98621f},
+                                        {-1.97223f, 0.97261f}};
+
+// [B,A] = butter(2,100/24000,'high')
+constexpr CascadedBiQuadFilter::BiQuadCoefficients
+    kHighPassFilterCoefficients48kHz = {{0.99079f, -1.98157f, 0.99079f},
+                                        {-1.98149f, 0.98166f}};
 
 constexpr size_t kNumberOfHighPassBiQuads = 1;
 
+const CascadedBiQuadFilter::BiQuadCoefficients& ChooseCoefficients(
+    int sample_rate_hz) {
+  switch (sample_rate_hz) {
+    case 16000:
+      return kHighPassFilterCoefficients16kHz;
+    case 32000:
+      return kHighPassFilterCoefficients32kHz;
+    case 48000:
+      return kHighPassFilterCoefficients48kHz;
+    default:
+      RTC_NOTREACHED();
+  }
+  RTC_NOTREACHED();
+  return kHighPassFilterCoefficients16kHz;
+}
+
 }  // namespace
 
-HighPassFilter::HighPassFilter(size_t num_channels) {
+HighPassFilter::HighPassFilter(int sample_rate_hz, size_t num_channels)
+    : sample_rate_hz_(sample_rate_hz) {
   filters_.resize(num_channels);
+  const auto& coefficients = ChooseCoefficients(sample_rate_hz_);
   for (size_t k = 0; k < filters_.size(); ++k) {
-    filters_[k].reset(new CascadedBiQuadFilter(kHighPassFilterCoefficients,
-                                               kNumberOfHighPassBiQuads));
+    filters_[k].reset(
+        new CascadedBiQuadFilter(coefficients, kNumberOfHighPassBiQuads));
   }
 }
 
 HighPassFilter::~HighPassFilter() = default;
 
-void HighPassFilter::Process(AudioBuffer* audio) {
+void HighPassFilter::Process(AudioBuffer* audio, bool use_split_band_data) {
   RTC_DCHECK(audio);
   RTC_DCHECK_EQ(filters_.size(), audio->num_channels());
-  for (size_t k = 0; k < audio->num_channels(); ++k) {
-    rtc::ArrayView<float> channel_data = rtc::ArrayView<float>(
-        audio->split_bands(k)[0], audio->num_frames_per_band());
-    filters_[k]->Process(channel_data);
+  if (use_split_band_data) {
+    for (size_t k = 0; k < audio->num_channels(); ++k) {
+      rtc::ArrayView<float> channel_data = rtc::ArrayView<float>(
+          audio->split_bands(k)[0], audio->num_frames_per_band());
+      filters_[k]->Process(channel_data);
+    }
+  } else {
+    for (size_t k = 0; k < audio->num_channels(); ++k) {
+      rtc::ArrayView<float> channel_data =
+          rtc::ArrayView<float>(&audio->channels()[k][0], audio->num_frames());
+      filters_[k]->Process(channel_data);
+    }
   }
 }
 
@@ -67,9 +104,10 @@
     for (size_t k = 0; k < old_num_channels; ++k) {
       filters_[k]->Reset();
     }
+    const auto& coefficients = ChooseCoefficients(sample_rate_hz_);
     for (size_t k = old_num_channels; k < filters_.size(); ++k) {
-      filters_[k].reset(new CascadedBiQuadFilter(kHighPassFilterCoefficients,
-                                                 kNumberOfHighPassBiQuads));
+      filters_[k].reset(
+          new CascadedBiQuadFilter(coefficients, kNumberOfHighPassBiQuads));
     }
   }
 }
diff --git a/modules/audio_processing/high_pass_filter.h b/modules/audio_processing/high_pass_filter.h
index 87105ce..d396383 100644
--- a/modules/audio_processing/high_pass_filter.h
+++ b/modules/audio_processing/high_pass_filter.h
@@ -21,20 +21,20 @@
 
 class AudioBuffer;
 
-// Filters that high
 class HighPassFilter {
  public:
-  explicit HighPassFilter(size_t num_channels);
+  HighPassFilter(int sample_rate_hz, size_t num_channels);
   ~HighPassFilter();
   HighPassFilter(const HighPassFilter&) = delete;
   HighPassFilter& operator=(const HighPassFilter&) = delete;
 
-  void Process(AudioBuffer* audio);
+  void Process(AudioBuffer* audio, bool use_split_band_data);
   void Process(std::vector<std::vector<float>>* audio);
   void Reset();
   void Reset(size_t num_channels);
 
  private:
+  const int sample_rate_hz_;
   std::vector<std::unique_ptr<CascadedBiQuadFilter>> filters_;
 };
 }  // namespace webrtc
diff --git a/modules/audio_processing/high_pass_filter_unittest.cc b/modules/audio_processing/high_pass_filter_unittest.cc
index 56ccb95..f8e7226 100644
--- a/modules/audio_processing/high_pass_filter_unittest.cc
+++ b/modules/audio_processing/high_pass_filter_unittest.cc
@@ -32,7 +32,7 @@
       stream_config.sample_rate_hz(), stream_config.num_channels());
 
   test::CopyVectorToAudioBuffer(stream_config, frame_input, &audio_buffer);
-  high_pass_filter->Process(&audio_buffer);
+  high_pass_filter->Process(&audio_buffer, /*use_split_band_data=*/false);
   std::vector<float> frame_output;
   test::ExtractVectorFromAudioBuffer(stream_config, &audio_buffer,
                                      &frame_output);
@@ -76,7 +76,7 @@
                          const std::vector<float>& input,
                          const std::vector<float>& reference) {
   const StreamConfig stream_config(16000, num_channels, false);
-  HighPassFilter high_pass_filter(num_channels);
+  HighPassFilter high_pass_filter(16000, num_channels);
 
   std::vector<float> output;
   const size_t num_frames_to_process =
@@ -135,7 +135,7 @@
   const StreamConfig stream_config_mono(16000, 1, false);
   std::vector<float> x_mono(160, 1.f);
   std::vector<float> x_stereo(320, 1.f);
-  HighPassFilter hpf(1);
+  HighPassFilter hpf(16000, 1);
   std::vector<float> y =
       ProcessOneFrameAsAudioBuffer(x_mono, stream_config_mono, &hpf);
   hpf.Reset(2);
@@ -151,7 +151,7 @@
   const StreamConfig stream_config_mono(16000, 1, false);
   std::vector<float> x_mono(160, 1.f);
   std::vector<float> x_stereo(320, 1.f);
-  HighPassFilter hpf(1);
+  HighPassFilter hpf(16000, 1);
   std::vector<float> y =
       ProcessOneFrameAsVector(x_mono, stream_config_mono, &hpf);
   hpf.Reset(2);
diff --git a/modules/audio_processing/include/audio_processing.h b/modules/audio_processing/include/audio_processing.h
index 2f67919..5ab591b 100644
--- a/modules/audio_processing/include/audio_processing.h
+++ b/modules/audio_processing/include/audio_processing.h
@@ -224,6 +224,7 @@
 
     struct HighPassFilter {
       bool enabled = false;
+      bool apply_in_full_band = true;
     } high_pass_filter;
 
     struct EchoCanceller {