/*
 *  Copyright (c) 2012 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/vad/vad_circular_buffer.h"

#include <memory>

#include "test/gtest.h"

namespace webrtc {

static const int kWidthThreshold = 7;
static const double kValThreshold = 1.0;
static const int kLongBuffSize = 100;
static const int kShortBuffSize = 10;

static void InsertSequentially(int k, VadCircularBuffer* circular_buffer) {
  double mean_val;
  for (int n = 1; n <= k; n++) {
    EXPECT_TRUE(!circular_buffer->is_full());
    circular_buffer->Insert(n);
    mean_val = circular_buffer->Mean();
    EXPECT_EQ((n + 1.0) / 2., mean_val);
  }
}

static void Insert(double value,
                   int num_insertion,
                   VadCircularBuffer* circular_buffer) {
  for (int n = 0; n < num_insertion; n++)
    circular_buffer->Insert(value);
}

static void InsertZeros(int num_zeros, VadCircularBuffer* circular_buffer) {
  Insert(0.0, num_zeros, circular_buffer);
}

TEST(VadCircularBufferTest, GeneralTest) {
  std::unique_ptr<VadCircularBuffer> circular_buffer(
      VadCircularBuffer::Create(kShortBuffSize));
  double mean_val;

  // Mean should return zero if nothing is inserted.
  mean_val = circular_buffer->Mean();
  EXPECT_DOUBLE_EQ(0.0, mean_val);
  InsertSequentially(kShortBuffSize, circular_buffer.get());

  // Should be full.
  EXPECT_TRUE(circular_buffer->is_full());
  // Correct update after being full.
  for (int n = 1; n < kShortBuffSize; n++) {
    circular_buffer->Insert(n);
    mean_val = circular_buffer->Mean();
    EXPECT_DOUBLE_EQ((kShortBuffSize + 1.) / 2., mean_val);
    EXPECT_TRUE(circular_buffer->is_full());
  }

  // Check reset. This should be like starting fresh.
  circular_buffer->Reset();
  mean_val = circular_buffer->Mean();
  EXPECT_DOUBLE_EQ(0, mean_val);
  InsertSequentially(kShortBuffSize, circular_buffer.get());
  EXPECT_TRUE(circular_buffer->is_full());
}

TEST(VadCircularBufferTest, TransientsRemoval) {
  std::unique_ptr<VadCircularBuffer> circular_buffer(
      VadCircularBuffer::Create(kLongBuffSize));
  // Let the first transient be in wrap-around.
  InsertZeros(kLongBuffSize - kWidthThreshold / 2, circular_buffer.get());

  double push_val = kValThreshold;
  double mean_val;
  for (int k = kWidthThreshold; k >= 1; k--) {
    Insert(push_val, k, circular_buffer.get());
    circular_buffer->Insert(0);
    mean_val = circular_buffer->Mean();
    EXPECT_DOUBLE_EQ(k * push_val / kLongBuffSize, mean_val);
    circular_buffer->RemoveTransient(kWidthThreshold, kValThreshold);
    mean_val = circular_buffer->Mean();
    EXPECT_DOUBLE_EQ(0, mean_val);
  }
}

TEST(VadCircularBufferTest, TransientDetection) {
  std::unique_ptr<VadCircularBuffer> circular_buffer(
      VadCircularBuffer::Create(kLongBuffSize));
  // Let the first transient be in wrap-around.
  int num_insertion = kLongBuffSize - kWidthThreshold / 2;
  InsertZeros(num_insertion, circular_buffer.get());

  double push_val = 2;
  // This is longer than a transient and shouldn't be removed.
  int num_non_zero_elements = kWidthThreshold + 1;
  Insert(push_val, num_non_zero_elements, circular_buffer.get());

  double mean_val = circular_buffer->Mean();
  EXPECT_DOUBLE_EQ(num_non_zero_elements * push_val / kLongBuffSize, mean_val);
  circular_buffer->Insert(0);
  EXPECT_EQ(0,
            circular_buffer->RemoveTransient(kWidthThreshold, kValThreshold));
  mean_val = circular_buffer->Mean();
  EXPECT_DOUBLE_EQ(num_non_zero_elements * push_val / kLongBuffSize, mean_val);

  // A transient right after a non-transient, should be removed and mean is
  // not changed.
  num_insertion = 3;
  Insert(push_val, num_insertion, circular_buffer.get());
  circular_buffer->Insert(0);
  EXPECT_EQ(0,
            circular_buffer->RemoveTransient(kWidthThreshold, kValThreshold));
  mean_val = circular_buffer->Mean();
  EXPECT_DOUBLE_EQ(num_non_zero_elements * push_val / kLongBuffSize, mean_val);

  // Last input is larger than threshold, although the sequence is short but
  // it shouldn't be considered transient.
  Insert(push_val, num_insertion, circular_buffer.get());
  num_non_zero_elements += num_insertion;
  EXPECT_EQ(0,
            circular_buffer->RemoveTransient(kWidthThreshold, kValThreshold));
  mean_val = circular_buffer->Mean();
  EXPECT_DOUBLE_EQ(num_non_zero_elements * push_val / kLongBuffSize, mean_val);
}

}  // namespace webrtc
