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