audio_output_win_unittest.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h> 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <mmsystem.h> 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/base_paths.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/aligned_memory.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/sync_socket.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_com_initializer.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/windows_version.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/limits.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/audio_io.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/audio_util.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/audio_manager.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/simple_sources.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::_; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::AnyNumber; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::DoAll; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::Field; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::Invoke; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::InSequence; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::NiceMock; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::NotNull; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::Return; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::win::ScopedCOMInitializer; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const wchar_t kAudioFile1_16b_m_16K[] 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) = L"media\\test\\data\\sweep02_16b_mono_16KHz.raw"; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class allows to find out if the callbacks are occurring as 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// expected and if any error has been reported. 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TestSourceBasic : public AudioOutputStream::AudioSourceCallback { 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit TestSourceBasic() 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : callback_count_(0), 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) had_error_(0) { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // AudioSourceCallback::OnMoreData implementation: 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual int OnMoreData(AudioBus* audio_bus, 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioBuffersState buffers_state) { 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++callback_count_; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Touch the channel memory value to make sure memory is good. 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_bus->Zero(); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return audio_bus->frames(); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual int OnMoreIOData(AudioBus* source, 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioBus* dest, 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioBuffersState buffers_state) { 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // AudioSourceCallback::OnError implementation: 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnError(AudioOutputStream* stream, int code) { 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++had_error_; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns how many times OnMoreData() has been called. 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int callback_count() const { 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return callback_count_; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns how many times the OnError callback was called. 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int had_error() const { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return had_error_; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void set_error(bool error) { 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) had_error_ += error ? 1 : 0; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int callback_count_; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int had_error_; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMaxNumBuffers = 3; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Specializes TestSourceBasic to simulate a source that blocks for some time 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in the OnMoreData callback. 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TestSourceLaggy : public TestSourceBasic { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestSourceLaggy(int laggy_after_buffer, int lag_in_ms) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : laggy_after_buffer_(laggy_after_buffer), lag_in_ms_(lag_in_ms) { 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual int OnMoreData(AudioBus* audio_bus, 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioBuffersState buffers_state) { 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Call the base, which increments the callback_count_. 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestSourceBasic::OnMoreData(audio_bus, buffers_state); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (callback_count() > kMaxNumBuffers) { 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::Sleep(lag_in_ms_); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return audio_bus->frames(); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int laggy_after_buffer_; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int lag_in_ms_; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MockAudioSource : public AudioOutputStream::AudioSourceCallback { 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MOCK_METHOD2(OnMoreData, int(AudioBus* audio_bus, 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioBuffersState buffers_state)); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MOCK_METHOD3(OnMoreIOData, int(AudioBus* source, 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioBus* dest, 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioBuffersState buffers_state)); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MOCK_METHOD2(OnError, void(AudioOutputStream* stream, int code)); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static int ClearData(AudioBus* audio_bus, AudioBuffersState buffers_state) { 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_bus->Zero(); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return audio_bus->frames(); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper class to memory map an entire file. The mapping is read-only. Don't 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// use for gigabyte-sized files. Attempts to write to this memory generate 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// memory access violations. 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ReadOnlyMappedFile { 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit ReadOnlyMappedFile(const wchar_t* file_name) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : fmap_(NULL), start_(NULL), size_(0) { 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE file = ::CreateFileW(file_name, GENERIC_READ, FILE_SHARE_READ, NULL, 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (INVALID_HANDLE_VALUE == file) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fmap_ = ::CreateFileMappingW(file, NULL, PAGE_READONLY, 0, 0, NULL); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::CloseHandle(file); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!fmap_) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start_ = reinterpret_cast<char*>(::MapViewOfFile(fmap_, FILE_MAP_READ, 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, 0, 0)); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!start_) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MEMORY_BASIC_INFORMATION mbi = {0}; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::VirtualQuery(start_, &mbi, sizeof(mbi)); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_ = mbi.RegionSize; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~ReadOnlyMappedFile() { 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (start_) { 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::UnmapViewOfFile(start_); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::CloseHandle(fmap_); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns true if the file was successfully mapped. 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_valid() const { 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ((start_ > 0) && (size_ > 0)); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns the size in bytes of the mapped memory. 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 size() const { 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return size_; 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns the memory backing the file. 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const void* GetChunkAt(uint32 offset) { 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return &start_[offset]; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE fmap_; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* start_; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 size_; 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// =========================================================================== 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Validation of AudioManager::AUDIO_PCM_LINEAR 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NOTE: 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The tests can fail on the build bots when somebody connects to them via 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// remote-desktop and the rdp client installs an audio device that fails to open 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// at some point, possibly when the connection goes idle. 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that can it be created and closed. 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WinAudioTest, PCMWaveStreamGetAndClose) { 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<AudioManager> audio_man(AudioManager::Create()); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!audio_man->HasAudioOutputDevices()) { 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "No output device detected."; 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioOutputStream* oas = audio_man->MakeAudioOutputStream( 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_STEREO, 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8000, 16, 256)); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(NULL != oas); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Close(); 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that can it be cannot be created with invalid parameters. 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WinAudioTest, SanityOnMakeParams) { 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<AudioManager> audio_man(AudioManager::Create()); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!audio_man->HasAudioOutputDevices()) { 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "No output device detected."; 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioParameters::Format fmt = AudioParameters::AUDIO_PCM_LINEAR; 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream( 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioParameters(fmt, CHANNEL_LAYOUT_UNSUPPORTED, 8000, 16, 256))); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream( 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 1024 * 1024, 16, 256))); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream( 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioParameters(fmt, CHANNEL_LAYOUT_STEREO, 8000, 80, 256))); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream( 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioParameters(fmt, CHANNEL_LAYOUT_UNSUPPORTED, 8000, 16, 256))); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream( 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioParameters(fmt, CHANNEL_LAYOUT_STEREO, -8000, 16, 256))); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream( 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 8000, 16, -100))); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream( 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 8000, 16, 0))); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream( 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 8000, 16, 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) media::limits::kMaxSamplesPerPacket + 1))); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that it can be opened and closed. 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WinAudioTest, PCMWaveStreamOpenAndClose) { 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<AudioManager> audio_man(AudioManager::Create()); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!audio_man->HasAudioOutputDevices()) { 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "No output device detected."; 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioOutputStream* oas = audio_man->MakeAudioOutputStream( 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_STEREO, 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8000, 16, 256)); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(NULL != oas); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(oas->Open()); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Close(); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that it has a maximum packet size. 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WinAudioTest, PCMWaveStreamOpenLimit) { 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<AudioManager> audio_man(AudioManager::Create()); 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!audio_man->HasAudioOutputDevices()) { 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "No output device detected."; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioOutputStream* oas = audio_man->MakeAudioOutputStream( 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_STEREO, 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8000, 16, 1024 * 1024 * 1024)); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(NULL == oas); 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (oas) 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Close(); 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test potential deadlock situation if the source is slow or blocks for some 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// time. The actual EXPECT_GT are mostly meaningless and the real test is that 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the test completes in reasonable time. 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WinAudioTest, PCMWaveSlowSource) { 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<AudioManager> audio_man(AudioManager::Create()); 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!audio_man->HasAudioOutputDevices()) { 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "No output device detected."; 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioOutputStream* oas = audio_man->MakeAudioOutputStream( 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO, 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16000, 16, 256)); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(NULL != oas); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestSourceLaggy test_laggy(2, 90); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(oas->Open()); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The test parameters cause a callback every 32 ms and the source is 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // sleeping for 90 ms, so it is guaranteed that we run out of ready buffers. 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Start(&test_laggy); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::Sleep(500); 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_GT(test_laggy.callback_count(), 2); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(test_laggy.had_error()); 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Stop(); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::Sleep(500); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Close(); 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test another potential deadlock situation if the thread that calls Start() 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// gets paused. This test is best when run over RDP with audio enabled. See 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// bug 19276 for more details. 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WinAudioTest, PCMWaveStreamPlaySlowLoop) { 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<AudioManager> audio_man(AudioManager::Create()); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!audio_man->HasAudioOutputDevices()) { 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "No output device detected."; 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 10; 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioOutputStream* oas = audio_man->MakeAudioOutputStream( 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO, 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioParameters::kAudioCDSampleRate, 16, samples_100_ms)); 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(NULL != oas); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SineWaveAudioSource source(1, 200.0, AudioParameters::kAudioCDSampleRate); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(oas->Open()); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->SetVolume(1.0); 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int ix = 0; ix != 5; ++ix) { 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Start(&source); 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::Sleep(10); 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Stop(); 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Close(); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This test produces actual audio for .5 seconds on the default wave 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// device at 44.1K s/sec. Parameters have been chosen carefully so you should 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// not hear pops or noises while the sound is playing. 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WinAudioTest, PCMWaveStreamPlay200HzTone44Kss) { 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<AudioManager> audio_man(AudioManager::Create()); 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!audio_man->HasAudioOutputDevices()) { 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "No output device detected."; 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 10; 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioOutputStream* oas = audio_man->MakeAudioOutputStream( 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO, 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioParameters::kAudioCDSampleRate, 16, samples_100_ms)); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(NULL != oas); 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SineWaveAudioSource source(1, 200.0, AudioParameters::kAudioCDSampleRate); 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(oas->Open()); 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->SetVolume(1.0); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Start(&source); 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::Sleep(500); 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Stop(); 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Close(); 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This test produces actual audio for for .5 seconds on the default wave 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// device at 22K s/sec. Parameters have been chosen carefully so you should 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// not hear pops or noises while the sound is playing. The audio also should 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// sound with a lower volume than PCMWaveStreamPlay200HzTone44Kss. 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WinAudioTest, PCMWaveStreamPlay200HzTone22Kss) { 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<AudioManager> audio_man(AudioManager::Create()); 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!audio_man->HasAudioOutputDevices()) { 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "No output device detected."; 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 20; 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioOutputStream* oas = audio_man->MakeAudioOutputStream( 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO, 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioParameters::kAudioCDSampleRate / 2, 16, 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) samples_100_ms)); 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(NULL != oas); 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SineWaveAudioSource source(1, 200.0, AudioParameters::kAudioCDSampleRate/2); 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(oas->Open()); 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->SetVolume(0.5); 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Start(&source); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::Sleep(500); 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Test that the volume is within the set limits. 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double volume = 0.0; 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->GetVolume(&volume); 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_LT(volume, 0.51); 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_GT(volume, 0.49); 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Stop(); 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Close(); 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Uses a restricted source to play ~2 seconds of audio for about 5 seconds. We 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// try hard to generate situation where the two threads are accessing the 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// object roughly at the same time. 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WinAudioTest, PushSourceFile16KHz) { 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<AudioManager> audio_man(AudioManager::Create()); 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!audio_man->HasAudioOutputDevices()) { 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "No output device detected."; 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const int kSampleRate = 16000; 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SineWaveAudioSource source(1, 200.0, kSampleRate); 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Compute buffer size for 100ms of audio. 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint32 kSamples100ms = (kSampleRate / 1000) * 100; 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Restrict SineWaveAudioSource to 100ms of samples. 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source.CapSamples(kSamples100ms); 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioOutputStream* oas = audio_man->MakeAudioOutputStream( 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO, 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kSampleRate, 16, kSamples100ms)); 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(NULL != oas); 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(oas->Open()); 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->SetVolume(1.0); 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Start(&source); 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We buffer and play at the same time, buffering happens every ~10ms and the 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // consuming of the buffer happens every ~100ms. We do 100 buffers which 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // effectively wrap around the file more than once. 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (uint32 ix = 0; ix != 100; ++ix) { 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::Sleep(10); 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source.Reset(); 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Play a little bit more of the file. 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::Sleep(500); 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Stop(); 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Close(); 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This test is to make sure an AudioOutputStream can be started after it was 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// stopped. You will here two .5 seconds wave signal separated by 0.5 seconds 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of silence. 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WinAudioTest, PCMWaveStreamPlayTwice200HzTone44Kss) { 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<AudioManager> audio_man(AudioManager::Create()); 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!audio_man->HasAudioOutputDevices()) { 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "No output device detected."; 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 10; 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioOutputStream* oas = audio_man->MakeAudioOutputStream( 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO, 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioParameters::kAudioCDSampleRate, 16, samples_100_ms)); 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(NULL != oas); 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SineWaveAudioSource source(1, 200.0, AudioParameters::kAudioCDSampleRate); 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(oas->Open()); 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->SetVolume(1.0); 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Play the wave for .5 seconds. 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Start(&source); 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::Sleep(500); 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Stop(); 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sleep to give silence after stopping the AudioOutputStream. 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::Sleep(250); 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start again and play for .5 seconds. 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Start(&source); 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::Sleep(500); 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Stop(); 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Close(); 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// With the low latency mode, WASAPI is utilized by default for Vista and 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// higher and Wave is used for XP and lower. It is possible to utilize a 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// smaller buffer size for WASAPI than for Wave. 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WinAudioTest, PCMWaveStreamPlay200HzToneLowLatency) { 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<AudioManager> audio_man(AudioManager::Create()); 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!audio_man->HasAudioOutputDevices()) { 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "No output device detected."; 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The WASAPI API requires a correct COM environment. 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedCOMInitializer com_init(ScopedCOMInitializer::kMTA); 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Use 10 ms buffer size for WASAPI and 50 ms buffer size for Wave. 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Take the existing native sample rate into account. 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int sample_rate = static_cast<int>(media::GetAudioHardwareSampleRate()); 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 samples_10_ms = sample_rate / 100; 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int n = 1; 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (base::win::GetVersion() <= base::win::VERSION_XP) ? n = 5 : n = 1; 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioOutputStream* oas = audio_man->MakeAudioOutputStream( 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY, 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHANNEL_LAYOUT_MONO, sample_rate, 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16, n * samples_10_ms)); 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(NULL != oas); 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SineWaveAudioSource source(1, 200, sample_rate); 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool opened = oas->Open(); 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!opened) { 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It was not possible to open this audio device in mono. 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No point in continuing the test so let's break here. 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Mono is not supported. Skipping test."; 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Close(); 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->SetVolume(1.0); 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Play the wave for .8 seconds. 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Start(&source); 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::Sleep(800); 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Stop(); 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Close(); 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Check that the pending bytes value is correct what the stream starts. 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WinAudioTest, PCMWaveStreamPendingBytes) { 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<AudioManager> audio_man(AudioManager::Create()); 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!audio_man->HasAudioOutputDevices()) { 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "No output device detected."; 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 10; 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioOutputStream* oas = audio_man->MakeAudioOutputStream( 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO, 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioParameters::kAudioCDSampleRate, 16, samples_100_ms)); 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(NULL != oas); 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NiceMock<MockAudioSource> source; 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(oas->Open()); 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 bytes_100_ms = samples_100_ms * 2; 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Audio output stream has either a double or triple buffer scheme. 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We expect the amount of pending bytes will reaching up to 2 times of 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |bytes_100_ms| depending on number of buffers used. 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // From that it would decrease as we are playing the data but not providing 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // new one. And then we will try to provide zero data so the amount of 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // pending bytes will go down and eventually read zero. 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InSequence s; 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_CALL(source, OnMoreData(NotNull(), 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Field(&AudioBuffersState::pending_bytes, 0))) 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .WillOnce(Invoke(MockAudioSource::ClearData)); 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (NumberOfWaveOutBuffers()) { 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 2: 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; // Calls are the same as at end of 3-buffer scheme. 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 3: 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_CALL(source, OnMoreData(NotNull(), 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Field(&AudioBuffersState::pending_bytes, 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bytes_100_ms))) 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .WillOnce(Invoke(MockAudioSource::ClearData)); 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_CALL(source, OnMoreData(NotNull(), 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Field(&AudioBuffersState::pending_bytes, 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2 * bytes_100_ms))) 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .WillOnce(Invoke(MockAudioSource::ClearData)); 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_CALL(source, OnMoreData(NotNull(), 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Field(&AudioBuffersState::pending_bytes, 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2 * bytes_100_ms))) 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .Times(AnyNumber()) 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .WillRepeatedly(Return(0)); 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(false) 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "Unexpected number of buffers: " << NumberOfWaveOutBuffers(); 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_CALL(source, OnMoreData(NotNull(), 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Field(&AudioBuffersState::pending_bytes, 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bytes_100_ms))) 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .Times(AnyNumber()) 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .WillRepeatedly(Return(0)); 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_CALL(source, OnMoreData(NotNull(), 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Field(&AudioBuffersState::pending_bytes, 0))) 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .Times(AnyNumber()) 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .WillRepeatedly(Return(0)); 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Start(&source); 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::Sleep(500); 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Stop(); 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Close(); 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Simple source that uses a SyncSocket to retrieve the audio data 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// from a potentially remote thread. 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SyncSocketSource : public AudioOutputStream::AudioSourceCallback { 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SyncSocketSource(base::SyncSocket* socket, const AudioParameters& params) 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : socket_(socket) { 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Setup AudioBus wrapping data we'll receive over the sync socket. 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data_size_ = AudioBus::CalculateMemorySize(params); 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data_.reset(static_cast<float*>( 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AlignedAlloc(data_size_, AudioBus::kChannelAlignment))); 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_bus_ = AudioBus::WrapMemory(params, data_.get()); 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~SyncSocketSource() {} 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // AudioSourceCallback::OnMoreData implementation: 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual int OnMoreData(AudioBus* audio_bus, 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioBuffersState buffers_state) { 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) socket_->Send(&buffers_state, sizeof(buffers_state)); 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 size = socket_->Receive(data_.get(), data_size_); 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(static_cast<size_t>(size) % sizeof(*audio_bus_->channel(0)), 0U); 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_bus_->CopyTo(audio_bus); 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return audio_bus_->frames(); 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual int OnMoreIOData(AudioBus* source, 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioBus* dest, 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioBuffersState buffers_state) { 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // AudioSourceCallback::OnError implementation: 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnError(AudioOutputStream* stream, int code) { 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SyncSocket* socket_; 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int data_size_; 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr_malloc<float, base::ScopedPtrAlignedFree> data_; 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<AudioBus> audio_bus_; 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct SyncThreadContext { 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SyncSocket* socket; 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int sample_rate; 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int channels; 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int frames; 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double sine_freq; 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 packet_size_bytes; 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This thread provides the data that the SyncSocketSource above needs 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// using the other end of a SyncSocket. The protocol is as follows: 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SyncSocketSource ---send 4 bytes ------------> SyncSocketThread 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// <--- audio packet ---------- 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DWORD __stdcall SyncSocketThread(void* context) { 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SyncThreadContext& ctx = *(reinterpret_cast<SyncThreadContext*>(context)); 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Setup AudioBus wrapping data we'll pass over the sync socket. 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr_malloc<float, base::ScopedPtrAlignedFree> data(static_cast<float*>( 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AlignedAlloc(ctx.packet_size_bytes, AudioBus::kChannelAlignment))); 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<AudioBus> audio_bus = AudioBus::WrapMemory( 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ctx.channels, ctx.frames, data.get()); 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SineWaveAudioSource sine(1, ctx.sine_freq, ctx.sample_rate); 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kTwoSecFrames = ctx.sample_rate * 2; 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioBuffersState buffers_state; 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int times = 0; 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int ix = 0; ix < kTwoSecFrames; ix += ctx.frames) { 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ctx.socket->Receive(&buffers_state, sizeof(buffers_state)) == 0) 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((times > 0) && (buffers_state.pending_bytes < 1000)) __debugbreak(); 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sine.OnMoreData(audio_bus.get(), buffers_state); 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ctx.socket->Send(data.get(), ctx.packet_size_bytes); 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++times; 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test the basic operation of AudioOutputStream used with a SyncSocket. 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The emphasis is to verify that it is possible to feed data to the audio 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// layer using a source based on SyncSocket. In a real situation we would 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// go for the low-latency version in combination with SyncSocket, but to keep 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the test more simple, AUDIO_PCM_LINEAR is utilized instead. The main 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// principle of the test still remains and we avoid the additional complexity 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// related to the two different audio-layers for AUDIO_PCM_LOW_LATENCY. 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In this test you should hear a continuous 200Hz tone for 2 seconds. 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WinAudioTest, SyncSocketBasic) { 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<AudioManager> audio_man(AudioManager::Create()); 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!audio_man->HasAudioOutputDevices()) { 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "No output device detected."; 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const int sample_rate = AudioParameters::kAudioCDSampleRate; 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const uint32 kSamples20ms = sample_rate / 50; 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHANNEL_LAYOUT_MONO, sample_rate, 16, kSamples20ms); 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioOutputStream* oas = audio_man->MakeAudioOutputStream(params); 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(NULL != oas); 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(oas->Open()); 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SyncSocket sockets[2]; 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(base::SyncSocket::CreatePair(&sockets[0], &sockets[1])); 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SyncSocketSource source(&sockets[0], params); 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SyncThreadContext thread_context; 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thread_context.sample_rate = params.sample_rate(); 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thread_context.sine_freq = 200.0; 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thread_context.packet_size_bytes = AudioBus::CalculateMemorySize(params); 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thread_context.frames = params.frames_per_buffer(); 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thread_context.channels = params.channels(); 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thread_context.socket = &sockets[1]; 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE thread = ::CreateThread(NULL, 0, SyncSocketThread, 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &thread_context, 0, NULL); 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Start(&source); 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::WaitForSingleObject(thread, INFINITE); 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::CloseHandle(thread); 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Stop(); 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Close(); 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace media 694