/*
 *  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/fullband_erle_estimator.h"

#include <algorithm>
#include <memory>
#include <numeric>

#include "absl/types/optional.h"
#include "api/array_view.h"
#include "modules/audio_processing/aec3/aec3_common.h"
#include "modules/audio_processing/logging/apm_data_dumper.h"
#include "rtc_base/checks.h"
#include "rtc_base/numerics/safe_minmax.h"

namespace webrtc {

namespace {
constexpr float kEpsilon = 1e-3f;
constexpr float kX2BandEnergyThreshold = 44015068.0f;
constexpr int kBlocksToHoldErle = 100;
constexpr int kPointsToAccumulate = 6;
}  // namespace

FullBandErleEstimator::FullBandErleEstimator(
    const EchoCanceller3Config::Erle& config,
    size_t num_capture_channels)
    : min_erle_log2_(FastApproxLog2f(config.min + kEpsilon)),
      max_erle_lf_log2_(FastApproxLog2f(config.max_l + kEpsilon)),
      hold_counters_instantaneous_erle_(num_capture_channels, 0),
      erle_time_domain_log2_(num_capture_channels, min_erle_log2_),
      instantaneous_erle_(num_capture_channels, ErleInstantaneous(config)),
      linear_filters_qualities_(num_capture_channels) {
  Reset();
}

FullBandErleEstimator::~FullBandErleEstimator() = default;

void FullBandErleEstimator::Reset() {
  for (auto& instantaneous_erle_ch : instantaneous_erle_) {
    instantaneous_erle_ch.Reset();
  }

  UpdateQualityEstimates();
  std::fill(erle_time_domain_log2_.begin(), erle_time_domain_log2_.end(),
            min_erle_log2_);
  std::fill(hold_counters_instantaneous_erle_.begin(),
            hold_counters_instantaneous_erle_.end(), 0);
}

void FullBandErleEstimator::Update(
    rtc::ArrayView<const float> X2,
    rtc::ArrayView<const std::array<float, kFftLengthBy2Plus1>> Y2,
    rtc::ArrayView<const std::array<float, kFftLengthBy2Plus1>> E2,
    const std::vector<bool>& converged_filters) {
  for (size_t ch = 0; ch < Y2.size(); ++ch) {
    if (converged_filters[ch]) {
      // Computes the fullband ERLE.
      const float X2_sum = std::accumulate(X2.begin(), X2.end(), 0.0f);
      if (X2_sum > kX2BandEnergyThreshold * X2.size()) {
        const float Y2_sum =
            std::accumulate(Y2[ch].begin(), Y2[ch].end(), 0.0f);
        const float E2_sum =
            std::accumulate(E2[ch].begin(), E2[ch].end(), 0.0f);
        if (instantaneous_erle_[ch].Update(Y2_sum, E2_sum)) {
          hold_counters_instantaneous_erle_[ch] = kBlocksToHoldErle;
          erle_time_domain_log2_[ch] +=
              0.05f * ((instantaneous_erle_[ch].GetInstErleLog2().value()) -
                       erle_time_domain_log2_[ch]);
          erle_time_domain_log2_[ch] =
              std::max(erle_time_domain_log2_[ch], min_erle_log2_);
        }
      }
    }
    --hold_counters_instantaneous_erle_[ch];
    if (hold_counters_instantaneous_erle_[ch] == 0) {
      instantaneous_erle_[ch].ResetAccumulators();
    }
  }

  UpdateQualityEstimates();
}

void FullBandErleEstimator::Dump(
    const std::unique_ptr<ApmDataDumper>& data_dumper) const {
  data_dumper->DumpRaw("aec3_fullband_erle_log2", FullbandErleLog2());
  instantaneous_erle_[0].Dump(data_dumper);
}

void FullBandErleEstimator::UpdateQualityEstimates() {
  for (size_t ch = 0; ch < instantaneous_erle_.size(); ++ch) {
    linear_filters_qualities_[ch] =
        instantaneous_erle_[ch].GetQualityEstimate();
  }
}

FullBandErleEstimator::ErleInstantaneous::ErleInstantaneous(
    const EchoCanceller3Config::Erle& config)
    : clamp_inst_quality_to_zero_(config.clamp_quality_estimate_to_zero),
      clamp_inst_quality_to_one_(config.clamp_quality_estimate_to_one) {
  Reset();
}

FullBandErleEstimator::ErleInstantaneous::~ErleInstantaneous() = default;

bool FullBandErleEstimator::ErleInstantaneous::Update(const float Y2_sum,
                                                      const float E2_sum) {
  bool update_estimates = false;
  E2_acum_ += E2_sum;
  Y2_acum_ += Y2_sum;
  num_points_++;
  if (num_points_ == kPointsToAccumulate) {
    if (E2_acum_ > 0.f) {
      update_estimates = true;
      erle_log2_ = FastApproxLog2f(Y2_acum_ / E2_acum_ + kEpsilon);
    }
    num_points_ = 0;
    E2_acum_ = 0.f;
    Y2_acum_ = 0.f;
  }

  if (update_estimates) {
    UpdateMaxMin();
    UpdateQualityEstimate();
  }
  return update_estimates;
}

void FullBandErleEstimator::ErleInstantaneous::Reset() {
  ResetAccumulators();
  max_erle_log2_ = -10.f;  // -30 dB.
  min_erle_log2_ = 33.f;   // 100 dB.
  inst_quality_estimate_ = 0.f;
}

void FullBandErleEstimator::ErleInstantaneous::ResetAccumulators() {
  erle_log2_ = absl::nullopt;
  inst_quality_estimate_ = 0.f;
  num_points_ = 0;
  E2_acum_ = 0.f;
  Y2_acum_ = 0.f;
}

void FullBandErleEstimator::ErleInstantaneous::Dump(
    const std::unique_ptr<ApmDataDumper>& data_dumper) const {
  data_dumper->DumpRaw("aec3_fullband_erle_inst_log2",
                       erle_log2_ ? *erle_log2_ : -10.f);
  data_dumper->DumpRaw(
      "aec3_erle_instantaneous_quality",
      GetQualityEstimate() ? GetQualityEstimate().value() : 0.f);
  data_dumper->DumpRaw("aec3_fullband_erle_max_log2", max_erle_log2_);
  data_dumper->DumpRaw("aec3_fullband_erle_min_log2", min_erle_log2_);
}

void FullBandErleEstimator::ErleInstantaneous::UpdateMaxMin() {
  RTC_DCHECK(erle_log2_);
  // Adding the forgetting factors for the maximum and minimum and capping the
  // result to the incoming value.
  max_erle_log2_ -= 0.0004f;  // Forget factor, approx 1dB every 3 sec.
  max_erle_log2_ = std::max(max_erle_log2_, erle_log2_.value());
  min_erle_log2_ += 0.0004f;  // Forget factor, approx 1dB every 3 sec.
  min_erle_log2_ = std::min(min_erle_log2_, erle_log2_.value());
}

void FullBandErleEstimator::ErleInstantaneous::UpdateQualityEstimate() {
  const float alpha = 0.07f;
  float quality_estimate = 0.f;
  RTC_DCHECK(erle_log2_);
  // TODO(peah): Currently, the estimate can become be less than 0; this should
  // be corrected.
  if (max_erle_log2_ > min_erle_log2_) {
    quality_estimate = (erle_log2_.value() - min_erle_log2_) /
                       (max_erle_log2_ - min_erle_log2_);
  }
  if (quality_estimate > inst_quality_estimate_) {
    inst_quality_estimate_ = quality_estimate;
  } else {
    inst_quality_estimate_ +=
        alpha * (quality_estimate - inst_quality_estimate_);
  }
}

}  // namespace webrtc
