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

#include "modules/audio_processing/logging/apm_data_dumper.h"
#include "test/gtest.h"

namespace webrtc {

// Verify the general functionality of AecState
TEST(AecState, NormalUsage) {
  ApmDataDumper data_dumper(42);
  AecState state(EchoCanceller3Config{});
  RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 30,
                             std::vector<size_t>(1, 30));
  std::array<float, kFftLengthBy2Plus1> E2_main = {};
  std::array<float, kFftLengthBy2Plus1> Y2 = {};
  std::vector<std::vector<float>> x(3, std::vector<float>(kBlockSize, 0.f));
  EchoPathVariability echo_path_variability(false, false);
  std::array<float, kBlockSize> s;
  s.fill(100.f);

  std::vector<std::array<float, kFftLengthBy2Plus1>>
      converged_filter_frequency_response(10);
  for (auto& v : converged_filter_frequency_response) {
    v.fill(0.01f);
  }
  std::vector<std::array<float, kFftLengthBy2Plus1>>
      diverged_filter_frequency_response = converged_filter_frequency_response;
  converged_filter_frequency_response[2].fill(100.f);
  converged_filter_frequency_response[2][0] = 1.f;

  std::array<float, kAdaptiveFilterTimeDomainLength> impulse_response;
  impulse_response.fill(0.f);

  // Verify that linear AEC usability is false when the filter is diverged and
  // there is no external delay reported.
  state.Update(diverged_filter_frequency_response, impulse_response, true,
               rtc::Optional<size_t>(), render_buffer, E2_main, Y2, x[0], s,
               false);
  EXPECT_FALSE(state.UsableLinearEstimate());

  // Verify that linear AEC usability is true when the filter is converged
  std::fill(x[0].begin(), x[0].end(), 101.f);
  for (int k = 0; k < 3000; ++k) {
    state.Update(converged_filter_frequency_response, impulse_response, true,
                 rtc::Optional<size_t>(2), render_buffer, E2_main, Y2, x[0], s,
                 false);
  }
  EXPECT_TRUE(state.UsableLinearEstimate());

  // Verify that linear AEC usability becomes false after an echo path change is
  // reported
  state.HandleEchoPathChange(EchoPathVariability(true, false));
  state.Update(converged_filter_frequency_response, impulse_response, true,
               rtc::Optional<size_t>(2), render_buffer, E2_main, Y2, x[0], s,
               false);
  EXPECT_FALSE(state.UsableLinearEstimate());

  // Verify that the active render detection works as intended.
  std::fill(x[0].begin(), x[0].end(), 101.f);
  state.HandleEchoPathChange(EchoPathVariability(true, true));
  state.Update(converged_filter_frequency_response, impulse_response, true,
               rtc::Optional<size_t>(2), render_buffer, E2_main, Y2, x[0], s,
               false);
  EXPECT_FALSE(state.ActiveRender());

  for (int k = 0; k < 1000; ++k) {
    state.Update(converged_filter_frequency_response, impulse_response, true,
                 rtc::Optional<size_t>(2), render_buffer, E2_main, Y2, x[0], s,
                 false);
  }
  EXPECT_TRUE(state.ActiveRender());

  // Verify that echo leakage is properly reported.
  state.Update(converged_filter_frequency_response, impulse_response, true,
               rtc::Optional<size_t>(2), render_buffer, E2_main, Y2, x[0], s,
               false);
  EXPECT_FALSE(state.EchoLeakageDetected());

  state.Update(converged_filter_frequency_response, impulse_response, true,
               rtc::Optional<size_t>(2), render_buffer, E2_main, Y2, x[0], s,
               true);
  EXPECT_TRUE(state.EchoLeakageDetected());

  // Verify that the ERL is properly estimated
  for (auto& x_k : x) {
    x_k = std::vector<float>(kBlockSize, 0.f);
  }

  x[0][0] = 5000.f;
  for (size_t k = 0; k < render_buffer.Buffer().size(); ++k) {
    render_buffer.Insert(x);
  }

  Y2.fill(10.f * 10000.f * 10000.f);
  for (size_t k = 0; k < 1000; ++k) {
    state.Update(converged_filter_frequency_response, impulse_response, true,
                 rtc::Optional<size_t>(2), render_buffer, E2_main, Y2, x[0], s,
                 false);
  }

  ASSERT_TRUE(state.UsableLinearEstimate());
  const std::array<float, kFftLengthBy2Plus1>& erl = state.Erl();
  EXPECT_EQ(erl[0], erl[1]);
  for (size_t k = 1; k < erl.size() - 1; ++k) {
    EXPECT_NEAR(k % 2 == 0 ? 10.f : 1000.f, erl[k], 0.1);
  }
  EXPECT_EQ(erl[erl.size() - 2], erl[erl.size() - 1]);

