/*
 *  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 "webrtc/modules/audio_processing/agc/circular_buffer.h"

#include <stdio.h>

#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/base/scoped_ptr.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, AgcCircularBuffer* 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,
                   AgcCircularBuffer* circular_buffer) {
  for (int n = 0; n < num_insertion; n++)
    circular_buffer->Insert(value);
}

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

TEST(AgcCircularBufferTest, GeneralTest) {
  rtc::scoped_ptr<AgcCircularBuffer> circular_buffer(
      AgcCircularBuffer::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(AgcCircularBufferTest, TransientsRemoval) {
  rtc::scoped_ptr<AgcCircularBuffer> circular_buffer(
      AgcCircularBuffer::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(AgcCircularBufferTest, TransientDetection) {
  rtc::scoped_ptr<AgcCircularBuffer> circular_buffer(
      AgcCircularBuffer::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
