Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(568)

Side by Side Diff: media/audio/win/audio_output_win_unittest.cc

Issue 10832285: Switch OnMoreData() to use AudioBus. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Review ready. Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <windows.h> 5 #include <windows.h>
6 #include <mmsystem.h> 6 #include <mmsystem.h>
7 7
8 #include "base/basictypes.h" 8 #include "base/basictypes.h"
9 #include "base/base_paths.h" 9 #include "base/base_paths.h"
10 #include "base/file_util.h" 10 #include "base/file_util.h"
11 #include "base/memory/aligned_memory.h"
11 #include "base/path_service.h" 12 #include "base/path_service.h"
12 #include "base/sync_socket.h" 13 #include "base/sync_socket.h"
13 #include "base/win/scoped_com_initializer.h" 14 #include "base/win/scoped_com_initializer.h"
14 #include "base/win/windows_version.h" 15 #include "base/win/windows_version.h"
15 #include "media/base/limits.h" 16 #include "media/base/limits.h"
16 #include "media/audio/audio_io.h" 17 #include "media/audio/audio_io.h"
17 #include "media/audio/audio_util.h" 18 #include "media/audio/audio_util.h"
18 #include "media/audio/audio_manager.h" 19 #include "media/audio/audio_manager.h"
19 #include "media/audio/simple_sources.h" 20 #include "media/audio/simple_sources.h"
20 #include "testing/gmock/include/gmock/gmock.h" 21 #include "testing/gmock/include/gmock/gmock.h"
21 #include "testing/gtest/include/gtest/gtest.h" 22 #include "testing/gtest/include/gtest/gtest.h"
22 23
23 using ::testing::_; 24 using ::testing::_;
24 using ::testing::AnyNumber; 25 using ::testing::AnyNumber;
25 using ::testing::DoAll; 26 using ::testing::DoAll;
26 using ::testing::Field; 27 using ::testing::Field;
28 using ::testing::Invoke;
27 using ::testing::InSequence; 29 using ::testing::InSequence;
28 using ::testing::NiceMock; 30 using ::testing::NiceMock;
29 using ::testing::NotNull; 31 using ::testing::NotNull;
30 using ::testing::Return; 32 using ::testing::Return;
31 33
32 using base::win::ScopedCOMInitializer; 34 using base::win::ScopedCOMInitializer;
33 35
34 namespace media { 36 namespace media {
35 37
36 static const wchar_t kAudioFile1_16b_m_16K[] 38 static const wchar_t kAudioFile1_16b_m_16K[]
37 = L"media\\test\\data\\sweep02_16b_mono_16KHz.raw"; 39 = L"media\\test\\data\\sweep02_16b_mono_16KHz.raw";
38 40
39 // This class allows to find out if the callbacks are occurring as 41 // This class allows to find out if the callbacks are occurring as
40 // expected and if any error has been reported. 42 // expected and if any error has been reported.
41 class TestSourceBasic : public AudioOutputStream::AudioSourceCallback { 43 class TestSourceBasic : public AudioOutputStream::AudioSourceCallback {
42 public: 44 public:
43 explicit TestSourceBasic() 45 explicit TestSourceBasic()
44 : callback_count_(0), 46 : callback_count_(0),
45 had_error_(0) { 47 had_error_(0) {
46 } 48 }
47 // AudioSourceCallback::OnMoreData implementation: 49 // AudioSourceCallback::OnMoreData implementation:
48 virtual uint32 OnMoreData(uint8* dest, 50 virtual int OnMoreData(AudioBus* audio_bus,
49 uint32 max_size, 51 AudioBuffersState buffers_state) {
50 AudioBuffersState buffers_state) {
51 ++callback_count_; 52 ++callback_count_;
52 // Touch the first byte to make sure memory is good. 53 // Touch the channel memory value to make sure memory is good.
53 if (max_size) 54 audio_bus->Zero();
54 reinterpret_cast<char*>(dest)[0] = 1; 55 return audio_bus->frames();
55 return max_size;
56 } 56 }
57 // AudioSourceCallback::OnError implementation: 57 // AudioSourceCallback::OnError implementation:
58 virtual void OnError(AudioOutputStream* stream, int code) { 58 virtual void OnError(AudioOutputStream* stream, int code) {
59 ++had_error_; 59 ++had_error_;
60 } 60 }
61 // Returns how many times OnMoreData() has been called. 61 // Returns how many times OnMoreData() has been called.
62 int callback_count() const { 62 int callback_count() const {
63 return callback_count_; 63 return callback_count_;
64 } 64 }
65 // Returns how many times the OnError callback was called. 65 // Returns how many times the OnError callback was called.
66 int had_error() const { 66 int had_error() const {
67 return had_error_; 67 return had_error_;
68 } 68 }
69 69
70 void set_error(bool error) { 70 void set_error(bool error) {
71 had_error_ += error ? 1 : 0; 71 had_error_ += error ? 1 : 0;
72 } 72 }
73 73
74 private: 74 private:
75 int callback_count_; 75 int callback_count_;
76 int had_error_; 76 int had_error_;
77 }; 77 };
78 78
79 const int kMaxNumBuffers = 3; 79 const int kMaxNumBuffers = 3;
80 // Specializes TestSourceBasic to detect that the AudioStream is using
81 // triple buffering correctly.
82 class TestSourceTripleBuffer : public TestSourceBasic {
DaleCurtis 2012/08/22 23:09:21 Misleading test to begin with since it's trying to
henrika (OOO until Aug 14) 2012/08/23 14:42:53 ALSA on Windows :-)
83 public:
84 TestSourceTripleBuffer() {
85 buffer_address_[0] = NULL;
86 buffer_address_[1] = NULL;
87 buffer_address_[2] = NULL;
88 }
89 // Override of TestSourceBasic::OnMoreData.
90 virtual uint32 OnMoreData(uint8* dest,
91 uint32 max_size,
92 AudioBuffersState buffers_state) {
93 // Call the base, which increments the callback_count_.
94 TestSourceBasic::OnMoreData(dest, max_size, buffers_state);
95 if (callback_count() % NumberOfWaveOutBuffers() == 2) {
96 set_error(!CompareExistingIfNotNULL(2, dest));
97 } else if (callback_count() % NumberOfWaveOutBuffers() == 1) {
98 set_error(!CompareExistingIfNotNULL(1, dest));
99 } else {
100 set_error(!CompareExistingIfNotNULL(0, dest));
101 }
102 if (callback_count() > kMaxNumBuffers) {
103 set_error(buffer_address_[0] == buffer_address_[1]);
104 set_error(buffer_address_[1] == buffer_address_[2]);
105 }
106 return max_size;
107 }
108
109 private:
110 bool CompareExistingIfNotNULL(uint32 index, void* address) {
111 void*& entry = buffer_address_[index];
112 if (!entry)
113 entry = address;
114 return (entry == address);
115 }
116
117 void* buffer_address_[kMaxNumBuffers];
118 };
119
120 // Specializes TestSourceBasic to simulate a source that blocks for some time 80 // Specializes TestSourceBasic to simulate a source that blocks for some time
121 // in the OnMoreData callback. 81 // in the OnMoreData callback.
122 class TestSourceLaggy : public TestSourceBasic { 82 class TestSourceLaggy : public TestSourceBasic {
123 public: 83 public:
124 TestSourceLaggy(int laggy_after_buffer, int lag_in_ms) 84 TestSourceLaggy(int laggy_after_buffer, int lag_in_ms)
125 : laggy_after_buffer_(laggy_after_buffer), lag_in_ms_(lag_in_ms) { 85 : laggy_after_buffer_(laggy_after_buffer), lag_in_ms_(lag_in_ms) {
126 } 86 }
127 virtual uint32 OnMoreData(uint8* dest, 87 virtual int OnMoreData(AudioBus* audio_bus,
128 uint32 max_size, 88 AudioBuffersState buffers_state) {
129 AudioBuffersState buffers_state) {
130 // Call the base, which increments the callback_count_. 89 // Call the base, which increments the callback_count_.
131 TestSourceBasic::OnMoreData(dest, max_size, buffers_state); 90 TestSourceBasic::OnMoreData(audio_bus, buffers_state);
132 if (callback_count() > kMaxNumBuffers) { 91 if (callback_count() > kMaxNumBuffers) {
133 ::Sleep(lag_in_ms_); 92 ::Sleep(lag_in_ms_);
134 } 93 }
135 return max_size; 94 return audio_bus->frames();
136 } 95 }
137 private: 96 private:
138 int laggy_after_buffer_; 97 int laggy_after_buffer_;
139 int lag_in_ms_; 98 int lag_in_ms_;
140 }; 99 };
141 100
142 class MockAudioSource : public AudioOutputStream::AudioSourceCallback { 101 class MockAudioSource : public AudioOutputStream::AudioSourceCallback {
143 public: 102 public:
144 MOCK_METHOD3(OnMoreData, uint32(uint8* dest, 103 MOCK_METHOD2(OnMoreData, int(AudioBus* audio_bus,
145 uint32 max_size, 104 AudioBuffersState buffers_state));
146 AudioBuffersState buffers_state));
147 MOCK_METHOD2(OnError, void(AudioOutputStream* stream, int code)); 105 MOCK_METHOD2(OnError, void(AudioOutputStream* stream, int code));
106
107 static int ClearData(AudioBus* audio_bus, AudioBuffersState buffers_state) {
108 audio_bus->Zero();
109 return audio_bus->frames();
110 }
148 }; 111 };
149 112
150 // Helper class to memory map an entire file. The mapping is read-only. Don't 113 // Helper class to memory map an entire file. The mapping is read-only. Don't
151 // use for gigabyte-sized files. Attempts to write to this memory generate 114 // use for gigabyte-sized files. Attempts to write to this memory generate
152 // memory access violations. 115 // memory access violations.
153 class ReadOnlyMappedFile { 116 class ReadOnlyMappedFile {
154 public: 117 public:
155 explicit ReadOnlyMappedFile(const wchar_t* file_name) 118 explicit ReadOnlyMappedFile(const wchar_t* file_name)
156 : fmap_(NULL), start_(NULL), size_(0) { 119 : fmap_(NULL), start_(NULL), size_(0) {
157 HANDLE file = ::CreateFileW(file_name, GENERIC_READ, FILE_SHARE_READ, NULL, 120 HANDLE file = ::CreateFileW(file_name, GENERIC_READ, FILE_SHARE_READ, NULL,
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
288 } 251 }
289 252
290 AudioOutputStream* oas = audio_man->MakeAudioOutputStream( 253 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
291 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_STEREO, 254 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_STEREO,
292 8000, 16, 1024 * 1024 * 1024)); 255 8000, 16, 1024 * 1024 * 1024));
293 EXPECT_TRUE(NULL == oas); 256 EXPECT_TRUE(NULL == oas);
294 if (oas) 257 if (oas)
295 oas->Close(); 258 oas->Close();
296 } 259 }
297 260
298 // Test that it uses the triple buffers correctly. Because it uses the actual
299 // audio device, you might hear a short pop noise for a short time.
300 TEST(WinAudioTest, PCMWaveStreamTripleBuffer) {
301 scoped_ptr<AudioManager> audio_man(AudioManager::Create());
302 if (!audio_man->HasAudioOutputDevices()) {
303 LOG(WARNING) << "No output device detected.";
304 return;
305 }
306
307 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
308 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
309 16000, 16, 256));
310 ASSERT_TRUE(NULL != oas);
311 TestSourceTripleBuffer test_triple_buffer;
312 EXPECT_TRUE(oas->Open());
313 oas->Start(&test_triple_buffer);
314 ::Sleep(300);
315 EXPECT_GT(test_triple_buffer.callback_count(), kMaxNumBuffers);
316 EXPECT_FALSE(test_triple_buffer.had_error());
317 oas->Stop();
318 ::Sleep(500);
319 oas->Close();
320 }
321
322 // Test potential deadlock situation if the source is slow or blocks for some 261 // Test potential deadlock situation if the source is slow or blocks for some
323 // time. The actual EXPECT_GT are mostly meaningless and the real test is that 262 // time. The actual EXPECT_GT are mostly meaningless and the real test is that
324 // the test completes in reasonable time. 263 // the test completes in reasonable time.
325 TEST(WinAudioTest, PCMWaveSlowSource) { 264 TEST(WinAudioTest, PCMWaveSlowSource) {
326 scoped_ptr<AudioManager> audio_man(AudioManager::Create()); 265 scoped_ptr<AudioManager> audio_man(AudioManager::Create());
327 if (!audio_man->HasAudioOutputDevices()) { 266 if (!audio_man->HasAudioOutputDevices()) {
328 LOG(WARNING) << "No output device detected."; 267 LOG(WARNING) << "No output device detected.";
329 return; 268 return;
330 } 269 }
331 270
(...skipping 23 matching lines...) Expand all
355 LOG(WARNING) << "No output device detected."; 294 LOG(WARNING) << "No output device detected.";
356 return; 295 return;
357 } 296 }
358 297
359 uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 10; 298 uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 10;
360 AudioOutputStream* oas = audio_man->MakeAudioOutputStream( 299 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
361 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO, 300 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
362 AudioParameters::kAudioCDSampleRate, 16, samples_100_ms)); 301 AudioParameters::kAudioCDSampleRate, 16, samples_100_ms));
363 ASSERT_TRUE(NULL != oas); 302 ASSERT_TRUE(NULL != oas);
364 303
365 SineWaveAudioSource source(SineWaveAudioSource::FORMAT_16BIT_LINEAR_PCM, 1, 304 SineWaveAudioSource source(1, 200.0, AudioParameters::kAudioCDSampleRate);
366 200.0, AudioParameters::kAudioCDSampleRate);
367 305
368 EXPECT_TRUE(oas->Open()); 306 EXPECT_TRUE(oas->Open());
369 oas->SetVolume(1.0); 307 oas->SetVolume(1.0);
370 308
371 for (int ix = 0; ix != 5; ++ix) { 309 for (int ix = 0; ix != 5; ++ix) {
372 oas->Start(&source); 310 oas->Start(&source);
373 ::Sleep(10); 311 ::Sleep(10);
374 oas->Stop(); 312 oas->Stop();
375 } 313 }
376 oas->Close(); 314 oas->Close();
377 } 315 }
378 316
379 317
380 // This test produces actual audio for .5 seconds on the default wave 318 // This test produces actual audio for .5 seconds on the default wave
381 // device at 44.1K s/sec. Parameters have been chosen carefully so you should 319 // device at 44.1K s/sec. Parameters have been chosen carefully so you should
382 // not hear pops or noises while the sound is playing. 320 // not hear pops or noises while the sound is playing.
383 TEST(WinAudioTest, PCMWaveStreamPlay200HzTone44Kss) { 321 TEST(WinAudioTest, PCMWaveStreamPlay200HzTone44Kss) {
384 scoped_ptr<AudioManager> audio_man(AudioManager::Create()); 322 scoped_ptr<AudioManager> audio_man(AudioManager::Create());
385 if (!audio_man->HasAudioOutputDevices()) { 323 if (!audio_man->HasAudioOutputDevices()) {
386 LOG(WARNING) << "No output device detected."; 324 LOG(WARNING) << "No output device detected.";
387 return; 325 return;
388 } 326 }
389 327
390 uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 10; 328 uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 10;
391 AudioOutputStream* oas = audio_man->MakeAudioOutputStream( 329 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
392 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO, 330 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
393 AudioParameters::kAudioCDSampleRate, 16, samples_100_ms)); 331 AudioParameters::kAudioCDSampleRate, 16, samples_100_ms));
394 ASSERT_TRUE(NULL != oas); 332 ASSERT_TRUE(NULL != oas);
395 333
396 SineWaveAudioSource source(SineWaveAudioSource::FORMAT_16BIT_LINEAR_PCM, 1, 334 SineWaveAudioSource source(1, 200.0, AudioParameters::kAudioCDSampleRate);
397 200.0, AudioParameters::kAudioCDSampleRate);
398 335
399 EXPECT_TRUE(oas->Open()); 336 EXPECT_TRUE(oas->Open());
400 oas->SetVolume(1.0); 337 oas->SetVolume(1.0);
401 oas->Start(&source); 338 oas->Start(&source);
402 ::Sleep(500); 339 ::Sleep(500);
403 oas->Stop(); 340 oas->Stop();
404 oas->Close(); 341 oas->Close();
405 } 342 }
406 343
407 // This test produces actual audio for for .5 seconds on the default wave 344 // This test produces actual audio for for .5 seconds on the default wave
408 // device at 22K s/sec. Parameters have been chosen carefully so you should 345 // device at 22K s/sec. Parameters have been chosen carefully so you should
409 // not hear pops or noises while the sound is playing. The audio also should 346 // not hear pops or noises while the sound is playing. The audio also should
410 // sound with a lower volume than PCMWaveStreamPlay200HzTone44Kss. 347 // sound with a lower volume than PCMWaveStreamPlay200HzTone44Kss.
411 TEST(WinAudioTest, PCMWaveStreamPlay200HzTone22Kss) { 348 TEST(WinAudioTest, PCMWaveStreamPlay200HzTone22Kss) {
412 scoped_ptr<AudioManager> audio_man(AudioManager::Create()); 349 scoped_ptr<AudioManager> audio_man(AudioManager::Create());
413 if (!audio_man->HasAudioOutputDevices()) { 350 if (!audio_man->HasAudioOutputDevices()) {
414 LOG(WARNING) << "No output device detected."; 351 LOG(WARNING) << "No output device detected.";
415 return; 352 return;
416 } 353 }
417 354
418 uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 20; 355 uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 20;
419 AudioOutputStream* oas = audio_man->MakeAudioOutputStream( 356 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
420 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO, 357 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
421 AudioParameters::kAudioCDSampleRate / 2, 16, 358 AudioParameters::kAudioCDSampleRate / 2, 16,
422 samples_100_ms)); 359 samples_100_ms));
423 ASSERT_TRUE(NULL != oas); 360 ASSERT_TRUE(NULL != oas);
424 361
425 SineWaveAudioSource source(SineWaveAudioSource::FORMAT_16BIT_LINEAR_PCM, 1, 362 SineWaveAudioSource source(1, 200.0, AudioParameters::kAudioCDSampleRate/2);
426 200.0, AudioParameters::kAudioCDSampleRate/2);
427 363
428 EXPECT_TRUE(oas->Open()); 364 EXPECT_TRUE(oas->Open());
429 365
430 oas->SetVolume(0.5); 366 oas->SetVolume(0.5);
431 oas->Start(&source); 367 oas->Start(&source);
432 ::Sleep(500); 368 ::Sleep(500);
433 369
434 // Test that the volume is within the set limits. 370 // Test that the volume is within the set limits.
435 double volume = 0.0; 371 double volume = 0.0;
436 oas->GetVolume(&volume); 372 oas->GetVolume(&volume);
437 EXPECT_LT(volume, 0.51); 373 EXPECT_LT(volume, 0.51);
438 EXPECT_GT(volume, 0.49); 374 EXPECT_GT(volume, 0.49);
439 oas->Stop(); 375 oas->Stop();
440 oas->Close(); 376 oas->Close();
441 } 377 }
442 378
443 // Uses the PushSource to play a 2 seconds file clip for about 5 seconds. We 379 // Uses a restricted source to play ~2 seconds of audio for about 5 seconds. We
444 // try hard to generate situation where the two threads are accessing the 380 // try hard to generate situation where the two threads are accessing the
445 // object roughly at the same time. What you hear is a sweeping tone from 1KHz 381 // object roughly at the same time.
446 // to 2KHz with a bit of fade out at the end for one second. The file is two
447 // of these sweeping tones back to back.
448 TEST(WinAudioTest, PushSourceFile16KHz) { 382 TEST(WinAudioTest, PushSourceFile16KHz) {
449 scoped_ptr<AudioManager> audio_man(AudioManager::Create()); 383 scoped_ptr<AudioManager> audio_man(AudioManager::Create());
450 if (!audio_man->HasAudioOutputDevices()) { 384 if (!audio_man->HasAudioOutputDevices()) {
451 LOG(WARNING) << "No output device detected."; 385 LOG(WARNING) << "No output device detected.";
452 return; 386 return;
453 } 387 }
454 388
455 // Open sweep02_16b_mono_16KHz.raw which has no format. It contains the 389 static const int kSampleRate = 16000;
456 // raw 16 bit samples for a single channel in little-endian format. The 390 SineWaveAudioSource source(1, 200.0, kSampleRate);
457 // creation sample rate is 16KHz.
458 FilePath audio_file;
459 ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &audio_file));
460 audio_file = audio_file.Append(kAudioFile1_16b_m_16K);
461 // Map the entire file in memory.
462 ReadOnlyMappedFile file_reader(audio_file.value().c_str());
463 ASSERT_TRUE(file_reader.is_valid());
464
465 // Compute buffer size for 100ms of audio. 391 // Compute buffer size for 100ms of audio.
466 const uint32 kSamples100ms = (16000 / 1000) * 100; 392 const uint32 kSamples100ms = (kSampleRate / 1000) * 100;
467 const uint32 kSize100ms = kSamples100ms * 2; 393 // Restrict SineWaveAudioSource to 100ms of samples.
394 source.CapSamples(kSamples100ms);
468 395
469 AudioOutputStream* oas = audio_man->MakeAudioOutputStream( 396 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
470 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO, 397 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
471 16000, 16, kSamples100ms)); 398 kSampleRate, 16, kSamples100ms));
472 ASSERT_TRUE(NULL != oas); 399 ASSERT_TRUE(NULL != oas);
473 400
474 EXPECT_TRUE(oas->Open()); 401 EXPECT_TRUE(oas->Open());
475 402
476 uint32 offset = 0; 403 oas->SetVolume(1.0);
477 const uint32 kMaxStartOffset = file_reader.size() - kSize100ms; 404 oas->Start(&source);
DaleCurtis 2012/08/22 23:09:21 Test was broken before, it never started the AOS.
478 405
479 // We buffer and play at the same time, buffering happens every ~10ms and the 406 // We buffer and play at the same time, buffering happens every ~10ms and the
480 // consuming of the buffer happens every ~100ms. We do 100 buffers which 407 // consuming of the buffer happens every ~100ms. We do 100 buffers which
481 // effectively wrap around the file more than once. 408 // effectively wrap around the file more than once.
482 PushSource push_source;
483 for (uint32 ix = 0; ix != 100; ++ix) { 409 for (uint32 ix = 0; ix != 100; ++ix) {
484 push_source.Write(file_reader.GetChunkAt(offset), kSize100ms);
485 if (ix == 2) {
486 // For glitch free, start playing after some buffers are in.
487 oas->Start(&push_source);
488 }
489 ::Sleep(10); 410 ::Sleep(10);
490 offset += kSize100ms; 411 source.Reset();
491 if (offset > kMaxStartOffset)
492 offset = 0;
493 } 412 }
494 413
495 // Play a little bit more of the file. 414 // Play a little bit more of the file.
496 ::Sleep(500); 415 ::Sleep(500);
497 416
498 oas->Stop(); 417 oas->Stop();
499 oas->Close(); 418 oas->Close();
500 } 419 }
501 420
502 // This test is to make sure an AudioOutputStream can be started after it was 421 // This test is to make sure an AudioOutputStream can be started after it was
503 // stopped. You will here two .5 seconds wave signal separated by 0.5 seconds 422 // stopped. You will here two .5 seconds wave signal separated by 0.5 seconds
504 // of silence. 423 // of silence.
505 TEST(WinAudioTest, PCMWaveStreamPlayTwice200HzTone44Kss) { 424 TEST(WinAudioTest, PCMWaveStreamPlayTwice200HzTone44Kss) {
506 scoped_ptr<AudioManager> audio_man(AudioManager::Create()); 425 scoped_ptr<AudioManager> audio_man(AudioManager::Create());
507 if (!audio_man->HasAudioOutputDevices()) { 426 if (!audio_man->HasAudioOutputDevices()) {
508 LOG(WARNING) << "No output device detected."; 427 LOG(WARNING) << "No output device detected.";
509 return; 428 return;
510 } 429 }
511 430
512 uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 10; 431 uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 10;
513 AudioOutputStream* oas = audio_man->MakeAudioOutputStream( 432 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
514 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO, 433 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
515 AudioParameters::kAudioCDSampleRate, 16, samples_100_ms)); 434 AudioParameters::kAudioCDSampleRate, 16, samples_100_ms));
516 ASSERT_TRUE(NULL != oas); 435 ASSERT_TRUE(NULL != oas);
517 436
518 SineWaveAudioSource source(SineWaveAudioSource::FORMAT_16BIT_LINEAR_PCM, 1, 437 SineWaveAudioSource source(1, 200.0, AudioParameters::kAudioCDSampleRate);
519 200.0, AudioParameters::kAudioCDSampleRate);
520 EXPECT_TRUE(oas->Open()); 438 EXPECT_TRUE(oas->Open());
521 oas->SetVolume(1.0); 439 oas->SetVolume(1.0);
522 440
523 // Play the wave for .5 seconds. 441 // Play the wave for .5 seconds.
524 oas->Start(&source); 442 oas->Start(&source);
525 ::Sleep(500); 443 ::Sleep(500);
526 oas->Stop(); 444 oas->Stop();
527 445
528 // Sleep to give silence after stopping the AudioOutputStream. 446 // Sleep to give silence after stopping the AudioOutputStream.
529 ::Sleep(250); 447 ::Sleep(250);
(...skipping 24 matching lines...) Expand all
554 int sample_rate = static_cast<int>(media::GetAudioHardwareSampleRate()); 472 int sample_rate = static_cast<int>(media::GetAudioHardwareSampleRate());
555 uint32 samples_10_ms = sample_rate / 100; 473 uint32 samples_10_ms = sample_rate / 100;
556 int n = 1; 474 int n = 1;
557 (base::win::GetVersion() <= base::win::VERSION_XP) ? n = 5 : n = 1; 475 (base::win::GetVersion() <= base::win::VERSION_XP) ? n = 5 : n = 1;
558 AudioOutputStream* oas = audio_man->MakeAudioOutputStream( 476 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
559 AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY, 477 AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY,
560 CHANNEL_LAYOUT_MONO, sample_rate, 478 CHANNEL_LAYOUT_MONO, sample_rate,
561 16, n * samples_10_ms)); 479 16, n * samples_10_ms));
562 ASSERT_TRUE(NULL != oas); 480 ASSERT_TRUE(NULL != oas);
563 481
564 SineWaveAudioSource source(SineWaveAudioSource::FORMAT_16BIT_LINEAR_PCM, 1, 482 SineWaveAudioSource source(1, 200, sample_rate);
565 200.0, sample_rate);
566 483
567 bool opened = oas->Open(); 484 bool opened = oas->Open();
568 if (!opened) { 485 if (!opened) {
569 // It was not possible to open this audio device in mono. 486 // It was not possible to open this audio device in mono.
570 // No point in continuing the test so let's break here. 487 // No point in continuing the test so let's break here.
571 LOG(WARNING) << "Mono is not supported. Skipping test."; 488 LOG(WARNING) << "Mono is not supported. Skipping test.";
572 oas->Close(); 489 oas->Close();
573 return; 490 return;
574 } 491 }
575 oas->SetVolume(1.0); 492 oas->SetVolume(1.0);
(...skipping 25 matching lines...) Expand all
601 uint32 bytes_100_ms = samples_100_ms * 2; 518 uint32 bytes_100_ms = samples_100_ms * 2;
602 519
603 // Audio output stream has either a double or triple buffer scheme. 520 // Audio output stream has either a double or triple buffer scheme.
604 // We expect the amount of pending bytes will reaching up to 2 times of 521 // We expect the amount of pending bytes will reaching up to 2 times of
605 // |bytes_100_ms| depending on number of buffers used. 522 // |bytes_100_ms| depending on number of buffers used.
606 // From that it would decrease as we are playing the data but not providing 523 // From that it would decrease as we are playing the data but not providing
607 // new one. And then we will try to provide zero data so the amount of 524 // new one. And then we will try to provide zero data so the amount of
608 // pending bytes will go down and eventually read zero. 525 // pending bytes will go down and eventually read zero.
609 InSequence s; 526 InSequence s;
610 527
611 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, 528 EXPECT_CALL(source, OnMoreData(NotNull(),
612 Field(&AudioBuffersState::pending_bytes, 0))) 529 Field(&AudioBuffersState::pending_bytes, 0)))
613 .WillOnce(Return(bytes_100_ms)); 530 .WillOnce(Invoke(MockAudioSource::ClearData));
614 switch (NumberOfWaveOutBuffers()) { 531 switch (NumberOfWaveOutBuffers()) {
615 case 2: 532 case 2:
616 break; // Calls are the same as at end of 3-buffer scheme. 533 break; // Calls are the same as at end of 3-buffer scheme.
617 case 3: 534 case 3:
618 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, 535 EXPECT_CALL(source, OnMoreData(NotNull(),
619 Field(&AudioBuffersState::pending_bytes, 536 Field(&AudioBuffersState::pending_bytes,
620 bytes_100_ms))) 537 bytes_100_ms)))
621 .WillOnce(Return(bytes_100_ms)); 538 .WillOnce(Invoke(MockAudioSource::ClearData));
622 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, 539 EXPECT_CALL(source, OnMoreData(NotNull(),
623 Field(&AudioBuffersState::pending_bytes, 540 Field(&AudioBuffersState::pending_bytes,
624 2 * bytes_100_ms))) 541 2 * bytes_100_ms)))
625 .WillOnce(Return(bytes_100_ms)); 542 .WillOnce(Invoke(MockAudioSource::ClearData));
626 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, 543 EXPECT_CALL(source, OnMoreData(NotNull(),
627 Field(&AudioBuffersState::pending_bytes, 544 Field(&AudioBuffersState::pending_bytes,
628 2 * bytes_100_ms))) 545 2 * bytes_100_ms)))
629 .Times(AnyNumber()) 546 .Times(AnyNumber())
630 .WillRepeatedly(Return(0)); 547 .WillRepeatedly(Return(0));
548 break;
DaleCurtis 2012/08/22 23:09:21 Not sure how this ever passed without this break;
631 default: 549 default:
632 ASSERT_TRUE(false) << "Unexpected number of buffers"; 550 ASSERT_TRUE(false)
551 << "Unexpected number of buffers: " << NumberOfWaveOutBuffers();
633 } 552 }
634 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, 553 EXPECT_CALL(source, OnMoreData(NotNull(),
635 Field(&AudioBuffersState::pending_bytes, 554 Field(&AudioBuffersState::pending_bytes,
636 bytes_100_ms))) 555 bytes_100_ms)))
637 .Times(AnyNumber()) 556 .Times(AnyNumber())
638 .WillRepeatedly(Return(0)); 557 .WillRepeatedly(Return(0));
639 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, 558 EXPECT_CALL(source, OnMoreData(NotNull(),
640 Field(&AudioBuffersState::pending_bytes, 0))) 559 Field(&AudioBuffersState::pending_bytes, 0)))
641 .Times(AnyNumber()) 560 .Times(AnyNumber())
642 .WillRepeatedly(Return(0)); 561 .WillRepeatedly(Return(0));
643 562
644 oas->Start(&source); 563 oas->Start(&source);
645 ::Sleep(500); 564 ::Sleep(500);
646 oas->Stop(); 565 oas->Stop();
647 oas->Close(); 566 oas->Close();
648 } 567 }
649 568
650 // Simple source that uses a SyncSocket to retrieve the audio data 569 // Simple source that uses a SyncSocket to retrieve the audio data
651 // from a potentially remote thread. 570 // from a potentially remote thread.
652 class SyncSocketSource : public AudioOutputStream::AudioSourceCallback { 571 class SyncSocketSource : public AudioOutputStream::AudioSourceCallback {
653 public: 572 public:
654 explicit SyncSocketSource(base::SyncSocket* socket) 573 SyncSocketSource(base::SyncSocket* socket, const AudioParameters& params)
655 : socket_(socket) {} 574 : socket_(socket) {
656 575 // Setup AudioBus wrapping data we'll receive over the sync socket.
657 ~SyncSocketSource() { 576 data_size_ = AudioBus::CalculateMemorySize(params);
577 data_.reset(static_cast<float*>(
578 base::AlignedAlloc(data_size_, AudioBus::kChannelAlignment)));
579 audio_bus_ = AudioBus::WrapMemory(params, data_.get());
658 } 580 }
581 ~SyncSocketSource() {}
659 582
660 // AudioSourceCallback::OnMoreData implementation: 583 // AudioSourceCallback::OnMoreData implementation:
661 virtual uint32 OnMoreData(uint8* dest, 584 virtual int OnMoreData(AudioBus* audio_bus,
662 uint32 max_size, 585 AudioBuffersState buffers_state) {
663 AudioBuffersState buffers_state) {
664 socket_->Send(&buffers_state, sizeof(buffers_state)); 586 socket_->Send(&buffers_state, sizeof(buffers_state));
665 uint32 got = socket_->Receive(dest, max_size); 587 uint32 size = socket_->Receive(data_.get(), data_size_);
666 return got; 588 DCHECK_EQ(static_cast<size_t>(size) % sizeof(*audio_bus_->channel(0)), 0U);
589 audio_bus_->CopyTo(audio_bus);
590 return audio_bus_->frames();
667 } 591 }
668 // AudioSourceCallback::OnError implementation: 592 // AudioSourceCallback::OnError implementation:
669 virtual void OnError(AudioOutputStream* stream, int code) { 593 virtual void OnError(AudioOutputStream* stream, int code) {
670 } 594 }
671 595
672 private: 596 private:
673 base::SyncSocket* socket_; 597 base::SyncSocket* socket_;
598 int data_size_;
599 scoped_ptr_malloc<float, base::ScopedPtrAlignedFree> data_;
600 scoped_ptr<AudioBus> audio_bus_;
674 }; 601 };
675 602
676 struct SyncThreadContext { 603 struct SyncThreadContext {
677 base::SyncSocket* socket; 604 base::SyncSocket* socket;
678 int sample_rate; 605 int sample_rate;
606 int channels;
607 int frames;
679 double sine_freq; 608 double sine_freq;
680 uint32 packet_size_bytes; 609 uint32 packet_size_bytes;
681 }; 610 };
682 611
683 // This thread provides the data that the SyncSocketSource above needs 612 // This thread provides the data that the SyncSocketSource above needs
684 // using the other end of a SyncSocket. The protocol is as follows: 613 // using the other end of a SyncSocket. The protocol is as follows:
685 // 614 //
686 // SyncSocketSource ---send 4 bytes ------------> SyncSocketThread 615 // SyncSocketSource ---send 4 bytes ------------> SyncSocketThread
687 // <--- audio packet ---------- 616 // <--- audio packet ----------
688 // 617 //
689 DWORD __stdcall SyncSocketThread(void* context) { 618 DWORD __stdcall SyncSocketThread(void* context) {
690 SyncThreadContext& ctx = *(reinterpret_cast<SyncThreadContext*>(context)); 619 SyncThreadContext& ctx = *(reinterpret_cast<SyncThreadContext*>(context));
691 620
692 const int kTwoSecBytes = 621 // Setup AudioBus wrapping data we'll pass over the sync socket.
693 AudioParameters::kAudioCDSampleRate * 2 * sizeof(uint16); // NOLINT 622 scoped_ptr_malloc<float, base::ScopedPtrAlignedFree> data(static_cast<float*>(
694 uint8* buffer = new uint8[kTwoSecBytes]; 623 base::AlignedAlloc(ctx.packet_size_bytes, AudioBus::kChannelAlignment)));
695 SineWaveAudioSource sine(SineWaveAudioSource::FORMAT_16BIT_LINEAR_PCM, 624 scoped_ptr<AudioBus> audio_bus = AudioBus::WrapMemory(
696 1, ctx.sine_freq, ctx.sample_rate); 625 ctx.channels, ctx.frames, data.get());
697 sine.OnMoreData(buffer, kTwoSecBytes, AudioBuffersState()); 626
627 SineWaveAudioSource sine(1, ctx.sine_freq, ctx.sample_rate);
628 const int kTwoSecFrames = ctx.sample_rate * 2;
698 629
699 AudioBuffersState buffers_state; 630 AudioBuffersState buffers_state;
700 int times = 0; 631 int times = 0;
701 for (int ix = 0; ix < kTwoSecBytes; ix += ctx.packet_size_bytes) { 632 for (int ix = 0; ix < kTwoSecFrames; ix += ctx.frames) {
702 if (ctx.socket->Receive(&buffers_state, sizeof(buffers_state)) == 0) 633 if (ctx.socket->Receive(&buffers_state, sizeof(buffers_state)) == 0)
703 break; 634 break;
704 if ((times > 0) && (buffers_state.pending_bytes < 1000)) __debugbreak(); 635 if ((times > 0) && (buffers_state.pending_bytes < 1000)) __debugbreak();
705 ctx.socket->Send(&buffer[ix], ctx.packet_size_bytes); 636 sine.OnMoreData(audio_bus.get(), buffers_state);
637 ctx.socket->Send(data.get(), ctx.packet_size_bytes);
706 ++times; 638 ++times;
707 } 639 }
708 640
709 delete buffer;
710 return 0; 641 return 0;
711 } 642 }
712 643
713 // Test the basic operation of AudioOutputStream used with a SyncSocket. 644 // Test the basic operation of AudioOutputStream used with a SyncSocket.
714 // The emphasis is to verify that it is possible to feed data to the audio 645 // The emphasis is to verify that it is possible to feed data to the audio
715 // layer using a source based on SyncSocket. In a real situation we would 646 // layer using a source based on SyncSocket. In a real situation we would
716 // go for the low-latency version in combination with SyncSocket, but to keep 647 // go for the low-latency version in combination with SyncSocket, but to keep
717 // the test more simple, AUDIO_PCM_LINEAR is utilized instead. The main 648 // the test more simple, AUDIO_PCM_LINEAR is utilized instead. The main
718 // principle of the test still remains and we avoid the additional complexity 649 // principle of the test still remains and we avoid the additional complexity
719 // related to the two different audio-layers for AUDIO_PCM_LOW_LATENCY. 650 // related to the two different audio-layers for AUDIO_PCM_LOW_LATENCY.
720 // In this test you should hear a continuous 200Hz tone for 2 seconds. 651 // In this test you should hear a continuous 200Hz tone for 2 seconds.
721 TEST(WinAudioTest, SyncSocketBasic) { 652 TEST(WinAudioTest, SyncSocketBasic) {
722 scoped_ptr<AudioManager> audio_man(AudioManager::Create()); 653 scoped_ptr<AudioManager> audio_man(AudioManager::Create());
723 if (!audio_man->HasAudioOutputDevices()) { 654 if (!audio_man->HasAudioOutputDevices()) {
724 LOG(WARNING) << "No output device detected."; 655 LOG(WARNING) << "No output device detected.";
725 return; 656 return;
726 } 657 }
727 658
728 int sample_rate = AudioParameters::kAudioCDSampleRate; 659 static const int sample_rate = AudioParameters::kAudioCDSampleRate;
729 const uint32 kSamples20ms = sample_rate / 50; 660 static const uint32 kSamples20ms = sample_rate / 50;
730 AudioOutputStream* oas = audio_man->MakeAudioOutputStream( 661 AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
731 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, 662 CHANNEL_LAYOUT_MONO, sample_rate, 16, kSamples20ms);
732 CHANNEL_LAYOUT_MONO, sample_rate, 16, kSamples20ms)); 663
664
665 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(params);
733 ASSERT_TRUE(NULL != oas); 666 ASSERT_TRUE(NULL != oas);
734 667
735 ASSERT_TRUE(oas->Open()); 668 ASSERT_TRUE(oas->Open());
736 669
737 base::SyncSocket sockets[2]; 670 base::SyncSocket sockets[2];
738 ASSERT_TRUE(base::SyncSocket::CreatePair(&sockets[0], &sockets[1])); 671 ASSERT_TRUE(base::SyncSocket::CreatePair(&sockets[0], &sockets[1]));
739 672
740 SyncSocketSource source(&sockets[0]); 673 SyncSocketSource source(&sockets[0], params);
741 674
742 SyncThreadContext thread_context; 675 SyncThreadContext thread_context;
743 thread_context.sample_rate = sample_rate; 676 thread_context.sample_rate = params.sample_rate();
744 thread_context.sine_freq = 200.0; 677 thread_context.sine_freq = 200.0;
745 thread_context.packet_size_bytes = kSamples20ms * 2; 678 thread_context.packet_size_bytes = AudioBus::CalculateMemorySize(params);
679 thread_context.frames = params.frames_per_buffer();
680 thread_context.channels = params.channels();
746 thread_context.socket = &sockets[1]; 681 thread_context.socket = &sockets[1];
747 682
748 HANDLE thread = ::CreateThread(NULL, 0, SyncSocketThread, 683 HANDLE thread = ::CreateThread(NULL, 0, SyncSocketThread,
749 &thread_context, 0, NULL); 684 &thread_context, 0, NULL);
750 685
751 oas->Start(&source); 686 oas->Start(&source);
752 687
753 ::WaitForSingleObject(thread, INFINITE); 688 ::WaitForSingleObject(thread, INFINITE);
754 ::CloseHandle(thread); 689 ::CloseHandle(thread);
755 690
756 oas->Stop(); 691 oas->Stop();
757 oas->Close(); 692 oas->Close();
758 } 693 }
759 694
760 } // namespace media 695 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698