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

#include "media/audio/simple_sources.h"

#include <stddef.h>
#include <stdint.h>

#include <limits>
#include <memory>

#include "base/files/file_util.h"
#include "base/time/time.h"
#include "media/audio/audio_io.h"
#include "media/audio/test_data.h"
#include "media/base/audio_bus.h"
#include "media/base/audio_parameters.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace media {

// Validate that the SineWaveAudioSource writes the expected values.
TEST(SimpleSources, SineWaveAudioSource) {
  static const uint32_t samples = 1024;
  static const int freq = 200;

  AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
                         ChannelLayoutConfig::Mono(),
                         AudioParameters::kTelephoneSampleRate, samples);

  SineWaveAudioSource source(1, freq, params.sample_rate());
  std::unique_ptr<AudioBus> audio_bus = AudioBus::Create(params);
  source.OnMoreData(base::TimeDelta(), base::TimeTicks::Now(), {},
                    audio_bus.get());
  EXPECT_EQ(1, source.callbacks());
  EXPECT_EQ(0, source.errors());

  uint32_t half_period = AudioParameters::kTelephoneSampleRate / (freq * 2);

  // Spot test positive incursion of sine wave.
  EXPECT_NEAR(0, audio_bus->channel(0)[0],
              std::numeric_limits<float>::epsilon());
  EXPECT_FLOAT_EQ(0.15643446f, audio_bus->channel(0)[1]);
  EXPECT_LT(audio_bus->channel(0)[1], audio_bus->channel(0)[2]);
  EXPECT_LT(audio_bus->channel(0)[2], audio_bus->channel(0)[3]);
  // Spot test negative incursion of sine wave.
  EXPECT_NEAR(0, audio_bus->channel(0)[half_period],
              std::numeric_limits<float>::epsilon());
  EXPECT_FLOAT_EQ(-0.15643446f, audio_bus->channel(0)[half_period + 1]);
  EXPECT_GT(audio_bus->channel(0)[half_period + 1],
            audio_bus->channel(0)[half_period + 2]);
  EXPECT_GT(audio_bus->channel(0)[half_period + 2],
            audio_bus->channel(0)[half_period + 3]);
}

TEST(SimpleSources, SineWaveAudioCapped) {
  SineWaveAudioSource source(1, 200, AudioParameters::kTelephoneSampleRate);

  static const int kSampleCap = 100;
  source.CapSamples(kSampleCap);

  std::unique_ptr<AudioBus> audio_bus = AudioBus::Create(1, 2 * kSampleCap);
  EXPECT_EQ(source.OnMoreData(base::TimeDelta(), base::TimeTicks::Now(), {},
                              audio_bus.get()),
            kSampleCap);
  EXPECT_EQ(1, source.callbacks());
  EXPECT_EQ(source.OnMoreData(base::TimeDelta(), base::TimeTicks::Now(), {},
                              audio_bus.get()),
            0);
  EXPECT_EQ(2, source.callbacks());
  source.Reset();
  EXPECT_EQ(source.OnMoreData(base::TimeDelta(), base::TimeTicks::Now(), {},
                              audio_bus.get()),
            kSampleCap);
  EXPECT_EQ(3, source.callbacks());
  EXPECT_EQ(0, source.errors());
}

TEST(SimpleSources, OnError) {
  SineWaveAudioSource source(1, 200, AudioParameters::kTelephoneSampleRate);
  source.OnError(AudioOutputStream::AudioSourceCallback::ErrorType::kUnknown);
  EXPECT_EQ(1, source.errors());
  source.OnError(AudioOutputStream::AudioSourceCallback::ErrorType::kUnknown);
  EXPECT_EQ(2, source.errors());
}

void VerifyContainsTestFile(const AudioBus* audio_bus) {
  // Convert the test data (little-endian) into floats and compare. We need to
  // index past the first bytes in the data, which contain the wav header.
  const int kFirstSampleIndex = 12 + 8 + 16 + 8;
  int16_t data[2];
  data[0] = kTestAudioData[kFirstSampleIndex];
  data[0] |= (kTestAudioData[kFirstSampleIndex + 1] << 8);
  data[1] = kTestAudioData[kFirstSampleIndex + 2];
  data[1] |= (kTestAudioData[kFirstSampleIndex + 3] << 8);

  // The first frame should hold the WAV data.
  EXPECT_FLOAT_EQ(static_cast<float>(data[0]) / ((1 << 15) - 1),
                  audio_bus->channel(0)[0]);
  EXPECT_FLOAT_EQ(static_cast<float>(data[1]) / ((1 << 15) - 1),
                  audio_bus->channel(1)[0]);

  // All other frames should be zero-padded. This applies even when looping, as
  // the looping will restart on the next call to OnMoreData.
  for (int channel = 0; channel < audio_bus->channels(); ++channel) {
    for (int frame = 1; frame < audio_bus->frames(); ++frame) {
      EXPECT_FLOAT_EQ(0.0, audio_bus->channel(channel)[frame]);
    }
  }
}

