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/memory/aligned_memory.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/sync_socket.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_com_initializer.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/windows_version.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/limits.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/audio_io.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/audio_manager.h" 185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "media/audio/mock_audio_source_callback.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/simple_sources.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::_; 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::AnyNumber; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::DoAll; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::Field; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::Invoke; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::InSequence; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::NiceMock; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::NotNull; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::Return; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::win::ScopedCOMInitializer; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media { 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const wchar_t kAudioFile1_16b_m_16K[] 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) = L"media\\test\\data\\sweep02_16b_mono_16KHz.raw"; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static int ClearData(AudioBus* audio_bus, AudioBuffersState buffers_state) { 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) audio_bus->Zero(); 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return audio_bus->frames(); 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class allows to find out if the callbacks are occurring as 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// expected and if any error has been reported. 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TestSourceBasic : public AudioOutputStream::AudioSourceCallback { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit TestSourceBasic() 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : callback_count_(0), 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) had_error_(0) { 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // AudioSourceCallback::OnMoreData implementation: 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual int OnMoreData(AudioBus* audio_bus, 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioBuffersState buffers_state) { 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++callback_count_; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Touch the channel memory value to make sure memory is good. 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_bus->Zero(); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return audio_bus->frames(); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // AudioSourceCallback::OnError implementation: 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void OnError(AudioOutputStream* stream) { 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++had_error_; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns how many times OnMoreData() has been called. 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int callback_count() const { 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return callback_count_; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns how many times the OnError callback was called. 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int had_error() const { 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return had_error_; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void set_error(bool error) { 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) had_error_ += error ? 1 : 0; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int callback_count_; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int had_error_; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMaxNumBuffers = 3; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Specializes TestSourceBasic to simulate a source that blocks for some time 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in the OnMoreData callback. 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TestSourceLaggy : public TestSourceBasic { 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestSourceLaggy(int laggy_after_buffer, int lag_in_ms) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : laggy_after_buffer_(laggy_after_buffer), lag_in_ms_(lag_in_ms) { 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual int OnMoreData(AudioBus* audio_bus, 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioBuffersState buffers_state) { 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Call the base, which increments the callback_count_. 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestSourceBasic::OnMoreData(audio_bus, buffers_state); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (callback_count() > kMaxNumBuffers) { 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::Sleep(lag_in_ms_); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return audio_bus->frames(); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int laggy_after_buffer_; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int lag_in_ms_; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper class to memory map an entire file. The mapping is read-only. Don't 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// use for gigabyte-sized files. Attempts to write to this memory generate 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// memory access violations. 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ReadOnlyMappedFile { 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit ReadOnlyMappedFile(const wchar_t* file_name) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : fmap_(NULL), start_(NULL), size_(0) { 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE file = ::CreateFileW(file_name, GENERIC_READ, FILE_SHARE_READ, NULL, 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (INVALID_HANDLE_VALUE == file) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fmap_ = ::CreateFileMappingW(file, NULL, PAGE_READONLY, 0, 0, NULL); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::CloseHandle(file); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!fmap_) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start_ = reinterpret_cast<char*>(::MapViewOfFile(fmap_, FILE_MAP_READ, 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, 0, 0)); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!start_) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MEMORY_BASIC_INFORMATION mbi = {0}; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::VirtualQuery(start_, &mbi, sizeof(mbi)); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_ = mbi.RegionSize; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~ReadOnlyMappedFile() { 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (start_) { 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::UnmapViewOfFile(start_); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::CloseHandle(fmap_); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns true if the file was successfully mapped. 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_valid() const { 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ((start_ > 0) && (size_ > 0)); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns the size in bytes of the mapped memory. 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 size() const { 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return size_; 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns the memory backing the file. 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const void* GetChunkAt(uint32 offset) { 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return &start_[offset]; 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE fmap_; 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* start_; 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 size_; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// =========================================================================== 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Validation of AudioManager::AUDIO_PCM_LINEAR 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NOTE: 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The tests can fail on the build bots when somebody connects to them via 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// remote-desktop and the rdp client installs an audio device that fails to open 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// at some point, possibly when the connection goes idle. 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that can it be created and closed. 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WinAudioTest, PCMWaveStreamGetAndClose) { 163a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting()); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!audio_man->HasAudioOutputDevices()) { 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "No output device detected."; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioOutputStream* oas = audio_man->MakeAudioOutputStream( 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_STEREO, 171868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 8000, 16, 256), 1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string()); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(NULL != oas); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Close(); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that can it be cannot be created with invalid parameters. 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WinAudioTest, SanityOnMakeParams) { 179a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting()); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!audio_man->HasAudioOutputDevices()) { 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "No output device detected."; 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioParameters::Format fmt = AudioParameters::AUDIO_PCM_LINEAR; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream( 187868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AudioParameters(fmt, CHANNEL_LAYOUT_UNSUPPORTED, 8000, 16, 256), 1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string())); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream( 190868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 1024 * 1024, 16, 256), 1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string())); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream( 193868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AudioParameters(fmt, CHANNEL_LAYOUT_STEREO, 8000, 80, 256), 1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string())); 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream( 196868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AudioParameters(fmt, CHANNEL_LAYOUT_UNSUPPORTED, 8000, 16, 256), 1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string())); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream( 199868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AudioParameters(fmt, CHANNEL_LAYOUT_STEREO, -8000, 16, 256), 2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string())); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream( 202868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 8000, 16, -100), 2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string())); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream( 205868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 8000, 16, 0), 2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string())); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream( 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 8000, 16, 209868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) media::limits::kMaxSamplesPerPacket + 1), 2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string())); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that it can be opened and closed. 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WinAudioTest, PCMWaveStreamOpenAndClose) { 215a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting()); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!audio_man->HasAudioOutputDevices()) { 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "No output device detected."; 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioOutputStream* oas = audio_man->MakeAudioOutputStream( 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_STEREO, 223868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 8000, 16, 256), 2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string()); 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(NULL != oas); 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(oas->Open()); 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Close(); 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that it has a maximum packet size. 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WinAudioTest, PCMWaveStreamOpenLimit) { 232a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting()); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!audio_man->HasAudioOutputDevices()) { 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "No output device detected."; 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioOutputStream* oas = audio_man->MakeAudioOutputStream( 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_STEREO, 240868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 8000, 16, 1024 * 1024 * 1024), 2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string()); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(NULL == oas); 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (oas) 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Close(); 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test potential deadlock situation if the source is slow or blocks for some 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// time. The actual EXPECT_GT are mostly meaningless and the real test is that 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the test completes in reasonable time. 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WinAudioTest, PCMWaveSlowSource) { 251a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting()); 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!audio_man->HasAudioOutputDevices()) { 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "No output device detected."; 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioOutputStream* oas = audio_man->MakeAudioOutputStream( 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO, 259868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 16000, 16, 256), 2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string()); 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(NULL != oas); 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestSourceLaggy test_laggy(2, 90); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(oas->Open()); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The test parameters cause a callback every 32 ms and the source is 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // sleeping for 90 ms, so it is guaranteed that we run out of ready buffers. 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Start(&test_laggy); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::Sleep(500); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_GT(test_laggy.callback_count(), 2); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(test_laggy.had_error()); 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Stop(); 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::Sleep(500); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Close(); 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test another potential deadlock situation if the thread that calls Start() 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// gets paused. This test is best when run over RDP with audio enabled. See 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// bug 19276 for more details. 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WinAudioTest, PCMWaveStreamPlaySlowLoop) { 279a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting()); 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!audio_man->HasAudioOutputDevices()) { 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "No output device detected."; 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 10; 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioOutputStream* oas = audio_man->MakeAudioOutputStream( 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO, 288868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AudioParameters::kAudioCDSampleRate, 16, samples_100_ms), 2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string()); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(NULL != oas); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SineWaveAudioSource source(1, 200.0, AudioParameters::kAudioCDSampleRate); 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(oas->Open()); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->SetVolume(1.0); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int ix = 0; ix != 5; ++ix) { 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Start(&source); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::Sleep(10); 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Stop(); 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Close(); 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This test produces actual audio for .5 seconds on the default wave 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// device at 44.1K s/sec. Parameters have been chosen carefully so you should 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// not hear pops or noises while the sound is playing. 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WinAudioTest, PCMWaveStreamPlay200HzTone44Kss) { 310a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting()); 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!audio_man->HasAudioOutputDevices()) { 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "No output device detected."; 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 10; 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioOutputStream* oas = audio_man->MakeAudioOutputStream( 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO, 319868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AudioParameters::kAudioCDSampleRate, 16, samples_100_ms), 3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string()); 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(NULL != oas); 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SineWaveAudioSource source(1, 200.0, AudioParameters::kAudioCDSampleRate); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(oas->Open()); 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->SetVolume(1.0); 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Start(&source); 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::Sleep(500); 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Stop(); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Close(); 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This test produces actual audio for for .5 seconds on the default wave 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// device at 22K s/sec. Parameters have been chosen carefully so you should 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// not hear pops or noises while the sound is playing. The audio also should 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// sound with a lower volume than PCMWaveStreamPlay200HzTone44Kss. 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WinAudioTest, PCMWaveStreamPlay200HzTone22Kss) { 338a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting()); 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!audio_man->HasAudioOutputDevices()) { 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "No output device detected."; 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 20; 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioOutputStream* oas = audio_man->MakeAudioOutputStream( 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO, 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioParameters::kAudioCDSampleRate / 2, 16, 348868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) samples_100_ms), 3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string()); 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(NULL != oas); 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SineWaveAudioSource source(1, 200.0, AudioParameters::kAudioCDSampleRate/2); 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(oas->Open()); 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->SetVolume(0.5); 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Start(&source); 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::Sleep(500); 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Test that the volume is within the set limits. 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double volume = 0.0; 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->GetVolume(&volume); 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_LT(volume, 0.51); 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_GT(volume, 0.49); 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Stop(); 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Close(); 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Uses a restricted source to play ~2 seconds of audio for about 5 seconds. We 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// try hard to generate situation where the two threads are accessing the 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// object roughly at the same time. 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WinAudioTest, PushSourceFile16KHz) { 373a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting()); 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!audio_man->HasAudioOutputDevices()) { 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "No output device detected."; 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const int kSampleRate = 16000; 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SineWaveAudioSource source(1, 200.0, kSampleRate); 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Compute buffer size for 100ms of audio. 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint32 kSamples100ms = (kSampleRate / 1000) * 100; 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Restrict SineWaveAudioSource to 100ms of samples. 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source.CapSamples(kSamples100ms); 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioOutputStream* oas = audio_man->MakeAudioOutputStream( 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO, 388868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kSampleRate, 16, kSamples100ms), 3895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string()); 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(NULL != oas); 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(oas->Open()); 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->SetVolume(1.0); 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Start(&source); 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We buffer and play at the same time, buffering happens every ~10ms and the 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // consuming of the buffer happens every ~100ms. We do 100 buffers which 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // effectively wrap around the file more than once. 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (uint32 ix = 0; ix != 100; ++ix) { 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::Sleep(10); 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source.Reset(); 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Play a little bit more of the file. 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::Sleep(500); 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Stop(); 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Close(); 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This test is to make sure an AudioOutputStream can be started after it was 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// stopped. You will here two .5 seconds wave signal separated by 0.5 seconds 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of silence. 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WinAudioTest, PCMWaveStreamPlayTwice200HzTone44Kss) { 416a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting()); 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!audio_man->HasAudioOutputDevices()) { 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "No output device detected."; 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 10; 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioOutputStream* oas = audio_man->MakeAudioOutputStream( 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO, 425868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AudioParameters::kAudioCDSampleRate, 16, samples_100_ms), 4265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string()); 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) { 453a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting()); 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. 4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const AudioParameters params = audio_man->GetDefaultOutputStreamParameters(); 4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int sample_rate = params.sample_rate(); 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 samples_10_ms = sample_rate / 100; 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int n = 1; 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (base::win::GetVersion() <= base::win::VERSION_XP) ? n = 5 : n = 1; 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioOutputStream* oas = audio_man->MakeAudioOutputStream( 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY, 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHANNEL_LAYOUT_MONO, sample_rate, 472868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 16, n * samples_10_ms), 4735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string()); 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(NULL != oas); 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SineWaveAudioSource source(1, 200, sample_rate); 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool opened = oas->Open(); 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!opened) { 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It was not possible to open this audio device in mono. 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No point in continuing the test so let's break here. 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Mono is not supported. Skipping test."; 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Close(); 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->SetVolume(1.0); 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Play the wave for .8 seconds. 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Start(&source); 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::Sleep(800); 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Stop(); 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Close(); 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Check that the pending bytes value is correct what the stream starts. 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WinAudioTest, PCMWaveStreamPendingBytes) { 497a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting()); 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!audio_man->HasAudioOutputDevices()) { 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "No output device detected."; 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 10; 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioOutputStream* oas = audio_man->MakeAudioOutputStream( 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO, 506868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AudioParameters::kAudioCDSampleRate, 16, samples_100_ms), 5075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string()); 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(NULL != oas); 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NiceMock<MockAudioSourceCallback> source; 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(oas->Open()); 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 bytes_100_ms = samples_100_ms * 2; 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Audio output stream has either a double or triple buffer scheme. 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We expect the amount of pending bytes will reaching up to 2 times of 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |bytes_100_ms| depending on number of buffers used. 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // From that it would decrease as we are playing the data but not providing 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // new one. And then we will try to provide zero data so the amount of 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // pending bytes will go down and eventually read zero. 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InSequence s; 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_CALL(source, OnMoreData(NotNull(), 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Field(&AudioBuffersState::pending_bytes, 0))) 5255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .WillOnce(Invoke(ClearData)); 5264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 5274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Note: If AudioManagerWin::NumberOfWaveOutBuffers() ever changes, or if this 5284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // test is run on Vista, these expectations will fail. 5294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_CALL(source, OnMoreData(NotNull(), 5304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) Field(&AudioBuffersState::pending_bytes, 5314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bytes_100_ms))) 5325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .WillOnce(Invoke(ClearData)); 5334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_CALL(source, OnMoreData(NotNull(), 5344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) Field(&AudioBuffersState::pending_bytes, 5354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2 * bytes_100_ms))) 5365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .WillOnce(Invoke(ClearData)); 5374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_CALL(source, OnMoreData(NotNull(), 5384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) Field(&AudioBuffersState::pending_bytes, 5394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2 * bytes_100_ms))) 5404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) .Times(AnyNumber()) 5414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) .WillRepeatedly(Return(0)); 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_CALL(source, OnMoreData(NotNull(), 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Field(&AudioBuffersState::pending_bytes, 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bytes_100_ms))) 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .Times(AnyNumber()) 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .WillRepeatedly(Return(0)); 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_CALL(source, OnMoreData(NotNull(), 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Field(&AudioBuffersState::pending_bytes, 0))) 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .Times(AnyNumber()) 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) .WillRepeatedly(Return(0)); 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Start(&source); 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::Sleep(500); 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Stop(); 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Close(); 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Simple source that uses a SyncSocket to retrieve the audio data 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// from a potentially remote thread. 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SyncSocketSource : public AudioOutputStream::AudioSourceCallback { 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SyncSocketSource(base::SyncSocket* socket, const AudioParameters& params) 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : socket_(socket) { 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Setup AudioBus wrapping data we'll receive over the sync socket. 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data_size_ = AudioBus::CalculateMemorySize(params); 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data_.reset(static_cast<float*>( 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AlignedAlloc(data_size_, AudioBus::kChannelAlignment))); 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_bus_ = AudioBus::WrapMemory(params, data_.get()); 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~SyncSocketSource() {} 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // AudioSourceCallback::OnMoreData implementation: 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual int OnMoreData(AudioBus* audio_bus, 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioBuffersState buffers_state) { 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) socket_->Send(&buffers_state, sizeof(buffers_state)); 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 size = socket_->Receive(data_.get(), data_size_); 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(static_cast<size_t>(size) % sizeof(*audio_bus_->channel(0)), 0U); 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_bus_->CopyTo(audio_bus); 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return audio_bus_->frames(); 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual int OnMoreIOData(AudioBus* source, 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioBus* dest, 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioBuffersState buffers_state) { 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // AudioSourceCallback::OnError implementation: 5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void OnError(AudioOutputStream* stream) { 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SyncSocket* socket_; 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int data_size_; 5945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<float, base::AlignedFreeDeleter> data_; 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<AudioBus> audio_bus_; 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct SyncThreadContext { 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SyncSocket* socket; 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int sample_rate; 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int channels; 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int frames; 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double sine_freq; 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 packet_size_bytes; 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This thread provides the data that the SyncSocketSource above needs 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// using the other end of a SyncSocket. The protocol is as follows: 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SyncSocketSource ---send 4 bytes ------------> SyncSocketThread 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// <--- audio packet ---------- 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DWORD __stdcall SyncSocketThread(void* context) { 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SyncThreadContext& ctx = *(reinterpret_cast<SyncThreadContext*>(context)); 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Setup AudioBus wrapping data we'll pass over the sync socket. 6175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<float, base::AlignedFreeDeleter> data(static_cast<float*>( 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AlignedAlloc(ctx.packet_size_bytes, AudioBus::kChannelAlignment))); 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<AudioBus> audio_bus = AudioBus::WrapMemory( 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ctx.channels, ctx.frames, data.get()); 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SineWaveAudioSource sine(1, ctx.sine_freq, ctx.sample_rate); 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kTwoSecFrames = ctx.sample_rate * 2; 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioBuffersState buffers_state; 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int times = 0; 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int ix = 0; ix < kTwoSecFrames; ix += ctx.frames) { 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ctx.socket->Receive(&buffers_state, sizeof(buffers_state)) == 0) 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((times > 0) && (buffers_state.pending_bytes < 1000)) __debugbreak(); 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sine.OnMoreData(audio_bus.get(), buffers_state); 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ctx.socket->Send(data.get(), ctx.packet_size_bytes); 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++times; 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test the basic operation of AudioOutputStream used with a SyncSocket. 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The emphasis is to verify that it is possible to feed data to the audio 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// layer using a source based on SyncSocket. In a real situation we would 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// go for the low-latency version in combination with SyncSocket, but to keep 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the test more simple, AUDIO_PCM_LINEAR is utilized instead. The main 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// principle of the test still remains and we avoid the additional complexity 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// related to the two different audio-layers for AUDIO_PCM_LOW_LATENCY. 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In this test you should hear a continuous 200Hz tone for 2 seconds. 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WinAudioTest, SyncSocketBasic) { 648a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting()); 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!audio_man->HasAudioOutputDevices()) { 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "No output device detected."; 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const int sample_rate = AudioParameters::kAudioCDSampleRate; 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const uint32 kSamples20ms = sample_rate / 50; 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHANNEL_LAYOUT_MONO, sample_rate, 16, kSamples20ms); 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 660868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AudioOutputStream* oas = audio_man->MakeAudioOutputStream(params, 6615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string()); 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(NULL != oas); 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(oas->Open()); 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SyncSocket sockets[2]; 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(base::SyncSocket::CreatePair(&sockets[0], &sockets[1])); 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SyncSocketSource source(&sockets[0], params); 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SyncThreadContext thread_context; 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thread_context.sample_rate = params.sample_rate(); 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thread_context.sine_freq = 200.0; 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thread_context.packet_size_bytes = AudioBus::CalculateMemorySize(params); 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thread_context.frames = params.frames_per_buffer(); 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thread_context.channels = params.channels(); 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thread_context.socket = &sockets[1]; 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE thread = ::CreateThread(NULL, 0, SyncSocketThread, 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &thread_context, 0, NULL); 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Start(&source); 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::WaitForSingleObject(thread, INFINITE); 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::CloseHandle(thread); 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Stop(); 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oas->Close(); 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace media 692