From: <man...@us...> - 2013-04-09 16:27:50
|
Revision: 1791 http://sourceforge.net/p/modplug/code/1791 Author: manxorist Date: 2013-04-09 16:27:40 +0000 (Tue, 09 Apr 2013) Log Message: ----------- [Imp] On Vista/Win7/Win8, boost the thread priority using MMCSS. Also add an option to completely disable boosting of audio thread priority. [Ref] Add code to use WASAPI in exclusive mode via portuadio. This is disabled for now as portaudio behaves kind of strange in that mode. Modified Paths: -------------- trunk/OpenMPT/mptrack/MainFrm.cpp trunk/OpenMPT/mptrack/Mainfrm.h trunk/OpenMPT/mptrack/Mpdlgs.cpp trunk/OpenMPT/mptrack/mptrack.rc trunk/OpenMPT/soundlib/SNDDEV.H trunk/OpenMPT/soundlib/SNDDEVX.H trunk/OpenMPT/soundlib/Snddev.cpp Modified: trunk/OpenMPT/mptrack/MainFrm.cpp =================================================================== --- trunk/OpenMPT/mptrack/MainFrm.cpp 2013-04-09 00:29:35 UTC (rev 1790) +++ trunk/OpenMPT/mptrack/MainFrm.cpp 2013-04-09 16:27:40 UTC (rev 1791) @@ -836,7 +836,11 @@ if(!gpSoundDevice) gpSoundDevice = CreateSoundDevice(nDevType); if(!gpSoundDevice) return false; gpSoundDevice->SetSource(this); - gpSoundDevice->Configure(m_hWnd, TrackerSettings::Instance().m_LatencyMS, TrackerSettings::Instance().m_UpdateIntervalMS, (TrackerSettings::Instance().m_dwSoundSetup & SOUNDSETUP_SECONDARY) ? SNDDEV_OPTIONS_SECONDARY : 0); + gpSoundDevice->Configure(m_hWnd, TrackerSettings::Instance().m_LatencyMS, TrackerSettings::Instance().m_UpdateIntervalMS, + ((TrackerSettings::Instance().m_dwSoundSetup & SOUNDSETUP_SECONDARY) ? 0 : SNDDEV_OPTIONS_EXCLUSIVE) + | + ((TrackerSettings::Instance().m_dwSoundSetup & SOUNDSETUP_NOBOOSTTHREADPRIORITY) ? 0 : SNDDEV_OPTIONS_BOOSTTHREADPRIORITY) + ); if (!gpSoundDevice->Open(SNDDEV_GET_NUMBER(TrackerSettings::Instance().m_nWaveDevice), &WaveFormat.Format)) return false; return true; } Modified: trunk/OpenMPT/mptrack/Mainfrm.h =================================================================== --- trunk/OpenMPT/mptrack/Mainfrm.h 2013-04-09 00:29:35 UTC (rev 1790) +++ trunk/OpenMPT/mptrack/Mainfrm.h 2013-04-09 16:27:40 UTC (rev 1791) @@ -111,7 +111,8 @@ #define SOUNDSETUP_ENABLEMMX 0x08 #define SOUNDSETUP_SOFTPANNING 0x10 #define SOUNDSETUP_SECONDARY 0x40 -#define SOUNDSETUP_RESTARTMASK SOUNDSETUP_SECONDARY +#define SOUNDSETUP_NOBOOSTTHREADPRIORITY 0x80 +#define SOUNDSETUP_RESTARTMASK (SOUNDSETUP_SECONDARY|SOUNDSETUP_NOBOOSTTHREADPRIORITY) #ifndef NO_DSP #define QUALITY_NOISEREDUCTION 0x01 Modified: trunk/OpenMPT/mptrack/Mpdlgs.cpp =================================================================== --- trunk/OpenMPT/mptrack/Mpdlgs.cpp 2013-04-09 00:29:35 UTC (rev 1790) +++ trunk/OpenMPT/mptrack/Mpdlgs.cpp 2013-04-09 16:27:40 UTC (rev 1791) @@ -65,6 +65,7 @@ ON_COMMAND(IDC_CHECK2, OnSettingsChanged) ON_COMMAND(IDC_CHECK3, OnSettingsChanged) ON_COMMAND(IDC_CHECK4, OnSettingsChanged) + ON_COMMAND(IDC_CHECK5, OnSettingsChanged) ON_CBN_SELCHANGE(IDC_COMBO1, OnDeviceChanged) ON_CBN_SELCHANGE(IDC_COMBO2, OnSettingsChanged) ON_CBN_SELCHANGE(IDC_COMBO_UPDATEINTERVAL, OnSettingsChanged) @@ -126,6 +127,7 @@ if (m_dwSoundSetup & SOUNDSETUP_SOFTPANNING) CheckDlgButton(IDC_CHECK2, MF_CHECKED); if (m_dwSoundSetup & SOUNDSETUP_ENABLEMMX) CheckDlgButton(IDC_CHECK3, MF_CHECKED); if (m_dwSoundSetup & SOUNDSETUP_SECONDARY) CheckDlgButton(IDC_CHECK4, MF_CHECKED); + if (!(m_dwSoundSetup & SOUNDSETUP_NOBOOSTTHREADPRIORITY)) CheckDlgButton(IDC_CHECK5, MF_CHECKED); // Multimedia extensions ::EnableWindow(::GetDlgItem(m_hWnd, IDC_CHECK3), (CSoundFile::GetSysInfo() & SYSMIX_ENABLEMMX) ? TRUE : FALSE); if(CSoundFile::GetSysInfo() & SYSMIX_SSE) @@ -243,7 +245,7 @@ nDev++; } } - GetDlgItem(IDC_CHECK4)->EnableWindow((SNDDEV_GET_TYPE(m_nSoundDevice) == SNDDEV_DSOUND) ? TRUE : FALSE); + GetDlgItem(IDC_CHECK4)->EnableWindow((SNDDEV_GET_TYPE(m_nSoundDevice) == SNDDEV_DSOUND /*|| SNDDEV_GET_TYPE(m_nSoundDevice) == SNDDEV_PORTAUDIO_WASAPI*/) ? TRUE : FALSE); GetDlgItem(IDC_STATIC_UPDATEINTERVAL)->EnableWindow((SNDDEV_GET_TYPE(m_nSoundDevice) == SNDDEV_ASIO) ? FALSE : TRUE); GetDlgItem(IDC_COMBO_UPDATEINTERVAL)->EnableWindow((SNDDEV_GET_TYPE(m_nSoundDevice) == SNDDEV_ASIO) ? FALSE : TRUE); } @@ -333,7 +335,7 @@ if (n >= 0) { int dev = m_CbnDevice.GetItemData(n); - GetDlgItem(IDC_CHECK4)->EnableWindow((SNDDEV_GET_TYPE(dev) == SNDDEV_DSOUND) ? TRUE : FALSE); + GetDlgItem(IDC_CHECK4)->EnableWindow((SNDDEV_GET_TYPE(dev) == SNDDEV_DSOUND /*|| SNDDEV_GET_TYPE(dev) == SNDDEV_PORTAUDIO_WASAPI*/) ? TRUE : FALSE); GetDlgItem(IDC_STATIC_UPDATEINTERVAL)->EnableWindow((SNDDEV_GET_TYPE(dev) == SNDDEV_ASIO) ? FALSE : TRUE); GetDlgItem(IDC_COMBO_UPDATEINTERVAL)->EnableWindow((SNDDEV_GET_TYPE(dev) == SNDDEV_ASIO) ? FALSE : TRUE); UpdateSampleRates(dev); @@ -410,10 +412,11 @@ void COptionsSoundcard::OnOK() //---------------------------- { - m_dwSoundSetup &= ~(SOUNDSETUP_ENABLEMMX | SOUNDSETUP_SECONDARY | SOUNDSETUP_SOFTPANNING); + m_dwSoundSetup &= ~(SOUNDSETUP_ENABLEMMX | SOUNDSETUP_SECONDARY | SOUNDSETUP_SOFTPANNING | SOUNDSETUP_NOBOOSTTHREADPRIORITY); if (IsDlgButtonChecked(IDC_CHECK2)) m_dwSoundSetup |= SOUNDSETUP_SOFTPANNING; if (IsDlgButtonChecked(IDC_CHECK3)) m_dwSoundSetup |= SOUNDSETUP_ENABLEMMX; if (IsDlgButtonChecked(IDC_CHECK4)) m_dwSoundSetup |= SOUNDSETUP_SECONDARY; + if (!IsDlgButtonChecked(IDC_CHECK5)) m_dwSoundSetup |= SOUNDSETUP_NOBOOSTTHREADPRIORITY; // Mixing Freq { m_dwRate = m_CbnMixingFreq.GetItemData(m_CbnMixingFreq.GetCurSel()); Modified: trunk/OpenMPT/mptrack/mptrack.rc =================================================================== --- trunk/OpenMPT/mptrack/mptrack.rc 2013-04-09 00:29:35 UTC (rev 1790) +++ trunk/OpenMPT/mptrack/mptrack.rc 2013-04-09 16:27:40 UTC (rev 1791) @@ -1299,6 +1299,7 @@ EDITTEXT IDC_EDIT_STATISTICS,6,222,258,36,ES_MULTILINE | ES_AUTOHSCROLL | ES_READONLY | NOT WS_TABSTOP GROUPBOX "",IDC_STATIC,6,6,258,114 GROUPBOX "",IDC_STATIC,6,126,258,90 + CONTROL "Boost thread priority",IDC_CHECK5,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,156,66,89,12 END IDD_MIDIMACRO DIALOGEX 0, 0, 358, 354 Modified: trunk/OpenMPT/soundlib/SNDDEV.H =================================================================== --- trunk/OpenMPT/soundlib/SNDDEV.H 2013-04-09 00:29:35 UTC (rev 1790) +++ trunk/OpenMPT/soundlib/SNDDEV.H 2013-04-09 16:27:40 UTC (rev 1791) @@ -75,7 +75,8 @@ #define SNDDEV_MINUPDATEINTERVAL_MS 1 #define SNDDEV_MAXUPDATEINTERVAL_MS 200 -#define SNDDEV_OPTIONS_SECONDARY 0x01 // Use secondary buffers (if available) +#define SNDDEV_OPTIONS_EXCLUSIVE 0x01 // Use hardware buffers directly +#define SNDDEV_OPTIONS_BOOSTTHREADPRIORITY 0x02 // Boost thread priority for glitch-free audio rendering //============================================= Modified: trunk/OpenMPT/soundlib/SNDDEVX.H =================================================================== --- trunk/OpenMPT/soundlib/SNDDEVX.H 2013-04-09 00:29:35 UTC (rev 1790) +++ trunk/OpenMPT/soundlib/SNDDEVX.H 2013-04-09 16:27:40 UTC (rev 1791) @@ -25,6 +25,7 @@ #ifndef NO_PORTAUDIO #include "portaudio/include/portaudio.h" +#include "portaudio/include/pa_win_wasapi.h" #endif @@ -261,6 +262,7 @@ protected: PaHostApiIndex m_HostApi; PaStreamParameters m_StreamParameters; + PaWasapiStreamInfo m_WasapiStreamInfo; PaStream * m_Stream; void * m_CurrentFrameBuffer; unsigned long m_CurrentFrameCount; Modified: trunk/OpenMPT/soundlib/Snddev.cpp =================================================================== --- trunk/OpenMPT/soundlib/Snddev.cpp 2013-04-09 00:29:35 UTC (rev 1790) +++ trunk/OpenMPT/soundlib/Snddev.cpp 2013-04-09 16:27:40 UTC (rev 1791) @@ -109,10 +109,6 @@ //------------------------------- { HANDLE sleepEvent = CreateEvent(NULL, FALSE, FALSE, NULL); -#ifdef NDEBUG - SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL ); -#endif - HANDLE waithandles[3]; waithandles[0] = m_hAudioThreadTerminateRequest; waithandles[1] = m_hAudioWakeUp; @@ -138,6 +134,43 @@ continue; } +#ifdef NDEBUG + typedef HANDLE (WINAPI *FAvSetMmThreadCharacteristics) (LPCTSTR,LPDWORD); + typedef BOOL (WINAPI *FAvRevertMmThreadCharacteristics)(HANDLE); + FAvSetMmThreadCharacteristics pAvSetMmThreadCharacteristics = NULL; + FAvRevertMmThreadCharacteristics pAvRevertMmThreadCharacteristics = NULL; + HMODULE hAvrtDLL = NULL; + DWORD task_idx = 0; + HANDLE hTask = NULL; + + OSVERSIONINFO versioninfo; + MemsetZero(versioninfo); + versioninfo.dwOSVersionInfoSize = sizeof(versioninfo); + GetVersionEx(&versioninfo); + + bool boostPriority = (m_SoundDevice.m_fulCfgOptions & SNDDEV_OPTIONS_BOOSTTHREADPRIORITY); + + if(boostPriority) + { + if(versioninfo.dwMajorVersion >= 6) // vista + { + hAvrtDLL = LoadLibrary("avrt.dll"); + if(hAvrtDLL) + { + pAvSetMmThreadCharacteristics = (FAvSetMmThreadCharacteristics)GetProcAddress(hAvrtDLL, "AvSetMmThreadCharacteristicsA"); + pAvRevertMmThreadCharacteristics = (FAvRevertMmThreadCharacteristics)GetProcAddress(hAvrtDLL, "AvRevertMmThreadCharacteristics"); + } + if(pAvSetMmThreadCharacteristics && pAvRevertMmThreadCharacteristics) + { + hTask = pAvSetMmThreadCharacteristics("Pro Audio", &task_idx); + } + } else + { + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL); + } + } +#endif + // increase resolution of multimedia timer bool period_set = (timeBeginPeriod(1) == TIMERR_NOERROR); @@ -173,6 +206,29 @@ if(period_set) timeEndPeriod(1); +#ifdef NDEBUG + if(boostPriority) + { + if(versioninfo.dwMajorVersion >= 6) // vista + { + if(pAvSetMmThreadCharacteristics && pAvRevertMmThreadCharacteristics) + { + pAvRevertMmThreadCharacteristics(hTask); + } + if(hAvrtDLL) + { + pAvRevertMmThreadCharacteristics = NULL; + pAvSetMmThreadCharacteristics = NULL; + FreeLibrary(hAvrtDLL); + hAvrtDLL = NULL; + } + } else + { + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL); + } + } +#endif + } SetEvent(m_hAudioThreadGoneIdle); @@ -544,7 +600,7 @@ { DSBUFFERDESC dsbd; DSBCAPS dsc; - UINT nPriorityLevel = (m_fulCfgOptions & SNDDEV_OPTIONS_SECONDARY) ? DSSCL_PRIORITY : DSSCL_WRITEPRIMARY; + UINT nPriorityLevel = (m_fulCfgOptions & SNDDEV_OPTIONS_EXCLUSIVE) ? DSSCL_WRITEPRIMARY : DSSCL_PRIORITY; if (m_piDS) return TRUE; if (!gpDSoundEnumerate) return FALSE; @@ -560,7 +616,7 @@ if(m_nDSoundBufferSize > DSOUND_MAXBUFFERSIZE) m_nDSoundBufferSize = DSOUND_MAXBUFFERSIZE; m_nBytesPerSec = pwfx->nAvgBytesPerSec; m_BytesPerSample = (pwfx->wBitsPerSample/8) * pwfx->nChannels; - if (m_fulCfgOptions & SNDDEV_OPTIONS_SECONDARY) + if(!(m_fulCfgOptions & SNDDEV_OPTIONS_EXCLUSIVE)) { // Set the format of the primary buffer dsbd.dwSize = sizeof(dsbd); @@ -1738,8 +1794,17 @@ } m_StreamParameters.suggestedLatency = m_LatencyMS / 1000.0; m_StreamParameters.hostApiSpecificStreamInfo = NULL; + if(false && (m_HostApi == Pa_HostApiTypeIdToHostApiIndex(paWASAPI)) && (m_fulCfgOptions & SNDDEV_OPTIONS_EXCLUSIVE)) + { + MemsetZero(m_WasapiStreamInfo); + m_WasapiStreamInfo.size = sizeof(PaWasapiStreamInfo); + m_WasapiStreamInfo.hostApiType = paWASAPI; + m_WasapiStreamInfo.version = 1; + m_WasapiStreamInfo.flags = paWinWasapiExclusive; + m_StreamParameters.hostApiSpecificStreamInfo = &m_WasapiStreamInfo; + } if(Pa_IsFormatSupported(NULL, &m_StreamParameters, pwfx->nSamplesPerSec) != paFormatIsSupported) return false; - if(Pa_OpenStream(&m_Stream, NULL, &m_StreamParameters, pwfx->nSamplesPerSec, (m_fulCfgOptions & SNDDEV_OPTIONS_SECONDARY && false) ? static_cast<long>(m_UpdateIntervalMS * pwfx->nSamplesPerSec / 1000.0f) : paFramesPerBufferUnspecified, paNoFlag, StreamCallbackWrapper, (void*)this) != paNoError) return false; + if(Pa_OpenStream(&m_Stream, NULL, &m_StreamParameters, pwfx->nSamplesPerSec, /*static_cast<long>(m_UpdateIntervalMS * pwfx->nSamplesPerSec / 1000.0f)*/ paFramesPerBufferUnspecified, paNoFlag, StreamCallbackWrapper, (void*)this) != paNoError) return false; if(!Pa_GetStreamInfo(m_Stream)) { Pa_CloseStream(m_Stream); @@ -1843,6 +1908,15 @@ StreamParameters.sampleFormat = paInt16; StreamParameters.suggestedLatency = 0.0; StreamParameters.hostApiSpecificStreamInfo = NULL; + if(false && (m_HostApi == Pa_HostApiTypeIdToHostApiIndex(paWASAPI)) && (m_fulCfgOptions & SNDDEV_OPTIONS_EXCLUSIVE)) + { + MemsetZero(m_WasapiStreamInfo); + m_WasapiStreamInfo.size = sizeof(PaWasapiStreamInfo); + m_WasapiStreamInfo.hostApiType = paWASAPI; + m_WasapiStreamInfo.version = 1; + m_WasapiStreamInfo.flags = paWinWasapiExclusive; + m_StreamParameters.hostApiSpecificStreamInfo = &m_WasapiStreamInfo; + } result.push_back(Pa_IsFormatSupported(NULL, &StreamParameters, samplerates[n]) == paFormatIsSupported); } return true; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |