blob: ed2c71bc4d018c00f42378c627626e6e79056317 [file] [log] [blame]
// Copyright 2015 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 "components/audio_modem/audio_player.h"
#include <memory>
#include "base/bind.h"
#include "base/location.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
#include "base/test/test_message_loop.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/audio_modem/audio_player_impl.h"
#include "components/audio_modem/public/audio_modem_types.h"
#include "components/audio_modem/test/random_samples.h"
#include "media/audio/audio_manager_base.h"
#include "media/base/audio_bus.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
class TestAudioOutputStream : public media::AudioOutputStream {
public:
using GatherSamplesCallback =
base::Callback<void(std::unique_ptr<media::AudioBus>, int frames)>;
TestAudioOutputStream(int default_frame_count,
int max_frame_count,
GatherSamplesCallback gather_callback)
: default_frame_count_(default_frame_count),
max_frame_count_(max_frame_count),
gather_callback_(gather_callback),
callback_(nullptr) {
caller_loop_ = base::MessageLoop::current();
}
~TestAudioOutputStream() override {}
bool Open() override { return true; }
void Start(AudioSourceCallback* callback) override {
callback_ = callback;
GatherPlayedSamples();
}
void Stop() override {}
void SetVolume(double volume) override {}
void GetVolume(double* volume) override {}
void Close() override {}
private:
void GatherPlayedSamples() {
int frames = 0, total_frames = 0;
do {
// Call back into the player to get samples that it wants us to play.
std::unique_ptr<media::AudioBus> dest =
media::AudioBus::Create(1, default_frame_count_);
frames = callback_->OnMoreData(dest.get(), 0, 0);
total_frames += frames;
// Send the samples given to us by the player to the gather callback.
caller_loop_->task_runner()->PostTask(
FROM_HERE, base::Bind(gather_callback_, base::Passed(&dest), frames));
} while (frames && total_frames < max_frame_count_);
}
int default_frame_count_;
int max_frame_count_;
GatherSamplesCallback gather_callback_;
AudioSourceCallback* callback_;
base::MessageLoop* caller_loop_;
DISALLOW_COPY_AND_ASSIGN(TestAudioOutputStream);
};
} // namespace
namespace audio_modem {
class AudioPlayerTest : public testing::Test,
public base::SupportsWeakPtr<AudioPlayerTest> {
public:
AudioPlayerTest() : buffer_index_(0), player_(nullptr) {
audio_manager_ = media::AudioManager::CreateForTesting(
base::ThreadTaskRunnerHandle::Get());
base::RunLoop().RunUntilIdle();
}
~AudioPlayerTest() override { DeletePlayer(); }
void CreatePlayer() {
DeletePlayer();
player_ = new AudioPlayerImpl();
player_->set_output_stream_for_testing(new TestAudioOutputStream(
kDefaultFrameCount,
kMaxFrameCount,
base::Bind(&AudioPlayerTest::GatherSamples, AsWeakPtr())));
player_->Initialize();
base::RunLoop().RunUntilIdle();
}
void DeletePlayer() {
if (!player_)
return;
player_->Finalize();
player_ = nullptr;
base::RunLoop().RunUntilIdle();
}
void PlayAndVerifySamples(
const scoped_refptr<media::AudioBusRefCounted>& samples) {
DCHECK_LT(samples->frames(), kMaxFrameCount);
buffer_ = media::AudioBus::Create(1, kMaxFrameCount);
buffer_index_ = 0;
player_->Play(samples);
player_->Stop();
base::RunLoop().RunUntilIdle();
int differences = 0;
for (int i = 0; i < kMaxFrameCount; ++i) {
differences += (buffer_->channel(0)[i] !=
samples->channel(0)[i % samples->frames()]);
}
ASSERT_EQ(0, differences);
buffer_.reset();
}
void GatherSamples(std::unique_ptr<media::AudioBus> bus, int frames) {
if (!buffer_.get())
return;
bus->CopyPartialFramesTo(0, frames, buffer_index_, buffer_.get());
buffer_index_ += frames;
}
protected:
bool IsPlaying() {
base::RunLoop().RunUntilIdle();
return player_->is_playing_;
}
static const int kDefaultFrameCount = 1024;
static const int kMaxFrameCount = 1024 * 100;
base::TestMessageLoop message_loop_;
media::ScopedAudioManagerPtr audio_manager_;
std::unique_ptr<media::AudioBus> buffer_;
int buffer_index_;
// Deleted by calling Finalize() on the object.
AudioPlayerImpl* player_;
};
TEST_F(AudioPlayerTest, BasicPlayAndStop) {
CreatePlayer();
scoped_refptr<media::AudioBusRefCounted> samples =
media::AudioBusRefCounted::Create(1, 7331);
player_->Play(samples);
EXPECT_TRUE(IsPlaying());
player_->Stop();
EXPECT_FALSE(IsPlaying());
player_->Play(samples);
EXPECT_TRUE(IsPlaying());
player_->Stop();
EXPECT_FALSE(IsPlaying());
player_->Play(samples);
EXPECT_TRUE(IsPlaying());
player_->Stop();
EXPECT_FALSE(IsPlaying());
DeletePlayer();
}
TEST_F(AudioPlayerTest, OutOfOrderPlayAndStopMultiple) {
CreatePlayer();
scoped_refptr<media::AudioBusRefCounted> samples =
media::AudioBusRefCounted::Create(1, 1337);
player_->Stop();
player_->Stop();
player_->Stop();
EXPECT_FALSE(IsPlaying());
player_->Play(samples);
player_->Play(samples);
EXPECT_TRUE(IsPlaying());
player_->Stop();
player_->Stop();
EXPECT_FALSE(IsPlaying());
DeletePlayer();
}
TEST_F(AudioPlayerTest, PlayingEndToEnd) {
const int kNumSamples = kDefaultFrameCount * 7 + 321;
CreatePlayer();
PlayAndVerifySamples(CreateRandomAudioRefCounted(0x1337, 1, kNumSamples));
DeletePlayer();
}
TEST_F(AudioPlayerTest, PlayingEndToEndRepeated) {
const int kNumSamples = kDefaultFrameCount * 7 + 537;
CreatePlayer();
PlayAndVerifySamples(CreateRandomAudioRefCounted(0x1337, 1, kNumSamples));
PlayAndVerifySamples(
CreateRandomAudioRefCounted(0x7331, 1, kNumSamples - 3123));
PlayAndVerifySamples(CreateRandomAudioRefCounted(0xf00d, 1, kNumSamples * 2));
DeletePlayer();
}
} // namespace audio_modem