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

#include <algorithm>
#include <iostream>
#include <string>

#include "api/audio/echo_canceller3_config.h"
#include "modules/audio_processing/aec3/render_buffer.h"
#include "modules/audio_processing/aec3/render_delay_buffer.h"
#include "rtc_base/strings/string_builder.h"
#include "test/gtest.h"

namespace webrtc {

namespace {

void GetActiveFrame(std::vector<std::vector<std::vector<float>>>* x) {
  const std::array<float, kBlockSize> frame = {
      7459.88, 17209.6, 17383,   20768.9, 16816.7, 18386.3, 4492.83, 9675.85,
      6665.52, 14808.6, 9342.3,  7483.28, 19261.7, 4145.98, 1622.18, 13475.2,
      7166.32, 6856.61, 21937,   7263.14, 9569.07, 14919,   8413.32, 7551.89,
      7848.65, 6011.27, 13080.6, 15865.2, 12656,   17459.6, 4263.93, 4503.03,
      9311.79, 21095.8, 12657.9, 13906.6, 19267.2, 11338.1, 16828.9, 11501.6,
      11405,   15031.4, 14541.6, 19765.5, 18346.3, 19350.2, 3157.47, 18095.8,
      1743.68, 21328.2, 19727.5, 7295.16, 10332.4, 11055.5, 20107.4, 14708.4,
      12416.2, 16434,   2454.69, 9840.8,  6867.23, 1615.75, 6059.9,  8394.19};
  for (size_t band = 0; band < x->size(); ++band) {
    for (size_t channel = 0; channel < (*x)[band].size(); ++channel) {
      RTC_DCHECK_GE((*x)[band][channel].size(), frame.size());
      std::copy(frame.begin(), frame.end(), (*x)[band][channel].begin());
    }
  }
}

class TestInputs {
 public:
  TestInputs(const EchoCanceller3Config& cfg,
             size_t num_render_channels,
             size_t num_capture_channels);
  ~TestInputs();
  const RenderBuffer& GetRenderBuffer() { return *render_buffer_; }
  rtc::ArrayView<const float, kFftLengthBy2Plus1> GetX2() { return X2_; }
  rtc::ArrayView<const std::array<float, kFftLengthBy2Plus1>> GetY2() const {
    return Y2_;
  }
  rtc::ArrayView<const std::array<float, kFftLengthBy2Plus1>> GetE2() const {
    return E2_;
  }
  rtc::ArrayView<const std::vector<std::array<float, kFftLengthBy2Plus1>>>
  GetH2() const {
    return H2_;
  }
  const std::vector<bool>& GetConvergedFilters() const {
    return converged_filters_;
  }
  void Update();

