Bypass unnecessary resampling.

This change keeps the original 48 kHz signal and uses it for the
fullband processing given that the following requirements are
fulfilled:
- Input signal is 48 kHz
- Output signal is 48 kHz
- Multiband processing is performed at 32 kHz
- The multiband processing does not modify the original signal
This avoids unnecessary, lossy resampling and band merging.

Bug: b/130016532
Change-Id: I690c26faba07eab0cbff6c0a95a81d89255dd1a1
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/155966
Commit-Queue: Gustaf Ullberg <gustaf@webrtc.org>
Reviewed-by: Per Ã…hgren <peah@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#29425}
diff --git a/api/audio/echo_control.h b/api/audio/echo_control.h
index f549f40..c8f73b8 100644
--- a/api/audio/echo_control.h
+++ b/api/audio/echo_control.h
@@ -41,6 +41,9 @@
   // Provides an optional external estimate of the audio buffer delay.
   virtual void SetAudioBufferDelay(size_t delay_ms) = 0;
 
+  // Returns wheter the signal is altered.
+  virtual bool ActiveProcessing() const = 0;
+
   virtual ~EchoControl() {}
 };
 
diff --git a/modules/audio_processing/aec3/echo_canceller3.cc b/modules/audio_processing/aec3/echo_canceller3.cc
index 85b2dc7..ffff1b6 100644
--- a/modules/audio_processing/aec3/echo_canceller3.cc
+++ b/modules/audio_processing/aec3/echo_canceller3.cc
@@ -371,6 +371,10 @@
   block_processor_->SetAudioBufferDelay(delay_ms);
 }
 
