/*
 *  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 "modules/audio_processing/aec3/suppression_gain.h"

#include "typedefs.h"
#if defined(WEBRTC_ARCH_X86_FAMILY)
#include <emmintrin.h>
#endif
#include <math.h>
#include <algorithm>
#include <functional>
#include <numeric>

#include "modules/audio_processing/aec3/vector_math.h"
#include "rtc_base/checks.h"

namespace webrtc {
namespace {

// Reduce gain to avoid narrow band echo leakage.
void NarrowBandAttenuation(int narrow_bin,
                           std::array<float, kFftLengthBy2Plus1>* gain) {
  const int upper_bin =
      std::min(narrow_bin + 6, static_cast<int>(kFftLengthBy2Plus1 - 1));
  for (int k = std::max(0, narrow_bin - 6); k <= upper_bin; ++k) {
    (*gain)[k] = std::min((*gain)[k], 0.001f);
  }
}

// Adjust the gains according to the presence of known external filters.
void AdjustForExternalFilters(std::array<float, kFftLengthBy2Plus1>* gain) {
  // Limit the low frequency gains to avoid the impact of the high-pass filter
  // on the lower-frequency gain influencing the overall achieved gain.
  (*gain)[0] = (*gain)[1] = std::min((*gain)[1], (*gain)[2]);

  // Limit the high frequency gains to avoid the impact of the anti-aliasing
  // filter on the upper-frequency gains influencing the overall achieved
  // gain. TODO(peah): Update this when new anti-aliasing filters are
  // implemented.
  constexpr size_t kAntiAliasingImpactLimit = (64 * 2000) / 8000;
  const float min_upper_gain = (*gain)[kAntiAliasingImpactLimit];
  std::for_each(
      gain->begin() + kAntiAliasingImpactLimit, gain->end() - 1,
      [min_upper_gain](float& a) { a = std::min(a, min_upper_gain); });
  (*gain)[kFftLengthBy2] = (*gain)[kFftLengthBy2Minus1];
}

// Computes the gain to apply for the bands beyond the first band.
float UpperBandsGain(
    const rtc::Optional<int>& narrow_peak_band,
    bool saturated_echo,
    const std::vector<std::vector<float>>& render,
    const std::array<float, kFftLengthBy2Plus1>& low_band_gain) {
  RTC_DCHECK_LT(0, render.size());
  if (render.size() == 1) {
    return 1.f;
  }

  if (narrow_peak_band &&
      (*narrow_peak_band > static_cast<int>(kFftLengthBy2Plus1 - 10))) {
    return 0.001f;
  }

  constexpr size_t kLowBandGainLimit = kFftLengthBy2 / 2;
  const float gain_below_8_khz = *std::min_element(
      low_band_gain.begin() + kLowBandGainLimit, low_band_gain.end());

  // Always attenuate the upper bands when there is saturated echo.
  if (saturated_echo) {
    return std::min(0.001f, gain_below_8_khz);
  }

  // Compute the upper and lower band energies.
  const auto sum_of_squares = [](float a, float b) { return a + b * b; };
  const float low_band_energy =
      std::accumulate(render[0].begin(), render[0].end(), 0.f, sum_of_squares);
  float high_band_energy = 0.f;
  for (size_t k = 1; k < render.size(); ++k) {
    const float energy = std::accumulate(render[k].begin(), render[k].end(),
                                         0.f, sum_of_squares);
    high_band_energy = std::max(high_band_energy, energy);
  }

  // If there is more power in the lower frequencies than the upper frequencies,
  // or if the power in upper frequencies is low, do not bound the gain in the
  // upper bands.
  float anti_howling_gain;
  constexpr float kThreshold = kSubBlockSize * 10.f * 10.f;
  if (high_band_energy < std::max(low_band_energy, kThreshold)) {
    anti_howling_gain = 1.f;
  } else {
    // In all other cases, bound the gain for upper frequencies.
    RTC_DCHECK_LE(low_band_energy, high_band_energy);
    RTC_DCHECK_NE(0.f, high_band_energy);
    anti_howling_gain = 0.01f * sqrtf(low_band_energy / high_band_energy);
  }

  // Choose the gain as the minimum of the lower and upper gains.
  return std::min(gain_below_8_khz, anti_howling_gain);
}

// Limits the gain increase.
void UpdateMaxGainIncrease(
    const AudioProcessing::Config::EchoCanceller3& config,
    size_t no_saturation_counter,
    bool low_noise_render,
    const std::array<float, kFftLengthBy2Plus1>& last_echo,
    const std::array<float, kFftLengthBy2Plus1>& echo,
    const std::array<float, kFftLengthBy2Plus1>& last_gain,
    const std::array<float, kFftLengthBy2Plus1>& new_gain,
    std::array<float, kFftLengthBy2Plus1>* gain_increase) {
  float max_increasing;
  float max_decreasing;
  float rate_increasing;
  float rate_decreasing;
  float min_increasing;
  float min_decreasing;

  auto& param = config.param.gain_updates;
  if (low_noise_render) {
    max_increasing = param.low_noise.max_inc;
    max_decreasing = param.low_noise.max_dec;
    rate_increasing = param.low_noise.rate_inc;
    rate_decreasing = param.low_noise.rate_dec;
    min_increasing = param.low_noise.min_inc;
    min_decreasing = param.low_noise.min_dec;
  } else if (no_saturation_counter > 10) {
    max_increasing = param.normal.max_inc;
    max_decreasing = param.normal.max_dec;
    rate_increasing = param.normal.rate_inc;
    rate_decreasing = param.normal.rate_dec;
    min_increasing = param.normal.min_inc;
    min_decreasing = param.normal.min_dec;
  } else {
    max_increasing = param.saturation.max_inc;
    max_decreasing = param.saturation.max_dec;
    rate_increasing = param.saturation.rate_inc;
    rate_decreasing = param.saturation.rate_dec;
    min_increasing = param.saturation.min_inc;
    min_decreasing = param.saturation.min_dec;
  }

  for (size_t k = 0; k < new_gain.size(); ++k) {
    if (echo[k] > last_echo[k]) {
      (*gain_increase)[k] =
          new_gain[k] > last_gain[k]
              ? std::min(max_increasing, (*gain_increase)[k] * rate_increasing)
              : min_increasing;
    } else {
      (*gain_increase)[k] =
          new_gain[k] > last_gain[k]
              ? std::min(max_decreasing, (*gain_increase)[k] * rate_decreasing)
              : min_decreasing;
    }
  }
}

// Computes the gain to reduce the echo to a non audible level.
void GainToNoAudibleEcho(
    const AudioProcessing::Config::EchoCanceller3& config,
    bool low_noise_render,
    bool saturated_echo,
    const std::array<float, kFftLengthBy2Plus1>& nearend,
    const std::array<float, kFftLengthBy2Plus1>& echo,
    const std::array<float, kFftLengthBy2Plus1>& masker,
    const std::array<float, kFftLengthBy2Plus1>& min_gain,
    const std::array<float, kFftLengthBy2Plus1>& max_gain,
    const std::array<float, kFftLengthBy2Plus1>& one_by_echo,
    std::array<float, kFftLengthBy2Plus1>* gain) {
  const float nearend_masking_margin =
      low_noise_render ? 0.1f
                       : (saturated_echo ? config.param.gain_mask.m2
                                         : config.param.gain_mask.m3);

  for (size_t k = 0; k < gain->size(); ++k) {
    RTC_DCHECK_LE(0.f, nearend_masking_margin * nearend[k]);
    if (echo[k] <= nearend_masking_margin * nearend[k]) {
      (*gain)[k] = 1.f;
    } else {
      (*gain)[k] = config.param.gain_mask.m1 * masker[k] * one_by_echo[k];
    }

    (*gain)[k] = std::min(std::max((*gain)[k], min_gain[k]), max_gain[k]);
  }
}

// Computes the signal output power that masks the echo signal.
void MaskingPower(const AudioProcessing::Config::EchoCanceller3& config,
                  const std::array<float, kFftLengthBy2Plus1>& nearend,
                  const std::array<float, kFftLengthBy2Plus1>& comfort_noise,
                  const std::array<float, kFftLengthBy2Plus1>& last_masker,
                  const std::array<float, kFftLengthBy2Plus1>& gain,
                  std::array<float, kFftLengthBy2Plus1>* masker) {
  std::array<float, kFftLengthBy2Plus1> side_band_masker;
  for (size_t k = 0; k < gain.size(); ++k) {
    side_band_masker[k] = nearend[k] * gain[k] + comfort_noise[k];
    (*masker)[k] =
        comfort_noise[k] + config.param.gain_mask.m4 * last_masker[k];
  }
  for (size_t k = 1; k < gain.size() - 1; ++k) {
    (*masker)[k] += 0.1f * (side_band_masker[k - 1] + side_band_masker[k + 1]);
  }
}

}  // namespace

// TODO(peah): Add further optimizations, in particular for the divisions.
void SuppressionGain::LowerBandGain(
    bool low_noise_render,
    const rtc::Optional<int>& narrow_peak_band,
    bool saturated_echo,
    const std::array<float, kFftLengthBy2Plus1>& nearend,
    const std::array<float, kFftLengthBy2Plus1>& echo,
    const std::array<float, kFftLengthBy2Plus1>& comfort_noise,
    std::array<float, kFftLengthBy2Plus1>* gain) {
  // Count the number of blocks since saturation.
  no_saturation_counter_ = saturated_echo ? 0 : no_saturation_counter_ + 1;

  // Precompute 1/echo (note that when the echo is zero, the precomputed value
  // is never used).
  std::array<float, kFftLengthBy2Plus1> one_by_echo;
  std::transform(echo.begin(), echo.end(), one_by_echo.begin(),
                 [](float a) { return a > 0.f ? 1.f / a : 1.f; });

  // Compute the minimum gain as the attenuating gain to put the signal just
  // above the zero sample values.
  std::array<float, kFftLengthBy2Plus1> min_gain;
  const float min_echo_power =
      low_noise_render ? config_.param.echo_audibility.low_render_limit
                       : config_.param.echo_audibility.normal_render_limit;
  if (no_saturation_counter_ > 10) {
    for (size_t k = 0; k < nearend.size(); ++k) {
      const float denom = std::min(nearend[k], echo[k]);
      min_gain[k] = denom > 0.f ? min_echo_power / denom : 1.f;
      min_gain[k] = std::min(min_gain[k], 1.f);
    }
  } else {
    min_gain.fill(0.f);
  }

  // Compute the maximum gain by limiting the gain increase from the previous
  // gain.
  std::array<float, kFftLengthBy2Plus1> max_gain;
  for (size_t k = 0; k < gain->size(); ++k) {
    max_gain[k] =
        std::min(std::max(last_gain_[k] * gain_increase_[k],
                          config_.param.gain_updates.floor_first_increase),
                 1.f);
  }

  // Iteratively compute the gain required to attenuate the echo to a non
  // noticeable level.
  gain->fill(0.f);
  for (int k = 0; k < 2; ++k) {
    std::array<float, kFftLengthBy2Plus1> masker;
    MaskingPower(config_, nearend, comfort_noise, last_masker_, *gain, &masker);
    GainToNoAudibleEcho(config_, low_noise_render, saturated_echo, nearend,
                        echo, masker, min_gain, max_gain, one_by_echo, gain);
    AdjustForExternalFilters(gain);
    if (narrow_peak_band) {
      NarrowBandAttenuation(*narrow_peak_band, gain);
    }
  }

  // Update the allowed maximum gain increase.
  UpdateMaxGainIncrease(config_, no_saturation_counter_, low_noise_render,
                        last_echo_, echo, last_gain_, *gain, &gain_increase_);

  // Store data required for the gain computation of the next block.
  std::copy(echo.begin(), echo.end(), last_echo_.begin());
  std::copy(gain->begin(), gain->end(), last_gain_.begin());
  MaskingPower(config_, nearend, comfort_noise, last_masker_, *gain,
               &last_masker_);
  aec3::VectorMath(optimization_).Sqrt(*gain);
}

SuppressionGain::SuppressionGain(
    const AudioProcessing::Config::EchoCanceller3& config,
    Aec3Optimization optimization)
    : optimization_(optimization), config_(config) {
  last_gain_.fill(1.f);
  last_masker_.fill(0.f);
  gain_increase_.fill(1.f);
  last_echo_.fill(0.f);
}

void SuppressionGain::GetGain(
    const std::array<float, kFftLengthBy2Plus1>& nearend,
    const std::array<float, kFftLengthBy2Plus1>& echo,
    const std::array<float, kFftLengthBy2Plus1>& comfort_noise,
    const RenderSignalAnalyzer& render_signal_analyzer,
    bool saturated_echo,
    const std::vector<std::vector<float>>& render,
    bool force_zero_gain,
    float* high_bands_gain,
    std::array<float, kFftLengthBy2Plus1>* low_band_gain) {
  RTC_DCHECK(high_bands_gain);
  RTC_DCHECK(low_band_gain);

  if (force_zero_gain) {
    last_gain_.fill(0.f);
    std::copy(comfort_noise.begin(), comfort_noise.end(), last_masker_.begin());
    low_band_gain->fill(0.f);
    gain_increase_.fill(1.f);
    *high_bands_gain = 0.f;
    return;
  }

  bool low_noise_render = low_render_detector_.Detect(render);

  // Compute gain for the lower band.
  const rtc::Optional<int> narrow_peak_band =
      render_signal_analyzer.NarrowPeakBand();
  LowerBandGain(low_noise_render, narrow_peak_band, saturated_echo, nearend,
                echo, comfort_noise, low_band_gain);

  // Compute the gain for the upper bands.
  *high_bands_gain =
      UpperBandsGain(narrow_peak_band, saturated_echo, render, *low_band_gain);
}

// Detects when the render signal can be considered to have low power and
// consist of stationary noise.
bool SuppressionGain::LowNoiseRenderDetector::Detect(
    const std::vector<std::vector<float>>& render) {
  float x2_sum = 0.f;
  float x2_max = 0.f;
  for (auto x_k : render[0]) {
    const float x2 = x_k * x_k;
    x2_sum += x2;
    x2_max = std::max(x2_max, x2);
  }

  constexpr float kThreshold = 50.f * 50.f * 64.f;
  const bool low_noise_render =
      average_power_ < kThreshold && x2_max < 3 * average_power_;
  average_power_ = average_power_ * 0.9f + x2_sum * 0.1f;
  return low_noise_render;
}

}  // namespace webrtc
