/*
 *  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 <array>
#include <vector>

#include "api/array_view.h"
#include "common_audio/include/audio_util.h"
#include "modules/audio_processing/agc2/agc2_common.h"
#include "modules/audio_processing/agc2/compute_interpolated_gain_curve.h"
#include "modules/audio_processing/agc2/interpolated_gain_curve.h"
#include "modules/audio_processing/agc2/limiter.h"
#include "modules/audio_processing/logging/apm_data_dumper.h"
#include "rtc_base/checks.h"
#include "rtc_base/gunit.h"

namespace webrtc {
namespace {

constexpr double kLevelEpsilon = 1e-2 * kMaxAbsFloatS16Value;
constexpr float kInterpolatedGainCurveTolerance = 1.f / 32768.f;
ApmDataDumper apm_data_dumper(0);
const Limiter limiter;

}  // namespace

TEST(AutomaticGainController2InterpolatedGainCurve, CreateUse) {
  InterpolatedGainCurve igc(&apm_data_dumper);

  const auto levels = test::LinSpace(
      kLevelEpsilon, DbfsToFloatS16(limiter.max_input_level_db() + 1), 500);
  for (const auto level : levels) {
    EXPECT_GE(igc.LookUpGainToApply(level), 0.0f);
  }
}

TEST(AutomaticGainController2InterpolatedGainCurve, CheckValidOutput) {
  InterpolatedGainCurve igc(&apm_data_dumper);

  const auto levels = test::LinSpace(
      kLevelEpsilon, limiter.max_input_level_linear() * 2.0, 500);
  for (const auto level : levels) {
    SCOPED_TRACE(std::to_string(level));
    const float gain = igc.LookUpGainToApply(level);
    EXPECT_LE(0.0f, gain);
    EXPECT_LE(gain, 1.0f);
  }
}

TEST(AutomaticGainController2InterpolatedGainCurve, CheckMonotonicity) {
  InterpolatedGainCurve igc(&apm_data_dumper);

  const auto levels = test::LinSpace(
      kLevelEpsilon, limiter.max_input_level_linear() + kLevelEpsilon + 0.5,
      500);
  float prev_gain = igc.LookUpGainToApply(0.0f);
  for (const auto level : levels) {
    const float gain = igc.LookUpGainToApply(level);
    EXPECT_GE(prev_gain, gain);
    prev_gain = gain;
  }
}

TEST(AutomaticGainController2InterpolatedGainCurve, CheckApproximation) {
  InterpolatedGainCurve igc(&apm_data_dumper);

  const auto levels = test::LinSpace(
      kLevelEpsilon, limiter.max_input_level_linear() - kLevelEpsilon, 500);
  for (const auto level : levels) {
    SCOPED_TRACE(std::to_string(level));
    EXPECT_LT(
        std::fabs(limiter.GetGainLinear(level) - igc.LookUpGainToApply(level)),
        kInterpolatedGainCurveTolerance);
  }
}

TEST(AutomaticGainController2InterpolatedGainCurve, CheckRegionBoundaries) {
  InterpolatedGainCurve igc(&apm_data_dumper);

  const std::vector<double> levels{
      {kLevelEpsilon, limiter.knee_start_linear() + kLevelEpsilon,
       limiter.limiter_start_linear() + kLevelEpsilon,
       limiter.max_input_level_linear() + kLevelEpsilon}};
  for (const auto level : levels) {
    igc.LookUpGainToApply(level);
  }

  const auto stats = igc.get_stats();
  EXPECT_EQ(1ul, stats.look_ups_identity_region);
  EXPECT_EQ(1ul, stats.look_ups_knee_region);
  EXPECT_EQ(1ul, stats.look_ups_limiter_region);
  EXPECT_EQ(1ul, stats.look_ups_saturation_region);
}

TEST(AutomaticGainController2InterpolatedGainCurve, CheckIdentityRegion) {
  constexpr size_t kNumSteps = 10;
  InterpolatedGainCurve igc(&apm_data_dumper);

  const auto levels =
      test::LinSpace(kLevelEpsilon, limiter.knee_start_linear(), kNumSteps);
  for (const auto level : levels) {
    SCOPED_TRACE(std::to_string(level));
    EXPECT_EQ(1.0f, igc.LookUpGainToApply(level));
  }

  const auto stats = igc.get_stats();
  EXPECT_EQ(kNumSteps - 1, stats.look_ups_identity_region);
  EXPECT_EQ(1ul, stats.look_ups_knee_region);
  EXPECT_EQ(0ul, stats.look_ups_limiter_region);
  EXPECT_EQ(0ul, stats.look_ups_saturation_region);
}

TEST(AutomaticGainController2InterpolatedGainCurve,
     CheckNoOverApproximationKnee) {
  constexpr size_t kNumSteps = 10;
  InterpolatedGainCurve igc(&apm_data_dumper);

  const auto levels =
      test::LinSpace(limiter.knee_start_linear() + kLevelEpsilon,
                     limiter.limiter_start_linear(), kNumSteps);
  for (const auto level : levels) {
    SCOPED_TRACE(std::to_string(level));
    // Small tolerance added (needed because comparing a float with a double).
    EXPECT_LE(igc.LookUpGainToApply(level),
              limiter.GetGainLinear(level) + 1e-7);
  }

  const auto stats = igc.get_stats();
  EXPECT_EQ(0ul, stats.look_ups_identity_region);
  EXPECT_EQ(kNumSteps - 1, stats.look_ups_knee_region);
  EXPECT_EQ(1ul, stats.look_ups_limiter_region);
  EXPECT_EQ(0ul, stats.look_ups_saturation_region);
}

TEST(AutomaticGainController2InterpolatedGainCurve,
     CheckNoOverApproximationBeyondKnee) {
  constexpr size_t kNumSteps = 10;
  InterpolatedGainCurve igc(&apm_data_dumper);

  const auto levels = test::LinSpace(
      limiter.limiter_start_linear() + kLevelEpsilon,
      limiter.max_input_level_linear() - kLevelEpsilon, kNumSteps);
  for (const auto level : levels) {
    SCOPED_TRACE(std::to_string(level));
    // Small tolerance added (needed because comparing a float with a double).
    EXPECT_LE(igc.LookUpGainToApply(level),
              limiter.GetGainLinear(level) + 1e-7);
  }

  const auto stats = igc.get_stats();
  EXPECT_EQ(0ul, stats.look_ups_identity_region);
  EXPECT_EQ(0ul, stats.look_ups_knee_region);
  EXPECT_EQ(kNumSteps, stats.look_ups_limiter_region);
  EXPECT_EQ(0ul, stats.look_ups_saturation_region);
}

TEST(AutomaticGainController2InterpolatedGainCurve,
     CheckNoOverApproximationWithSaturation) {
  constexpr size_t kNumSteps = 3;
  InterpolatedGainCurve igc(&apm_data_dumper);

  const auto levels = test::LinSpace(
      limiter.max_input_level_linear() + kLevelEpsilon,
      limiter.max_input_level_linear() + kLevelEpsilon + 0.5, kNumSteps);
  for (const auto level : levels) {
    SCOPED_TRACE(std::to_string(level));
    EXPECT_LE(igc.LookUpGainToApply(level), limiter.GetGainLinear(level));
  }

  const auto stats = igc.get_stats();
  EXPECT_EQ(0ul, stats.look_ups_identity_region);
  EXPECT_EQ(0ul, stats.look_ups_knee_region);
  EXPECT_EQ(0ul, stats.look_ups_limiter_region);
  EXPECT_EQ(kNumSteps, stats.look_ups_saturation_region);
}

TEST(AutomaticGainController2InterpolatedGainCurve, CheckApproximationParams) {
  test::InterpolatedParameters parameters =
      test::ComputeInterpolatedGainCurveApproximationParams();

  InterpolatedGainCurve igc(&apm_data_dumper);

  for (size_t i = 0; i < kInterpolatedGainCurveTotalPoints; ++i) {
    // The tolerance levels are chosen to account for deviations due
    // to computing with single precision floating point numbers.
    EXPECT_NEAR(igc.approximation_params_x_[i],
                parameters.computed_approximation_params_x[i], 0.9f);
    EXPECT_NEAR(igc.approximation_params_m_[i],
                parameters.computed_approximation_params_m[i], 0.00001f);
    EXPECT_NEAR(igc.approximation_params_q_[i],
                parameters.computed_approximation_params_q[i], 0.001f);
  }
}

}  // namespace webrtc
