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