// 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 "base/bind.h" #include "base/location.h" #include "base/memory/weak_ptr.h" #include "base/single_thread_task_runner.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.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, 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. scoped_ptr dest = media::AudioBus::Create(1, default_frame_count_); frames = callback_->OnMoreData(dest.get(), 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 { public: AudioPlayerTest() : buffer_index_(0), player_(nullptr) { if (!media::AudioManager::Get()) media::AudioManager::CreateForTesting(); } ~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(); } void DeletePlayer() { if (!player_) return; player_->Finalize(); player_ = nullptr; } void PlayAndVerifySamples( const scoped_refptr& samples) { DCHECK_LT(samples->frames(), kMaxFrameCount); buffer_ = media::AudioBus::Create(1, kMaxFrameCount); buffer_index_ = 0; player_->Play(samples); player_->FlushAudioLoopForTesting(); player_->Stop(); 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(scoped_ptr bus, int frames) { if (!buffer_.get()) return; bus->CopyPartialFramesTo(0, frames, buffer_index_, buffer_.get()); buffer_index_ += frames; } protected: bool IsPlaying() { player_->FlushAudioLoopForTesting(); return player_->is_playing_; } static const int kDefaultFrameCount = 1024; static const int kMaxFrameCount = 1024 * 100; scoped_ptr buffer_; int buffer_index_; // Deleted by calling Finalize() on the object. AudioPlayerImpl* player_; base::MessageLoop message_loop_; }; TEST_F(AudioPlayerTest, BasicPlayAndStop) { CreatePlayer(); scoped_refptr 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 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