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

#include <math.h>

#include <algorithm>
#include <array>
#include <cmath>
#include <cstring>
#include <numeric>
#include <string>
#include <vector>

#include "modules/audio_processing/aec3/aec3_common.h"
#include "rtc_base/strings/string_builder.h"
#include "test/gtest.h"

namespace webrtc {

namespace {

std::string ProduceDebugText(int sample_rate_hz) {
  rtc::StringBuilder ss;
  ss << "Sample rate: " << sample_rate_hz;
  return ss.Release();
}

constexpr size_t kDownSamplingFactors[] = {2, 4, 8};
constexpr float kPi = 3.141592f;
constexpr size_t kNumStartupBlocks = 50;
constexpr size_t kNumBlocks = 1000;

void ProduceDecimatedSinusoidalOutputPower(int sample_rate_hz,
                                           size_t down_sampling_factor,
                                           float sinusoidal_frequency_hz,
                                           float* input_power,
                                           float* output_power) {
  float input[kBlockSize * kNumBlocks];
  const size_t sub_block_size = kBlockSize / down_sampling_factor;

  // Produce a sinusoid of the specified frequency.
  for (size_t k = 0; k < kBlockSize * kNumBlocks; ++k) {
    input[k] = 32767.f * std::sin(2.f * kPi * sinusoidal_frequency_hz * k /
                                  sample_rate_hz);
  }

  Decimator decimator(down_sampling_factor);
  std::vector<float> output(sub_block_size * kNumBlocks);

  for (size_t k = 0; k < kNumBlocks; ++k) {
    std::vector<float> sub_block(sub_block_size);
    std::vector<std::vector<float>> input_multichannel(
        1, std::vector<float>(kBlockSize));
    memcpy(input_multichannel[0].data(), &input[k * kBlockSize],
           kBlockSize * sizeof(float));
    decimator.Decimate(input_multichannel, true, sub_block);

    std::copy(sub_block.begin(), sub_block.end(),
              output.begin() + k * sub_block_size);
  }

  ASSERT_GT(kNumBlocks, kNumStartupBlocks);
  rtc::ArrayView<const float> input_to_evaluate(
      &input[kNumStartupBlocks * kBlockSize],
      (kNumBlocks - kNumStartupBlocks) * kBlockSize);
  rtc::ArrayView<const float> output_to_evaluate(
      &output[kNumStartupBlocks * sub_block_size],
      (kNumBlocks - kNumStartupBlocks) * sub_block_size);
  *input_power =
      std::inner_product(input_to_evaluate.begin(), input_to_evaluate.end(),
                         input_to_evaluate.begin(), 0.f) /
      input_to_evaluate.size();
  *output_power =
      std::inner_product(output_to_evaluate.begin(), output_to_evaluate.end(),
                         output_to_evaluate.begin(), 0.f) /
      output_to_evaluate.size();
}

}  // namespace

// Verifies that there is little aliasing from upper frequencies in the
// downsampling.
TEST(Decimator, NoLeakageFromUpperFrequencies) {
  float input_power;
  float output_power;
  for (auto rate : {16000, 32000, 48000}) {
    for (auto down_sampling_factor : kDownSamplingFactors) {
      ProduceDebugText(rate);
      ProduceDecimatedSinusoidalOutputPower(rate, down_sampling_factor,
                                            3.f / 8.f * rate, &input_power,
                                            &output_power);
      EXPECT_GT(0.0001f * input_power, output_power);
    }
  }
}

#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
// Verifies the check for the input size.
TEST(Decimator, WrongInputSize) {
  Decimator decimator(4);
  std::vector<std::vector<float>> x(1, std::vector<float>(kBlockSize - 1, 0.f));
  std::array<float, kBlockSize / 4> x_downsampled;
  EXPECT_DEATH(decimator.Decimate(x, true, x_downsampled), "");
}

// Verifies the check for non-null output parameter.
TEST(Decimator, NullOutput) {
  Decimator decimator(4);
  std::vector<std::vector<float>> x(1, std::vector<float>(kBlockSize, 0.f));
  EXPECT_DEATH(decimator.Decimate(x, true, nullptr), "");
}

// Verifies the check for the output size.
TEST(Decimator, WrongOutputSize) {
  Decimator decimator(4);
  std::vector<std::vector<float>> x(1, std::vector<float>(kBlockSize, 0.f));
  std::array<float, kBlockSize / 4 - 1> x_downsampled;
  EXPECT_DEATH(decimator.Decimate(x, true, x_downsampled), "");
}

// Verifies the check for the correct downsampling factor.
TEST(Decimator, CorrectDownSamplingFactor) {
  EXPECT_DEATH(Decimator(3), "");
}

#endif

}  // namespace webrtc
