// 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 "base/basictypes.h" #include "base/memory/scoped_ptr.h" #include "media/audio/audio_io.h" #include "media/audio/audio_manager.h" #include "media/audio/simple_sources.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" using ::testing::_; using ::testing::AnyNumber; using ::testing::DoAll; using ::testing::Field; using ::testing::InSequence; using ::testing::Invoke; using ::testing::NiceMock; using ::testing::NotNull; using ::testing::Return; namespace media { class MockAudioSource : public AudioOutputStream::AudioSourceCallback { public: MOCK_METHOD2(OnMoreData, int(AudioBus* audio_bus, AudioBuffersState buffers_state)); MOCK_METHOD3(OnMoreIOData, int(AudioBus* source, AudioBus* dest, AudioBuffersState buffers_state)); MOCK_METHOD2(OnError, void(AudioOutputStream* stream, int code)); }; // =========================================================================== // Validation of AudioParameters::AUDIO_PCM_LINEAR // // Test that can it be created and closed. TEST(MacAudioTest, PCMWaveStreamGetAndClose) { scoped_ptr audio_man(AudioManager::Create()); if (!audio_man->HasAudioOutputDevices()) return; AudioOutputStream* oas = audio_man->MakeAudioOutputStream( AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_STEREO, 8000, 16, 1024)); ASSERT_TRUE(NULL != oas); oas->Close(); } // Test that it can be opened and closed. TEST(MacAudioTest, PCMWaveStreamOpenAndClose) { scoped_ptr audio_man(AudioManager::Create()); if (!audio_man->HasAudioOutputDevices()) return; AudioOutputStream* oas = audio_man->MakeAudioOutputStream( AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_STEREO, 8000, 16, 1024)); ASSERT_TRUE(NULL != oas); EXPECT_TRUE(oas->Open()); oas->Close(); } // This test produces actual audio for 1.5 seconds on the default wave device at // 44.1K s/sec. Parameters have been chosen carefully so you should not hear // pops or noises while the sound is playing. The sound must also be identical // to the sound of PCMWaveStreamPlay200HzTone22KssMono test. TEST(MacAudioTest, PCMWaveStreamPlay200HzTone44KssMono) { scoped_ptr audio_man(AudioManager::Create()); if (!audio_man->HasAudioOutputDevices()) return; uint32 frames_100_ms = AudioParameters::kAudioCDSampleRate / 10; AudioOutputStream* oas = audio_man->MakeAudioOutputStream( AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO, AudioParameters::kAudioCDSampleRate, 16, frames_100_ms)); ASSERT_TRUE(NULL != oas); EXPECT_TRUE(oas->Open()); SineWaveAudioSource source(1, 200.0, AudioParameters::kAudioCDSampleRate); oas->SetVolume(0.5); oas->Start(&source); usleep(500000); // Test that the volume is within the set limits. double volume = 0.0; oas->GetVolume(&volume); EXPECT_LT(volume, 0.51); EXPECT_GT(volume, 0.49); oas->Stop(); oas->Close(); } // This test produces actual audio for 1.5 seconds on the default wave device at // 22K s/sec. Parameters have been chosen carefully so you should not hear pops // or noises while the sound is playing. The sound must also be identical to the // sound of PCMWaveStreamPlay200HzTone44KssMono test. TEST(MacAudioTest, PCMWaveStreamPlay200HzTone22KssMono) { scoped_ptr audio_man(AudioManager::Create()); if (!audio_man->HasAudioOutputDevices()) return; uint32 frames_100_ms = AudioParameters::kAudioCDSampleRate / 10; AudioOutputStream* oas = audio_man->MakeAudioOutputStream( AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO, AudioParameters::kAudioCDSampleRate / 2, 16, frames_100_ms)); ASSERT_TRUE(NULL != oas); SineWaveAudioSource source(1, 200.0, AudioParameters::kAudioCDSampleRate/2); EXPECT_TRUE(oas->Open()); oas->Start(&source); usleep(1500000); oas->Stop(); oas->Close(); } // Custom action to clear a memory buffer. static int ClearBuffer(AudioBus* audio_bus, AudioBuffersState buffers_state) { audio_bus->Zero(); return audio_bus->frames(); } TEST(MacAudioTest, PCMWaveStreamPendingBytes) { scoped_ptr audio_man(AudioManager::Create()); if (!audio_man->HasAudioOutputDevices()) return; uint32 frames_100_ms = AudioParameters::kAudioCDSampleRate / 10; AudioOutputStream* oas = audio_man->MakeAudioOutputStream( AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO, AudioParameters::kAudioCDSampleRate, 16, frames_100_ms)); ASSERT_TRUE(NULL != oas); NiceMock source; EXPECT_TRUE(oas->Open()); uint32 bytes_100_ms = frames_100_ms * 2; // We expect the amount of pending bytes will reaching |bytes_100_ms| // because the audio output stream has a double buffer scheme. // And then we will try to provide zero data so the amount of pending bytes // will go down and eventually read zero. InSequence s; EXPECT_CALL(source, OnMoreData(NotNull(), Field(&AudioBuffersState::pending_bytes, 0))) .WillOnce(Invoke(ClearBuffer)); EXPECT_CALL(source, OnMoreData(NotNull(), Field(&AudioBuffersState::pending_bytes, bytes_100_ms))) .WillOnce(Invoke(ClearBuffer)); EXPECT_CALL(source, OnMoreData(NotNull(), Field(&AudioBuffersState::pending_bytes, bytes_100_ms))) .WillOnce(Return(0)); EXPECT_CALL(source, OnMoreData(NotNull(), _)) .Times(AnyNumber()) .WillRepeatedly(Return(0)); oas->Start(&source); usleep(500000); oas->Stop(); oas->Close(); } } // namespace media