 private:
  void UpdateCurrentPowerSpectra();
  int n_ = 0;
  std::unique_ptr<RenderDelayBuffer> render_delay_buffer_;
  RenderBuffer* render_buffer_;
  std::array<float, kFftLengthBy2Plus1> X2_;
  std::vector<std::array<float, kFftLengthBy2Plus1>> Y2_;
  std::vector<std::array<float, kFftLengthBy2Plus1>> E2_;
  std::vector<std::vector<std::array<float, kFftLengthBy2Plus1>>> H2_;
  std::vector<std::vector<std::vector<float>>> x_;
  std::vector<bool> converged_filters_;
};

TestInputs::TestInputs(const EchoCanceller3Config& cfg,
                       size_t num_render_channels,
                       size_t num_capture_channels)
    : render_delay_buffer_(
          RenderDelayBuffer::Create(cfg, 16000, num_render_channels)),
      Y2_(num_capture_channels),
      E2_(num_capture_channels),
      H2_(num_capture_channels,
          std::vector<std::array<float, kFftLengthBy2Plus1>>(
              cfg.filter.main.length_blocks)),
      x_(1,
         std::vector<std::vector<float>>(num_render_channels,
                                         std::vector<float>(kBlockSize, 0.f))),
      converged_filters_(num_capture_channels, true) {
  render_delay_buffer_->AlignFromDelay(4);
  render_buffer_ = render_delay_buffer_->GetRenderBuffer();
  for (auto& H2_ch : H2_) {
    for (auto& H2_p : H2_ch) {
      H2_p.fill(0.f);
    }
  }
  for (auto& H2_p : H2_[0]) {
    H2_p.fill(1.f);
  }
}

TestInputs::~TestInputs() = default;

void TestInputs::Update() {
  if (n_ % 2 == 0) {
    std::fill(x_[0][0].begin(), x_[0][0].end(), 0.f);
  } else {
    GetActiveFrame(&x_);
  }

  render_delay_buffer_->Insert(x_);
  render_delay_buffer_->PrepareCaptureProcessing();
  UpdateCurrentPowerSpectra();
  ++n_;
}

void TestInputs::UpdateCurrentPowerSpectra() {
  const SpectrumBuffer& spectrum_render_buffer =
      render_buffer_->GetSpectrumBuffer();
  size_t idx = render_buffer_->Position();
  size_t prev_idx = spectrum_render_buffer.OffsetIndex(idx, 1);
  auto& X2 = spectrum_render_buffer.buffer[idx][/*channel=*/0];
  auto& X2_prev = spectrum_render_buffer.buffer[prev_idx][/*channel=*/0];
  std::copy(X2.begin(), X2.end(), X2_.begin());
  for (size_t ch = 0; ch < Y2_.size(); ++ch) {
    RTC_DCHECK_EQ(X2.size(), Y2_[ch].size());
    for (size_t k = 0; k < X2.size(); ++k) {
      E2_[ch][k] = 0.01f * X2_prev[k];
      Y2_[ch][k] = X2[k] + E2_[ch][k];
    }
  }
}

}  // namespace

TEST(SignalDependentErleEstimator, SweepSettings) {
  for (size_t num_render_channels : {1, 2, 4}) {
    for (size_t num_capture_channels : {1, 2, 4}) {
      EchoCanceller3Config cfg;
      size_t max_length_blocks = 50;
      for (size_t blocks = 0; blocks < max_length_blocks;
           blocks = blocks + 10) {
        for (size_t delay_headroom = 0; delay_headroom < 5; ++delay_headroom) {
          for (size_t num_sections = 2; num_sections < max_length_blocks;
               ++num_sections) {
            cfg.filter.main.length_blocks = blocks;
            cfg.filter.main_initial.length_blocks =
                std::min(cfg.filter.main_initial.length_blocks, blocks);
            cfg.delay.delay_headroom_samples = delay_headroom * kBlockSize;
            cfg.erle.num_sections = num_sections;
            if (EchoCanceller3Config::Validate(&cfg)) {
              SignalDependentErleEstimator s(cfg, num_capture_channels);
              std::vector<std::array<float, kFftLengthBy2Plus1>> average_erle(
                  num_capture_channels);
              for (auto& e : average_erle) {
                e.fill(cfg.erle.max_l);
              }
              TestInputs inputs(cfg, num_render_channels, num_capture_channels);
              for (size_t n = 0; n < 10; ++n) {
                inputs.Update();
                s.Update(inputs.GetRenderBuffer(), inputs.GetH2(),
                         inputs.GetX2(), inputs.GetY2(), inputs.GetE2(),
                         average_erle, inputs.GetConvergedFilters());
              }
            }
          }
        }
      }
    }
  }
}

TEST(SignalDependentErleEstimator, LongerRun) {
  for (size_t num_render_channels : {1, 2, 4}) {
    for (size_t num_capture_channels : {1, 2, 4}) {
      EchoCanceller3Config cfg;
      cfg.filter.main.length_blocks = 2;
      cfg.filter.main_initial.length_blocks = 1;
      cfg.delay.delay_headroom_samples = 0;
      cfg.delay.hysteresis_limit_blocks = 0;
      cfg.erle.num_sections = 2;
      EXPECT_EQ(EchoCanceller3Config::Validate(&cfg), true);
      std::vector<std::array<float, kFftLengthBy2Plus1>> average_erle(
          num_capture_channels);
      for (auto& e : average_erle) {
        e.fill(cfg.erle.max_l);
      }
      SignalDependentErleEstimator s(cfg, num_capture_channels);
      TestInputs inputs(cfg, num_render_channels, num_capture_channels);
      for (size_t n = 0; n < 200; ++n) {
        inputs.Update();
        s.Update(inputs.GetRenderBuffer(), inputs.GetH2(), inputs.GetX2(),
                 inputs.GetY2(), inputs.GetE2(), average_erle,
                 inputs.GetConvergedFilters());
      }
    }
  }
}

}  // namespace webrtc