+bool EchoCanceller3::ActiveProcessing() const {
+  return true;
+}
+
 void EchoCanceller3::EmptyRenderQueue() {
   RTC_DCHECK_RUNS_SERIALIZED(&capture_race_checker_);
   bool frame_to_buffer =
diff --git a/modules/audio_processing/aec3/echo_canceller3.h b/modules/audio_processing/aec3/echo_canceller3.h
index 5b59674..7a7df07 100644
--- a/modules/audio_processing/aec3/echo_canceller3.h
+++ b/modules/audio_processing/aec3/echo_canceller3.h
@@ -111,6 +111,8 @@
   // Provides an optional external estimate of the audio buffer delay.
   void SetAudioBufferDelay(size_t delay_ms) override;
 
+  bool ActiveProcessing() const override;
+
   // Signals whether an external detector has detected echo leakage from the
   // echo canceller.
   // Note that in the case echo leakage has been flagged, it should be unflagged
diff --git a/modules/audio_processing/audio_processing_impl.cc b/modules/audio_processing/audio_processing_impl.cc
index ceb1006..3a70791 100644
--- a/modules/audio_processing/audio_processing_impl.cc
+++ b/modules/audio_processing/audio_processing_impl.cc
@@ -206,14 +206,21 @@
 
 bool AudioProcessingImpl::ApmSubmoduleStates::CaptureMultiBandSubModulesActive()
     const {
-  return CaptureMultiBandProcessingActive() || voice_detector_enabled_;
+  return CaptureMultiBandProcessingPresent() || voice_detector_enabled_;
 }
 
-bool AudioProcessingImpl::ApmSubmoduleStates::CaptureMultiBandProcessingActive()
-    const {
+bool AudioProcessingImpl::ApmSubmoduleStates::
+    CaptureMultiBandProcessingPresent() const {
+  // If echo controller is present, assume it performs active processing.
+  return CaptureMultiBandProcessingActive(/*ec_processing_active=*/true);
+}
+
+bool AudioProcessingImpl::ApmSubmoduleStates::CaptureMultiBandProcessingActive(
+    bool ec_processing_active) const {
   return high_pass_filter_enabled_ || echo_canceller_enabled_ ||
          mobile_echo_controller_enabled_ || noise_suppressor_enabled_ ||
-         adaptive_gain_controller_enabled_ || echo_controller_enabled_;
+         adaptive_gain_controller_enabled_ ||
+         (echo_controller_enabled_ && ec_processing_active);
 }
 
 bool AudioProcessingImpl::ApmSubmoduleStates::CaptureFullBandProcessingActive()
@@ -987,6 +994,10 @@
 
   capture_.keyboard_info.Extract(src, formats_.api_format.input_stream());
   capture_.capture_audio->CopyFrom(src, formats_.api_format.input_stream());
+  if (capture_.capture_fullband_audio) {
+    capture_.capture_fullband_audio->CopyFrom(
+        src, formats_.api_format.input_stream());
+  }
   RETURN_ON_ERR(ProcessCaptureStreamLocked());
   if (capture_.capture_fullband_audio) {
     capture_.capture_fullband_audio->CopyTo(formats_.api_format.output_stream(),
@@ -1287,7 +1298,7 @@
 
   capture_.capture_audio->CopyFrom(frame);
   RETURN_ON_ERR(ProcessCaptureStreamLocked());
-  if (submodule_states_.CaptureMultiBandProcessingActive() ||
+  if (submodule_states_.CaptureMultiBandProcessingPresent() ||
       submodule_states_.CaptureFullBandProcessingActive()) {
     if (capture_.capture_fullband_audio) {
       capture_.capture_fullband_audio->CopyTo(frame);
@@ -1469,14 +1480,20 @@
       private_submodules_->echo_cancellation &&
           private_submodules_->echo_cancellation->stream_has_echo()));
 
-  if (submodule_states_.CaptureMultiBandProcessingActive() &&
+  if (submodule_states_.CaptureMultiBandProcessingPresent() &&
       SampleRateSupportsMultiBand(
           capture_nonlocked_.capture_processing_format.sample_rate_hz())) {
     capture_buffer->MergeFrequencyBands();
   }
 
   if (capture_.capture_fullband_audio) {
-    capture_buffer->CopyTo(capture_.capture_fullband_audio.get());
+    const auto& ec = private_submodules_->echo_controller;
+    bool ec_active = ec ? ec->ActiveProcessing() : false;
+    // Only update the fullband buffer if the multiband processing has changed
+    // the signal. Keep the original signal otherwise.
+    if (submodule_states_.CaptureMultiBandProcessingActive(ec_active)) {
+      capture_buffer->CopyTo(capture_.capture_fullband_audio.get());
+    }
     capture_buffer = capture_.capture_fullband_audio.get();
   }
 
diff --git a/modules/audio_processing/audio_processing_impl.h b/modules/audio_processing/audio_processing_impl.h
index c8e8c01..5d07fe3 100644
--- a/modules/audio_processing/audio_processing_impl.h
+++ b/modules/audio_processing/audio_processing_impl.h
@@ -185,7 +185,8 @@
                 bool level_estimator_enabled,
                 bool transient_suppressor_enabled);
     bool CaptureMultiBandSubModulesActive() const;
-    bool CaptureMultiBandProcessingActive() const;
+    bool CaptureMultiBandProcessingPresent() const;
+    bool CaptureMultiBandProcessingActive(bool ec_processing_active) const;
     bool CaptureFullBandProcessingActive() const;
     bool CaptureAnalyzerActive() const;
     bool RenderMultiBandSubModulesActive() const;
diff --git a/modules/audio_processing/include/mock_audio_processing.h b/modules/audio_processing/include/mock_audio_processing.h
index e989fea..c5a1f09 100644
--- a/modules/audio_processing/include/mock_audio_processing.h
+++ b/modules/audio_processing/include/mock_audio_processing.h
@@ -89,6 +89,7 @@
                void(AudioBuffer* capture, bool echo_path_change));
   MOCK_CONST_METHOD0(GetMetrics, Metrics());
   MOCK_METHOD1(SetAudioBufferDelay, void(size_t delay_ms));
+  MOCK_CONST_METHOD0(ActiveProcessing, bool());
 };
 
 class MockAudioProcessing : public ::testing::NiceMock<AudioProcessing> {
diff --git a/modules/audio_processing/test/echo_control_mock.h b/modules/audio_processing/test/echo_control_mock.h
index 0386762..8479a7c 100644
--- a/modules/audio_processing/test/echo_control_mock.h
+++ b/modules/audio_processing/test/echo_control_mock.h
@@ -26,6 +26,7 @@
                void(AudioBuffer* capture, bool echo_path_change));
   MOCK_CONST_METHOD0(GetMetrics, EchoControl::Metrics());
   MOCK_METHOD1(SetAudioBufferDelay, void(size_t delay_ms));
+  MOCK_CONST_METHOD0(ActiveProcessing, bool());
 };
 
 }  // namespace webrtc