| Index: webrtc/modules/audio_device/win/audio_device_wave_win.cc | 
| diff --git a/webrtc/modules/audio_device/win/audio_device_wave_win.cc b/webrtc/modules/audio_device/win/audio_device_wave_win.cc | 
| deleted file mode 100644 | 
| index 7874575e7ce166259801f1aa34bfe8f603d9ff9d..0000000000000000000000000000000000000000 | 
| --- a/webrtc/modules/audio_device/win/audio_device_wave_win.cc | 
| +++ /dev/null | 
| @@ -1,3723 +0,0 @@ | 
| -/* | 
| - *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 
| - * | 
| - *  Use of this source code is governed by a BSD-style license | 
| - *  that can be found in the LICENSE file in the root of the source | 
| - *  tree. An additional intellectual property rights grant can be found | 
| - *  in the file PATENTS.  All contributing project authors may | 
| - *  be found in the AUTHORS file in the root of the source tree. | 
| - */ | 
| - | 
| -#include "webrtc/base/logging.h" | 
| -#include "webrtc/base/timeutils.h" | 
| -#include "webrtc/modules/audio_device/audio_device_config.h" | 
| -#include "webrtc/modules/audio_device/win/audio_device_wave_win.h" | 
| - | 
| -#include "webrtc/system_wrappers/include/event_wrapper.h" | 
| -#include "webrtc/system_wrappers/include/trace.h" | 
| - | 
| -#include <windows.h> | 
| -#include <objbase.h>    // CoTaskMemAlloc, CoTaskMemFree | 
| -#include <strsafe.h>    // StringCchCopy(), StringCchCat(), StringCchPrintf() | 
| -#include <assert.h> | 
| - | 
| -// Avoids the need of Windows 7 SDK | 
| -#ifndef WAVE_MAPPED_DEFAULT_COMMUNICATION_DEVICE | 
| -#define WAVE_MAPPED_DEFAULT_COMMUNICATION_DEVICE   0x0010 | 
| -#endif | 
| - | 
| -// Supported in Windows Vista and Windows 7. | 
| -// http://msdn.microsoft.com/en-us/library/dd370819(v=VS.85).aspx | 
| -// Taken from Mmddk.h. | 
| -#define DRV_RESERVED                      0x0800 | 
| -#define DRV_QUERYFUNCTIONINSTANCEID       (DRV_RESERVED + 17) | 
| -#define DRV_QUERYFUNCTIONINSTANCEIDSIZE   (DRV_RESERVED + 18) | 
| - | 
| -#define POW2(A) (2 << ((A) - 1)) | 
| - | 
| -namespace webrtc { | 
| - | 
| -// ============================================================================ | 
| -//                            Construction & Destruction | 
| -// ============================================================================ | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  AudioDeviceWindowsWave - ctor | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -AudioDeviceWindowsWave::AudioDeviceWindowsWave(const int32_t id) : | 
| -    _ptrAudioBuffer(NULL), | 
| -    _critSect(*CriticalSectionWrapper::CreateCriticalSection()), | 
| -    _timeEvent(*EventTimerWrapper::Create()), | 
| -    _recStartEvent(*EventWrapper::Create()), | 
| -    _playStartEvent(*EventWrapper::Create()), | 
| -    _hGetCaptureVolumeThread(NULL), | 
| -    _hShutdownGetVolumeEvent(NULL), | 
| -    _hSetCaptureVolumeThread(NULL), | 
| -    _hShutdownSetVolumeEvent(NULL), | 
| -    _hSetCaptureVolumeEvent(NULL), | 
| -    _critSectCb(*CriticalSectionWrapper::CreateCriticalSection()), | 
| -    _id(id), | 
| -    _mixerManager(id), | 
| -    _usingInputDeviceIndex(false), | 
| -    _usingOutputDeviceIndex(false), | 
| -    _inputDevice(AudioDeviceModule::kDefaultDevice), | 
| -    _outputDevice(AudioDeviceModule::kDefaultDevice), | 
| -    _inputDeviceIndex(0), | 
| -    _outputDeviceIndex(0), | 
| -    _inputDeviceIsSpecified(false), | 
| -    _outputDeviceIsSpecified(false), | 
| -    _initialized(false), | 
| -    _recIsInitialized(false), | 
| -    _playIsInitialized(false), | 
| -    _recording(false), | 
| -    _playing(false), | 
| -    _startRec(false), | 
| -    _stopRec(false), | 
| -    _startPlay(false), | 
| -    _stopPlay(false), | 
| -    _AGC(false), | 
| -    _hWaveIn(NULL), | 
| -    _hWaveOut(NULL), | 
| -    _recChannels(N_REC_CHANNELS), | 
| -    _playChannels(N_PLAY_CHANNELS), | 
| -    _recBufCount(0), | 
| -    _recPutBackDelay(0), | 
| -    _recDelayCount(0), | 
| -    _playBufCount(0), | 
| -    _prevPlayTime(0), | 
| -    _prevRecTime(0), | 
| -    _prevTimerCheckTime(0), | 
| -    _timesdwBytes(0), | 
| -    _timerFaults(0), | 
| -    _timerRestartAttempts(0), | 
| -    _no_of_msecleft_warnings(0), | 
| -    _MAX_minBuffer(65), | 
| -    _useHeader(0), | 
| -    _dTcheckPlayBufDelay(10), | 
| -    _playBufDelay(80), | 
| -    _playBufDelayFixed(80), | 
| -    _minPlayBufDelay(20), | 
| -    _avgCPULoad(0), | 
| -    _sndCardPlayDelay(0), | 
| -    _sndCardRecDelay(0), | 
| -    _plSampOld(0), | 
| -    _rcSampOld(0), | 
| -    _playBufType(AudioDeviceModule::kAdaptiveBufferSize), | 
| -    _recordedBytes(0), | 
| -    _playWarning(0), | 
| -    _playError(0), | 
| -    _recWarning(0), | 
| -    _recError(0), | 
| -    _newMicLevel(0), | 
| -    _minMicVolume(0), | 
| -    _maxMicVolume(0) | 
| -{ | 
| -    WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, id, "%s created", __FUNCTION__); | 
| - | 
| -    // Initialize value, set to 0 if it fails | 
| -    if (!QueryPerformanceFrequency(&_perfFreq)) | 
| -    { | 
| -        _perfFreq.QuadPart = 0; | 
| -    } | 
| - | 
| -    _hShutdownGetVolumeEvent = CreateEvent(NULL, FALSE, FALSE, NULL); | 
| -    _hShutdownSetVolumeEvent = CreateEvent(NULL, FALSE, FALSE, NULL); | 
| -    _hSetCaptureVolumeEvent = CreateEvent(NULL, FALSE, FALSE, NULL); | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  AudioDeviceWindowsWave - dtor | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -AudioDeviceWindowsWave::~AudioDeviceWindowsWave() | 
| -{ | 
| -    WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s destroyed", __FUNCTION__); | 
| - | 
| -    Terminate(); | 
| - | 
| -    delete &_recStartEvent; | 
| -    delete &_playStartEvent; | 
| -    delete &_timeEvent; | 
| -    delete &_critSect; | 
| -    delete &_critSectCb; | 
| - | 
| -    if (NULL != _hShutdownGetVolumeEvent) | 
| -    { | 
| -        CloseHandle(_hShutdownGetVolumeEvent); | 
| -        _hShutdownGetVolumeEvent = NULL; | 
| -    } | 
| - | 
| -    if (NULL != _hShutdownSetVolumeEvent) | 
| -    { | 
| -        CloseHandle(_hShutdownSetVolumeEvent); | 
| -        _hShutdownSetVolumeEvent = NULL; | 
| -    } | 
| - | 
| -    if (NULL != _hSetCaptureVolumeEvent) | 
| -    { | 
| -        CloseHandle(_hSetCaptureVolumeEvent); | 
| -        _hSetCaptureVolumeEvent = NULL; | 
| -    } | 
| -} | 
| - | 
| -// ============================================================================ | 
| -//                                     API | 
| -// ============================================================================ | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  AttachAudioBuffer | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -void AudioDeviceWindowsWave::AttachAudioBuffer(AudioDeviceBuffer* audioBuffer) | 
| -{ | 
| - | 
| -    CriticalSectionScoped lock(&_critSect); | 
| - | 
| -    _ptrAudioBuffer = audioBuffer; | 
| - | 
| -    // inform the AudioBuffer about default settings for this implementation | 
| -    _ptrAudioBuffer->SetRecordingSampleRate(N_REC_SAMPLES_PER_SEC); | 
| -    _ptrAudioBuffer->SetPlayoutSampleRate(N_PLAY_SAMPLES_PER_SEC); | 
| -    _ptrAudioBuffer->SetRecordingChannels(N_REC_CHANNELS); | 
| -    _ptrAudioBuffer->SetPlayoutChannels(N_PLAY_CHANNELS); | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  ActiveAudioLayer | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::ActiveAudioLayer(AudioDeviceModule::AudioLayer& audioLayer) const | 
| -{ | 
| -    audioLayer = AudioDeviceModule::kWindowsWaveAudio; | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  Init | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -AudioDeviceGeneric::InitStatus AudioDeviceWindowsWave::Init() { | 
| -  CriticalSectionScoped lock(&_critSect); | 
| - | 
| -  if (_initialized) { | 
| -    return InitStatus::OK; | 
| -  } | 
| - | 
| -  const uint32_t nowTime(rtc::TimeMillis()); | 
| - | 
| -  _recordedBytes = 0; | 
| -  _prevRecByteCheckTime = nowTime; | 
| -  _prevRecTime = nowTime; | 
| -  _prevPlayTime = nowTime; | 
| -  _prevTimerCheckTime = nowTime; | 
| - | 
| -  _playWarning = 0; | 
| -  _playError = 0; | 
| -  _recWarning = 0; | 
| -  _recError = 0; | 
| - | 
| -  _mixerManager.EnumerateAll(); | 
| - | 
| -  if (_ptrThread) { | 
| -    // thread is already created and active | 
| -    return InitStatus::OK; | 
| -  } | 
| - | 
| -  const char* threadName = "webrtc_audio_module_thread"; | 
| -  _ptrThread.reset(new rtc::PlatformThread(ThreadFunc, this, threadName)); | 
| -  _ptrThread->Start(); | 
| -  _ptrThread->SetPriority(rtc::kRealtimePriority); | 
| - | 
| -  const bool periodic(true); | 
| -  if (!_timeEvent.StartTimer(periodic, TIMER_PERIOD_MS)) { | 
| -    LOG(LS_ERROR) << "failed to start the timer event"; | 
| -    _ptrThread->Stop(); | 
| -    _ptrThread.reset(); | 
| -    return InitStatus::OTHER_ERROR; | 
| -  } | 
| -  WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, | 
| -               "periodic timer (dT=%d) is now active", TIMER_PERIOD_MS); | 
| - | 
| -  _hGetCaptureVolumeThread = | 
| -      CreateThread(NULL, 0, GetCaptureVolumeThread, this, 0, NULL); | 
| -  if (_hGetCaptureVolumeThread == NULL) { | 
| -    LOG(LS_ERROR) << "  failed to create the volume getter thread"; | 
| -    return InitStatus::OTHER_ERROR; | 
| -  } | 
| - | 
| -  SetThreadPriority(_hGetCaptureVolumeThread, THREAD_PRIORITY_NORMAL); | 
| - | 
| -  _hSetCaptureVolumeThread = | 
| -      CreateThread(NULL, 0, SetCaptureVolumeThread, this, 0, NULL); | 
| -  if (_hSetCaptureVolumeThread == NULL) { | 
| -    LOG(LS_ERROR) << "  failed to create the volume setter thread"; | 
| -    return InitStatus::OTHER_ERROR; | 
| -  } | 
| - | 
| -  SetThreadPriority(_hSetCaptureVolumeThread, THREAD_PRIORITY_NORMAL); | 
| - | 
| -  _initialized = true; | 
| - | 
| -  return InitStatus::OK; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  Terminate | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::Terminate() | 
| -{ | 
| - | 
| -    if (!_initialized) | 
| -    { | 
| -        return 0; | 
| -    } | 
| - | 
| -    _critSect.Enter(); | 
| - | 
| -    _mixerManager.Close(); | 
| - | 
| -    if (_ptrThread) | 
| -    { | 
| -        rtc::PlatformThread* tmpThread = _ptrThread.release(); | 
| -        _critSect.Leave(); | 
| - | 
| -        _timeEvent.Set(); | 
| - | 
| -        tmpThread->Stop(); | 
| -        delete tmpThread; | 
| -    } | 
| -    else | 
| -    { | 
| -        _critSect.Leave(); | 
| -    } | 
| - | 
| -    _critSect.Enter(); | 
| -    SetEvent(_hShutdownGetVolumeEvent); | 
| -    _critSect.Leave(); | 
| -    int32_t ret = WaitForSingleObject(_hGetCaptureVolumeThread, 2000); | 
| -    if (ret != WAIT_OBJECT_0) | 
| -    { | 
| -        // the thread did not stop as it should | 
| -        WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, | 
| -            "  failed to close down volume getter thread"); | 
| -        CloseHandle(_hGetCaptureVolumeThread); | 
| -        _hGetCaptureVolumeThread = NULL; | 
| -        return -1; | 
| -    } | 
| -    _critSect.Enter(); | 
| -    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, | 
| -        "  volume getter thread is now closed"); | 
| - | 
| -    SetEvent(_hShutdownSetVolumeEvent); | 
| -    _critSect.Leave(); | 
| -    ret = WaitForSingleObject(_hSetCaptureVolumeThread, 2000); | 
| -    if (ret != WAIT_OBJECT_0) | 
| -    { | 
| -        // the thread did not stop as it should | 
| -        WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, | 
| -            "  failed to close down volume setter thread"); | 
| -        CloseHandle(_hSetCaptureVolumeThread); | 
| -        _hSetCaptureVolumeThread = NULL; | 
| -        return -1; | 
| -    } | 
| -    _critSect.Enter(); | 
| -    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, | 
| -        "  volume setter thread is now closed"); | 
| - | 
| -    CloseHandle(_hGetCaptureVolumeThread); | 
| -    _hGetCaptureVolumeThread = NULL; | 
| - | 
| -    CloseHandle(_hSetCaptureVolumeThread); | 
| -    _hSetCaptureVolumeThread = NULL; | 
| - | 
| -    _critSect.Leave(); | 
| - | 
| -    _timeEvent.StopTimer(); | 
| - | 
| -    _initialized = false; | 
| -    _outputDeviceIsSpecified = false; | 
| -    _inputDeviceIsSpecified = false; | 
| - | 
| -    return 0; | 
| -} | 
| - | 
| - | 
| -DWORD WINAPI AudioDeviceWindowsWave::GetCaptureVolumeThread(LPVOID context) | 
| -{ | 
| -    return(((AudioDeviceWindowsWave*)context)->DoGetCaptureVolumeThread()); | 
| -} | 
| - | 
| -DWORD WINAPI AudioDeviceWindowsWave::SetCaptureVolumeThread(LPVOID context) | 
| -{ | 
| -    return(((AudioDeviceWindowsWave*)context)->DoSetCaptureVolumeThread()); | 
| -} | 
| - | 
| -DWORD AudioDeviceWindowsWave::DoGetCaptureVolumeThread() | 
| -{ | 
| -    HANDLE waitObject = _hShutdownGetVolumeEvent; | 
| - | 
| -    while (1) | 
| -    { | 
| -        DWORD waitResult = WaitForSingleObject(waitObject, | 
| -                                               GET_MIC_VOLUME_INTERVAL_MS); | 
| -        switch (waitResult) | 
| -        { | 
| -            case WAIT_OBJECT_0: // _hShutdownGetVolumeEvent | 
| -                return 0; | 
| -            case WAIT_TIMEOUT:	// timeout notification | 
| -                break; | 
| -            default:            // unexpected error | 
| -                WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, | 
| -                    "  unknown wait termination on get volume thread"); | 
| -                return 1; | 
| -        } | 
| - | 
| -        if (AGC()) | 
| -        { | 
| -            uint32_t currentMicLevel = 0; | 
| -            if (MicrophoneVolume(currentMicLevel) == 0) | 
| -            { | 
| -                // This doesn't set the system volume, just stores it. | 
| -                _critSect.Enter(); | 
| -                if (_ptrAudioBuffer) | 
| -                { | 
| -                    _ptrAudioBuffer->SetCurrentMicLevel(currentMicLevel); | 
| -                } | 
| -                _critSect.Leave(); | 
| -            } | 
| -        } | 
| -    } | 
| -} | 
| - | 
| -DWORD AudioDeviceWindowsWave::DoSetCaptureVolumeThread() | 
| -{ | 
| -    HANDLE waitArray[2] = {_hShutdownSetVolumeEvent, _hSetCaptureVolumeEvent}; | 
| - | 
| -    while (1) | 
| -    { | 
| -        DWORD waitResult = WaitForMultipleObjects(2, waitArray, FALSE, INFINITE); | 
| -        switch (waitResult) | 
| -        { | 
| -            case WAIT_OBJECT_0:     // _hShutdownSetVolumeEvent | 
| -                return 0; | 
| -            case WAIT_OBJECT_0 + 1: // _hSetCaptureVolumeEvent | 
| -                break; | 
| -            default:                // unexpected error | 
| -                WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, | 
| -                    "  unknown wait termination on set volume thread"); | 
| -                return 1; | 
| -        } | 
| - | 
| -        _critSect.Enter(); | 
| -        uint32_t newMicLevel = _newMicLevel; | 
| -        _critSect.Leave(); | 
| - | 
| -        if (SetMicrophoneVolume(newMicLevel) == -1) | 
| -        { | 
| -            WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, | 
| -                "  the required modification of the microphone volume failed"); | 
| -        } | 
| -    } | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  Initialized | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -bool AudioDeviceWindowsWave::Initialized() const | 
| -{ | 
| -    return (_initialized); | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  InitSpeaker | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::InitSpeaker() | 
| -{ | 
| - | 
| -    CriticalSectionScoped lock(&_critSect); | 
| - | 
| -    if (_playing) | 
| -    { | 
| -        return -1; | 
| -    } | 
| - | 
| -    if (_mixerManager.EnumerateSpeakers() == -1) | 
| -    { | 
| -        // failed to locate any valid/controllable speaker | 
| -        return -1; | 
| -    } | 
| - | 
| -    if (IsUsingOutputDeviceIndex()) | 
| -    { | 
| -        if (_mixerManager.OpenSpeaker(OutputDeviceIndex()) == -1) | 
| -        { | 
| -            return -1; | 
| -        } | 
| -    } | 
| -    else | 
| -    { | 
| -        if (_mixerManager.OpenSpeaker(OutputDevice()) == -1) | 
| -        { | 
| -            return -1; | 
| -        } | 
| -    } | 
| - | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  InitMicrophone | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::InitMicrophone() | 
| -{ | 
| - | 
| -    CriticalSectionScoped lock(&_critSect); | 
| - | 
| -    if (_recording) | 
| -    { | 
| -        return -1; | 
| -    } | 
| - | 
| -    if (_mixerManager.EnumerateMicrophones() == -1) | 
| -    { | 
| -        // failed to locate any valid/controllable microphone | 
| -        return -1; | 
| -    } | 
| - | 
| -    if (IsUsingInputDeviceIndex()) | 
| -    { | 
| -        if (_mixerManager.OpenMicrophone(InputDeviceIndex()) == -1) | 
| -        { | 
| -            return -1; | 
| -        } | 
| -    } | 
| -    else | 
| -    { | 
| -        if (_mixerManager.OpenMicrophone(InputDevice()) == -1) | 
| -        { | 
| -            return -1; | 
| -        } | 
| -    } | 
| - | 
| -    uint32_t maxVol = 0; | 
| -    if (_mixerManager.MaxMicrophoneVolume(maxVol) == -1) | 
| -    { | 
| -        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, | 
| -            "  unable to retrieve max microphone volume"); | 
| -    } | 
| -    _maxMicVolume = maxVol; | 
| - | 
| -    uint32_t minVol = 0; | 
| -    if (_mixerManager.MinMicrophoneVolume(minVol) == -1) | 
| -    { | 
| -        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, | 
| -            "  unable to retrieve min microphone volume"); | 
| -    } | 
| -    _minMicVolume = minVol; | 
| - | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  SpeakerIsInitialized | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -bool AudioDeviceWindowsWave::SpeakerIsInitialized() const | 
| -{ | 
| -    return (_mixerManager.SpeakerIsInitialized()); | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  MicrophoneIsInitialized | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -bool AudioDeviceWindowsWave::MicrophoneIsInitialized() const | 
| -{ | 
| -    return (_mixerManager.MicrophoneIsInitialized()); | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  SpeakerVolumeIsAvailable | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::SpeakerVolumeIsAvailable(bool& available) | 
| -{ | 
| - | 
| -    bool isAvailable(false); | 
| - | 
| -    // Enumerate all avaliable speakers and make an attempt to open up the | 
| -    // output mixer corresponding to the currently selected output device. | 
| -    // | 
| -    if (InitSpeaker() == -1) | 
| -    { | 
| -        // failed to find a valid speaker | 
| -        available = false; | 
| -        return 0; | 
| -    } | 
| - | 
| -    // Check if the selected speaker has a volume control | 
| -    // | 
| -    _mixerManager.SpeakerVolumeIsAvailable(isAvailable); | 
| -    available = isAvailable; | 
| - | 
| -    // Close the initialized output mixer | 
| -    // | 
| -    _mixerManager.CloseSpeaker(); | 
| - | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  SetSpeakerVolume | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::SetSpeakerVolume(uint32_t volume) | 
| -{ | 
| - | 
| -    return (_mixerManager.SetSpeakerVolume(volume)); | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  SpeakerVolume | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::SpeakerVolume(uint32_t& volume) const | 
| -{ | 
| - | 
| -    uint32_t level(0); | 
| - | 
| -    if (_mixerManager.SpeakerVolume(level) == -1) | 
| -    { | 
| -        return -1; | 
| -    } | 
| - | 
| -    volume = level; | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  SetWaveOutVolume | 
| -// | 
| -//    The low-order word contains the left-channel volume setting, and the | 
| -//    high-order word contains the right-channel setting. | 
| -//    A value of 0xFFFF represents full volume, and a value of 0x0000 is silence. | 
| -// | 
| -//    If a device does not support both left and right volume control, | 
| -//    the low-order word of dwVolume specifies the volume level, | 
| -//    and the high-order word is ignored. | 
| -// | 
| -//    Most devices do not support the full 16 bits of volume-level control | 
| -//    and will not use the least-significant bits of the requested volume setting. | 
| -//    For example, if a device supports 4 bits of volume control, the values | 
| -//    0x4000, 0x4FFF, and 0x43BE will all be truncated to 0x4000. | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::SetWaveOutVolume(uint16_t volumeLeft, uint16_t volumeRight) | 
| -{ | 
| - | 
| -    MMRESULT res(0); | 
| -    WAVEOUTCAPS caps; | 
| - | 
| -    CriticalSectionScoped lock(&_critSect); | 
| - | 
| -    if (_hWaveOut == NULL) | 
| -    { | 
| -        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no open playout device exists => using default"); | 
| -    } | 
| - | 
| -    // To determine whether the device supports volume control on both | 
| -    // the left and right channels, use the WAVECAPS_LRVOLUME flag. | 
| -    // | 
| -    res = waveOutGetDevCaps((UINT_PTR)_hWaveOut, &caps, sizeof(WAVEOUTCAPS)); | 
| -    if (MMSYSERR_NOERROR != res) | 
| -    { | 
| -        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveOutGetDevCaps() failed (err=%d)", res); | 
| -        TraceWaveOutError(res); | 
| -    } | 
| -    if (!(caps.dwSupport & WAVECAPS_VOLUME)) | 
| -    { | 
| -        // this device does not support volume control using the waveOutSetVolume API | 
| -        WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "device does not support volume control using the Wave API"); | 
| -        return -1; | 
| -    } | 
| -    if (!(caps.dwSupport & WAVECAPS_LRVOLUME)) | 
| -    { | 
| -        // high-order word (right channel) is ignored | 
| -        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "device does not support volume control on both channels"); | 
| -    } | 
| - | 
| -    DWORD dwVolume(0x00000000); | 
| -    dwVolume = (DWORD)(((volumeRight & 0xFFFF) << 16) | (volumeLeft & 0xFFFF)); | 
| - | 
| -    res = waveOutSetVolume(_hWaveOut, dwVolume); | 
| -    if (MMSYSERR_NOERROR != res) | 
| -    { | 
| -        WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "waveOutSetVolume() failed (err=%d)", res); | 
| -        TraceWaveOutError(res); | 
| -        return -1; | 
| -    } | 
| - | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  WaveOutVolume | 
| -// | 
| -//    The low-order word of this location contains the left-channel volume setting, | 
| -//    and the high-order word contains the right-channel setting. | 
| -//    A value of 0xFFFF (65535) represents full volume, and a value of 0x0000 | 
| -//    is silence. | 
| -// | 
| -//    If a device does not support both left and right volume control, | 
| -//    the low-order word of the specified location contains the mono volume level. | 
| -// | 
| -//    The full 16-bit setting(s) set with the waveOutSetVolume function is returned, | 
| -//    regardless of whether the device supports the full 16 bits of volume-level | 
| -//    control. | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::WaveOutVolume(uint16_t& volumeLeft, uint16_t& volumeRight) const | 
| -{ | 
| - | 
| -    MMRESULT res(0); | 
| -    WAVEOUTCAPS caps; | 
| - | 
| -    CriticalSectionScoped lock(&_critSect); | 
| - | 
| -    if (_hWaveOut == NULL) | 
| -    { | 
| -        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "no open playout device exists => using default"); | 
| -    } | 
| - | 
| -    // To determine whether the device supports volume control on both | 
| -    // the left and right channels, use the WAVECAPS_LRVOLUME flag. | 
| -    // | 
| -    res = waveOutGetDevCaps((UINT_PTR)_hWaveOut, &caps, sizeof(WAVEOUTCAPS)); | 
| -    if (MMSYSERR_NOERROR != res) | 
| -    { | 
| -        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveOutGetDevCaps() failed (err=%d)", res); | 
| -        TraceWaveOutError(res); | 
| -    } | 
| -    if (!(caps.dwSupport & WAVECAPS_VOLUME)) | 
| -    { | 
| -        // this device does not support volume control using the waveOutSetVolume API | 
| -        WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "device does not support volume control using the Wave API"); | 
| -        return -1; | 
| -    } | 
| -    if (!(caps.dwSupport & WAVECAPS_LRVOLUME)) | 
| -    { | 
| -        // high-order word (right channel) is ignored | 
| -        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "device does not support volume control on both channels"); | 
| -    } | 
| - | 
| -    DWORD dwVolume(0x00000000); | 
| - | 
| -    res = waveOutGetVolume(_hWaveOut, &dwVolume); | 
| -    if (MMSYSERR_NOERROR != res) | 
| -    { | 
| -        WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "waveOutGetVolume() failed (err=%d)", res); | 
| -        TraceWaveOutError(res); | 
| -        return -1; | 
| -    } | 
| - | 
| -    WORD wVolumeLeft = LOWORD(dwVolume); | 
| -    WORD wVolumeRight = HIWORD(dwVolume); | 
| - | 
| -    volumeLeft = static_cast<uint16_t> (wVolumeLeft); | 
| -    volumeRight = static_cast<uint16_t> (wVolumeRight); | 
| - | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  MaxSpeakerVolume | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::MaxSpeakerVolume(uint32_t& maxVolume) const | 
| -{ | 
| - | 
| -    uint32_t maxVol(0); | 
| - | 
| -    if (_mixerManager.MaxSpeakerVolume(maxVol) == -1) | 
| -    { | 
| -        return -1; | 
| -    } | 
| - | 
| -    maxVolume = maxVol; | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  MinSpeakerVolume | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::MinSpeakerVolume(uint32_t& minVolume) const | 
| -{ | 
| - | 
| -    uint32_t minVol(0); | 
| - | 
| -    if (_mixerManager.MinSpeakerVolume(minVol) == -1) | 
| -    { | 
| -        return -1; | 
| -    } | 
| - | 
| -    minVolume = minVol; | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  SpeakerVolumeStepSize | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::SpeakerVolumeStepSize(uint16_t& stepSize) const | 
| -{ | 
| - | 
| -    uint16_t delta(0); | 
| - | 
| -    if (_mixerManager.SpeakerVolumeStepSize(delta) == -1) | 
| -    { | 
| -        return -1; | 
| -    } | 
| - | 
| -    stepSize = delta; | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  SpeakerMuteIsAvailable | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::SpeakerMuteIsAvailable(bool& available) | 
| -{ | 
| - | 
| -    bool isAvailable(false); | 
| - | 
| -    // Enumerate all avaliable speakers and make an attempt to open up the | 
| -    // output mixer corresponding to the currently selected output device. | 
| -    // | 
| -    if (InitSpeaker() == -1) | 
| -    { | 
| -        // If we end up here it means that the selected speaker has no volume | 
| -        // control, hence it is safe to state that there is no mute control | 
| -        // already at this stage. | 
| -        available = false; | 
| -        return 0; | 
| -    } | 
| - | 
| -    // Check if the selected speaker has a mute control | 
| -    // | 
| -    _mixerManager.SpeakerMuteIsAvailable(isAvailable); | 
| -    available = isAvailable; | 
| - | 
| -    // Close the initialized output mixer | 
| -    // | 
| -    _mixerManager.CloseSpeaker(); | 
| - | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  SetSpeakerMute | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::SetSpeakerMute(bool enable) | 
| -{ | 
| -    return (_mixerManager.SetSpeakerMute(enable)); | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  SpeakerMute | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::SpeakerMute(bool& enabled) const | 
| -{ | 
| - | 
| -    bool muted(0); | 
| - | 
| -    if (_mixerManager.SpeakerMute(muted) == -1) | 
| -    { | 
| -        return -1; | 
| -    } | 
| - | 
| -    enabled = muted; | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  MicrophoneMuteIsAvailable | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::MicrophoneMuteIsAvailable(bool& available) | 
| -{ | 
| - | 
| -    bool isAvailable(false); | 
| - | 
| -    // Enumerate all avaliable microphones and make an attempt to open up the | 
| -    // input mixer corresponding to the currently selected input device. | 
| -    // | 
| -    if (InitMicrophone() == -1) | 
| -    { | 
| -        // If we end up here it means that the selected microphone has no volume | 
| -        // control, hence it is safe to state that there is no boost control | 
| -        // already at this stage. | 
| -        available = false; | 
| -        return 0; | 
| -    } | 
| - | 
| -    // Check if the selected microphone has a mute control | 
| -    // | 
| -    _mixerManager.MicrophoneMuteIsAvailable(isAvailable); | 
| -    available = isAvailable; | 
| - | 
| -    // Close the initialized input mixer | 
| -    // | 
| -    _mixerManager.CloseMicrophone(); | 
| - | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  SetMicrophoneMute | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::SetMicrophoneMute(bool enable) | 
| -{ | 
| -    return (_mixerManager.SetMicrophoneMute(enable)); | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  MicrophoneMute | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::MicrophoneMute(bool& enabled) const | 
| -{ | 
| - | 
| -    bool muted(0); | 
| - | 
| -    if (_mixerManager.MicrophoneMute(muted) == -1) | 
| -    { | 
| -        return -1; | 
| -    } | 
| - | 
| -    enabled = muted; | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  MicrophoneBoostIsAvailable | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::MicrophoneBoostIsAvailable(bool& available) | 
| -{ | 
| - | 
| -    bool isAvailable(false); | 
| - | 
| -    // Enumerate all avaliable microphones and make an attempt to open up the | 
| -    // input mixer corresponding to the currently selected input device. | 
| -    // | 
| -    if (InitMicrophone() == -1) | 
| -    { | 
| -        // If we end up here it means that the selected microphone has no volume | 
| -        // control, hence it is safe to state that there is no boost control | 
| -        // already at this stage. | 
| -        available = false; | 
| -        return 0; | 
| -    } | 
| - | 
| -    // Check if the selected microphone has a boost control | 
| -    // | 
| -    _mixerManager.MicrophoneBoostIsAvailable(isAvailable); | 
| -    available = isAvailable; | 
| - | 
| -    // Close the initialized input mixer | 
| -    // | 
| -    _mixerManager.CloseMicrophone(); | 
| - | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  SetMicrophoneBoost | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::SetMicrophoneBoost(bool enable) | 
| -{ | 
| - | 
| -    return (_mixerManager.SetMicrophoneBoost(enable)); | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  MicrophoneBoost | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::MicrophoneBoost(bool& enabled) const | 
| -{ | 
| - | 
| -    bool onOff(0); | 
| - | 
| -    if (_mixerManager.MicrophoneBoost(onOff) == -1) | 
| -    { | 
| -        return -1; | 
| -    } | 
| - | 
| -    enabled = onOff; | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  StereoRecordingIsAvailable | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::StereoRecordingIsAvailable(bool& available) | 
| -{ | 
| -    available = true; | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  SetStereoRecording | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::SetStereoRecording(bool enable) | 
| -{ | 
| - | 
| -    if (enable) | 
| -        _recChannels = 2; | 
| -    else | 
| -        _recChannels = 1; | 
| - | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  StereoRecording | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::StereoRecording(bool& enabled) const | 
| -{ | 
| - | 
| -    if (_recChannels == 2) | 
| -        enabled = true; | 
| -    else | 
| -        enabled = false; | 
| - | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  StereoPlayoutIsAvailable | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::StereoPlayoutIsAvailable(bool& available) | 
| -{ | 
| -    available = true; | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  SetStereoPlayout | 
| -// | 
| -//  Specifies the number of output channels. | 
| -// | 
| -//  NOTE - the setting will only have an effect after InitPlayout has | 
| -//  been called. | 
| -// | 
| -//  16-bit mono: | 
| -// | 
| -//  Each sample is 2 bytes. Sample 1 is followed by samples 2, 3, 4, and so on. | 
| -//  For each sample, the first byte is the low-order byte of channel 0 and the | 
| -//  second byte is the high-order byte of channel 0. | 
| -// | 
| -//  16-bit stereo: | 
| -// | 
| -//  Each sample is 4 bytes. Sample 1 is followed by samples 2, 3, 4, and so on. | 
| -//  For each sample, the first byte is the low-order byte of channel 0 (left channel); | 
| -//  the second byte is the high-order byte of channel 0; the third byte is the | 
| -//  low-order byte of channel 1 (right channel); and the fourth byte is the | 
| -//  high-order byte of channel 1. | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::SetStereoPlayout(bool enable) | 
| -{ | 
| - | 
| -    if (enable) | 
| -        _playChannels = 2; | 
| -    else | 
| -        _playChannels = 1; | 
| - | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  StereoPlayout | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::StereoPlayout(bool& enabled) const | 
| -{ | 
| - | 
| -    if (_playChannels == 2) | 
| -        enabled = true; | 
| -    else | 
| -        enabled = false; | 
| - | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  SetAGC | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::SetAGC(bool enable) | 
| -{ | 
| - | 
| -    _AGC = enable; | 
| - | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  AGC | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -bool AudioDeviceWindowsWave::AGC() const | 
| -{ | 
| -    return _AGC; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  MicrophoneVolumeIsAvailable | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::MicrophoneVolumeIsAvailable(bool& available) | 
| -{ | 
| - | 
| -    bool isAvailable(false); | 
| - | 
| -    // Enumerate all avaliable microphones and make an attempt to open up the | 
| -    // input mixer corresponding to the currently selected output device. | 
| -    // | 
| -    if (InitMicrophone() == -1) | 
| -    { | 
| -        // Failed to find valid microphone | 
| -        available = false; | 
| -        return 0; | 
| -    } | 
| - | 
| -    // Check if the selected microphone has a volume control | 
| -    // | 
| -    _mixerManager.MicrophoneVolumeIsAvailable(isAvailable); | 
| -    available = isAvailable; | 
| - | 
| -    // Close the initialized input mixer | 
| -    // | 
| -    _mixerManager.CloseMicrophone(); | 
| - | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  SetMicrophoneVolume | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::SetMicrophoneVolume(uint32_t volume) | 
| -{ | 
| -    return (_mixerManager.SetMicrophoneVolume(volume)); | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  MicrophoneVolume | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::MicrophoneVolume(uint32_t& volume) const | 
| -{ | 
| -    uint32_t level(0); | 
| - | 
| -    if (_mixerManager.MicrophoneVolume(level) == -1) | 
| -    { | 
| -        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "failed to retrive current microphone level"); | 
| -        return -1; | 
| -    } | 
| - | 
| -    volume = level; | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  MaxMicrophoneVolume | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::MaxMicrophoneVolume(uint32_t& maxVolume) const | 
| -{ | 
| -    // _maxMicVolume can be zero in AudioMixerManager::MaxMicrophoneVolume(): | 
| -    // (1) API GetLineControl() returns failure at querying the max Mic level. | 
| -    // (2) API GetLineControl() returns maxVolume as zero in rare cases. | 
| -    // Both cases show we don't have access to the mixer controls. | 
| -    // We return -1 here to indicate that. | 
| -    if (_maxMicVolume == 0) | 
| -    { | 
| -        return -1; | 
| -    } | 
| - | 
| -    maxVolume = _maxMicVolume;; | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  MinMicrophoneVolume | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::MinMicrophoneVolume(uint32_t& minVolume) const | 
| -{ | 
| -    minVolume = _minMicVolume; | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  MicrophoneVolumeStepSize | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::MicrophoneVolumeStepSize(uint16_t& stepSize) const | 
| -{ | 
| - | 
| -    uint16_t delta(0); | 
| - | 
| -    if (_mixerManager.MicrophoneVolumeStepSize(delta) == -1) | 
| -    { | 
| -        return -1; | 
| -    } | 
| - | 
| -    stepSize = delta; | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  PlayoutDevices | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int16_t AudioDeviceWindowsWave::PlayoutDevices() | 
| -{ | 
| - | 
| -    return (waveOutGetNumDevs()); | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  SetPlayoutDevice I (II) | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::SetPlayoutDevice(uint16_t index) | 
| -{ | 
| - | 
| -    if (_playIsInitialized) | 
| -    { | 
| -        return -1; | 
| -    } | 
| - | 
| -    UINT nDevices = waveOutGetNumDevs(); | 
| -    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "number of availiable waveform-audio output devices is %u", nDevices); | 
| - | 
| -    if (index < 0 || index > (nDevices-1)) | 
| -    { | 
| -        WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "device index is out of range [0,%u]", (nDevices-1)); | 
| -        return -1; | 
| -    } | 
| - | 
| -    _usingOutputDeviceIndex = true; | 
| -    _outputDeviceIndex = index; | 
| -    _outputDeviceIsSpecified = true; | 
| - | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  SetPlayoutDevice II (II) | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::SetPlayoutDevice(AudioDeviceModule::WindowsDeviceType device) | 
| -{ | 
| -    if (_playIsInitialized) | 
| -    { | 
| -        return -1; | 
| -    } | 
| - | 
| -    if (device == AudioDeviceModule::kDefaultDevice) | 
| -    { | 
| -    } | 
| -    else if (device == AudioDeviceModule::kDefaultCommunicationDevice) | 
| -    { | 
| -    } | 
| - | 
| -    _usingOutputDeviceIndex = false; | 
| -    _outputDevice = device; | 
| -    _outputDeviceIsSpecified = true; | 
| - | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  PlayoutDeviceName | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::PlayoutDeviceName( | 
| -    uint16_t index, | 
| -    char name[kAdmMaxDeviceNameSize], | 
| -    char guid[kAdmMaxGuidSize]) | 
| -{ | 
| - | 
| -    uint16_t nDevices(PlayoutDevices()); | 
| - | 
| -    // Special fix for the case when the user asks for the name of the default device. | 
| -    // | 
| -    if (index == (uint16_t)(-1)) | 
| -    { | 
| -        index = 0; | 
| -    } | 
| - | 
| -    if ((index > (nDevices-1)) || (name == NULL)) | 
| -    { | 
| -        return -1; | 
| -    } | 
| - | 
| -    memset(name, 0, kAdmMaxDeviceNameSize); | 
| - | 
| -    if (guid != NULL) | 
| -    { | 
| -        memset(guid, 0, kAdmMaxGuidSize); | 
| -    } | 
| - | 
| -    WAVEOUTCAPSW caps;    // szPname member (product name (NULL terminated) is a WCHAR | 
| -    MMRESULT res; | 
| - | 
| -    res = waveOutGetDevCapsW(index, &caps, sizeof(WAVEOUTCAPSW)); | 
| -    if (res != MMSYSERR_NOERROR) | 
| -    { | 
| -        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveOutGetDevCapsW() failed (err=%d)", res); | 
| -        return -1; | 
| -    } | 
| -    if (WideCharToMultiByte(CP_UTF8, 0, caps.szPname, -1, name, kAdmMaxDeviceNameSize, NULL, NULL) == 0) | 
| -    { | 
| -        WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "WideCharToMultiByte(CP_UTF8) failed with error code %d - 1", GetLastError()); | 
| -    } | 
| - | 
| -    if (guid == NULL) | 
| -    { | 
| -        return 0; | 
| -    } | 
| - | 
| -    // It is possible to get the unique endpoint ID string using the Wave API. | 
| -    // However, it is only supported on Windows Vista and Windows 7. | 
| - | 
| -    size_t cbEndpointId(0); | 
| - | 
| -    // Get the size (including the terminating null) of the endpoint ID string of the waveOut device. | 
| -    // Windows Vista supports the DRV_QUERYFUNCTIONINSTANCEIDSIZE and DRV_QUERYFUNCTIONINSTANCEID messages. | 
| -    res = waveOutMessage((HWAVEOUT)IntToPtr(index), | 
| -                          DRV_QUERYFUNCTIONINSTANCEIDSIZE, | 
| -                         (DWORD_PTR)&cbEndpointId, NULL); | 
| -    if (res != MMSYSERR_NOERROR) | 
| -    { | 
| -        // DRV_QUERYFUNCTIONINSTANCEIDSIZE is not supported <=> earlier version of Windows than Vista | 
| -        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "waveOutMessage(DRV_QUERYFUNCTIONINSTANCEIDSIZE) failed (err=%d)", res); | 
| -        TraceWaveOutError(res); | 
| -        // Best we can do is to copy the friendly name and use it as guid | 
| -        if (WideCharToMultiByte(CP_UTF8, 0, caps.szPname, -1, guid, kAdmMaxGuidSize, NULL, NULL) == 0) | 
| -        { | 
| -            WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "WideCharToMultiByte(CP_UTF8) failed with error code %d - 2", GetLastError()); | 
| -        } | 
| -        return 0; | 
| -    } | 
| - | 
| -    // waveOutMessage(DRV_QUERYFUNCTIONINSTANCEIDSIZE) worked => we are on a Vista or Windows 7 device | 
| - | 
| -    WCHAR *pstrEndpointId = NULL; | 
| -    pstrEndpointId = (WCHAR*)CoTaskMemAlloc(cbEndpointId); | 
| - | 
| -    // Get the endpoint ID string for this waveOut device. | 
| -    res = waveOutMessage((HWAVEOUT)IntToPtr(index), | 
| -                          DRV_QUERYFUNCTIONINSTANCEID, | 
| -                         (DWORD_PTR)pstrEndpointId, | 
| -                          cbEndpointId); | 
| -    if (res != MMSYSERR_NOERROR) | 
| -    { | 
| -        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "waveOutMessage(DRV_QUERYFUNCTIONINSTANCEID) failed (err=%d)", res); | 
| -        TraceWaveOutError(res); | 
| -        // Best we can do is to copy the friendly name and use it as guid | 
| -        if (WideCharToMultiByte(CP_UTF8, 0, caps.szPname, -1, guid, kAdmMaxGuidSize, NULL, NULL) == 0) | 
| -        { | 
| -            WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "WideCharToMultiByte(CP_UTF8) failed with error code %d - 3", GetLastError()); | 
| -        } | 
| -        CoTaskMemFree(pstrEndpointId); | 
| -        return 0; | 
| -    } | 
| - | 
| -    if (WideCharToMultiByte(CP_UTF8, 0, pstrEndpointId, -1, guid, kAdmMaxGuidSize, NULL, NULL) == 0) | 
| -    { | 
| -        WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "WideCharToMultiByte(CP_UTF8) failed with error code %d - 4", GetLastError()); | 
| -    } | 
| -    CoTaskMemFree(pstrEndpointId); | 
| - | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  RecordingDeviceName | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::RecordingDeviceName( | 
| -    uint16_t index, | 
| -    char name[kAdmMaxDeviceNameSize], | 
| -    char guid[kAdmMaxGuidSize]) | 
| -{ | 
| - | 
| -    uint16_t nDevices(RecordingDevices()); | 
| - | 
| -    // Special fix for the case when the user asks for the name of the default device. | 
| -    // | 
| -    if (index == (uint16_t)(-1)) | 
| -    { | 
| -        index = 0; | 
| -    } | 
| - | 
| -    if ((index > (nDevices-1)) || (name == NULL)) | 
| -    { | 
| -        return -1; | 
| -    } | 
| - | 
| -    memset(name, 0, kAdmMaxDeviceNameSize); | 
| - | 
| -    if (guid != NULL) | 
| -    { | 
| -        memset(guid, 0, kAdmMaxGuidSize); | 
| -    } | 
| - | 
| -    WAVEINCAPSW caps;    // szPname member (product name (NULL terminated) is a WCHAR | 
| -    MMRESULT res; | 
| - | 
| -    res = waveInGetDevCapsW(index, &caps, sizeof(WAVEINCAPSW)); | 
| -    if (res != MMSYSERR_NOERROR) | 
| -    { | 
| -        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveInGetDevCapsW() failed (err=%d)", res); | 
| -        return -1; | 
| -    } | 
| -    if (WideCharToMultiByte(CP_UTF8, 0, caps.szPname, -1, name, kAdmMaxDeviceNameSize, NULL, NULL) == 0) | 
| -    { | 
| -        WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "WideCharToMultiByte(CP_UTF8) failed with error code %d - 1", GetLastError()); | 
| -    } | 
| - | 
| -    if (guid == NULL) | 
| -    { | 
| -        return 0; | 
| -    } | 
| - | 
| -    // It is possible to get the unique endpoint ID string using the Wave API. | 
| -    // However, it is only supported on Windows Vista and Windows 7. | 
| - | 
| -    size_t cbEndpointId(0); | 
| - | 
| -    // Get the size (including the terminating null) of the endpoint ID string of the waveOut device. | 
| -    // Windows Vista supports the DRV_QUERYFUNCTIONINSTANCEIDSIZE and DRV_QUERYFUNCTIONINSTANCEID messages. | 
| -    res = waveInMessage((HWAVEIN)IntToPtr(index), | 
| -                         DRV_QUERYFUNCTIONINSTANCEIDSIZE, | 
| -                        (DWORD_PTR)&cbEndpointId, NULL); | 
| -    if (res != MMSYSERR_NOERROR) | 
| -    { | 
| -        // DRV_QUERYFUNCTIONINSTANCEIDSIZE is not supported <=> earlier version of Windows than Vista | 
| -        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "waveInMessage(DRV_QUERYFUNCTIONINSTANCEIDSIZE) failed (err=%d)", res); | 
| -        TraceWaveInError(res); | 
| -        // Best we can do is to copy the friendly name and use it as guid | 
| -        if (WideCharToMultiByte(CP_UTF8, 0, caps.szPname, -1, guid, kAdmMaxGuidSize, NULL, NULL) == 0) | 
| -        { | 
| -            WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "WideCharToMultiByte(CP_UTF8) failed with error code %d - 2", GetLastError()); | 
| -        } | 
| -        return 0; | 
| -    } | 
| - | 
| -    // waveOutMessage(DRV_QUERYFUNCTIONINSTANCEIDSIZE) worked => we are on a Vista or Windows 7 device | 
| - | 
| -    WCHAR *pstrEndpointId = NULL; | 
| -    pstrEndpointId = (WCHAR*)CoTaskMemAlloc(cbEndpointId); | 
| - | 
| -    // Get the endpoint ID string for this waveOut device. | 
| -    res = waveInMessage((HWAVEIN)IntToPtr(index), | 
| -                          DRV_QUERYFUNCTIONINSTANCEID, | 
| -                         (DWORD_PTR)pstrEndpointId, | 
| -                          cbEndpointId); | 
| -    if (res != MMSYSERR_NOERROR) | 
| -    { | 
| -        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "waveInMessage(DRV_QUERYFUNCTIONINSTANCEID) failed (err=%d)", res); | 
| -        TraceWaveInError(res); | 
| -        // Best we can do is to copy the friendly name and use it as guid | 
| -        if (WideCharToMultiByte(CP_UTF8, 0, caps.szPname, -1, guid, kAdmMaxGuidSize, NULL, NULL) == 0) | 
| -        { | 
| -            WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "WideCharToMultiByte(CP_UTF8) failed with error code %d - 3", GetLastError()); | 
| -        } | 
| -        CoTaskMemFree(pstrEndpointId); | 
| -        return 0; | 
| -    } | 
| - | 
| -    if (WideCharToMultiByte(CP_UTF8, 0, pstrEndpointId, -1, guid, kAdmMaxGuidSize, NULL, NULL) == 0) | 
| -    { | 
| -        WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "WideCharToMultiByte(CP_UTF8) failed with error code %d - 4", GetLastError()); | 
| -    } | 
| -    CoTaskMemFree(pstrEndpointId); | 
| - | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  RecordingDevices | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int16_t AudioDeviceWindowsWave::RecordingDevices() | 
| -{ | 
| - | 
| -    return (waveInGetNumDevs()); | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  SetRecordingDevice I (II) | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::SetRecordingDevice(uint16_t index) | 
| -{ | 
| - | 
| -    if (_recIsInitialized) | 
| -    { | 
| -        return -1; | 
| -    } | 
| - | 
| -    UINT nDevices = waveInGetNumDevs(); | 
| -    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "number of availiable waveform-audio input devices is %u", nDevices); | 
| - | 
| -    if (index < 0 || index > (nDevices-1)) | 
| -    { | 
| -        WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "device index is out of range [0,%u]", (nDevices-1)); | 
| -        return -1; | 
| -    } | 
| - | 
| -    _usingInputDeviceIndex = true; | 
| -    _inputDeviceIndex = index; | 
| -    _inputDeviceIsSpecified = true; | 
| - | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  SetRecordingDevice II (II) | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::SetRecordingDevice(AudioDeviceModule::WindowsDeviceType device) | 
| -{ | 
| -    if (device == AudioDeviceModule::kDefaultDevice) | 
| -    { | 
| -    } | 
| -    else if (device == AudioDeviceModule::kDefaultCommunicationDevice) | 
| -    { | 
| -    } | 
| - | 
| -    if (_recIsInitialized) | 
| -    { | 
| -        return -1; | 
| -    } | 
| - | 
| -    _usingInputDeviceIndex = false; | 
| -    _inputDevice = device; | 
| -    _inputDeviceIsSpecified = true; | 
| - | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  PlayoutIsAvailable | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::PlayoutIsAvailable(bool& available) | 
| -{ | 
| - | 
| -    available = false; | 
| - | 
| -    // Try to initialize the playout side | 
| -    int32_t res = InitPlayout(); | 
| - | 
| -    // Cancel effect of initialization | 
| -    StopPlayout(); | 
| - | 
| -    if (res != -1) | 
| -    { | 
| -        available = true; | 
| -    } | 
| - | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  RecordingIsAvailable | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::RecordingIsAvailable(bool& available) | 
| -{ | 
| - | 
| -    available = false; | 
| - | 
| -    // Try to initialize the recording side | 
| -    int32_t res = InitRecording(); | 
| - | 
| -    // Cancel effect of initialization | 
| -    StopRecording(); | 
| - | 
| -    if (res != -1) | 
| -    { | 
| -        available = true; | 
| -    } | 
| - | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  InitPlayout | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::InitPlayout() | 
| -{ | 
| - | 
| -    CriticalSectionScoped lock(&_critSect); | 
| - | 
| -    if (_playing) | 
| -    { | 
| -        return -1; | 
| -    } | 
| - | 
| -    if (!_outputDeviceIsSpecified) | 
| -    { | 
| -        return -1; | 
| -    } | 
| - | 
| -    if (_playIsInitialized) | 
| -    { | 
| -        return 0; | 
| -    } | 
| - | 
| -    // Initialize the speaker (devices might have been added or removed) | 
| -    if (InitSpeaker() == -1) | 
| -    { | 
| -        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "InitSpeaker() failed"); | 
| -    } | 
| - | 
| -    // Enumerate all availiable output devices | 
| -    EnumeratePlayoutDevices(); | 
| - | 
| -    // Start by closing any existing wave-output devices | 
| -    // | 
| -    MMRESULT res(MMSYSERR_ERROR); | 
| - | 
| -    if (_hWaveOut != NULL) | 
| -    { | 
| -        res = waveOutClose(_hWaveOut); | 
| -        if (MMSYSERR_NOERROR != res) | 
| -        { | 
| -            WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveOutClose() failed (err=%d)", res); | 
| -            TraceWaveOutError(res); | 
| -        } | 
| -    } | 
| - | 
| -    // Set the output wave format | 
| -    // | 
| -    WAVEFORMATEX waveFormat; | 
| - | 
| -    waveFormat.wFormatTag      = WAVE_FORMAT_PCM; | 
| -    waveFormat.nChannels       = _playChannels;  // mono <=> 1, stereo <=> 2 | 
| -    waveFormat.nSamplesPerSec  = N_PLAY_SAMPLES_PER_SEC; | 
| -    waveFormat.wBitsPerSample  = 16; | 
| -    waveFormat.nBlockAlign     = waveFormat.nChannels * (waveFormat.wBitsPerSample/8); | 
| -    waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign; | 
| -    waveFormat.cbSize          = 0; | 
| - | 
| -    // Open the given waveform-audio output device for playout | 
| -    // | 
| -    HWAVEOUT hWaveOut(NULL); | 
| - | 
| -    if (IsUsingOutputDeviceIndex()) | 
| -    { | 
| -        // verify settings first | 
| -        res = waveOutOpen(NULL, _outputDeviceIndex, &waveFormat, 0, 0, CALLBACK_NULL | WAVE_FORMAT_QUERY); | 
| -        if (MMSYSERR_NOERROR == res) | 
| -        { | 
| -            // open the given waveform-audio output device for recording | 
| -            res = waveOutOpen(&hWaveOut, _outputDeviceIndex, &waveFormat, 0, 0, CALLBACK_NULL); | 
| -            WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "opening output device corresponding to device ID %u", _outputDeviceIndex); | 
| -        } | 
| -    } | 
| -    else | 
| -    { | 
| -        if (_outputDevice == AudioDeviceModule::kDefaultCommunicationDevice) | 
| -        { | 
| -            // check if it is possible to open the default communication device (supported on Windows 7) | 
| -            res = waveOutOpen(NULL, WAVE_MAPPER, &waveFormat, 0, 0, CALLBACK_NULL | WAVE_MAPPED_DEFAULT_COMMUNICATION_DEVICE | WAVE_FORMAT_QUERY); | 
| -            if (MMSYSERR_NOERROR == res) | 
| -            { | 
| -                // if so, open the default communication device for real | 
| -                res = waveOutOpen(&hWaveOut, WAVE_MAPPER, &waveFormat, 0, 0, CALLBACK_NULL |  WAVE_MAPPED_DEFAULT_COMMUNICATION_DEVICE); | 
| -                WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "opening default communication device"); | 
| -            } | 
| -            else | 
| -            { | 
| -                // use default device since default communication device was not avaliable | 
| -                res = waveOutOpen(&hWaveOut, WAVE_MAPPER, &waveFormat, 0, 0, CALLBACK_NULL); | 
| -                WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "unable to open default communication device => using default instead"); | 
| -            } | 
| -        } | 
| -        else if (_outputDevice == AudioDeviceModule::kDefaultDevice) | 
| -        { | 
| -            // open default device since it has been requested | 
| -            res = waveOutOpen(NULL, WAVE_MAPPER, &waveFormat, 0, 0, CALLBACK_NULL | WAVE_FORMAT_QUERY); | 
| -            if (MMSYSERR_NOERROR == res) | 
| -            { | 
| -                res = waveOutOpen(&hWaveOut, WAVE_MAPPER, &waveFormat, 0, 0, CALLBACK_NULL); | 
| -                WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "opening default output device"); | 
| -            } | 
| -        } | 
| -    } | 
| - | 
| -    if (MMSYSERR_NOERROR != res) | 
| -    { | 
| -        WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "waveOutOpen() failed (err=%d)", res); | 
| -        TraceWaveOutError(res); | 
| -        return -1; | 
| -    } | 
| - | 
| -    // Log information about the aquired output device | 
| -    // | 
| -    WAVEOUTCAPS caps; | 
| - | 
| -    res = waveOutGetDevCaps((UINT_PTR)hWaveOut, &caps, sizeof(WAVEOUTCAPS)); | 
| -    if (res != MMSYSERR_NOERROR) | 
| -    { | 
| -        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveOutGetDevCaps() failed (err=%d)", res); | 
| -        TraceWaveOutError(res); | 
| -    } | 
| - | 
| -    UINT deviceID(0); | 
| -    res = waveOutGetID(hWaveOut, &deviceID); | 
| -    if (res != MMSYSERR_NOERROR) | 
| -    { | 
| -        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveOutGetID() failed (err=%d)", res); | 
| -        TraceWaveOutError(res); | 
| -    } | 
| -    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "utilized device ID : %u", deviceID); | 
| -    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "product name       : %s", caps.szPname); | 
| - | 
| -    // Store valid handle for the open waveform-audio output device | 
| -    _hWaveOut = hWaveOut; | 
| - | 
| -    // Store the input wave header as well | 
| -    _waveFormatOut = waveFormat; | 
| - | 
| -    // Prepare wave-out headers | 
| -    // | 
| -    const uint8_t bytesPerSample = 2*_playChannels; | 
| - | 
| -    for (int n = 0; n < N_BUFFERS_OUT; n++) | 
| -    { | 
| -        // set up the output wave header | 
| -        _waveHeaderOut[n].lpData          = reinterpret_cast<LPSTR>(&_playBuffer[n]); | 
| -        _waveHeaderOut[n].dwBufferLength  = bytesPerSample*PLAY_BUF_SIZE_IN_SAMPLES; | 
| -        _waveHeaderOut[n].dwFlags         = 0; | 
| -        _waveHeaderOut[n].dwLoops         = 0; | 
| - | 
| -        memset(_playBuffer[n], 0, bytesPerSample*PLAY_BUF_SIZE_IN_SAMPLES); | 
| - | 
| -        // The waveOutPrepareHeader function prepares a waveform-audio data block for playback. | 
| -        // The lpData, dwBufferLength, and dwFlags members of the WAVEHDR structure must be set | 
| -        // before calling this function. | 
| -        // | 
| -        res = waveOutPrepareHeader(_hWaveOut, &_waveHeaderOut[n], sizeof(WAVEHDR)); | 
| -        if (MMSYSERR_NOERROR != res) | 
| -        { | 
| -            WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveOutPrepareHeader(%d) failed (err=%d)", n, res); | 
| -            TraceWaveOutError(res); | 
| -        } | 
| - | 
| -        // perform extra check to ensure that the header is prepared | 
| -        if (_waveHeaderOut[n].dwFlags != WHDR_PREPARED) | 
| -        { | 
| -            WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveOutPrepareHeader(%d) failed (dwFlags != WHDR_PREPARED)", n); | 
| -        } | 
| -    } | 
| - | 
| -    // Mark playout side as initialized | 
| -    _playIsInitialized = true; | 
| - | 
| -    _dTcheckPlayBufDelay = 10;  // check playback buffer delay every 10 ms | 
| -    _playBufCount = 0;          // index of active output wave header (<=> output buffer index) | 
| -    _playBufDelay = 80;         // buffer delay/size is initialized to 80 ms and slowly decreased until er < 25 | 
| -    _minPlayBufDelay = 25;      // minimum playout buffer delay | 
| -    _MAX_minBuffer = 65;        // adaptive minimum playout buffer delay cannot be larger than this value | 
| -    _intro = 1;                 // Used to make sure that adaption starts after (2000-1700)/100 seconds | 
| -    _waitCounter = 1700;        // Counter for start of adaption of playback buffer | 
| -    _erZeroCounter = 0;         // Log how many times er = 0 in consequtive calls to RecTimeProc | 
| -    _useHeader = 0;             // Counts number of "useHeader" detections. Stops at 2. | 
| - | 
| -    _writtenSamples = 0; | 
| -    _writtenSamplesOld = 0; | 
| -    _playedSamplesOld = 0; | 
| -    _sndCardPlayDelay = 0; | 
| -    _sndCardRecDelay = 0; | 
| - | 
| -    WEBRTC_TRACE(kTraceInfo, kTraceUtility, _id,"initial playout status: _playBufDelay=%d, _minPlayBufDelay=%d", | 
| -        _playBufDelay, _minPlayBufDelay); | 
| - | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  InitRecording | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::InitRecording() | 
| -{ | 
| - | 
| -    CriticalSectionScoped lock(&_critSect); | 
| - | 
| -    if (_recording) | 
| -    { | 
| -        return -1; | 
| -    } | 
| - | 
| -    if (!_inputDeviceIsSpecified) | 
| -    { | 
| -        return -1; | 
| -    } | 
| - | 
| -    if (_recIsInitialized) | 
| -    { | 
| -        return 0; | 
| -    } | 
| - | 
| -    _avgCPULoad = 0; | 
| -    _playAcc  = 0; | 
| - | 
| -    // Initialize the microphone (devices might have been added or removed) | 
| -    if (InitMicrophone() == -1) | 
| -    { | 
| -        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "InitMicrophone() failed"); | 
| -    } | 
| - | 
| -    // Enumerate all availiable input devices | 
| -    EnumerateRecordingDevices(); | 
| - | 
| -    // Start by closing any existing wave-input devices | 
| -    // | 
| -    MMRESULT res(MMSYSERR_ERROR); | 
| - | 
| -    if (_hWaveIn != NULL) | 
| -    { | 
| -        res = waveInClose(_hWaveIn); | 
| -        if (MMSYSERR_NOERROR != res) | 
| -        { | 
| -            WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveInClose() failed (err=%d)", res); | 
| -            TraceWaveInError(res); | 
| -        } | 
| -    } | 
| - | 
| -    // Set the input wave format | 
| -    // | 
| -    WAVEFORMATEX waveFormat; | 
| - | 
| -    waveFormat.wFormatTag      = WAVE_FORMAT_PCM; | 
| -    waveFormat.nChannels       = _recChannels;  // mono <=> 1, stereo <=> 2 | 
| -    waveFormat.nSamplesPerSec  = N_REC_SAMPLES_PER_SEC; | 
| -    waveFormat.wBitsPerSample  = 16; | 
| -    waveFormat.nBlockAlign     = waveFormat.nChannels * (waveFormat.wBitsPerSample/8); | 
| -    waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign; | 
| -    waveFormat.cbSize          = 0; | 
| - | 
| -    // Open the given waveform-audio input device for recording | 
| -    // | 
| -    HWAVEIN hWaveIn(NULL); | 
| - | 
| -    if (IsUsingInputDeviceIndex()) | 
| -    { | 
| -        // verify settings first | 
| -        res = waveInOpen(NULL, _inputDeviceIndex, &waveFormat, 0, 0, CALLBACK_NULL | WAVE_FORMAT_QUERY); | 
| -        if (MMSYSERR_NOERROR == res) | 
| -        { | 
| -            // open the given waveform-audio input device for recording | 
| -            res = waveInOpen(&hWaveIn, _inputDeviceIndex, &waveFormat, 0, 0, CALLBACK_NULL); | 
| -            WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "opening input device corresponding to device ID %u", _inputDeviceIndex); | 
| -        } | 
| -    } | 
| -    else | 
| -    { | 
| -        if (_inputDevice == AudioDeviceModule::kDefaultCommunicationDevice) | 
| -        { | 
| -            // check if it is possible to open the default communication device (supported on Windows 7) | 
| -            res = waveInOpen(NULL, WAVE_MAPPER, &waveFormat, 0, 0, CALLBACK_NULL | WAVE_MAPPED_DEFAULT_COMMUNICATION_DEVICE | WAVE_FORMAT_QUERY); | 
| -            if (MMSYSERR_NOERROR == res) | 
| -            { | 
| -                // if so, open the default communication device for real | 
| -                res = waveInOpen(&hWaveIn, WAVE_MAPPER, &waveFormat, 0, 0, CALLBACK_NULL | WAVE_MAPPED_DEFAULT_COMMUNICATION_DEVICE); | 
| -                WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "opening default communication device"); | 
| -            } | 
| -            else | 
| -            { | 
| -                // use default device since default communication device was not avaliable | 
| -                res = waveInOpen(&hWaveIn, WAVE_MAPPER, &waveFormat, 0, 0, CALLBACK_NULL); | 
| -                WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "unable to open default communication device => using default instead"); | 
| -            } | 
| -        } | 
| -        else if (_inputDevice == AudioDeviceModule::kDefaultDevice) | 
| -        { | 
| -            // open default device since it has been requested | 
| -            res = waveInOpen(NULL, WAVE_MAPPER, &waveFormat, 0, 0, CALLBACK_NULL | WAVE_FORMAT_QUERY); | 
| -            if (MMSYSERR_NOERROR == res) | 
| -            { | 
| -                res = waveInOpen(&hWaveIn, WAVE_MAPPER, &waveFormat, 0, 0, CALLBACK_NULL); | 
| -                WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "opening default input device"); | 
| -            } | 
| -        } | 
| -    } | 
| - | 
| -    if (MMSYSERR_NOERROR != res) | 
| -    { | 
| -        WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "waveInOpen() failed (err=%d)", res); | 
| -        TraceWaveInError(res); | 
| -        return -1; | 
| -    } | 
| - | 
| -    // Log information about the aquired input device | 
| -    // | 
| -    WAVEINCAPS caps; | 
| - | 
| -    res = waveInGetDevCaps((UINT_PTR)hWaveIn, &caps, sizeof(WAVEINCAPS)); | 
| -    if (res != MMSYSERR_NOERROR) | 
| -    { | 
| -        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveInGetDevCaps() failed (err=%d)", res); | 
| -        TraceWaveInError(res); | 
| -    } | 
| - | 
| -    UINT deviceID(0); | 
| -    res = waveInGetID(hWaveIn, &deviceID); | 
| -    if (res != MMSYSERR_NOERROR) | 
| -    { | 
| -        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveInGetID() failed (err=%d)", res); | 
| -        TraceWaveInError(res); | 
| -    } | 
| -    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "utilized device ID : %u", deviceID); | 
| -    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "product name       : %s", caps.szPname); | 
| - | 
| -    // Store valid handle for the open waveform-audio input device | 
| -    _hWaveIn = hWaveIn; | 
| - | 
| -    // Store the input wave header as well | 
| -    _waveFormatIn = waveFormat; | 
| - | 
| -    // Mark recording side as initialized | 
| -    _recIsInitialized = true; | 
| - | 
| -    _recBufCount = 0;     // index of active input wave header (<=> input buffer index) | 
| -    _recDelayCount = 0;   // ensures that input buffers are returned with certain delay | 
| - | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  StartRecording | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::StartRecording() | 
| -{ | 
| - | 
| -    if (!_recIsInitialized) | 
| -    { | 
| -        return -1; | 
| -    } | 
| - | 
| -    if (_recording) | 
| -    { | 
| -        return 0; | 
| -    } | 
| - | 
| -    // set state to ensure that the recording starts from the audio thread | 
| -    _startRec = true; | 
| - | 
| -    // the audio thread will signal when recording has stopped | 
| -    if (kEventTimeout == _recStartEvent.Wait(10000)) | 
| -    { | 
| -        _startRec = false; | 
| -        StopRecording(); | 
| -        WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "failed to activate recording"); | 
| -        return -1; | 
| -    } | 
| - | 
| -    if (_recording) | 
| -    { | 
| -        // the recording state is set by the audio thread after recording has started | 
| -    } | 
| -    else | 
| -    { | 
| -        WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "failed to activate recording"); | 
| -        return -1; | 
| -    } | 
| - | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  StopRecording | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::StopRecording() | 
| -{ | 
| - | 
| -    CriticalSectionScoped lock(&_critSect); | 
| - | 
| -    if (!_recIsInitialized) | 
| -    { | 
| -        return 0; | 
| -    } | 
| - | 
| -    if (_hWaveIn == NULL) | 
| -    { | 
| -        return -1; | 
| -    } | 
| - | 
| -    bool wasRecording = _recording; | 
| -    _recIsInitialized = false; | 
| -    _recording = false; | 
| - | 
| -    MMRESULT res; | 
| - | 
| -    // Stop waveform-adio input. If there are any buffers in the queue, the | 
| -    // current buffer will be marked as done (the dwBytesRecorded member in | 
| -    // the header will contain the length of data), but any empty buffers in | 
| -    // the queue will remain there. | 
| -    // | 
| -    res = waveInStop(_hWaveIn); | 
| -    if (MMSYSERR_NOERROR != res) | 
| -    { | 
| -        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveInStop() failed (err=%d)", res); | 
| -        TraceWaveInError(res); | 
| -    } | 
| - | 
| -    // Stop input on the given waveform-audio input device and resets the current | 
| -    // position to zero. All pending buffers are marked as done and returned to | 
| -    // the application. | 
| -    // | 
| -    res = waveInReset(_hWaveIn); | 
| -    if (MMSYSERR_NOERROR != res) | 
| -    { | 
| -        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveInReset() failed (err=%d)", res); | 
| -        TraceWaveInError(res); | 
| -    } | 
| - | 
| -    // Clean up the preparation performed by the waveInPrepareHeader function. | 
| -    // Only unprepare header if recording was ever started (and headers are prepared). | 
| -    // | 
| -    if (wasRecording) | 
| -    { | 
| -        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "waveInUnprepareHeader() will be performed"); | 
| -        for (int n = 0; n < N_BUFFERS_IN; n++) | 
| -        { | 
| -            res = waveInUnprepareHeader(_hWaveIn, &_waveHeaderIn[n], sizeof(WAVEHDR)); | 
| -            if (MMSYSERR_NOERROR != res) | 
| -            { | 
| -                WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveInUnprepareHeader() failed (err=%d)", res); | 
| -                TraceWaveInError(res); | 
| -            } | 
| -        } | 
| -    } | 
| - | 
| -    // Close the given waveform-audio input device. | 
| -    // | 
| -    res = waveInClose(_hWaveIn); | 
| -    if (MMSYSERR_NOERROR != res) | 
| -    { | 
| -        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveInClose() failed (err=%d)", res); | 
| -        TraceWaveInError(res); | 
| -    } | 
| - | 
| -    // Set the wave input handle to NULL | 
| -    // | 
| -    _hWaveIn = NULL; | 
| -    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "_hWaveIn is now set to NULL"); | 
| - | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  RecordingIsInitialized | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -bool AudioDeviceWindowsWave::RecordingIsInitialized() const | 
| -{ | 
| -    return (_recIsInitialized); | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  Recording | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -bool AudioDeviceWindowsWave::Recording() const | 
| -{ | 
| -    return (_recording); | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  PlayoutIsInitialized | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -bool AudioDeviceWindowsWave::PlayoutIsInitialized() const | 
| -{ | 
| -    return (_playIsInitialized); | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  StartPlayout | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::StartPlayout() | 
| -{ | 
| - | 
| -    if (!_playIsInitialized) | 
| -    { | 
| -        return -1; | 
| -    } | 
| - | 
| -    if (_playing) | 
| -    { | 
| -        return 0; | 
| -    } | 
| - | 
| -    // set state to ensure that playout starts from the audio thread | 
| -    _startPlay = true; | 
| - | 
| -    // the audio thread will signal when recording has started | 
| -    if (kEventTimeout == _playStartEvent.Wait(10000)) | 
| -    { | 
| -        _startPlay = false; | 
| -        StopPlayout(); | 
| -        WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "failed to activate playout"); | 
| -        return -1; | 
| -    } | 
| - | 
| -    if (_playing) | 
| -    { | 
| -        // the playing state is set by the audio thread after playout has started | 
| -    } | 
| -    else | 
| -    { | 
| -        WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "failed to activate playing"); | 
| -        return -1; | 
| -    } | 
| - | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  StopPlayout | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::StopPlayout() | 
| -{ | 
| - | 
| -    CriticalSectionScoped lock(&_critSect); | 
| - | 
| -    if (!_playIsInitialized) | 
| -    { | 
| -        return 0; | 
| -    } | 
| - | 
| -    if (_hWaveOut == NULL) | 
| -    { | 
| -        return -1; | 
| -    } | 
| - | 
| -    _playIsInitialized = false; | 
| -    _playing = false; | 
| -    _sndCardPlayDelay = 0; | 
| -    _sndCardRecDelay = 0; | 
| - | 
| -    MMRESULT res; | 
| - | 
| -    // The waveOutReset function stops playback on the given waveform-audio | 
| -    // output device and resets the current position to zero. All pending | 
| -    // playback buffers are marked as done (WHDR_DONE) and returned to the application. | 
| -    // After this function returns, the application can send new playback buffers | 
| -    // to the device by calling waveOutWrite, or close the device by calling waveOutClose. | 
| -    // | 
| -    res = waveOutReset(_hWaveOut); | 
| -    if (MMSYSERR_NOERROR != res) | 
| -    { | 
| -        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveOutReset() failed (err=%d)", res); | 
| -        TraceWaveOutError(res); | 
| -    } | 
| - | 
| -    // The waveOutUnprepareHeader function cleans up the preparation performed | 
| -    // by the waveOutPrepareHeader function. This function must be called after | 
| -    // the device driver is finished with a data block. | 
| -    // You must call this function before freeing the buffer. | 
| -    // | 
| -    for (int n = 0; n < N_BUFFERS_OUT; n++) | 
| -    { | 
| -        res = waveOutUnprepareHeader(_hWaveOut, &_waveHeaderOut[n], sizeof(WAVEHDR)); | 
| -        if (MMSYSERR_NOERROR != res) | 
| -        { | 
| -            WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveOutUnprepareHeader() failed (err=%d)", res); | 
| -            TraceWaveOutError(res); | 
| -        } | 
| -    } | 
| - | 
| -    // The waveOutClose function closes the given waveform-audio output device. | 
| -    // The close operation fails if the device is still playing a waveform-audio | 
| -    // buffer that was previously sent by calling waveOutWrite. Before calling | 
| -    // waveOutClose, the application must wait for all buffers to finish playing | 
| -    // or call the waveOutReset function to terminate playback. | 
| -    // | 
| -    res = waveOutClose(_hWaveOut); | 
| -    if (MMSYSERR_NOERROR != res) | 
| -    { | 
| -        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveOutClose() failed (err=%d)", res); | 
| -        TraceWaveOutError(res); | 
| -    } | 
| - | 
| -    _hWaveOut = NULL; | 
| -    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "_hWaveOut is now set to NULL"); | 
| - | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  PlayoutDelay | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::PlayoutDelay(uint16_t& delayMS) const | 
| -{ | 
| -    CriticalSectionScoped lock(&_critSect); | 
| -    delayMS = (uint16_t)_sndCardPlayDelay; | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  RecordingDelay | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::RecordingDelay(uint16_t& delayMS) const | 
| -{ | 
| -    CriticalSectionScoped lock(&_critSect); | 
| -    delayMS = (uint16_t)_sndCardRecDelay; | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  Playing | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -bool AudioDeviceWindowsWave::Playing() const | 
| -{ | 
| -    return (_playing); | 
| -} | 
| -// ---------------------------------------------------------------------------- | 
| -//  SetPlayoutBuffer | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::SetPlayoutBuffer(const AudioDeviceModule::BufferType type, uint16_t sizeMS) | 
| -{ | 
| -    CriticalSectionScoped lock(&_critSect); | 
| -    _playBufType = type; | 
| -    if (type == AudioDeviceModule::kFixedBufferSize) | 
| -    { | 
| -        _playBufDelayFixed = sizeMS; | 
| -    } | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  PlayoutBuffer | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::PlayoutBuffer(AudioDeviceModule::BufferType& type, uint16_t& sizeMS) const | 
| -{ | 
| -    CriticalSectionScoped lock(&_critSect); | 
| -    type = _playBufType; | 
| -    if (type == AudioDeviceModule::kFixedBufferSize) | 
| -    { | 
| -        sizeMS = _playBufDelayFixed; | 
| -    } | 
| -    else | 
| -    { | 
| -        sizeMS = _playBufDelay; | 
| -    } | 
| - | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  CPULoad | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::CPULoad(uint16_t& load) const | 
| -{ | 
| - | 
| -    load = static_cast<uint16_t>(100*_avgCPULoad); | 
| - | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  PlayoutWarning | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -bool AudioDeviceWindowsWave::PlayoutWarning() const | 
| -{ | 
| -    return ( _playWarning > 0); | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  PlayoutError | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -bool AudioDeviceWindowsWave::PlayoutError() const | 
| -{ | 
| -    return ( _playError > 0); | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  RecordingWarning | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -bool AudioDeviceWindowsWave::RecordingWarning() const | 
| -{ | 
| -    return ( _recWarning > 0); | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  RecordingError | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -bool AudioDeviceWindowsWave::RecordingError() const | 
| -{ | 
| -    return ( _recError > 0); | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  ClearPlayoutWarning | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -void AudioDeviceWindowsWave::ClearPlayoutWarning() | 
| -{ | 
| -    _playWarning = 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  ClearPlayoutError | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -void AudioDeviceWindowsWave::ClearPlayoutError() | 
| -{ | 
| -    _playError = 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  ClearRecordingWarning | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -void AudioDeviceWindowsWave::ClearRecordingWarning() | 
| -{ | 
| -    _recWarning = 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  ClearRecordingError | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -void AudioDeviceWindowsWave::ClearRecordingError() | 
| -{ | 
| -    _recError = 0; | 
| -} | 
| - | 
| -// ============================================================================ | 
| -//                                 Private Methods | 
| -// ============================================================================ | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  InputSanityCheckAfterUnlockedPeriod | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::InputSanityCheckAfterUnlockedPeriod() const | 
| -{ | 
| -    if (_hWaveIn == NULL) | 
| -    { | 
| -        WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "input state has been modified during unlocked period"); | 
| -        return -1; | 
| -    } | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  OutputSanityCheckAfterUnlockedPeriod | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::OutputSanityCheckAfterUnlockedPeriod() const | 
| -{ | 
| -    if (_hWaveOut == NULL) | 
| -    { | 
| -        WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "output state has been modified during unlocked period"); | 
| -        return -1; | 
| -    } | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  EnumeratePlayoutDevices | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::EnumeratePlayoutDevices() | 
| -{ | 
| - | 
| -    uint16_t nDevices(PlayoutDevices()); | 
| -    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "==============================================================="); | 
| -    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "#output devices: %u", nDevices); | 
| - | 
| -    WAVEOUTCAPS caps; | 
| -    MMRESULT res; | 
| - | 
| -    for (UINT deviceID = 0; deviceID < nDevices; deviceID++) | 
| -    { | 
| -        res = waveOutGetDevCaps(deviceID, &caps, sizeof(WAVEOUTCAPS)); | 
| -        if (res != MMSYSERR_NOERROR) | 
| -        { | 
| -            WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveOutGetDevCaps() failed (err=%d)", res); | 
| -        } | 
| - | 
| -        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "==============================================================="); | 
| -        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "Device ID %u:", deviceID); | 
| -        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "manufacturer ID      : %u", caps.wMid); | 
| -        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "product ID           : %u",caps.wPid); | 
| -        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "version of driver    : %u.%u", HIBYTE(caps.vDriverVersion), LOBYTE(caps.vDriverVersion)); | 
| -        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "product name         : %s", caps.szPname); | 
| -        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "dwFormats            : 0x%x", caps.dwFormats); | 
| -        if (caps.dwFormats & WAVE_FORMAT_48S16) | 
| -        { | 
| -            WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "  48kHz,stereo,16bit : SUPPORTED"); | 
| -        } | 
| -        else | 
| -        { | 
| -                WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, " 48kHz,stereo,16bit  : *NOT* SUPPORTED"); | 
| -        } | 
| -        if (caps.dwFormats & WAVE_FORMAT_48M16) | 
| -        { | 
| -            WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "  48kHz,mono,16bit   : SUPPORTED"); | 
| -        } | 
| -        else | 
| -        { | 
| -                WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, " 48kHz,mono,16bit    : *NOT* SUPPORTED"); | 
| -        } | 
| -        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "wChannels            : %u", caps.wChannels); | 
| -        TraceSupportFlags(caps.dwSupport); | 
| -    } | 
| - | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  EnumerateRecordingDevices | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::EnumerateRecordingDevices() | 
| -{ | 
| - | 
| -    uint16_t nDevices(RecordingDevices()); | 
| -    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "==============================================================="); | 
| -    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "#input devices: %u", nDevices); | 
| - | 
| -    WAVEINCAPS caps; | 
| -    MMRESULT res; | 
| - | 
| -    for (UINT deviceID = 0; deviceID < nDevices; deviceID++) | 
| -    { | 
| -        res = waveInGetDevCaps(deviceID, &caps, sizeof(WAVEINCAPS)); | 
| -        if (res != MMSYSERR_NOERROR) | 
| -        { | 
| -            WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveInGetDevCaps() failed (err=%d)", res); | 
| -        } | 
| - | 
| -        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "==============================================================="); | 
| -        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "Device ID %u:", deviceID); | 
| -        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "manufacturer ID      : %u", caps.wMid); | 
| -        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "product ID           : %u",caps.wPid); | 
| -        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "version of driver    : %u.%u", HIBYTE(caps.vDriverVersion), LOBYTE(caps.vDriverVersion)); | 
| -        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "product name         : %s", caps.szPname); | 
| -        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "dwFormats            : 0x%x", caps.dwFormats); | 
| -        if (caps.dwFormats & WAVE_FORMAT_48S16) | 
| -        { | 
| -            WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "  48kHz,stereo,16bit : SUPPORTED"); | 
| -        } | 
| -        else | 
| -        { | 
| -                WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, " 48kHz,stereo,16bit  : *NOT* SUPPORTED"); | 
| -        } | 
| -        if (caps.dwFormats & WAVE_FORMAT_48M16) | 
| -        { | 
| -            WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "  48kHz,mono,16bit   : SUPPORTED"); | 
| -        } | 
| -        else | 
| -        { | 
| -                WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, " 48kHz,mono,16bit    : *NOT* SUPPORTED"); | 
| -        } | 
| -        WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "wChannels            : %u", caps.wChannels); | 
| -    } | 
| - | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  TraceSupportFlags | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -void AudioDeviceWindowsWave::TraceSupportFlags(DWORD dwSupport) const | 
| -{ | 
| -    TCHAR buf[256]; | 
| - | 
| -    StringCchPrintf(buf, 128, TEXT("support flags        : 0x%x "), dwSupport); | 
| - | 
| -    if (dwSupport & WAVECAPS_PITCH) | 
| -    { | 
| -        // supports pitch control | 
| -        StringCchCat(buf, 256, TEXT("(PITCH)")); | 
| -    } | 
| -    if (dwSupport & WAVECAPS_PLAYBACKRATE) | 
| -    { | 
| -        // supports playback rate control | 
| -        StringCchCat(buf, 256, TEXT("(PLAYBACKRATE)")); | 
| -    } | 
| -    if (dwSupport & WAVECAPS_VOLUME) | 
| -    { | 
| -        // supports volume control | 
| -        StringCchCat(buf, 256, TEXT("(VOLUME)")); | 
| -    } | 
| -    if (dwSupport & WAVECAPS_LRVOLUME) | 
| -    { | 
| -        // supports separate left and right volume control | 
| -        StringCchCat(buf, 256, TEXT("(LRVOLUME)")); | 
| -    } | 
| -    if (dwSupport & WAVECAPS_SYNC) | 
| -    { | 
| -        // the driver is synchronous and will block while playing a buffer | 
| -        StringCchCat(buf, 256, TEXT("(SYNC)")); | 
| -    } | 
| -    if (dwSupport & WAVECAPS_SAMPLEACCURATE) | 
| -    { | 
| -        // returns sample-accurate position information | 
| -        StringCchCat(buf, 256, TEXT("(SAMPLEACCURATE)")); | 
| -    } | 
| - | 
| -    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%S", buf); | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  TraceWaveInError | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -void AudioDeviceWindowsWave::TraceWaveInError(MMRESULT error) const | 
| -{ | 
| -    TCHAR buf[MAXERRORLENGTH]; | 
| -    TCHAR msg[MAXERRORLENGTH]; | 
| - | 
| -    StringCchPrintf(buf, MAXERRORLENGTH, TEXT("Error details: ")); | 
| -    waveInGetErrorText(error, msg, MAXERRORLENGTH); | 
| -    StringCchCat(buf, MAXERRORLENGTH, msg); | 
| -    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%S", buf); | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  TraceWaveOutError | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -void AudioDeviceWindowsWave::TraceWaveOutError(MMRESULT error) const | 
| -{ | 
| -    TCHAR buf[MAXERRORLENGTH]; | 
| -    TCHAR msg[MAXERRORLENGTH]; | 
| - | 
| -    StringCchPrintf(buf, MAXERRORLENGTH, TEXT("Error details: ")); | 
| -    waveOutGetErrorText(error, msg, MAXERRORLENGTH); | 
| -    StringCchCat(buf, MAXERRORLENGTH, msg); | 
| -    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "%S", buf); | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  PrepareStartPlayout | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::PrepareStartPlayout() | 
| -{ | 
| - | 
| -    CriticalSectionScoped lock(&_critSect); | 
| - | 
| -    if (_hWaveOut == NULL) | 
| -    { | 
| -        return -1; | 
| -    } | 
| - | 
| -    // A total of 30ms of data is immediately placed in the SC buffer | 
| -    // | 
| -    int8_t zeroVec[4*PLAY_BUF_SIZE_IN_SAMPLES];  // max allocation | 
| -    memset(zeroVec, 0, 4*PLAY_BUF_SIZE_IN_SAMPLES); | 
| - | 
| -    { | 
| -        Write(zeroVec, PLAY_BUF_SIZE_IN_SAMPLES); | 
| -        Write(zeroVec, PLAY_BUF_SIZE_IN_SAMPLES); | 
| -        Write(zeroVec, PLAY_BUF_SIZE_IN_SAMPLES); | 
| -    } | 
| - | 
| -    _playAcc = 0; | 
| -    _playWarning = 0; | 
| -    _playError = 0; | 
| -    _dc_diff_mean = 0; | 
| -    _dc_y_prev = 0; | 
| -    _dc_penalty_counter = 20; | 
| -    _dc_prevtime = 0; | 
| -    _dc_prevplay = 0; | 
| - | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  PrepareStartRecording | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::PrepareStartRecording() | 
| -{ | 
| - | 
| -    CriticalSectionScoped lock(&_critSect); | 
| - | 
| -    if (_hWaveIn == NULL) | 
| -    { | 
| -        return -1; | 
| -    } | 
| - | 
| -    _playAcc = 0; | 
| -    _recordedBytes = 0; | 
| -    _recPutBackDelay = REC_PUT_BACK_DELAY; | 
| - | 
| -    MMRESULT res; | 
| -    MMTIME mmtime; | 
| -    mmtime.wType = TIME_SAMPLES; | 
| - | 
| -    res = waveInGetPosition(_hWaveIn, &mmtime, sizeof(mmtime)); | 
| -    if (MMSYSERR_NOERROR != res) | 
| -    { | 
| -        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveInGetPosition(TIME_SAMPLES) failed (err=%d)", res); | 
| -        TraceWaveInError(res); | 
| -    } | 
| - | 
| -    _read_samples = mmtime.u.sample; | 
| -    _read_samples_old = _read_samples; | 
| -    _rec_samples_old = mmtime.u.sample; | 
| -    _wrapCounter = 0; | 
| - | 
| -    for (int n = 0; n < N_BUFFERS_IN; n++) | 
| -    { | 
| -        const uint8_t nBytesPerSample = 2*_recChannels; | 
| - | 
| -        // set up the input wave header | 
| -        _waveHeaderIn[n].lpData          = reinterpret_cast<LPSTR>(&_recBuffer[n]); | 
| -        _waveHeaderIn[n].dwBufferLength  = nBytesPerSample * REC_BUF_SIZE_IN_SAMPLES; | 
| -        _waveHeaderIn[n].dwFlags         = 0; | 
| -        _waveHeaderIn[n].dwBytesRecorded = 0; | 
| -        _waveHeaderIn[n].dwUser          = 0; | 
| - | 
| -        memset(_recBuffer[n], 0, nBytesPerSample * REC_BUF_SIZE_IN_SAMPLES); | 
| - | 
| -        // prepare a buffer for waveform-audio input | 
| -        res = waveInPrepareHeader(_hWaveIn, &_waveHeaderIn[n], sizeof(WAVEHDR)); | 
| -        if (MMSYSERR_NOERROR != res) | 
| -        { | 
| -            WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveInPrepareHeader(%d) failed (err=%d)", n, res); | 
| -            TraceWaveInError(res); | 
| -        } | 
| - | 
| -        // send an input buffer to the given waveform-audio input device | 
| -        res = waveInAddBuffer(_hWaveIn, &_waveHeaderIn[n], sizeof(WAVEHDR)); | 
| -        if (MMSYSERR_NOERROR != res) | 
| -        { | 
| -            WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveInAddBuffer(%d) failed (err=%d)", n, res); | 
| -            TraceWaveInError(res); | 
| -        } | 
| -    } | 
| - | 
| -    // start input on the given waveform-audio input device | 
| -    res = waveInStart(_hWaveIn); | 
| -    if (MMSYSERR_NOERROR != res) | 
| -    { | 
| -        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveInStart() failed (err=%d)", res); | 
| -        TraceWaveInError(res); | 
| -    } | 
| - | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  GetPlayoutBufferDelay | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::GetPlayoutBufferDelay(uint32_t& writtenSamples, uint32_t& playedSamples) | 
| -{ | 
| -    int i; | 
| -    int ms_Header; | 
| -    long playedDifference; | 
| -    int msecInPlayoutBuffer(0);   // #milliseconds of audio in the playout buffer | 
| - | 
| -    const uint16_t nSamplesPerMs = (uint16_t)(N_PLAY_SAMPLES_PER_SEC/1000);  // default is 48000/1000 = 48 | 
| - | 
| -    MMRESULT res; | 
| -    MMTIME mmtime; | 
| - | 
| -    if (!_playing) | 
| -    { | 
| -        playedSamples = 0; | 
| -        return (0); | 
| -    } | 
| - | 
| -    // Retrieve the current playback position. | 
| -    // | 
| -    mmtime.wType = TIME_SAMPLES;  // number of waveform-audio samples | 
| -    res = waveOutGetPosition(_hWaveOut, &mmtime, sizeof(mmtime)); | 
| -    if (MMSYSERR_NOERROR != res) | 
| -    { | 
| -        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveOutGetPosition() failed (err=%d)", res); | 
| -        TraceWaveOutError(res); | 
| -    } | 
| - | 
| -    writtenSamples = _writtenSamples;   // #samples written to the playout buffer | 
| -    playedSamples = mmtime.u.sample;    // current playout position in the playout buffer | 
| - | 
| -    // derive remaining amount (in ms) of data in the playout buffer | 
| -    msecInPlayoutBuffer = ((writtenSamples - playedSamples)/nSamplesPerMs); | 
| - | 
| -    playedDifference = (long) (_playedSamplesOld - playedSamples); | 
| - | 
| -    if (playedDifference > 64000) | 
| -    { | 
| -        // If the sound cards number-of-played-out-samples variable wraps around before | 
| -        // written_sampels wraps around this needs to be adjusted. This can happen on | 
| -        // sound cards that uses less than 32 bits to keep track of number of played out | 
| -        // sampels. To avoid being fooled by sound cards that sometimes produces false | 
| -        // output we compare old value minus the new value with a large value. This is | 
| -        // neccessary because some SC:s produce an output like 153, 198, 175, 230 which | 
| -        // would trigger the wrap-around function if we didn't compare with a large value. | 
| -        // The value 64000 is chosen because 2^16=65536 so we allow wrap around at 16 bits. | 
| - | 
| -        i = 31; | 
| -        while((_playedSamplesOld <= (unsigned long)POW2(i)) && (i > 14)) { | 
| -            i--; | 
| -        } | 
| - | 
| -        if((i < 31) && (i > 14)) { | 
| -            // Avoid adjusting when there is 32-bit wrap-around since that is | 
| -            // something neccessary. | 
| -            // | 
| -            WEBRTC_TRACE(kTraceDebug, kTraceUtility, _id, "msecleft() => wrap around occured: %d bits used by sound card)", (i+1)); | 
| - | 
| -            _writtenSamples = _writtenSamples - POW2(i + 1); | 
| -            writtenSamples = _writtenSamples; | 
| -            msecInPlayoutBuffer = ((writtenSamples - playedSamples)/nSamplesPerMs); | 
| -        } | 
| -    } | 
| -    else if ((_writtenSamplesOld > (unsigned long)POW2(31)) && (writtenSamples < 96000)) | 
| -    { | 
| -        // Wrap around as expected after having used all 32 bits. (But we still | 
| -        // test if the wrap around happened earlier which it should not) | 
| - | 
| -        i = 31; | 
| -        while (_writtenSamplesOld <= (unsigned long)POW2(i)) { | 
| -            i--; | 
| -        } | 
| - | 
| -        WEBRTC_TRACE(kTraceDebug, kTraceUtility, _id, "  msecleft() (wrap around occured after having used all 32 bits)"); | 
| - | 
| -        _writtenSamplesOld = writtenSamples; | 
| -        _playedSamplesOld = playedSamples; | 
| -        msecInPlayoutBuffer = (int)((writtenSamples + POW2(i + 1) - playedSamples)/nSamplesPerMs); | 
| - | 
| -    } | 
| -    else if ((writtenSamples < 96000) && (playedSamples > (unsigned long)POW2(31))) | 
| -    { | 
| -        // Wrap around has, as expected, happened for written_sampels before | 
| -        // playedSampels so we have to adjust for this until also playedSampels | 
| -        // has had wrap around. | 
| - | 
| -        WEBRTC_TRACE(kTraceDebug, kTraceUtility, _id, "  msecleft() (wrap around occured: correction of output is done)"); | 
| - | 
| -        _writtenSamplesOld = writtenSamples; | 
| -        _playedSamplesOld = playedSamples; | 
| -        msecInPlayoutBuffer = (int)((writtenSamples + POW2(32) - playedSamples)/nSamplesPerMs); | 
| -    } | 
| - | 
| -    _writtenSamplesOld = writtenSamples; | 
| -    _playedSamplesOld = playedSamples; | 
| - | 
| - | 
| -    // We use the following formaula to track that playout works as it should | 
| -    // y=playedSamples/48 - timeGetTime(); | 
| -    // y represent the clock drift between system clock and sound card clock - should be fairly stable | 
| -    // When the exponential mean value of diff(y) goes away from zero something is wrong | 
| -    // The exponential formula will accept 1% clock drift but not more | 
| -    // The driver error means that we will play to little audio and have a high negative clock drift | 
| -    // We kick in our alternative method when the clock drift reaches 20% | 
| - | 
| -    int diff,y; | 
| -    int unsigned time =0; | 
| - | 
| -    // If we have other problems that causes playout glitches | 
| -    // we don't want to switch playout method. | 
| -    // Check if playout buffer is extremely low, or if we haven't been able to | 
| -    // exectue our code in more than 40 ms | 
| - | 
| -    time = timeGetTime(); | 
| - | 
| -    if ((msecInPlayoutBuffer < 20) || (time - _dc_prevtime > 40)) | 
| -    { | 
| -        _dc_penalty_counter = 100; | 
| -    } | 
| - | 
| -    if ((playedSamples != 0)) | 
| -    { | 
| -        y = playedSamples/48 - time; | 
| -        if ((_dc_y_prev != 0) && (_dc_penalty_counter == 0)) | 
| -        { | 
| -            diff = y - _dc_y_prev; | 
| -            _dc_diff_mean = (990*_dc_diff_mean)/1000 + 10*diff; | 
| -        } | 
| -        _dc_y_prev = y; | 
| -    } | 
| - | 
| -    if (_dc_penalty_counter) | 
| -    { | 
| -        _dc_penalty_counter--; | 
| -    } | 
| - | 
| -    if (_dc_diff_mean < -200) | 
| -    { | 
| -        // Always reset the filter | 
| -        _dc_diff_mean = 0; | 
| - | 
| -        // Problem is detected. Switch delay method and set min buffer to 80. | 
| -        // Reset the filter and keep monitoring the filter output. | 
| -        // If issue is detected a second time, increase min buffer to 100. | 
| -        // If that does not help, we must modify this scheme further. | 
| - | 
| -        _useHeader++; | 
| -        if (_useHeader == 1) | 
| -        { | 
| -            _minPlayBufDelay = 80; | 
| -            _playWarning = 1;   // only warn first time | 
| -            WEBRTC_TRACE(kTraceInfo, kTraceUtility, -1, "Modification #1: _useHeader = %d, _minPlayBufDelay = %d", _useHeader, _minPlayBufDelay); | 
| -        } | 
| -        else if (_useHeader == 2) | 
| -        { | 
| -            _minPlayBufDelay = 100;   // add some more safety | 
| -            WEBRTC_TRACE(kTraceInfo, kTraceUtility, -1, "Modification #2: _useHeader = %d, _minPlayBufDelay = %d", _useHeader, _minPlayBufDelay); | 
| -        } | 
| -        else | 
| -        { | 
| -            // This state should not be entered... (HA) | 
| -            WEBRTC_TRACE (kTraceWarning, kTraceUtility, -1, "further actions are required!"); | 
| -        } | 
| -        if (_playWarning == 1) | 
| -        { | 
| -            WEBRTC_TRACE(kTraceWarning, kTraceUtility, _id, "pending playout warning exists"); | 
| -        } | 
| -        _playWarning = 1;  // triggers callback from module process thread | 
| -        WEBRTC_TRACE(kTraceWarning, kTraceUtility, _id, "kPlayoutWarning message posted: switching to alternative playout delay method"); | 
| -    } | 
| -    _dc_prevtime = time; | 
| -    _dc_prevplay = playedSamples; | 
| - | 
| -    // Try a very rough method of looking at how many buffers are still playing | 
| -    ms_Header = 0; | 
| -    for (i = 0; i < N_BUFFERS_OUT; i++) { | 
| -        if ((_waveHeaderOut[i].dwFlags & WHDR_INQUEUE)!=0) { | 
| -            ms_Header += 10; | 
| -        } | 
| -    } | 
| - | 
| -    if ((ms_Header-50) > msecInPlayoutBuffer) { | 
| -        // Test for cases when GetPosition appears to be screwed up (currently just log....) | 
| -        TCHAR infoStr[300]; | 
| -        if (_no_of_msecleft_warnings%20==0) | 
| -        { | 
| -            StringCchPrintf(infoStr, 300, TEXT("writtenSamples=%i, playedSamples=%i, msecInPlayoutBuffer=%i, ms_Header=%i"), writtenSamples, playedSamples, msecInPlayoutBuffer, ms_Header); | 
| -            WEBRTC_TRACE(kTraceWarning, kTraceUtility, _id, "%S", infoStr); | 
| -        } | 
| -        _no_of_msecleft_warnings++; | 
| -    } | 
| - | 
| -    // If this is true we have had a problem with the playout | 
| -    if (_useHeader > 0) | 
| -    { | 
| -        return (ms_Header); | 
| -    } | 
| - | 
| - | 
| -    if (ms_Header < msecInPlayoutBuffer) | 
| -    { | 
| -        if (_no_of_msecleft_warnings % 100 == 0) | 
| -        { | 
| -            TCHAR str[300]; | 
| -            StringCchPrintf(str, 300, TEXT("_no_of_msecleft_warnings=%i, msecInPlayoutBuffer=%i ms_Header=%i (minBuffer=%i buffersize=%i writtenSamples=%i playedSamples=%i)"), | 
| -                _no_of_msecleft_warnings, msecInPlayoutBuffer, ms_Header, _minPlayBufDelay, _playBufDelay, writtenSamples, playedSamples); | 
| -            WEBRTC_TRACE(kTraceWarning, kTraceUtility, _id, "%S", str); | 
| -        } | 
| -        _no_of_msecleft_warnings++; | 
| -        ms_Header -= 6; // Round off as we only have 10ms resolution + Header info is usually slightly delayed compared to GetPosition | 
| - | 
| -        if (ms_Header < 0) | 
| -            ms_Header = 0; | 
| - | 
| -        return (ms_Header); | 
| -    } | 
| -    else | 
| -    { | 
| -        return (msecInPlayoutBuffer); | 
| -    } | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  GetRecordingBufferDelay | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::GetRecordingBufferDelay(uint32_t& readSamples, uint32_t& recSamples) | 
| -{ | 
| -    long recDifference; | 
| -    MMTIME mmtime; | 
| -    MMRESULT mmr; | 
| - | 
| -    const uint16_t nSamplesPerMs = (uint16_t)(N_REC_SAMPLES_PER_SEC/1000);  // default is 48000/1000 = 48 | 
| - | 
| -    // Retrieve the current input position of the given waveform-audio input device | 
| -    // | 
| -    mmtime.wType = TIME_SAMPLES; | 
| -    mmr = waveInGetPosition(_hWaveIn, &mmtime, sizeof(mmtime)); | 
| -    if (MMSYSERR_NOERROR != mmr) | 
| -    { | 
| -        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveInGetPosition() failed (err=%d)", mmr); | 
| -        TraceWaveInError(mmr); | 
| -    } | 
| - | 
| -    readSamples = _read_samples;    // updated for each full fram in RecProc() | 
| -    recSamples = mmtime.u.sample;   // remaining time in input queue (recorded but not read yet) | 
| - | 
| -    recDifference = (long) (_rec_samples_old - recSamples); | 
| - | 
| -    if( recDifference > 64000) { | 
| -        WEBRTC_TRACE (kTraceDebug, kTraceUtility, -1,"WRAP 1 (recDifference =%d)", recDifference); | 
| -        // If the sound cards number-of-recorded-samples variable wraps around before | 
| -        // read_sampels wraps around this needs to be adjusted. This can happen on | 
| -        // sound cards that uses less than 32 bits to keep track of number of played out | 
| -        // sampels. To avoid being fooled by sound cards that sometimes produces false | 
| -        // output we compare old value minus the new value with a large value. This is | 
| -        // neccessary because some SC:s produce an output like 153, 198, 175, 230 which | 
| -        // would trigger the wrap-around function if we didn't compare with a large value. | 
| -        // The value 64000 is chosen because 2^16=65536 so we allow wrap around at 16 bits. | 
| -        // | 
| -        int i = 31; | 
| -        while((_rec_samples_old <= (unsigned long)POW2(i)) && (i > 14)) | 
| -            i--; | 
| - | 
| -        if((i < 31) && (i > 14)) { | 
| -            // Avoid adjusting when there is 32-bit wrap-around since that is | 
| -            // somethying neccessary. | 
| -            // | 
| -            _read_samples = _read_samples - POW2(i + 1); | 
| -            readSamples = _read_samples; | 
| -            _wrapCounter++; | 
| -        } else { | 
| -            WEBRTC_TRACE (kTraceWarning, kTraceUtility, -1,"AEC (_rec_samples_old %d recSamples %d)",_rec_samples_old, recSamples); | 
| -        } | 
| -    } | 
| - | 
| -    if((_wrapCounter>200)){ | 
| -        // Do nothing, handled later | 
| -    } | 
| -    else if((_rec_samples_old > (unsigned long)POW2(31)) && (recSamples < 96000)) { | 
| -        WEBRTC_TRACE (kTraceDebug, kTraceUtility, -1,"WRAP 2 (_rec_samples_old %d recSamples %d)",_rec_samples_old, recSamples); | 
| -        // Wrap around as expected after having used all 32 bits. | 
| -        _read_samples_old = readSamples; | 
| -        _rec_samples_old = recSamples; | 
| -        _wrapCounter++; | 
| -        return (int)((recSamples + POW2(32) - readSamples)/nSamplesPerMs); | 
| - | 
| - | 
| -    } else if((recSamples < 96000) && (readSamples > (unsigned long)POW2(31))) { | 
| -        WEBRTC_TRACE (kTraceDebug, kTraceUtility, -1,"WRAP 3 (readSamples %d recSamples %d)",readSamples, recSamples); | 
| -        // Wrap around has, as expected, happened for rec_sampels before | 
| -        // readSampels so we have to adjust for this until also readSampels | 
| -        // has had wrap around. | 
| -        _read_samples_old = readSamples; | 
| -        _rec_samples_old = recSamples; | 
| -        _wrapCounter++; | 
| -        return (int)((recSamples + POW2(32) - readSamples)/nSamplesPerMs); | 
| -    } | 
| - | 
| -    _read_samples_old = _read_samples; | 
| -    _rec_samples_old = recSamples; | 
| -    int res=(((int)_rec_samples_old - (int)_read_samples_old)/nSamplesPerMs); | 
| - | 
| -    if((res > 2000)||(res < 0)||(_wrapCounter>200)){ | 
| -        // Reset everything | 
| -        WEBRTC_TRACE (kTraceWarning, kTraceUtility, -1,"msec_read error (res %d wrapCounter %d)",res, _wrapCounter); | 
| -        MMTIME mmtime; | 
| -        mmtime.wType = TIME_SAMPLES; | 
| - | 
| -        mmr=waveInGetPosition(_hWaveIn, &mmtime, sizeof(mmtime)); | 
| -        if (mmr != MMSYSERR_NOERROR) { | 
| -            WEBRTC_TRACE (kTraceWarning, kTraceUtility, -1, "waveInGetPosition failed (mmr=%d)", mmr); | 
| -        } | 
| -        _read_samples=mmtime.u.sample; | 
| -        _read_samples_old=_read_samples; | 
| -        _rec_samples_old=mmtime.u.sample; | 
| - | 
| -        // Guess a decent value | 
| -        res = 20; | 
| -    } | 
| - | 
| -    _wrapCounter = 0; | 
| -    return res; | 
| -} | 
| - | 
| -// ============================================================================ | 
| -//                                  Thread Methods | 
| -// ============================================================================ | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  ThreadFunc | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -bool AudioDeviceWindowsWave::ThreadFunc(void* pThis) | 
| -{ | 
| -    return (static_cast<AudioDeviceWindowsWave*>(pThis)->ThreadProcess()); | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  ThreadProcess | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -bool AudioDeviceWindowsWave::ThreadProcess() | 
| -{ | 
| -    uint32_t time(0); | 
| -    uint32_t playDiff(0); | 
| -    uint32_t recDiff(0); | 
| - | 
| -    LONGLONG playTime(0); | 
| -    LONGLONG recTime(0); | 
| - | 
| -    switch (_timeEvent.Wait(1000)) | 
| -    { | 
| -    case kEventSignaled: | 
| -        break; | 
| -    case kEventError: | 
| -        WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "EventWrapper::Wait() failed => restarting timer"); | 
| -        _timeEvent.StopTimer(); | 
| -        _timeEvent.StartTimer(true, TIMER_PERIOD_MS); | 
| -        return true; | 
| -    case kEventTimeout: | 
| -        return true; | 
| -    } | 
| - | 
| -    time = rtc::TimeMillis(); | 
| - | 
| -    if (_startPlay) | 
| -    { | 
| -        if (PrepareStartPlayout() == 0) | 
| -        { | 
| -            _prevTimerCheckTime = time; | 
| -            _prevPlayTime = time; | 
| -            _startPlay = false; | 
| -            _playing = true; | 
| -            _playStartEvent.Set(); | 
| -        } | 
| -    } | 
| - | 
| -    if (_startRec) | 
| -    { | 
| -        if (PrepareStartRecording() == 0) | 
| -        { | 
| -            _prevTimerCheckTime = time; | 
| -            _prevRecTime = time; | 
| -            _prevRecByteCheckTime = time; | 
| -            _startRec = false; | 
| -            _recording = true; | 
| -            _recStartEvent.Set(); | 
| -        } | 
| -    } | 
| - | 
| -    if (_playing) | 
| -    { | 
| -        playDiff = time - _prevPlayTime; | 
| -    } | 
| - | 
| -    if (_recording) | 
| -    { | 
| -        recDiff = time - _prevRecTime; | 
| -    } | 
| - | 
| -    if (_playing || _recording) | 
| -    { | 
| -        RestartTimerIfNeeded(time); | 
| -    } | 
| - | 
| -    if (_playing && | 
| -        (playDiff > (uint32_t)(_dTcheckPlayBufDelay - 1)) || | 
| -        (playDiff < 0)) | 
| -    { | 
| -        Lock(); | 
| -        if (_playing) | 
| -        { | 
| -            if (PlayProc(playTime) == -1) | 
| -            { | 
| -                WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "PlayProc() failed"); | 
| -            } | 
| -            _prevPlayTime = time; | 
| -            if (playTime != 0) | 
| -                _playAcc += playTime; | 
| -        } | 
| -        UnLock(); | 
| -    } | 
| - | 
| -    if (_playing && (playDiff > 12)) | 
| -    { | 
| -        // It has been a long time since we were able to play out, try to | 
| -        // compensate by calling PlayProc again. | 
| -        // | 
| -        Lock(); | 
| -        if (_playing) | 
| -        { | 
| -            if (PlayProc(playTime)) | 
| -            { | 
| -                WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "PlayProc() failed"); | 
| -            } | 
| -            _prevPlayTime = time; | 
| -            if (playTime != 0) | 
| -                _playAcc += playTime; | 
| -        } | 
| -        UnLock(); | 
| -    } | 
| - | 
| -    if (_recording && | 
| -       (recDiff > REC_CHECK_TIME_PERIOD_MS) || | 
| -       (recDiff < 0)) | 
| -    { | 
| -        Lock(); | 
| -        if (_recording) | 
| -        { | 
| -            int32_t nRecordedBytes(0); | 
| -            uint16_t maxIter(10); | 
| - | 
| -            // Deliver all availiable recorded buffers and update the CPU load measurement. | 
| -            // We use a while loop here to compensate for the fact that the multi-media timer | 
| -            // can sometimed enter a "bad state" after hibernation where the resolution is | 
| -            // reduced from ~1ms to ~10-15 ms. | 
| -            // | 
| -            while ((nRecordedBytes = RecProc(recTime)) > 0) | 
| -            { | 
| -                maxIter--; | 
| -                _recordedBytes += nRecordedBytes; | 
| -                if (recTime && _perfFreq.QuadPart) | 
| -                { | 
| -                    // Measure the average CPU load: | 
| -                    // This is a simplified expression where an exponential filter is used: | 
| -                    //   _avgCPULoad = 0.99 * _avgCPULoad + 0.01 * newCPU, | 
| -                    //   newCPU = (recTime+playAcc)/f is time in seconds | 
| -                    //   newCPU / 0.01 is the fraction of a 10 ms period | 
| -                    // The two 0.01 cancels each other. | 
| -                    // NOTE - assumes 10ms audio buffers. | 
| -                    // | 
| -                    _avgCPULoad = (float)(_avgCPULoad*.99 + (recTime+_playAcc)/(double)(_perfFreq.QuadPart)); | 
| -                    _playAcc = 0; | 
| -                } | 
| -                if (maxIter == 0) | 
| -                { | 
| -                    // If we get this message ofte, our compensation scheme is not sufficient. | 
| -                    WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "failed to compensate for reduced MM-timer resolution"); | 
| -                } | 
| -            } | 
| - | 
| -            if (nRecordedBytes == -1) | 
| -            { | 
| -                WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "RecProc() failed"); | 
| -            } | 
| - | 
| -            _prevRecTime = time; | 
| - | 
| -            // Monitor the recording process and generate error/warning callbacks if needed | 
| -            MonitorRecording(time); | 
| -        } | 
| -        UnLock(); | 
| -    } | 
| - | 
| -    if (!_recording) | 
| -    { | 
| -        _prevRecByteCheckTime = time; | 
| -        _avgCPULoad = 0; | 
| -    } | 
| - | 
| -    return true; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  RecProc | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::RecProc(LONGLONG& consumedTime) | 
| -{ | 
| -    MMRESULT res; | 
| -    uint32_t bufCount(0); | 
| -    uint32_t nBytesRecorded(0); | 
| - | 
| -    consumedTime = 0; | 
| - | 
| -    // count modulo N_BUFFERS_IN (0,1,2,...,(N_BUFFERS_IN-1),0,1,2,..) | 
| -    if (_recBufCount == N_BUFFERS_IN) | 
| -    { | 
| -        _recBufCount = 0; | 
| -    } | 
| - | 
| -    bufCount = _recBufCount; | 
| - | 
| -    // take mono/stereo mode into account when deriving size of a full buffer | 
| -    const uint16_t bytesPerSample = 2*_recChannels; | 
| -    const uint32_t fullBufferSizeInBytes = bytesPerSample * REC_BUF_SIZE_IN_SAMPLES; | 
| - | 
| -    // read number of recorded bytes for the given input-buffer | 
| -    nBytesRecorded = _waveHeaderIn[bufCount].dwBytesRecorded; | 
| - | 
| -    if (nBytesRecorded == fullBufferSizeInBytes || | 
| -       (nBytesRecorded > 0)) | 
| -    { | 
| -        int32_t msecOnPlaySide; | 
| -        int32_t msecOnRecordSide; | 
| -        uint32_t writtenSamples; | 
| -        uint32_t playedSamples; | 
| -        uint32_t readSamples, recSamples; | 
| -        bool send = true; | 
| - | 
| -        uint32_t nSamplesRecorded = (nBytesRecorded/bytesPerSample);  // divide by 2 or 4 depending on mono or stereo | 
| - | 
| -        if (nBytesRecorded == fullBufferSizeInBytes) | 
| -        { | 
| -            _timesdwBytes = 0; | 
| -        } | 
| -        else | 
| -        { | 
| -            // Test if it is stuck on this buffer | 
| -            _timesdwBytes++; | 
| -            if (_timesdwBytes < 5) | 
| -            { | 
| -                // keep trying | 
| -                return (0); | 
| -            } | 
| -            else | 
| -            { | 
| -                WEBRTC_TRACE(kTraceDebug, kTraceUtility, _id,"nBytesRecorded=%d => don't use", nBytesRecorded); | 
| -                _timesdwBytes = 0; | 
| -                send = false; | 
| -            } | 
| -        } | 
| - | 
| -        // store the recorded buffer (no action will be taken if the #recorded samples is not a full buffer) | 
| -        _ptrAudioBuffer->SetRecordedBuffer(_waveHeaderIn[bufCount].lpData, nSamplesRecorded); | 
| - | 
| -        // update #samples read | 
| -        _read_samples += nSamplesRecorded; | 
| - | 
| -        // Check how large the playout and recording buffers are on the sound card. | 
| -        // This info is needed by the AEC. | 
| -        // | 
| -        msecOnPlaySide = GetPlayoutBufferDelay(writtenSamples, playedSamples); | 
| -        msecOnRecordSide = GetRecordingBufferDelay(readSamples, recSamples); | 
| - | 
| -        // If we use the alternative playout delay method, skip the clock drift compensation | 
| -        // since it will be an unreliable estimate and might degrade AEC performance. | 
| -        int32_t drift = (_useHeader > 0) ? 0 : GetClockDrift(playedSamples, recSamples); | 
| - | 
| -        _ptrAudioBuffer->SetVQEData(msecOnPlaySide, msecOnRecordSide, drift); | 
| - | 
| -        _ptrAudioBuffer->SetTypingStatus(KeyPressed()); | 
| - | 
| -        // Store the play and rec delay values for video synchronization | 
| -        _sndCardPlayDelay = msecOnPlaySide; | 
| -        _sndCardRecDelay = msecOnRecordSide; | 
| - | 
| -        LARGE_INTEGER t1={0},t2={0}; | 
| - | 
| -        if (send) | 
| -        { | 
| -            QueryPerformanceCounter(&t1); | 
| - | 
| -            // deliver recorded samples at specified sample rate, mic level etc. to the observer using callback | 
| -            UnLock(); | 
| -            _ptrAudioBuffer->DeliverRecordedData(); | 
| -            Lock(); | 
| - | 
| -            QueryPerformanceCounter(&t2); | 
| - | 
| -            if (InputSanityCheckAfterUnlockedPeriod() == -1) | 
| -            { | 
| -                // assert(false); | 
| -                return -1; | 
| -            } | 
| -        } | 
| - | 
| -        if (_AGC) | 
| -        { | 
| -            uint32_t  newMicLevel = _ptrAudioBuffer->NewMicLevel(); | 
| -            if (newMicLevel != 0) | 
| -            { | 
| -                // The VQE will only deliver non-zero microphone levels when a change is needed. | 
| -                WEBRTC_TRACE(kTraceStream, kTraceUtility, _id,"AGC change of volume: => new=%u", newMicLevel); | 
| - | 
| -                // We store this outside of the audio buffer to avoid | 
| -                // having it overwritten by the getter thread. | 
| -                _newMicLevel = newMicLevel; | 
| -                SetEvent(_hSetCaptureVolumeEvent); | 
| -            } | 
| -        } | 
| - | 
| -        // return utilized buffer to queue after specified delay (default is 4) | 
| -        if (_recDelayCount > (_recPutBackDelay-1)) | 
| -        { | 
| -            // deley buffer counter to compensate for "put-back-delay" | 
| -            bufCount = (bufCount + N_BUFFERS_IN - _recPutBackDelay) % N_BUFFERS_IN; | 
| - | 
| -            // reset counter so we can make new detection | 
| -            _waveHeaderIn[bufCount].dwBytesRecorded = 0; | 
| - | 
| -            // return the utilized wave-header after certain delay (given by _recPutBackDelay) | 
| -            res = waveInUnprepareHeader(_hWaveIn, &(_waveHeaderIn[bufCount]), sizeof(WAVEHDR)); | 
| -            if (MMSYSERR_NOERROR != res) | 
| -            { | 
| -                WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "waveInUnprepareHeader(%d) failed (err=%d)", bufCount, res); | 
| -                TraceWaveInError(res); | 
| -            } | 
| - | 
| -            // ensure that the utilized header can be used again | 
| -            res = waveInPrepareHeader(_hWaveIn, &(_waveHeaderIn[bufCount]), sizeof(WAVEHDR)); | 
| -            if (res != MMSYSERR_NOERROR) | 
| -            { | 
| -                WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "waveInPrepareHeader(%d) failed (err=%d)", bufCount, res); | 
| -                TraceWaveInError(res); | 
| -                return -1; | 
| -            } | 
| - | 
| -            // add the utilized buffer to the queue again | 
| -            res = waveInAddBuffer(_hWaveIn, &(_waveHeaderIn[bufCount]), sizeof(WAVEHDR)); | 
| -            if (res != MMSYSERR_NOERROR) | 
| -            { | 
| -                WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "waveInAddBuffer(%d) failed (err=%d)", bufCount, res); | 
| -                TraceWaveInError(res); | 
| -                if (_recPutBackDelay < 50) | 
| -                { | 
| -                    _recPutBackDelay++; | 
| -                    WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "_recPutBackDelay increased to %d", _recPutBackDelay); | 
| -                } | 
| -                else | 
| -                { | 
| -                    if (_recError == 1) | 
| -                    { | 
| -                        WEBRTC_TRACE(kTraceWarning, kTraceUtility, _id, "pending recording error exists"); | 
| -                    } | 
| -                    _recError = 1;  // triggers callback from module process thread | 
| -                    WEBRTC_TRACE(kTraceError, kTraceUtility, _id, "kRecordingError message posted: _recPutBackDelay=%u", _recPutBackDelay); | 
| -                } | 
| -            } | 
| -        }  // if (_recDelayCount > (_recPutBackDelay-1)) | 
| - | 
| -        if (_recDelayCount < (_recPutBackDelay+1)) | 
| -        { | 
| -            _recDelayCount++; | 
| -        } | 
| - | 
| -        // increase main buffer count since one complete buffer has now been delivered | 
| -        _recBufCount++; | 
| - | 
| -        if (send) { | 
| -            // Calculate processing time | 
| -            consumedTime = (int)(t2.QuadPart-t1.QuadPart); | 
| -            // handle wraps, time should not be higher than a second | 
| -            if ((consumedTime > _perfFreq.QuadPart) || (consumedTime < 0)) | 
| -                consumedTime = 0; | 
| -        } | 
| - | 
| -    }  // if ((nBytesRecorded == fullBufferSizeInBytes)) | 
| - | 
| -    return nBytesRecorded; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  PlayProc | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int AudioDeviceWindowsWave::PlayProc(LONGLONG& consumedTime) | 
| -{ | 
| -    int32_t remTimeMS(0); | 
| -    int8_t playBuffer[4*PLAY_BUF_SIZE_IN_SAMPLES]; | 
| -    uint32_t writtenSamples(0); | 
| -    uint32_t playedSamples(0); | 
| - | 
| -    LARGE_INTEGER t1; | 
| -    LARGE_INTEGER t2; | 
| - | 
| -    consumedTime = 0; | 
| -    _waitCounter++; | 
| - | 
| -    // Get number of ms of sound that remains in the sound card buffer for playback. | 
| -    // | 
| -    remTimeMS = GetPlayoutBufferDelay(writtenSamples, playedSamples); | 
| - | 
| -    // The threshold can be adaptive or fixed. The adaptive scheme is updated | 
| -    // also for fixed mode but the updated threshold is not utilized. | 
| -    // | 
| -    const uint16_t thresholdMS = | 
| -        (_playBufType == AudioDeviceModule::kAdaptiveBufferSize) ? _playBufDelay : _playBufDelayFixed; | 
| - | 
| -    if (remTimeMS < thresholdMS + 9) | 
| -    { | 
| -        _dTcheckPlayBufDelay = 5; | 
| - | 
| -        if (remTimeMS == 0) | 
| -        { | 
| -            WEBRTC_TRACE(kTraceInfo, kTraceUtility, _id, "playout buffer is empty => we must adapt..."); | 
| -            if (_waitCounter > 30) | 
| -            { | 
| -                _erZeroCounter++; | 
| -                if (_erZeroCounter == 2) | 
| -                { | 
| -                    _playBufDelay += 15; | 
| -                    _minPlayBufDelay += 20; | 
| -                    _waitCounter = 50; | 
| -                    WEBRTC_TRACE(kTraceDebug, kTraceUtility, _id, "New playout states (er=0,erZero=2): minPlayBufDelay=%u, playBufDelay=%u", _minPlayBufDelay, _playBufDelay); | 
| -                } | 
| -                else if (_erZeroCounter == 3) | 
| -                { | 
| -                    _erZeroCounter = 0; | 
| -                    _playBufDelay += 30; | 
| -                    _minPlayBufDelay += 25; | 
| -                    _waitCounter = 0; | 
| -                    WEBRTC_TRACE(kTraceDebug, kTraceUtility, _id, "New playout states (er=0, erZero=3): minPlayBufDelay=%u, playBufDelay=%u", _minPlayBufDelay, _playBufDelay); | 
| -                } | 
| -                else | 
| -                { | 
| -                    _minPlayBufDelay += 10; | 
| -                    _playBufDelay += 15; | 
| -                    _waitCounter = 50; | 
| -                    WEBRTC_TRACE(kTraceDebug, kTraceUtility, _id, "New playout states (er=0, erZero=1): minPlayBufDelay=%u, playBufDelay=%u", _minPlayBufDelay, _playBufDelay); | 
| -                } | 
| -            } | 
| -        } | 
| -        else if (remTimeMS < _minPlayBufDelay) | 
| -        { | 
| -            // If there is less than 25 ms of audio in the play out buffer | 
| -            // increase the buffersize limit value. _waitCounter prevents | 
| -            // _playBufDelay to be increased every time this function is called. | 
| - | 
| -            if (_waitCounter > 30) | 
| -            { | 
| -                _playBufDelay += 10; | 
| -                if (_intro == 0) | 
| -                    _waitCounter = 0; | 
| -                WEBRTC_TRACE(kTraceDebug, kTraceUtility, _id, "Playout threshold is increased: playBufDelay=%u", _playBufDelay); | 
| -            } | 
| -        } | 
| -        else if (remTimeMS < thresholdMS - 9) | 
| -        { | 
| -            _erZeroCounter = 0; | 
| -        } | 
| -        else | 
| -        { | 
| -            _erZeroCounter = 0; | 
| -            _dTcheckPlayBufDelay = 10; | 
| -        } | 
| - | 
| -        QueryPerformanceCounter(&t1);   // measure time: START | 
| - | 
| -        // Ask for new PCM data to be played out using the AudioDeviceBuffer. | 
| -        // Ensure that this callback is executed without taking the audio-thread lock. | 
| -        // | 
| -        UnLock(); | 
| -        uint32_t nSamples = _ptrAudioBuffer->RequestPlayoutData(PLAY_BUF_SIZE_IN_SAMPLES); | 
| -        Lock(); | 
| - | 
| -        if (OutputSanityCheckAfterUnlockedPeriod() == -1) | 
| -        { | 
| -            // assert(false); | 
| -            return -1; | 
| -        } | 
| - | 
| -        nSamples = _ptrAudioBuffer->GetPlayoutData(playBuffer); | 
| -        if (nSamples != PLAY_BUF_SIZE_IN_SAMPLES) | 
| -        { | 
| -            WEBRTC_TRACE(kTraceError, kTraceUtility, _id, "invalid number of output samples(%d)", nSamples); | 
| -        } | 
| - | 
| -        QueryPerformanceCounter(&t2);   // measure time: STOP | 
| -        consumedTime = (int)(t2.QuadPart - t1.QuadPart); | 
| - | 
| -        Write(playBuffer, PLAY_BUF_SIZE_IN_SAMPLES); | 
| - | 
| -    }  // if (er < thresholdMS + 9) | 
| -    else if (thresholdMS + 9 < remTimeMS ) | 
| -    { | 
| -        _erZeroCounter = 0; | 
| -        _dTcheckPlayBufDelay = 2;    // check buffer more often | 
| -        WEBRTC_TRACE(kTraceDebug, kTraceUtility, _id, "Need to check playout buffer more often (dT=%u, remTimeMS=%u)", _dTcheckPlayBufDelay, remTimeMS); | 
| -    } | 
| - | 
| -    // If the buffersize has been stable for 20 seconds try to decrease the buffer size | 
| -    if (_waitCounter > 2000) | 
| -    { | 
| -        _intro = 0; | 
| -        _playBufDelay--; | 
| -        _waitCounter = 1990; | 
| -        WEBRTC_TRACE(kTraceDebug, kTraceUtility, _id, "Playout threshold is decreased: playBufDelay=%u", _playBufDelay); | 
| -    } | 
| - | 
| -    // Limit the minimum sound card (playback) delay to adaptive minimum delay | 
| -    if (_playBufDelay < _minPlayBufDelay) | 
| -    { | 
| -        _playBufDelay = _minPlayBufDelay; | 
| -        WEBRTC_TRACE(kTraceDebug, kTraceUtility, _id, "Playout threshold is limited to %u", _minPlayBufDelay); | 
| -    } | 
| - | 
| -    // Limit the maximum sound card (playback) delay to 150 ms | 
| -    if (_playBufDelay > 150) | 
| -    { | 
| -        _playBufDelay = 150; | 
| -        WEBRTC_TRACE(kTraceDebug, kTraceUtility, _id, "Playout threshold is limited to %d", _playBufDelay); | 
| -    } | 
| - | 
| -    // Upper limit of the minimum sound card (playback) delay to 65 ms. | 
| -    // Deactivated during "useHeader mode" (_useHeader > 0). | 
| -    if (_minPlayBufDelay > _MAX_minBuffer && | 
| -       (_useHeader == 0)) | 
| -    { | 
| -        _minPlayBufDelay = _MAX_minBuffer; | 
| -        WEBRTC_TRACE(kTraceDebug, kTraceUtility, _id, "Minimum playout threshold is limited to %d", _MAX_minBuffer); | 
| -    } | 
| - | 
| -    return (0); | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  Write | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::Write(int8_t* data, uint16_t nSamples) | 
| -{ | 
| -    if (_hWaveOut == NULL) | 
| -    { | 
| -        return -1; | 
| -    } | 
| - | 
| -    if (_playIsInitialized) | 
| -    { | 
| -        MMRESULT res; | 
| - | 
| -        const uint16_t bufCount(_playBufCount); | 
| - | 
| -        // Place data in the memory associated with _waveHeaderOut[bufCount] | 
| -        // | 
| -        const int16_t nBytes = (2*_playChannels)*nSamples; | 
| -        memcpy(&_playBuffer[bufCount][0], &data[0], nBytes); | 
| - | 
| -        // Send a data block to the given waveform-audio output device. | 
| -        // | 
| -        // When the buffer is finished, the WHDR_DONE bit is set in the dwFlags | 
| -        // member of the WAVEHDR structure. The buffer must be prepared with the | 
| -        // waveOutPrepareHeader function before it is passed to waveOutWrite. | 
| -        // Unless the device is paused by calling the waveOutPause function, | 
| -        // playback begins when the first data block is sent to the device. | 
| -        // | 
| -        res = waveOutWrite(_hWaveOut, &_waveHeaderOut[bufCount], sizeof(_waveHeaderOut[bufCount])); | 
| -        if (MMSYSERR_NOERROR != res) | 
| -        { | 
| -            WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, "waveOutWrite(%d) failed (err=%d)", bufCount, res); | 
| -            TraceWaveOutError(res); | 
| - | 
| -            _writeErrors++; | 
| -            if (_writeErrors > 10) | 
| -            { | 
| -                if (_playError == 1) | 
| -                { | 
| -                    WEBRTC_TRACE(kTraceWarning, kTraceUtility, _id, "pending playout error exists"); | 
| -                } | 
| -                _playError = 1;  // triggers callback from module process thread | 
| -                WEBRTC_TRACE(kTraceError, kTraceUtility, _id, "kPlayoutError message posted: _writeErrors=%u", _writeErrors); | 
| -            } | 
| - | 
| -            return -1; | 
| -        } | 
| - | 
| -        _playBufCount = (_playBufCount+1) % N_BUFFERS_OUT;  // increase buffer counter modulo size of total buffer | 
| -        _writtenSamples += nSamples;                        // each sample is 2 or 4 bytes | 
| -        _writeErrors = 0; | 
| -    } | 
| - | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//    GetClockDrift | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::GetClockDrift(const uint32_t plSamp, const uint32_t rcSamp) | 
| -{ | 
| -    int drift = 0; | 
| -    unsigned int plSampDiff = 0, rcSampDiff = 0; | 
| - | 
| -    if (plSamp >= _plSampOld) | 
| -    { | 
| -        plSampDiff = plSamp - _plSampOld; | 
| -    } | 
| -    else | 
| -    { | 
| -        // Wrap | 
| -        int i = 31; | 
| -        while(_plSampOld <= (unsigned int)POW2(i)) | 
| -        { | 
| -            i--; | 
| -        } | 
| - | 
| -        // Add the amount remaining prior to wrapping | 
| -        plSampDiff = plSamp +  POW2(i + 1) - _plSampOld; | 
| -    } | 
| - | 
| -    if (rcSamp >= _rcSampOld) | 
| -    { | 
| -        rcSampDiff = rcSamp - _rcSampOld; | 
| -    } | 
| -    else | 
| -    {   // Wrap | 
| -        int i = 31; | 
| -        while(_rcSampOld <= (unsigned int)POW2(i)) | 
| -        { | 
| -            i--; | 
| -        } | 
| - | 
| -        rcSampDiff = rcSamp +  POW2(i + 1) - _rcSampOld; | 
| -    } | 
| - | 
| -    drift = plSampDiff - rcSampDiff; | 
| - | 
| -    _plSampOld = plSamp; | 
| -    _rcSampOld = rcSamp; | 
| - | 
| -    return drift; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  MonitorRecording | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::MonitorRecording(const uint32_t time) | 
| -{ | 
| -    const uint16_t bytesPerSample = 2*_recChannels; | 
| -    const uint32_t nRecordedSamples = _recordedBytes/bytesPerSample; | 
| - | 
| -    if (nRecordedSamples > 5*N_REC_SAMPLES_PER_SEC) | 
| -    { | 
| -        // 5 seconds of audio has been recorded... | 
| -        if ((time - _prevRecByteCheckTime) > 5700) | 
| -        { | 
| -            // ...and it was more than 5.7 seconds since we last did this check <=> | 
| -            // we have not been able to record 5 seconds of audio in 5.7 seconds, | 
| -            // hence a problem should be reported. | 
| -            // This problem can be related to USB overload. | 
| -            // | 
| -            if (_recWarning == 1) | 
| -            { | 
| -                WEBRTC_TRACE(kTraceWarning, kTraceUtility, _id, "pending recording warning exists"); | 
| -            } | 
| -            _recWarning = 1;  // triggers callback from module process thread | 
| -            WEBRTC_TRACE(kTraceWarning, kTraceUtility, _id, "kRecordingWarning message posted: time-_prevRecByteCheckTime=%d", time - _prevRecByteCheckTime); | 
| -        } | 
| - | 
| -        _recordedBytes = 0;            // restart "check again when 5 seconds are recorded" | 
| -        _prevRecByteCheckTime = time;  // reset timer to measure time for recording of 5 seconds | 
| -    } | 
| - | 
| -    if ((time - _prevRecByteCheckTime) > 8000) | 
| -    { | 
| -        // It has been more than 8 seconds since we able to confirm that 5 seconds of | 
| -        // audio was recorded, hence we have not been able to record 5 seconds in | 
| -        // 8 seconds => the complete recording process is most likely dead. | 
| -        // | 
| -        if (_recError == 1) | 
| -        { | 
| -            WEBRTC_TRACE(kTraceWarning, kTraceUtility, _id, "pending recording error exists"); | 
| -        } | 
| -        _recError = 1;  // triggers callback from module process thread | 
| -        WEBRTC_TRACE(kTraceError, kTraceUtility, _id, "kRecordingError message posted: time-_prevRecByteCheckTime=%d", time - _prevRecByteCheckTime); | 
| - | 
| -        _prevRecByteCheckTime = time; | 
| -    } | 
| - | 
| -    return 0; | 
| -} | 
| - | 
| -// ---------------------------------------------------------------------------- | 
| -//  MonitorRecording | 
| -// | 
| -//  Restart timer if needed (they seem to be messed up after a hibernate). | 
| -// ---------------------------------------------------------------------------- | 
| - | 
| -int32_t AudioDeviceWindowsWave::RestartTimerIfNeeded(const uint32_t time) | 
| -{ | 
| -    const uint32_t diffMS = time - _prevTimerCheckTime; | 
| -    _prevTimerCheckTime = time; | 
| - | 
| -    if (diffMS > 7) | 
| -    { | 
| -        // one timer-issue detected... | 
| -        _timerFaults++; | 
| -        if (_timerFaults > 5 && _timerRestartAttempts < 2) | 
| -        { | 
| -            // Reinitialize timer event if event fails to execute at least every 5ms. | 
| -            // On some machines it helps and the timer starts working as it should again; | 
| -            // however, not all machines (we have seen issues on e.g. IBM T60). | 
| -            // Therefore, the scheme below ensures that we do max 2 attempts to restart the timer. | 
| -            // For the cases where restart does not do the trick, we compensate for the reduced | 
| -            // resolution on both the recording and playout sides. | 
| -            WEBRTC_TRACE(kTraceWarning, kTraceUtility, _id, " timer issue detected => timer is restarted"); | 
| -            _timeEvent.StopTimer(); | 
| -            _timeEvent.StartTimer(true, TIMER_PERIOD_MS); | 
| -            // make sure timer gets time to start up and we don't kill/start timer serveral times over and over again | 
| -            _timerFaults = -20; | 
| -            _timerRestartAttempts++; | 
| -        } | 
| -    } | 
| -    else | 
| -    { | 
| -        // restart timer-check scheme since we are OK | 
| -        _timerFaults = 0; | 
| -        _timerRestartAttempts = 0; | 
| -    } | 
| - | 
| -    return 0; | 
| -} | 
| - | 
| - | 
| -bool AudioDeviceWindowsWave::KeyPressed() const{ | 
| - | 
| -  int key_down = 0; | 
| -  for (int key = VK_SPACE; key < VK_NUMLOCK; key++) { | 
| -    short res = GetAsyncKeyState(key); | 
| -    key_down |= res & 0x1; // Get the LSB | 
| -  } | 
| -  return (key_down > 0); | 
| -} | 
| -}  // namespace webrtc | 
|  |