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