1 /* 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "webrtc/modules/audio_device/audio_device_config.h" 12 #include "webrtc/modules/audio_device/win/audio_device_wave_win.h" 13 14 #include "webrtc/system_wrappers/include/event_wrapper.h" 15 #include "webrtc/system_wrappers/include/tick_util.h" 16 #include "webrtc/system_wrappers/include/trace.h" 17 18 #include <windows.h> 19 #include <objbase.h> // CoTaskMemAlloc, CoTaskMemFree 20 #include <strsafe.h> // StringCchCopy(), StringCchCat(), StringCchPrintf() 21 #include <assert.h> 22 23 // Avoids the need of Windows 7 SDK 24 #ifndef WAVE_MAPPED_DEFAULT_COMMUNICATION_DEVICE 25 #define WAVE_MAPPED_DEFAULT_COMMUNICATION_DEVICE 0x0010 26 #endif 27 28 // Supported in Windows Vista and Windows 7. 29 // http://msdn.microsoft.com/en-us/library/dd370819(v=VS.85).aspx 30 // Taken from Mmddk.h. 31 #define DRV_RESERVED 0x0800 32 #define DRV_QUERYFUNCTIONINSTANCEID (DRV_RESERVED + 17) 33 #define DRV_QUERYFUNCTIONINSTANCEIDSIZE (DRV_RESERVED + 18) 34 35 #define POW2(A) (2 << ((A) - 1)) 36 37 namespace webrtc { 38 39 // ============================================================================ 40 // Construction & Destruction 41 // ============================================================================ 42 43 // ---------------------------------------------------------------------------- 44 // AudioDeviceWindowsWave - ctor 45 // ---------------------------------------------------------------------------- 46 47 AudioDeviceWindowsWave::AudioDeviceWindowsWave(const int32_t id) : 48 _ptrAudioBuffer(NULL), 49 _critSect(*CriticalSectionWrapper::CreateCriticalSection()), 50 _timeEvent(*EventTimerWrapper::Create()), 51 _recStartEvent(*EventWrapper::Create()), 52 _playStartEvent(*EventWrapper::Create()), 53 _hGetCaptureVolumeThread(NULL), 54 _hShutdownGetVolumeEvent(NULL), 55 _hSetCaptureVolumeThread(NULL), 56 _hShutdownSetVolumeEvent(NULL), 57 _hSetCaptureVolumeEvent(NULL), 58 _critSectCb(*CriticalSectionWrapper::CreateCriticalSection()), 59 _id(id), 60 _mixerManager(id), 61 _usingInputDeviceIndex(false), 62 _usingOutputDeviceIndex(false), 63 _inputDevice(AudioDeviceModule::kDefaultDevice), 64 _outputDevice(AudioDeviceModule::kDefaultDevice), 65 _inputDeviceIndex(0), 66 _outputDeviceIndex(0), 67 _inputDeviceIsSpecified(false), 68 _outputDeviceIsSpecified(false), 69 _initialized(false), 70 _recIsInitialized(false), 71 _playIsInitialized(false), 72 _recording(false), 73 _playing(false), 74 _startRec(false), 75 _stopRec(false), 76 _startPlay(false), 77 _stopPlay(false), 78 _AGC(false), 79 _hWaveIn(NULL), 80 _hWaveOut(NULL), 81 _recChannels(N_REC_CHANNELS), 82 _playChannels(N_PLAY_CHANNELS), 83 _recBufCount(0), 84 _recPutBackDelay(0), 85 _recDelayCount(0), 86 _playBufCount(0), 87 _prevPlayTime(0), 88 _prevRecTime(0), 89 _prevTimerCheckTime(0), 90 _timesdwBytes(0), 91 _timerFaults(0), 92 _timerRestartAttempts(0), 93 _no_of_msecleft_warnings(0), 94 _MAX_minBuffer(65), 95 _useHeader(0), 96 _dTcheckPlayBufDelay(10), 97 _playBufDelay(80), 98 _playBufDelayFixed(80), 99 _minPlayBufDelay(20), 100 _avgCPULoad(0), 101 _sndCardPlayDelay(0), 102 _sndCardRecDelay(0), 103 _plSampOld(0), 104 _rcSampOld(0), 105 _playBufType(AudioDeviceModule::kAdaptiveBufferSize), 106 _recordedBytes(0), 107 _playWarning(0), 108 _playError(0), 109 _recWarning(0), 110 _recError(0), 111 _newMicLevel(0), 112 _minMicVolume(0), 113 _maxMicVolume(0) 114 { 115 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, id, "%s created", __FUNCTION__); 116 117 // Initialize value, set to 0 if it fails 118 if (!QueryPerformanceFrequency(&_perfFreq)) 119 { 120 _perfFreq.QuadPart = 0; 121 } 122 123 _hShutdownGetVolumeEvent = CreateEvent(NULL, FALSE, FALSE, NULL); 124 _hShutdownSetVolumeEvent = CreateEvent(NULL, FALSE, FALSE, NULL); 125 _hSetCaptureVolumeEvent = CreateEvent(NULL, FALSE, FALSE, NULL); 126 } 127 128 // ---------------------------------------------------------------------------- 129 // AudioDeviceWindowsWave - dtor 130 // ---------------------------------------------------------------------------- 131 132 AudioDeviceWindowsWave::~AudioDeviceWindowsWave() 133 { 134 WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s destroyed", __FUNCTION__); 135 136 Terminate(); 137 138 delete &_recStartEvent; 139 delete &_playStartEvent; 140 delete &_timeEvent; 141 delete &_critSect; 142 delete &_critSectCb; 143 144 if (NULL != _hShutdownGetVolumeEvent) 145 { 146 CloseHandle(_hShutdownGetVolumeEvent); 147 _hShutdownGetVolumeEvent = NULL; 148 } 149 150 if (NULL != _hShutdownSetVolumeEvent) 151 { 152 CloseHandle(_hShutdownSetVolumeEvent); 153 _hShutdownSetVolumeEvent = NULL; 154 } 155 156 if (NULL != _hSetCaptureVolumeEvent) 157 { 158 CloseHandle(_hSetCaptureVolumeEvent); 159 _hSetCaptureVolumeEvent = NULL; 160 } 161 } 162 163 // ============================================================================ 164 // API 165 // ============================================================================ 166 167 // ---------------------------------------------------------------------------- 168 // AttachAudioBuffer 169 // ---------------------------------------------------------------------------- 170 171 void AudioDeviceWindowsWave::AttachAudioBuffer(AudioDeviceBuffer* audioBuffer) 172 { 173 174 CriticalSectionScoped lock(&_critSect); 175 176 _ptrAudioBuffer = audioBuffer; 177 178 // inform the AudioBuffer about default settings for this implementation 179 _ptrAudioBuffer->SetRecordingSampleRate(N_REC_SAMPLES_PER_SEC); 180 _ptrAudioBuffer->SetPlayoutSampleRate(N_PLAY_SAMPLES_PER_SEC); 181 _ptrAudioBuffer->SetRecordingChannels(N_REC_CHANNELS); 182 _ptrAudioBuffer->SetPlayoutChannels(N_PLAY_CHANNELS); 183 } 184 185 // ---------------------------------------------------------------------------- 186 // ActiveAudioLayer 187 // ---------------------------------------------------------------------------- 188 189 int32_t AudioDeviceWindowsWave::ActiveAudioLayer(AudioDeviceModule::AudioLayer& audioLayer) const 190 { 191 audioLayer = AudioDeviceModule::kWindowsWaveAudio; 192 return 0; 193 } 194 195 // ---------------------------------------------------------------------------- 196 // Init 197 // ---------------------------------------------------------------------------- 198 199 int32_t AudioDeviceWindowsWave::Init() 200 { 201 202 CriticalSectionScoped lock(&_critSect); 203 204 if (_initialized) 205 { 206 return 0; 207 } 208 209 const uint32_t nowTime(TickTime::MillisecondTimestamp()); 210 211 _recordedBytes = 0; 212 _prevRecByteCheckTime = nowTime; 213 _prevRecTime = nowTime; 214 _prevPlayTime = nowTime; 215 _prevTimerCheckTime = nowTime; 216 217 _playWarning = 0; 218 _playError = 0; 219 _recWarning = 0; 220 _recError = 0; 221 222 _mixerManager.EnumerateAll(); 223 224 if (_ptrThread) 225 { 226 // thread is already created and active 227 return 0; 228 } 229 230 const char* threadName = "webrtc_audio_module_thread"; 231 _ptrThread.reset(new rtc::PlatformThread(ThreadFunc, this, threadName)); 232 _ptrThread->Start(); 233 _ptrThread->SetPriority(rtc::kRealtimePriority); 234 235 const bool periodic(true); 236 if (!_timeEvent.StartTimer(periodic, TIMER_PERIOD_MS)) 237 { 238 WEBRTC_TRACE(kTraceCritical, kTraceAudioDevice, _id, 239 "failed to start the timer event"); 240 _ptrThread->Stop(); 241 _ptrThread.reset(); 242 return -1; 243 } 244 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, 245 "periodic timer (dT=%d) is now active", TIMER_PERIOD_MS); 246 247 _hGetCaptureVolumeThread = 248 CreateThread(NULL, 0, GetCaptureVolumeThread, this, 0, NULL); 249 if (_hGetCaptureVolumeThread == NULL) 250 { 251 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 252 " failed to create the volume getter thread"); 253 return -1; 254 } 255 256 SetThreadPriority(_hGetCaptureVolumeThread, THREAD_PRIORITY_NORMAL); 257 258 _hSetCaptureVolumeThread = 259 CreateThread(NULL, 0, SetCaptureVolumeThread, this, 0, NULL); 260 if (_hSetCaptureVolumeThread == NULL) 261 { 262 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 263 " failed to create the volume setter thread"); 264 return -1; 265 } 266 267 SetThreadPriority(_hSetCaptureVolumeThread, THREAD_PRIORITY_NORMAL); 268 269 _initialized = true; 270 271 return 0; 272 } 273 274 // ---------------------------------------------------------------------------- 275 // Terminate 276 // ---------------------------------------------------------------------------- 277 278 int32_t AudioDeviceWindowsWave::Terminate() 279 { 280 281 if (!_initialized) 282 { 283 return 0; 284 } 285 286 _critSect.Enter(); 287 288 _mixerManager.Close(); 289 290 if (_ptrThread) 291 { 292 rtc::PlatformThread* tmpThread = _ptrThread.release(); 293 _critSect.Leave(); 294 295 _timeEvent.Set(); 296 297 tmpThread->Stop(); 298 delete tmpThread; 299 } 300 else 301 { 302 _critSect.Leave(); 303 } 304 305 _critSect.Enter(); 306 SetEvent(_hShutdownGetVolumeEvent); 307 _critSect.Leave(); 308 int32_t ret = WaitForSingleObject(_hGetCaptureVolumeThread, 2000); 309 if (ret != WAIT_OBJECT_0) 310 { 311 // the thread did not stop as it should 312 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 313 " failed to close down volume getter thread"); 314 CloseHandle(_hGetCaptureVolumeThread); 315 _hGetCaptureVolumeThread = NULL; 316 return -1; 317 } 318 _critSect.Enter(); 319 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, 320 " volume getter thread is now closed"); 321 322 SetEvent(_hShutdownSetVolumeEvent); 323 _critSect.Leave(); 324 ret = WaitForSingleObject(_hSetCaptureVolumeThread, 2000); 325 if (ret != WAIT_OBJECT_0) 326 { 327 // the thread did not stop as it should 328 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, 329 " failed to close down volume setter thread"); 330 CloseHandle(_hSetCaptureVolumeThread); 331 _hSetCaptureVolumeThread = NULL; 332 return -1; 333 } 334 _critSect.Enter(); 335 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, 336 " volume setter thread is now closed"); 337 338 CloseHandle(_hGetCaptureVolumeThread); 339 _hGetCaptureVolumeThread = NULL; 340 341 CloseHandle(_hSetCaptureVolumeThread); 342 _hSetCaptureVolumeThread = NULL; 343 344 _critSect.Leave(); 345 346 _timeEvent.StopTimer(); 347 348 _initialized = false; 349 _outputDeviceIsSpecified = false; 350 _inputDeviceIsSpecified = false; 351 352 return 0; 353 } 354 355 356 DWORD WINAPI AudioDeviceWindowsWave::GetCaptureVolumeThread(LPVOID context) 357 { 358 return(((AudioDeviceWindowsWave*)context)->DoGetCaptureVolumeThread()); 359 } 360 361 DWORD WINAPI AudioDeviceWindowsWave::SetCaptureVolumeThread(LPVOID context) 362 { 363 return(((AudioDeviceWindowsWave*)context)->DoSetCaptureVolumeThread()); 364 } 365 366 DWORD AudioDeviceWindowsWave::DoGetCaptureVolumeThread() 367 { 368 HANDLE waitObject = _hShutdownGetVolumeEvent; 369 370 while (1) 371 { 372 DWORD waitResult = WaitForSingleObject(waitObject, 373 GET_MIC_VOLUME_INTERVAL_MS); 374 switch (waitResult) 375 { 376 case WAIT_OBJECT_0: // _hShutdownGetVolumeEvent 377 return 0; 378 case WAIT_TIMEOUT: // timeout notification 379 break; 380 default: // unexpected error 381 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, 382 " unknown wait termination on get volume thread"); 383 return 1; 384 } 385 386 if (AGC()) 387 { 388 uint32_t currentMicLevel = 0; 389 if (MicrophoneVolume(currentMicLevel) == 0) 390 { 391 // This doesn't set the system volume, just stores it. 392 _critSect.Enter(); 393 if (_ptrAudioBuffer) 394 { 395 _ptrAudioBuffer->SetCurrentMicLevel(currentMicLevel); 396 } 397 _critSect.Leave(); 398 } 399 } 400 } 401 } 402 403 DWORD AudioDeviceWindowsWave::DoSetCaptureVolumeThread() 404 { 405 HANDLE waitArray[2] = {_hShutdownSetVolumeEvent, _hSetCaptureVolumeEvent}; 406 407 while (1) 408 { 409 DWORD waitResult = WaitForMultipleObjects(2, waitArray, FALSE, INFINITE); 410 switch (waitResult) 411 { 412 case WAIT_OBJECT_0: // _hShutdownSetVolumeEvent 413 return 0; 414 case WAIT_OBJECT_0 + 1: // _hSetCaptureVolumeEvent 415 break; 416 default: // unexpected error 417 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, 418 " unknown wait termination on set volume thread"); 419 return 1; 420 } 421 422 _critSect.Enter(); 423 uint32_t newMicLevel = _newMicLevel; 424 _critSect.Leave(); 425 426 if (SetMicrophoneVolume(newMicLevel) == -1) 427 { 428 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, 429 " the required modification of the microphone volume failed"); 430 } 431 } 432 return 0; 433 } 434 435 // ---------------------------------------------------------------------------- 436 // Initialized 437 // ---------------------------------------------------------------------------- 438 439 bool AudioDeviceWindowsWave::Initialized() const 440 { 441 return (_initialized); 442 } 443 444 // ---------------------------------------------------------------------------- 445 // InitSpeaker 446 // ---------------------------------------------------------------------------- 447 448 int32_t AudioDeviceWindowsWave::InitSpeaker() 449 { 450 451 CriticalSectionScoped lock(&_critSect); 452 453 if (_playing) 454 { 455 return -1; 456 } 457 458 if (_mixerManager.EnumerateSpeakers() == -1) 459 { 460 // failed to locate any valid/controllable speaker 461 return -1; 462 } 463 464 if (IsUsingOutputDeviceIndex()) 465 { 466 if (_mixerManager.OpenSpeaker(OutputDeviceIndex()) == -1) 467 { 468 return -1; 469 } 470 } 471 else 472 { 473 if (_mixerManager.OpenSpeaker(OutputDevice()) == -1) 474 { 475 return -1; 476 } 477 } 478 479 return 0; 480 } 481 482 // ---------------------------------------------------------------------------- 483 // InitMicrophone 484 // ---------------------------------------------------------------------------- 485 486 int32_t AudioDeviceWindowsWave::InitMicrophone() 487 { 488 489 CriticalSectionScoped lock(&_critSect); 490 491 if (_recording) 492 { 493 return -1; 494 } 495 496 if (_mixerManager.EnumerateMicrophones() == -1) 497 { 498 // failed to locate any valid/controllable microphone 499 return -1; 500 } 501 502 if (IsUsingInputDeviceIndex()) 503 { 504 if (_mixerManager.OpenMicrophone(InputDeviceIndex()) == -1) 505 { 506 return -1; 507 } 508 } 509 else 510 { 511 if (_mixerManager.OpenMicrophone(InputDevice()) == -1) 512 { 513 return -1; 514 } 515 } 516 517 uint32_t maxVol = 0; 518 if (_mixerManager.MaxMicrophoneVolume(maxVol) == -1) 519 { 520 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, 521 " unable to retrieve max microphone volume"); 522 } 523 _maxMicVolume = maxVol; 524 525 uint32_t minVol = 0; 526 if (_mixerManager.MinMicrophoneVolume(minVol) == -1) 527 { 528 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, 529 " unable to retrieve min microphone volume"); 530 } 531 _minMicVolume = minVol; 532 533 return 0; 534 } 535 536 // ---------------------------------------------------------------------------- 537 // SpeakerIsInitialized 538 // ---------------------------------------------------------------------------- 539 540 bool AudioDeviceWindowsWave::SpeakerIsInitialized() const 541 { 542 return (_mixerManager.SpeakerIsInitialized()); 543 } 544 545 // ---------------------------------------------------------------------------- 546 // MicrophoneIsInitialized 547 // ---------------------------------------------------------------------------- 548 549 bool AudioDeviceWindowsWave::MicrophoneIsInitialized() const 550 { 551 return (_mixerManager.MicrophoneIsInitialized()); 552 } 553 554 // ---------------------------------------------------------------------------- 555 // SpeakerVolumeIsAvailable 556 // ---------------------------------------------------------------------------- 557 558 int32_t AudioDeviceWindowsWave::SpeakerVolumeIsAvailable(bool& available) 559 { 560 561 bool isAvailable(false); 562 563 // Enumerate all avaliable speakers and make an attempt to open up the 564 // output mixer corresponding to the currently selected output device. 565 // 566 if (InitSpeaker() == -1) 567 { 568 // failed to find a valid speaker 569 available = false; 570 return 0; 571 } 572 573 // Check if the selected speaker has a volume control 574 // 575 _mixerManager.SpeakerVolumeIsAvailable(isAvailable); 576 available = isAvailable; 577 578 // Close the initialized output mixer 579 // 580 _mixerManager.CloseSpeaker(); 581 582 return 0; 583 } 584 585 // ---------------------------------------------------------------------------- 586 // SetSpeakerVolume 587 // ---------------------------------------------------------------------------- 588 589 int32_t AudioDeviceWindowsWave::SetSpeakerVolume(uint32_t volume) 590 { 591 592 return (_mixerManager.SetSpeakerVolume(volume)); 593 } 594 595 // ---------------------------------------------------------------------------- 596 // SpeakerVolume 597 // ---------------------------------------------------------------------------- 598 599 int32_t AudioDeviceWindowsWave::SpeakerVolume(uint32_t& volume) const 600 { 601 602 uint32_t level(0); 603 604 if (_mixerManager.SpeakerVolume(level) == -1) 605 { 606 return -1; 607 } 608 609 volume = level; 610 return 0; 611 } 612 613 // ---------------------------------------------------------------------------- 614 // SetWaveOutVolume 615 // 616 // The low-order word contains the left-channel volume setting, and the 617 // high-order word contains the right-channel setting. 618 // A value of 0xFFFF represents full volume, and a value of 0x0000 is silence. 619 // 620 // If a device does not support both left and right volume control, 621 // the low-order word of dwVolume specifies the volume level, 622 // and the high-order word is ignored. 623 // 624 // Most devices do not support the full 16 bits of volume-level control 625 // and will not use the least-significant bits of the requested volume setting. 626 // For example, if a device supports 4 bits of volume control, the values 627 // 0x4000, 0x4FFF, and 0x43BE will all be truncated to 0x4000. 628 // ---------------------------------------------------------------------------- 629 630 int32_t AudioDeviceWindowsWave::SetWaveOutVolume(uint16_t volumeLeft, uint16_t volumeRight) 631 { 632 633 MMRESULT res(0); 634 WAVEOUTCAPS caps; 635 636 CriticalSectionScoped lock(&_critSect); 637 638 if (_hWaveOut == NULL) 639 { 640 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no open playout device exists => using default"); 641 } 642 643 // To determine whether the device supports volume control on both 644 // the left and right channels, use the WAVECAPS_LRVOLUME flag. 645 // 646 res = waveOutGetDevCaps((UINT_PTR)_hWaveOut, &caps, sizeof(WAVEOUTCAPS)); 647 if (MMSYSERR_NOERROR != res) 648 { 649 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveOutGetDevCaps() failed (err=%d)", res); 650 TraceWaveOutError(res); 651 } 652 if (!(caps.dwSupport & WAVECAPS_VOLUME)) 653 { 654 // this device does not support volume control using the waveOutSetVolume API 655 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "device does not support volume control using the Wave API"); 656 return -1; 657 } 658 if (!(caps.dwSupport & WAVECAPS_LRVOLUME)) 659 { 660 // high-order word (right channel) is ignored 661 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "device does not support volume control on both channels"); 662 } 663 664 DWORD dwVolume(0x00000000); 665 dwVolume = (DWORD)(((volumeRight & 0xFFFF) << 16) | (volumeLeft & 0xFFFF)); 666 667 res = waveOutSetVolume(_hWaveOut, dwVolume); 668 if (MMSYSERR_NOERROR != res) 669 { 670 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "waveOutSetVolume() failed (err=%d)", res); 671 TraceWaveOutError(res); 672 return -1; 673 } 674 675 return 0; 676 } 677 678 // ---------------------------------------------------------------------------- 679 // WaveOutVolume 680 // 681 // The low-order word of this location contains the left-channel volume setting, 682 // and the high-order word contains the right-channel setting. 683 // A value of 0xFFFF (65535) represents full volume, and a value of 0x0000 684 // is silence. 685 // 686 // If a device does not support both left and right volume control, 687 // the low-order word of the specified location contains the mono volume level. 688 // 689 // The full 16-bit setting(s) set with the waveOutSetVolume function is returned, 690 // regardless of whether the device supports the full 16 bits of volume-level 691 // control. 692 // ---------------------------------------------------------------------------- 693 694 int32_t AudioDeviceWindowsWave::WaveOutVolume(uint16_t& volumeLeft, uint16_t& volumeRight) const 695 { 696 697 MMRESULT res(0); 698 WAVEOUTCAPS caps; 699 700 CriticalSectionScoped lock(&_critSect); 701 702 if (_hWaveOut == NULL) 703 { 704 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no open playout device exists => using default"); 705 } 706 707 // To determine whether the device supports volume control on both 708 // the left and right channels, use the WAVECAPS_LRVOLUME flag. 709 // 710 res = waveOutGetDevCaps((UINT_PTR)_hWaveOut, &caps, sizeof(WAVEOUTCAPS)); 711 if (MMSYSERR_NOERROR != res) 712 { 713 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveOutGetDevCaps() failed (err=%d)", res); 714 TraceWaveOutError(res); 715 } 716 if (!(caps.dwSupport & WAVECAPS_VOLUME)) 717 { 718 // this device does not support volume control using the waveOutSetVolume API 719 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "device does not support volume control using the Wave API"); 720 return -1; 721 } 722 if (!(caps.dwSupport & WAVECAPS_LRVOLUME)) 723 { 724 // high-order word (right channel) is ignored 725 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "device does not support volume control on both channels"); 726 } 727 728 DWORD dwVolume(0x00000000); 729 730 res = waveOutGetVolume(_hWaveOut, &dwVolume); 731 if (MMSYSERR_NOERROR != res) 732 { 733 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "waveOutGetVolume() failed (err=%d)", res); 734 TraceWaveOutError(res); 735 return -1; 736 } 737 738 WORD wVolumeLeft = LOWORD(dwVolume); 739 WORD wVolumeRight = HIWORD(dwVolume); 740 741 volumeLeft = static_cast<uint16_t> (wVolumeLeft); 742 volumeRight = static_cast<uint16_t> (wVolumeRight); 743 744 return 0; 745 } 746 747 // ---------------------------------------------------------------------------- 748 // MaxSpeakerVolume 749 // ---------------------------------------------------------------------------- 750 751 int32_t AudioDeviceWindowsWave::MaxSpeakerVolume(uint32_t& maxVolume) const 752 { 753 754 uint32_t maxVol(0); 755 756 if (_mixerManager.MaxSpeakerVolume(maxVol) == -1) 757 { 758 return -1; 759 } 760 761 maxVolume = maxVol; 762 return 0; 763 } 764 765 // ---------------------------------------------------------------------------- 766 // MinSpeakerVolume 767 // ---------------------------------------------------------------------------- 768 769 int32_t AudioDeviceWindowsWave::MinSpeakerVolume(uint32_t& minVolume) const 770 { 771 772 uint32_t minVol(0); 773 774 if (_mixerManager.MinSpeakerVolume(minVol) == -1) 775 { 776 return -1; 777 } 778 779 minVolume = minVol; 780 return 0; 781 } 782 783 // ---------------------------------------------------------------------------- 784 // SpeakerVolumeStepSize 785 // ---------------------------------------------------------------------------- 786 787 int32_t AudioDeviceWindowsWave::SpeakerVolumeStepSize(uint16_t& stepSize) const 788 { 789 790 uint16_t delta(0); 791 792 if (_mixerManager.SpeakerVolumeStepSize(delta) == -1) 793 { 794 return -1; 795 } 796 797 stepSize = delta; 798 return 0; 799 } 800 801 // ---------------------------------------------------------------------------- 802 // SpeakerMuteIsAvailable 803 // ---------------------------------------------------------------------------- 804 805 int32_t AudioDeviceWindowsWave::SpeakerMuteIsAvailable(bool& available) 806 { 807 808 bool isAvailable(false); 809 810 // Enumerate all avaliable speakers and make an attempt to open up the 811 // output mixer corresponding to the currently selected output device. 812 // 813 if (InitSpeaker() == -1) 814 { 815 // If we end up here it means that the selected speaker has no volume 816 // control, hence it is safe to state that there is no mute control 817 // already at this stage. 818 available = false; 819 return 0; 820 } 821 822 // Check if the selected speaker has a mute control 823 // 824 _mixerManager.SpeakerMuteIsAvailable(isAvailable); 825 available = isAvailable; 826 827 // Close the initialized output mixer 828 // 829 _mixerManager.CloseSpeaker(); 830 831 return 0; 832 } 833 834 // ---------------------------------------------------------------------------- 835 // SetSpeakerMute 836 // ---------------------------------------------------------------------------- 837 838 int32_t AudioDeviceWindowsWave::SetSpeakerMute(bool enable) 839 { 840 return (_mixerManager.SetSpeakerMute(enable)); 841 } 842 843 // ---------------------------------------------------------------------------- 844 // SpeakerMute 845 // ---------------------------------------------------------------------------- 846 847 int32_t AudioDeviceWindowsWave::SpeakerMute(bool& enabled) const 848 { 849 850 bool muted(0); 851 852 if (_mixerManager.SpeakerMute(muted) == -1) 853 { 854 return -1; 855 } 856 857 enabled = muted; 858 return 0; 859 } 860 861 // ---------------------------------------------------------------------------- 862 // MicrophoneMuteIsAvailable 863 // ---------------------------------------------------------------------------- 864 865 int32_t AudioDeviceWindowsWave::MicrophoneMuteIsAvailable(bool& available) 866 { 867 868 bool isAvailable(false); 869 870 // Enumerate all avaliable microphones and make an attempt to open up the 871 // input mixer corresponding to the currently selected input device. 872 // 873 if (InitMicrophone() == -1) 874 { 875 // If we end up here it means that the selected microphone has no volume 876 // control, hence it is safe to state that there is no boost control 877 // already at this stage. 878 available = false; 879 return 0; 880 } 881 882 // Check if the selected microphone has a mute control 883 // 884 _mixerManager.MicrophoneMuteIsAvailable(isAvailable); 885 available = isAvailable; 886 887 // Close the initialized input mixer 888 // 889 _mixerManager.CloseMicrophone(); 890 891 return 0; 892 } 893 894 // ---------------------------------------------------------------------------- 895 // SetMicrophoneMute 896 // ---------------------------------------------------------------------------- 897 898 int32_t AudioDeviceWindowsWave::SetMicrophoneMute(bool enable) 899 { 900 return (_mixerManager.SetMicrophoneMute(enable)); 901 } 902 903 // ---------------------------------------------------------------------------- 904 // MicrophoneMute 905 // ---------------------------------------------------------------------------- 906 907 int32_t AudioDeviceWindowsWave::MicrophoneMute(bool& enabled) const 908 { 909 910 bool muted(0); 911 912 if (_mixerManager.MicrophoneMute(muted) == -1) 913 { 914 return -1; 915 } 916 917 enabled = muted; 918 return 0; 919 } 920 921 // ---------------------------------------------------------------------------- 922 // MicrophoneBoostIsAvailable 923 // ---------------------------------------------------------------------------- 924 925 int32_t AudioDeviceWindowsWave::MicrophoneBoostIsAvailable(bool& available) 926 { 927 928 bool isAvailable(false); 929 930 // Enumerate all avaliable microphones and make an attempt to open up the 931 // input mixer corresponding to the currently selected input device. 932 // 933 if (InitMicrophone() == -1) 934 { 935 // If we end up here it means that the selected microphone has no volume 936 // control, hence it is safe to state that there is no boost control 937 // already at this stage. 938 available = false; 939 return 0; 940 } 941 942 // Check if the selected microphone has a boost control 943 // 944 _mixerManager.MicrophoneBoostIsAvailable(isAvailable); 945 available = isAvailable; 946 947 // Close the initialized input mixer 948 // 949 _mixerManager.CloseMicrophone(); 950 951 return 0; 952 } 953 954 // ---------------------------------------------------------------------------- 955 // SetMicrophoneBoost 956 // ---------------------------------------------------------------------------- 957 958 int32_t AudioDeviceWindowsWave::SetMicrophoneBoost(bool enable) 959 { 960 961 return (_mixerManager.SetMicrophoneBoost(enable)); 962 } 963 964 // ---------------------------------------------------------------------------- 965 // MicrophoneBoost 966 // ---------------------------------------------------------------------------- 967 968 int32_t AudioDeviceWindowsWave::MicrophoneBoost(bool& enabled) const 969 { 970 971 bool onOff(0); 972 973 if (_mixerManager.MicrophoneBoost(onOff) == -1) 974 { 975 return -1; 976 } 977 978 enabled = onOff; 979 return 0; 980 } 981 982 // ---------------------------------------------------------------------------- 983 // StereoRecordingIsAvailable 984 // ---------------------------------------------------------------------------- 985 986 int32_t AudioDeviceWindowsWave::StereoRecordingIsAvailable(bool& available) 987 { 988 available = true; 989 return 0; 990 } 991 992 // ---------------------------------------------------------------------------- 993 // SetStereoRecording 994 // ---------------------------------------------------------------------------- 995 996 int32_t AudioDeviceWindowsWave::SetStereoRecording(bool enable) 997 { 998 999 if (enable) 1000 _recChannels = 2; 1001 else 1002 _recChannels = 1; 1003 1004 return 0; 1005 } 1006 1007 // ---------------------------------------------------------------------------- 1008 // StereoRecording 1009 // ---------------------------------------------------------------------------- 1010 1011 int32_t AudioDeviceWindowsWave::StereoRecording(bool& enabled) const 1012 { 1013 1014 if (_recChannels == 2) 1015 enabled = true; 1016 else 1017 enabled = false; 1018 1019 return 0; 1020 } 1021 1022 // ---------------------------------------------------------------------------- 1023 // StereoPlayoutIsAvailable 1024 // ---------------------------------------------------------------------------- 1025 1026 int32_t AudioDeviceWindowsWave::StereoPlayoutIsAvailable(bool& available) 1027 { 1028 available = true; 1029 return 0; 1030 } 1031 1032 // ---------------------------------------------------------------------------- 1033 // SetStereoPlayout 1034 // 1035 // Specifies the number of output channels. 1036 // 1037 // NOTE - the setting will only have an effect after InitPlayout has 1038 // been called. 1039 // 1040 // 16-bit mono: 1041 // 1042 // Each sample is 2 bytes. Sample 1 is followed by samples 2, 3, 4, and so on. 1043 // For each sample, the first byte is the low-order byte of channel 0 and the 1044 // second byte is the high-order byte of channel 0. 1045 // 1046 // 16-bit stereo: 1047 // 1048 // Each sample is 4 bytes. Sample 1 is followed by samples 2, 3, 4, and so on. 1049 // For each sample, the first byte is the low-order byte of channel 0 (left channel); 1050 // the second byte is the high-order byte of channel 0; the third byte is the 1051 // low-order byte of channel 1 (right channel); and the fourth byte is the 1052 // high-order byte of channel 1. 1053 // ---------------------------------------------------------------------------- 1054 1055 int32_t AudioDeviceWindowsWave::SetStereoPlayout(bool enable) 1056 { 1057 1058 if (enable) 1059 _playChannels = 2; 1060 else 1061 _playChannels = 1; 1062 1063 return 0; 1064 } 1065 1066 // ---------------------------------------------------------------------------- 1067 // StereoPlayout 1068 // ---------------------------------------------------------------------------- 1069 1070 int32_t AudioDeviceWindowsWave::StereoPlayout(bool& enabled) const 1071 { 1072 1073 if (_playChannels == 2) 1074 enabled = true; 1075 else 1076 enabled = false; 1077 1078 return 0; 1079 } 1080 1081 // ---------------------------------------------------------------------------- 1082 // SetAGC 1083 // ---------------------------------------------------------------------------- 1084 1085 int32_t AudioDeviceWindowsWave::SetAGC(bool enable) 1086 { 1087 1088 _AGC = enable; 1089 1090 return 0; 1091 } 1092 1093 // ---------------------------------------------------------------------------- 1094 // AGC 1095 // ---------------------------------------------------------------------------- 1096 1097 bool AudioDeviceWindowsWave::AGC() const 1098 { 1099 return _AGC; 1100 } 1101 1102 // ---------------------------------------------------------------------------- 1103 // MicrophoneVolumeIsAvailable 1104 // ---------------------------------------------------------------------------- 1105 1106 int32_t AudioDeviceWindowsWave::MicrophoneVolumeIsAvailable(bool& available) 1107 { 1108 1109 bool isAvailable(false); 1110 1111 // Enumerate all avaliable microphones and make an attempt to open up the 1112 // input mixer corresponding to the currently selected output device. 1113 // 1114 if (InitMicrophone() == -1) 1115 { 1116 // Failed to find valid microphone 1117 available = false; 1118 return 0; 1119 } 1120 1121 // Check if the selected microphone has a volume control 1122 // 1123 _mixerManager.MicrophoneVolumeIsAvailable(isAvailable); 1124 available = isAvailable; 1125 1126 // Close the initialized input mixer 1127 // 1128 _mixerManager.CloseMicrophone(); 1129 1130 return 0; 1131 } 1132 1133 // ---------------------------------------------------------------------------- 1134 // SetMicrophoneVolume 1135 // ---------------------------------------------------------------------------- 1136 1137 int32_t AudioDeviceWindowsWave::SetMicrophoneVolume(uint32_t volume) 1138 { 1139 return (_mixerManager.SetMicrophoneVolume(volume)); 1140 } 1141 1142 // ---------------------------------------------------------------------------- 1143 // MicrophoneVolume 1144 // ---------------------------------------------------------------------------- 1145 1146 int32_t AudioDeviceWindowsWave::MicrophoneVolume(uint32_t& volume) const 1147 { 1148 uint32_t level(0); 1149 1150 if (_mixerManager.MicrophoneVolume(level) == -1) 1151 { 1152 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "failed to retrive current microphone level"); 1153 return -1; 1154 } 1155 1156 volume = level; 1157 return 0; 1158 } 1159 1160 // ---------------------------------------------------------------------------- 1161 // MaxMicrophoneVolume 1162 // ---------------------------------------------------------------------------- 1163 1164 int32_t AudioDeviceWindowsWave::MaxMicrophoneVolume(uint32_t& maxVolume) const 1165 { 1166 // _maxMicVolume can be zero in AudioMixerManager::MaxMicrophoneVolume(): 1167 // (1) API GetLineControl() returns failure at querying the max Mic level. 1168 // (2) API GetLineControl() returns maxVolume as zero in rare cases. 1169 // Both cases show we don't have access to the mixer controls. 1170 // We return -1 here to indicate that. 1171 if (_maxMicVolume == 0) 1172 { 1173 return -1; 1174 } 1175 1176 maxVolume = _maxMicVolume;; 1177 return 0; 1178 } 1179 1180 // ---------------------------------------------------------------------------- 1181 // MinMicrophoneVolume 1182 // ---------------------------------------------------------------------------- 1183 1184 int32_t AudioDeviceWindowsWave::MinMicrophoneVolume(uint32_t& minVolume) const 1185 { 1186 minVolume = _minMicVolume; 1187 return 0; 1188 } 1189 1190 // ---------------------------------------------------------------------------- 1191 // MicrophoneVolumeStepSize 1192 // ---------------------------------------------------------------------------- 1193 1194 int32_t AudioDeviceWindowsWave::MicrophoneVolumeStepSize(uint16_t& stepSize) const 1195 { 1196 1197 uint16_t delta(0); 1198 1199 if (_mixerManager.MicrophoneVolumeStepSize(delta) == -1) 1200 { 1201 return -1; 1202 } 1203 1204 stepSize = delta; 1205 return 0; 1206 } 1207 1208 // ---------------------------------------------------------------------------- 1209 // PlayoutDevices 1210 // ---------------------------------------------------------------------------- 1211 1212 int16_t AudioDeviceWindowsWave::PlayoutDevices() 1213 { 1214 1215 return (waveOutGetNumDevs()); 1216 } 1217 1218 // ---------------------------------------------------------------------------- 1219 // SetPlayoutDevice I (II) 1220 // ---------------------------------------------------------------------------- 1221 1222 int32_t AudioDeviceWindowsWave::SetPlayoutDevice(uint16_t index) 1223 { 1224 1225 if (_playIsInitialized) 1226 { 1227 return -1; 1228 } 1229 1230 UINT nDevices = waveOutGetNumDevs(); 1231 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "number of availiable waveform-audio output devices is %u", nDevices); 1232 1233 if (index < 0 || index > (nDevices-1)) 1234 { 1235 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "device index is out of range [0,%u]", (nDevices-1)); 1236 return -1; 1237 } 1238 1239 _usingOutputDeviceIndex = true; 1240 _outputDeviceIndex = index; 1241 _outputDeviceIsSpecified = true; 1242 1243 return 0; 1244 } 1245 1246 // ---------------------------------------------------------------------------- 1247 // SetPlayoutDevice II (II) 1248 // ---------------------------------------------------------------------------- 1249 1250 int32_t AudioDeviceWindowsWave::SetPlayoutDevice(AudioDeviceModule::WindowsDeviceType device) 1251 { 1252 if (_playIsInitialized) 1253 { 1254 return -1; 1255 } 1256 1257 if (device == AudioDeviceModule::kDefaultDevice) 1258 { 1259 } 1260 else if (device == AudioDeviceModule::kDefaultCommunicationDevice) 1261 { 1262 } 1263 1264 _usingOutputDeviceIndex = false; 1265 _outputDevice = device; 1266 _outputDeviceIsSpecified = true; 1267 1268 return 0; 1269 } 1270 1271 // ---------------------------------------------------------------------------- 1272 // PlayoutDeviceName 1273 // ---------------------------------------------------------------------------- 1274 1275 int32_t AudioDeviceWindowsWave::PlayoutDeviceName( 1276 uint16_t index, 1277 char name[kAdmMaxDeviceNameSize], 1278 char guid[kAdmMaxGuidSize]) 1279 { 1280 1281 uint16_t nDevices(PlayoutDevices()); 1282 1283 // Special fix for the case when the user asks for the name of the default device. 1284 // 1285 if (index == (uint16_t)(-1)) 1286 { 1287 index = 0; 1288 } 1289 1290 if ((index > (nDevices-1)) || (name == NULL)) 1291 { 1292 return -1; 1293 } 1294 1295 memset(name, 0, kAdmMaxDeviceNameSize); 1296 1297 if (guid != NULL) 1298 { 1299 memset(guid, 0, kAdmMaxGuidSize); 1300 } 1301 1302 WAVEOUTCAPSW caps; // szPname member (product name (NULL terminated) is a WCHAR 1303 MMRESULT res; 1304 1305 res = waveOutGetDevCapsW(index, &caps, sizeof(WAVEOUTCAPSW)); 1306 if (res != MMSYSERR_NOERROR) 1307 { 1308 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveOutGetDevCapsW() failed (err=%d)", res); 1309 return -1; 1310 } 1311 if (WideCharToMultiByte(CP_UTF8, 0, caps.szPname, -1, name, kAdmMaxDeviceNameSize, NULL, NULL) == 0) 1312 { 1313 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "WideCharToMultiByte(CP_UTF8) failed with error code %d - 1", GetLastError()); 1314 } 1315 1316 if (guid == NULL) 1317 { 1318 return 0; 1319 } 1320 1321 // It is possible to get the unique endpoint ID string using the Wave API. 1322 // However, it is only supported on Windows Vista and Windows 7. 1323 1324 size_t cbEndpointId(0); 1325 1326 // Get the size (including the terminating null) of the endpoint ID string of the waveOut device. 1327 // Windows Vista supports the DRV_QUERYFUNCTIONINSTANCEIDSIZE and DRV_QUERYFUNCTIONINSTANCEID messages. 1328 res = waveOutMessage((HWAVEOUT)IntToPtr(index), 1329 DRV_QUERYFUNCTIONINSTANCEIDSIZE, 1330 (DWORD_PTR)&cbEndpointId, NULL); 1331 if (res != MMSYSERR_NOERROR) 1332 { 1333 // DRV_QUERYFUNCTIONINSTANCEIDSIZE is not supported <=> earlier version of Windows than Vista 1334 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "waveOutMessage(DRV_QUERYFUNCTIONINSTANCEIDSIZE) failed (err=%d)", res); 1335 TraceWaveOutError(res); 1336 // Best we can do is to copy the friendly name and use it as guid 1337 if (WideCharToMultiByte(CP_UTF8, 0, caps.szPname, -1, guid, kAdmMaxGuidSize, NULL, NULL) == 0) 1338 { 1339 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "WideCharToMultiByte(CP_UTF8) failed with error code %d - 2", GetLastError()); 1340 } 1341 return 0; 1342 } 1343 1344 // waveOutMessage(DRV_QUERYFUNCTIONINSTANCEIDSIZE) worked => we are on a Vista or Windows 7 device 1345 1346 WCHAR *pstrEndpointId = NULL; 1347 pstrEndpointId = (WCHAR*)CoTaskMemAlloc(cbEndpointId); 1348 1349 // Get the endpoint ID string for this waveOut device. 1350 res = waveOutMessage((HWAVEOUT)IntToPtr(index), 1351 DRV_QUERYFUNCTIONINSTANCEID, 1352 (DWORD_PTR)pstrEndpointId, 1353 cbEndpointId); 1354 if (res != MMSYSERR_NOERROR) 1355 { 1356 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "waveOutMessage(DRV_QUERYFUNCTIONINSTANCEID) failed (err=%d)", res); 1357 TraceWaveOutError(res); 1358 // Best we can do is to copy the friendly name and use it as guid 1359 if (WideCharToMultiByte(CP_UTF8, 0, caps.szPname, -1, guid, kAdmMaxGuidSize, NULL, NULL) == 0) 1360 { 1361 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "WideCharToMultiByte(CP_UTF8) failed with error code %d - 3", GetLastError()); 1362 } 1363 CoTaskMemFree(pstrEndpointId); 1364 return 0; 1365 } 1366 1367 if (WideCharToMultiByte(CP_UTF8, 0, pstrEndpointId, -1, guid, kAdmMaxGuidSize, NULL, NULL) == 0) 1368 { 1369 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "WideCharToMultiByte(CP_UTF8) failed with error code %d - 4", GetLastError()); 1370 } 1371 CoTaskMemFree(pstrEndpointId); 1372 1373 return 0; 1374 } 1375 1376 // ---------------------------------------------------------------------------- 1377 // RecordingDeviceName 1378 // ---------------------------------------------------------------------------- 1379 1380 int32_t AudioDeviceWindowsWave::RecordingDeviceName( 1381 uint16_t index, 1382 char name[kAdmMaxDeviceNameSize], 1383 char guid[kAdmMaxGuidSize]) 1384 { 1385 1386 uint16_t nDevices(RecordingDevices()); 1387 1388 // Special fix for the case when the user asks for the name of the default device. 1389 // 1390 if (index == (uint16_t)(-1)) 1391 { 1392 index = 0; 1393 } 1394 1395 if ((index > (nDevices-1)) || (name == NULL)) 1396 { 1397 return -1; 1398 } 1399 1400 memset(name, 0, kAdmMaxDeviceNameSize); 1401 1402 if (guid != NULL) 1403 { 1404 memset(guid, 0, kAdmMaxGuidSize); 1405 } 1406 1407 WAVEINCAPSW caps; // szPname member (product name (NULL terminated) is a WCHAR 1408 MMRESULT res; 1409 1410 res = waveInGetDevCapsW(index, &caps, sizeof(WAVEINCAPSW)); 1411 if (res != MMSYSERR_NOERROR) 1412 { 1413 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveInGetDevCapsW() failed (err=%d)", res); 1414 return -1; 1415 } 1416 if (WideCharToMultiByte(CP_UTF8, 0, caps.szPname, -1, name, kAdmMaxDeviceNameSize, NULL, NULL) == 0) 1417 { 1418 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "WideCharToMultiByte(CP_UTF8) failed with error code %d - 1", GetLastError()); 1419 } 1420 1421 if (guid == NULL) 1422 { 1423 return 0; 1424 } 1425 1426 // It is possible to get the unique endpoint ID string using the Wave API. 1427 // However, it is only supported on Windows Vista and Windows 7. 1428 1429 size_t cbEndpointId(0); 1430 1431 // Get the size (including the terminating null) of the endpoint ID string of the waveOut device. 1432 // Windows Vista supports the DRV_QUERYFUNCTIONINSTANCEIDSIZE and DRV_QUERYFUNCTIONINSTANCEID messages. 1433 res = waveInMessage((HWAVEIN)IntToPtr(index), 1434 DRV_QUERYFUNCTIONINSTANCEIDSIZE, 1435 (DWORD_PTR)&cbEndpointId, NULL); 1436 if (res != MMSYSERR_NOERROR) 1437 { 1438 // DRV_QUERYFUNCTIONINSTANCEIDSIZE is not supported <=> earlier version of Windows than Vista 1439 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "waveInMessage(DRV_QUERYFUNCTIONINSTANCEIDSIZE) failed (err=%d)", res); 1440 TraceWaveInError(res); 1441 // Best we can do is to copy the friendly name and use it as guid 1442 if (WideCharToMultiByte(CP_UTF8, 0, caps.szPname, -1, guid, kAdmMaxGuidSize, NULL, NULL) == 0) 1443 { 1444 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "WideCharToMultiByte(CP_UTF8) failed with error code %d - 2", GetLastError()); 1445 } 1446 return 0; 1447 } 1448 1449 // waveOutMessage(DRV_QUERYFUNCTIONINSTANCEIDSIZE) worked => we are on a Vista or Windows 7 device 1450 1451 WCHAR *pstrEndpointId = NULL; 1452 pstrEndpointId = (WCHAR*)CoTaskMemAlloc(cbEndpointId); 1453 1454 // Get the endpoint ID string for this waveOut device. 1455 res = waveInMessage((HWAVEIN)IntToPtr(index), 1456 DRV_QUERYFUNCTIONINSTANCEID, 1457 (DWORD_PTR)pstrEndpointId, 1458 cbEndpointId); 1459 if (res != MMSYSERR_NOERROR) 1460 { 1461 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "waveInMessage(DRV_QUERYFUNCTIONINSTANCEID) failed (err=%d)", res); 1462 TraceWaveInError(res); 1463 // Best we can do is to copy the friendly name and use it as guid 1464 if (WideCharToMultiByte(CP_UTF8, 0, caps.szPname, -1, guid, kAdmMaxGuidSize, NULL, NULL) == 0) 1465 { 1466 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "WideCharToMultiByte(CP_UTF8) failed with error code %d - 3", GetLastError()); 1467 } 1468 CoTaskMemFree(pstrEndpointId); 1469 return 0; 1470 } 1471 1472 if (WideCharToMultiByte(CP_UTF8, 0, pstrEndpointId, -1, guid, kAdmMaxGuidSize, NULL, NULL) == 0) 1473 { 1474 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "WideCharToMultiByte(CP_UTF8) failed with error code %d - 4", GetLastError()); 1475 } 1476 CoTaskMemFree(pstrEndpointId); 1477 1478 return 0; 1479 } 1480 1481 // ---------------------------------------------------------------------------- 1482 // RecordingDevices 1483 // ---------------------------------------------------------------------------- 1484 1485 int16_t AudioDeviceWindowsWave::RecordingDevices() 1486 { 1487 1488 return (waveInGetNumDevs()); 1489 } 1490 1491 // ---------------------------------------------------------------------------- 1492 // SetRecordingDevice I (II) 1493 // ---------------------------------------------------------------------------- 1494 1495 int32_t AudioDeviceWindowsWave::SetRecordingDevice(uint16_t index) 1496 { 1497 1498 if (_recIsInitialized) 1499 { 1500 return -1; 1501 } 1502 1503 UINT nDevices = waveInGetNumDevs(); 1504 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "number of availiable waveform-audio input devices is %u", nDevices); 1505 1506 if (index < 0 || index > (nDevices-1)) 1507 { 1508 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "device index is out of range [0,%u]", (nDevices-1)); 1509 return -1; 1510 } 1511 1512 _usingInputDeviceIndex = true; 1513 _inputDeviceIndex = index; 1514 _inputDeviceIsSpecified = true; 1515 1516 return 0; 1517 } 1518 1519 // ---------------------------------------------------------------------------- 1520 // SetRecordingDevice II (II) 1521 // ---------------------------------------------------------------------------- 1522 1523 int32_t AudioDeviceWindowsWave::SetRecordingDevice(AudioDeviceModule::WindowsDeviceType device) 1524 { 1525 if (device == AudioDeviceModule::kDefaultDevice) 1526 { 1527 } 1528 else if (device == AudioDeviceModule::kDefaultCommunicationDevice) 1529 { 1530 } 1531 1532 if (_recIsInitialized) 1533 { 1534 return -1; 1535 } 1536 1537 _usingInputDeviceIndex = false; 1538 _inputDevice = device; 1539 _inputDeviceIsSpecified = true; 1540 1541 return 0; 1542 } 1543 1544 // ---------------------------------------------------------------------------- 1545 // PlayoutIsAvailable 1546 // ---------------------------------------------------------------------------- 1547 1548 int32_t AudioDeviceWindowsWave::PlayoutIsAvailable(bool& available) 1549 { 1550 1551 available = false; 1552 1553 // Try to initialize the playout side 1554 int32_t res = InitPlayout(); 1555 1556 // Cancel effect of initialization 1557 StopPlayout(); 1558 1559 if (res != -1) 1560 { 1561 available = true; 1562 } 1563 1564 return 0; 1565 } 1566 1567 // ---------------------------------------------------------------------------- 1568 // RecordingIsAvailable 1569 // ---------------------------------------------------------------------------- 1570 1571 int32_t AudioDeviceWindowsWave::RecordingIsAvailable(bool& available) 1572 { 1573 1574 available = false; 1575 1576 // Try to initialize the recording side 1577 int32_t res = InitRecording(); 1578 1579 // Cancel effect of initialization 1580 StopRecording(); 1581 1582 if (res != -1) 1583 { 1584 available = true; 1585 } 1586 1587 return 0; 1588 } 1589 1590 // ---------------------------------------------------------------------------- 1591 // InitPlayout 1592 // ---------------------------------------------------------------------------- 1593 1594 int32_t AudioDeviceWindowsWave::InitPlayout() 1595 { 1596 1597 CriticalSectionScoped lock(&_critSect); 1598 1599 if (_playing) 1600 { 1601 return -1; 1602 } 1603 1604 if (!_outputDeviceIsSpecified) 1605 { 1606 return -1; 1607 } 1608 1609 if (_playIsInitialized) 1610 { 1611 return 0; 1612 } 1613 1614 // Initialize the speaker (devices might have been added or removed) 1615 if (InitSpeaker() == -1) 1616 { 1617 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "InitSpeaker() failed"); 1618 } 1619 1620 // Enumerate all availiable output devices 1621 EnumeratePlayoutDevices(); 1622 1623 // Start by closing any existing wave-output devices 1624 // 1625 MMRESULT res(MMSYSERR_ERROR); 1626 1627 if (_hWaveOut != NULL) 1628 { 1629 res = waveOutClose(_hWaveOut); 1630 if (MMSYSERR_NOERROR != res) 1631 { 1632 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveOutClose() failed (err=%d)", res); 1633 TraceWaveOutError(res); 1634 } 1635 } 1636 1637 // Set the output wave format 1638 // 1639 WAVEFORMATEX waveFormat; 1640 1641 waveFormat.wFormatTag = WAVE_FORMAT_PCM; 1642 waveFormat.nChannels = _playChannels; // mono <=> 1, stereo <=> 2 1643 waveFormat.nSamplesPerSec = N_PLAY_SAMPLES_PER_SEC; 1644 waveFormat.wBitsPerSample = 16; 1645 waveFormat.nBlockAlign = waveFormat.nChannels * (waveFormat.wBitsPerSample/8); 1646 waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign; 1647 waveFormat.cbSize = 0; 1648 1649 // Open the given waveform-audio output device for playout 1650 // 1651 HWAVEOUT hWaveOut(NULL); 1652 1653 if (IsUsingOutputDeviceIndex()) 1654 { 1655 // verify settings first 1656 res = waveOutOpen(NULL, _outputDeviceIndex, &waveFormat, 0, 0, CALLBACK_NULL | WAVE_FORMAT_QUERY); 1657 if (MMSYSERR_NOERROR == res) 1658 { 1659 // open the given waveform-audio output device for recording 1660 res = waveOutOpen(&hWaveOut, _outputDeviceIndex, &waveFormat, 0, 0, CALLBACK_NULL); 1661 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "opening output device corresponding to device ID %u", _outputDeviceIndex); 1662 } 1663 } 1664 else 1665 { 1666 if (_outputDevice == AudioDeviceModule::kDefaultCommunicationDevice) 1667 { 1668 // check if it is possible to open the default communication device (supported on Windows 7) 1669 res = waveOutOpen(NULL, WAVE_MAPPER, &waveFormat, 0, 0, CALLBACK_NULL | WAVE_MAPPED_DEFAULT_COMMUNICATION_DEVICE | WAVE_FORMAT_QUERY); 1670 if (MMSYSERR_NOERROR == res) 1671 { 1672 // if so, open the default communication device for real 1673 res = waveOutOpen(&hWaveOut, WAVE_MAPPER, &waveFormat, 0, 0, CALLBACK_NULL | WAVE_MAPPED_DEFAULT_COMMUNICATION_DEVICE); 1674 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "opening default communication device"); 1675 } 1676 else 1677 { 1678 // use default device since default communication device was not avaliable 1679 res = waveOutOpen(&hWaveOut, WAVE_MAPPER, &waveFormat, 0, 0, CALLBACK_NULL); 1680 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "unable to open default communication device => using default instead"); 1681 } 1682 } 1683 else if (_outputDevice == AudioDeviceModule::kDefaultDevice) 1684 { 1685 // open default device since it has been requested 1686 res = waveOutOpen(NULL, WAVE_MAPPER, &waveFormat, 0, 0, CALLBACK_NULL | WAVE_FORMAT_QUERY); 1687 if (MMSYSERR_NOERROR == res) 1688 { 1689 res = waveOutOpen(&hWaveOut, WAVE_MAPPER, &waveFormat, 0, 0, CALLBACK_NULL); 1690 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "opening default output device"); 1691 } 1692 } 1693 } 1694 1695 if (MMSYSERR_NOERROR != res) 1696 { 1697 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "waveOutOpen() failed (err=%d)", res); 1698 TraceWaveOutError(res); 1699 return -1; 1700 } 1701 1702 // Log information about the aquired output device 1703 // 1704 WAVEOUTCAPS caps; 1705 1706 res = waveOutGetDevCaps((UINT_PTR)hWaveOut, &caps, sizeof(WAVEOUTCAPS)); 1707 if (res != MMSYSERR_NOERROR) 1708 { 1709 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveOutGetDevCaps() failed (err=%d)", res); 1710 TraceWaveOutError(res); 1711 } 1712 1713 UINT deviceID(0); 1714 res = waveOutGetID(hWaveOut, &deviceID); 1715 if (res != MMSYSERR_NOERROR) 1716 { 1717 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveOutGetID() failed (err=%d)", res); 1718 TraceWaveOutError(res); 1719 } 1720 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "utilized device ID : %u", deviceID); 1721 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "product name : %s", caps.szPname); 1722 1723 // Store valid handle for the open waveform-audio output device 1724 _hWaveOut = hWaveOut; 1725 1726 // Store the input wave header as well 1727 _waveFormatOut = waveFormat; 1728 1729 // Prepare wave-out headers 1730 // 1731 const uint8_t bytesPerSample = 2*_playChannels; 1732 1733 for (int n = 0; n < N_BUFFERS_OUT; n++) 1734 { 1735 // set up the output wave header 1736 _waveHeaderOut[n].lpData = reinterpret_cast<LPSTR>(&_playBuffer[n]); 1737 _waveHeaderOut[n].dwBufferLength = bytesPerSample*PLAY_BUF_SIZE_IN_SAMPLES; 1738 _waveHeaderOut[n].dwFlags = 0; 1739 _waveHeaderOut[n].dwLoops = 0; 1740 1741 memset(_playBuffer[n], 0, bytesPerSample*PLAY_BUF_SIZE_IN_SAMPLES); 1742 1743 // The waveOutPrepareHeader function prepares a waveform-audio data block for playback. 1744 // The lpData, dwBufferLength, and dwFlags members of the WAVEHDR structure must be set 1745 // before calling this function. 1746 // 1747 res = waveOutPrepareHeader(_hWaveOut, &_waveHeaderOut[n], sizeof(WAVEHDR)); 1748 if (MMSYSERR_NOERROR != res) 1749 { 1750 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveOutPrepareHeader(%d) failed (err=%d)", n, res); 1751 TraceWaveOutError(res); 1752 } 1753 1754 // perform extra check to ensure that the header is prepared 1755 if (_waveHeaderOut[n].dwFlags != WHDR_PREPARED) 1756 { 1757 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveOutPrepareHeader(%d) failed (dwFlags != WHDR_PREPARED)", n); 1758 } 1759 } 1760 1761 // Mark playout side as initialized 1762 _playIsInitialized = true; 1763 1764 _dTcheckPlayBufDelay = 10; // check playback buffer delay every 10 ms 1765 _playBufCount = 0; // index of active output wave header (<=> output buffer index) 1766 _playBufDelay = 80; // buffer delay/size is initialized to 80 ms and slowly decreased until er < 25 1767 _minPlayBufDelay = 25; // minimum playout buffer delay 1768 _MAX_minBuffer = 65; // adaptive minimum playout buffer delay cannot be larger than this value 1769 _intro = 1; // Used to make sure that adaption starts after (2000-1700)/100 seconds 1770 _waitCounter = 1700; // Counter for start of adaption of playback buffer 1771 _erZeroCounter = 0; // Log how many times er = 0 in consequtive calls to RecTimeProc 1772 _useHeader = 0; // Counts number of "useHeader" detections. Stops at 2. 1773 1774 _writtenSamples = 0; 1775 _writtenSamplesOld = 0; 1776 _playedSamplesOld = 0; 1777 _sndCardPlayDelay = 0; 1778 _sndCardRecDelay = 0; 1779 1780 WEBRTC_TRACE(kTraceInfo, kTraceUtility, _id,"initial playout status: _playBufDelay=%d, _minPlayBufDelay=%d", 1781 _playBufDelay, _minPlayBufDelay); 1782 1783 return 0; 1784 } 1785 1786 // ---------------------------------------------------------------------------- 1787 // InitRecording 1788 // ---------------------------------------------------------------------------- 1789 1790 int32_t AudioDeviceWindowsWave::InitRecording() 1791 { 1792 1793 CriticalSectionScoped lock(&_critSect); 1794 1795 if (_recording) 1796 { 1797 return -1; 1798 } 1799 1800 if (!_inputDeviceIsSpecified) 1801 { 1802 return -1; 1803 } 1804 1805 if (_recIsInitialized) 1806 { 1807 return 0; 1808 } 1809 1810 _avgCPULoad = 0; 1811 _playAcc = 0; 1812 1813 // Initialize the microphone (devices might have been added or removed) 1814 if (InitMicrophone() == -1) 1815 { 1816 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "InitMicrophone() failed"); 1817 } 1818 1819 // Enumerate all availiable input devices 1820 EnumerateRecordingDevices(); 1821 1822 // Start by closing any existing wave-input devices 1823 // 1824 MMRESULT res(MMSYSERR_ERROR); 1825 1826 if (_hWaveIn != NULL) 1827 { 1828 res = waveInClose(_hWaveIn); 1829 if (MMSYSERR_NOERROR != res) 1830 { 1831 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveInClose() failed (err=%d)", res); 1832 TraceWaveInError(res); 1833 } 1834 } 1835 1836 // Set the input wave format 1837 // 1838 WAVEFORMATEX waveFormat; 1839 1840 waveFormat.wFormatTag = WAVE_FORMAT_PCM; 1841 waveFormat.nChannels = _recChannels; // mono <=> 1, stereo <=> 2 1842 waveFormat.nSamplesPerSec = N_REC_SAMPLES_PER_SEC; 1843 waveFormat.wBitsPerSample = 16; 1844 waveFormat.nBlockAlign = waveFormat.nChannels * (waveFormat.wBitsPerSample/8); 1845 waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign; 1846 waveFormat.cbSize = 0; 1847 1848 // Open the given waveform-audio input device for recording 1849 // 1850 HWAVEIN hWaveIn(NULL); 1851 1852 if (IsUsingInputDeviceIndex()) 1853 { 1854 // verify settings first 1855 res = waveInOpen(NULL, _inputDeviceIndex, &waveFormat, 0, 0, CALLBACK_NULL | WAVE_FORMAT_QUERY); 1856 if (MMSYSERR_NOERROR == res) 1857 { 1858 // open the given waveform-audio input device for recording 1859 res = waveInOpen(&hWaveIn, _inputDeviceIndex, &waveFormat, 0, 0, CALLBACK_NULL); 1860 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "opening input device corresponding to device ID %u", _inputDeviceIndex); 1861 } 1862 } 1863 else 1864 { 1865 if (_inputDevice == AudioDeviceModule::kDefaultCommunicationDevice) 1866 { 1867 // check if it is possible to open the default communication device (supported on Windows 7) 1868 res = waveInOpen(NULL, WAVE_MAPPER, &waveFormat, 0, 0, CALLBACK_NULL | WAVE_MAPPED_DEFAULT_COMMUNICATION_DEVICE | WAVE_FORMAT_QUERY); 1869 if (MMSYSERR_NOERROR == res) 1870 { 1871 // if so, open the default communication device for real 1872 res = waveInOpen(&hWaveIn, WAVE_MAPPER, &waveFormat, 0, 0, CALLBACK_NULL | WAVE_MAPPED_DEFAULT_COMMUNICATION_DEVICE); 1873 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "opening default communication device"); 1874 } 1875 else 1876 { 1877 // use default device since default communication device was not avaliable 1878 res = waveInOpen(&hWaveIn, WAVE_MAPPER, &waveFormat, 0, 0, CALLBACK_NULL); 1879 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "unable to open default communication device => using default instead"); 1880 } 1881 } 1882 else if (_inputDevice == AudioDeviceModule::kDefaultDevice) 1883 { 1884 // open default device since it has been requested 1885 res = waveInOpen(NULL, WAVE_MAPPER, &waveFormat, 0, 0, CALLBACK_NULL | WAVE_FORMAT_QUERY); 1886 if (MMSYSERR_NOERROR == res) 1887 { 1888 res = waveInOpen(&hWaveIn, WAVE_MAPPER, &waveFormat, 0, 0, CALLBACK_NULL); 1889 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "opening default input device"); 1890 } 1891 } 1892 } 1893 1894 if (MMSYSERR_NOERROR != res) 1895 { 1896 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "waveInOpen() failed (err=%d)", res); 1897 TraceWaveInError(res); 1898 return -1; 1899 } 1900 1901 // Log information about the aquired input device 1902 // 1903 WAVEINCAPS caps; 1904 1905 res = waveInGetDevCaps((UINT_PTR)hWaveIn, &caps, sizeof(WAVEINCAPS)); 1906 if (res != MMSYSERR_NOERROR) 1907 { 1908 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveInGetDevCaps() failed (err=%d)", res); 1909 TraceWaveInError(res); 1910 } 1911 1912 UINT deviceID(0); 1913 res = waveInGetID(hWaveIn, &deviceID); 1914 if (res != MMSYSERR_NOERROR) 1915 { 1916 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveInGetID() failed (err=%d)", res); 1917 TraceWaveInError(res); 1918 } 1919 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "utilized device ID : %u", deviceID); 1920 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "product name : %s", caps.szPname); 1921 1922 // Store valid handle for the open waveform-audio input device 1923 _hWaveIn = hWaveIn; 1924 1925 // Store the input wave header as well 1926 _waveFormatIn = waveFormat; 1927 1928 // Mark recording side as initialized 1929 _recIsInitialized = true; 1930 1931 _recBufCount = 0; // index of active input wave header (<=> input buffer index) 1932 _recDelayCount = 0; // ensures that input buffers are returned with certain delay 1933 1934 return 0; 1935 } 1936 1937 // ---------------------------------------------------------------------------- 1938 // StartRecording 1939 // ---------------------------------------------------------------------------- 1940 1941 int32_t AudioDeviceWindowsWave::StartRecording() 1942 { 1943 1944 if (!_recIsInitialized) 1945 { 1946 return -1; 1947 } 1948 1949 if (_recording) 1950 { 1951 return 0; 1952 } 1953 1954 // set state to ensure that the recording starts from the audio thread 1955 _startRec = true; 1956 1957 // the audio thread will signal when recording has stopped 1958 if (kEventTimeout == _recStartEvent.Wait(10000)) 1959 { 1960 _startRec = false; 1961 StopRecording(); 1962 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "failed to activate recording"); 1963 return -1; 1964 } 1965 1966 if (_recording) 1967 { 1968 // the recording state is set by the audio thread after recording has started 1969 } 1970 else 1971 { 1972 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "failed to activate recording"); 1973 return -1; 1974 } 1975 1976 return 0; 1977 } 1978 1979 // ---------------------------------------------------------------------------- 1980 // StopRecording 1981 // ---------------------------------------------------------------------------- 1982 1983 int32_t AudioDeviceWindowsWave::StopRecording() 1984 { 1985 1986 CriticalSectionScoped lock(&_critSect); 1987 1988 if (!_recIsInitialized) 1989 { 1990 return 0; 1991 } 1992 1993 if (_hWaveIn == NULL) 1994 { 1995 return -1; 1996 } 1997 1998 bool wasRecording = _recording; 1999 _recIsInitialized = false; 2000 _recording = false; 2001 2002 MMRESULT res; 2003 2004 // Stop waveform-adio input. If there are any buffers in the queue, the 2005 // current buffer will be marked as done (the dwBytesRecorded member in 2006 // the header will contain the length of data), but any empty buffers in 2007 // the queue will remain there. 2008 // 2009 res = waveInStop(_hWaveIn); 2010 if (MMSYSERR_NOERROR != res) 2011 { 2012 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveInStop() failed (err=%d)", res); 2013 TraceWaveInError(res); 2014 } 2015 2016 // Stop input on the given waveform-audio input device and resets the current 2017 // position to zero. All pending buffers are marked as done and returned to 2018 // the application. 2019 // 2020 res = waveInReset(_hWaveIn); 2021 if (MMSYSERR_NOERROR != res) 2022 { 2023 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveInReset() failed (err=%d)", res); 2024 TraceWaveInError(res); 2025 } 2026 2027 // Clean up the preparation performed by the waveInPrepareHeader function. 2028 // Only unprepare header if recording was ever started (and headers are prepared). 2029 // 2030 if (wasRecording) 2031 { 2032 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "waveInUnprepareHeader() will be performed"); 2033 for (int n = 0; n < N_BUFFERS_IN; n++) 2034 { 2035 res = waveInUnprepareHeader(_hWaveIn, &_waveHeaderIn[n], sizeof(WAVEHDR)); 2036 if (MMSYSERR_NOERROR != res) 2037 { 2038 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveInUnprepareHeader() failed (err=%d)", res); 2039 TraceWaveInError(res); 2040 } 2041 } 2042 } 2043 2044 // Close the given waveform-audio input device. 2045 // 2046 res = waveInClose(_hWaveIn); 2047 if (MMSYSERR_NOERROR != res) 2048 { 2049 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveInClose() failed (err=%d)", res); 2050 TraceWaveInError(res); 2051 } 2052 2053 // Set the wave input handle to NULL 2054 // 2055 _hWaveIn = NULL; 2056 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "_hWaveIn is now set to NULL"); 2057 2058 return 0; 2059 } 2060 2061 // ---------------------------------------------------------------------------- 2062 // RecordingIsInitialized 2063 // ---------------------------------------------------------------------------- 2064 2065 bool AudioDeviceWindowsWave::RecordingIsInitialized() const 2066 { 2067 return (_recIsInitialized); 2068 } 2069 2070 // ---------------------------------------------------------------------------- 2071 // Recording 2072 // ---------------------------------------------------------------------------- 2073 2074 bool AudioDeviceWindowsWave::Recording() const 2075 { 2076 return (_recording); 2077 } 2078 2079 // ---------------------------------------------------------------------------- 2080 // PlayoutIsInitialized 2081 // ---------------------------------------------------------------------------- 2082 2083 bool AudioDeviceWindowsWave::PlayoutIsInitialized() const 2084 { 2085 return (_playIsInitialized); 2086 } 2087 2088 // ---------------------------------------------------------------------------- 2089 // StartPlayout 2090 // ---------------------------------------------------------------------------- 2091 2092 int32_t AudioDeviceWindowsWave::StartPlayout() 2093 { 2094 2095 if (!_playIsInitialized) 2096 { 2097 return -1; 2098 } 2099 2100 if (_playing) 2101 { 2102 return 0; 2103 } 2104 2105 // set state to ensure that playout starts from the audio thread 2106 _startPlay = true; 2107 2108 // the audio thread will signal when recording has started 2109 if (kEventTimeout == _playStartEvent.Wait(10000)) 2110 { 2111 _startPlay = false; 2112 StopPlayout(); 2113 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "failed to activate playout"); 2114 return -1; 2115 } 2116 2117 if (_playing) 2118 { 2119 // the playing state is set by the audio thread after playout has started 2120 } 2121 else 2122 { 2123 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "failed to activate playing"); 2124 return -1; 2125 } 2126 2127 return 0; 2128 } 2129 2130 // ---------------------------------------------------------------------------- 2131 // StopPlayout 2132 // ---------------------------------------------------------------------------- 2133 2134 int32_t AudioDeviceWindowsWave::StopPlayout() 2135 { 2136 2137 CriticalSectionScoped lock(&_critSect); 2138 2139 if (!_playIsInitialized) 2140 { 2141 return 0; 2142 } 2143 2144 if (_hWaveOut == NULL) 2145 { 2146 return -1; 2147 } 2148 2149 _playIsInitialized = false; 2150 _playing = false; 2151 _sndCardPlayDelay = 0; 2152 _sndCardRecDelay = 0; 2153 2154 MMRESULT res; 2155 2156 // The waveOutReset function stops playback on the given waveform-audio 2157 // output device and resets the current position to zero. All pending 2158 // playback buffers are marked as done (WHDR_DONE) and returned to the application. 2159 // After this function returns, the application can send new playback buffers 2160 // to the device by calling waveOutWrite, or close the device by calling waveOutClose. 2161 // 2162 res = waveOutReset(_hWaveOut); 2163 if (MMSYSERR_NOERROR != res) 2164 { 2165 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveOutReset() failed (err=%d)", res); 2166 TraceWaveOutError(res); 2167 } 2168 2169 // The waveOutUnprepareHeader function cleans up the preparation performed 2170 // by the waveOutPrepareHeader function. This function must be called after 2171 // the device driver is finished with a data block. 2172 // You must call this function before freeing the buffer. 2173 // 2174 for (int n = 0; n < N_BUFFERS_OUT; n++) 2175 { 2176 res = waveOutUnprepareHeader(_hWaveOut, &_waveHeaderOut[n], sizeof(WAVEHDR)); 2177 if (MMSYSERR_NOERROR != res) 2178 { 2179 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveOutUnprepareHeader() failed (err=%d)", res); 2180 TraceWaveOutError(res); 2181 } 2182 } 2183 2184 // The waveOutClose function closes the given waveform-audio output device. 2185 // The close operation fails if the device is still playing a waveform-audio 2186 // buffer that was previously sent by calling waveOutWrite. Before calling 2187 // waveOutClose, the application must wait for all buffers to finish playing 2188 // or call the waveOutReset function to terminate playback. 2189 // 2190 res = waveOutClose(_hWaveOut); 2191 if (MMSYSERR_NOERROR != res) 2192 { 2193 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveOutClose() failed (err=%d)", res); 2194 TraceWaveOutError(res); 2195 } 2196 2197 _hWaveOut = NULL; 2198 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "_hWaveOut is now set to NULL"); 2199 2200 return 0; 2201 } 2202 2203 // ---------------------------------------------------------------------------- 2204 // PlayoutDelay 2205 // ---------------------------------------------------------------------------- 2206 2207 int32_t AudioDeviceWindowsWave::PlayoutDelay(uint16_t& delayMS) const 2208 { 2209 CriticalSectionScoped lock(&_critSect); 2210 delayMS = (uint16_t)_sndCardPlayDelay; 2211 return 0; 2212 } 2213 2214 // ---------------------------------------------------------------------------- 2215 // RecordingDelay 2216 // ---------------------------------------------------------------------------- 2217 2218 int32_t AudioDeviceWindowsWave::RecordingDelay(uint16_t& delayMS) const 2219 { 2220 CriticalSectionScoped lock(&_critSect); 2221 delayMS = (uint16_t)_sndCardRecDelay; 2222 return 0; 2223 } 2224 2225 // ---------------------------------------------------------------------------- 2226 // Playing 2227 // ---------------------------------------------------------------------------- 2228 2229 bool AudioDeviceWindowsWave::Playing() const 2230 { 2231 return (_playing); 2232 } 2233 // ---------------------------------------------------------------------------- 2234 // SetPlayoutBuffer 2235 // ---------------------------------------------------------------------------- 2236 2237 int32_t AudioDeviceWindowsWave::SetPlayoutBuffer(const AudioDeviceModule::BufferType type, uint16_t sizeMS) 2238 { 2239 CriticalSectionScoped lock(&_critSect); 2240 _playBufType = type; 2241 if (type == AudioDeviceModule::kFixedBufferSize) 2242 { 2243 _playBufDelayFixed = sizeMS; 2244 } 2245 return 0; 2246 } 2247 2248 // ---------------------------------------------------------------------------- 2249 // PlayoutBuffer 2250 // ---------------------------------------------------------------------------- 2251 2252 int32_t AudioDeviceWindowsWave::PlayoutBuffer(AudioDeviceModule::BufferType& type, uint16_t& sizeMS) const 2253 { 2254 CriticalSectionScoped lock(&_critSect); 2255 type = _playBufType; 2256 if (type == AudioDeviceModule::kFixedBufferSize) 2257 { 2258 sizeMS = _playBufDelayFixed; 2259 } 2260 else 2261 { 2262 sizeMS = _playBufDelay; 2263 } 2264 2265 return 0; 2266 } 2267 2268 // ---------------------------------------------------------------------------- 2269 // CPULoad 2270 // ---------------------------------------------------------------------------- 2271 2272 int32_t AudioDeviceWindowsWave::CPULoad(uint16_t& load) const 2273 { 2274 2275 load = static_cast<uint16_t>(100*_avgCPULoad); 2276 2277 return 0; 2278 } 2279 2280 // ---------------------------------------------------------------------------- 2281 // PlayoutWarning 2282 // ---------------------------------------------------------------------------- 2283 2284 bool AudioDeviceWindowsWave::PlayoutWarning() const 2285 { 2286 return ( _playWarning > 0); 2287 } 2288 2289 // ---------------------------------------------------------------------------- 2290 // PlayoutError 2291 // ---------------------------------------------------------------------------- 2292 2293 bool AudioDeviceWindowsWave::PlayoutError() const 2294 { 2295 return ( _playError > 0); 2296 } 2297 2298 // ---------------------------------------------------------------------------- 2299 // RecordingWarning 2300 // ---------------------------------------------------------------------------- 2301 2302 bool AudioDeviceWindowsWave::RecordingWarning() const 2303 { 2304 return ( _recWarning > 0); 2305 } 2306 2307 // ---------------------------------------------------------------------------- 2308 // RecordingError 2309 // ---------------------------------------------------------------------------- 2310 2311 bool AudioDeviceWindowsWave::RecordingError() const 2312 { 2313 return ( _recError > 0); 2314 } 2315 2316 // ---------------------------------------------------------------------------- 2317 // ClearPlayoutWarning 2318 // ---------------------------------------------------------------------------- 2319 2320 void AudioDeviceWindowsWave::ClearPlayoutWarning() 2321 { 2322 _playWarning = 0; 2323 } 2324 2325 // ---------------------------------------------------------------------------- 2326 // ClearPlayoutError 2327 // ---------------------------------------------------------------------------- 2328 2329 void AudioDeviceWindowsWave::ClearPlayoutError() 2330 { 2331 _playError = 0; 2332 } 2333 2334 // ---------------------------------------------------------------------------- 2335 // ClearRecordingWarning 2336 // ---------------------------------------------------------------------------- 2337 2338 void AudioDeviceWindowsWave::ClearRecordingWarning() 2339 { 2340 _recWarning = 0; 2341 } 2342 2343 // ---------------------------------------------------------------------------- 2344 // ClearRecordingError 2345 // ---------------------------------------------------------------------------- 2346 2347 void AudioDeviceWindowsWave::ClearRecordingError() 2348 { 2349 _recError = 0; 2350 } 2351 2352 // ============================================================================ 2353 // Private Methods 2354 // ============================================================================ 2355 2356 // ---------------------------------------------------------------------------- 2357 // InputSanityCheckAfterUnlockedPeriod 2358 // ---------------------------------------------------------------------------- 2359 2360 int32_t AudioDeviceWindowsWave::InputSanityCheckAfterUnlockedPeriod() const 2361 { 2362 if (_hWaveIn == NULL) 2363 { 2364 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "input state has been modified during unlocked period"); 2365 return -1; 2366 } 2367 return 0; 2368 } 2369 2370 // ---------------------------------------------------------------------------- 2371 // OutputSanityCheckAfterUnlockedPeriod 2372 // ---------------------------------------------------------------------------- 2373 2374 int32_t AudioDeviceWindowsWave::OutputSanityCheckAfterUnlockedPeriod() const 2375 { 2376 if (_hWaveOut == NULL) 2377 { 2378 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "output state has been modified during unlocked period"); 2379 return -1; 2380 } 2381 return 0; 2382 } 2383 2384 // ---------------------------------------------------------------------------- 2385 // EnumeratePlayoutDevices 2386 // ---------------------------------------------------------------------------- 2387 2388 int32_t AudioDeviceWindowsWave::EnumeratePlayoutDevices() 2389 { 2390 2391 uint16_t nDevices(PlayoutDevices()); 2392 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "==============================================================="); 2393 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "#output devices: %u", nDevices); 2394 2395 WAVEOUTCAPS caps; 2396 MMRESULT res; 2397 2398 for (UINT deviceID = 0; deviceID < nDevices; deviceID++) 2399 { 2400 res = waveOutGetDevCaps(deviceID, &caps, sizeof(WAVEOUTCAPS)); 2401 if (res != MMSYSERR_NOERROR) 2402 { 2403 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveOutGetDevCaps() failed (err=%d)", res); 2404 } 2405 2406 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "==============================================================="); 2407 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "Device ID %u:", deviceID); 2408 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "manufacturer ID : %u", caps.wMid); 2409 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "product ID : %u",caps.wPid); 2410 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "version of driver : %u.%u", HIBYTE(caps.vDriverVersion), LOBYTE(caps.vDriverVersion)); 2411 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "product name : %s", caps.szPname); 2412 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "dwFormats : 0x%x", caps.dwFormats); 2413 if (caps.dwFormats & WAVE_FORMAT_48S16) 2414 { 2415 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, " 48kHz,stereo,16bit : SUPPORTED"); 2416 } 2417 else 2418 { 2419 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, " 48kHz,stereo,16bit : *NOT* SUPPORTED"); 2420 } 2421 if (caps.dwFormats & WAVE_FORMAT_48M16) 2422 { 2423 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, " 48kHz,mono,16bit : SUPPORTED"); 2424 } 2425 else 2426 { 2427 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, " 48kHz,mono,16bit : *NOT* SUPPORTED"); 2428 } 2429 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "wChannels : %u", caps.wChannels); 2430 TraceSupportFlags(caps.dwSupport); 2431 } 2432 2433 return 0; 2434 } 2435 2436 // ---------------------------------------------------------------------------- 2437 // EnumerateRecordingDevices 2438 // ---------------------------------------------------------------------------- 2439 2440 int32_t AudioDeviceWindowsWave::EnumerateRecordingDevices() 2441 { 2442 2443 uint16_t nDevices(RecordingDevices()); 2444 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "==============================================================="); 2445 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "#input devices: %u", nDevices); 2446 2447 WAVEINCAPS caps; 2448 MMRESULT res; 2449 2450 for (UINT deviceID = 0; deviceID < nDevices; deviceID++) 2451 { 2452 res = waveInGetDevCaps(deviceID, &caps, sizeof(WAVEINCAPS)); 2453 if (res != MMSYSERR_NOERROR) 2454 { 2455 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveInGetDevCaps() failed (err=%d)", res); 2456 } 2457 2458 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "==============================================================="); 2459 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "Device ID %u:", deviceID); 2460 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "manufacturer ID : %u", caps.wMid); 2461 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "product ID : %u",caps.wPid); 2462 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "version of driver : %u.%u", HIBYTE(caps.vDriverVersion), LOBYTE(caps.vDriverVersion)); 2463 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "product name : %s", caps.szPname); 2464 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "dwFormats : 0x%x", caps.dwFormats); 2465 if (caps.dwFormats & WAVE_FORMAT_48S16) 2466 { 2467 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, " 48kHz,stereo,16bit : SUPPORTED"); 2468 } 2469 else 2470 { 2471 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, " 48kHz,stereo,16bit : *NOT* SUPPORTED"); 2472 } 2473 if (caps.dwFormats & WAVE_FORMAT_48M16) 2474 { 2475 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, " 48kHz,mono,16bit : SUPPORTED"); 2476 } 2477 else 2478 { 2479 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, " 48kHz,mono,16bit : *NOT* SUPPORTED"); 2480 } 2481 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "wChannels : %u", caps.wChannels); 2482 } 2483 2484 return 0; 2485 } 2486 2487 // ---------------------------------------------------------------------------- 2488 // TraceSupportFlags 2489 // ---------------------------------------------------------------------------- 2490 2491 void AudioDeviceWindowsWave::TraceSupportFlags(DWORD dwSupport) const 2492 { 2493 TCHAR buf[256]; 2494 2495 StringCchPrintf(buf, 128, TEXT("support flags : 0x%x "), dwSupport); 2496 2497 if (dwSupport & WAVECAPS_PITCH) 2498 { 2499 // supports pitch control 2500 StringCchCat(buf, 256, TEXT("(PITCH)")); 2501 } 2502 if (dwSupport & WAVECAPS_PLAYBACKRATE) 2503 { 2504 // supports playback rate control 2505 StringCchCat(buf, 256, TEXT("(PLAYBACKRATE)")); 2506 } 2507 if (dwSupport & WAVECAPS_VOLUME) 2508 { 2509 // supports volume control 2510 StringCchCat(buf, 256, TEXT("(VOLUME)")); 2511 } 2512 if (dwSupport & WAVECAPS_LRVOLUME) 2513 { 2514 // supports separate left and right volume control 2515 StringCchCat(buf, 256, TEXT("(LRVOLUME)")); 2516 } 2517 if (dwSupport & WAVECAPS_SYNC) 2518 { 2519 // the driver is synchronous and will block while playing a buffer 2520 StringCchCat(buf, 256, TEXT("(SYNC)")); 2521 } 2522 if (dwSupport & WAVECAPS_SAMPLEACCURATE) 2523 { 2524 // returns sample-accurate position information 2525 StringCchCat(buf, 256, TEXT("(SAMPLEACCURATE)")); 2526 } 2527 2528 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%S", buf); 2529 } 2530 2531 // ---------------------------------------------------------------------------- 2532 // TraceWaveInError 2533 // ---------------------------------------------------------------------------- 2534 2535 void AudioDeviceWindowsWave::TraceWaveInError(MMRESULT error) const 2536 { 2537 TCHAR buf[MAXERRORLENGTH]; 2538 TCHAR msg[MAXERRORLENGTH]; 2539 2540 StringCchPrintf(buf, MAXERRORLENGTH, TEXT("Error details: ")); 2541 waveInGetErrorText(error, msg, MAXERRORLENGTH); 2542 StringCchCat(buf, MAXERRORLENGTH, msg); 2543 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%S", buf); 2544 } 2545 2546 // ---------------------------------------------------------------------------- 2547 // TraceWaveOutError 2548 // ---------------------------------------------------------------------------- 2549 2550 void AudioDeviceWindowsWave::TraceWaveOutError(MMRESULT error) const 2551 { 2552 TCHAR buf[MAXERRORLENGTH]; 2553 TCHAR msg[MAXERRORLENGTH]; 2554 2555 StringCchPrintf(buf, MAXERRORLENGTH, TEXT("Error details: ")); 2556 waveOutGetErrorText(error, msg, MAXERRORLENGTH); 2557 StringCchCat(buf, MAXERRORLENGTH, msg); 2558 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%S", buf); 2559 } 2560 2561 // ---------------------------------------------------------------------------- 2562 // PrepareStartPlayout 2563 // ---------------------------------------------------------------------------- 2564 2565 int32_t AudioDeviceWindowsWave::PrepareStartPlayout() 2566 { 2567 2568 CriticalSectionScoped lock(&_critSect); 2569 2570 if (_hWaveOut == NULL) 2571 { 2572 return -1; 2573 } 2574 2575 // A total of 30ms of data is immediately placed in the SC buffer 2576 // 2577 int8_t zeroVec[4*PLAY_BUF_SIZE_IN_SAMPLES]; // max allocation 2578 memset(zeroVec, 0, 4*PLAY_BUF_SIZE_IN_SAMPLES); 2579 2580 { 2581 Write(zeroVec, PLAY_BUF_SIZE_IN_SAMPLES); 2582 Write(zeroVec, PLAY_BUF_SIZE_IN_SAMPLES); 2583 Write(zeroVec, PLAY_BUF_SIZE_IN_SAMPLES); 2584 } 2585 2586 _playAcc = 0; 2587 _playWarning = 0; 2588 _playError = 0; 2589 _dc_diff_mean = 0; 2590 _dc_y_prev = 0; 2591 _dc_penalty_counter = 20; 2592 _dc_prevtime = 0; 2593 _dc_prevplay = 0; 2594 2595 return 0; 2596 } 2597 2598 // ---------------------------------------------------------------------------- 2599 // PrepareStartRecording 2600 // ---------------------------------------------------------------------------- 2601 2602 int32_t AudioDeviceWindowsWave::PrepareStartRecording() 2603 { 2604 2605 CriticalSectionScoped lock(&_critSect); 2606 2607 if (_hWaveIn == NULL) 2608 { 2609 return -1; 2610 } 2611 2612 _playAcc = 0; 2613 _recordedBytes = 0; 2614 _recPutBackDelay = REC_PUT_BACK_DELAY; 2615 2616 MMRESULT res; 2617 MMTIME mmtime; 2618 mmtime.wType = TIME_SAMPLES; 2619 2620 res = waveInGetPosition(_hWaveIn, &mmtime, sizeof(mmtime)); 2621 if (MMSYSERR_NOERROR != res) 2622 { 2623 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveInGetPosition(TIME_SAMPLES) failed (err=%d)", res); 2624 TraceWaveInError(res); 2625 } 2626 2627 _read_samples = mmtime.u.sample; 2628 _read_samples_old = _read_samples; 2629 _rec_samples_old = mmtime.u.sample; 2630 _wrapCounter = 0; 2631 2632 for (int n = 0; n < N_BUFFERS_IN; n++) 2633 { 2634 const uint8_t nBytesPerSample = 2*_recChannels; 2635 2636 // set up the input wave header 2637 _waveHeaderIn[n].lpData = reinterpret_cast<LPSTR>(&_recBuffer[n]); 2638 _waveHeaderIn[n].dwBufferLength = nBytesPerSample * REC_BUF_SIZE_IN_SAMPLES; 2639 _waveHeaderIn[n].dwFlags = 0; 2640 _waveHeaderIn[n].dwBytesRecorded = 0; 2641 _waveHeaderIn[n].dwUser = 0; 2642 2643 memset(_recBuffer[n], 0, nBytesPerSample * REC_BUF_SIZE_IN_SAMPLES); 2644 2645 // prepare a buffer for waveform-audio input 2646 res = waveInPrepareHeader(_hWaveIn, &_waveHeaderIn[n], sizeof(WAVEHDR)); 2647 if (MMSYSERR_NOERROR != res) 2648 { 2649 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveInPrepareHeader(%d) failed (err=%d)", n, res); 2650 TraceWaveInError(res); 2651 } 2652 2653 // send an input buffer to the given waveform-audio input device 2654 res = waveInAddBuffer(_hWaveIn, &_waveHeaderIn[n], sizeof(WAVEHDR)); 2655 if (MMSYSERR_NOERROR != res) 2656 { 2657 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveInAddBuffer(%d) failed (err=%d)", n, res); 2658 TraceWaveInError(res); 2659 } 2660 } 2661 2662 // start input on the given waveform-audio input device 2663 res = waveInStart(_hWaveIn); 2664 if (MMSYSERR_NOERROR != res) 2665 { 2666 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveInStart() failed (err=%d)", res); 2667 TraceWaveInError(res); 2668 } 2669 2670 return 0; 2671 } 2672 2673 // ---------------------------------------------------------------------------- 2674 // GetPlayoutBufferDelay 2675 // ---------------------------------------------------------------------------- 2676 2677 int32_t AudioDeviceWindowsWave::GetPlayoutBufferDelay(uint32_t& writtenSamples, uint32_t& playedSamples) 2678 { 2679 int i; 2680 int ms_Header; 2681 long playedDifference; 2682 int msecInPlayoutBuffer(0); // #milliseconds of audio in the playout buffer 2683 2684 const uint16_t nSamplesPerMs = (uint16_t)(N_PLAY_SAMPLES_PER_SEC/1000); // default is 48000/1000 = 48 2685 2686 MMRESULT res; 2687 MMTIME mmtime; 2688 2689 if (!_playing) 2690 { 2691 playedSamples = 0; 2692 return (0); 2693 } 2694 2695 // Retrieve the current playback position. 2696 // 2697 mmtime.wType = TIME_SAMPLES; // number of waveform-audio samples 2698 res = waveOutGetPosition(_hWaveOut, &mmtime, sizeof(mmtime)); 2699 if (MMSYSERR_NOERROR != res) 2700 { 2701 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveOutGetPosition() failed (err=%d)", res); 2702 TraceWaveOutError(res); 2703 } 2704 2705 writtenSamples = _writtenSamples; // #samples written to the playout buffer 2706 playedSamples = mmtime.u.sample; // current playout position in the playout buffer 2707 2708 // derive remaining amount (in ms) of data in the playout buffer 2709 msecInPlayoutBuffer = ((writtenSamples - playedSamples)/nSamplesPerMs); 2710 2711 playedDifference = (long) (_playedSamplesOld - playedSamples); 2712 2713 if (playedDifference > 64000) 2714 { 2715 // If the sound cards number-of-played-out-samples variable wraps around before 2716 // written_sampels wraps around this needs to be adjusted. This can happen on 2717 // sound cards that uses less than 32 bits to keep track of number of played out 2718 // sampels. To avoid being fooled by sound cards that sometimes produces false 2719 // output we compare old value minus the new value with a large value. This is 2720 // neccessary because some SC:s produce an output like 153, 198, 175, 230 which 2721 // would trigger the wrap-around function if we didn't compare with a large value. 2722 // The value 64000 is chosen because 2^16=65536 so we allow wrap around at 16 bits. 2723 2724 i = 31; 2725 while((_playedSamplesOld <= (unsigned long)POW2(i)) && (i > 14)) { 2726 i--; 2727 } 2728 2729 if((i < 31) && (i > 14)) { 2730 // Avoid adjusting when there is 32-bit wrap-around since that is 2731 // something neccessary. 2732 // 2733 WEBRTC_TRACE(kTraceDebug, kTraceUtility, _id, "msecleft() => wrap around occured: %d bits used by sound card)", (i+1)); 2734 2735 _writtenSamples = _writtenSamples - POW2(i + 1); 2736 writtenSamples = _writtenSamples; 2737 msecInPlayoutBuffer = ((writtenSamples - playedSamples)/nSamplesPerMs); 2738 } 2739 } 2740 else if ((_writtenSamplesOld > POW2(31)) && (writtenSamples < 96000)) 2741 { 2742 // Wrap around as expected after having used all 32 bits. (But we still 2743 // test if the wrap around happened earlier which it should not) 2744 2745 i = 31; 2746 while (_writtenSamplesOld <= (unsigned long)POW2(i)) { 2747 i--; 2748 } 2749 2750 WEBRTC_TRACE(kTraceDebug, kTraceUtility, _id, " msecleft() (wrap around occured after having used all 32 bits)"); 2751 2752 _writtenSamplesOld = writtenSamples; 2753 _playedSamplesOld = playedSamples; 2754 msecInPlayoutBuffer = (int)((writtenSamples + POW2(i + 1) - playedSamples)/nSamplesPerMs); 2755 2756 } 2757 else if ((writtenSamples < 96000) && (playedSamples > POW2(31))) 2758 { 2759 // Wrap around has, as expected, happened for written_sampels before 2760 // playedSampels so we have to adjust for this until also playedSampels 2761 // has had wrap around. 2762 2763 WEBRTC_TRACE(kTraceDebug, kTraceUtility, _id, " msecleft() (wrap around occured: correction of output is done)"); 2764 2765 _writtenSamplesOld = writtenSamples; 2766 _playedSamplesOld = playedSamples; 2767 msecInPlayoutBuffer = (int)((writtenSamples + POW2(32) - playedSamples)/nSamplesPerMs); 2768 } 2769 2770 _writtenSamplesOld = writtenSamples; 2771 _playedSamplesOld = playedSamples; 2772 2773 2774 // We use the following formaula to track that playout works as it should 2775 // y=playedSamples/48 - timeGetTime(); 2776 // y represent the clock drift between system clock and sound card clock - should be fairly stable 2777 // When the exponential mean value of diff(y) goes away from zero something is wrong 2778 // The exponential formula will accept 1% clock drift but not more 2779 // The driver error means that we will play to little audio and have a high negative clock drift 2780 // We kick in our alternative method when the clock drift reaches 20% 2781 2782 int diff,y; 2783 int unsigned time =0; 2784 2785 // If we have other problems that causes playout glitches 2786 // we don't want to switch playout method. 2787 // Check if playout buffer is extremely low, or if we haven't been able to 2788 // exectue our code in more than 40 ms 2789 2790 time = timeGetTime(); 2791 2792 if ((msecInPlayoutBuffer < 20) || (time - _dc_prevtime > 40)) 2793 { 2794 _dc_penalty_counter = 100; 2795 } 2796 2797 if ((playedSamples != 0)) 2798 { 2799 y = playedSamples/48 - time; 2800 if ((_dc_y_prev != 0) && (_dc_penalty_counter == 0)) 2801 { 2802 diff = y - _dc_y_prev; 2803 _dc_diff_mean = (990*_dc_diff_mean)/1000 + 10*diff; 2804 } 2805 _dc_y_prev = y; 2806 } 2807 2808 if (_dc_penalty_counter) 2809 { 2810 _dc_penalty_counter--; 2811 } 2812 2813 if (_dc_diff_mean < -200) 2814 { 2815 // Always reset the filter 2816 _dc_diff_mean = 0; 2817 2818 // Problem is detected. Switch delay method and set min buffer to 80. 2819 // Reset the filter and keep monitoring the filter output. 2820 // If issue is detected a second time, increase min buffer to 100. 2821 // If that does not help, we must modify this scheme further. 2822 2823 _useHeader++; 2824 if (_useHeader == 1) 2825 { 2826 _minPlayBufDelay = 80; 2827 _playWarning = 1; // only warn first time 2828 WEBRTC_TRACE(kTraceInfo, kTraceUtility, -1, "Modification #1: _useHeader = %d, _minPlayBufDelay = %d", _useHeader, _minPlayBufDelay); 2829 } 2830 else if (_useHeader == 2) 2831 { 2832 _minPlayBufDelay = 100; // add some more safety 2833 WEBRTC_TRACE(kTraceInfo, kTraceUtility, -1, "Modification #2: _useHeader = %d, _minPlayBufDelay = %d", _useHeader, _minPlayBufDelay); 2834 } 2835 else 2836 { 2837 // This state should not be entered... (HA) 2838 WEBRTC_TRACE (kTraceWarning, kTraceUtility, -1, "further actions are required!"); 2839 } 2840 if (_playWarning == 1) 2841 { 2842 WEBRTC_TRACE(kTraceWarning, kTraceUtility, _id, "pending playout warning exists"); 2843 } 2844 _playWarning = 1; // triggers callback from module process thread 2845 WEBRTC_TRACE(kTraceWarning, kTraceUtility, _id, "kPlayoutWarning message posted: switching to alternative playout delay method"); 2846 } 2847 _dc_prevtime = time; 2848 _dc_prevplay = playedSamples; 2849 2850 // Try a very rough method of looking at how many buffers are still playing 2851 ms_Header = 0; 2852 for (i = 0; i < N_BUFFERS_OUT; i++) { 2853 if ((_waveHeaderOut[i].dwFlags & WHDR_INQUEUE)!=0) { 2854 ms_Header += 10; 2855 } 2856 } 2857 2858 if ((ms_Header-50) > msecInPlayoutBuffer) { 2859 // Test for cases when GetPosition appears to be screwed up (currently just log....) 2860 TCHAR infoStr[300]; 2861 if (_no_of_msecleft_warnings%20==0) 2862 { 2863 StringCchPrintf(infoStr, 300, TEXT("writtenSamples=%i, playedSamples=%i, msecInPlayoutBuffer=%i, ms_Header=%i"), writtenSamples, playedSamples, msecInPlayoutBuffer, ms_Header); 2864 WEBRTC_TRACE(kTraceWarning, kTraceUtility, _id, "%S", infoStr); 2865 } 2866 _no_of_msecleft_warnings++; 2867 } 2868 2869 // If this is true we have had a problem with the playout 2870 if (_useHeader > 0) 2871 { 2872 return (ms_Header); 2873 } 2874 2875 2876 if (ms_Header < msecInPlayoutBuffer) 2877 { 2878 if (_no_of_msecleft_warnings % 100 == 0) 2879 { 2880 TCHAR str[300]; 2881 StringCchPrintf(str, 300, TEXT("_no_of_msecleft_warnings=%i, msecInPlayoutBuffer=%i ms_Header=%i (minBuffer=%i buffersize=%i writtenSamples=%i playedSamples=%i)"), 2882 _no_of_msecleft_warnings, msecInPlayoutBuffer, ms_Header, _minPlayBufDelay, _playBufDelay, writtenSamples, playedSamples); 2883 WEBRTC_TRACE(kTraceWarning, kTraceUtility, _id, "%S", str); 2884 } 2885 _no_of_msecleft_warnings++; 2886 ms_Header -= 6; // Round off as we only have 10ms resolution + Header info is usually slightly delayed compared to GetPosition 2887 2888 if (ms_Header < 0) 2889 ms_Header = 0; 2890 2891 return (ms_Header); 2892 } 2893 else 2894 { 2895 return (msecInPlayoutBuffer); 2896 } 2897 } 2898 2899 // ---------------------------------------------------------------------------- 2900 // GetRecordingBufferDelay 2901 // ---------------------------------------------------------------------------- 2902 2903 int32_t AudioDeviceWindowsWave::GetRecordingBufferDelay(uint32_t& readSamples, uint32_t& recSamples) 2904 { 2905 long recDifference; 2906 MMTIME mmtime; 2907 MMRESULT mmr; 2908 2909 const uint16_t nSamplesPerMs = (uint16_t)(N_REC_SAMPLES_PER_SEC/1000); // default is 48000/1000 = 48 2910 2911 // Retrieve the current input position of the given waveform-audio input device 2912 // 2913 mmtime.wType = TIME_SAMPLES; 2914 mmr = waveInGetPosition(_hWaveIn, &mmtime, sizeof(mmtime)); 2915 if (MMSYSERR_NOERROR != mmr) 2916 { 2917 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveInGetPosition() failed (err=%d)", mmr); 2918 TraceWaveInError(mmr); 2919 } 2920 2921 readSamples = _read_samples; // updated for each full fram in RecProc() 2922 recSamples = mmtime.u.sample; // remaining time in input queue (recorded but not read yet) 2923 2924 recDifference = (long) (_rec_samples_old - recSamples); 2925 2926 if( recDifference > 64000) { 2927 WEBRTC_TRACE (kTraceDebug, kTraceUtility, -1,"WRAP 1 (recDifference =%d)", recDifference); 2928 // If the sound cards number-of-recorded-samples variable wraps around before 2929 // read_sampels wraps around this needs to be adjusted. This can happen on 2930 // sound cards that uses less than 32 bits to keep track of number of played out 2931 // sampels. To avoid being fooled by sound cards that sometimes produces false 2932 // output we compare old value minus the new value with a large value. This is 2933 // neccessary because some SC:s produce an output like 153, 198, 175, 230 which 2934 // would trigger the wrap-around function if we didn't compare with a large value. 2935 // The value 64000 is chosen because 2^16=65536 so we allow wrap around at 16 bits. 2936 // 2937 int i = 31; 2938 while((_rec_samples_old <= (unsigned long)POW2(i)) && (i > 14)) 2939 i--; 2940 2941 if((i < 31) && (i > 14)) { 2942 // Avoid adjusting when there is 32-bit wrap-around since that is 2943 // somethying neccessary. 2944 // 2945 _read_samples = _read_samples - POW2(i + 1); 2946 readSamples = _read_samples; 2947 _wrapCounter++; 2948 } else { 2949 WEBRTC_TRACE (kTraceWarning, kTraceUtility, -1,"AEC (_rec_samples_old %d recSamples %d)",_rec_samples_old, recSamples); 2950 } 2951 } 2952 2953 if((_wrapCounter>200)){ 2954 // Do nothing, handled later 2955 } 2956 else if((_rec_samples_old > POW2(31)) && (recSamples < 96000)) { 2957 WEBRTC_TRACE (kTraceDebug, kTraceUtility, -1,"WRAP 2 (_rec_samples_old %d recSamples %d)",_rec_samples_old, recSamples); 2958 // Wrap around as expected after having used all 32 bits. 2959 _read_samples_old = readSamples; 2960 _rec_samples_old = recSamples; 2961 _wrapCounter++; 2962 return (int)((recSamples + POW2(32) - readSamples)/nSamplesPerMs); 2963 2964 2965 } else if((recSamples < 96000) && (readSamples > POW2(31))) { 2966 WEBRTC_TRACE (kTraceDebug, kTraceUtility, -1,"WRAP 3 (readSamples %d recSamples %d)",readSamples, recSamples); 2967 // Wrap around has, as expected, happened for rec_sampels before 2968 // readSampels so we have to adjust for this until also readSampels 2969 // has had wrap around. 2970 _read_samples_old = readSamples; 2971 _rec_samples_old = recSamples; 2972 _wrapCounter++; 2973 return (int)((recSamples + POW2(32) - readSamples)/nSamplesPerMs); 2974 } 2975 2976 _read_samples_old = _read_samples; 2977 _rec_samples_old = recSamples; 2978 int res=(((int)_rec_samples_old - (int)_read_samples_old)/nSamplesPerMs); 2979 2980 if((res > 2000)||(res < 0)||(_wrapCounter>200)){ 2981 // Reset everything 2982 WEBRTC_TRACE (kTraceWarning, kTraceUtility, -1,"msec_read error (res %d wrapCounter %d)",res, _wrapCounter); 2983 MMTIME mmtime; 2984 mmtime.wType = TIME_SAMPLES; 2985 2986 mmr=waveInGetPosition(_hWaveIn, &mmtime, sizeof(mmtime)); 2987 if (mmr != MMSYSERR_NOERROR) { 2988 WEBRTC_TRACE (kTraceWarning, kTraceUtility, -1, "waveInGetPosition failed (mmr=%d)", mmr); 2989 } 2990 _read_samples=mmtime.u.sample; 2991 _read_samples_old=_read_samples; 2992 _rec_samples_old=mmtime.u.sample; 2993 2994 // Guess a decent value 2995 res = 20; 2996 } 2997 2998 _wrapCounter = 0; 2999 return res; 3000 } 3001 3002 // ============================================================================ 3003 // Thread Methods 3004 // ============================================================================ 3005 3006 // ---------------------------------------------------------------------------- 3007 // ThreadFunc 3008 // ---------------------------------------------------------------------------- 3009 3010 bool AudioDeviceWindowsWave::ThreadFunc(void* pThis) 3011 { 3012 return (static_cast<AudioDeviceWindowsWave*>(pThis)->ThreadProcess()); 3013 } 3014 3015 // ---------------------------------------------------------------------------- 3016 // ThreadProcess 3017 // ---------------------------------------------------------------------------- 3018 3019 bool AudioDeviceWindowsWave::ThreadProcess() 3020 { 3021 uint32_t time(0); 3022 uint32_t playDiff(0); 3023 uint32_t recDiff(0); 3024 3025 LONGLONG playTime(0); 3026 LONGLONG recTime(0); 3027 3028 switch (_timeEvent.Wait(1000)) 3029 { 3030 case kEventSignaled: 3031 break; 3032 case kEventError: 3033 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "EventWrapper::Wait() failed => restarting timer"); 3034 _timeEvent.StopTimer(); 3035 _timeEvent.StartTimer(true, TIMER_PERIOD_MS); 3036 return true; 3037 case kEventTimeout: 3038 return true; 3039 } 3040 3041 time = TickTime::MillisecondTimestamp(); 3042 3043 if (_startPlay) 3044 { 3045 if (PrepareStartPlayout() == 0) 3046 { 3047 _prevTimerCheckTime = time; 3048 _prevPlayTime = time; 3049 _startPlay = false; 3050 _playing = true; 3051 _playStartEvent.Set(); 3052 } 3053 } 3054 3055 if (_startRec) 3056 { 3057 if (PrepareStartRecording() == 0) 3058 { 3059 _prevTimerCheckTime = time; 3060 _prevRecTime = time; 3061 _prevRecByteCheckTime = time; 3062 _startRec = false; 3063 _recording = true; 3064 _recStartEvent.Set(); 3065 } 3066 } 3067 3068 if (_playing) 3069 { 3070 playDiff = time - _prevPlayTime; 3071 } 3072 3073 if (_recording) 3074 { 3075 recDiff = time - _prevRecTime; 3076 } 3077 3078 if (_playing || _recording) 3079 { 3080 RestartTimerIfNeeded(time); 3081 } 3082 3083 if (_playing && 3084 (playDiff > (uint32_t)(_dTcheckPlayBufDelay - 1)) || 3085 (playDiff < 0)) 3086 { 3087 Lock(); 3088 if (_playing) 3089 { 3090 if (PlayProc(playTime) == -1) 3091 { 3092 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "PlayProc() failed"); 3093 } 3094 _prevPlayTime = time; 3095 if (playTime != 0) 3096 _playAcc += playTime; 3097 } 3098 UnLock(); 3099 } 3100 3101 if (_playing && (playDiff > 12)) 3102 { 3103 // It has been a long time since we were able to play out, try to 3104 // compensate by calling PlayProc again. 3105 // 3106 Lock(); 3107 if (_playing) 3108 { 3109 if (PlayProc(playTime)) 3110 { 3111 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "PlayProc() failed"); 3112 } 3113 _prevPlayTime = time; 3114 if (playTime != 0) 3115 _playAcc += playTime; 3116 } 3117 UnLock(); 3118 } 3119 3120 if (_recording && 3121 (recDiff > REC_CHECK_TIME_PERIOD_MS) || 3122 (recDiff < 0)) 3123 { 3124 Lock(); 3125 if (_recording) 3126 { 3127 int32_t nRecordedBytes(0); 3128 uint16_t maxIter(10); 3129 3130 // Deliver all availiable recorded buffers and update the CPU load measurement. 3131 // We use a while loop here to compensate for the fact that the multi-media timer 3132 // can sometimed enter a "bad state" after hibernation where the resolution is 3133 // reduced from ~1ms to ~10-15 ms. 3134 // 3135 while ((nRecordedBytes = RecProc(recTime)) > 0) 3136 { 3137 maxIter--; 3138 _recordedBytes += nRecordedBytes; 3139 if (recTime && _perfFreq.QuadPart) 3140 { 3141 // Measure the average CPU load: 3142 // This is a simplified expression where an exponential filter is used: 3143 // _avgCPULoad = 0.99 * _avgCPULoad + 0.01 * newCPU, 3144 // newCPU = (recTime+playAcc)/f is time in seconds 3145 // newCPU / 0.01 is the fraction of a 10 ms period 3146 // The two 0.01 cancels each other. 3147 // NOTE - assumes 10ms audio buffers. 3148 // 3149 _avgCPULoad = (float)(_avgCPULoad*.99 + (recTime+_playAcc)/(double)(_perfFreq.QuadPart)); 3150 _playAcc = 0; 3151 } 3152 if (maxIter == 0) 3153 { 3154 // If we get this message ofte, our compensation scheme is not sufficient. 3155 WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "failed to compensate for reduced MM-timer resolution"); 3156 } 3157 } 3158 3159 if (nRecordedBytes == -1) 3160 { 3161 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "RecProc() failed"); 3162 } 3163 3164 _prevRecTime = time; 3165 3166 // Monitor the recording process and generate error/warning callbacks if needed 3167 MonitorRecording(time); 3168 } 3169 UnLock(); 3170 } 3171 3172 if (!_recording) 3173 { 3174 _prevRecByteCheckTime = time; 3175 _avgCPULoad = 0; 3176 } 3177 3178 return true; 3179 } 3180 3181 // ---------------------------------------------------------------------------- 3182 // RecProc 3183 // ---------------------------------------------------------------------------- 3184 3185 int32_t AudioDeviceWindowsWave::RecProc(LONGLONG& consumedTime) 3186 { 3187 MMRESULT res; 3188 uint32_t bufCount(0); 3189 uint32_t nBytesRecorded(0); 3190 3191 consumedTime = 0; 3192 3193 // count modulo N_BUFFERS_IN (0,1,2,...,(N_BUFFERS_IN-1),0,1,2,..) 3194 if (_recBufCount == N_BUFFERS_IN) 3195 { 3196 _recBufCount = 0; 3197 } 3198 3199 bufCount = _recBufCount; 3200 3201 // take mono/stereo mode into account when deriving size of a full buffer 3202 const uint16_t bytesPerSample = 2*_recChannels; 3203 const uint32_t fullBufferSizeInBytes = bytesPerSample * REC_BUF_SIZE_IN_SAMPLES; 3204 3205 // read number of recorded bytes for the given input-buffer 3206 nBytesRecorded = _waveHeaderIn[bufCount].dwBytesRecorded; 3207 3208 if (nBytesRecorded == fullBufferSizeInBytes || 3209 (nBytesRecorded > 0)) 3210 { 3211 int32_t msecOnPlaySide; 3212 int32_t msecOnRecordSide; 3213 uint32_t writtenSamples; 3214 uint32_t playedSamples; 3215 uint32_t readSamples, recSamples; 3216 bool send = true; 3217 3218 uint32_t nSamplesRecorded = (nBytesRecorded/bytesPerSample); // divide by 2 or 4 depending on mono or stereo 3219 3220 if (nBytesRecorded == fullBufferSizeInBytes) 3221 { 3222 _timesdwBytes = 0; 3223 } 3224 else 3225 { 3226 // Test if it is stuck on this buffer 3227 _timesdwBytes++; 3228 if (_timesdwBytes < 5) 3229 { 3230 // keep trying 3231 return (0); 3232 } 3233 else 3234 { 3235 WEBRTC_TRACE(kTraceDebug, kTraceUtility, _id,"nBytesRecorded=%d => don't use", nBytesRecorded); 3236 _timesdwBytes = 0; 3237 send = false; 3238 } 3239 } 3240 3241 // store the recorded buffer (no action will be taken if the #recorded samples is not a full buffer) 3242 _ptrAudioBuffer->SetRecordedBuffer(_waveHeaderIn[bufCount].lpData, nSamplesRecorded); 3243 3244 // update #samples read 3245 _read_samples += nSamplesRecorded; 3246 3247 // Check how large the playout and recording buffers are on the sound card. 3248 // This info is needed by the AEC. 3249 // 3250 msecOnPlaySide = GetPlayoutBufferDelay(writtenSamples, playedSamples); 3251 msecOnRecordSide = GetRecordingBufferDelay(readSamples, recSamples); 3252 3253 // If we use the alternative playout delay method, skip the clock drift compensation 3254 // since it will be an unreliable estimate and might degrade AEC performance. 3255 int32_t drift = (_useHeader > 0) ? 0 : GetClockDrift(playedSamples, recSamples); 3256 3257 _ptrAudioBuffer->SetVQEData(msecOnPlaySide, msecOnRecordSide, drift); 3258 3259 _ptrAudioBuffer->SetTypingStatus(KeyPressed()); 3260 3261 // Store the play and rec delay values for video synchronization 3262 _sndCardPlayDelay = msecOnPlaySide; 3263 _sndCardRecDelay = msecOnRecordSide; 3264 3265 LARGE_INTEGER t1={0},t2={0}; 3266 3267 if (send) 3268 { 3269 QueryPerformanceCounter(&t1); 3270 3271 // deliver recorded samples at specified sample rate, mic level etc. to the observer using callback 3272 UnLock(); 3273 _ptrAudioBuffer->DeliverRecordedData(); 3274 Lock(); 3275 3276 QueryPerformanceCounter(&t2); 3277 3278 if (InputSanityCheckAfterUnlockedPeriod() == -1) 3279 { 3280 // assert(false); 3281 return -1; 3282 } 3283 } 3284 3285 if (_AGC) 3286 { 3287 uint32_t newMicLevel = _ptrAudioBuffer->NewMicLevel(); 3288 if (newMicLevel != 0) 3289 { 3290 // The VQE will only deliver non-zero microphone levels when a change is needed. 3291 WEBRTC_TRACE(kTraceStream, kTraceUtility, _id,"AGC change of volume: => new=%u", newMicLevel); 3292 3293 // We store this outside of the audio buffer to avoid 3294 // having it overwritten by the getter thread. 3295 _newMicLevel = newMicLevel; 3296 SetEvent(_hSetCaptureVolumeEvent); 3297 } 3298 } 3299 3300 // return utilized buffer to queue after specified delay (default is 4) 3301 if (_recDelayCount > (_recPutBackDelay-1)) 3302 { 3303 // deley buffer counter to compensate for "put-back-delay" 3304 bufCount = (bufCount + N_BUFFERS_IN - _recPutBackDelay) % N_BUFFERS_IN; 3305 3306 // reset counter so we can make new detection 3307 _waveHeaderIn[bufCount].dwBytesRecorded = 0; 3308 3309 // return the utilized wave-header after certain delay (given by _recPutBackDelay) 3310 res = waveInUnprepareHeader(_hWaveIn, &(_waveHeaderIn[bufCount]), sizeof(WAVEHDR)); 3311 if (MMSYSERR_NOERROR != res) 3312 { 3313 WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveInUnprepareHeader(%d) failed (err=%d)", bufCount, res); 3314 TraceWaveInError(res); 3315 } 3316 3317 // ensure that the utilized header can be used again 3318 res = waveInPrepareHeader(_hWaveIn, &(_waveHeaderIn[bufCount]), sizeof(WAVEHDR)); 3319 if (res != MMSYSERR_NOERROR) 3320 { 3321 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "waveInPrepareHeader(%d) failed (err=%d)", bufCount, res); 3322 TraceWaveInError(res); 3323 return -1; 3324 } 3325 3326 // add the utilized buffer to the queue again 3327 res = waveInAddBuffer(_hWaveIn, &(_waveHeaderIn[bufCount]), sizeof(WAVEHDR)); 3328 if (res != MMSYSERR_NOERROR) 3329 { 3330 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "waveInAddBuffer(%d) failed (err=%d)", bufCount, res); 3331 TraceWaveInError(res); 3332 if (_recPutBackDelay < 50) 3333 { 3334 _recPutBackDelay++; 3335 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "_recPutBackDelay increased to %d", _recPutBackDelay); 3336 } 3337 else 3338 { 3339 if (_recError == 1) 3340 { 3341 WEBRTC_TRACE(kTraceWarning, kTraceUtility, _id, "pending recording error exists"); 3342 } 3343 _recError = 1; // triggers callback from module process thread 3344 WEBRTC_TRACE(kTraceError, kTraceUtility, _id, "kRecordingError message posted: _recPutBackDelay=%u", _recPutBackDelay); 3345 } 3346 } 3347 } // if (_recDelayCount > (_recPutBackDelay-1)) 3348 3349 if (_recDelayCount < (_recPutBackDelay+1)) 3350 { 3351 _recDelayCount++; 3352 } 3353 3354 // increase main buffer count since one complete buffer has now been delivered 3355 _recBufCount++; 3356 3357 if (send) { 3358 // Calculate processing time 3359 consumedTime = (int)(t2.QuadPart-t1.QuadPart); 3360 // handle wraps, time should not be higher than a second 3361 if ((consumedTime > _perfFreq.QuadPart) || (consumedTime < 0)) 3362 consumedTime = 0; 3363 } 3364 3365 } // if ((nBytesRecorded == fullBufferSizeInBytes)) 3366 3367 return nBytesRecorded; 3368 } 3369 3370 // ---------------------------------------------------------------------------- 3371 // PlayProc 3372 // ---------------------------------------------------------------------------- 3373 3374 int AudioDeviceWindowsWave::PlayProc(LONGLONG& consumedTime) 3375 { 3376 int32_t remTimeMS(0); 3377 int8_t playBuffer[4*PLAY_BUF_SIZE_IN_SAMPLES]; 3378 uint32_t writtenSamples(0); 3379 uint32_t playedSamples(0); 3380 3381 LARGE_INTEGER t1; 3382 LARGE_INTEGER t2; 3383 3384 consumedTime = 0; 3385 _waitCounter++; 3386 3387 // Get number of ms of sound that remains in the sound card buffer for playback. 3388 // 3389 remTimeMS = GetPlayoutBufferDelay(writtenSamples, playedSamples); 3390 3391 // The threshold can be adaptive or fixed. The adaptive scheme is updated 3392 // also for fixed mode but the updated threshold is not utilized. 3393 // 3394 const uint16_t thresholdMS = 3395 (_playBufType == AudioDeviceModule::kAdaptiveBufferSize) ? _playBufDelay : _playBufDelayFixed; 3396 3397 if (remTimeMS < thresholdMS + 9) 3398 { 3399 _dTcheckPlayBufDelay = 5; 3400 3401 if (remTimeMS == 0) 3402 { 3403 WEBRTC_TRACE(kTraceInfo, kTraceUtility, _id, "playout buffer is empty => we must adapt..."); 3404 if (_waitCounter > 30) 3405 { 3406 _erZeroCounter++; 3407 if (_erZeroCounter == 2) 3408 { 3409 _playBufDelay += 15; 3410 _minPlayBufDelay += 20; 3411 _waitCounter = 50; 3412 WEBRTC_TRACE(kTraceDebug, kTraceUtility, _id, "New playout states (er=0,erZero=2): minPlayBufDelay=%u, playBufDelay=%u", _minPlayBufDelay, _playBufDelay); 3413 } 3414 else if (_erZeroCounter == 3) 3415 { 3416 _erZeroCounter = 0; 3417 _playBufDelay += 30; 3418 _minPlayBufDelay += 25; 3419 _waitCounter = 0; 3420 WEBRTC_TRACE(kTraceDebug, kTraceUtility, _id, "New playout states (er=0, erZero=3): minPlayBufDelay=%u, playBufDelay=%u", _minPlayBufDelay, _playBufDelay); 3421 } 3422 else 3423 { 3424 _minPlayBufDelay += 10; 3425 _playBufDelay += 15; 3426 _waitCounter = 50; 3427 WEBRTC_TRACE(kTraceDebug, kTraceUtility, _id, "New playout states (er=0, erZero=1): minPlayBufDelay=%u, playBufDelay=%u", _minPlayBufDelay, _playBufDelay); 3428 } 3429 } 3430 } 3431 else if (remTimeMS < _minPlayBufDelay) 3432 { 3433 // If there is less than 25 ms of audio in the play out buffer 3434 // increase the buffersize limit value. _waitCounter prevents 3435 // _playBufDelay to be increased every time this function is called. 3436 3437 if (_waitCounter > 30) 3438 { 3439 _playBufDelay += 10; 3440 if (_intro == 0) 3441 _waitCounter = 0; 3442 WEBRTC_TRACE(kTraceDebug, kTraceUtility, _id, "Playout threshold is increased: playBufDelay=%u", _playBufDelay); 3443 } 3444 } 3445 else if (remTimeMS < thresholdMS - 9) 3446 { 3447 _erZeroCounter = 0; 3448 } 3449 else 3450 { 3451 _erZeroCounter = 0; 3452 _dTcheckPlayBufDelay = 10; 3453 } 3454 3455 QueryPerformanceCounter(&t1); // measure time: START 3456 3457 // Ask for new PCM data to be played out using the AudioDeviceBuffer. 3458 // Ensure that this callback is executed without taking the audio-thread lock. 3459 // 3460 UnLock(); 3461 uint32_t nSamples = _ptrAudioBuffer->RequestPlayoutData(PLAY_BUF_SIZE_IN_SAMPLES); 3462 Lock(); 3463 3464 if (OutputSanityCheckAfterUnlockedPeriod() == -1) 3465 { 3466 // assert(false); 3467 return -1; 3468 } 3469 3470 nSamples = _ptrAudioBuffer->GetPlayoutData(playBuffer); 3471 if (nSamples != PLAY_BUF_SIZE_IN_SAMPLES) 3472 { 3473 WEBRTC_TRACE(kTraceError, kTraceUtility, _id, "invalid number of output samples(%d)", nSamples); 3474 } 3475 3476 QueryPerformanceCounter(&t2); // measure time: STOP 3477 consumedTime = (int)(t2.QuadPart - t1.QuadPart); 3478 3479 Write(playBuffer, PLAY_BUF_SIZE_IN_SAMPLES); 3480 3481 } // if (er < thresholdMS + 9) 3482 else if (thresholdMS + 9 < remTimeMS ) 3483 { 3484 _erZeroCounter = 0; 3485 _dTcheckPlayBufDelay = 2; // check buffer more often 3486 WEBRTC_TRACE(kTraceDebug, kTraceUtility, _id, "Need to check playout buffer more often (dT=%u, remTimeMS=%u)", _dTcheckPlayBufDelay, remTimeMS); 3487 } 3488 3489 // If the buffersize has been stable for 20 seconds try to decrease the buffer size 3490 if (_waitCounter > 2000) 3491 { 3492 _intro = 0; 3493 _playBufDelay--; 3494 _waitCounter = 1990; 3495 WEBRTC_TRACE(kTraceDebug, kTraceUtility, _id, "Playout threshold is decreased: playBufDelay=%u", _playBufDelay); 3496 } 3497 3498 // Limit the minimum sound card (playback) delay to adaptive minimum delay 3499 if (_playBufDelay < _minPlayBufDelay) 3500 { 3501 _playBufDelay = _minPlayBufDelay; 3502 WEBRTC_TRACE(kTraceDebug, kTraceUtility, _id, "Playout threshold is limited to %u", _minPlayBufDelay); 3503 } 3504 3505 // Limit the maximum sound card (playback) delay to 150 ms 3506 if (_playBufDelay > 150) 3507 { 3508 _playBufDelay = 150; 3509 WEBRTC_TRACE(kTraceDebug, kTraceUtility, _id, "Playout threshold is limited to %d", _playBufDelay); 3510 } 3511 3512 // Upper limit of the minimum sound card (playback) delay to 65 ms. 3513 // Deactivated during "useHeader mode" (_useHeader > 0). 3514 if (_minPlayBufDelay > _MAX_minBuffer && 3515 (_useHeader == 0)) 3516 { 3517 _minPlayBufDelay = _MAX_minBuffer; 3518 WEBRTC_TRACE(kTraceDebug, kTraceUtility, _id, "Minimum playout threshold is limited to %d", _MAX_minBuffer); 3519 } 3520 3521 return (0); 3522 } 3523 3524 // ---------------------------------------------------------------------------- 3525 // Write 3526 // ---------------------------------------------------------------------------- 3527 3528 int32_t AudioDeviceWindowsWave::Write(int8_t* data, uint16_t nSamples) 3529 { 3530 if (_hWaveOut == NULL) 3531 { 3532 return -1; 3533 } 3534 3535 if (_playIsInitialized) 3536 { 3537 MMRESULT res; 3538 3539 const uint16_t bufCount(_playBufCount); 3540 3541 // Place data in the memory associated with _waveHeaderOut[bufCount] 3542 // 3543 const int16_t nBytes = (2*_playChannels)*nSamples; 3544 memcpy(&_playBuffer[bufCount][0], &data[0], nBytes); 3545 3546 // Send a data block to the given waveform-audio output device. 3547 // 3548 // When the buffer is finished, the WHDR_DONE bit is set in the dwFlags 3549 // member of the WAVEHDR structure. The buffer must be prepared with the 3550 // waveOutPrepareHeader function before it is passed to waveOutWrite. 3551 // Unless the device is paused by calling the waveOutPause function, 3552 // playback begins when the first data block is sent to the device. 3553 // 3554 res = waveOutWrite(_hWaveOut, &_waveHeaderOut[bufCount], sizeof(_waveHeaderOut[bufCount])); 3555 if (MMSYSERR_NOERROR != res) 3556 { 3557 WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "waveOutWrite(%d) failed (err=%d)", bufCount, res); 3558 TraceWaveOutError(res); 3559 3560 _writeErrors++; 3561 if (_writeErrors > 10) 3562 { 3563 if (_playError == 1) 3564 { 3565 WEBRTC_TRACE(kTraceWarning, kTraceUtility, _id, "pending playout error exists"); 3566 } 3567 _playError = 1; // triggers callback from module process thread 3568 WEBRTC_TRACE(kTraceError, kTraceUtility, _id, "kPlayoutError message posted: _writeErrors=%u", _writeErrors); 3569 } 3570 3571 return -1; 3572 } 3573 3574 _playBufCount = (_playBufCount+1) % N_BUFFERS_OUT; // increase buffer counter modulo size of total buffer 3575 _writtenSamples += nSamples; // each sample is 2 or 4 bytes 3576 _writeErrors = 0; 3577 } 3578 3579 return 0; 3580 } 3581 3582 // ---------------------------------------------------------------------------- 3583 // GetClockDrift 3584 // ---------------------------------------------------------------------------- 3585 3586 int32_t AudioDeviceWindowsWave::GetClockDrift(const uint32_t plSamp, const uint32_t rcSamp) 3587 { 3588 int drift = 0; 3589 unsigned int plSampDiff = 0, rcSampDiff = 0; 3590 3591 if (plSamp >= _plSampOld) 3592 { 3593 plSampDiff = plSamp - _plSampOld; 3594 } 3595 else 3596 { 3597 // Wrap 3598 int i = 31; 3599 while(_plSampOld <= (unsigned int)POW2(i)) 3600 { 3601 i--; 3602 } 3603 3604 // Add the amount remaining prior to wrapping 3605 plSampDiff = plSamp + POW2(i + 1) - _plSampOld; 3606 } 3607 3608 if (rcSamp >= _rcSampOld) 3609 { 3610 rcSampDiff = rcSamp - _rcSampOld; 3611 } 3612 else 3613 { // Wrap 3614 int i = 31; 3615 while(_rcSampOld <= (unsigned int)POW2(i)) 3616 { 3617 i--; 3618 } 3619 3620 rcSampDiff = rcSamp + POW2(i + 1) - _rcSampOld; 3621 } 3622 3623 drift = plSampDiff - rcSampDiff; 3624 3625 _plSampOld = plSamp; 3626 _rcSampOld = rcSamp; 3627 3628 return drift; 3629 } 3630 3631 // ---------------------------------------------------------------------------- 3632 // MonitorRecording 3633 // ---------------------------------------------------------------------------- 3634 3635 int32_t AudioDeviceWindowsWave::MonitorRecording(const uint32_t time) 3636 { 3637 const uint16_t bytesPerSample = 2*_recChannels; 3638 const uint32_t nRecordedSamples = _recordedBytes/bytesPerSample; 3639 3640 if (nRecordedSamples > 5*N_REC_SAMPLES_PER_SEC) 3641 { 3642 // 5 seconds of audio has been recorded... 3643 if ((time - _prevRecByteCheckTime) > 5700) 3644 { 3645 // ...and it was more than 5.7 seconds since we last did this check <=> 3646 // we have not been able to record 5 seconds of audio in 5.7 seconds, 3647 // hence a problem should be reported. 3648 // This problem can be related to USB overload. 3649 // 3650 if (_recWarning == 1) 3651 { 3652 WEBRTC_TRACE(kTraceWarning, kTraceUtility, _id, "pending recording warning exists"); 3653 } 3654 _recWarning = 1; // triggers callback from module process thread 3655 WEBRTC_TRACE(kTraceWarning, kTraceUtility, _id, "kRecordingWarning message posted: time-_prevRecByteCheckTime=%d", time - _prevRecByteCheckTime); 3656 } 3657 3658 _recordedBytes = 0; // restart "check again when 5 seconds are recorded" 3659 _prevRecByteCheckTime = time; // reset timer to measure time for recording of 5 seconds 3660 } 3661 3662 if ((time - _prevRecByteCheckTime) > 8000) 3663 { 3664 // It has been more than 8 seconds since we able to confirm that 5 seconds of 3665 // audio was recorded, hence we have not been able to record 5 seconds in 3666 // 8 seconds => the complete recording process is most likely dead. 3667 // 3668 if (_recError == 1) 3669 { 3670 WEBRTC_TRACE(kTraceWarning, kTraceUtility, _id, "pending recording error exists"); 3671 } 3672 _recError = 1; // triggers callback from module process thread 3673 WEBRTC_TRACE(kTraceError, kTraceUtility, _id, "kRecordingError message posted: time-_prevRecByteCheckTime=%d", time - _prevRecByteCheckTime); 3674 3675 _prevRecByteCheckTime = time; 3676 } 3677 3678 return 0; 3679 } 3680 3681 // ---------------------------------------------------------------------------- 3682 // MonitorRecording 3683 // 3684 // Restart timer if needed (they seem to be messed up after a hibernate). 3685 // ---------------------------------------------------------------------------- 3686 3687 int32_t AudioDeviceWindowsWave::RestartTimerIfNeeded(const uint32_t time) 3688 { 3689 const uint32_t diffMS = time - _prevTimerCheckTime; 3690 _prevTimerCheckTime = time; 3691 3692 if (diffMS > 7) 3693 { 3694 // one timer-issue detected... 3695 _timerFaults++; 3696 if (_timerFaults > 5 && _timerRestartAttempts < 2) 3697 { 3698 // Reinitialize timer event if event fails to execute at least every 5ms. 3699 // On some machines it helps and the timer starts working as it should again; 3700 // however, not all machines (we have seen issues on e.g. IBM T60). 3701 // Therefore, the scheme below ensures that we do max 2 attempts to restart the timer. 3702 // For the cases where restart does not do the trick, we compensate for the reduced 3703 // resolution on both the recording and playout sides. 3704 WEBRTC_TRACE(kTraceWarning, kTraceUtility, _id, " timer issue detected => timer is restarted"); 3705 _timeEvent.StopTimer(); 3706 _timeEvent.StartTimer(true, TIMER_PERIOD_MS); 3707 // make sure timer gets time to start up and we don't kill/start timer serveral times over and over again 3708 _timerFaults = -20; 3709 _timerRestartAttempts++; 3710 } 3711 } 3712 else 3713 { 3714 // restart timer-check scheme since we are OK 3715 _timerFaults = 0; 3716 _timerRestartAttempts = 0; 3717 } 3718 3719 return 0; 3720 } 3721 3722 3723 bool AudioDeviceWindowsWave::KeyPressed() const{ 3724 3725 int key_down = 0; 3726 for (int key = VK_SPACE; key < VK_NUMLOCK; key++) { 3727 short res = GetAsyncKeyState(key); 3728 key_down |= res & 0x1; // Get the LSB 3729 } 3730 return (key_down > 0); 3731 } 3732 } // namespace webrtc 3733