  // Verify that the ERLE is properly estimated
  E2_main.fill(1.f * 10000.f * 10000.f);
  Y2.fill(10.f * E2_main[0]);
  for (size_t k = 0; k < 1000; ++k) {
    state.Update(converged_filter_frequency_response, impulse_response, true,
                 rtc::Optional<size_t>(2), render_buffer, E2_main, Y2, x[0], s,
                 false);
  }
  ASSERT_TRUE(state.UsableLinearEstimate());
  {
    const auto& erle = state.Erle();
    EXPECT_EQ(erle[0], erle[1]);
    constexpr size_t kLowFrequencyLimit = 32;
    for (size_t k = 1; k < kLowFrequencyLimit; ++k) {
      EXPECT_NEAR(k % 2 == 0 ? 8.f : 1.f, erle[k], 0.1);
    }
    for (size_t k = kLowFrequencyLimit; k < erle.size() - 1; ++k) {
      EXPECT_NEAR(k % 2 == 0 ? 1.5f : 1.f, erle[k], 0.1);
    }
    EXPECT_EQ(erle[erle.size() - 2], erle[erle.size() - 1]);
  }

  E2_main.fill(1.f * 10000.f * 10000.f);
  Y2.fill(5.f * E2_main[0]);
  for (size_t k = 0; k < 1000; ++k) {
    state.Update(converged_filter_frequency_response, impulse_response, true,
                 rtc::Optional<size_t>(2), render_buffer, E2_main, Y2, x[0], s,
                 false);
  }

  ASSERT_TRUE(state.UsableLinearEstimate());
  {
    const auto& erle = state.Erle();
    EXPECT_EQ(erle[0], erle[1]);
    constexpr size_t kLowFrequencyLimit = 32;
    for (size_t k = 1; k < kLowFrequencyLimit; ++k) {
      EXPECT_NEAR(k % 2 == 0 ? 5.f : 1.f, erle[k], 0.1);
    }
    for (size_t k = kLowFrequencyLimit; k < erle.size() - 1; ++k) {
      EXPECT_NEAR(k % 2 == 0 ? 1.5f : 1.f, erle[k], 0.1);
    }
    EXPECT_EQ(erle[erle.size() - 2], erle[erle.size() - 1]);
  }
}

// Verifies the delay for a converged filter is correctly identified.
TEST(AecState, ConvergedFilterDelay) {
  constexpr int kFilterLength = 10;
  AecState state(EchoCanceller3Config{});
  RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 30,
                             std::vector<size_t>(1, 30));
  std::array<float, kFftLengthBy2Plus1> E2_main;
  std::array<float, kFftLengthBy2Plus1> Y2;
  std::array<float, kBlockSize> x;
  EchoPathVariability echo_path_variability(false, false);
  std::array<float, kBlockSize> s;
  s.fill(100.f);
  x.fill(0.f);

  std::vector<std::array<float, kFftLengthBy2Plus1>> frequency_response(
      kFilterLength);

  std::array<float, kAdaptiveFilterTimeDomainLength> impulse_response;
  impulse_response.fill(0.f);

  // Verify that the filter delay for a converged filter is properly identified.
  for (int k = 0; k < kFilterLength; ++k) {
    for (auto& v : frequency_response) {
      v.fill(0.01f);
    }
    frequency_response[k].fill(100.f);
    frequency_response[k][0] = 0.f;
    state.HandleEchoPathChange(echo_path_variability);
    state.Update(frequency_response, impulse_response, true,
                 rtc::Optional<size_t>(), render_buffer, E2_main, Y2, x, s,
                 false);
    EXPECT_TRUE(k == (kFilterLength - 1) || state.FilterDelay());
    if (k != (kFilterLength - 1)) {
      EXPECT_EQ(k, state.FilterDelay());
    }
  }
}

// Verify that the externally reported delay is properly reported and converted.
TEST(AecState, ExternalDelay) {
  AecState state(EchoCanceller3Config{});
  std::array<float, kFftLengthBy2Plus1> E2_main;
  std::array<float, kFftLengthBy2Plus1> E2_shadow;
  std::array<float, kFftLengthBy2Plus1> Y2;
  std::array<float, kBlockSize> x;
  std::array<float, kBlockSize> s;
  s.fill(100.f);
  E2_main.fill(0.f);
  E2_shadow.fill(0.f);
  Y2.fill(0.f);
  x.fill(0.f);
  RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 30,
                             std::vector<size_t>(1, 30));
  std::vector<std::array<float, kFftLengthBy2Plus1>> frequency_response(
      kAdaptiveFilterLength);
  for (auto& v : frequency_response) {
    v.fill(0.01f);
  }

  std::array<float, kAdaptiveFilterTimeDomainLength> impulse_response;
  impulse_response.fill(0.f);

  for (size_t k = 0; k < frequency_response.size() - 1; ++k) {
    state.HandleEchoPathChange(EchoPathVariability(false, false));
    state.Update(frequency_response, impulse_response, true,
                 rtc::Optional<size_t>(k * kBlockSize + 5), render_buffer,
                 E2_main, Y2, x, s, false);
    EXPECT_TRUE(state.ExternalDelay());
    EXPECT_EQ(k, state.ExternalDelay());
  }

  // Verify that the externally reported delay is properly unset when it is no
  // longer present.
  state.HandleEchoPathChange(EchoPathVariability(false, false));
  state.Update(frequency_response, impulse_response, true,
               rtc::Optional<size_t>(), render_buffer, E2_main, Y2, x, s,
               false);
  EXPECT_FALSE(state.ExternalDelay());
}

}  // namespace webrtc
