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