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