/*
 *  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 <memory>
#include <string>

#include "api/array_view.h"
#include "modules/audio_processing/agc2/digital_gain_applier.h"
#include "modules/audio_processing/agc2/gain_controller2.h"
#include "modules/audio_processing/audio_buffer.h"
#include "test/gtest.h"

namespace webrtc {
namespace test {

namespace {

constexpr size_t kNumFrames = 480u;
constexpr size_t kStereo = 2u;

void SetAudioBufferSamples(float value, AudioBuffer* ab) {
  for (size_t k = 0; k < ab->num_channels(); ++k) {
    auto channel = rtc::ArrayView<float>(ab->channels_f()[k], ab->num_frames());
    for (auto& sample : channel) { sample = value; }
  }
}

template<typename Functor>
bool CheckAudioBufferSamples(Functor validator, AudioBuffer* ab) {
  for (size_t k = 0; k < ab->num_channels(); ++k) {
    auto channel = rtc::ArrayView<float>(ab->channels_f()[k], ab->num_frames());
    for (auto& sample : channel) { if (!validator(sample)) { return false; } }
  }
  return true;
}

bool TestDigitalGainApplier(float sample_value, float gain, float expected) {
  AudioBuffer ab(kNumFrames, kStereo, kNumFrames, kStereo, kNumFrames);
  SetAudioBufferSamples(sample_value, &ab);

  DigitalGainApplier gain_applier;
  for (size_t k = 0; k < ab.num_channels(); ++k) {
    auto channel_view = rtc::ArrayView<float>(
        ab.channels_f()[k], ab.num_frames());
    gain_applier.Process(gain, channel_view);
  }

  auto check_expectation = [expected](float sample) {
      return sample == expected; };
  return CheckAudioBufferSamples(check_expectation, &ab);
}

}  // namespace

TEST(GainController2, Instance) {
  std::unique_ptr<GainController2> gain_controller2;
  gain_controller2.reset(new GainController2(
      AudioProcessing::kSampleRate48kHz));
}

TEST(GainController2, ToString) {
  AudioProcessing::Config config;

  config.gain_controller2.enabled = false;
  EXPECT_EQ("{enabled: false}",
            GainController2::ToString(config.gain_controller2));

  config.gain_controller2.enabled = true;
  EXPECT_EQ("{enabled: true}",
            GainController2::ToString(config.gain_controller2));
}

TEST(GainController2, DigitalGainApplierProcess) {
  EXPECT_TRUE(TestDigitalGainApplier(1000.0f, 0.5, 500.0f));
}

TEST(GainController2, DigitalGainApplierCheckClipping) {
  EXPECT_TRUE(TestDigitalGainApplier(30000.0f, 1.5, 32767.0f));
  EXPECT_TRUE(TestDigitalGainApplier(-30000.0f, 1.5, -32767.0f));
}

TEST(GainController2, Usage) {
  std::unique_ptr<GainController2> gain_controller2;
  gain_controller2.reset(new GainController2(
      AudioProcessing::kSampleRate48kHz));
  AudioBuffer ab(kNumFrames, kStereo, kNumFrames, kStereo, kNumFrames);
  SetAudioBufferSamples(1000.0f, &ab);
  gain_controller2->Process(&ab);
}

}  // namespace test
}  // namespace webrtc
