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