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

#include <limits>
#include <memory>
#include <tuple>
#include <utility>
#include <vector>

#include "modules/audio_processing/agc2/agc2_common.h"
#include "modules/audio_processing/include/audio_frame_view.h"
#include "rtc_base/checks.h"
#include "rtc_base/gunit.h"
#include "rtc_base/numerics/safe_compare.h"
#include "test/gmock.h"

namespace webrtc {
namespace {

using ::testing::AnyNumber;
using ::testing::Return;
using ::testing::ReturnRoundRobin;
using ::testing::Truly;

constexpr int kNumFramesPerSecond = 100;

constexpr int kNoVadPeriodicReset =
    kFrameDurationMs * (std::numeric_limits<int>::max() / kFrameDurationMs);

constexpr int kSampleRate8kHz = 8000;

class MockVad : public VoiceActivityDetectorWrapper::MonoVad {
 public:
  MOCK_METHOD(int, SampleRateHz, (), (const, override));
  MOCK_METHOD(void, Reset, (), (override));
  MOCK_METHOD(float, Analyze, (rtc::ArrayView<const float> frame), (override));
};

// Checks that the ctor and `Initialize()` read the sample rate of the wrapped
// VAD.
TEST(GainController2VoiceActivityDetectorWrapper, CtorAndInitReadSampleRate) {
  auto vad = std::make_unique<MockVad>();
  EXPECT_CALL(*vad, SampleRateHz)
      .Times(2)
      .WillRepeatedly(Return(kSampleRate8kHz));
  EXPECT_CALL(*vad, Reset).Times(AnyNumber());
  auto vad_wrapper = std::make_unique<VoiceActivityDetectorWrapper>(
      kNoVadPeriodicReset, std::move(vad), kSampleRate8kHz);
}

// Creates a `VoiceActivityDetectorWrapper` injecting a mock VAD that
// repeatedly returns the next value from `speech_probabilities` and that
// restarts from the beginning when after the last element is returned.
std::unique_ptr<VoiceActivityDetectorWrapper> CreateMockVadWrapper(
    int vad_reset_period_ms,
    int sample_rate_hz,
    const std::vector<float>& speech_probabilities,
    int expected_vad_reset_calls) {
  auto vad = std::make_unique<MockVad>();
  EXPECT_CALL(*vad, SampleRateHz)
      .Times(AnyNumber())
      .WillRepeatedly(Return(sample_rate_hz));
  if (expected_vad_reset_calls >= 0) {
    EXPECT_CALL(*vad, Reset).Times(expected_vad_reset_calls);
  }
  EXPECT_CALL(*vad, Analyze)
      .Times(AnyNumber())
      .WillRepeatedly(ReturnRoundRobin(speech_probabilities));
  return std::make_unique<VoiceActivityDetectorWrapper>(
      vad_reset_period_ms, std::move(vad), kSampleRate8kHz);
}

// 10 ms mono frame.
struct FrameWithView {
  // Ctor. Initializes the frame samples with `value`.
  explicit FrameWithView(int sample_rate_hz)
      : samples(rtc::CheckedDivExact(sample_rate_hz, kNumFramesPerSecond),
                0.0f),
        channel0(samples.data()),
        view(&channel0, /*num_channels=*/1, samples.size()) {}
  std::vector<float> samples;
  const float* const channel0;
  const AudioFrameView<const float> view;
};

// Checks that the expected speech probabilities are returned.
TEST(GainController2VoiceActivityDetectorWrapper, CheckSpeechProbabilities) {
  const std::vector<float> speech_probabilities{0.709f, 0.484f, 0.882f, 0.167f,
                                                0.44f,  0.525f, 0.858f, 0.314f,
                                                0.653f, 0.965f, 0.413f, 0.0f};
  auto vad_wrapper = CreateMockVadWrapper(kNoVadPeriodicReset, kSampleRate8kHz,
                                          speech_probabilities,
                                          /*expected_vad_reset_calls=*/1);
  FrameWithView frame(kSampleRate8kHz);
  for (int i = 0; rtc::SafeLt(i, speech_probabilities.size()); ++i) {
    SCOPED_TRACE(i);
    EXPECT_EQ(speech_probabilities[i], vad_wrapper->Analyze(frame.view));
  }
}

// Checks that the VAD is not periodically reset.
TEST(GainController2VoiceActivityDetectorWrapper, VadNoPeriodicReset) {
  constexpr int kNumFrames = 19;
  auto vad_wrapper = CreateMockVadWrapper(kNoVadPeriodicReset, kSampleRate8kHz,
                                          /*speech_probabilities=*/{1.0f},
                                          /*expected_vad_reset_calls=*/1);
  FrameWithView frame(kSampleRate8kHz);
  for (int i = 0; i < kNumFrames; ++i) {
    vad_wrapper->Analyze(frame.view);
  }
}

class VadPeriodResetParametrization
    : public ::testing::TestWithParam<std::tuple<int, int>> {
 protected:
  int num_frames() const { return std::get<0>(GetParam()); }
  int vad_reset_period_frames() const { return std::get<1>(GetParam()); }
};

// Checks that the VAD is periodically reset with the expected period.
TEST_P(VadPeriodResetParametrization, VadPeriodicReset) {
  auto vad_wrapper = CreateMockVadWrapper(
      /*vad_reset_period_ms=*/vad_reset_period_frames() * kFrameDurationMs,
      kSampleRate8kHz,
      /*speech_probabilities=*/{1.0f},
      /*expected_vad_reset_calls=*/1 +
          num_frames() / vad_reset_period_frames());
  FrameWithView frame(kSampleRate8kHz);
  for (int i = 0; i < num_frames(); ++i) {
    vad_wrapper->Analyze(frame.view);
  }
}

INSTANTIATE_TEST_SUITE_P(GainController2VoiceActivityDetectorWrapper,
                         VadPeriodResetParametrization,
                         ::testing::Combine(::testing::Values(1, 19, 123),
                                            ::testing::Values(2, 5, 20, 53)));

class VadResamplingParametrization
    : public ::testing::TestWithParam<std::tuple<int, int>> {
 protected:
  int input_sample_rate_hz() const { return std::get<0>(GetParam()); }
  int vad_sample_rate_hz() const { return std::get<1>(GetParam()); }
};

// Checks that regardless of the input audio sample rate, the wrapped VAD
// analyzes frames having the expected size, that is according to its internal
// sample rate.
TEST_P(VadResamplingParametrization, CheckResampledFrameSize) {
  auto vad = std::make_unique<MockVad>();
  EXPECT_CALL(*vad, SampleRateHz)
      .Times(AnyNumber())
      .WillRepeatedly(Return(vad_sample_rate_hz()));
  EXPECT_CALL(*vad, Reset).Times(1);
  EXPECT_CALL(*vad, Analyze(Truly([this](rtc::ArrayView<const float> frame) {
    return rtc::SafeEq(frame.size(), rtc::CheckedDivExact(vad_sample_rate_hz(),
                                                          kNumFramesPerSecond));
  }))).Times(1);
  auto vad_wrapper = std::make_unique<VoiceActivityDetectorWrapper>(
      kNoVadPeriodicReset, std::move(vad), input_sample_rate_hz());
  FrameWithView frame(input_sample_rate_hz());
  vad_wrapper->Analyze(frame.view);
}

INSTANTIATE_TEST_SUITE_P(
    GainController2VoiceActivityDetectorWrapper,
    VadResamplingParametrization,
    ::testing::Combine(::testing::Values(8000, 16000, 44100, 48000),
                       ::testing::Values(6000, 8000, 12000, 16000, 24000)));

}  // namespace
}  // namespace webrtc
