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/path_service.h"
12 #include "base/sync_socket.h"
13 #include "base/win/scoped_com_initializer.h"
14 #include "base/win/windows_version.h"
15 #include "media/base/limits.h"
16 #include "media/audio/audio_io.h"
17 #include "media/audio/audio_manager.h"
18 #include "media/audio/simple_sources.h"
19 #include "testing/gmock/include/gmock/gmock.h"
20 #include "testing/gtest/include/gtest/gtest.h"
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
;
36 static const wchar_t kAudioFile1_16b_m_16K
[]
37 = L
"media\\test\\data\\sweep02_16b_mono_16KHz.raw";
39 // This class allows to find out if the callbacks are occurring as
40 // expected and if any error has been reported.
41 class TestSourceBasic
: public AudioOutputStream::AudioSourceCallback
{
43 explicit TestSourceBasic()
47 // AudioSourceCallback::OnMoreData implementation:
48 virtual int OnMoreData(AudioBus
* audio_bus
,
49 AudioBuffersState buffers_state
) {
51 // Touch the channel memory value to make sure memory is good.
53 return audio_bus
->frames();
55 virtual int OnMoreIOData(AudioBus
* source
,
57 AudioBuffersState buffers_state
) {
61 // AudioSourceCallback::OnError implementation:
62 virtual void OnError(AudioOutputStream
* stream
) {
65 // Returns how many times OnMoreData() has been called.
66 int callback_count() const {
67 return callback_count_
;
69 // Returns how many times the OnError callback was called.
70 int had_error() const {
74 void set_error(bool error
) {
75 had_error_
+= error
? 1 : 0;
83 const int kMaxNumBuffers
= 3;
84 // Specializes TestSourceBasic to simulate a source that blocks for some time
85 // in the OnMoreData callback.
86 class TestSourceLaggy
: public TestSourceBasic
{
88 TestSourceLaggy(int laggy_after_buffer
, int lag_in_ms
)
89 : laggy_after_buffer_(laggy_after_buffer
), lag_in_ms_(lag_in_ms
) {
91 virtual int OnMoreData(AudioBus
* audio_bus
,
92 AudioBuffersState buffers_state
) {
93 // Call the base, which increments the callback_count_.
94 TestSourceBasic::OnMoreData(audio_bus
, buffers_state
);
95 if (callback_count() > kMaxNumBuffers
) {
98 return audio_bus
->frames();
101 int laggy_after_buffer_
;
105 class MockAudioSource
: public AudioOutputStream::AudioSourceCallback
{
107 MOCK_METHOD2(OnMoreData
, int(AudioBus
* audio_bus
,
108 AudioBuffersState buffers_state
));
109 MOCK_METHOD3(OnMoreIOData
, int(AudioBus
* source
,
111 AudioBuffersState buffers_state
));
112 MOCK_METHOD1(OnError
, void(AudioOutputStream
* stream
));
114 static int ClearData(AudioBus
* audio_bus
, AudioBuffersState buffers_state
) {
116 return audio_bus
->frames();
120 // Helper class to memory map an entire file. The mapping is read-only. Don't
121 // use for gigabyte-sized files. Attempts to write to this memory generate
122 // memory access violations.
123 class ReadOnlyMappedFile
{
125 explicit ReadOnlyMappedFile(const wchar_t* file_name
)
126 : fmap_(NULL
), start_(NULL
), size_(0) {
127 HANDLE file
= ::CreateFileW(file_name
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
128 OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
129 if (INVALID_HANDLE_VALUE
== file
)
131 fmap_
= ::CreateFileMappingW(file
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
135 start_
= reinterpret_cast<char*>(::MapViewOfFile(fmap_
, FILE_MAP_READ
,
139 MEMORY_BASIC_INFORMATION mbi
= {0};
140 ::VirtualQuery(start_
, &mbi
, sizeof(mbi
));
141 size_
= mbi
.RegionSize
;
143 ~ReadOnlyMappedFile() {
145 ::UnmapViewOfFile(start_
);
146 ::CloseHandle(fmap_
);
149 // Returns true if the file was successfully mapped.
150 bool is_valid() const {
151 return ((start_
> 0) && (size_
> 0));
153 // Returns the size in bytes of the mapped memory.
154 uint32
size() const {
157 // Returns the memory backing the file.
158 const void* GetChunkAt(uint32 offset
) {
159 return &start_
[offset
];
168 // ===========================================================================
169 // Validation of AudioManager::AUDIO_PCM_LINEAR
172 // The tests can fail on the build bots when somebody connects to them via
173 // remote-desktop and the rdp client installs an audio device that fails to open
174 // at some point, possibly when the connection goes idle.
176 // Test that can it be created and closed.
177 TEST(WinAudioTest
, PCMWaveStreamGetAndClose
) {
178 scoped_ptr
<AudioManager
> audio_man(AudioManager::Create());
179 if (!audio_man
->HasAudioOutputDevices()) {
180 LOG(WARNING
) << "No output device detected.";
184 AudioOutputStream
* oas
= audio_man
->MakeAudioOutputStream(
185 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR
, CHANNEL_LAYOUT_STEREO
,
187 std::string(), std::string());
188 ASSERT_TRUE(NULL
!= oas
);
192 // Test that can it be cannot be created with invalid parameters.
193 TEST(WinAudioTest
, SanityOnMakeParams
) {
194 scoped_ptr
<AudioManager
> audio_man(AudioManager::Create());
195 if (!audio_man
->HasAudioOutputDevices()) {
196 LOG(WARNING
) << "No output device detected.";
200 AudioParameters::Format fmt
= AudioParameters::AUDIO_PCM_LINEAR
;
201 EXPECT_TRUE(NULL
== audio_man
->MakeAudioOutputStream(
202 AudioParameters(fmt
, CHANNEL_LAYOUT_UNSUPPORTED
, 8000, 16, 256),
203 std::string(), std::string()));
204 EXPECT_TRUE(NULL
== audio_man
->MakeAudioOutputStream(
205 AudioParameters(fmt
, CHANNEL_LAYOUT_MONO
, 1024 * 1024, 16, 256),
206 std::string(), std::string()));
207 EXPECT_TRUE(NULL
== audio_man
->MakeAudioOutputStream(
208 AudioParameters(fmt
, CHANNEL_LAYOUT_STEREO
, 8000, 80, 256),
209 std::string(), std::string()));
210 EXPECT_TRUE(NULL
== audio_man
->MakeAudioOutputStream(
211 AudioParameters(fmt
, CHANNEL_LAYOUT_UNSUPPORTED
, 8000, 16, 256),
212 std::string(), std::string()));
213 EXPECT_TRUE(NULL
== audio_man
->MakeAudioOutputStream(
214 AudioParameters(fmt
, CHANNEL_LAYOUT_STEREO
, -8000, 16, 256),
215 std::string(), std::string()));
216 EXPECT_TRUE(NULL
== audio_man
->MakeAudioOutputStream(
217 AudioParameters(fmt
, CHANNEL_LAYOUT_MONO
, 8000, 16, -100),
218 std::string(), std::string()));
219 EXPECT_TRUE(NULL
== audio_man
->MakeAudioOutputStream(
220 AudioParameters(fmt
, CHANNEL_LAYOUT_MONO
, 8000, 16, 0),
221 std::string(), std::string()));
222 EXPECT_TRUE(NULL
== audio_man
->MakeAudioOutputStream(
223 AudioParameters(fmt
, CHANNEL_LAYOUT_MONO
, 8000, 16,
224 media::limits::kMaxSamplesPerPacket
+ 1),
225 std::string(), std::string()));
228 // Test that it can be opened and closed.
229 TEST(WinAudioTest
, PCMWaveStreamOpenAndClose
) {
230 scoped_ptr
<AudioManager
> audio_man(AudioManager::Create());
231 if (!audio_man
->HasAudioOutputDevices()) {
232 LOG(WARNING
) << "No output device detected.";
236 AudioOutputStream
* oas
= audio_man
->MakeAudioOutputStream(
237 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR
, CHANNEL_LAYOUT_STEREO
,
239 std::string(), std::string());
240 ASSERT_TRUE(NULL
!= oas
);
241 EXPECT_TRUE(oas
->Open());
245 // Test that it has a maximum packet size.
246 TEST(WinAudioTest
, PCMWaveStreamOpenLimit
) {
247 scoped_ptr
<AudioManager
> audio_man(AudioManager::Create());
248 if (!audio_man
->HasAudioOutputDevices()) {
249 LOG(WARNING
) << "No output device detected.";
253 AudioOutputStream
* oas
= audio_man
->MakeAudioOutputStream(
254 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR
, CHANNEL_LAYOUT_STEREO
,
255 8000, 16, 1024 * 1024 * 1024),
256 std::string(), std::string());
257 EXPECT_TRUE(NULL
== oas
);
262 // Test potential deadlock situation if the source is slow or blocks for some
263 // time. The actual EXPECT_GT are mostly meaningless and the real test is that
264 // the test completes in reasonable time.
265 TEST(WinAudioTest
, PCMWaveSlowSource
) {
266 scoped_ptr
<AudioManager
> audio_man(AudioManager::Create());
267 if (!audio_man
->HasAudioOutputDevices()) {
268 LOG(WARNING
) << "No output device detected.";
272 AudioOutputStream
* oas
= audio_man
->MakeAudioOutputStream(
273 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR
, CHANNEL_LAYOUT_MONO
,
275 std::string(), std::string());
276 ASSERT_TRUE(NULL
!= oas
);
277 TestSourceLaggy
test_laggy(2, 90);
278 EXPECT_TRUE(oas
->Open());
279 // The test parameters cause a callback every 32 ms and the source is
280 // sleeping for 90 ms, so it is guaranteed that we run out of ready buffers.
281 oas
->Start(&test_laggy
);
283 EXPECT_GT(test_laggy
.callback_count(), 2);
284 EXPECT_FALSE(test_laggy
.had_error());
290 // Test another potential deadlock situation if the thread that calls Start()
291 // gets paused. This test is best when run over RDP with audio enabled. See
292 // bug 19276 for more details.
293 TEST(WinAudioTest
, PCMWaveStreamPlaySlowLoop
) {
294 scoped_ptr
<AudioManager
> audio_man(AudioManager::Create());
295 if (!audio_man
->HasAudioOutputDevices()) {
296 LOG(WARNING
) << "No output device detected.";
300 uint32 samples_100_ms
= AudioParameters::kAudioCDSampleRate
/ 10;
301 AudioOutputStream
* oas
= audio_man
->MakeAudioOutputStream(
302 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR
, CHANNEL_LAYOUT_MONO
,
303 AudioParameters::kAudioCDSampleRate
, 16, samples_100_ms
),
304 std::string(), std::string());
305 ASSERT_TRUE(NULL
!= oas
);
307 SineWaveAudioSource
source(1, 200.0, AudioParameters::kAudioCDSampleRate
);
309 EXPECT_TRUE(oas
->Open());
312 for (int ix
= 0; ix
!= 5; ++ix
) {
321 // This test produces actual audio for .5 seconds on the default wave
322 // device at 44.1K s/sec. Parameters have been chosen carefully so you should
323 // not hear pops or noises while the sound is playing.
324 TEST(WinAudioTest
, PCMWaveStreamPlay200HzTone44Kss
) {
325 scoped_ptr
<AudioManager
> audio_man(AudioManager::Create());
326 if (!audio_man
->HasAudioOutputDevices()) {
327 LOG(WARNING
) << "No output device detected.";
331 uint32 samples_100_ms
= AudioParameters::kAudioCDSampleRate
/ 10;
332 AudioOutputStream
* oas
= audio_man
->MakeAudioOutputStream(
333 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR
, CHANNEL_LAYOUT_MONO
,
334 AudioParameters::kAudioCDSampleRate
, 16, samples_100_ms
),
335 std::string(), std::string());
336 ASSERT_TRUE(NULL
!= oas
);
338 SineWaveAudioSource
source(1, 200.0, AudioParameters::kAudioCDSampleRate
);
340 EXPECT_TRUE(oas
->Open());
348 // This test produces actual audio for for .5 seconds on the default wave
349 // device at 22K s/sec. Parameters have been chosen carefully so you should
350 // not hear pops or noises while the sound is playing. The audio also should
351 // sound with a lower volume than PCMWaveStreamPlay200HzTone44Kss.
352 TEST(WinAudioTest
, PCMWaveStreamPlay200HzTone22Kss
) {
353 scoped_ptr
<AudioManager
> audio_man(AudioManager::Create());
354 if (!audio_man
->HasAudioOutputDevices()) {
355 LOG(WARNING
) << "No output device detected.";
359 uint32 samples_100_ms
= AudioParameters::kAudioCDSampleRate
/ 20;
360 AudioOutputStream
* oas
= audio_man
->MakeAudioOutputStream(
361 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR
, CHANNEL_LAYOUT_MONO
,
362 AudioParameters::kAudioCDSampleRate
/ 2, 16,
364 std::string(), std::string());
365 ASSERT_TRUE(NULL
!= oas
);
367 SineWaveAudioSource
source(1, 200.0, AudioParameters::kAudioCDSampleRate
/2);
369 EXPECT_TRUE(oas
->Open());
375 // Test that the volume is within the set limits.
377 oas
->GetVolume(&volume
);
378 EXPECT_LT(volume
, 0.51);
379 EXPECT_GT(volume
, 0.49);
384 // Uses a restricted source to play ~2 seconds of audio for about 5 seconds. We
385 // try hard to generate situation where the two threads are accessing the
386 // object roughly at the same time.
387 TEST(WinAudioTest
, PushSourceFile16KHz
) {
388 scoped_ptr
<AudioManager
> audio_man(AudioManager::Create());
389 if (!audio_man
->HasAudioOutputDevices()) {
390 LOG(WARNING
) << "No output device detected.";
394 static const int kSampleRate
= 16000;
395 SineWaveAudioSource
source(1, 200.0, kSampleRate
);
396 // Compute buffer size for 100ms of audio.
397 const uint32 kSamples100ms
= (kSampleRate
/ 1000) * 100;
398 // Restrict SineWaveAudioSource to 100ms of samples.
399 source
.CapSamples(kSamples100ms
);
401 AudioOutputStream
* oas
= audio_man
->MakeAudioOutputStream(
402 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR
, CHANNEL_LAYOUT_MONO
,
403 kSampleRate
, 16, kSamples100ms
),
404 std::string(), std::string());
405 ASSERT_TRUE(NULL
!= oas
);
407 EXPECT_TRUE(oas
->Open());
412 // We buffer and play at the same time, buffering happens every ~10ms and the
413 // consuming of the buffer happens every ~100ms. We do 100 buffers which
414 // effectively wrap around the file more than once.
415 for (uint32 ix
= 0; ix
!= 100; ++ix
) {
420 // Play a little bit more of the file.
427 // This test is to make sure an AudioOutputStream can be started after it was
428 // stopped. You will here two .5 seconds wave signal separated by 0.5 seconds
430 TEST(WinAudioTest
, PCMWaveStreamPlayTwice200HzTone44Kss
) {
431 scoped_ptr
<AudioManager
> audio_man(AudioManager::Create());
432 if (!audio_man
->HasAudioOutputDevices()) {
433 LOG(WARNING
) << "No output device detected.";
437 uint32 samples_100_ms
= AudioParameters::kAudioCDSampleRate
/ 10;
438 AudioOutputStream
* oas
= audio_man
->MakeAudioOutputStream(
439 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR
, CHANNEL_LAYOUT_MONO
,
440 AudioParameters::kAudioCDSampleRate
, 16, samples_100_ms
),
441 std::string(), std::string());
442 ASSERT_TRUE(NULL
!= oas
);
444 SineWaveAudioSource
source(1, 200.0, AudioParameters::kAudioCDSampleRate
);
445 EXPECT_TRUE(oas
->Open());
448 // Play the wave for .5 seconds.
453 // Sleep to give silence after stopping the AudioOutputStream.
456 // Start again and play for .5 seconds.
464 // With the low latency mode, WASAPI is utilized by default for Vista and
465 // higher and Wave is used for XP and lower. It is possible to utilize a
466 // smaller buffer size for WASAPI than for Wave.
467 TEST(WinAudioTest
, PCMWaveStreamPlay200HzToneLowLatency
) {
468 scoped_ptr
<AudioManager
> audio_man(AudioManager::Create());
469 if (!audio_man
->HasAudioOutputDevices()) {
470 LOG(WARNING
) << "No output device detected.";
474 // The WASAPI API requires a correct COM environment.
475 ScopedCOMInitializer
com_init(ScopedCOMInitializer::kMTA
);
477 // Use 10 ms buffer size for WASAPI and 50 ms buffer size for Wave.
478 // Take the existing native sample rate into account.
479 const AudioParameters params
= audio_man
->GetDefaultOutputStreamParameters();
480 int sample_rate
= params
.sample_rate();
481 uint32 samples_10_ms
= sample_rate
/ 100;
483 (base::win::GetVersion() <= base::win::VERSION_XP
) ? n
= 5 : n
= 1;
484 AudioOutputStream
* oas
= audio_man
->MakeAudioOutputStream(
485 AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY
,
486 CHANNEL_LAYOUT_MONO
, sample_rate
,
487 16, n
* samples_10_ms
),
488 std::string(), std::string());
489 ASSERT_TRUE(NULL
!= oas
);
491 SineWaveAudioSource
source(1, 200, sample_rate
);
493 bool opened
= oas
->Open();
495 // It was not possible to open this audio device in mono.
496 // No point in continuing the test so let's break here.
497 LOG(WARNING
) << "Mono is not supported. Skipping test.";
503 // Play the wave for .8 seconds.
510 // Check that the pending bytes value is correct what the stream starts.
511 TEST(WinAudioTest
, PCMWaveStreamPendingBytes
) {
512 scoped_ptr
<AudioManager
> audio_man(AudioManager::Create());
513 if (!audio_man
->HasAudioOutputDevices()) {
514 LOG(WARNING
) << "No output device detected.";
518 uint32 samples_100_ms
= AudioParameters::kAudioCDSampleRate
/ 10;
519 AudioOutputStream
* oas
= audio_man
->MakeAudioOutputStream(
520 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR
, CHANNEL_LAYOUT_MONO
,
521 AudioParameters::kAudioCDSampleRate
, 16, samples_100_ms
),
522 std::string(), std::string());
523 ASSERT_TRUE(NULL
!= oas
);
525 NiceMock
<MockAudioSource
> source
;
526 EXPECT_TRUE(oas
->Open());
528 uint32 bytes_100_ms
= samples_100_ms
* 2;
530 // Audio output stream has either a double or triple buffer scheme.
531 // We expect the amount of pending bytes will reaching up to 2 times of
532 // |bytes_100_ms| depending on number of buffers used.
533 // From that it would decrease as we are playing the data but not providing
534 // new one. And then we will try to provide zero data so the amount of
535 // pending bytes will go down and eventually read zero.
538 EXPECT_CALL(source
, OnMoreData(NotNull(),
539 Field(&AudioBuffersState::pending_bytes
, 0)))
540 .WillOnce(Invoke(MockAudioSource::ClearData
));
542 // Note: If AudioManagerWin::NumberOfWaveOutBuffers() ever changes, or if this
543 // test is run on Vista, these expectations will fail.
544 EXPECT_CALL(source
, OnMoreData(NotNull(),
545 Field(&AudioBuffersState::pending_bytes
,
547 .WillOnce(Invoke(MockAudioSource::ClearData
));
548 EXPECT_CALL(source
, OnMoreData(NotNull(),
549 Field(&AudioBuffersState::pending_bytes
,
551 .WillOnce(Invoke(MockAudioSource::ClearData
));
552 EXPECT_CALL(source
, OnMoreData(NotNull(),
553 Field(&AudioBuffersState::pending_bytes
,
556 .WillRepeatedly(Return(0));
557 EXPECT_CALL(source
, OnMoreData(NotNull(),
558 Field(&AudioBuffersState::pending_bytes
,
561 .WillRepeatedly(Return(0));
562 EXPECT_CALL(source
, OnMoreData(NotNull(),
563 Field(&AudioBuffersState::pending_bytes
, 0)))
565 .WillRepeatedly(Return(0));
573 // Simple source that uses a SyncSocket to retrieve the audio data
574 // from a potentially remote thread.
575 class SyncSocketSource
: public AudioOutputStream::AudioSourceCallback
{
577 SyncSocketSource(base::SyncSocket
* socket
, const AudioParameters
& params
)
579 // Setup AudioBus wrapping data we'll receive over the sync socket.
580 data_size_
= AudioBus::CalculateMemorySize(params
);
581 data_
.reset(static_cast<float*>(
582 base::AlignedAlloc(data_size_
, AudioBus::kChannelAlignment
)));
583 audio_bus_
= AudioBus::WrapMemory(params
, data_
.get());
585 ~SyncSocketSource() {}
587 // AudioSourceCallback::OnMoreData implementation:
588 virtual int OnMoreData(AudioBus
* audio_bus
,
589 AudioBuffersState buffers_state
) {
590 socket_
->Send(&buffers_state
, sizeof(buffers_state
));
591 uint32 size
= socket_
->Receive(data_
.get(), data_size_
);
592 DCHECK_EQ(static_cast<size_t>(size
) % sizeof(*audio_bus_
->channel(0)), 0U);
593 audio_bus_
->CopyTo(audio_bus
);
594 return audio_bus_
->frames();
596 virtual int OnMoreIOData(AudioBus
* source
,
598 AudioBuffersState buffers_state
) {
602 // AudioSourceCallback::OnError implementation:
603 virtual void OnError(AudioOutputStream
* stream
) {
607 base::SyncSocket
* socket_
;
609 scoped_ptr_malloc
<float, base::ScopedPtrAlignedFree
> data_
;
610 scoped_ptr
<AudioBus
> audio_bus_
;
613 struct SyncThreadContext
{
614 base::SyncSocket
* socket
;
619 uint32 packet_size_bytes
;
622 // This thread provides the data that the SyncSocketSource above needs
623 // using the other end of a SyncSocket. The protocol is as follows:
625 // SyncSocketSource ---send 4 bytes ------------> SyncSocketThread
626 // <--- audio packet ----------
628 DWORD __stdcall
SyncSocketThread(void* context
) {
629 SyncThreadContext
& ctx
= *(reinterpret_cast<SyncThreadContext
*>(context
));
631 // Setup AudioBus wrapping data we'll pass over the sync socket.
632 scoped_ptr_malloc
<float, base::ScopedPtrAlignedFree
> data(static_cast<float*>(
633 base::AlignedAlloc(ctx
.packet_size_bytes
, AudioBus::kChannelAlignment
)));
634 scoped_ptr
<AudioBus
> audio_bus
= AudioBus::WrapMemory(
635 ctx
.channels
, ctx
.frames
, data
.get());
637 SineWaveAudioSource
sine(1, ctx
.sine_freq
, ctx
.sample_rate
);
638 const int kTwoSecFrames
= ctx
.sample_rate
* 2;
640 AudioBuffersState buffers_state
;
642 for (int ix
= 0; ix
< kTwoSecFrames
; ix
+= ctx
.frames
) {
643 if (ctx
.socket
->Receive(&buffers_state
, sizeof(buffers_state
)) == 0)
645 if ((times
> 0) && (buffers_state
.pending_bytes
< 1000)) __debugbreak();
646 sine
.OnMoreData(audio_bus
.get(), buffers_state
);
647 ctx
.socket
->Send(data
.get(), ctx
.packet_size_bytes
);
654 // Test the basic operation of AudioOutputStream used with a SyncSocket.
655 // The emphasis is to verify that it is possible to feed data to the audio
656 // layer using a source based on SyncSocket. In a real situation we would
657 // go for the low-latency version in combination with SyncSocket, but to keep
658 // the test more simple, AUDIO_PCM_LINEAR is utilized instead. The main
659 // principle of the test still remains and we avoid the additional complexity
660 // related to the two different audio-layers for AUDIO_PCM_LOW_LATENCY.
661 // In this test you should hear a continuous 200Hz tone for 2 seconds.
662 TEST(WinAudioTest
, SyncSocketBasic
) {
663 scoped_ptr
<AudioManager
> audio_man(AudioManager::Create());
664 if (!audio_man
->HasAudioOutputDevices()) {
665 LOG(WARNING
) << "No output device detected.";
669 static const int sample_rate
= AudioParameters::kAudioCDSampleRate
;
670 static const uint32 kSamples20ms
= sample_rate
/ 50;
671 AudioParameters
params(AudioParameters::AUDIO_PCM_LINEAR
,
672 CHANNEL_LAYOUT_MONO
, sample_rate
, 16, kSamples20ms
);
675 AudioOutputStream
* oas
= audio_man
->MakeAudioOutputStream(params
,
676 std::string(), std::string());
677 ASSERT_TRUE(NULL
!= oas
);
679 ASSERT_TRUE(oas
->Open());
681 base::SyncSocket sockets
[2];
682 ASSERT_TRUE(base::SyncSocket::CreatePair(&sockets
[0], &sockets
[1]));
684 SyncSocketSource
source(&sockets
[0], params
);
686 SyncThreadContext thread_context
;
687 thread_context
.sample_rate
= params
.sample_rate();
688 thread_context
.sine_freq
= 200.0;
689 thread_context
.packet_size_bytes
= AudioBus::CalculateMemorySize(params
);
690 thread_context
.frames
= params
.frames_per_buffer();
691 thread_context
.channels
= params
.channels();
692 thread_context
.socket
= &sockets
[1];
694 HANDLE thread
= ::CreateThread(NULL
, 0, SyncSocketThread
,
695 &thread_context
, 0, NULL
);
699 ::WaitForSingleObject(thread
, INFINITE
);
700 ::CloseHandle(thread
);