// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/base/multi_channel_resampler.h"

#include <cmath>
#include <memory>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/logging.h"
#include "base/macros.h"
#include "media/base/audio_bus.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace media {

// Just test a basic resampling case.  The SincResampler unit test will take
// care of accuracy testing; we just need to check that multichannel works as
// expected within some tolerance.
static const float kScaleFactor = 192000.0f / 44100.0f;

// Simulate large and small sample requests used by the different audio paths.
static const int kHighLatencySize = 8192;
// Low latency buffers show a larger error than high latency ones.  Which makes
// sense since each error represents a larger portion of the total request.
static const int kLowLatencySize = 128;

// Test fill value.
static const float kFillValue = 0.1f;

// Chosen arbitrarily based on what each resampler reported during testing.
static const double kLowLatencyMaxRMSError = 0.0036;
static const double kLowLatencyMaxError = 0.04;
static const double kHighLatencyMaxRMSError = 0.0036;
static const double kHighLatencyMaxError = 0.04;

class MultiChannelResamplerTest
    : public testing::TestWithParam<int> {
 public:
  MultiChannelResamplerTest()
      : last_frame_delay_(-1) {
  }
  virtual ~MultiChannelResamplerTest() = default;

  void InitializeAudioData(int channels, int frames) {
    frames_ = frames;
    audio_bus_ = AudioBus::Create(channels, frames);
  }

  // MultiChannelResampler::MultiChannelAudioSourceProvider implementation, just
  // fills the provided audio_data with |kFillValue|.
  virtual void ProvideInput(int frame_delay, AudioBus* audio_bus) {
    EXPECT_GE(frame_delay, last_frame_delay_);
    last_frame_delay_ = frame_delay;

    float fill_value = fill_junk_values_ ? (1 / kFillValue) : kFillValue;
    EXPECT_EQ(audio_bus->channels(), audio_bus_->channels());
    for (int i = 0; i < audio_bus->channels(); ++i)
      for (int j = 0; j < audio_bus->frames(); ++j)
        audio_bus->channel(i)[j] = fill_value;
  }

  void MultiChannelTest(int channels, int frames, double expected_max_rms_error,
                        double expected_max_error) {
    InitializeAudioData(channels, frames);
    MultiChannelResampler resampler(
        channels, kScaleFactor, SincResampler::kDefaultRequestSize, base::Bind(
            &MultiChannelResamplerTest::ProvideInput, base::Unretained(this)));

    // First prime the resampler with some junk data, so we can verify Flush().
    fill_junk_values_ = true;
    resampler.Resample(1, audio_bus_.get());
    resampler.Flush();
    fill_junk_values_ = false;

    // The last frame delay should be strictly less than the total frame count.
    EXPECT_LT(last_frame_delay_, audio_bus_->frames());
    last_frame_delay_ = -1;

    // If Flush() didn't work, the rest of the tests will fail.
    resampler.Resample(frames, audio_bus_.get());
    TestValues(expected_max_rms_error, expected_max_error);
  }

  void HighLatencyTest(int channels) {
    MultiChannelTest(channels, kHighLatencySize, kHighLatencyMaxRMSError,
                     kHighLatencyMaxError);
  }

  void LowLatencyTest(int channels) {
    MultiChannelTest(channels, kLowLatencySize, kLowLatencyMaxRMSError,
                     kLowLatencyMaxError);
  }

  void TestValues(double expected_max_rms_error, double expected_max_error ) {
    // Calculate Root-Mean-Square-Error for the resampling.
    double max_error = 0.0;
    double sum_of_squares = 0.0;
    for (int i = 0; i < audio_bus_->channels(); ++i) {
      for (int j = 0; j < frames_; ++j) {
        // Ensure all values are accounted for.
        ASSERT_NE(audio_bus_->channel(i)[j], 0);

        double error = fabs(audio_bus_->channel(i)[j] - kFillValue);
        max_error = std::max(max_error, error);
        sum_of_squares += error * error;
      }
    }

    double rms_error = sqrt(
        sum_of_squares / (frames_ * audio_bus_->channels()));

    EXPECT_LE(rms_error, expected_max_rms_error);
    EXPECT_LE(max_error, expected_max_error);
  }

 protected:
  int frames_;
  bool fill_junk_values_;
  std::unique_ptr<AudioBus> audio_bus_;
  int last_frame_delay_;

  DISALLOW_COPY_AND_ASSIGN(MultiChannelResamplerTest);
};

TEST_P(MultiChannelResamplerTest, HighLatency) {
  HighLatencyTest(GetParam());
}

TEST_P(MultiChannelResamplerTest, LowLatency) {
  LowLatencyTest(GetParam());
}

// Test common channel layouts: mono, stereo, 5.1, 7.1.
INSTANTIATE_TEST_CASE_P(
    MultiChannelResamplerTest, MultiChannelResamplerTest,
    testing::Values(1, 2, 6, 8));

}  // namespace media
