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.
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"
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
;
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
) {
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
{
49 explicit TestSourceBasic()
53 // AudioSourceCallback::OnMoreData implementation:
54 int OnMoreData(AudioBus
* audio_bus
, uint32 total_bytes_delay
) override
{
56 // Touch the channel memory value to make sure memory is good.
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 {
71 void set_error(bool error
) {
72 had_error_
+= error
? 1 : 0;
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
{
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
) {
94 return audio_bus
->frames();
97 int laggy_after_buffer_
;
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
{
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
)
112 fmap_
= ::CreateFileMappingW(file
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
116 start_
= reinterpret_cast<char*>(::MapViewOfFile(fmap_
, FILE_MAP_READ
,
120 MEMORY_BASIC_INFORMATION mbi
= {0};
121 ::VirtualQuery(start_
, &mbi
, sizeof(mbi
));
122 size_
= mbi
.RegionSize
;
124 ~ReadOnlyMappedFile() {
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 {
138 // Returns the memory backing the file.
139 const void* GetChunkAt(uint32 offset
) {
140 return &start_
[offset
];
149 // ===========================================================================
150 // Validation of AudioManager::AUDIO_PCM_LINEAR
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
,
166 ASSERT_TRUE(NULL
!= oas
);
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),
179 EXPECT_TRUE(NULL
== audio_man
->MakeAudioOutputStream(
180 AudioParameters(fmt
, CHANNEL_LAYOUT_MONO
, 1024 * 1024, 16, 256),
182 EXPECT_TRUE(NULL
== audio_man
->MakeAudioOutputStream(
183 AudioParameters(fmt
, CHANNEL_LAYOUT_STEREO
, 8000, 80, 256),
185 EXPECT_TRUE(NULL
== audio_man
->MakeAudioOutputStream(
186 AudioParameters(fmt
, CHANNEL_LAYOUT_UNSUPPORTED
, 8000, 16, 256),
188 EXPECT_TRUE(NULL
== audio_man
->MakeAudioOutputStream(
189 AudioParameters(fmt
, CHANNEL_LAYOUT_STEREO
, -8000, 16, 256),
191 EXPECT_TRUE(NULL
== audio_man
->MakeAudioOutputStream(
192 AudioParameters(fmt
, CHANNEL_LAYOUT_MONO
, 8000, 16, -100),
194 EXPECT_TRUE(NULL
== audio_man
->MakeAudioOutputStream(
195 AudioParameters(fmt
, CHANNEL_LAYOUT_MONO
, 8000, 16, 0),
197 EXPECT_TRUE(NULL
== audio_man
->MakeAudioOutputStream(
198 AudioParameters(fmt
, CHANNEL_LAYOUT_MONO
, 8000, 16,
199 media::limits::kMaxSamplesPerPacket
+ 1),
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
,
212 ASSERT_TRUE(NULL
!= oas
);
213 EXPECT_TRUE(oas
->Open());
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),
226 EXPECT_TRUE(NULL
== oas
);
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
,
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
);
249 EXPECT_GT(test_laggy
.callback_count(), 2);
250 EXPECT_FALSE(test_laggy
.had_error());
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
),
268 ASSERT_TRUE(NULL
!= oas
);
270 SineWaveAudioSource
source(1, 200.0, AudioParameters::kAudioCDSampleRate
);
272 EXPECT_TRUE(oas
->Open());
275 for (int ix
= 0; ix
!= 5; ++ix
) {
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.";
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
),
299 ASSERT_TRUE(NULL
!= oas
);
301 SineWaveAudioSource
source(1, 200.0, AudioParameters::kAudioCDSampleRate
);
303 EXPECT_TRUE(oas
->Open());
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,
325 ASSERT_TRUE(NULL
!= oas
);
327 SineWaveAudioSource
source(1, 200.0, AudioParameters::kAudioCDSampleRate
/2);
329 EXPECT_TRUE(oas
->Open());
335 // Test that the volume is within the set limits.
337 oas
->GetVolume(&volume
);
338 EXPECT_LT(volume
, 0.51);
339 EXPECT_GT(volume
, 0.49);
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
),
362 ASSERT_TRUE(NULL
!= oas
);
364 EXPECT_TRUE(oas
->Open());
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
) {
377 // Play a little bit more of the file.
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
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
),
396 ASSERT_TRUE(NULL
!= oas
);
398 SineWaveAudioSource
source(1, 200.0, AudioParameters::kAudioCDSampleRate
);
399 EXPECT_TRUE(oas
->Open());
402 // Play the wave for .5 seconds.
407 // Sleep to give silence after stopping the AudioOutputStream.
410 // Start again and play for .5 seconds.
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;
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
),
440 ASSERT_TRUE(NULL
!= oas
);
442 SineWaveAudioSource
source(1, 200, sample_rate
);
444 bool opened
= oas
->Open();
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.";
454 // Play the wave for .8 seconds.
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
),
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.
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
))
497 .WillRepeatedly(Return(0));
498 EXPECT_CALL(source
, OnMoreData(NotNull(), bytes_100_ms
))
500 .WillRepeatedly(Return(0));
501 EXPECT_CALL(source
, OnMoreData(NotNull(), 0))
503 .WillRepeatedly(Return(0));
511 // Simple source that uses a SyncSocket to retrieve the audio data
512 // from a potentially remote thread.
513 class SyncSocketSource
: public AudioOutputStream::AudioSourceCallback
{
515 SyncSocketSource(base::SyncSocket
* socket
, const AudioParameters
& params
)
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
{}
538 base::SyncSocket
* socket_
;
540 scoped_ptr
<float, base::AlignedFreeDeleter
> data_
;
541 scoped_ptr
<AudioBus
> audio_bus_
;
544 struct SyncThreadContext
{
545 base::SyncSocket
* socket
;
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;
573 for (int ix
= 0; ix
< kTwoSecFrames
; ix
+= ctx
.frames
) {
574 if (ctx
.socket
->Receive(&total_bytes_delay
, sizeof(total_bytes_delay
)) == 0)
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
);
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
,
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
);
627 ::WaitForSingleObject(thread
, INFINITE
);
628 ::CloseHandle(thread
);