Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / media / audio / win / audio_output_win_unittest.cc
blob68f61eaf4d7395b3b91e4074e7f8fe150778e4be
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/audio_unittest_util.h"
18 #include "media/audio/mock_audio_source_callback.h"
19 #include "media/audio/simple_sources.h"
20 #include "testing/gmock/include/gmock/gmock.h"
21 #include "testing/gtest/include/gtest/gtest.h"
23 using ::testing::_;
24 using ::testing::AnyNumber;
25 using ::testing::DoAll;
26 using ::testing::Field;
27 using ::testing::Invoke;
28 using ::testing::InSequence;
29 using ::testing::NiceMock;
30 using ::testing::NotNull;
31 using ::testing::Return;
33 namespace media {
35 static int ClearData(AudioBus* audio_bus, uint32 total_bytes_delay) {
36 audio_bus->Zero();
37 return audio_bus->frames();
40 // This class allows to find out if the callbacks are occurring as
41 // expected and if any error has been reported.
42 class TestSourceBasic : public AudioOutputStream::AudioSourceCallback {
43 public:
44 TestSourceBasic()
45 : callback_count_(0),
46 had_error_(0) {
48 // AudioSourceCallback::OnMoreData implementation:
49 int OnMoreData(AudioBus* audio_bus, uint32 total_bytes_delay) override {
50 ++callback_count_;
51 // Touch the channel memory value to make sure memory is good.
52 audio_bus->Zero();
53 return audio_bus->frames();
55 // AudioSourceCallback::OnError implementation:
56 void OnError(AudioOutputStream* stream) override { ++had_error_; }
57 // Returns how many times OnMoreData() has been called.
58 int callback_count() const {
59 return callback_count_;
61 // Returns how many times the OnError callback was called.
62 int had_error() const {
63 return had_error_;
66 void set_error(bool error) {
67 had_error_ += error ? 1 : 0;
70 private:
71 int callback_count_;
72 int had_error_;
75 const int kMaxNumBuffers = 3;
76 // Specializes TestSourceBasic to simulate a source that blocks for some time
77 // in the OnMoreData callback.
78 class TestSourceLaggy : public TestSourceBasic {
79 public:
80 explicit TestSourceLaggy(int lag_in_ms)
81 : lag_in_ms_(lag_in_ms) {
83 int OnMoreData(AudioBus* audio_bus, uint32 total_bytes_delay) override {
84 // Call the base, which increments the callback_count_.
85 TestSourceBasic::OnMoreData(audio_bus, total_bytes_delay);
86 if (callback_count() > kMaxNumBuffers) {
87 ::Sleep(lag_in_ms_);
89 return audio_bus->frames();
91 private:
92 int lag_in_ms_;
95 // Helper class to memory map an entire file. The mapping is read-only. Don't
96 // use for gigabyte-sized files. Attempts to write to this memory generate
97 // memory access violations.
98 class ReadOnlyMappedFile {
99 public:
100 explicit ReadOnlyMappedFile(const wchar_t* file_name)
101 : fmap_(NULL), start_(NULL), size_(0) {
102 HANDLE file = ::CreateFileW(file_name, GENERIC_READ, FILE_SHARE_READ, NULL,
103 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
104 if (INVALID_HANDLE_VALUE == file)
105 return;
106 fmap_ = ::CreateFileMappingW(file, NULL, PAGE_READONLY, 0, 0, NULL);
107 ::CloseHandle(file);
108 if (!fmap_)
109 return;
110 start_ = reinterpret_cast<char*>(::MapViewOfFile(fmap_, FILE_MAP_READ,
111 0, 0, 0));
112 if (!start_)
113 return;
114 MEMORY_BASIC_INFORMATION mbi = {0};
115 ::VirtualQuery(start_, &mbi, sizeof(mbi));
116 size_ = mbi.RegionSize;
118 ~ReadOnlyMappedFile() {
119 if (start_) {
120 ::UnmapViewOfFile(start_);
121 ::CloseHandle(fmap_);
124 // Returns true if the file was successfully mapped.
125 bool is_valid() const {
126 return ((start_ > 0) && (size_ > 0));
128 // Returns the size in bytes of the mapped memory.
129 uint32 size() const {
130 return size_;
132 // Returns the memory backing the file.
133 const void* GetChunkAt(uint32 offset) {
134 return &start_[offset];
137 private:
138 HANDLE fmap_;
139 char* start_;
140 uint32 size_;
143 // ===========================================================================
144 // Validation of AudioManager::AUDIO_PCM_LINEAR
146 // NOTE:
147 // The tests can fail on the build bots when somebody connects to them via
148 // remote-desktop and the rdp client installs an audio device that fails to open
149 // at some point, possibly when the connection goes idle.
151 // Test that can it be created and closed.
152 TEST(WinAudioTest, PCMWaveStreamGetAndClose) {
153 scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
154 ABORT_AUDIO_TEST_IF_NOT(audio_man->HasAudioOutputDevices());
156 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
157 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_STEREO,
158 8000, 16, 256),
159 std::string());
160 ASSERT_TRUE(NULL != oas);
161 oas->Close();
164 // Test that can it be cannot be created with invalid parameters.
165 TEST(WinAudioTest, SanityOnMakeParams) {
166 scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
167 ABORT_AUDIO_TEST_IF_NOT(audio_man->HasAudioOutputDevices());
169 AudioParameters::Format fmt = AudioParameters::AUDIO_PCM_LINEAR;
170 EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
171 AudioParameters(fmt, CHANNEL_LAYOUT_UNSUPPORTED, 8000, 16, 256),
172 std::string()));
173 EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
174 AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 1024 * 1024, 16, 256),
175 std::string()));
176 EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
177 AudioParameters(fmt, CHANNEL_LAYOUT_STEREO, 8000, 80, 256),
178 std::string()));
179 EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
180 AudioParameters(fmt, CHANNEL_LAYOUT_UNSUPPORTED, 8000, 16, 256),
181 std::string()));
182 EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
183 AudioParameters(fmt, CHANNEL_LAYOUT_STEREO, -8000, 16, 256),
184 std::string()));
185 EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
186 AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 8000, 16, -100),
187 std::string()));
188 EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
189 AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 8000, 16, 0),
190 std::string()));
191 EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
192 AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 8000, 16,
193 media::limits::kMaxSamplesPerPacket + 1),
194 std::string()));
197 // Test that it can be opened and closed.
198 TEST(WinAudioTest, PCMWaveStreamOpenAndClose) {
199 scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
200 ABORT_AUDIO_TEST_IF_NOT(audio_man->HasAudioOutputDevices());
202 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
203 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_STEREO,
204 8000, 16, 256),
205 std::string());
206 ASSERT_TRUE(NULL != oas);
207 EXPECT_TRUE(oas->Open());
208 oas->Close();
211 // Test that it has a maximum packet size.
212 TEST(WinAudioTest, PCMWaveStreamOpenLimit) {
213 scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
214 ABORT_AUDIO_TEST_IF_NOT(audio_man->HasAudioOutputDevices());
216 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
217 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_STEREO,
218 8000, 16, 1024 * 1024 * 1024),
219 std::string());
220 EXPECT_TRUE(NULL == oas);
221 if (oas)
222 oas->Close();
225 // Test potential deadlock situation if the source is slow or blocks for some
226 // time. The actual EXPECT_GT are mostly meaningless and the real test is that
227 // the test completes in reasonable time.
228 TEST(WinAudioTest, PCMWaveSlowSource) {
229 scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
230 ABORT_AUDIO_TEST_IF_NOT(audio_man->HasAudioOutputDevices());
232 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
233 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
234 16000, 16, 256),
235 std::string());
236 ASSERT_TRUE(NULL != oas);
237 TestSourceLaggy test_laggy(90);
238 EXPECT_TRUE(oas->Open());
239 // The test parameters cause a callback every 32 ms and the source is
240 // sleeping for 90 ms, so it is guaranteed that we run out of ready buffers.
241 oas->Start(&test_laggy);
242 ::Sleep(500);
243 EXPECT_GT(test_laggy.callback_count(), 2);
244 EXPECT_FALSE(test_laggy.had_error());
245 oas->Stop();
246 ::Sleep(500);
247 oas->Close();
250 // Test another potential deadlock situation if the thread that calls Start()
251 // gets paused. This test is best when run over RDP with audio enabled. See
252 // bug 19276 for more details.
253 TEST(WinAudioTest, PCMWaveStreamPlaySlowLoop) {
254 scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
255 ABORT_AUDIO_TEST_IF_NOT(audio_man->HasAudioOutputDevices());
257 uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 10;
258 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
259 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
260 AudioParameters::kAudioCDSampleRate, 16, samples_100_ms),
261 std::string());
262 ASSERT_TRUE(NULL != oas);
264 SineWaveAudioSource source(1, 200.0, AudioParameters::kAudioCDSampleRate);
266 EXPECT_TRUE(oas->Open());
267 oas->SetVolume(1.0);
269 for (int ix = 0; ix != 5; ++ix) {
270 oas->Start(&source);
271 ::Sleep(10);
272 oas->Stop();
274 oas->Close();
278 // This test produces actual audio for .5 seconds on the default wave
279 // device at 44.1K s/sec. Parameters have been chosen carefully so you should
280 // not hear pops or noises while the sound is playing.
281 TEST(WinAudioTest, PCMWaveStreamPlay200HzTone44Kss) {
282 scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
283 if (!audio_man->HasAudioOutputDevices()) {
284 LOG(WARNING) << "No output device detected.";
285 return;
288 uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 10;
289 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
290 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
291 AudioParameters::kAudioCDSampleRate, 16, samples_100_ms),
292 std::string());
293 ASSERT_TRUE(NULL != oas);
295 SineWaveAudioSource source(1, 200.0, AudioParameters::kAudioCDSampleRate);
297 EXPECT_TRUE(oas->Open());
298 oas->SetVolume(1.0);
299 oas->Start(&source);
300 ::Sleep(500);
301 oas->Stop();
302 oas->Close();
305 // This test produces actual audio for for .5 seconds on the default wave
306 // device at 22K s/sec. Parameters have been chosen carefully so you should
307 // not hear pops or noises while the sound is playing. The audio also should
308 // sound with a lower volume than PCMWaveStreamPlay200HzTone44Kss.
309 TEST(WinAudioTest, PCMWaveStreamPlay200HzTone22Kss) {
310 scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
311 ABORT_AUDIO_TEST_IF_NOT(audio_man->HasAudioOutputDevices());
313 uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 20;
314 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
315 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
316 AudioParameters::kAudioCDSampleRate / 2, 16,
317 samples_100_ms),
318 std::string());
319 ASSERT_TRUE(NULL != oas);
321 SineWaveAudioSource source(1, 200.0, AudioParameters::kAudioCDSampleRate/2);
323 EXPECT_TRUE(oas->Open());
325 oas->SetVolume(0.5);
326 oas->Start(&source);
327 ::Sleep(500);
329 // Test that the volume is within the set limits.
330 double volume = 0.0;
331 oas->GetVolume(&volume);
332 EXPECT_LT(volume, 0.51);
333 EXPECT_GT(volume, 0.49);
334 oas->Stop();
335 oas->Close();
338 // Uses a restricted source to play ~2 seconds of audio for about 5 seconds. We
339 // try hard to generate situation where the two threads are accessing the
340 // object roughly at the same time.
341 TEST(WinAudioTest, PushSourceFile16KHz) {
342 scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
343 ABORT_AUDIO_TEST_IF_NOT(audio_man->HasAudioOutputDevices());
345 static const int kSampleRate = 16000;
346 SineWaveAudioSource source(1, 200.0, kSampleRate);
347 // Compute buffer size for 100ms of audio.
348 const uint32 kSamples100ms = (kSampleRate / 1000) * 100;
349 // Restrict SineWaveAudioSource to 100ms of samples.
350 source.CapSamples(kSamples100ms);
352 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
353 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
354 kSampleRate, 16, kSamples100ms),
355 std::string());
356 ASSERT_TRUE(NULL != oas);
358 EXPECT_TRUE(oas->Open());
360 oas->SetVolume(1.0);
361 oas->Start(&source);
363 // We buffer and play at the same time, buffering happens every ~10ms and the
364 // consuming of the buffer happens every ~100ms. We do 100 buffers which
365 // effectively wrap around the file more than once.
366 for (uint32 ix = 0; ix != 100; ++ix) {
367 ::Sleep(10);
368 source.Reset();
371 // Play a little bit more of the file.
372 ::Sleep(500);
374 oas->Stop();
375 oas->Close();
378 // This test is to make sure an AudioOutputStream can be started after it was
379 // stopped. You will here two .5 seconds wave signal separated by 0.5 seconds
380 // of silence.
381 TEST(WinAudioTest, PCMWaveStreamPlayTwice200HzTone44Kss) {
382 scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
383 ABORT_AUDIO_TEST_IF_NOT(audio_man->HasAudioOutputDevices());
385 uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 10;
386 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
387 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
388 AudioParameters::kAudioCDSampleRate, 16, samples_100_ms),
389 std::string());
390 ASSERT_TRUE(NULL != oas);
392 SineWaveAudioSource source(1, 200.0, AudioParameters::kAudioCDSampleRate);
393 EXPECT_TRUE(oas->Open());
394 oas->SetVolume(1.0);
396 // Play the wave for .5 seconds.
397 oas->Start(&source);
398 ::Sleep(500);
399 oas->Stop();
401 // Sleep to give silence after stopping the AudioOutputStream.
402 ::Sleep(250);
404 // Start again and play for .5 seconds.
405 oas->Start(&source);
406 ::Sleep(500);
407 oas->Stop();
409 oas->Close();
412 // With the low latency mode, WASAPI is utilized by default for Vista and
413 // higher and Wave is used for XP and lower. It is possible to utilize a
414 // smaller buffer size for WASAPI than for Wave.
415 TEST(WinAudioTest, PCMWaveStreamPlay200HzToneLowLatency) {
416 scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
417 ABORT_AUDIO_TEST_IF_NOT(audio_man->HasAudioOutputDevices());
419 // Use 10 ms buffer size for WASAPI and 50 ms buffer size for Wave.
420 // Take the existing native sample rate into account.
421 const AudioParameters params = audio_man->GetDefaultOutputStreamParameters();
422 int sample_rate = params.sample_rate();
423 uint32 samples_10_ms = sample_rate / 100;
424 int n = 1;
425 (base::win::GetVersion() <= base::win::VERSION_XP) ? n = 5 : n = 1;
426 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
427 AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY,
428 CHANNEL_LAYOUT_MONO, sample_rate,
429 16, n * samples_10_ms),
430 std::string());
431 ASSERT_TRUE(NULL != oas);
433 SineWaveAudioSource source(1, 200, sample_rate);
435 bool opened = oas->Open();
436 if (!opened) {
437 // It was not possible to open this audio device in mono.
438 // No point in continuing the test so let's break here.
439 LOG(WARNING) << "Mono is not supported. Skipping test.";
440 oas->Close();
441 return;
443 oas->SetVolume(1.0);
445 // Play the wave for .8 seconds.
446 oas->Start(&source);
447 ::Sleep(800);
448 oas->Stop();
449 oas->Close();
452 // Check that the pending bytes value is correct what the stream starts.
453 TEST(WinAudioTest, PCMWaveStreamPendingBytes) {
454 scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
455 ABORT_AUDIO_TEST_IF_NOT(audio_man->HasAudioOutputDevices());
457 uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 10;
458 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
459 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
460 AudioParameters::kAudioCDSampleRate, 16, samples_100_ms),
461 std::string());
462 ASSERT_TRUE(NULL != oas);
464 NiceMock<MockAudioSourceCallback> source;
465 EXPECT_TRUE(oas->Open());
467 uint32 bytes_100_ms = samples_100_ms * 2;
469 // Audio output stream has either a double or triple buffer scheme.
470 // We expect the amount of pending bytes will reaching up to 2 times of
471 // |bytes_100_ms| depending on number of buffers used.
472 // From that it would decrease as we are playing the data but not providing
473 // new one. And then we will try to provide zero data so the amount of
474 // pending bytes will go down and eventually read zero.
475 InSequence s;
477 EXPECT_CALL(source, OnMoreData(NotNull(), 0))
478 .WillOnce(Invoke(ClearData));
480 // Note: If AudioManagerWin::NumberOfWaveOutBuffers() ever changes, or if this
481 // test is run on Vista, these expectations will fail.
482 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms))
483 .WillOnce(Invoke(ClearData));
484 EXPECT_CALL(source, OnMoreData(NotNull(), 2 * bytes_100_ms))
485 .WillOnce(Invoke(ClearData));
486 EXPECT_CALL(source, OnMoreData(NotNull(), 2 * bytes_100_ms))
487 .Times(AnyNumber())
488 .WillRepeatedly(Return(0));
489 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms))
490 .Times(AnyNumber())
491 .WillRepeatedly(Return(0));
492 EXPECT_CALL(source, OnMoreData(NotNull(), 0))
493 .Times(AnyNumber())
494 .WillRepeatedly(Return(0));
496 oas->Start(&source);
497 ::Sleep(500);
498 oas->Stop();
499 oas->Close();
502 // Simple source that uses a SyncSocket to retrieve the audio data
503 // from a potentially remote thread.
504 class SyncSocketSource : public AudioOutputStream::AudioSourceCallback {
505 public:
506 SyncSocketSource(base::SyncSocket* socket, const AudioParameters& params)
507 : socket_(socket) {
508 // Setup AudioBus wrapping data we'll receive over the sync socket.
509 data_size_ = AudioBus::CalculateMemorySize(params);
510 data_.reset(static_cast<float*>(
511 base::AlignedAlloc(data_size_, AudioBus::kChannelAlignment)));
512 audio_bus_ = AudioBus::WrapMemory(params, data_.get());
514 ~SyncSocketSource() override {}
516 // AudioSourceCallback::OnMoreData implementation:
517 int OnMoreData(AudioBus* audio_bus, uint32 total_bytes_delay) override {
518 socket_->Send(&total_bytes_delay, sizeof(total_bytes_delay));
519 uint32 size = socket_->Receive(data_.get(), data_size_);
520 DCHECK_EQ(static_cast<size_t>(size) % sizeof(*audio_bus_->channel(0)), 0U);
521 audio_bus_->CopyTo(audio_bus);
522 return audio_bus_->frames();
525 // AudioSourceCallback::OnError implementation:
526 void OnError(AudioOutputStream* stream) override {}
528 private:
529 base::SyncSocket* socket_;
530 int data_size_;
531 scoped_ptr<float, base::AlignedFreeDeleter> data_;
532 scoped_ptr<AudioBus> audio_bus_;
535 struct SyncThreadContext {
536 base::SyncSocket* socket;
537 int sample_rate;
538 int channels;
539 int frames;
540 double sine_freq;
541 uint32 packet_size_bytes;
544 // This thread provides the data that the SyncSocketSource above needs
545 // using the other end of a SyncSocket. The protocol is as follows:
547 // SyncSocketSource ---send 4 bytes ------------> SyncSocketThread
548 // <--- audio packet ----------
550 DWORD __stdcall SyncSocketThread(void* context) {
551 SyncThreadContext& ctx = *(reinterpret_cast<SyncThreadContext*>(context));
553 // Setup AudioBus wrapping data we'll pass over the sync socket.
554 scoped_ptr<float, base::AlignedFreeDeleter> data(static_cast<float*>(
555 base::AlignedAlloc(ctx.packet_size_bytes, AudioBus::kChannelAlignment)));
556 scoped_ptr<AudioBus> audio_bus = AudioBus::WrapMemory(
557 ctx.channels, ctx.frames, data.get());
559 SineWaveAudioSource sine(1, ctx.sine_freq, ctx.sample_rate);
560 const int kTwoSecFrames = ctx.sample_rate * 2;
562 uint32 total_bytes_delay = 0;
563 int times = 0;
564 for (int ix = 0; ix < kTwoSecFrames; ix += ctx.frames) {
565 if (ctx.socket->Receive(&total_bytes_delay, sizeof(total_bytes_delay)) == 0)
566 break;
567 if ((times > 0) && (total_bytes_delay < 1000)) __debugbreak();
568 sine.OnMoreData(audio_bus.get(), total_bytes_delay);
569 ctx.socket->Send(data.get(), ctx.packet_size_bytes);
570 ++times;
573 return 0;
576 // Test the basic operation of AudioOutputStream used with a SyncSocket.
577 // The emphasis is to verify that it is possible to feed data to the audio
578 // layer using a source based on SyncSocket. In a real situation we would
579 // go for the low-latency version in combination with SyncSocket, but to keep
580 // the test more simple, AUDIO_PCM_LINEAR is utilized instead. The main
581 // principle of the test still remains and we avoid the additional complexity
582 // related to the two different audio-layers for AUDIO_PCM_LOW_LATENCY.
583 // In this test you should hear a continuous 200Hz tone for 2 seconds.
584 TEST(WinAudioTest, SyncSocketBasic) {
585 scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
586 ABORT_AUDIO_TEST_IF_NOT(audio_man->HasAudioOutputDevices());
588 static const int sample_rate = AudioParameters::kAudioCDSampleRate;
589 static const uint32 kSamples20ms = sample_rate / 50;
590 AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
591 CHANNEL_LAYOUT_MONO, sample_rate, 16, kSamples20ms);
594 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(params,
595 std::string());
596 ASSERT_TRUE(NULL != oas);
598 ASSERT_TRUE(oas->Open());
600 base::SyncSocket sockets[2];
601 ASSERT_TRUE(base::SyncSocket::CreatePair(&sockets[0], &sockets[1]));
603 SyncSocketSource source(&sockets[0], params);
605 SyncThreadContext thread_context;
606 thread_context.sample_rate = params.sample_rate();
607 thread_context.sine_freq = 200.0;
608 thread_context.packet_size_bytes = AudioBus::CalculateMemorySize(params);
609 thread_context.frames = params.frames_per_buffer();
610 thread_context.channels = params.channels();
611 thread_context.socket = &sockets[1];
613 HANDLE thread = ::CreateThread(NULL, 0, SyncSocketThread,
614 &thread_context, 0, NULL);
616 oas->Start(&source);
618 ::WaitForSingleObject(thread, INFINITE);
619 ::CloseHandle(thread);
621 oas->Stop();
622 oas->Close();
625 } // namespace media