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

#include <math.h>

#include <algorithm>
#include <cmath>
#include <numeric>

#include "test/gtest.h"

namespace webrtc {
namespace {

constexpr float kPi = 3.141592f;

void ProduceSinusoid(int sample_rate_hz,
                     float sinusoidal_frequency_hz,
                     size_t* sample_counter,
                     rtc::ArrayView<float> x) {
  // Produce a sinusoid of the specified frequency.
  for (size_t k = *sample_counter, j = 0; k < (*sample_counter + kBlockSize);
       ++k, ++j) {
    x[j] = 32767.f *
           std::sin(2.f * kPi * sinusoidal_frequency_hz * k / sample_rate_hz);
  }
  *sample_counter = *sample_counter + kBlockSize;
}

}  // namespace

#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)

// Verifies the check for null suppressor output.
TEST(SuppressionFilter, NullOutput) {
  FftData cn;
  FftData cn_high_bands;
  FftData E;
  std::array<float, kFftLengthBy2Plus1> gain;

  EXPECT_DEATH(SuppressionFilter(Aec3Optimization::kNone, 16000)
                   .ApplyGain(cn, cn_high_bands, gain, 1.0f, E, nullptr),
               "");
}

// Verifies the check for allowed sample rate.
TEST(SuppressionFilter, ProperSampleRate) {
  EXPECT_DEATH(SuppressionFilter(Aec3Optimization::kNone, 16001), "");
}

#endif

// Verifies that no comfort noise is added when the gain is 1.
TEST(SuppressionFilter, ComfortNoiseInUnityGain) {
  SuppressionFilter filter(Aec3Optimization::kNone, 48000);
  FftData cn;
  FftData cn_high_bands;
  std::array<float, kFftLengthBy2Plus1> gain;
  std::array<float, kFftLengthBy2> e_old_;
  Aec3Fft fft;

  e_old_.fill(0.f);
  gain.fill(1.f);
  cn.re.fill(1.f);
  cn.im.fill(1.f);
  cn_high_bands.re.fill(1.f);
  cn_high_bands.im.fill(1.f);

  std::vector<std::vector<float>> e(3, std::vector<float>(kBlockSize, 0.f));
  std::vector<std::vector<float>> e_ref = e;

  FftData E;
  fft.PaddedFft(e[0], e_old_, Aec3Fft::Window::kSqrtHanning, &E);
  std::copy(e[0].begin(), e[0].end(), e_old_.begin());

  filter.ApplyGain(cn, cn_high_bands, gain, 1.f, E, &e);

  for (size_t k = 0; k < e.size(); ++k) {
    EXPECT_EQ(e_ref[k], e[k]);
  }
}

// Verifies that the suppressor is able to suppress a signal.
TEST(SuppressionFilter, SignalSuppression) {
  SuppressionFilter filter(Aec3Optimization::kNone, 48000);
  FftData cn;
  FftData cn_high_bands;
  std::array<float, kFftLengthBy2> e_old_;
  Aec3Fft fft;
  std::array<float, kFftLengthBy2Plus1> gain;
  std::vector<std::vector<float>> e(3, std::vector<float>(kBlockSize, 0.f));
  e_old_.fill(0.f);

  gain.fill(1.f);
  std::for_each(gain.begin() + 10, gain.end(), [](float& a) { a = 0.f; });

  cn.re.fill(0.f);
  cn.im.fill(0.f);
  cn_high_bands.re.fill(0.f);
  cn_high_bands.im.fill(0.f);

  size_t sample_counter = 0;

  float e0_input = 0.f;
  float e0_output = 0.f;
  for (size_t k = 0; k < 100; ++k) {
    ProduceSinusoid(16000, 16000 * 40 / kFftLengthBy2 / 2, &sample_counter,
                    e[0]);
    e0_input =
        std::inner_product(e[0].begin(), e[0].end(), e[0].begin(), e0_input);

    FftData E;
    fft.PaddedFft(e[0], e_old_, Aec3Fft::Window::kSqrtHanning, &E);
    std::copy(e[0].begin(), e[0].end(), e_old_.begin());

    filter.ApplyGain(cn, cn_high_bands, gain, 1.f, E, &e);
    e0_output =
        std::inner_product(e[0].begin(), e[0].end(), e[0].begin(), e0_output);
  }

  EXPECT_LT(e0_output, e0_input / 1000.f);
}

// Verifies that the suppressor is able to pass through a desired signal while
// applying suppressing for some frequencies.
TEST(SuppressionFilter, SignalTransparency) {
  SuppressionFilter filter(Aec3Optimization::kNone, 48000);
  FftData cn;
  std::array<float, kFftLengthBy2> e_old_;
  Aec3Fft fft;
  FftData cn_high_bands;
  std::array<float, kFftLengthBy2Plus1> gain;
  std::vector<std::vector<float>> e(3, std::vector<float>(kBlockSize, 0.f));
  e_old_.fill(0.f);
  gain.fill(1.f);
  std::for_each(gain.begin() + 30, gain.end(), [](float& a) { a = 0.f; });

  cn.re.fill(0.f);
  cn.im.fill(0.f);
  cn_high_bands.re.fill(0.f);
  cn_high_bands.im.fill(0.f);

  size_t sample_counter = 0;

  float e0_input = 0.f;
  float e0_output = 0.f;
  for (size_t k = 0; k < 100; ++k) {
    ProduceSinusoid(16000, 16000 * 10 / kFftLengthBy2 / 2, &sample_counter,
                    e[0]);
    e0_input =
        std::inner_product(e[0].begin(), e[0].end(), e[0].begin(), e0_input);

    FftData E;
    fft.PaddedFft(e[0], e_old_, Aec3Fft::Window::kSqrtHanning, &E);
    std::copy(e[0].begin(), e[0].end(), e_old_.begin());

    filter.ApplyGain(cn, cn_high_bands, gain, 1.f, E, &e);
    e0_output =
        std::inner_product(e[0].begin(), e[0].end(), e[0].begin(), e0_output);
  }

  EXPECT_LT(0.9f * e0_input, e0_output);
}

// Verifies that the suppressor delay.
TEST(SuppressionFilter, Delay) {
  SuppressionFilter filter(Aec3Optimization::kNone, 48000);
  FftData cn;
  FftData cn_high_bands;
  std::array<float, kFftLengthBy2> e_old_;
  Aec3Fft fft;
  std::array<float, kFftLengthBy2Plus1> gain;
  std::vector<std::vector<float>> e(3, std::vector<float>(kBlockSize, 0.f));

  gain.fill(1.f);

  cn.re.fill(0.f);
  cn.im.fill(0.f);
  cn_high_bands.re.fill(0.f);
  cn_high_bands.im.fill(0.f);

  for (size_t k = 0; k < 100; ++k) {
    for (size_t j = 0; j < 3; ++j) {
      for (size_t i = 0; i < kBlockSize; ++i) {
        e[j][i] = k * kBlockSize + i;
      }
    }

    FftData E;
    fft.PaddedFft(e[0], e_old_, Aec3Fft::Window::kSqrtHanning, &E);
    std::copy(e[0].begin(), e[0].end(), e_old_.begin());

    filter.ApplyGain(cn, cn_high_bands, gain, 1.f, E, &e);
    if (k > 2) {
      for (size_t j = 0; j < 2; ++j) {
        for (size_t i = 0; i < kBlockSize; ++i) {
          EXPECT_NEAR(k * kBlockSize + i - kBlockSize, e[j][i], 0.01);
        }
      }
    }
  }
}

}  // namespace webrtc
