audio_low_latency_output_win_unittest.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include <windows.h> 6#include <mmsystem.h> 7 8#include "base/basictypes.h" 9#include "base/environment.h" 10#include "base/file_util.h" 11#include "base/memory/scoped_ptr.h" 12#include "base/message_loop.h" 13#include "base/test/test_timeouts.h" 14#include "base/time.h" 15#include "base/path_service.h" 16#include "base/win/scoped_com_initializer.h" 17#include "media/audio/audio_io.h" 18#include "media/audio/audio_manager.h" 19#include "media/audio/audio_util.h" 20#include "media/audio/win/audio_low_latency_output_win.h" 21#include "media/audio/win/core_audio_util_win.h" 22#include "media/base/decoder_buffer.h" 23#include "media/base/seekable_buffer.h" 24#include "media/base/test_data_util.h" 25#include "testing/gmock_mutant.h" 26#include "testing/gmock/include/gmock/gmock.h" 27#include "testing/gtest/include/gtest/gtest.h" 28 29using ::testing::_; 30using ::testing::AnyNumber; 31using ::testing::AtLeast; 32using ::testing::Between; 33using ::testing::CreateFunctor; 34using ::testing::DoAll; 35using ::testing::Gt; 36using ::testing::InvokeWithoutArgs; 37using ::testing::NotNull; 38using ::testing::Return; 39using base::win::ScopedCOMInitializer; 40 41namespace media { 42 43static const char kSpeechFile_16b_s_48k[] = "speech_16b_stereo_48kHz.raw"; 44static const char kSpeechFile_16b_s_44k[] = "speech_16b_stereo_44kHz.raw"; 45static const size_t kFileDurationMs = 20000; 46static const size_t kNumFileSegments = 2; 47static const int kBitsPerSample = 16; 48static const size_t kMaxDeltaSamples = 1000; 49static const char kDeltaTimeMsFileName[] = "delta_times_ms.txt"; 50 51MATCHER_P(HasValidDelay, value, "") { 52 // It is difficult to come up with a perfect test condition for the delay 53 // estimation. For now, verify that the produced output delay is always 54 // larger than the selected buffer size. 55 return arg.hardware_delay_bytes >= value.hardware_delay_bytes; 56} 57 58// Used to terminate a loop from a different thread than the loop belongs to. 59// |loop| should be a MessageLoopProxy. 60ACTION_P(QuitLoop, loop) { 61 loop->PostTask(FROM_HERE, base::MessageLoop::QuitClosure()); 62} 63 64class MockAudioSourceCallback : public AudioOutputStream::AudioSourceCallback { 65 public: 66 MOCK_METHOD2(OnMoreData, int(AudioBus* audio_bus, 67 AudioBuffersState buffers_state)); 68 MOCK_METHOD3(OnMoreIOData, int(AudioBus* source, 69 AudioBus* dest, 70 AudioBuffersState buffers_state)); 71 MOCK_METHOD1(OnError, void(AudioOutputStream* stream)); 72}; 73 74// This audio source implementation should be used for manual tests only since 75// it takes about 20 seconds to play out a file. 76class ReadFromFileAudioSource : public AudioOutputStream::AudioSourceCallback { 77 public: 78 explicit ReadFromFileAudioSource(const std::string& name) 79 : pos_(0), 80 previous_call_time_(base::Time::Now()), 81 text_file_(NULL), 82 elements_to_write_(0) { 83 // Reads a test file from media/test/data directory. 84 file_ = ReadTestDataFile(name); 85 86 // Creates an array that will store delta times between callbacks. 87 // The content of this array will be written to a text file at 88 // destruction and can then be used for off-line analysis of the exact 89 // timing of callbacks. The text file will be stored in media/test/data. 90 delta_times_.reset(new int[kMaxDeltaSamples]); 91 } 92 93 virtual ~ReadFromFileAudioSource() { 94 // Get complete file path to output file in directory containing 95 // media_unittests.exe. 96 base::FilePath file_name; 97 EXPECT_TRUE(PathService::Get(base::DIR_EXE, &file_name)); 98 file_name = file_name.AppendASCII(kDeltaTimeMsFileName); 99 100 EXPECT_TRUE(!text_file_); 101 text_file_ = file_util::OpenFile(file_name, "wt"); 102 DLOG_IF(ERROR, !text_file_) << "Failed to open log file."; 103 104 // Write the array which contains delta times to a text file. 105 size_t elements_written = 0; 106 while (elements_written < elements_to_write_) { 107 fprintf(text_file_, "%d\n", delta_times_[elements_written]); 108 ++elements_written; 109 } 110 111 file_util::CloseFile(text_file_); 112 } 113 114 // AudioOutputStream::AudioSourceCallback implementation. 115 virtual int OnMoreData(AudioBus* audio_bus, 116 AudioBuffersState buffers_state) { 117 // Store time difference between two successive callbacks in an array. 118 // These values will be written to a file in the destructor. 119 int diff = (base::Time::Now() - previous_call_time_).InMilliseconds(); 120 previous_call_time_ = base::Time::Now(); 121 if (elements_to_write_ < kMaxDeltaSamples) { 122 delta_times_[elements_to_write_] = diff; 123 ++elements_to_write_; 124 } 125 126 int max_size = 127 audio_bus->frames() * audio_bus->channels() * kBitsPerSample / 8; 128 129 // Use samples read from a data file and fill up the audio buffer 130 // provided to us in the callback. 131 if (pos_ + static_cast<int>(max_size) > file_size()) 132 max_size = file_size() - pos_; 133 int frames = max_size / (audio_bus->channels() * kBitsPerSample / 8); 134 if (max_size) { 135 audio_bus->FromInterleaved( 136 file_->GetData() + pos_, frames, kBitsPerSample / 8); 137 pos_ += max_size; 138 } 139 return frames; 140 } 141 142 virtual int OnMoreIOData(AudioBus* source, 143 AudioBus* dest, 144 AudioBuffersState buffers_state) OVERRIDE { 145 NOTREACHED(); 146 return 0; 147 } 148 149 virtual void OnError(AudioOutputStream* stream) {} 150 151 int file_size() { return file_->GetDataSize(); } 152 153 private: 154 scoped_refptr<DecoderBuffer> file_; 155 scoped_ptr<int[]> delta_times_; 156 int pos_; 157 base::Time previous_call_time_; 158 FILE* text_file_; 159 size_t elements_to_write_; 160}; 161 162static bool ExclusiveModeIsEnabled() { 163 return (WASAPIAudioOutputStream::GetShareMode() == 164 AUDCLNT_SHAREMODE_EXCLUSIVE); 165} 166 167// Convenience method which ensures that we are not running on the build 168// bots and that at least one valid output device can be found. We also 169// verify that we are not running on XP since the low-latency (WASAPI- 170// based) version requires Windows Vista or higher. 171static bool CanRunAudioTests(AudioManager* audio_man) { 172 if (!CoreAudioUtil::IsSupported()) { 173 LOG(WARNING) << "This test requires Windows Vista or higher."; 174 return false; 175 } 176 177 // TODO(henrika): note that we use Wave today to query the number of 178 // existing output devices. 179 if (!audio_man->HasAudioOutputDevices()) { 180 LOG(WARNING) << "No output devices detected."; 181 return false; 182 } 183 184 return true; 185} 186 187// Convenience method which creates a default AudioOutputStream object but 188// also allows the user to modify the default settings. 189class AudioOutputStreamWrapper { 190 public: 191 explicit AudioOutputStreamWrapper(AudioManager* audio_manager) 192 : audio_man_(audio_manager), 193 format_(AudioParameters::AUDIO_PCM_LOW_LATENCY), 194 bits_per_sample_(kBitsPerSample) { 195 AudioParameters preferred_params; 196 EXPECT_TRUE(SUCCEEDED(CoreAudioUtil::GetPreferredAudioParameters( 197 eRender, eConsole, &preferred_params))); 198 channel_layout_ = preferred_params.channel_layout(); 199 sample_rate_ = preferred_params.sample_rate(); 200 samples_per_packet_ = preferred_params.frames_per_buffer(); 201 } 202 203 ~AudioOutputStreamWrapper() {} 204 205 // Creates AudioOutputStream object using default parameters. 206 AudioOutputStream* Create() { 207 return CreateOutputStream(); 208 } 209 210 // Creates AudioOutputStream object using non-default parameters where the 211 // frame size is modified. 212 AudioOutputStream* Create(int samples_per_packet) { 213 samples_per_packet_ = samples_per_packet; 214 return CreateOutputStream(); 215 } 216 217 // Creates AudioOutputStream object using non-default parameters where the 218 // sample rate and frame size are modified. 219 AudioOutputStream* Create(int sample_rate, int samples_per_packet) { 220 sample_rate_ = sample_rate; 221 samples_per_packet_ = samples_per_packet; 222 return CreateOutputStream(); 223 } 224 225 AudioParameters::Format format() const { return format_; } 226 int channels() const { return ChannelLayoutToChannelCount(channel_layout_); } 227 int bits_per_sample() const { return bits_per_sample_; } 228 int sample_rate() const { return sample_rate_; } 229 int samples_per_packet() const { return samples_per_packet_; } 230 231 private: 232 AudioOutputStream* CreateOutputStream() { 233 AudioOutputStream* aos = audio_man_->MakeAudioOutputStream( 234 AudioParameters(format_, channel_layout_, sample_rate_, 235 bits_per_sample_, samples_per_packet_)); 236 EXPECT_TRUE(aos); 237 return aos; 238 } 239 240 AudioManager* audio_man_; 241 AudioParameters::Format format_; 242 ChannelLayout channel_layout_; 243 int bits_per_sample_; 244 int sample_rate_; 245 int samples_per_packet_; 246}; 247 248// Convenience method which creates a default AudioOutputStream object. 249static AudioOutputStream* CreateDefaultAudioOutputStream( 250 AudioManager* audio_manager) { 251 AudioOutputStreamWrapper aosw(audio_manager); 252 AudioOutputStream* aos = aosw.Create(); 253 return aos; 254} 255 256// Verify that we can retrieve the current hardware/mixing sample rate 257// for the default audio device. 258// TODO(henrika): modify this test when we support full device enumeration. 259TEST(WASAPIAudioOutputStreamTest, HardwareSampleRate) { 260 // Skip this test in exclusive mode since the resulting rate is only utilized 261 // for shared mode streams. 262 scoped_ptr<AudioManager> audio_manager(AudioManager::Create()); 263 if (!CanRunAudioTests(audio_manager.get()) || ExclusiveModeIsEnabled()) 264 return; 265 266 // Default device intended for games, system notification sounds, 267 // and voice commands. 268 int fs = static_cast<int>( 269 WASAPIAudioOutputStream::HardwareSampleRate()); 270 EXPECT_GE(fs, 0); 271} 272 273// Test Create(), Close() calling sequence. 274TEST(WASAPIAudioOutputStreamTest, CreateAndClose) { 275 scoped_ptr<AudioManager> audio_manager(AudioManager::Create()); 276 if (!CanRunAudioTests(audio_manager.get())) 277 return; 278 AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get()); 279 aos->Close(); 280} 281 282// Test Open(), Close() calling sequence. 283TEST(WASAPIAudioOutputStreamTest, OpenAndClose) { 284 scoped_ptr<AudioManager> audio_manager(AudioManager::Create()); 285 if (!CanRunAudioTests(audio_manager.get())) 286 return; 287 AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get()); 288 EXPECT_TRUE(aos->Open()); 289 aos->Close(); 290} 291 292// Test Open(), Start(), Close() calling sequence. 293TEST(WASAPIAudioOutputStreamTest, OpenStartAndClose) { 294 scoped_ptr<AudioManager> audio_manager(AudioManager::Create()); 295 if (!CanRunAudioTests(audio_manager.get())) 296 return; 297 AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get()); 298 EXPECT_TRUE(aos->Open()); 299 MockAudioSourceCallback source; 300 EXPECT_CALL(source, OnError(aos)) 301 .Times(0); 302 aos->Start(&source); 303 aos->Close(); 304} 305 306// Test Open(), Start(), Stop(), Close() calling sequence. 307TEST(WASAPIAudioOutputStreamTest, OpenStartStopAndClose) { 308 scoped_ptr<AudioManager> audio_manager(AudioManager::Create()); 309 if (!CanRunAudioTests(audio_manager.get())) 310 return; 311 AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get()); 312 EXPECT_TRUE(aos->Open()); 313 MockAudioSourceCallback source; 314 EXPECT_CALL(source, OnError(aos)) 315 .Times(0); 316 aos->Start(&source); 317 aos->Stop(); 318 aos->Close(); 319} 320 321// Test SetVolume(), GetVolume() 322TEST(WASAPIAudioOutputStreamTest, Volume) { 323 scoped_ptr<AudioManager> audio_manager(AudioManager::Create()); 324 if (!CanRunAudioTests(audio_manager.get())) 325 return; 326 AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get()); 327 328 // Initial volume should be full volume (1.0). 329 double volume = 0.0; 330 aos->GetVolume(&volume); 331 EXPECT_EQ(1.0, volume); 332 333 // Verify some valid volume settings. 334 aos->SetVolume(0.0); 335 aos->GetVolume(&volume); 336 EXPECT_EQ(0.0, volume); 337 338 aos->SetVolume(0.5); 339 aos->GetVolume(&volume); 340 EXPECT_EQ(0.5, volume); 341 342 aos->SetVolume(1.0); 343 aos->GetVolume(&volume); 344 EXPECT_EQ(1.0, volume); 345 346 // Ensure that invalid volume setting have no effect. 347 aos->SetVolume(1.5); 348 aos->GetVolume(&volume); 349 EXPECT_EQ(1.0, volume); 350 351 aos->SetVolume(-0.5); 352 aos->GetVolume(&volume); 353 EXPECT_EQ(1.0, volume); 354 355 aos->Close(); 356} 357 358// Test some additional calling sequences. 359TEST(WASAPIAudioOutputStreamTest, MiscCallingSequences) { 360 scoped_ptr<AudioManager> audio_manager(AudioManager::Create()); 361 if (!CanRunAudioTests(audio_manager.get())) 362 return; 363 364 AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get()); 365 WASAPIAudioOutputStream* waos = static_cast<WASAPIAudioOutputStream*>(aos); 366 367 // Open(), Open() is a valid calling sequence (second call does nothing). 368 EXPECT_TRUE(aos->Open()); 369 EXPECT_TRUE(aos->Open()); 370 371 MockAudioSourceCallback source; 372 373 // Start(), Start() is a valid calling sequence (second call does nothing). 374 aos->Start(&source); 375 EXPECT_TRUE(waos->started()); 376 aos->Start(&source); 377 EXPECT_TRUE(waos->started()); 378 379 // Stop(), Stop() is a valid calling sequence (second call does nothing). 380 aos->Stop(); 381 EXPECT_FALSE(waos->started()); 382 aos->Stop(); 383 EXPECT_FALSE(waos->started()); 384 385 // Start(), Stop(), Start(), Stop(). 386 aos->Start(&source); 387 EXPECT_TRUE(waos->started()); 388 aos->Stop(); 389 EXPECT_FALSE(waos->started()); 390 aos->Start(&source); 391 EXPECT_TRUE(waos->started()); 392 aos->Stop(); 393 EXPECT_FALSE(waos->started()); 394 395 aos->Close(); 396} 397 398// Use preferred packet size and verify that rendering starts. 399TEST(WASAPIAudioOutputStreamTest, ValidPacketSize) { 400 scoped_ptr<AudioManager> audio_manager(AudioManager::Create()); 401 if (!CanRunAudioTests(audio_manager.get())) 402 return; 403 404 base::MessageLoopForUI loop; 405 MockAudioSourceCallback source; 406 407 // Create default WASAPI output stream which plays out in stereo using 408 // the shared mixing rate. The default buffer size is 10ms. 409 AudioOutputStreamWrapper aosw(audio_manager.get()); 410 AudioOutputStream* aos = aosw.Create(); 411 EXPECT_TRUE(aos->Open()); 412 413 // Derive the expected size in bytes of each packet. 414 uint32 bytes_per_packet = aosw.channels() * aosw.samples_per_packet() * 415 (aosw.bits_per_sample() / 8); 416 417 // Set up expected minimum delay estimation. 418 AudioBuffersState state(0, bytes_per_packet); 419 420 // Wait for the first callback and verify its parameters. 421 EXPECT_CALL(source, OnMoreData(NotNull(), HasValidDelay(state))) 422 .WillOnce(DoAll( 423 QuitLoop(loop.message_loop_proxy()), 424 Return(aosw.samples_per_packet()))); 425 426 aos->Start(&source); 427 loop.PostDelayedTask(FROM_HERE, base::MessageLoop::QuitClosure(), 428 TestTimeouts::action_timeout()); 429 loop.Run(); 430 aos->Stop(); 431 aos->Close(); 432} 433 434// Use a non-preferred packet size and verify that Open() fails. 435TEST(WASAPIAudioOutputStreamTest, InvalidPacketSize) { 436 scoped_ptr<AudioManager> audio_manager(AudioManager::Create()); 437 if (!CanRunAudioTests(audio_manager.get())) 438 return; 439 440 if (ExclusiveModeIsEnabled()) 441 return; 442 443 AudioParameters preferred_params; 444 EXPECT_TRUE(SUCCEEDED(CoreAudioUtil::GetPreferredAudioParameters( 445 eRender, eConsole, &preferred_params))); 446 int too_large_packet_size = 2 * preferred_params.frames_per_buffer(); 447 448 AudioOutputStreamWrapper aosw(audio_manager.get()); 449 AudioOutputStream* aos = aosw.Create(too_large_packet_size); 450 EXPECT_FALSE(aos->Open()); 451 452 aos->Close(); 453} 454 455// This test is intended for manual tests and should only be enabled 456// when it is required to play out data from a local PCM file. 457// By default, GTest will print out YOU HAVE 1 DISABLED TEST. 458// To include disabled tests in test execution, just invoke the test program 459// with --gtest_also_run_disabled_tests or set the GTEST_ALSO_RUN_DISABLED_TESTS 460// environment variable to a value greater than 0. 461// The test files are approximately 20 seconds long. 462TEST(WASAPIAudioOutputStreamTest, DISABLED_ReadFromStereoFile) { 463 scoped_ptr<AudioManager> audio_manager(AudioManager::Create()); 464 if (!CanRunAudioTests(audio_manager.get())) 465 return; 466 467 AudioOutputStreamWrapper aosw(audio_manager.get()); 468 AudioOutputStream* aos = aosw.Create(); 469 EXPECT_TRUE(aos->Open()); 470 471 std::string file_name; 472 if (aosw.sample_rate() == 48000) { 473 file_name = kSpeechFile_16b_s_48k; 474 } else if (aosw.sample_rate() == 44100) { 475 file_name = kSpeechFile_16b_s_44k; 476 } else if (aosw.sample_rate() == 96000) { 477 // Use 48kHz file at 96kHz as well. Will sound like Donald Duck. 478 file_name = kSpeechFile_16b_s_48k; 479 } else { 480 FAIL() << "This test supports 44.1, 48kHz and 96kHz only."; 481 return; 482 } 483 ReadFromFileAudioSource file_source(file_name); 484 485 LOG(INFO) << "File name : " << file_name.c_str(); 486 LOG(INFO) << "Sample rate : " << aosw.sample_rate(); 487 LOG(INFO) << "Bits per sample: " << aosw.bits_per_sample(); 488 LOG(INFO) << "#channels : " << aosw.channels(); 489 LOG(INFO) << "File size : " << file_source.file_size(); 490 LOG(INFO) << "#file segments : " << kNumFileSegments; 491 LOG(INFO) << ">> Listen to the stereo file while playing..."; 492 493 for (int i = 0; i < kNumFileSegments; i++) { 494 // Each segment will start with a short (~20ms) block of zeros, hence 495 // some short glitches might be heard in this test if kNumFileSegments 496 // is larger than one. The exact length of the silence period depends on 497 // the selected sample rate. 498 aos->Start(&file_source); 499 base::PlatformThread::Sleep( 500 base::TimeDelta::FromMilliseconds(kFileDurationMs / kNumFileSegments)); 501 aos->Stop(); 502 } 503 504 LOG(INFO) << ">> Stereo file playout has stopped."; 505 aos->Close(); 506} 507 508// Verify that we can open the output stream in exclusive mode using a 509// certain set of audio parameters and a sample rate of 48kHz. 510// The expected outcomes of each setting in this test has been derived 511// manually using log outputs (--v=1). 512TEST(WASAPIAudioOutputStreamTest, ExclusiveModeBufferSizesAt48kHz) { 513 if (!ExclusiveModeIsEnabled()) 514 return; 515 516 scoped_ptr<AudioManager> audio_manager(AudioManager::Create()); 517 if (!CanRunAudioTests(audio_manager.get())) 518 return; 519 520 AudioOutputStreamWrapper aosw(audio_manager.get()); 521 522 // 10ms @ 48kHz shall work. 523 // Note that, this is the same size as we can use for shared-mode streaming 524 // but here the endpoint buffer delay is only 10ms instead of 20ms. 525 AudioOutputStream* aos = aosw.Create(48000, 480); 526 EXPECT_TRUE(aos->Open()); 527 aos->Close(); 528 529 // 5ms @ 48kHz does not work due to misalignment. 530 // This test will propose an aligned buffer size of 5.3333ms. 531 // Note that we must call Close() even is Open() fails since Close() also 532 // deletes the object and we want to create a new object in the next test. 533 aos = aosw.Create(48000, 240); 534 EXPECT_FALSE(aos->Open()); 535 aos->Close(); 536 537 // 5.3333ms @ 48kHz should work (see test above). 538 aos = aosw.Create(48000, 256); 539 EXPECT_TRUE(aos->Open()); 540 aos->Close(); 541 542 // 2.6667ms is smaller than the minimum supported size (=3ms). 543 aos = aosw.Create(48000, 128); 544 EXPECT_FALSE(aos->Open()); 545 aos->Close(); 546 547 // 3ms does not correspond to an aligned buffer size. 548 // This test will propose an aligned buffer size of 3.3333ms. 549 aos = aosw.Create(48000, 144); 550 EXPECT_FALSE(aos->Open()); 551 aos->Close(); 552 553 // 3.3333ms @ 48kHz <=> smallest possible buffer size we can use. 554 aos = aosw.Create(48000, 160); 555 EXPECT_TRUE(aos->Open()); 556 aos->Close(); 557} 558 559// Verify that we can open the output stream in exclusive mode using a 560// certain set of audio parameters and a sample rate of 44.1kHz. 561// The expected outcomes of each setting in this test has been derived 562// manually using log outputs (--v=1). 563TEST(WASAPIAudioOutputStreamTest, ExclusiveModeBufferSizesAt44kHz) { 564 if (!ExclusiveModeIsEnabled()) 565 return; 566 567 scoped_ptr<AudioManager> audio_manager(AudioManager::Create()); 568 if (!CanRunAudioTests(audio_manager.get())) 569 return; 570 571 AudioOutputStreamWrapper aosw(audio_manager.get()); 572 573 // 10ms @ 44.1kHz does not work due to misalignment. 574 // This test will propose an aligned buffer size of 10.1587ms. 575 AudioOutputStream* aos = aosw.Create(44100, 441); 576 EXPECT_FALSE(aos->Open()); 577 aos->Close(); 578 579 // 10.1587ms @ 44.1kHz shall work (see test above). 580 aos = aosw.Create(44100, 448); 581 EXPECT_TRUE(aos->Open()); 582 aos->Close(); 583 584 // 5.8050ms @ 44.1 should work. 585 aos = aosw.Create(44100, 256); 586 EXPECT_TRUE(aos->Open()); 587 aos->Close(); 588 589 // 4.9887ms @ 44.1kHz does not work to misalignment. 590 // This test will propose an aligned buffer size of 5.0794ms. 591 // Note that we must call Close() even is Open() fails since Close() also 592 // deletes the object and we want to create a new object in the next test. 593 aos = aosw.Create(44100, 220); 594 EXPECT_FALSE(aos->Open()); 595 aos->Close(); 596 597 // 5.0794ms @ 44.1kHz shall work (see test above). 598 aos = aosw.Create(44100, 224); 599 EXPECT_TRUE(aos->Open()); 600 aos->Close(); 601 602 // 2.9025ms is smaller than the minimum supported size (=3ms). 603 aos = aosw.Create(44100, 132); 604 EXPECT_FALSE(aos->Open()); 605 aos->Close(); 606 607 // 3.01587ms is larger than the minimum size but is not aligned. 608 // This test will propose an aligned buffer size of 3.6281ms. 609 aos = aosw.Create(44100, 133); 610 EXPECT_FALSE(aos->Open()); 611 aos->Close(); 612 613 // 3.6281ms @ 44.1kHz <=> smallest possible buffer size we can use. 614 aos = aosw.Create(44100, 160); 615 EXPECT_TRUE(aos->Open()); 616 aos->Close(); 617} 618 619// Verify that we can open and start the output stream in exclusive mode at 620// the lowest possible delay at 48kHz. 621TEST(WASAPIAudioOutputStreamTest, ExclusiveModeMinBufferSizeAt48kHz) { 622 if (!ExclusiveModeIsEnabled()) 623 return; 624 625 scoped_ptr<AudioManager> audio_manager(AudioManager::Create()); 626 if (!CanRunAudioTests(audio_manager.get())) 627 return; 628 629 base::MessageLoopForUI loop; 630 MockAudioSourceCallback source; 631 632 // Create exclusive-mode WASAPI output stream which plays out in stereo 633 // using the minimum buffer size at 48kHz sample rate. 634 AudioOutputStreamWrapper aosw(audio_manager.get()); 635 AudioOutputStream* aos = aosw.Create(48000, 160); 636 EXPECT_TRUE(aos->Open()); 637 638 // Derive the expected size in bytes of each packet. 639 uint32 bytes_per_packet = aosw.channels() * aosw.samples_per_packet() * 640 (aosw.bits_per_sample() / 8); 641 642 // Set up expected minimum delay estimation. 643 AudioBuffersState state(0, bytes_per_packet); 644 645 // Wait for the first callback and verify its parameters. 646 EXPECT_CALL(source, OnMoreData(NotNull(), HasValidDelay(state))) 647 .WillOnce(DoAll( 648 QuitLoop(loop.message_loop_proxy()), 649 Return(aosw.samples_per_packet()))) 650 .WillRepeatedly(Return(aosw.samples_per_packet())); 651 652 aos->Start(&source); 653 loop.PostDelayedTask(FROM_HERE, base::MessageLoop::QuitClosure(), 654 TestTimeouts::action_timeout()); 655 loop.Run(); 656 aos->Stop(); 657 aos->Close(); 658} 659 660// Verify that we can open and start the output stream in exclusive mode at 661// the lowest possible delay at 44.1kHz. 662TEST(WASAPIAudioOutputStreamTest, ExclusiveModeMinBufferSizeAt44kHz) { 663 if (!ExclusiveModeIsEnabled()) 664 return; 665 666 scoped_ptr<AudioManager> audio_manager(AudioManager::Create()); 667 if (!CanRunAudioTests(audio_manager.get())) 668 return; 669 670 base::MessageLoopForUI loop; 671 MockAudioSourceCallback source; 672 673 // Create exclusive-mode WASAPI output stream which plays out in stereo 674 // using the minimum buffer size at 44.1kHz sample rate. 675 AudioOutputStreamWrapper aosw(audio_manager.get()); 676 AudioOutputStream* aos = aosw.Create(44100, 160); 677 EXPECT_TRUE(aos->Open()); 678 679 // Derive the expected size in bytes of each packet. 680 uint32 bytes_per_packet = aosw.channels() * aosw.samples_per_packet() * 681 (aosw.bits_per_sample() / 8); 682 683 // Set up expected minimum delay estimation. 684 AudioBuffersState state(0, bytes_per_packet); 685 686 // Wait for the first callback and verify its parameters. 687 EXPECT_CALL(source, OnMoreData(NotNull(), HasValidDelay(state))) 688 .WillOnce(DoAll( 689 QuitLoop(loop.message_loop_proxy()), 690 Return(aosw.samples_per_packet()))) 691 .WillRepeatedly(Return(aosw.samples_per_packet())); 692 693 aos->Start(&source); 694 loop.PostDelayedTask(FROM_HERE, base::MessageLoop::QuitClosure(), 695 TestTimeouts::action_timeout()); 696 loop.Run(); 697 aos->Stop(); 698 aos->Close(); 699} 700 701} // namespace media 702