Blink roll 25b6bd3a7a131ffe68d809546ad1a20707915cdc:3a503f41ae42e5b79cfcd2ff10e65afde...
[chromium-blink-merge.git] / media / audio / win / audio_output_win_unittest.cc
blob00e67507ceedbe43722949ce383a69b45f13bf95
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.
5 #include <windows.h>
6 #include <mmsystem.h>
8 #include "base/basictypes.h"
9 #include "base/base_paths.h"
10 #include "base/memory/aligned_memory.h"
11 #include "base/sync_socket.h"
12 #include "base/win/scoped_com_initializer.h"
13 #include "base/win/windows_version.h"
14 #include "media/base/limits.h"
15 #include "media/audio/audio_io.h"
16 #include "media/audio/audio_manager.h"
17 #include "media/audio/mock_audio_source_callback.h"
18 #include "media/audio/simple_sources.h"
19 #include "testing/gmock/include/gmock/gmock.h"
20 #include "testing/gtest/include/gtest/gtest.h"
22 using ::testing::_;
23 using ::testing::AnyNumber;
24 using ::testing::DoAll;
25 using ::testing::Field;
26 using ::testing::Invoke;
27 using ::testing::InSequence;
28 using ::testing::NiceMock;
29 using ::testing::NotNull;
30 using ::testing::Return;
32 using base::win::ScopedCOMInitializer;
34 namespace media {
36 static const wchar_t kAudioFile1_16b_m_16K[]
37 = L"media\\test\\data\\sweep02_16b_mono_16KHz.raw";
39 static int ClearData(AudioBus* audio_bus, uint32 total_bytes_delay) {
40 audio_bus->Zero();
41 return audio_bus->frames();
44 // This class allows to find out if the callbacks are occurring as
45 // expected and if any error has been reported.
46 class TestSourceBasic : public AudioOutputStream::AudioSourceCallback {
47 public:
48 explicit TestSourceBasic()
49 : callback_count_(0),
50 had_error_(0) {
52 // AudioSourceCallback::OnMoreData implementation:
53 virtual int OnMoreData(AudioBus* audio_bus,
54 uint32 total_bytes_delay) {
55 ++callback_count_;
56 // Touch the channel memory value to make sure memory is good.
57 audio_bus->Zero();
58 return audio_bus->frames();
60 // AudioSourceCallback::OnError implementation:
61 virtual void OnError(AudioOutputStream* stream) {
62 ++had_error_;
64 // Returns how many times OnMoreData() has been called.
65 int callback_count() const {
66 return callback_count_;
68 // Returns how many times the OnError callback was called.
69 int had_error() const {
70 return had_error_;
73 void set_error(bool error) {
74 had_error_ += error ? 1 : 0;
77 private:
78 int callback_count_;
79 int had_error_;
82 const int kMaxNumBuffers = 3;
83 // Specializes TestSourceBasic to simulate a source that blocks for some time
84 // in the OnMoreData callback.
85 class TestSourceLaggy : public TestSourceBasic {
86 public:
87 TestSourceLaggy(int laggy_after_buffer, int lag_in_ms)
88 : laggy_after_buffer_(laggy_after_buffer), lag_in_ms_(lag_in_ms) {
90 virtual int OnMoreData(AudioBus* audio_bus,
91 uint32 total_bytes_delay) {
92 // Call the base, which increments the callback_count_.
93 TestSourceBasic::OnMoreData(audio_bus, total_bytes_delay);
94 if (callback_count() > kMaxNumBuffers) {
95 ::Sleep(lag_in_ms_);
97 return audio_bus->frames();
99 private:
100 int laggy_after_buffer_;
101 int lag_in_ms_;
104 // Helper class to memory map an entire file. The mapping is read-only. Don't
105 // use for gigabyte-sized files. Attempts to write to this memory generate
106 // memory access violations.
107 class ReadOnlyMappedFile {
108 public:
109 explicit ReadOnlyMappedFile(const wchar_t* file_name)
110 : fmap_(NULL), start_(NULL), size_(0) {
111 HANDLE file = ::CreateFileW(file_name, GENERIC_READ, FILE_SHARE_READ, NULL,
112 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
113 if (INVALID_HANDLE_VALUE == file)
114 return;
115 fmap_ = ::CreateFileMappingW(file, NULL, PAGE_READONLY, 0, 0, NULL);
116 ::CloseHandle(file);
117 if (!fmap_)
118 return;
119 start_ = reinterpret_cast<char*>(::MapViewOfFile(fmap_, FILE_MAP_READ,
120 0, 0, 0));
121 if (!start_)
122 return;
123 MEMORY_BASIC_INFORMATION mbi = {0};
124 ::VirtualQuery(start_, &mbi, sizeof(mbi));
125 size_ = mbi.RegionSize;
127 ~ReadOnlyMappedFile() {
128 if (start_) {
129 ::UnmapViewOfFile(start_);
130 ::CloseHandle(fmap_);
133 // Returns true if the file was successfully mapped.
134 bool is_valid() const {
135 return ((start_ > 0) && (size_ > 0));
137 // Returns the size in bytes of the mapped memory.
138 uint32 size() const {
139 return size_;
141 // Returns the memory backing the file.
142 const void* GetChunkAt(uint32 offset) {
143 return &start_[offset];
146 private:
147 HANDLE fmap_;
148 char* start_;
149 uint32 size_;
152 // ===========================================================================
153 // Validation of AudioManager::AUDIO_PCM_LINEAR
155 // NOTE:
156 // The tests can fail on the build bots when somebody connects to them via
157 // remote-desktop and the rdp client installs an audio device that fails to open
158 // at some point, possibly when the connection goes idle.
160 // Test that can it be created and closed.
161 TEST(WinAudioTest, PCMWaveStreamGetAndClose) {
162 scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
163 if (!audio_man->HasAudioOutputDevices()) {
164 LOG(WARNING) << "No output device detected.";
165 return;
168 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
169 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_STEREO,
170 8000, 16, 256),
171 std::string());
172 ASSERT_TRUE(NULL != oas);
173 oas->Close();
176 // Test that can it be cannot be created with invalid parameters.
177 TEST(WinAudioTest, SanityOnMakeParams) {
178 scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
179 if (!audio_man->HasAudioOutputDevices()) {
180 LOG(WARNING) << "No output device detected.";
181 return;
184 AudioParameters::Format fmt = AudioParameters::AUDIO_PCM_LINEAR;
185 EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
186 AudioParameters(fmt, CHANNEL_LAYOUT_UNSUPPORTED, 8000, 16, 256),
187 std::string()));
188 EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
189 AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 1024 * 1024, 16, 256),
190 std::string()));
191 EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
192 AudioParameters(fmt, CHANNEL_LAYOUT_STEREO, 8000, 80, 256),
193 std::string()));
194 EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
195 AudioParameters(fmt, CHANNEL_LAYOUT_UNSUPPORTED, 8000, 16, 256),
196 std::string()));
197 EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
198 AudioParameters(fmt, CHANNEL_LAYOUT_STEREO, -8000, 16, 256),
199 std::string()));
200 EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
201 AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 8000, 16, -100),
202 std::string()));
203 EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
204 AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 8000, 16, 0),
205 std::string()));
206 EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
207 AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 8000, 16,
208 media::limits::kMaxSamplesPerPacket + 1),
209 std::string()));
212 // Test that it can be opened and closed.
213 TEST(WinAudioTest, PCMWaveStreamOpenAndClose) {
214 scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
215 if (!audio_man->HasAudioOutputDevices()) {
216 LOG(WARNING) << "No output device detected.";
217 return;
220 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
221 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_STEREO,
222 8000, 16, 256),
223 std::string());
224 ASSERT_TRUE(NULL != oas);
225 EXPECT_TRUE(oas->Open());
226 oas->Close();
229 // Test that it has a maximum packet size.
230 TEST(WinAudioTest, PCMWaveStreamOpenLimit) {
231 scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
232 if (!audio_man->HasAudioOutputDevices()) {
233 LOG(WARNING) << "No output device detected.";
234 return;
237 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
238 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_STEREO,
239 8000, 16, 1024 * 1024 * 1024),
240 std::string());
241 EXPECT_TRUE(NULL == oas);
242 if (oas)
243 oas->Close();
246 // Test potential deadlock situation if the source is slow or blocks for some
247 // time. The actual EXPECT_GT are mostly meaningless and the real test is that
248 // the test completes in reasonable time.
249 TEST(WinAudioTest, PCMWaveSlowSource) {
250 scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
251 if (!audio_man->HasAudioOutputDevices()) {
252 LOG(WARNING) << "No output device detected.";
253 return;
256 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
257 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
258 16000, 16, 256),
259 std::string());
260 ASSERT_TRUE(NULL != oas);
261 TestSourceLaggy test_laggy(2, 90);
262 EXPECT_TRUE(oas->Open());
263 // The test parameters cause a callback every 32 ms and the source is
264 // sleeping for 90 ms, so it is guaranteed that we run out of ready buffers.
265 oas->Start(&test_laggy);
266 ::Sleep(500);
267 EXPECT_GT(test_laggy.callback_count(), 2);
268 EXPECT_FALSE(test_laggy.had_error());
269 oas->Stop();
270 ::Sleep(500);
271 oas->Close();
274 // Test another potential deadlock situation if the thread that calls Start()
275 // gets paused. This test is best when run over RDP with audio enabled. See
276 // bug 19276 for more details.
277 TEST(WinAudioTest, PCMWaveStreamPlaySlowLoop) {
278 scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
279 if (!audio_man->HasAudioOutputDevices()) {
280 LOG(WARNING) << "No output device detected.";
281 return;
284 uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 10;
285 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
286 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
287 AudioParameters::kAudioCDSampleRate, 16, samples_100_ms),
288 std::string());
289 ASSERT_TRUE(NULL != oas);
291 SineWaveAudioSource source(1, 200.0, AudioParameters::kAudioCDSampleRate);
293 EXPECT_TRUE(oas->Open());
294 oas->SetVolume(1.0);
296 for (int ix = 0; ix != 5; ++ix) {
297 oas->Start(&source);
298 ::Sleep(10);
299 oas->Stop();
301 oas->Close();
305 // This test produces actual audio for .5 seconds on the default wave
306 // device at 44.1K s/sec. Parameters have been chosen carefully so you should
307 // not hear pops or noises while the sound is playing.
308 TEST(WinAudioTest, PCMWaveStreamPlay200HzTone44Kss) {
309 scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
310 if (!audio_man->HasAudioOutputDevices()) {
311 LOG(WARNING) << "No output device detected.";
312 return;
315 uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 10;
316 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
317 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
318 AudioParameters::kAudioCDSampleRate, 16, samples_100_ms),
319 std::string());
320 ASSERT_TRUE(NULL != oas);
322 SineWaveAudioSource source(1, 200.0, AudioParameters::kAudioCDSampleRate);
324 EXPECT_TRUE(oas->Open());
325 oas->SetVolume(1.0);
326 oas->Start(&source);
327 ::Sleep(500);
328 oas->Stop();
329 oas->Close();
332 // This test produces actual audio for for .5 seconds on the default wave
333 // device at 22K s/sec. Parameters have been chosen carefully so you should
334 // not hear pops or noises while the sound is playing. The audio also should
335 // sound with a lower volume than PCMWaveStreamPlay200HzTone44Kss.
336 TEST(WinAudioTest, PCMWaveStreamPlay200HzTone22Kss) {
337 scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
338 if (!audio_man->HasAudioOutputDevices()) {
339 LOG(WARNING) << "No output device detected.";
340 return;
343 uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 20;
344 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
345 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
346 AudioParameters::kAudioCDSampleRate / 2, 16,
347 samples_100_ms),
348 std::string());
349 ASSERT_TRUE(NULL != oas);
351 SineWaveAudioSource source(1, 200.0, AudioParameters::kAudioCDSampleRate/2);
353 EXPECT_TRUE(oas->Open());
355 oas->SetVolume(0.5);
356 oas->Start(&source);
357 ::Sleep(500);
359 // Test that the volume is within the set limits.
360 double volume = 0.0;
361 oas->GetVolume(&volume);
362 EXPECT_LT(volume, 0.51);
363 EXPECT_GT(volume, 0.49);
364 oas->Stop();
365 oas->Close();
368 // Uses a restricted source to play ~2 seconds of audio for about 5 seconds. We
369 // try hard to generate situation where the two threads are accessing the
370 // object roughly at the same time.
371 TEST(WinAudioTest, PushSourceFile16KHz) {
372 scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
373 if (!audio_man->HasAudioOutputDevices()) {
374 LOG(WARNING) << "No output device detected.";
375 return;
378 static const int kSampleRate = 16000;
379 SineWaveAudioSource source(1, 200.0, kSampleRate);
380 // Compute buffer size for 100ms of audio.
381 const uint32 kSamples100ms = (kSampleRate / 1000) * 100;
382 // Restrict SineWaveAudioSource to 100ms of samples.
383 source.CapSamples(kSamples100ms);
385 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
386 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
387 kSampleRate, 16, kSamples100ms),
388 std::string());
389 ASSERT_TRUE(NULL != oas);
391 EXPECT_TRUE(oas->Open());
393 oas->SetVolume(1.0);
394 oas->Start(&source);
396 // We buffer and play at the same time, buffering happens every ~10ms and the
397 // consuming of the buffer happens every ~100ms. We do 100 buffers which
398 // effectively wrap around the file more than once.
399 for (uint32 ix = 0; ix != 100; ++ix) {
400 ::Sleep(10);
401 source.Reset();
404 // Play a little bit more of the file.
405 ::Sleep(500);
407 oas->Stop();
408 oas->Close();
411 // This test is to make sure an AudioOutputStream can be started after it was
412 // stopped. You will here two .5 seconds wave signal separated by 0.5 seconds
413 // of silence.
414 TEST(WinAudioTest, PCMWaveStreamPlayTwice200HzTone44Kss) {
415 scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
416 if (!audio_man->HasAudioOutputDevices()) {
417 LOG(WARNING) << "No output device detected.";
418 return;
421 uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 10;
422 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
423 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
424 AudioParameters::kAudioCDSampleRate, 16, samples_100_ms),
425 std::string());
426 ASSERT_TRUE(NULL != oas);
428 SineWaveAudioSource source(1, 200.0, AudioParameters::kAudioCDSampleRate);
429 EXPECT_TRUE(oas->Open());
430 oas->SetVolume(1.0);
432 // Play the wave for .5 seconds.
433 oas->Start(&source);
434 ::Sleep(500);
435 oas->Stop();
437 // Sleep to give silence after stopping the AudioOutputStream.
438 ::Sleep(250);
440 // Start again and play for .5 seconds.
441 oas->Start(&source);
442 ::Sleep(500);
443 oas->Stop();
445 oas->Close();
448 // With the low latency mode, WASAPI is utilized by default for Vista and
449 // higher and Wave is used for XP and lower. It is possible to utilize a
450 // smaller buffer size for WASAPI than for Wave.
451 TEST(WinAudioTest, PCMWaveStreamPlay200HzToneLowLatency) {
452 scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
453 if (!audio_man->HasAudioOutputDevices()) {
454 LOG(WARNING) << "No output device detected.";
455 return;
458 // The WASAPI API requires a correct COM environment.
459 ScopedCOMInitializer com_init(ScopedCOMInitializer::kMTA);
461 // Use 10 ms buffer size for WASAPI and 50 ms buffer size for Wave.
462 // Take the existing native sample rate into account.
463 const AudioParameters params = audio_man->GetDefaultOutputStreamParameters();
464 int sample_rate = params.sample_rate();
465 uint32 samples_10_ms = sample_rate / 100;
466 int n = 1;
467 (base::win::GetVersion() <= base::win::VERSION_XP) ? n = 5 : n = 1;
468 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
469 AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY,
470 CHANNEL_LAYOUT_MONO, sample_rate,
471 16, n * samples_10_ms),
472 std::string());
473 ASSERT_TRUE(NULL != oas);
475 SineWaveAudioSource source(1, 200, sample_rate);
477 bool opened = oas->Open();
478 if (!opened) {
479 // It was not possible to open this audio device in mono.
480 // No point in continuing the test so let's break here.
481 LOG(WARNING) << "Mono is not supported. Skipping test.";
482 oas->Close();
483 return;
485 oas->SetVolume(1.0);
487 // Play the wave for .8 seconds.
488 oas->Start(&source);
489 ::Sleep(800);
490 oas->Stop();
491 oas->Close();
494 // Check that the pending bytes value is correct what the stream starts.
495 TEST(WinAudioTest, PCMWaveStreamPendingBytes) {
496 scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
497 if (!audio_man->HasAudioOutputDevices()) {
498 LOG(WARNING) << "No output device detected.";
499 return;
502 uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 10;
503 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
504 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
505 AudioParameters::kAudioCDSampleRate, 16, samples_100_ms),
506 std::string());
507 ASSERT_TRUE(NULL != oas);
509 NiceMock<MockAudioSourceCallback> source;
510 EXPECT_TRUE(oas->Open());
512 uint32 bytes_100_ms = samples_100_ms * 2;
514 // Audio output stream has either a double or triple buffer scheme.
515 // We expect the amount of pending bytes will reaching up to 2 times of
516 // |bytes_100_ms| depending on number of buffers used.
517 // From that it would decrease as we are playing the data but not providing
518 // new one. And then we will try to provide zero data so the amount of
519 // pending bytes will go down and eventually read zero.
520 InSequence s;
522 EXPECT_CALL(source, OnMoreData(NotNull(), 0))
523 .WillOnce(Invoke(ClearData));
525 // Note: If AudioManagerWin::NumberOfWaveOutBuffers() ever changes, or if this
526 // test is run on Vista, these expectations will fail.
527 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms))
528 .WillOnce(Invoke(ClearData));
529 EXPECT_CALL(source, OnMoreData(NotNull(), 2 * bytes_100_ms))
530 .WillOnce(Invoke(ClearData));
531 EXPECT_CALL(source, OnMoreData(NotNull(), 2 * bytes_100_ms))
532 .Times(AnyNumber())
533 .WillRepeatedly(Return(0));
534 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms))
535 .Times(AnyNumber())
536 .WillRepeatedly(Return(0));
537 EXPECT_CALL(source, OnMoreData(NotNull(), 0))
538 .Times(AnyNumber())
539 .WillRepeatedly(Return(0));
541 oas->Start(&source);
542 ::Sleep(500);
543 oas->Stop();
544 oas->Close();
547 // Simple source that uses a SyncSocket to retrieve the audio data
548 // from a potentially remote thread.
549 class SyncSocketSource : public AudioOutputStream::AudioSourceCallback {
550 public:
551 SyncSocketSource(base::SyncSocket* socket, const AudioParameters& params)
552 : socket_(socket) {
553 // Setup AudioBus wrapping data we'll receive over the sync socket.
554 data_size_ = AudioBus::CalculateMemorySize(params);
555 data_.reset(static_cast<float*>(
556 base::AlignedAlloc(data_size_, AudioBus::kChannelAlignment)));
557 audio_bus_ = AudioBus::WrapMemory(params, data_.get());
559 ~SyncSocketSource() {}
561 // AudioSourceCallback::OnMoreData implementation:
562 virtual int OnMoreData(AudioBus* audio_bus,
563 uint32 total_bytes_delay) {
564 socket_->Send(&total_bytes_delay, sizeof(total_bytes_delay));
565 uint32 size = socket_->Receive(data_.get(), data_size_);
566 DCHECK_EQ(static_cast<size_t>(size) % sizeof(*audio_bus_->channel(0)), 0U);
567 audio_bus_->CopyTo(audio_bus);
568 return audio_bus_->frames();
571 // AudioSourceCallback::OnError implementation:
572 virtual void OnError(AudioOutputStream* stream) {
575 private:
576 base::SyncSocket* socket_;
577 int data_size_;
578 scoped_ptr<float, base::AlignedFreeDeleter> data_;
579 scoped_ptr<AudioBus> audio_bus_;
582 struct SyncThreadContext {
583 base::SyncSocket* socket;
584 int sample_rate;
585 int channels;
586 int frames;
587 double sine_freq;
588 uint32 packet_size_bytes;
591 // This thread provides the data that the SyncSocketSource above needs
592 // using the other end of a SyncSocket. The protocol is as follows:
594 // SyncSocketSource ---send 4 bytes ------------> SyncSocketThread
595 // <--- audio packet ----------
597 DWORD __stdcall SyncSocketThread(void* context) {
598 SyncThreadContext& ctx = *(reinterpret_cast<SyncThreadContext*>(context));
600 // Setup AudioBus wrapping data we'll pass over the sync socket.
601 scoped_ptr<float, base::AlignedFreeDeleter> data(static_cast<float*>(
602 base::AlignedAlloc(ctx.packet_size_bytes, AudioBus::kChannelAlignment)));
603 scoped_ptr<AudioBus> audio_bus = AudioBus::WrapMemory(
604 ctx.channels, ctx.frames, data.get());
606 SineWaveAudioSource sine(1, ctx.sine_freq, ctx.sample_rate);
607 const int kTwoSecFrames = ctx.sample_rate * 2;
609 uint32 total_bytes_delay = 0;
610 int times = 0;
611 for (int ix = 0; ix < kTwoSecFrames; ix += ctx.frames) {
612 if (ctx.socket->Receive(&total_bytes_delay, sizeof(total_bytes_delay)) == 0)
613 break;
614 if ((times > 0) && (total_bytes_delay < 1000)) __debugbreak();
615 sine.OnMoreData(audio_bus.get(), total_bytes_delay);
616 ctx.socket->Send(data.get(), ctx.packet_size_bytes);
617 ++times;
620 return 0;
623 // Test the basic operation of AudioOutputStream used with a SyncSocket.
624 // The emphasis is to verify that it is possible to feed data to the audio
625 // layer using a source based on SyncSocket. In a real situation we would
626 // go for the low-latency version in combination with SyncSocket, but to keep
627 // the test more simple, AUDIO_PCM_LINEAR is utilized instead. The main
628 // principle of the test still remains and we avoid the additional complexity
629 // related to the two different audio-layers for AUDIO_PCM_LOW_LATENCY.
630 // In this test you should hear a continuous 200Hz tone for 2 seconds.
631 TEST(WinAudioTest, SyncSocketBasic) {
632 scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
633 if (!audio_man->HasAudioOutputDevices()) {
634 LOG(WARNING) << "No output device detected.";
635 return;
638 static const int sample_rate = AudioParameters::kAudioCDSampleRate;
639 static const uint32 kSamples20ms = sample_rate / 50;
640 AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
641 CHANNEL_LAYOUT_MONO, sample_rate, 16, kSamples20ms);
644 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(params,
645 std::string());
646 ASSERT_TRUE(NULL != oas);
648 ASSERT_TRUE(oas->Open());
650 base::SyncSocket sockets[2];
651 ASSERT_TRUE(base::SyncSocket::CreatePair(&sockets[0], &sockets[1]));
653 SyncSocketSource source(&sockets[0], params);
655 SyncThreadContext thread_context;
656 thread_context.sample_rate = params.sample_rate();
657 thread_context.sine_freq = 200.0;
658 thread_context.packet_size_bytes = AudioBus::CalculateMemorySize(params);
659 thread_context.frames = params.frames_per_buffer();
660 thread_context.channels = params.channels();
661 thread_context.socket = &sockets[1];
663 HANDLE thread = ::CreateThread(NULL, 0, SyncSocketThread,
664 &thread_context, 0, NULL);
666 oas->Start(&source);
668 ::WaitForSingleObject(thread, INFINITE);
669 ::CloseHandle(thread);
671 oas->Stop();
672 oas->Close();
675 } // namespace media