/*
 *  Copyright (c) 2018 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 "modules/audio_processing/aec3/subband_erle_estimator.h"

#include <algorithm>
#include <functional>

#include "rtc_base/checks.h"
#include "rtc_base/numerics/safe_minmax.h"
#include "system_wrappers/include/field_trial.h"

namespace webrtc {

namespace {

constexpr float kX2BandEnergyThreshold = 44015068.0f;
constexpr int kBlocksToHoldErle = 100;
constexpr int kBlocksForOnsetDetection = kBlocksToHoldErle + 150;
constexpr int kPointsToAccumulate = 6;

std::array<float, kFftLengthBy2Plus1> SetMaxErleBands(float max_erle_l,
                                                      float max_erle_h) {
  std::array<float, kFftLengthBy2Plus1> max_erle;
  std::fill(max_erle.begin(), max_erle.begin() + kFftLengthBy2 / 2, max_erle_l);
  std::fill(max_erle.begin() + kFftLengthBy2 / 2, max_erle.end(), max_erle_h);
  return max_erle;
}

bool EnableMinErleDuringOnsets() {
  return !field_trial::IsEnabled("WebRTC-Aec3MinErleDuringOnsetsKillSwitch");
}

}  // namespace

SubbandErleEstimator::SubbandErleEstimator(const EchoCanceller3Config& config)
    : min_erle_(config.erle.min),
      max_erle_(SetMaxErleBands(config.erle.max_l, config.erle.max_h)),
      use_min_erle_during_onsets_(EnableMinErleDuringOnsets()) {
  Reset();
}

SubbandErleEstimator::~SubbandErleEstimator() = default;

void SubbandErleEstimator::Reset() {
  erle_.fill(min_erle_);
  erle_onsets_.fill(min_erle_);
  coming_onset_.fill(true);
  hold_counters_.fill(0);
  ResetAccumulatedSpectra();
}

void SubbandErleEstimator::Update(rtc::ArrayView<const float> X2,
                                  rtc::ArrayView<const float> Y2,
                                  rtc::ArrayView<const float> E2,
                                  bool converged_filter,
                                  bool onset_detection) {
  if (converged_filter) {
    // Note that the use of the converged_filter flag already imposed
    // a minimum of the erle that can be estimated as that flag would
    // be false if the filter is performing poorly.
    UpdateAccumulatedSpectra(X2, Y2, E2);
    UpdateBands(onset_detection);
  }

  if (onset_detection) {
    DecreaseErlePerBandForLowRenderSignals();
  }

  erle_[0] = erle_[1];
  erle_[kFftLengthBy2] = erle_[kFftLengthBy2 - 1];
}

void SubbandErleEstimator::Dump(
    const std::unique_ptr<ApmDataDumper>& data_dumper) const {
  data_dumper->DumpRaw("aec3_erle_onset", ErleOnsets());
}

void SubbandErleEstimator::UpdateBands(bool onset_detection) {
  std::array<float, kFftLengthBy2> new_erle;
  std::array<bool, kFftLengthBy2> is_erle_updated;
  is_erle_updated.fill(false);

  for (size_t k = 1; k < kFftLengthBy2; ++k) {
    if (accum_spectra_.num_points_[k] == kPointsToAccumulate &&
        accum_spectra_.E2_[k] > 0.f) {
      new_erle[k] = accum_spectra_.Y2_[k] / accum_spectra_.E2_[k];
      is_erle_updated[k] = true;
    }
  }

  if (onset_detection) {
    for (size_t k = 1; k < kFftLengthBy2; ++k) {
      if (is_erle_updated[k] && !accum_spectra_.low_render_energy_[k]) {
        if (coming_onset_[k]) {
          coming_onset_[k] = false;
          if (!use_min_erle_during_onsets_) {
            float alpha = new_erle[k] < erle_onsets_[k] ? 0.3f : 0.15f;
            erle_onsets_[k] = rtc::SafeClamp(
                erle_onsets_[k] + alpha * (new_erle[k] - erle_onsets_[k]),
                min_erle_, max_erle_[k]);
          }
        }
        hold_counters_[k] = kBlocksForOnsetDetection;
      }
    }
  }

  for (size_t k = 1; k < kFftLengthBy2; ++k) {
    if (is_erle_updated[k]) {
      float alpha = 0.05f;
      if (new_erle[k] < erle_[k]) {
        alpha = accum_spectra_.low_render_energy_[k] ? 0.f : 0.1f;
      }
      erle_[k] = rtc::SafeClamp(erle_[k] + alpha * (new_erle[k] - erle_[k]),
                                min_erle_, max_erle_[k]);
    }
  }
}

void SubbandErleEstimator::DecreaseErlePerBandForLowRenderSignals() {
  for (size_t k = 1; k < kFftLengthBy2; ++k) {
    hold_counters_[k]--;
    if (hold_counters_[k] <= (kBlocksForOnsetDetection - kBlocksToHoldErle)) {
      if (erle_[k] > erle_onsets_[k]) {
        erle_[k] = std::max(erle_onsets_[k], 0.97f * erle_[k]);
        RTC_DCHECK_LE(min_erle_, erle_[k]);
      }
      if (hold_counters_[k] <= 0) {
        coming_onset_[k] = true;
        hold_counters_[k] = 0;
      }
    }
  }
}

void SubbandErleEstimator::ResetAccumulatedSpectra() {
  accum_spectra_.Y2_.fill(0.f);
  accum_spectra_.E2_.fill(0.f);
  accum_spectra_.num_points_.fill(0);
  accum_spectra_.low_render_energy_.fill(false);
}

void SubbandErleEstimator::UpdateAccumulatedSpectra(
    rtc::ArrayView<const float> X2,
    rtc::ArrayView<const float> Y2,
    rtc::ArrayView<const float> E2) {
  auto& st = accum_spectra_;
  if (st.num_points_[0] == kPointsToAccumulate) {
    st.num_points_[0] = 0;
    st.Y2_.fill(0.f);
    st.E2_.fill(0.f);
    st.low_render_energy_.fill(false);
  }
  std::transform(Y2.begin(), Y2.end(), st.Y2_.begin(), st.Y2_.begin(),
                 std::plus<float>());
  std::transform(E2.begin(), E2.end(), st.E2_.begin(), st.E2_.begin(),
                 std::plus<float>());

  for (size_t k = 0; k < X2.size(); ++k) {
    st.low_render_energy_[k] =
        st.low_render_energy_[k] || X2[k] < kX2BandEnergyThreshold;
  }
  st.num_points_[0]++;
  st.num_points_.fill(st.num_points_[0]);
}

}  // namespace webrtc