TEST(SimpleSources, FileSourceTestDataWithoutLooping) {
  const int kNumFrames = 10;

  // Create a temporary file filled with WAV data.
  base::FilePath temp_path;
  ASSERT_TRUE(base::CreateTemporaryFile(&temp_path));
  base::File temp(temp_path,
                  base::File::FLAG_WRITE | base::File::FLAG_OPEN_ALWAYS);
  temp.WriteAtCurrentPos(kTestAudioData, kTestAudioDataSize);
  ASSERT_EQ(kTestAudioDataSize, static_cast<size_t>(temp.GetLength()));
  temp.Close();

  // Create AudioParameters which match those in the WAV data.
  AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
                         ChannelLayoutConfig::Stereo(), 48000, kNumFrames);
  std::unique_ptr<AudioBus> audio_bus = AudioBus::Create(2, kNumFrames);
  audio_bus->Zero();

  // Create a FileSource that reads this file.
  bool loop = false;
  FileSource source(params, temp_path, loop);
  EXPECT_EQ(kNumFrames,
            source.OnMoreData(base::TimeDelta(), base::TimeTicks::Now(), {},
                              audio_bus.get()));

  VerifyContainsTestFile(audio_bus.get());

  // We should not play any more audio after the file reaches its end.
  audio_bus->Zero();
  source.OnMoreData(base::TimeDelta(), base::TimeTicks::Now(), {},
                    audio_bus.get());
  for (int channel = 0; channel < audio_bus->channels(); ++channel) {
    for (int frame = 0; frame < audio_bus->frames(); ++frame) {
      EXPECT_FLOAT_EQ(0.0, audio_bus->channel(channel)[frame]);
    }
  }
}

TEST(SimpleSources, FileSourceTestDataWithLooping) {
  const int kNumFrames = 10;

  // Create a temporary file filled with WAV data.
  base::FilePath temp_path;
  ASSERT_TRUE(base::CreateTemporaryFile(&temp_path));
  base::File temp(temp_path,
                  base::File::FLAG_WRITE | base::File::FLAG_OPEN_ALWAYS);
  temp.WriteAtCurrentPos(kTestAudioData, kTestAudioDataSize);
  ASSERT_EQ(kTestAudioDataSize, static_cast<size_t>(temp.GetLength()));
  temp.Close();

  // Create AudioParameters which match those in the WAV data.
  AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
                         ChannelLayoutConfig::Stereo(), 48000, kNumFrames);
  std::unique_ptr<AudioBus> audio_bus = AudioBus::Create(2, kNumFrames);
  audio_bus->Zero();

  bool loop = true;
  FileSource source(params, temp_path, loop);

  // Verify that we keep reading in the file when looping.
  source.OnMoreData(base::TimeDelta(), base::TimeTicks::Now(), {},
                    audio_bus.get());
  audio_bus->Zero();
  source.OnMoreData(base::TimeDelta(), base::TimeTicks::Now(), {},
                    audio_bus.get());

  VerifyContainsTestFile(audio_bus.get());
}

TEST(SimpleSources, BadFilePathFails) {
  AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
                         ChannelLayoutConfig::Stereo(), 48000, 10);
  std::unique_ptr<AudioBus> audio_bus = AudioBus::Create(2, 10);
  audio_bus->Zero();

  // Create a FileSource that reads this file.
  base::FilePath path;
  path = path.Append(FILE_PATH_LITERAL("does"))
             .Append(FILE_PATH_LITERAL("not"))
             .Append(FILE_PATH_LITERAL("exist"));
  bool loop = false;
  FileSource source(params, path, loop);
  EXPECT_EQ(0, source.OnMoreData(base::TimeDelta(), base::TimeTicks::Now(), {},
                                 audio_bus.get()));

  // Confirm all frames are zero-padded.
  for (int channel = 0; channel < audio_bus->channels(); ++channel) {
    for (int frame = 0; frame < audio_bus->frames(); ++frame) {
      EXPECT_FLOAT_EQ(0.0, audio_bus->channel(channel)[frame]);
    }
  }
}

TEST(SimpleSources, FileSourceCorruptTestDataFails) {
  const int kNumFrames = 10;

  // Create a temporary file filled with WAV data.
  base::FilePath temp_path;
  ASSERT_TRUE(base::CreateTemporaryFile(&temp_path));
  base::File temp(temp_path,
                  base::File::FLAG_WRITE | base::File::FLAG_OPEN_ALWAYS);
  temp.WriteAtCurrentPos(kTestAudioData, kTestAudioDataSize);

  // Corrupt the header.
  temp.Write(3, "0x00", 1);

  ASSERT_EQ(kTestAudioDataSize, static_cast<size_t>(temp.GetLength()));
  temp.Close();

  // Create AudioParameters which match those in the WAV data.
  AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
                         ChannelLayoutConfig::Stereo(), 48000, kNumFrames);
  std::unique_ptr<AudioBus> audio_bus = AudioBus::Create(2, kNumFrames);
  audio_bus->Zero();

  // Create a FileSource that reads this file.
  bool loop = false;
  FileSource source(params, temp_path, loop);
  EXPECT_EQ(0, source.OnMoreData(base::TimeDelta(), base::TimeTicks::Now(), {},
                                 audio_bus.get()));

  // Confirm all frames are zero-padded.
  for (int channel = 0; channel < audio_bus->channels(); ++channel) {
    for (int frame = 0; frame < audio_bus->frames(); ++frame) {
      EXPECT_FLOAT_EQ(0.0, audio_bus->channel(channel)[frame]);
    }
  }
}

}  // namespace media
