Supervised user import: Listen for profile creation/deletion
[chromium-blink-merge.git] / media / audio / win / audio_output_win_unittest.cc
blob973df61895c08d12633d3f4108f9859400c51a2b
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 using base::win::ScopedCOMInitializer;
35 namespace media {
37 static const wchar_t kAudioFile1_16b_m_16K[]
38 = L"media\\test\\data\\sweep02_16b_mono_16KHz.raw";
40 static int ClearData(AudioBus* audio_bus, uint32 total_bytes_delay) {
41 audio_bus->Zero();
42 return audio_bus->frames();
45 // This class allows to find out if the callbacks are occurring as
46 // expected and if any error has been reported.
47 class TestSourceBasic : public AudioOutputStream::AudioSourceCallback {
48 public:
49 explicit TestSourceBasic()
50 : callback_count_(0),
51 had_error_(0) {
53 // AudioSourceCallback::OnMoreData implementation:
54 int OnMoreData(AudioBus* audio_bus, uint32 total_bytes_delay) override {
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 void OnError(AudioOutputStream* stream) override { ++had_error_; }
62 // Returns how many times OnMoreData() has been called.
63 int callback_count() const {
64 return callback_count_;
66 // Returns how many times the OnError callback was called.
67 int had_error() const {
68 return had_error_;
71 void set_error(bool error) {
72 had_error_ += error ? 1 : 0;
75 private:
76 int callback_count_;
77 int had_error_;
80 const int kMaxNumBuffers = 3;
81 // Specializes TestSourceBasic to simulate a source that blocks for some time
82 // in the OnMoreData callback.
83 class TestSourceLaggy : public TestSourceBasic {
84 public:
85 TestSourceLaggy(int laggy_after_buffer, int lag_in_ms)
86 : laggy_after_buffer_(laggy_after_buffer), lag_in_ms_(lag_in_ms) {
88 int OnMoreData(AudioBus* audio_bus, uint32 total_bytes_delay) override {
89 // Call the base, which increments the callback_count_.
90 TestSourceBasic::OnMoreData(audio_bus, total_bytes_delay);
91 if (callback_count() > kMaxNumBuffers) {
92 ::Sleep(lag_in_ms_);
94 return audio_bus->frames();
96 private:
97 int laggy_after_buffer_;
98 int lag_in_ms_;
101 // Helper class to memory map an entire file. The mapping is read-only. Don't
102 // use for gigabyte-sized files. Attempts to write to this memory generate
103 // memory access violations.
104 class ReadOnlyMappedFile {
105 public:
106 explicit ReadOnlyMappedFile(const wchar_t* file_name)
107 : fmap_(NULL), start_(NULL), size_(0) {
108 HANDLE file = ::CreateFileW(file_name, GENERIC_READ, FILE_SHARE_READ, NULL,
109 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
110 if (INVALID_HANDLE_VALUE == file)
111 return;
112 fmap_ = ::CreateFileMappingW(file, NULL, PAGE_READONLY, 0, 0, NULL);
113 ::CloseHandle(file);
114 if (!fmap_)
115 return;
116 start_ = reinterpret_cast<char*>(::MapViewOfFile(fmap_, FILE_MAP_READ,
117 0, 0, 0));
118 if (!start_)
119 return;
120 MEMORY_BASIC_INFORMATION mbi = {0};
121 ::VirtualQuery(start_, &mbi, sizeof(mbi));
122 size_ = mbi.RegionSize;
124 ~ReadOnlyMappedFile() {
125 if (start_) {
126 ::UnmapViewOfFile(start_);
127 ::CloseHandle(fmap_);
130 // Returns true if the file was successfully mapped.
131 bool is_valid() const {
132 return ((start_ > 0) && (size_ > 0));
134 // Returns the size in bytes of the mapped memory.
135 uint32 size() const {
136 return size_;
138 // Returns the memory backing the file.
139 const void* GetChunkAt(uint32 offset) {
140 return &start_[offset];
143 private:
144 HANDLE fmap_;
145 char* start_;
146 uint32 size_;
149 // ===========================================================================
150 // Validation of AudioManager::AUDIO_PCM_LINEAR
152 // NOTE:
153 // The tests can fail on the build bots when somebody connects to them via
154 // remote-desktop and the rdp client installs an audio device that fails to open
155 // at some point, possibly when the connection goes idle.
157 // Test that can it be created and closed.
158 TEST(WinAudioTest, PCMWaveStreamGetAndClose) {
159 scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
160 ABORT_AUDIO_TEST_IF_NOT(audio_man->HasAudioOutputDevices());
162 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
163 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_STEREO,
164 8000, 16, 256),
165 std::string());
166 ASSERT_TRUE(NULL != oas);
167 oas->Close();
170 // Test that can it be cannot be created with invalid parameters.
171 TEST(WinAudioTest, SanityOnMakeParams) {
172 scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
173 ABORT_AUDIO_TEST_IF_NOT(audio_man->HasAudioOutputDevices());
175 AudioParameters::Format fmt = AudioParameters::AUDIO_PCM_LINEAR;
176 EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
177 AudioParameters(fmt, CHANNEL_LAYOUT_UNSUPPORTED, 8000, 16, 256),
178 std::string()));
179 EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
180 AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 1024 * 1024, 16, 256),
181 std::string()));
182 EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
183 AudioParameters(fmt, CHANNEL_LAYOUT_STEREO, 8000, 80, 256),
184 std::string()));
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_STEREO, -8000, 16, 256),
190 std::string()));
191 EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
192 AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 8000, 16, -100),
193 std::string()));
194 EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
195 AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 8000, 16, 0),
196 std::string()));
197 EXPECT_TRUE(NULL == audio_man->MakeAudioOutputStream(
198 AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 8000, 16,
199 media::limits::kMaxSamplesPerPacket + 1),
200 std::string()));
203 // Test that it can be opened and closed.
204 TEST(WinAudioTest, PCMWaveStreamOpenAndClose) {
205 scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
206 ABORT_AUDIO_TEST_IF_NOT(audio_man->HasAudioOutputDevices());
208 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
209 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_STEREO,
210 8000, 16, 256),
211 std::string());
212 ASSERT_TRUE(NULL != oas);
213 EXPECT_TRUE(oas->Open());
214 oas->Close();
217 // Test that it has a maximum packet size.
218 TEST(WinAudioTest, PCMWaveStreamOpenLimit) {
219 scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
220 ABORT_AUDIO_TEST_IF_NOT(audio_man->HasAudioOutputDevices());
222 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
223 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_STEREO,
224 8000, 16, 1024 * 1024 * 1024),
225 std::string());
226 EXPECT_TRUE(NULL == oas);
227 if (oas)
228 oas->Close();
231 // Test potential deadlock situation if the source is slow or blocks for some
232 // time. The actual EXPECT_GT are mostly meaningless and the real test is that
233 // the test completes in reasonable time.
234 TEST(WinAudioTest, PCMWaveSlowSource) {
235 scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
236 ABORT_AUDIO_TEST_IF_NOT(audio_man->HasAudioOutputDevices());
238 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
239 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
240 16000, 16, 256),
241 std::string());
242 ASSERT_TRUE(NULL != oas);
243 TestSourceLaggy test_laggy(2, 90);
244 EXPECT_TRUE(oas->Open());
245 // The test parameters cause a callback every 32 ms and the source is
246 // sleeping for 90 ms, so it is guaranteed that we run out of ready buffers.
247 oas->Start(&test_laggy);
248 ::Sleep(500);
249 EXPECT_GT(test_laggy.callback_count(), 2);
250 EXPECT_FALSE(test_laggy.had_error());
251 oas->Stop();
252 ::Sleep(500);
253 oas->Close();
256 // Test another potential deadlock situation if the thread that calls Start()
257 // gets paused. This test is best when run over RDP with audio enabled. See
258 // bug 19276 for more details.
259 TEST(WinAudioTest, PCMWaveStreamPlaySlowLoop) {
260 scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
261 ABORT_AUDIO_TEST_IF_NOT(audio_man->HasAudioOutputDevices());
263 uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 10;
264 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
265 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
266 AudioParameters::kAudioCDSampleRate, 16, samples_100_ms),
267 std::string());
268 ASSERT_TRUE(NULL != oas);
270 SineWaveAudioSource source(1, 200.0, AudioParameters::kAudioCDSampleRate);
272 EXPECT_TRUE(oas->Open());
273 oas->SetVolume(1.0);
275 for (int ix = 0; ix != 5; ++ix) {
276 oas->Start(&source);
277 ::Sleep(10);
278 oas->Stop();
280 oas->Close();
284 // This test produces actual audio for .5 seconds on the default wave
285 // device at 44.1K s/sec. Parameters have been chosen carefully so you should
286 // not hear pops or noises while the sound is playing.
287 TEST(WinAudioTest, PCMWaveStreamPlay200HzTone44Kss) {
288 scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
289 if (!audio_man->HasAudioOutputDevices()) {
290 LOG(WARNING) << "No output device detected.";
291 return;
294 uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 10;
295 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
296 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
297 AudioParameters::kAudioCDSampleRate, 16, samples_100_ms),
298 std::string());
299 ASSERT_TRUE(NULL != oas);
301 SineWaveAudioSource source(1, 200.0, AudioParameters::kAudioCDSampleRate);
303 EXPECT_TRUE(oas->Open());
304 oas->SetVolume(1.0);
305 oas->Start(&source);
306 ::Sleep(500);
307 oas->Stop();
308 oas->Close();
311 // This test produces actual audio for for .5 seconds on the default wave
312 // device at 22K s/sec. Parameters have been chosen carefully so you should
313 // not hear pops or noises while the sound is playing. The audio also should
314 // sound with a lower volume than PCMWaveStreamPlay200HzTone44Kss.
315 TEST(WinAudioTest, PCMWaveStreamPlay200HzTone22Kss) {
316 scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
317 ABORT_AUDIO_TEST_IF_NOT(audio_man->HasAudioOutputDevices());
319 uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 20;
320 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
321 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
322 AudioParameters::kAudioCDSampleRate / 2, 16,
323 samples_100_ms),
324 std::string());
325 ASSERT_TRUE(NULL != oas);
327 SineWaveAudioSource source(1, 200.0, AudioParameters::kAudioCDSampleRate/2);
329 EXPECT_TRUE(oas->Open());
331 oas->SetVolume(0.5);
332 oas->Start(&source);
333 ::Sleep(500);
335 // Test that the volume is within the set limits.
336 double volume = 0.0;
337 oas->GetVolume(&volume);
338 EXPECT_LT(volume, 0.51);
339 EXPECT_GT(volume, 0.49);
340 oas->Stop();
341 oas->Close();
344 // Uses a restricted source to play ~2 seconds of audio for about 5 seconds. We
345 // try hard to generate situation where the two threads are accessing the
346 // object roughly at the same time.
347 TEST(WinAudioTest, PushSourceFile16KHz) {
348 scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
349 ABORT_AUDIO_TEST_IF_NOT(audio_man->HasAudioOutputDevices());
351 static const int kSampleRate = 16000;
352 SineWaveAudioSource source(1, 200.0, kSampleRate);
353 // Compute buffer size for 100ms of audio.
354 const uint32 kSamples100ms = (kSampleRate / 1000) * 100;
355 // Restrict SineWaveAudioSource to 100ms of samples.
356 source.CapSamples(kSamples100ms);
358 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
359 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
360 kSampleRate, 16, kSamples100ms),
361 std::string());
362 ASSERT_TRUE(NULL != oas);
364 EXPECT_TRUE(oas->Open());
366 oas->SetVolume(1.0);
367 oas->Start(&source);
369 // We buffer and play at the same time, buffering happens every ~10ms and the
370 // consuming of the buffer happens every ~100ms. We do 100 buffers which
371 // effectively wrap around the file more than once.
372 for (uint32 ix = 0; ix != 100; ++ix) {
373 ::Sleep(10);
374 source.Reset();
377 // Play a little bit more of the file.
378 ::Sleep(500);
380 oas->Stop();
381 oas->Close();
384 // This test is to make sure an AudioOutputStream can be started after it was
385 // stopped. You will here two .5 seconds wave signal separated by 0.5 seconds
386 // of silence.
387 TEST(WinAudioTest, PCMWaveStreamPlayTwice200HzTone44Kss) {
388 scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
389 ABORT_AUDIO_TEST_IF_NOT(audio_man->HasAudioOutputDevices());
391 uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 10;
392 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
393 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
394 AudioParameters::kAudioCDSampleRate, 16, samples_100_ms),
395 std::string());
396 ASSERT_TRUE(NULL != oas);
398 SineWaveAudioSource source(1, 200.0, AudioParameters::kAudioCDSampleRate);
399 EXPECT_TRUE(oas->Open());
400 oas->SetVolume(1.0);
402 // Play the wave for .5 seconds.
403 oas->Start(&source);
404 ::Sleep(500);
405 oas->Stop();
407 // Sleep to give silence after stopping the AudioOutputStream.
408 ::Sleep(250);
410 // Start again and play for .5 seconds.
411 oas->Start(&source);
412 ::Sleep(500);
413 oas->Stop();
415 oas->Close();
418 // With the low latency mode, WASAPI is utilized by default for Vista and
419 // higher and Wave is used for XP and lower. It is possible to utilize a
420 // smaller buffer size for WASAPI than for Wave.
421 TEST(WinAudioTest, PCMWaveStreamPlay200HzToneLowLatency) {
422 scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
423 ABORT_AUDIO_TEST_IF_NOT(audio_man->HasAudioOutputDevices());
425 // The WASAPI API requires a correct COM environment.
426 ScopedCOMInitializer com_init(ScopedCOMInitializer::kMTA);
428 // Use 10 ms buffer size for WASAPI and 50 ms buffer size for Wave.
429 // Take the existing native sample rate into account.
430 const AudioParameters params = audio_man->GetDefaultOutputStreamParameters();
431 int sample_rate = params.sample_rate();
432 uint32 samples_10_ms = sample_rate / 100;
433 int n = 1;
434 (base::win::GetVersion() <= base::win::VERSION_XP) ? n = 5 : n = 1;
435 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
436 AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY,
437 CHANNEL_LAYOUT_MONO, sample_rate,
438 16, n * samples_10_ms),
439 std::string());
440 ASSERT_TRUE(NULL != oas);
442 SineWaveAudioSource source(1, 200, sample_rate);
444 bool opened = oas->Open();
445 if (!opened) {
446 // It was not possible to open this audio device in mono.
447 // No point in continuing the test so let's break here.
448 LOG(WARNING) << "Mono is not supported. Skipping test.";
449 oas->Close();
450 return;
452 oas->SetVolume(1.0);
454 // Play the wave for .8 seconds.
455 oas->Start(&source);
456 ::Sleep(800);
457 oas->Stop();
458 oas->Close();
461 // Check that the pending bytes value is correct what the stream starts.
462 TEST(WinAudioTest, PCMWaveStreamPendingBytes) {
463 scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
464 ABORT_AUDIO_TEST_IF_NOT(audio_man->HasAudioOutputDevices());
466 uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 10;
467 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(
468 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
469 AudioParameters::kAudioCDSampleRate, 16, samples_100_ms),
470 std::string());
471 ASSERT_TRUE(NULL != oas);
473 NiceMock<MockAudioSourceCallback> source;
474 EXPECT_TRUE(oas->Open());
476 uint32 bytes_100_ms = samples_100_ms * 2;
478 // Audio output stream has either a double or triple buffer scheme.
479 // We expect the amount of pending bytes will reaching up to 2 times of
480 // |bytes_100_ms| depending on number of buffers used.
481 // From that it would decrease as we are playing the data but not providing
482 // new one. And then we will try to provide zero data so the amount of
483 // pending bytes will go down and eventually read zero.
484 InSequence s;
486 EXPECT_CALL(source, OnMoreData(NotNull(), 0))
487 .WillOnce(Invoke(ClearData));
489 // Note: If AudioManagerWin::NumberOfWaveOutBuffers() ever changes, or if this
490 // test is run on Vista, these expectations will fail.
491 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms))
492 .WillOnce(Invoke(ClearData));
493 EXPECT_CALL(source, OnMoreData(NotNull(), 2 * bytes_100_ms))
494 .WillOnce(Invoke(ClearData));
495 EXPECT_CALL(source, OnMoreData(NotNull(), 2 * bytes_100_ms))
496 .Times(AnyNumber())
497 .WillRepeatedly(Return(0));
498 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms))
499 .Times(AnyNumber())
500 .WillRepeatedly(Return(0));
501 EXPECT_CALL(source, OnMoreData(NotNull(), 0))
502 .Times(AnyNumber())
503 .WillRepeatedly(Return(0));
505 oas->Start(&source);
506 ::Sleep(500);
507 oas->Stop();
508 oas->Close();
511 // Simple source that uses a SyncSocket to retrieve the audio data
512 // from a potentially remote thread.
513 class SyncSocketSource : public AudioOutputStream::AudioSourceCallback {
514 public:
515 SyncSocketSource(base::SyncSocket* socket, const AudioParameters& params)
516 : socket_(socket) {
517 // Setup AudioBus wrapping data we'll receive over the sync socket.
518 data_size_ = AudioBus::CalculateMemorySize(params);
519 data_.reset(static_cast<float*>(
520 base::AlignedAlloc(data_size_, AudioBus::kChannelAlignment)));
521 audio_bus_ = AudioBus::WrapMemory(params, data_.get());
523 ~SyncSocketSource() override {}
525 // AudioSourceCallback::OnMoreData implementation:
526 int OnMoreData(AudioBus* audio_bus, uint32 total_bytes_delay) override {
527 socket_->Send(&total_bytes_delay, sizeof(total_bytes_delay));
528 uint32 size = socket_->Receive(data_.get(), data_size_);
529 DCHECK_EQ(static_cast<size_t>(size) % sizeof(*audio_bus_->channel(0)), 0U);
530 audio_bus_->CopyTo(audio_bus);
531 return audio_bus_->frames();
534 // AudioSourceCallback::OnError implementation:
535 void OnError(AudioOutputStream* stream) override {}
537 private:
538 base::SyncSocket* socket_;
539 int data_size_;
540 scoped_ptr<float, base::AlignedFreeDeleter> data_;
541 scoped_ptr<AudioBus> audio_bus_;
544 struct SyncThreadContext {
545 base::SyncSocket* socket;
546 int sample_rate;
547 int channels;
548 int frames;
549 double sine_freq;
550 uint32 packet_size_bytes;
553 // This thread provides the data that the SyncSocketSource above needs
554 // using the other end of a SyncSocket. The protocol is as follows:
556 // SyncSocketSource ---send 4 bytes ------------> SyncSocketThread
557 // <--- audio packet ----------
559 DWORD __stdcall SyncSocketThread(void* context) {
560 SyncThreadContext& ctx = *(reinterpret_cast<SyncThreadContext*>(context));
562 // Setup AudioBus wrapping data we'll pass over the sync socket.
563 scoped_ptr<float, base::AlignedFreeDeleter> data(static_cast<float*>(
564 base::AlignedAlloc(ctx.packet_size_bytes, AudioBus::kChannelAlignment)));
565 scoped_ptr<AudioBus> audio_bus = AudioBus::WrapMemory(
566 ctx.channels, ctx.frames, data.get());
568 SineWaveAudioSource sine(1, ctx.sine_freq, ctx.sample_rate);
569 const int kTwoSecFrames = ctx.sample_rate * 2;
571 uint32 total_bytes_delay = 0;
572 int times = 0;
573 for (int ix = 0; ix < kTwoSecFrames; ix += ctx.frames) {
574 if (ctx.socket->Receive(&total_bytes_delay, sizeof(total_bytes_delay)) == 0)
575 break;
576 if ((times > 0) && (total_bytes_delay < 1000)) __debugbreak();
577 sine.OnMoreData(audio_bus.get(), total_bytes_delay);
578 ctx.socket->Send(data.get(), ctx.packet_size_bytes);
579 ++times;
582 return 0;
585 // Test the basic operation of AudioOutputStream used with a SyncSocket.
586 // The emphasis is to verify that it is possible to feed data to the audio
587 // layer using a source based on SyncSocket. In a real situation we would
588 // go for the low-latency version in combination with SyncSocket, but to keep
589 // the test more simple, AUDIO_PCM_LINEAR is utilized instead. The main
590 // principle of the test still remains and we avoid the additional complexity
591 // related to the two different audio-layers for AUDIO_PCM_LOW_LATENCY.
592 // In this test you should hear a continuous 200Hz tone for 2 seconds.
593 TEST(WinAudioTest, SyncSocketBasic) {
594 scoped_ptr<AudioManager> audio_man(AudioManager::CreateForTesting());
595 ABORT_AUDIO_TEST_IF_NOT(audio_man->HasAudioOutputDevices());
597 static const int sample_rate = AudioParameters::kAudioCDSampleRate;
598 static const uint32 kSamples20ms = sample_rate / 50;
599 AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
600 CHANNEL_LAYOUT_MONO, sample_rate, 16, kSamples20ms);
603 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(params,
604 std::string());
605 ASSERT_TRUE(NULL != oas);
607 ASSERT_TRUE(oas->Open());
609 base::SyncSocket sockets[2];
610 ASSERT_TRUE(base::SyncSocket::CreatePair(&sockets[0], &sockets[1]));
612 SyncSocketSource source(&sockets[0], params);
614 SyncThreadContext thread_context;
615 thread_context.sample_rate = params.sample_rate();
616 thread_context.sine_freq = 200.0;
617 thread_context.packet_size_bytes = AudioBus::CalculateMemorySize(params);
618 thread_context.frames = params.frames_per_buffer();
619 thread_context.channels = params.channels();
620 thread_context.socket = &sockets[1];
622 HANDLE thread = ::CreateThread(NULL, 0, SyncSocketThread,
623 &thread_context, 0, NULL);
625 oas->Start(&source);
627 ::WaitForSingleObject(thread, INFINITE);
628 ::CloseHandle(thread);
630 oas->Stop();
631 oas->Close();
634 } // namespace media