| Index: webrtc/modules/audio_processing/aec3/residual_echo_estimator.cc
 | 
| diff --git a/webrtc/modules/audio_processing/aec3/residual_echo_estimator.cc b/webrtc/modules/audio_processing/aec3/residual_echo_estimator.cc
 | 
| new file mode 100644
 | 
| index 0000000000000000000000000000000000000000..e84439dbd9778008372bc8632c8e8d31f0827ec8
 | 
| --- /dev/null
 | 
| +++ b/webrtc/modules/audio_processing/aec3/residual_echo_estimator.cc
 | 
| @@ -0,0 +1,76 @@
 | 
| +/*
 | 
| + *  Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
 | 
| + *
 | 
| + *  Use of this source code is governed by a BSD-style license
 | 
| + *  that can be found in the LICENSE file in the root of the source
 | 
| + *  tree. An additional intellectual property rights grant can be found
 | 
| + *  in the file PATENTS.  All contributing project authors may
 | 
| + *  be found in the AUTHORS file in the root of the source tree.
 | 
| + */
 | 
| +
 | 
| +#include "webrtc/modules/audio_processing/aec3/residual_echo_estimator.h"
 | 
| +
 | 
| +#include <math.h>
 | 
| +#include <vector>
 | 
| +
 | 
| +#include "webrtc/base/checks.h"
 | 
| +
 | 
| +namespace webrtc {
 | 
| +
 | 
| +ResidualEchoEstimator::ResidualEchoEstimator() {
 | 
| +  echo_path_gain_.fill(0.f);
 | 
| +}
 | 
| +
 | 
| +ResidualEchoEstimator::~ResidualEchoEstimator() = default;
 | 
| +
 | 
| +void ResidualEchoEstimator::Estimate(
 | 
| +    const AecState& aec_state,
 | 
| +    const FftBuffer& X_buffer,
 | 
| +    const std::vector<std::array<float, kFftLengthBy2Plus1>>& H2,
 | 
| +    const std::array<float, kFftLengthBy2Plus1>& E2_main,
 | 
| +    const std::array<float, kFftLengthBy2Plus1>& E2_shadow,
 | 
| +    const std::array<float, kFftLengthBy2Plus1>& S2_linear,
 | 
| +    const std::array<float, kFftLengthBy2Plus1>& S2_fallback,
 | 
| +    const std::array<float, kFftLengthBy2Plus1>& Y2,
 | 
| +    const DelayHandler& delay_handler,
 | 
| +    std::array<float, kFftLengthBy2Plus1>* R2) {
 | 
| +  const rtc::Optional<size_t>& linear_filter_based_delay =
 | 
| +      delay_handler.FilterDelay();
 | 
| +  if (linear_filter_based_delay) {
 | 
| +    std::copy(H2[*linear_filter_based_delay].begin(),
 | 
| +              H2[*linear_filter_based_delay].end(), echo_path_gain_.begin());
 | 
| +  }
 | 
| +
 | 
| +  const std::array<bool, kFftLengthBy2Plus1>& bands_with_reliable_filter =
 | 
| +      aec_state.BandsWithReliableFilter();
 | 
| +
 | 
| +  if (aec_state.UsableLinearEstimate()) {
 | 
| +    const std::array<float, kFftLengthBy2Plus1>& erle = aec_state.Erle();
 | 
| +
 | 
| +    for (size_t k = 0; k < R2->size(); ++k) {
 | 
| +      RTC_DCHECK_LT(0.f, erle[k]);
 | 
| +      (*R2)[k] = bands_with_reliable_filter[k] ? S2_linear[k] / erle[k]
 | 
| +                                               : S2_fallback[k];
 | 
| +    }
 | 
| +
 | 
| +  } else if (aec_state.ModelBasedAecFeasible()) {
 | 
| +    const rtc::Optional<size_t>& provided_delay = delay_handler.ExternalDelay();
 | 
| +    RTC_DCHECK(provided_delay);
 | 
| +    const std::array<float, kFftLengthBy2Plus1>& X2 =
 | 
| +        X_buffer.Spectrum(*provided_delay);
 | 
| +    for (size_t k = 0; k < R2->size(); ++k) {
 | 
| +      (*R2)[k] = bands_with_reliable_filter[k] ? echo_path_gain_[k] * X2[k]
 | 
| +                                               : S2_fallback[k];
 | 
| +    }
 | 
| +  } else if (aec_state.EchoLeakageDetected()) {
 | 
| +    if (aec_state.ActiveRender()) {
 | 
| +      std::copy(Y2.begin(), Y2.end(), R2->begin());
 | 
| +    } else {
 | 
| +      R2->fill(0.f);
 | 
| +    }
 | 
| +  } else {
 | 
| +    R2->fill(0.f);
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +}  // namespace webrtc
 | 
| 
 |