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