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/environment.h"
101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
12ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h"
14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/test/test_timeouts.h"
15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_com_initializer.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/audio_io.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/audio_manager.h"
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "media/audio/mock_audio_source_callback.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/win/audio_low_latency_output_win.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/audio/win/core_audio_util_win.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/decoder_buffer.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/seekable_buffer.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/test_data_util.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h"
26eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "testing/gmock_mutant.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::_;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::AnyNumber;
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using ::testing::AtLeast;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::Between;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::CreateFunctor;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::DoAll;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::Gt;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::InvokeWithoutArgs;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::NotNull;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::Return;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::win::ScopedCOMInitializer;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char kSpeechFile_16b_s_48k[] = "speech_16b_stereo_48kHz.raw";
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char kSpeechFile_16b_s_44k[] = "speech_16b_stereo_44kHz.raw";
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const size_t kFileDurationMs = 20000;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const size_t kNumFileSegments = 2;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kBitsPerSample = 16;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const size_t kMaxDeltaSamples = 1000;
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const char kDeltaTimeMsFileName[] = "delta_times_ms.txt";
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MATCHER_P(HasValidDelay, value, "") {
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It is difficult to come up with a perfect test condition for the delay
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // estimation. For now, verify that the produced output delay is always
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // larger than the selected buffer size.
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return arg.hardware_delay_bytes >= value.hardware_delay_bytes;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Used to terminate a loop from a different thread than the loop belongs to.
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |loop| should be a MessageLoopProxy.
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ACTION_P(QuitLoop, loop) {
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  loop->PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This audio source implementation should be used for manual tests only since
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// it takes about 20 seconds to play out a file.
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ReadFromFileAudioSource : public AudioOutputStream::AudioSourceCallback {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit ReadFromFileAudioSource(const std::string& name)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : pos_(0),
707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      previous_call_time_(base::TimeTicks::Now()),
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      text_file_(NULL),
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      elements_to_write_(0) {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Reads a test file from media/test/data directory.
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file_ = ReadTestDataFile(name);
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Creates an array that will store delta times between callbacks.
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The content of this array will be written to a text file at
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // destruction and can then be used for off-line analysis of the exact
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // timing of callbacks. The text file will be stored in media/test/data.
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delta_times_.reset(new int[kMaxDeltaSamples]);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~ReadFromFileAudioSource() {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Get complete file path to output file in directory containing
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // media_unittests.exe.
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath file_name;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(PathService::Get(base::DIR_EXE, &file_name));
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file_name = file_name.AppendASCII(kDeltaTimeMsFileName);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(!text_file_);
91a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    text_file_ = base::OpenFile(file_name, "wt");
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG_IF(ERROR, !text_file_) << "Failed to open log file.";
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Write the array which contains delta times to a text file.
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t elements_written = 0;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (elements_written < elements_to_write_) {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fprintf(text_file_, "%d\n", delta_times_[elements_written]);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++elements_written;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::CloseFile(text_file_);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // AudioOutputStream::AudioSourceCallback implementation.
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int OnMoreData(AudioBus* audio_bus,
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         AudioBuffersState buffers_state) {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Store time difference between two successive callbacks in an array.
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // These values will be written to a file in the destructor.
1097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const base::TimeTicks now_time = base::TimeTicks::Now();
1107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const int diff = (now_time - previous_call_time_).InMilliseconds();
1117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    previous_call_time_ = now_time;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (elements_to_write_ < kMaxDeltaSamples) {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delta_times_[elements_to_write_] = diff;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++elements_to_write_;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int max_size =
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        audio_bus->frames() * audio_bus->channels() * kBitsPerSample / 8;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Use samples read from a data file and fill up the audio buffer
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // provided to us in the callback.
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pos_ + static_cast<int>(max_size) > file_size())
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      max_size = file_size() - pos_;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int frames = max_size / (audio_bus->channels() * kBitsPerSample / 8);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (max_size) {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      audio_bus->FromInterleaved(
127ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          file_->data() + pos_, frames, kBitsPerSample / 8);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pos_ += max_size;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return frames;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnError(AudioOutputStream* stream) {}
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  int file_size() { return file_->data_size(); }
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<DecoderBuffer> file_;
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<int[]> delta_times_;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int pos_;
1417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  base::TimeTicks previous_call_time_;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FILE* text_file_;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t elements_to_write_;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool ExclusiveModeIsEnabled() {
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (WASAPIAudioOutputStream::GetShareMode() ==
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          AUDCLNT_SHAREMODE_EXCLUSIVE);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Convenience method which ensures that we are not running on the build
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// bots and that at least one valid output device can be found. We also
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// verify that we are not running on XP since the low-latency (WASAPI-
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// based) version requires Windows Vista or higher.
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool CanRunAudioTests(AudioManager* audio_man) {
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!CoreAudioUtil::IsSupported()) {
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "This test requires Windows Vista or higher.";
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(henrika): note that we use Wave today to query the number of
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // existing output devices.
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!audio_man->HasAudioOutputDevices()) {
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "No output devices detected.";
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Convenience method which creates a default AudioOutputStream object but
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// also allows the user to modify the default settings.
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class AudioOutputStreamWrapper {
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit AudioOutputStreamWrapper(AudioManager* audio_manager)
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : audio_man_(audio_manager),
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        format_(AudioParameters::AUDIO_PCM_LOW_LATENCY),
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        bits_per_sample_(kBitsPerSample) {
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AudioParameters preferred_params;
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_TRUE(SUCCEEDED(CoreAudioUtil::GetPreferredAudioParameters(
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        eRender, eConsole, &preferred_params)));
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    channel_layout_ = preferred_params.channel_layout();
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sample_rate_ = preferred_params.sample_rate();
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    samples_per_packet_ = preferred_params.frames_per_buffer();
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~AudioOutputStreamWrapper() {}
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Creates AudioOutputStream object using default parameters.
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioOutputStream* Create() {
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return CreateOutputStream();
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Creates AudioOutputStream object using non-default parameters where the
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // frame size is modified.
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioOutputStream* Create(int samples_per_packet) {
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    samples_per_packet_ = samples_per_packet;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return CreateOutputStream();
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Creates AudioOutputStream object using non-default parameters where the
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // sample rate and frame size are modified.
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioOutputStream* Create(int sample_rate, int samples_per_packet) {
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sample_rate_ = sample_rate;
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    samples_per_packet_ = samples_per_packet;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return CreateOutputStream();
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioParameters::Format format() const { return format_; }
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int channels() const { return ChannelLayoutToChannelCount(channel_layout_); }
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int bits_per_sample() const { return bits_per_sample_; }
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int sample_rate() const { return sample_rate_; }
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int samples_per_packet() const { return samples_per_packet_; }
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioOutputStream* CreateOutputStream() {
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AudioOutputStream* aos = audio_man_->MakeAudioOutputStream(
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        AudioParameters(format_, channel_layout_, sample_rate_,
219868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                        bits_per_sample_, samples_per_packet_),
2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        std::string());
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(aos);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return aos;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioManager* audio_man_;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioParameters::Format format_;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ChannelLayout channel_layout_;
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int bits_per_sample_;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int sample_rate_;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int samples_per_packet_;
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Convenience method which creates a default AudioOutputStream object.
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static AudioOutputStream* CreateDefaultAudioOutputStream(
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AudioManager* audio_manager) {
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioOutputStreamWrapper aosw(audio_manager);
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioOutputStream* aos = aosw.Create();
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return aos;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify that we can retrieve the current hardware/mixing sample rate
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// for the default audio device.
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(henrika): modify this test when we support full device enumeration.
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WASAPIAudioOutputStreamTest, HardwareSampleRate) {
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Skip this test in exclusive mode since the resulting rate is only utilized
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for shared mode streams.
247a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CanRunAudioTests(audio_manager.get()) || ExclusiveModeIsEnabled())
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Default device intended for games, system notification sounds,
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and voice commands.
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int fs = static_cast<int>(
25458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      WASAPIAudioOutputStream::HardwareSampleRate(std::string()));
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GE(fs, 0);
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test Create(), Close() calling sequence.
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WASAPIAudioOutputStreamTest, CreateAndClose) {
260a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CanRunAudioTests(audio_manager.get()))
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get());
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->Close();
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test Open(), Close() calling sequence.
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WASAPIAudioOutputStreamTest, OpenAndClose) {
269a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CanRunAudioTests(audio_manager.get()))
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get());
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(aos->Open());
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->Close();
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test Open(), Start(), Close() calling sequence.
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WASAPIAudioOutputStreamTest, OpenStartAndClose) {
279a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CanRunAudioTests(audio_manager.get()))
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get());
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(aos->Open());
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockAudioSourceCallback source;
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(source, OnError(aos))
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Times(0);
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->Start(&source);
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->Close();
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test Open(), Start(), Stop(), Close() calling sequence.
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WASAPIAudioOutputStreamTest, OpenStartStopAndClose) {
293a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CanRunAudioTests(audio_manager.get()))
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get());
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(aos->Open());
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockAudioSourceCallback source;
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_CALL(source, OnError(aos))
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Times(0);
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->Start(&source);
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->Stop();
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->Close();
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test SetVolume(), GetVolume()
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WASAPIAudioOutputStreamTest, Volume) {
308a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CanRunAudioTests(audio_manager.get()))
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get());
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initial volume should be full volume (1.0).
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double volume = 0.0;
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->GetVolume(&volume);
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1.0, volume);
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify some valid volume settings.
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->SetVolume(0.0);
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->GetVolume(&volume);
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0.0, volume);
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->SetVolume(0.5);
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->GetVolume(&volume);
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0.5, volume);
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->SetVolume(1.0);
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->GetVolume(&volume);
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1.0, volume);
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that invalid volume setting have no effect.
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->SetVolume(1.5);
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->GetVolume(&volume);
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1.0, volume);
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->SetVolume(-0.5);
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->GetVolume(&volume);
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1.0, volume);
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->Close();
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test some additional calling sequences.
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WASAPIAudioOutputStreamTest, MiscCallingSequences) {
345a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CanRunAudioTests(audio_manager.get()))
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get());
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WASAPIAudioOutputStream* waos = static_cast<WASAPIAudioOutputStream*>(aos);
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Open(), Open() is a valid calling sequence (second call does nothing).
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(aos->Open());
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(aos->Open());
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockAudioSourceCallback source;
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start(), Start() is a valid calling sequence (second call does nothing).
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->Start(&source);
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(waos->started());
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->Start(&source);
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(waos->started());
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Stop(), Stop() is a valid calling sequence (second call does nothing).
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->Stop();
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(waos->started());
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->Stop();
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(waos->started());
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start(), Stop(), Start(), Stop().
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->Start(&source);
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(waos->started());
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->Stop();
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(waos->started());
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->Start(&source);
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(waos->started());
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->Stop();
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(waos->started());
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->Close();
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use preferred packet size and verify that rendering starts.
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(WASAPIAudioOutputStreamTest, ValidPacketSize) {
385a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CanRunAudioTests(audio_manager.get()))
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::MessageLoopForUI loop;
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockAudioSourceCallback source;
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create default WASAPI output stream which plays out in stereo using
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the shared mixing rate. The default buffer size is 10ms.
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioOutputStreamWrapper aosw(audio_manager.get());
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioOutputStream* aos = aosw.Create();
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(aos->Open());
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Derive the expected size in bytes of each packet.
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 bytes_per_packet = aosw.channels() * aosw.samples_per_packet() *
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           (aosw.bits_per_sample() / 8);
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set up expected minimum delay estimation.
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioBuffersState state(0, bytes_per_packet);
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wait for the first callback and verify its parameters.
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_CALL(source, OnMoreData(NotNull(), HasValidDelay(state)))
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .WillOnce(DoAll(
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          QuitLoop(loop.message_loop_proxy()),
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          Return(aosw.samples_per_packet())));
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->Start(&source);
412c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  loop.PostDelayedTask(FROM_HERE, base::MessageLoop::QuitClosure(),
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       TestTimeouts::action_timeout());
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loop.Run();
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->Stop();
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->Close();
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This test is intended for manual tests and should only be enabled
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// when it is required to play out data from a local PCM file.
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// By default, GTest will print out YOU HAVE 1 DISABLED TEST.
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// To include disabled tests in test execution, just invoke the test program
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// with --gtest_also_run_disabled_tests or set the GTEST_ALSO_RUN_DISABLED_TESTS
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// environment variable to a value greater than 0.
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The test files are approximately 20 seconds long.
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WASAPIAudioOutputStreamTest, DISABLED_ReadFromStereoFile) {
427a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CanRunAudioTests(audio_manager.get()))
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioOutputStreamWrapper aosw(audio_manager.get());
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioOutputStream* aos = aosw.Create();
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(aos->Open());
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string file_name;
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (aosw.sample_rate() == 48000) {
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file_name = kSpeechFile_16b_s_48k;
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (aosw.sample_rate() == 44100) {
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file_name = kSpeechFile_16b_s_44k;
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (aosw.sample_rate() == 96000) {
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Use 48kHz file at 96kHz as well. Will sound like Donald Duck.
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file_name = kSpeechFile_16b_s_48k;
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FAIL() << "This test supports 44.1, 48kHz and 96kHz only.";
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadFromFileAudioSource file_source(file_name);
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
449f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  VLOG(0) << "File name      : " << file_name.c_str();
450f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  VLOG(0) << "Sample rate    : " << aosw.sample_rate();
451f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  VLOG(0) << "Bits per sample: " << aosw.bits_per_sample();
452f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  VLOG(0) << "#channels      : " << aosw.channels();
453f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  VLOG(0) << "File size      : " << file_source.file_size();
454f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  VLOG(0) << "#file segments : " << kNumFileSegments;
455f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  VLOG(0) << ">> Listen to the stereo file while playing...";
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kNumFileSegments; i++) {
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Each segment will start with a short (~20ms) block of zeros, hence
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // some short glitches might be heard in this test if kNumFileSegments
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // is larger than one. The exact length of the silence period depends on
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the selected sample rate.
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    aos->Start(&file_source);
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::PlatformThread::Sleep(
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::TimeDelta::FromMilliseconds(kFileDurationMs / kNumFileSegments));
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    aos->Stop();
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
468f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  VLOG(0) << ">> Stereo file playout has stopped.";
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->Close();
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify that we can open the output stream in exclusive mode using a
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// certain set of audio parameters and a sample rate of 48kHz.
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The expected outcomes of each setting in this test has been derived
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// manually using log outputs (--v=1).
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WASAPIAudioOutputStreamTest, ExclusiveModeBufferSizesAt48kHz) {
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ExclusiveModeIsEnabled())
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
480a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CanRunAudioTests(audio_manager.get()))
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioOutputStreamWrapper aosw(audio_manager.get());
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 10ms @ 48kHz shall work.
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note that, this is the same size as we can use for shared-mode streaming
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // but here the endpoint buffer delay is only 10ms instead of 20ms.
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioOutputStream* aos = aosw.Create(48000, 480);
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(aos->Open());
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->Close();
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 5ms @ 48kHz does not work due to misalignment.
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This test will propose an aligned buffer size of 5.3333ms.
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note that we must call Close() even is Open() fails since Close() also
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // deletes the object and we want to create a new object in the next test.
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos = aosw.Create(48000, 240);
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(aos->Open());
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->Close();
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 5.3333ms @ 48kHz should work (see test above).
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos = aosw.Create(48000, 256);
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(aos->Open());
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->Close();
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 2.6667ms is smaller than the minimum supported size (=3ms).
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos = aosw.Create(48000, 128);
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(aos->Open());
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->Close();
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 3ms does not correspond to an aligned buffer size.
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This test will propose an aligned buffer size of 3.3333ms.
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos = aosw.Create(48000, 144);
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(aos->Open());
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->Close();
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 3.3333ms @ 48kHz <=> smallest possible buffer size we can use.
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos = aosw.Create(48000, 160);
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(aos->Open());
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->Close();
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify that we can open the output stream in exclusive mode using a
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// certain set of audio parameters and a sample rate of 44.1kHz.
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The expected outcomes of each setting in this test has been derived
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// manually using log outputs (--v=1).
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WASAPIAudioOutputStreamTest, ExclusiveModeBufferSizesAt44kHz) {
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ExclusiveModeIsEnabled())
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
531a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CanRunAudioTests(audio_manager.get()))
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioOutputStreamWrapper aosw(audio_manager.get());
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 10ms @ 44.1kHz does not work due to misalignment.
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This test will propose an aligned buffer size of 10.1587ms.
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioOutputStream* aos = aosw.Create(44100, 441);
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(aos->Open());
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->Close();
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 10.1587ms @ 44.1kHz shall work (see test above).
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos = aosw.Create(44100, 448);
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(aos->Open());
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->Close();
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 5.8050ms @ 44.1 should work.
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos = aosw.Create(44100, 256);
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(aos->Open());
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->Close();
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 4.9887ms @ 44.1kHz does not work to misalignment.
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This test will propose an aligned buffer size of 5.0794ms.
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note that we must call Close() even is Open() fails since Close() also
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // deletes the object and we want to create a new object in the next test.
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos = aosw.Create(44100, 220);
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(aos->Open());
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->Close();
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 5.0794ms @ 44.1kHz shall work (see test above).
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos = aosw.Create(44100, 224);
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(aos->Open());
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->Close();
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 2.9025ms is smaller than the minimum supported size (=3ms).
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos = aosw.Create(44100, 132);
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(aos->Open());
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->Close();
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 3.01587ms is larger than the minimum size but is not aligned.
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This test will propose an aligned buffer size of 3.6281ms.
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos = aosw.Create(44100, 133);
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(aos->Open());
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->Close();
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 3.6281ms @ 44.1kHz <=> smallest possible buffer size we can use.
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos = aosw.Create(44100, 160);
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(aos->Open());
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->Close();
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify that we can open and start the output stream in exclusive mode at
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the lowest possible delay at 48kHz.
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WASAPIAudioOutputStreamTest, ExclusiveModeMinBufferSizeAt48kHz) {
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ExclusiveModeIsEnabled())
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
589a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CanRunAudioTests(audio_manager.get()))
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
593c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::MessageLoopForUI loop;
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockAudioSourceCallback source;
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create exclusive-mode WASAPI output stream which plays out in stereo
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // using the minimum buffer size at 48kHz sample rate.
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioOutputStreamWrapper aosw(audio_manager.get());
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioOutputStream* aos = aosw.Create(48000, 160);
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(aos->Open());
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Derive the expected size in bytes of each packet.
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 bytes_per_packet = aosw.channels() * aosw.samples_per_packet() *
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (aosw.bits_per_sample() / 8);
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set up expected minimum delay estimation.
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioBuffersState state(0, bytes_per_packet);
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Wait for the first callback and verify its parameters.
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_CALL(source, OnMoreData(NotNull(), HasValidDelay(state)))
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .WillOnce(DoAll(
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          QuitLoop(loop.message_loop_proxy()),
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          Return(aosw.samples_per_packet())))
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .WillRepeatedly(Return(aosw.samples_per_packet()));
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->Start(&source);
617c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  loop.PostDelayedTask(FROM_HERE, base::MessageLoop::QuitClosure(),
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       TestTimeouts::action_timeout());
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loop.Run();
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->Stop();
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->Close();
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify that we can open and start the output stream in exclusive mode at
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the lowest possible delay at 44.1kHz.
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WASAPIAudioOutputStreamTest, ExclusiveModeMinBufferSizeAt44kHz) {
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ExclusiveModeIsEnabled())
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
630a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting());
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CanRunAudioTests(audio_manager.get()))
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
634c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::MessageLoopForUI loop;
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockAudioSourceCallback source;
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create exclusive-mode WASAPI output stream which plays out in stereo
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // using the minimum buffer size at 44.1kHz sample rate.
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioOutputStreamWrapper aosw(audio_manager.get());
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioOutputStream* aos = aosw.Create(44100, 160);
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(aos->Open());
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Derive the expected size in bytes of each packet.
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 bytes_per_packet = aosw.channels() * aosw.samples_per_packet() *
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (aosw.bits_per_sample() / 8);
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set up expected minimum delay estimation.
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioBuffersState state(0, bytes_per_packet);
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wait for the first callback and verify its parameters.
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_CALL(source, OnMoreData(NotNull(), HasValidDelay(state)))
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    .WillOnce(DoAll(
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        QuitLoop(loop.message_loop_proxy()),
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Return(aosw.samples_per_packet())))
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    .WillRepeatedly(Return(aosw.samples_per_packet()));
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->Start(&source);
658c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  loop.PostDelayedTask(FROM_HERE, base::MessageLoop::QuitClosure(),
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        TestTimeouts::action_timeout());
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loop.Run();
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->Stop();
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  aos->Close();
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace media
666