Note: WASAPI Event driven core is capable of 2ms latency!!!, but Polling\r
method can only provide 15-20ms latency. */\r
paWinWasapiPolling = (1 << 3),\r
+\r
+ /* forces custom thread priority setting. must be used if PaWasapiStreamInfo::threadPriority \r
+ is set to custom value. */\r
+ paWinWasapiThreadPriority = (1 << 4)\r
}\r
PaWasapiFlags;\r
#define paWinWasapiExclusive (paWinWasapiExclusive)\r
#define paWinWasapiRedirectHostProcessor (paWinWasapiRedirectHostProcessor)\r
#define paWinWasapiUseChannelMask (paWinWasapiUseChannelMask)\r
#define paWinWasapiPolling (paWinWasapiPolling)\r
+#define paWinWasapiThreadPriority (paWinWasapiThreadPriority)\r
\r
\r
/* Host processor. Allows to skip internal PA processing completely. \r
void *outputBuffer, long outputFrames,\r
void *userData);\r
\r
+/* Device role */\r
+typedef enum PaWasapiDeviceRole\r
+{\r
+ eRoleRemoteNetworkDevice = 0,\r
+ eRoleSpeakers,\r
+ eRoleLineLevel,\r
+ eRoleHeadphones,\r
+ eRoleMicrophone,\r
+ eRoleHeadset,\r
+ eRoleHandset,\r
+ eRoleUnknownDigitalPassthrough,\r
+ eRoleSPDIF,\r
+ eRoleHDMI,\r
+ eRoleUnknownFormFactor\r
+}\r
+PaWasapiDeviceRole;\r
+\r
+\r
+/* Thread priority */\r
+typedef enum PaWasapiThreadPriority\r
+{\r
+ eThreadPriorityNone = 0,\r
+ eThreadPriorityAudio, //!< Default for Shared mode.\r
+ eThreadPriorityCapture,\r
+ eThreadPriorityDistribution,\r
+ eThreadPriorityGames,\r
+ eThreadPriorityPlayback,\r
+ eThreadPriorityProAudio, //!< Default for Exclusive mode.\r
+ eThreadPriorityWindowManager\r
+}\r
+PaWasapiThreadPriority;\r
+\r
+\r
/* Stream descriptor. */\r
typedef struct PaWasapiStreamInfo \r
{\r
/* Support for WAVEFORMATEXTENSIBLE channel masks. If flags contains\r
paWinWasapiUseChannelMask this allows you to specify which speakers \r
to address in a multichannel stream. Constants for channelMask\r
- are specified in pa_win_waveformat.h\r
+ are specified in pa_win_waveformat.h. Will be used only if \r
+ paWinWasapiUseChannelMask flag is specified.\r
*/\r
PaWinWaveFormatChannelMask channelMask;\r
\r
/* Delivers raw data to callback obtained from GetBuffer() methods skipping \r
internal PortAudio processing inventory completely. userData parameter will \r
- be the same that was passed to Pa_OpenStream method.\r
+ be the same that was passed to Pa_OpenStream method. Will be used only if \r
+ paWinWasapiRedirectHostProcessor flag is specified.\r
*/\r
PaWasapiHostProcessorCallback hostProcessorOutput;\r
PaWasapiHostProcessorCallback hostProcessorInput;\r
+\r
+ /* Specifies thread priority explicitly. Will be used only if paWinWasapiThreadPriority flag\r
+ is specified.\r
+\r
+ Please note, if Input/Output streams are opened simultaniously (Full-Duplex mode)\r
+ you shall specify same value for threadPriority or othervise one of the values will be used\r
+ to setup thread priority.\r
+ */\r
+ PaWasapiThreadPriority threadPriority;\r
} \r
PaWasapiStreamInfo;\r
\r
or, a PaErrorCode (which are always negative) if PortAudio is not initialized\r
or an error is encountered.\r
*/\r
-int PaWasapi_GetDeviceDefaultFormat( void *pFormat, int nFormatSize, PaDeviceIndex nDevice );\r
-\r
-\r
-/* Device role */\r
-typedef enum PaWasapiDeviceRole\r
-{\r
- eRoleRemoteNetworkDevice = 0,\r
- eRoleSpeakers,\r
- eRoleLineLevel,\r
- eRoleHeadphones,\r
- eRoleMicrophone,\r
- eRoleHeadset,\r
- eRoleHandset,\r
- eRoleUnknownDigitalPassthrough,\r
- eRoleSPDIF,\r
- eRoleHDMI,\r
- eRoleUnknownFormFactor\r
-}\r
-PaWasapiDeviceRole;\r
+int PaWasapi_GetDeviceDefaultFormat( void *pFormat, unsigned int nFormatSize, PaDeviceIndex nDevice );\r
\r
\r
/** Returns device role (PaWasapiDeviceRole enum).\r
@param hTask a handle to pointer to priority task. Must be used with PaWasapi_RevertThreadPriority\r
method to revert thread priority to initial state.\r
\r
- @param nPriorityClass an Id of thread priority: 1 - Audio\r
- 2 - Capture\r
- 3 - Distribution\r
- 4 - Games\r
- 5 - Playback\r
- 6 - Pro Audio\r
- 7 - Window Manager\r
+ @param nPriorityClass an Id of thread priority of PaWasapiThreadPriority type. Specifying \r
+ eThreadPriorityNone does nothing.\r
\r
@return Error code indicating success or failure.\r
@see PaWasapi_RevertThreadPriority\r
*/\r
-PaError PaWasapi_ThreadPriorityBoost( void **hTask, int nPriorityClass );\r
+PaError PaWasapi_ThreadPriorityBoost( void **hTask, PaWasapiThreadPriority nPriorityClass );\r
\r
\r
/** Boost thread priority of calling thread (MMCSS). Use it for Blocking Interface only for thread\r
\r
enum { S_INPUT = 0, S_OUTPUT, S_COUNT };\r
\r
+#define STATIC_ARRAY_SIZE(array) (sizeof(array)/sizeof(array[0]))\r
+\r
#define PRINT(x) PA_DEBUG(x);\r
\r
#define PA_SKELETON_SET_LAST_HOST_ERROR( errorCode, errorText ) \\r
\r
// Av Task (MM thread management)\r
HANDLE hAvTask;\r
+\r
+ // Thread priority level\r
+ PaWasapiThreadPriority nThreadPriority;\r
}\r
PaWasapiStream;\r
\r
}\r
\r
// ------------------------------------------------------------------------------------------\r
-int PaWasapi_GetDeviceDefaultFormat( void *pFormat, int nFormatSize, PaDeviceIndex nDevice )\r
+int PaWasapi_GetDeviceDefaultFormat( void *pFormat, unsigned int nFormatSize, PaDeviceIndex nDevice )\r
{\r
if (pFormat == NULL)\r
return paBadBufferPtr;\r
if (paWasapi == NULL)\r
return ret;\r
\r
- if (nDevice >= (int)paWasapi->deviceCount)\r
+ if ((UINT32)nDevice >= paWasapi->deviceCount)\r
return paInvalidDevice;\r
\r
- int size = min(nFormatSize, sizeof(paWasapi->devInfo[ nDevice ].DefaultFormat));\r
+ UINT32 size = min(nFormatSize, (UINT32)sizeof(paWasapi->devInfo[ nDevice ].DefaultFormat));\r
memcpy(pFormat, &paWasapi->devInfo[ nDevice ].DefaultFormat, size);\r
\r
return size;\r
goto error;\r
}\r
\r
+ // Default thread priority is Audio: for exclusive mode we will use Pro Audio.\r
+ stream->nThreadPriority = eThreadPriorityAudio;\r
+\r
// Try create device: Input\r
if (inputParameters != NULL)\r
{\r
// Select Exclusive/Shared mode\r
stream->in.shareMode = AUDCLNT_SHAREMODE_SHARED;\r
if ((inputStreamInfo != NULL) && (inputStreamInfo->flags & paWinWasapiExclusive))\r
+ {\r
+ // Boost thread priority\r
+ stream->nThreadPriority = eThreadPriorityProAudio;\r
+ // Make Exclusive\r
stream->in.shareMode = AUDCLNT_SHAREMODE_EXCLUSIVE;\r
+ }\r
+\r
+ // If user provided explicit thread priority level, use it\r
+ if ((inputStreamInfo != NULL) && (inputStreamInfo->flags & paWinWasapiThreadPriority))\r
+ {\r
+ if ((inputStreamInfo->threadPriority > eThreadPriorityNone) &&\r
+ (inputStreamInfo->threadPriority <= eThreadPriorityWindowManager))\r
+ stream->nThreadPriority = inputStreamInfo->threadPriority;\r
+ }\r
\r
// Choose processing mode\r
stream->in.streamFlags = AUDCLNT_STREAMFLAGS_EVENTCALLBACK;\r
// Select Exclusive/Shared mode\r
stream->out.shareMode = AUDCLNT_SHAREMODE_SHARED;\r
if ((outputStreamInfo != NULL) && (outputStreamInfo->flags & paWinWasapiExclusive))\r
+ {\r
+ // Boost thread priority\r
+ stream->nThreadPriority = eThreadPriorityProAudio;\r
+ // Make Exclusive\r
stream->out.shareMode = AUDCLNT_SHAREMODE_EXCLUSIVE;\r
+ }\r
+\r
+ // If user provided explicit thread priority level, use it\r
+ if ((outputStreamInfo != NULL) && (outputStreamInfo->flags & paWinWasapiThreadPriority))\r
+ {\r
+ if ((outputStreamInfo->threadPriority > eThreadPriorityNone) &&\r
+ (outputStreamInfo->threadPriority <= eThreadPriorityWindowManager))\r
+ stream->nThreadPriority = outputStreamInfo->threadPriority;\r
+ }\r
\r
// Choose processing mode\r
stream->out.streamFlags = AUDCLNT_STREAMFLAGS_EVENTCALLBACK;\r
}\r
\r
// ------------------------------------------------------------------------------------------\r
-PaError PaWasapi_ThreadPriorityBoost(void **hTask, int nPriorityClass)\r
+PaError PaWasapi_ThreadPriorityBoost(void **hTask, PaWasapiThreadPriority nPriorityClass)\r
{\r
if (hTask == NULL)\r
return paUnanticipatedHostError;\r
\r
- static const char *mmcs_name[7] = \r
+ static const char *mmcs_name[] = \r
{\r
+ NULL,\r
"Audio",\r
"Capture",\r
"Distribution",\r
"Pro Audio",\r
"Window Manager"\r
};\r
- if ((UINT32)nPriorityClass >= 7)\r
+ if ((UINT32)nPriorityClass >= STATIC_ARRAY_SIZE(mmcs_name))\r
return paUnanticipatedHostError;\r
\r
HANDLE task = MMCSS_activate(mmcs_name[nPriorityClass]);\r
// Restore thread priority\r
if (stream->hAvTask != NULL)\r
{\r
- MMCSS_deactivate(stream->hAvTask);\r
+ PaWasapi_ThreadPriorityRevert(stream->hAvTask);\r
stream->hAvTask = NULL;\r
}\r
\r
}\r
\r
// Boost thread priority\r
- stream->hAvTask = MMCSS_activate("Pro Audio");\r
+ stream->hAvTask = NULL;\r
+ PaWasapi_ThreadPriorityBoost((void **)&stream->hAvTask, stream->nThreadPriority);\r
\r
// Initialize event & start INPUT stream\r
if (stream->in.client)\r
processor[S_OUTPUT] = (stream->hostProcessOverrideOutput.processor != NULL ? stream->hostProcessOverrideOutput : defaultProcessor);\r
\r
// Boost thread priority\r
- stream->hAvTask = MMCSS_activate("Pro Audio");\r
+ stream->hAvTask = NULL;\r
+ PaWasapi_ThreadPriorityBoost((void **)&stream->hAvTask, stream->nThreadPriority);\r
\r
// Initialize event & start INPUT stream\r
if (stream->in.client)\r