| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <windows.h> | 5 #include <windows.h> |
| 6 #include <mmsystem.h> | 6 #include <mmsystem.h> |
| 7 | 7 |
| 8 #include "base/basictypes.h" | 8 #include "base/basictypes.h" |
| 9 #include "base/base_paths.h" | 9 #include "base/base_paths.h" |
| 10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
| 11 #include "base/memory/aligned_memory.h" |
| 11 #include "base/path_service.h" | 12 #include "base/path_service.h" |
| 12 #include "base/sync_socket.h" | 13 #include "base/sync_socket.h" |
| 13 #include "base/win/scoped_com_initializer.h" | 14 #include "base/win/scoped_com_initializer.h" |
| 14 #include "base/win/windows_version.h" | 15 #include "base/win/windows_version.h" |
| 15 #include "media/base/limits.h" | 16 #include "media/base/limits.h" |
| 16 #include "media/audio/audio_io.h" | 17 #include "media/audio/audio_io.h" |
| 17 #include "media/audio/audio_util.h" | 18 #include "media/audio/audio_util.h" |
| 18 #include "media/audio/audio_manager.h" | 19 #include "media/audio/audio_manager.h" |
| 19 #include "media/audio/simple_sources.h" | 20 #include "media/audio/simple_sources.h" |
| 20 #include "testing/gmock/include/gmock/gmock.h" | 21 #include "testing/gmock/include/gmock/gmock.h" |
| 21 #include "testing/gtest/include/gtest/gtest.h" | 22 #include "testing/gtest/include/gtest/gtest.h" |
| 22 | 23 |
| 23 using ::testing::_; | 24 using ::testing::_; |
| 24 using ::testing::AnyNumber; | 25 using ::testing::AnyNumber; |
| 25 using ::testing::DoAll; | 26 using ::testing::DoAll; |
| 26 using ::testing::Field; | 27 using ::testing::Field; |
| 28 using ::testing::Invoke; |
| 27 using ::testing::InSequence; | 29 using ::testing::InSequence; |
| 28 using ::testing::NiceMock; | 30 using ::testing::NiceMock; |
| 29 using ::testing::NotNull; | 31 using ::testing::NotNull; |
| 30 using ::testing::Return; | 32 using ::testing::Return; |
| 31 | 33 |
| 32 using base::win::ScopedCOMInitializer; | 34 using base::win::ScopedCOMInitializer; |
| 33 | 35 |
| 34 namespace media { | 36 namespace media { |
| 35 | 37 |
| 36 static const wchar_t kAudioFile1_16b_m_16K[] | 38 static const wchar_t kAudioFile1_16b_m_16K[] |
| 37 = L"media\\test\\data\\sweep02_16b_mono_16KHz.raw"; | 39 = L"media\\test\\data\\sweep02_16b_mono_16KHz.raw"; |
| 38 | 40 |
| 39 // This class allows to find out if the callbacks are occurring as | 41 // This class allows to find out if the callbacks are occurring as |
| 40 // expected and if any error has been reported. | 42 // expected and if any error has been reported. |
| 41 class TestSourceBasic : public AudioOutputStream::AudioSourceCallback { | 43 class TestSourceBasic : public AudioOutputStream::AudioSourceCallback { |
| 42 public: | 44 public: |
| 43 explicit TestSourceBasic() | 45 explicit TestSourceBasic() |
| 44 : callback_count_(0), | 46 : callback_count_(0), |
| 45 had_error_(0) { | 47 had_error_(0) { |
| 46 } | 48 } |
| 47 // AudioSourceCallback::OnMoreData implementation: | 49 // AudioSourceCallback::OnMoreData implementation: |
| 48 virtual uint32 OnMoreData(uint8* dest, | 50 virtual int OnMoreData(AudioBus* audio_bus, |
| 49 uint32 max_size, | 51 AudioBuffersState buffers_state) { |
| 50 AudioBuffersState buffers_state) { | |
| 51 ++callback_count_; | 52 ++callback_count_; |
| 52 // Touch the first byte to make sure memory is good. | 53 // Touch the channel memory value to make sure memory is good. |
| 53 if (max_size) | 54 audio_bus->Zero(); |
| 54 reinterpret_cast<char*>(dest)[0] = 1; | 55 return audio_bus->frames(); |
| 55 return max_size; | |
| 56 } | 56 } |
| 57 // AudioSourceCallback::OnError implementation: | 57 // AudioSourceCallback::OnError implementation: |
| 58 virtual void OnError(AudioOutputStream* stream, int code) { | 58 virtual void OnError(AudioOutputStream* stream, int code) { |
| 59 ++had_error_; | 59 ++had_error_; |
| 60 } | 60 } |
| 61 // Returns how many times OnMoreData() has been called. | 61 // Returns how many times OnMoreData() has been called. |
| 62 int callback_count() const { | 62 int callback_count() const { |
| 63 return callback_count_; | 63 return callback_count_; |
| 64 } | 64 } |
| 65 // Returns how many times the OnError callback was called. | 65 // Returns how many times the OnError callback was called. |
| 66 int had_error() const { | 66 int had_error() const { |
| 67 return had_error_; | 67 return had_error_; |
| 68 } | 68 } |
| 69 | 69 |
| 70 void set_error(bool error) { | 70 void set_error(bool error) { |
| 71 had_error_ += error ? 1 : 0; | 71 had_error_ += error ? 1 : 0; |
| 72 } | 72 } |
| 73 | 73 |
| 74 private: | 74 private: |
| 75 int callback_count_; | 75 int callback_count_; |
| 76 int had_error_; | 76 int had_error_; |
| 77 }; | 77 }; |
| 78 | 78 |
| 79 const int kMaxNumBuffers = 3; | 79 const int kMaxNumBuffers = 3; |
| 80 // Specializes TestSourceBasic to detect that the AudioStream is using | |
| 81 // triple buffering correctly. | |
| 82 class TestSourceTripleBuffer : public TestSourceBasic { | |
| 83 public: | |
| 84 TestSourceTripleBuffer() { | |
| 85 buffer_address_[0] = NULL; | |
| 86 buffer_address_[1] = NULL; | |
| 87 buffer_address_[2] = NULL; | |
| 88 } | |
| 89 // Override of TestSourceBasic::OnMoreData. | |
| 90 virtual uint32 OnMoreData(uint8* dest, | |
| 91 uint32 max_size, | |
| 92 AudioBuffersState buffers_state) { | |
| 93 // Call the base, which increments the callback_count_. | |
| 94 TestSourceBasic::OnMoreData(dest, max_size, buffers_state); | |
| 95 if (callback_count() % NumberOfWaveOutBuffers() == 2) { | |
| 96 set_error(!CompareExistingIfNotNULL(2, dest)); | |
| 97 } else if (callback_count() % NumberOfWaveOutBuffers() == 1) { | |
| 98 set_error(!CompareExistingIfNotNULL(1, dest)); | |
| 99 } else { | |
| 100 set_error(!CompareExistingIfNotNULL(0, dest)); | |
| 101 } | |
| 102 if (callback_count() > kMaxNumBuffers) { | |
| 103 set_error(buffer_address_[0] == buffer_address_[1]); | |
| 104 set_error(buffer_address_[1] == buffer_address_[2]); | |
| 105 } | |
| 106 return max_size; | |
| 107 } | |
| 108 | |
| 109 private: | |
| 110 bool CompareExistingIfNotNULL(uint32 index, void* address) { | |
| 111 void*& entry = buffer_address_[index]; | |
| 112 if (!entry) | |
| 113 entry = address; | |
| 114 return (entry == address); | |
| 115 } | |
| 116 | |
| 117 void* buffer_address_[kMaxNumBuffers]; | |
| 118 }; | |
| 119 | |
| 120 // Specializes TestSourceBasic to simulate a source that blocks for some time | 80 // Specializes TestSourceBasic to simulate a source that blocks for some time |
| 121 // in the OnMoreData callback. | 81 // in the OnMoreData callback. |
| 122 class TestSourceLaggy : public TestSourceBasic { | 82 class TestSourceLaggy : public TestSourceBasic { |
| 123 public: | 83 public: |
| 124 TestSourceLaggy(int laggy_after_buffer, int lag_in_ms) | 84 TestSourceLaggy(int laggy_after_buffer, int lag_in_ms) |
| 125 : laggy_after_buffer_(laggy_after_buffer), lag_in_ms_(lag_in_ms) { | 85 : laggy_after_buffer_(laggy_after_buffer), lag_in_ms_(lag_in_ms) { |
| 126 } | 86 } |
| 127 virtual uint32 OnMoreData(uint8* dest, | 87 virtual int OnMoreData(AudioBus* audio_bus, |
| 128 uint32 max_size, | 88 AudioBuffersState buffers_state) { |
| 129 AudioBuffersState buffers_state) { | |
| 130 // Call the base, which increments the callback_count_. | 89 // Call the base, which increments the callback_count_. |
| 131 TestSourceBasic::OnMoreData(dest, max_size, buffers_state); | 90 TestSourceBasic::OnMoreData(audio_bus, buffers_state); |
| 132 if (callback_count() > kMaxNumBuffers) { | 91 if (callback_count() > kMaxNumBuffers) { |
| 133 ::Sleep(lag_in_ms_); | 92 ::Sleep(lag_in_ms_); |
| 134 } | 93 } |
| 135 return max_size; | 94 return audio_bus->frames(); |
| 136 } | 95 } |
| 137 private: | 96 private: |
| 138 int laggy_after_buffer_; | 97 int laggy_after_buffer_; |
| 139 int lag_in_ms_; | 98 int lag_in_ms_; |
| 140 }; | 99 }; |
| 141 | 100 |
| 142 class MockAudioSource : public AudioOutputStream::AudioSourceCallback { | 101 class MockAudioSource : public AudioOutputStream::AudioSourceCallback { |
| 143 public: | 102 public: |
| 144 MOCK_METHOD3(OnMoreData, uint32(uint8* dest, | 103 MOCK_METHOD2(OnMoreData, int(AudioBus* audio_bus, |
| 145 uint32 max_size, | 104 AudioBuffersState buffers_state)); |
| 146 AudioBuffersState buffers_state)); | |
| 147 MOCK_METHOD2(OnError, void(AudioOutputStream* stream, int code)); | 105 MOCK_METHOD2(OnError, void(AudioOutputStream* stream, int code)); |
| 106 |
| 107 static int ClearData(AudioBus* audio_bus, AudioBuffersState buffers_state) { |
| 108 audio_bus->Zero(); |
| 109 return audio_bus->frames(); |
| 110 } |
| 148 }; | 111 }; |
| 149 | 112 |
| 150 // Helper class to memory map an entire file. The mapping is read-only. Don't | 113 // Helper class to memory map an entire file. The mapping is read-only. Don't |
| 151 // use for gigabyte-sized files. Attempts to write to this memory generate | 114 // use for gigabyte-sized files. Attempts to write to this memory generate |
| 152 // memory access violations. | 115 // memory access violations. |
| 153 class ReadOnlyMappedFile { | 116 class ReadOnlyMappedFile { |
| 154 public: | 117 public: |
| 155 explicit ReadOnlyMappedFile(const wchar_t* file_name) | 118 explicit ReadOnlyMappedFile(const wchar_t* file_name) |
| 156 : fmap_(NULL), start_(NULL), size_(0) { | 119 : fmap_(NULL), start_(NULL), size_(0) { |
| 157 HANDLE file = ::CreateFileW(file_name, GENERIC_READ, FILE_SHARE_READ, NULL, | 120 HANDLE file = ::CreateFileW(file_name, GENERIC_READ, FILE_SHARE_READ, NULL, |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 288 } | 251 } |
| 289 | 252 |
| 290 AudioOutputStream* oas = audio_man->MakeAudioOutputStream( | 253 AudioOutputStream* oas = audio_man->MakeAudioOutputStream( |
| 291 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_STEREO, | 254 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_STEREO, |
| 292 8000, 16, 1024 * 1024 * 1024)); | 255 8000, 16, 1024 * 1024 * 1024)); |
| 293 EXPECT_TRUE(NULL == oas); | 256 EXPECT_TRUE(NULL == oas); |
| 294 if (oas) | 257 if (oas) |
| 295 oas->Close(); | 258 oas->Close(); |
| 296 } | 259 } |
| 297 | 260 |
| 298 // Test that it uses the triple buffers correctly. Because it uses the actual | |
| 299 // audio device, you might hear a short pop noise for a short time. | |
| 300 TEST(WinAudioTest, PCMWaveStreamTripleBuffer) { | |
| 301 scoped_ptr<AudioManager> audio_man(AudioManager::Create()); | |
| 302 if (!audio_man->HasAudioOutputDevices()) { | |
| 303 LOG(WARNING) << "No output device detected."; | |
| 304 return; | |
| 305 } | |
| 306 | |
| 307 AudioOutputStream* oas = audio_man->MakeAudioOutputStream( | |
| 308 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO, | |
| 309 16000, 16, 256)); | |
| 310 ASSERT_TRUE(NULL != oas); | |
| 311 TestSourceTripleBuffer test_triple_buffer; | |
| 312 EXPECT_TRUE(oas->Open()); | |
| 313 oas->Start(&test_triple_buffer); | |
| 314 ::Sleep(300); | |
| 315 EXPECT_GT(test_triple_buffer.callback_count(), kMaxNumBuffers); | |
| 316 EXPECT_FALSE(test_triple_buffer.had_error()); | |
| 317 oas->Stop(); | |
| 318 ::Sleep(500); | |
| 319 oas->Close(); | |
| 320 } | |
| 321 | |
| 322 // Test potential deadlock situation if the source is slow or blocks for some | 261 // Test potential deadlock situation if the source is slow or blocks for some |
| 323 // time. The actual EXPECT_GT are mostly meaningless and the real test is that | 262 // time. The actual EXPECT_GT are mostly meaningless and the real test is that |
| 324 // the test completes in reasonable time. | 263 // the test completes in reasonable time. |
| 325 TEST(WinAudioTest, PCMWaveSlowSource) { | 264 TEST(WinAudioTest, PCMWaveSlowSource) { |
| 326 scoped_ptr<AudioManager> audio_man(AudioManager::Create()); | 265 scoped_ptr<AudioManager> audio_man(AudioManager::Create()); |
| 327 if (!audio_man->HasAudioOutputDevices()) { | 266 if (!audio_man->HasAudioOutputDevices()) { |
| 328 LOG(WARNING) << "No output device detected."; | 267 LOG(WARNING) << "No output device detected."; |
| 329 return; | 268 return; |
| 330 } | 269 } |
| 331 | 270 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 355 LOG(WARNING) << "No output device detected."; | 294 LOG(WARNING) << "No output device detected."; |
| 356 return; | 295 return; |
| 357 } | 296 } |
| 358 | 297 |
| 359 uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 10; | 298 uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 10; |
| 360 AudioOutputStream* oas = audio_man->MakeAudioOutputStream( | 299 AudioOutputStream* oas = audio_man->MakeAudioOutputStream( |
| 361 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO, | 300 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO, |
| 362 AudioParameters::kAudioCDSampleRate, 16, samples_100_ms)); | 301 AudioParameters::kAudioCDSampleRate, 16, samples_100_ms)); |
| 363 ASSERT_TRUE(NULL != oas); | 302 ASSERT_TRUE(NULL != oas); |
| 364 | 303 |
| 365 SineWaveAudioSource source(SineWaveAudioSource::FORMAT_16BIT_LINEAR_PCM, 1, | 304 SineWaveAudioSource source(1, 200.0, AudioParameters::kAudioCDSampleRate); |
| 366 200.0, AudioParameters::kAudioCDSampleRate); | |
| 367 | 305 |
| 368 EXPECT_TRUE(oas->Open()); | 306 EXPECT_TRUE(oas->Open()); |
| 369 oas->SetVolume(1.0); | 307 oas->SetVolume(1.0); |
| 370 | 308 |
| 371 for (int ix = 0; ix != 5; ++ix) { | 309 for (int ix = 0; ix != 5; ++ix) { |
| 372 oas->Start(&source); | 310 oas->Start(&source); |
| 373 ::Sleep(10); | 311 ::Sleep(10); |
| 374 oas->Stop(); | 312 oas->Stop(); |
| 375 } | 313 } |
| 376 oas->Close(); | 314 oas->Close(); |
| 377 } | 315 } |
| 378 | 316 |
| 379 | 317 |
| 380 // This test produces actual audio for .5 seconds on the default wave | 318 // This test produces actual audio for .5 seconds on the default wave |
| 381 // device at 44.1K s/sec. Parameters have been chosen carefully so you should | 319 // device at 44.1K s/sec. Parameters have been chosen carefully so you should |
| 382 // not hear pops or noises while the sound is playing. | 320 // not hear pops or noises while the sound is playing. |
| 383 TEST(WinAudioTest, PCMWaveStreamPlay200HzTone44Kss) { | 321 TEST(WinAudioTest, PCMWaveStreamPlay200HzTone44Kss) { |
| 384 scoped_ptr<AudioManager> audio_man(AudioManager::Create()); | 322 scoped_ptr<AudioManager> audio_man(AudioManager::Create()); |
| 385 if (!audio_man->HasAudioOutputDevices()) { | 323 if (!audio_man->HasAudioOutputDevices()) { |
| 386 LOG(WARNING) << "No output device detected."; | 324 LOG(WARNING) << "No output device detected."; |
| 387 return; | 325 return; |
| 388 } | 326 } |
| 389 | 327 |
| 390 uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 10; | 328 uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 10; |
| 391 AudioOutputStream* oas = audio_man->MakeAudioOutputStream( | 329 AudioOutputStream* oas = audio_man->MakeAudioOutputStream( |
| 392 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO, | 330 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO, |
| 393 AudioParameters::kAudioCDSampleRate, 16, samples_100_ms)); | 331 AudioParameters::kAudioCDSampleRate, 16, samples_100_ms)); |
| 394 ASSERT_TRUE(NULL != oas); | 332 ASSERT_TRUE(NULL != oas); |
| 395 | 333 |
| 396 SineWaveAudioSource source(SineWaveAudioSource::FORMAT_16BIT_LINEAR_PCM, 1, | 334 SineWaveAudioSource source(1, 200.0, AudioParameters::kAudioCDSampleRate); |
| 397 200.0, AudioParameters::kAudioCDSampleRate); | |
| 398 | 335 |
| 399 EXPECT_TRUE(oas->Open()); | 336 EXPECT_TRUE(oas->Open()); |
| 400 oas->SetVolume(1.0); | 337 oas->SetVolume(1.0); |
| 401 oas->Start(&source); | 338 oas->Start(&source); |
| 402 ::Sleep(500); | 339 ::Sleep(500); |
| 403 oas->Stop(); | 340 oas->Stop(); |
| 404 oas->Close(); | 341 oas->Close(); |
| 405 } | 342 } |
| 406 | 343 |
| 407 // This test produces actual audio for for .5 seconds on the default wave | 344 // This test produces actual audio for for .5 seconds on the default wave |
| 408 // device at 22K s/sec. Parameters have been chosen carefully so you should | 345 // device at 22K s/sec. Parameters have been chosen carefully so you should |
| 409 // not hear pops or noises while the sound is playing. The audio also should | 346 // not hear pops or noises while the sound is playing. The audio also should |
| 410 // sound with a lower volume than PCMWaveStreamPlay200HzTone44Kss. | 347 // sound with a lower volume than PCMWaveStreamPlay200HzTone44Kss. |
| 411 TEST(WinAudioTest, PCMWaveStreamPlay200HzTone22Kss) { | 348 TEST(WinAudioTest, PCMWaveStreamPlay200HzTone22Kss) { |
| 412 scoped_ptr<AudioManager> audio_man(AudioManager::Create()); | 349 scoped_ptr<AudioManager> audio_man(AudioManager::Create()); |
| 413 if (!audio_man->HasAudioOutputDevices()) { | 350 if (!audio_man->HasAudioOutputDevices()) { |
| 414 LOG(WARNING) << "No output device detected."; | 351 LOG(WARNING) << "No output device detected."; |
| 415 return; | 352 return; |
| 416 } | 353 } |
| 417 | 354 |
| 418 uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 20; | 355 uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 20; |
| 419 AudioOutputStream* oas = audio_man->MakeAudioOutputStream( | 356 AudioOutputStream* oas = audio_man->MakeAudioOutputStream( |
| 420 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO, | 357 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO, |
| 421 AudioParameters::kAudioCDSampleRate / 2, 16, | 358 AudioParameters::kAudioCDSampleRate / 2, 16, |
| 422 samples_100_ms)); | 359 samples_100_ms)); |
| 423 ASSERT_TRUE(NULL != oas); | 360 ASSERT_TRUE(NULL != oas); |
| 424 | 361 |
| 425 SineWaveAudioSource source(SineWaveAudioSource::FORMAT_16BIT_LINEAR_PCM, 1, | 362 SineWaveAudioSource source(1, 200.0, AudioParameters::kAudioCDSampleRate/2); |
| 426 200.0, AudioParameters::kAudioCDSampleRate/2); | |
| 427 | 363 |
| 428 EXPECT_TRUE(oas->Open()); | 364 EXPECT_TRUE(oas->Open()); |
| 429 | 365 |
| 430 oas->SetVolume(0.5); | 366 oas->SetVolume(0.5); |
| 431 oas->Start(&source); | 367 oas->Start(&source); |
| 432 ::Sleep(500); | 368 ::Sleep(500); |
| 433 | 369 |
| 434 // Test that the volume is within the set limits. | 370 // Test that the volume is within the set limits. |
| 435 double volume = 0.0; | 371 double volume = 0.0; |
| 436 oas->GetVolume(&volume); | 372 oas->GetVolume(&volume); |
| 437 EXPECT_LT(volume, 0.51); | 373 EXPECT_LT(volume, 0.51); |
| 438 EXPECT_GT(volume, 0.49); | 374 EXPECT_GT(volume, 0.49); |
| 439 oas->Stop(); | 375 oas->Stop(); |
| 440 oas->Close(); | 376 oas->Close(); |
| 441 } | 377 } |
| 442 | 378 |
| 443 // Uses the PushSource to play a 2 seconds file clip for about 5 seconds. We | 379 // Uses a restricted source to play ~2 seconds of audio for about 5 seconds. We |
| 444 // try hard to generate situation where the two threads are accessing the | 380 // try hard to generate situation where the two threads are accessing the |
| 445 // object roughly at the same time. What you hear is a sweeping tone from 1KHz | 381 // object roughly at the same time. |
| 446 // to 2KHz with a bit of fade out at the end for one second. The file is two | |
| 447 // of these sweeping tones back to back. | |
| 448 TEST(WinAudioTest, PushSourceFile16KHz) { | 382 TEST(WinAudioTest, PushSourceFile16KHz) { |
| 449 scoped_ptr<AudioManager> audio_man(AudioManager::Create()); | 383 scoped_ptr<AudioManager> audio_man(AudioManager::Create()); |
| 450 if (!audio_man->HasAudioOutputDevices()) { | 384 if (!audio_man->HasAudioOutputDevices()) { |
| 451 LOG(WARNING) << "No output device detected."; | 385 LOG(WARNING) << "No output device detected."; |
| 452 return; | 386 return; |
| 453 } | 387 } |
| 454 | 388 |
| 455 // Open sweep02_16b_mono_16KHz.raw which has no format. It contains the | 389 static const int kSampleRate = 16000; |
| 456 // raw 16 bit samples for a single channel in little-endian format. The | 390 SineWaveAudioSource source(1, 200.0, kSampleRate); |
| 457 // creation sample rate is 16KHz. | |
| 458 FilePath audio_file; | |
| 459 ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &audio_file)); | |
| 460 audio_file = audio_file.Append(kAudioFile1_16b_m_16K); | |
| 461 // Map the entire file in memory. | |
| 462 ReadOnlyMappedFile file_reader(audio_file.value().c_str()); | |
| 463 ASSERT_TRUE(file_reader.is_valid()); | |
| 464 | |
| 465 // Compute buffer size for 100ms of audio. | 391 // Compute buffer size for 100ms of audio. |
| 466 const uint32 kSamples100ms = (16000 / 1000) * 100; | 392 const uint32 kSamples100ms = (kSampleRate / 1000) * 100; |
| 467 const uint32 kSize100ms = kSamples100ms * 2; | 393 // Restrict SineWaveAudioSource to 100ms of samples. |
| 394 source.CapSamples(kSamples100ms); |
| 468 | 395 |
| 469 AudioOutputStream* oas = audio_man->MakeAudioOutputStream( | 396 AudioOutputStream* oas = audio_man->MakeAudioOutputStream( |
| 470 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO, | 397 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO, |
| 471 16000, 16, kSamples100ms)); | 398 kSampleRate, 16, kSamples100ms)); |
| 472 ASSERT_TRUE(NULL != oas); | 399 ASSERT_TRUE(NULL != oas); |
| 473 | 400 |
| 474 EXPECT_TRUE(oas->Open()); | 401 EXPECT_TRUE(oas->Open()); |
| 475 | 402 |
| 476 uint32 offset = 0; | 403 oas->SetVolume(1.0); |
| 477 const uint32 kMaxStartOffset = file_reader.size() - kSize100ms; | 404 oas->Start(&source); |
| 478 | 405 |
| 479 // We buffer and play at the same time, buffering happens every ~10ms and the | 406 // We buffer and play at the same time, buffering happens every ~10ms and the |
| 480 // consuming of the buffer happens every ~100ms. We do 100 buffers which | 407 // consuming of the buffer happens every ~100ms. We do 100 buffers which |
| 481 // effectively wrap around the file more than once. | 408 // effectively wrap around the file more than once. |
| 482 PushSource push_source; | |
| 483 for (uint32 ix = 0; ix != 100; ++ix) { | 409 for (uint32 ix = 0; ix != 100; ++ix) { |
| 484 push_source.Write(file_reader.GetChunkAt(offset), kSize100ms); | |
| 485 if (ix == 2) { | |
| 486 // For glitch free, start playing after some buffers are in. | |
| 487 oas->Start(&push_source); | |
| 488 } | |
| 489 ::Sleep(10); | 410 ::Sleep(10); |
| 490 offset += kSize100ms; | 411 source.Reset(); |
| 491 if (offset > kMaxStartOffset) | |
| 492 offset = 0; | |
| 493 } | 412 } |
| 494 | 413 |
| 495 // Play a little bit more of the file. | 414 // Play a little bit more of the file. |
| 496 ::Sleep(500); | 415 ::Sleep(500); |
| 497 | 416 |
| 498 oas->Stop(); | 417 oas->Stop(); |
| 499 oas->Close(); | 418 oas->Close(); |
| 500 } | 419 } |
| 501 | 420 |
| 502 // This test is to make sure an AudioOutputStream can be started after it was | 421 // This test is to make sure an AudioOutputStream can be started after it was |
| 503 // stopped. You will here two .5 seconds wave signal separated by 0.5 seconds | 422 // stopped. You will here two .5 seconds wave signal separated by 0.5 seconds |
| 504 // of silence. | 423 // of silence. |
| 505 TEST(WinAudioTest, PCMWaveStreamPlayTwice200HzTone44Kss) { | 424 TEST(WinAudioTest, PCMWaveStreamPlayTwice200HzTone44Kss) { |
| 506 scoped_ptr<AudioManager> audio_man(AudioManager::Create()); | 425 scoped_ptr<AudioManager> audio_man(AudioManager::Create()); |
| 507 if (!audio_man->HasAudioOutputDevices()) { | 426 if (!audio_man->HasAudioOutputDevices()) { |
| 508 LOG(WARNING) << "No output device detected."; | 427 LOG(WARNING) << "No output device detected."; |
| 509 return; | 428 return; |
| 510 } | 429 } |
| 511 | 430 |
| 512 uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 10; | 431 uint32 samples_100_ms = AudioParameters::kAudioCDSampleRate / 10; |
| 513 AudioOutputStream* oas = audio_man->MakeAudioOutputStream( | 432 AudioOutputStream* oas = audio_man->MakeAudioOutputStream( |
| 514 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO, | 433 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO, |
| 515 AudioParameters::kAudioCDSampleRate, 16, samples_100_ms)); | 434 AudioParameters::kAudioCDSampleRate, 16, samples_100_ms)); |
| 516 ASSERT_TRUE(NULL != oas); | 435 ASSERT_TRUE(NULL != oas); |
| 517 | 436 |
| 518 SineWaveAudioSource source(SineWaveAudioSource::FORMAT_16BIT_LINEAR_PCM, 1, | 437 SineWaveAudioSource source(1, 200.0, AudioParameters::kAudioCDSampleRate); |
| 519 200.0, AudioParameters::kAudioCDSampleRate); | |
| 520 EXPECT_TRUE(oas->Open()); | 438 EXPECT_TRUE(oas->Open()); |
| 521 oas->SetVolume(1.0); | 439 oas->SetVolume(1.0); |
| 522 | 440 |
| 523 // Play the wave for .5 seconds. | 441 // Play the wave for .5 seconds. |
| 524 oas->Start(&source); | 442 oas->Start(&source); |
| 525 ::Sleep(500); | 443 ::Sleep(500); |
| 526 oas->Stop(); | 444 oas->Stop(); |
| 527 | 445 |
| 528 // Sleep to give silence after stopping the AudioOutputStream. | 446 // Sleep to give silence after stopping the AudioOutputStream. |
| 529 ::Sleep(250); | 447 ::Sleep(250); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 554 int sample_rate = static_cast<int>(media::GetAudioHardwareSampleRate()); | 472 int sample_rate = static_cast<int>(media::GetAudioHardwareSampleRate()); |
| 555 uint32 samples_10_ms = sample_rate / 100; | 473 uint32 samples_10_ms = sample_rate / 100; |
| 556 int n = 1; | 474 int n = 1; |
| 557 (base::win::GetVersion() <= base::win::VERSION_XP) ? n = 5 : n = 1; | 475 (base::win::GetVersion() <= base::win::VERSION_XP) ? n = 5 : n = 1; |
| 558 AudioOutputStream* oas = audio_man->MakeAudioOutputStream( | 476 AudioOutputStream* oas = audio_man->MakeAudioOutputStream( |
| 559 AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY, | 477 AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY, |
| 560 CHANNEL_LAYOUT_MONO, sample_rate, | 478 CHANNEL_LAYOUT_MONO, sample_rate, |
| 561 16, n * samples_10_ms)); | 479 16, n * samples_10_ms)); |
| 562 ASSERT_TRUE(NULL != oas); | 480 ASSERT_TRUE(NULL != oas); |
| 563 | 481 |
| 564 SineWaveAudioSource source(SineWaveAudioSource::FORMAT_16BIT_LINEAR_PCM, 1, | 482 SineWaveAudioSource source(1, 200, sample_rate); |
| 565 200.0, sample_rate); | |
| 566 | 483 |
| 567 bool opened = oas->Open(); | 484 bool opened = oas->Open(); |
| 568 if (!opened) { | 485 if (!opened) { |
| 569 // It was not possible to open this audio device in mono. | 486 // It was not possible to open this audio device in mono. |
| 570 // No point in continuing the test so let's break here. | 487 // No point in continuing the test so let's break here. |
| 571 LOG(WARNING) << "Mono is not supported. Skipping test."; | 488 LOG(WARNING) << "Mono is not supported. Skipping test."; |
| 572 oas->Close(); | 489 oas->Close(); |
| 573 return; | 490 return; |
| 574 } | 491 } |
| 575 oas->SetVolume(1.0); | 492 oas->SetVolume(1.0); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 601 uint32 bytes_100_ms = samples_100_ms * 2; | 518 uint32 bytes_100_ms = samples_100_ms * 2; |
| 602 | 519 |
| 603 // Audio output stream has either a double or triple buffer scheme. | 520 // Audio output stream has either a double or triple buffer scheme. |
| 604 // We expect the amount of pending bytes will reaching up to 2 times of | 521 // We expect the amount of pending bytes will reaching up to 2 times of |
| 605 // |bytes_100_ms| depending on number of buffers used. | 522 // |bytes_100_ms| depending on number of buffers used. |
| 606 // From that it would decrease as we are playing the data but not providing | 523 // From that it would decrease as we are playing the data but not providing |
| 607 // new one. And then we will try to provide zero data so the amount of | 524 // new one. And then we will try to provide zero data so the amount of |
| 608 // pending bytes will go down and eventually read zero. | 525 // pending bytes will go down and eventually read zero. |
| 609 InSequence s; | 526 InSequence s; |
| 610 | 527 |
| 611 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, | 528 EXPECT_CALL(source, OnMoreData(NotNull(), |
| 612 Field(&AudioBuffersState::pending_bytes, 0))) | 529 Field(&AudioBuffersState::pending_bytes, 0))) |
| 613 .WillOnce(Return(bytes_100_ms)); | 530 .WillOnce(Invoke(MockAudioSource::ClearData)); |
| 614 switch (NumberOfWaveOutBuffers()) { | 531 switch (NumberOfWaveOutBuffers()) { |
| 615 case 2: | 532 case 2: |
| 616 break; // Calls are the same as at end of 3-buffer scheme. | 533 break; // Calls are the same as at end of 3-buffer scheme. |
| 617 case 3: | 534 case 3: |
| 618 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, | 535 EXPECT_CALL(source, OnMoreData(NotNull(), |
| 619 Field(&AudioBuffersState::pending_bytes, | 536 Field(&AudioBuffersState::pending_bytes, |
| 620 bytes_100_ms))) | 537 bytes_100_ms))) |
| 621 .WillOnce(Return(bytes_100_ms)); | 538 .WillOnce(Invoke(MockAudioSource::ClearData)); |
| 622 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, | 539 EXPECT_CALL(source, OnMoreData(NotNull(), |
| 623 Field(&AudioBuffersState::pending_bytes, | 540 Field(&AudioBuffersState::pending_bytes, |
| 624 2 * bytes_100_ms))) | 541 2 * bytes_100_ms))) |
| 625 .WillOnce(Return(bytes_100_ms)); | 542 .WillOnce(Invoke(MockAudioSource::ClearData)); |
| 626 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, | 543 EXPECT_CALL(source, OnMoreData(NotNull(), |
| 627 Field(&AudioBuffersState::pending_bytes, | 544 Field(&AudioBuffersState::pending_bytes, |
| 628 2 * bytes_100_ms))) | 545 2 * bytes_100_ms))) |
| 629 .Times(AnyNumber()) | 546 .Times(AnyNumber()) |
| 630 .WillRepeatedly(Return(0)); | 547 .WillRepeatedly(Return(0)); |
| 631 break; | 548 break; |
| 632 default: | 549 default: |
| 633 ASSERT_TRUE(false) << "Unexpected number of buffers"; | 550 ASSERT_TRUE(false) |
| 551 << "Unexpected number of buffers: " << NumberOfWaveOutBuffers(); |
| 634 } | 552 } |
| 635 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, | 553 EXPECT_CALL(source, OnMoreData(NotNull(), |
| 636 Field(&AudioBuffersState::pending_bytes, | 554 Field(&AudioBuffersState::pending_bytes, |
| 637 bytes_100_ms))) | 555 bytes_100_ms))) |
| 638 .Times(AnyNumber()) | 556 .Times(AnyNumber()) |
| 639 .WillRepeatedly(Return(0)); | 557 .WillRepeatedly(Return(0)); |
| 640 EXPECT_CALL(source, OnMoreData(NotNull(), bytes_100_ms, | 558 EXPECT_CALL(source, OnMoreData(NotNull(), |
| 641 Field(&AudioBuffersState::pending_bytes, 0))) | 559 Field(&AudioBuffersState::pending_bytes, 0))) |
| 642 .Times(AnyNumber()) | 560 .Times(AnyNumber()) |
| 643 .WillRepeatedly(Return(0)); | 561 .WillRepeatedly(Return(0)); |
| 644 | 562 |
| 645 oas->Start(&source); | 563 oas->Start(&source); |
| 646 ::Sleep(500); | 564 ::Sleep(500); |
| 647 oas->Stop(); | 565 oas->Stop(); |
| 648 oas->Close(); | 566 oas->Close(); |
| 649 } | 567 } |
| 650 | 568 |
| 651 // Simple source that uses a SyncSocket to retrieve the audio data | 569 // Simple source that uses a SyncSocket to retrieve the audio data |
| 652 // from a potentially remote thread. | 570 // from a potentially remote thread. |
| 653 class SyncSocketSource : public AudioOutputStream::AudioSourceCallback { | 571 class SyncSocketSource : public AudioOutputStream::AudioSourceCallback { |
| 654 public: | 572 public: |
| 655 explicit SyncSocketSource(base::SyncSocket* socket) | 573 SyncSocketSource(base::SyncSocket* socket, const AudioParameters& params) |
| 656 : socket_(socket) {} | 574 : socket_(socket) { |
| 657 | 575 // Setup AudioBus wrapping data we'll receive over the sync socket. |
| 658 ~SyncSocketSource() { | 576 data_size_ = AudioBus::CalculateMemorySize(params); |
| 577 data_.reset(static_cast<float*>( |
| 578 base::AlignedAlloc(data_size_, AudioBus::kChannelAlignment))); |
| 579 audio_bus_ = AudioBus::WrapMemory(params, data_.get()); |
| 659 } | 580 } |
| 581 ~SyncSocketSource() {} |
| 660 | 582 |
| 661 // AudioSourceCallback::OnMoreData implementation: | 583 // AudioSourceCallback::OnMoreData implementation: |
| 662 virtual uint32 OnMoreData(uint8* dest, | 584 virtual int OnMoreData(AudioBus* audio_bus, |
| 663 uint32 max_size, | 585 AudioBuffersState buffers_state) { |
| 664 AudioBuffersState buffers_state) { | |
| 665 socket_->Send(&buffers_state, sizeof(buffers_state)); | 586 socket_->Send(&buffers_state, sizeof(buffers_state)); |
| 666 uint32 got = socket_->Receive(dest, max_size); | 587 uint32 size = socket_->Receive(data_.get(), data_size_); |
| 667 return got; | 588 DCHECK_EQ(static_cast<size_t>(size) % sizeof(*audio_bus_->channel(0)), 0U); |
| 589 audio_bus_->CopyTo(audio_bus); |
| 590 return audio_bus_->frames(); |
| 668 } | 591 } |
| 669 // AudioSourceCallback::OnError implementation: | 592 // AudioSourceCallback::OnError implementation: |
| 670 virtual void OnError(AudioOutputStream* stream, int code) { | 593 virtual void OnError(AudioOutputStream* stream, int code) { |
| 671 } | 594 } |
| 672 | 595 |
| 673 private: | 596 private: |
| 674 base::SyncSocket* socket_; | 597 base::SyncSocket* socket_; |
| 598 int data_size_; |
| 599 scoped_ptr_malloc<float, base::ScopedPtrAlignedFree> data_; |
| 600 scoped_ptr<AudioBus> audio_bus_; |
| 675 }; | 601 }; |
| 676 | 602 |
| 677 struct SyncThreadContext { | 603 struct SyncThreadContext { |
| 678 base::SyncSocket* socket; | 604 base::SyncSocket* socket; |
| 679 int sample_rate; | 605 int sample_rate; |
| 606 int channels; |
| 607 int frames; |
| 680 double sine_freq; | 608 double sine_freq; |
| 681 uint32 packet_size_bytes; | 609 uint32 packet_size_bytes; |
| 682 }; | 610 }; |
| 683 | 611 |
| 684 // This thread provides the data that the SyncSocketSource above needs | 612 // This thread provides the data that the SyncSocketSource above needs |
| 685 // using the other end of a SyncSocket. The protocol is as follows: | 613 // using the other end of a SyncSocket. The protocol is as follows: |
| 686 // | 614 // |
| 687 // SyncSocketSource ---send 4 bytes ------------> SyncSocketThread | 615 // SyncSocketSource ---send 4 bytes ------------> SyncSocketThread |
| 688 // <--- audio packet ---------- | 616 // <--- audio packet ---------- |
| 689 // | 617 // |
| 690 DWORD __stdcall SyncSocketThread(void* context) { | 618 DWORD __stdcall SyncSocketThread(void* context) { |
| 691 SyncThreadContext& ctx = *(reinterpret_cast<SyncThreadContext*>(context)); | 619 SyncThreadContext& ctx = *(reinterpret_cast<SyncThreadContext*>(context)); |
| 692 | 620 |
| 693 const int kTwoSecBytes = | 621 // Setup AudioBus wrapping data we'll pass over the sync socket. |
| 694 AudioParameters::kAudioCDSampleRate * 2 * sizeof(uint16); // NOLINT | 622 scoped_ptr_malloc<float, base::ScopedPtrAlignedFree> data(static_cast<float*>( |
| 695 uint8* buffer = new uint8[kTwoSecBytes]; | 623 base::AlignedAlloc(ctx.packet_size_bytes, AudioBus::kChannelAlignment))); |
| 696 SineWaveAudioSource sine(SineWaveAudioSource::FORMAT_16BIT_LINEAR_PCM, | 624 scoped_ptr<AudioBus> audio_bus = AudioBus::WrapMemory( |
| 697 1, ctx.sine_freq, ctx.sample_rate); | 625 ctx.channels, ctx.frames, data.get()); |
| 698 sine.OnMoreData(buffer, kTwoSecBytes, AudioBuffersState()); | 626 |
| 627 SineWaveAudioSource sine(1, ctx.sine_freq, ctx.sample_rate); |
| 628 const int kTwoSecFrames = ctx.sample_rate * 2; |
| 699 | 629 |
| 700 AudioBuffersState buffers_state; | 630 AudioBuffersState buffers_state; |
| 701 int times = 0; | 631 int times = 0; |
| 702 for (int ix = 0; ix < kTwoSecBytes; ix += ctx.packet_size_bytes) { | 632 for (int ix = 0; ix < kTwoSecFrames; ix += ctx.frames) { |
| 703 if (ctx.socket->Receive(&buffers_state, sizeof(buffers_state)) == 0) | 633 if (ctx.socket->Receive(&buffers_state, sizeof(buffers_state)) == 0) |
| 704 break; | 634 break; |
| 705 if ((times > 0) && (buffers_state.pending_bytes < 1000)) __debugbreak(); | 635 if ((times > 0) && (buffers_state.pending_bytes < 1000)) __debugbreak(); |
| 706 ctx.socket->Send(&buffer[ix], ctx.packet_size_bytes); | 636 sine.OnMoreData(audio_bus.get(), buffers_state); |
| 637 ctx.socket->Send(data.get(), ctx.packet_size_bytes); |
| 707 ++times; | 638 ++times; |
| 708 } | 639 } |
| 709 | 640 |
| 710 delete buffer; | |
| 711 return 0; | 641 return 0; |
| 712 } | 642 } |
| 713 | 643 |
| 714 // Test the basic operation of AudioOutputStream used with a SyncSocket. | 644 // Test the basic operation of AudioOutputStream used with a SyncSocket. |
| 715 // The emphasis is to verify that it is possible to feed data to the audio | 645 // The emphasis is to verify that it is possible to feed data to the audio |
| 716 // layer using a source based on SyncSocket. In a real situation we would | 646 // layer using a source based on SyncSocket. In a real situation we would |
| 717 // go for the low-latency version in combination with SyncSocket, but to keep | 647 // go for the low-latency version in combination with SyncSocket, but to keep |
| 718 // the test more simple, AUDIO_PCM_LINEAR is utilized instead. The main | 648 // the test more simple, AUDIO_PCM_LINEAR is utilized instead. The main |
| 719 // principle of the test still remains and we avoid the additional complexity | 649 // principle of the test still remains and we avoid the additional complexity |
| 720 // related to the two different audio-layers for AUDIO_PCM_LOW_LATENCY. | 650 // related to the two different audio-layers for AUDIO_PCM_LOW_LATENCY. |
| 721 // In this test you should hear a continuous 200Hz tone for 2 seconds. | 651 // In this test you should hear a continuous 200Hz tone for 2 seconds. |
| 722 TEST(WinAudioTest, SyncSocketBasic) { | 652 TEST(WinAudioTest, SyncSocketBasic) { |
| 723 scoped_ptr<AudioManager> audio_man(AudioManager::Create()); | 653 scoped_ptr<AudioManager> audio_man(AudioManager::Create()); |
| 724 if (!audio_man->HasAudioOutputDevices()) { | 654 if (!audio_man->HasAudioOutputDevices()) { |
| 725 LOG(WARNING) << "No output device detected."; | 655 LOG(WARNING) << "No output device detected."; |
| 726 return; | 656 return; |
| 727 } | 657 } |
| 728 | 658 |
| 729 int sample_rate = AudioParameters::kAudioCDSampleRate; | 659 static const int sample_rate = AudioParameters::kAudioCDSampleRate; |
| 730 const uint32 kSamples20ms = sample_rate / 50; | 660 static const uint32 kSamples20ms = sample_rate / 50; |
| 731 AudioOutputStream* oas = audio_man->MakeAudioOutputStream( | 661 AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, |
| 732 AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, | 662 CHANNEL_LAYOUT_MONO, sample_rate, 16, kSamples20ms); |
| 733 CHANNEL_LAYOUT_MONO, sample_rate, 16, kSamples20ms)); | 663 |
| 664 |
| 665 AudioOutputStream* oas = audio_man->MakeAudioOutputStream(params); |
| 734 ASSERT_TRUE(NULL != oas); | 666 ASSERT_TRUE(NULL != oas); |
| 735 | 667 |
| 736 ASSERT_TRUE(oas->Open()); | 668 ASSERT_TRUE(oas->Open()); |
| 737 | 669 |
| 738 base::SyncSocket sockets[2]; | 670 base::SyncSocket sockets[2]; |
| 739 ASSERT_TRUE(base::SyncSocket::CreatePair(&sockets[0], &sockets[1])); | 671 ASSERT_TRUE(base::SyncSocket::CreatePair(&sockets[0], &sockets[1])); |
| 740 | 672 |
| 741 SyncSocketSource source(&sockets[0]); | 673 SyncSocketSource source(&sockets[0], params); |
| 742 | 674 |
| 743 SyncThreadContext thread_context; | 675 SyncThreadContext thread_context; |
| 744 thread_context.sample_rate = sample_rate; | 676 thread_context.sample_rate = params.sample_rate(); |
| 745 thread_context.sine_freq = 200.0; | 677 thread_context.sine_freq = 200.0; |
| 746 thread_context.packet_size_bytes = kSamples20ms * 2; | 678 thread_context.packet_size_bytes = AudioBus::CalculateMemorySize(params); |
| 679 thread_context.frames = params.frames_per_buffer(); |
| 680 thread_context.channels = params.channels(); |
| 747 thread_context.socket = &sockets[1]; | 681 thread_context.socket = &sockets[1]; |
| 748 | 682 |
| 749 HANDLE thread = ::CreateThread(NULL, 0, SyncSocketThread, | 683 HANDLE thread = ::CreateThread(NULL, 0, SyncSocketThread, |
| 750 &thread_context, 0, NULL); | 684 &thread_context, 0, NULL); |
| 751 | 685 |
| 752 oas->Start(&source); | 686 oas->Start(&source); |
| 753 | 687 |
| 754 ::WaitForSingleObject(thread, INFINITE); | 688 ::WaitForSingleObject(thread, INFINITE); |
| 755 ::CloseHandle(thread); | 689 ::CloseHandle(thread); |
| 756 | 690 |
| 757 oas->Stop(); | 691 oas->Stop(); |
| 758 oas->Close(); | 692 oas->Close(); |
| 759 } | 693 } |
| 760 | 694 |
| 761 } // namespace media | 695 } // namespace media |
| OLD | NEW |