improved PaWasapi_ThreadPriorityBoost by providing enum PaWasapiThreadPriority with explicit thread priority values for convenience. it is possible to override default thread priority setting for Event/Poll-driven modes by specifying new flag paWinWasapiThreadPriority and setting priority value through PaWasapiStreamInfo::threadPriority member.
This commit is contained in:
parent
8185016b2a
commit
75e59cb874
2 changed files with 101 additions and 38 deletions
|
|
@ -68,12 +68,17 @@ typedef enum PaWasapiFlags
|
|||
Note: WASAPI Event driven core is capable of 2ms latency!!!, but Polling
|
||||
method can only provide 15-20ms latency. */
|
||||
paWinWasapiPolling = (1 << 3),
|
||||
|
||||
/* forces custom thread priority setting. must be used if PaWasapiStreamInfo::threadPriority
|
||||
is set to custom value. */
|
||||
paWinWasapiThreadPriority = (1 << 4)
|
||||
}
|
||||
PaWasapiFlags;
|
||||
#define paWinWasapiExclusive (paWinWasapiExclusive)
|
||||
#define paWinWasapiRedirectHostProcessor (paWinWasapiRedirectHostProcessor)
|
||||
#define paWinWasapiUseChannelMask (paWinWasapiUseChannelMask)
|
||||
#define paWinWasapiPolling (paWinWasapiPolling)
|
||||
#define paWinWasapiThreadPriority (paWinWasapiThreadPriority)
|
||||
|
||||
|
||||
/* Host processor. Allows to skip internal PA processing completely.
|
||||
|
|
@ -86,46 +91,6 @@ typedef void (*PaWasapiHostProcessorCallback) (void *inputBuffer, long inputFra
|
|||
void *outputBuffer, long outputFrames,
|
||||
void *userData);
|
||||
|
||||
/* Stream descriptor. */
|
||||
typedef struct PaWasapiStreamInfo
|
||||
{
|
||||
unsigned long size; /**< sizeof(PaWasapiStreamInfo) */
|
||||
PaHostApiTypeId hostApiType; /**< paWASAPI */
|
||||
unsigned long version; /**< 1 */
|
||||
|
||||
unsigned long flags; /**< collection of PaWasapiFlags */
|
||||
|
||||
/* Support for WAVEFORMATEXTENSIBLE channel masks. If flags contains
|
||||
paWinWasapiUseChannelMask this allows you to specify which speakers
|
||||
to address in a multichannel stream. Constants for channelMask
|
||||
are specified in pa_win_waveformat.h
|
||||
*/
|
||||
PaWinWaveFormatChannelMask channelMask;
|
||||
|
||||
/* Delivers raw data to callback obtained from GetBuffer() methods skipping
|
||||
internal PortAudio processing inventory completely. userData parameter will
|
||||
be the same that was passed to Pa_OpenStream method.
|
||||
*/
|
||||
PaWasapiHostProcessorCallback hostProcessorOutput;
|
||||
PaWasapiHostProcessorCallback hostProcessorInput;
|
||||
}
|
||||
PaWasapiStreamInfo;
|
||||
|
||||
|
||||
/** Returns default sound format for device. Format is represented by PaWinWaveFormat or
|
||||
WAVEFORMATEXTENSIBLE structure.
|
||||
|
||||
@param pFormat pointer to PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure.
|
||||
@param nFormatSize pize of PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure in bytes.
|
||||
@param nDevice device index.
|
||||
|
||||
@return A non-negative value indicating the number of bytes copied into format decriptor
|
||||
or, a PaErrorCode (which are always negative) if PortAudio is not initialized
|
||||
or an error is encountered.
|
||||
*/
|
||||
int PaWasapi_GetDeviceDefaultFormat( void *pFormat, int nFormatSize, PaDeviceIndex nDevice );
|
||||
|
||||
|
||||
/* Device role */
|
||||
typedef enum PaWasapiDeviceRole
|
||||
{
|
||||
|
|
@ -144,6 +109,72 @@ typedef enum PaWasapiDeviceRole
|
|||
PaWasapiDeviceRole;
|
||||
|
||||
|
||||
/* Thread priority */
|
||||
typedef enum PaWasapiThreadPriority
|
||||
{
|
||||
eThreadPriorityNone = 0,
|
||||
eThreadPriorityAudio, //!< Default for Shared mode.
|
||||
eThreadPriorityCapture,
|
||||
eThreadPriorityDistribution,
|
||||
eThreadPriorityGames,
|
||||
eThreadPriorityPlayback,
|
||||
eThreadPriorityProAudio, //!< Default for Exclusive mode.
|
||||
eThreadPriorityWindowManager
|
||||
}
|
||||
PaWasapiThreadPriority;
|
||||
|
||||
|
||||
/* Stream descriptor. */
|
||||
typedef struct PaWasapiStreamInfo
|
||||
{
|
||||
unsigned long size; /**< sizeof(PaWasapiStreamInfo) */
|
||||
PaHostApiTypeId hostApiType; /**< paWASAPI */
|
||||
unsigned long version; /**< 1 */
|
||||
|
||||
unsigned long flags; /**< collection of PaWasapiFlags */
|
||||
|
||||
/* Support for WAVEFORMATEXTENSIBLE channel masks. If flags contains
|
||||
paWinWasapiUseChannelMask this allows you to specify which speakers
|
||||
to address in a multichannel stream. Constants for channelMask
|
||||
are specified in pa_win_waveformat.h. Will be used only if
|
||||
paWinWasapiUseChannelMask flag is specified.
|
||||
*/
|
||||
PaWinWaveFormatChannelMask channelMask;
|
||||
|
||||
/* Delivers raw data to callback obtained from GetBuffer() methods skipping
|
||||
internal PortAudio processing inventory completely. userData parameter will
|
||||
be the same that was passed to Pa_OpenStream method. Will be used only if
|
||||
paWinWasapiRedirectHostProcessor flag is specified.
|
||||
*/
|
||||
PaWasapiHostProcessorCallback hostProcessorOutput;
|
||||
PaWasapiHostProcessorCallback hostProcessorInput;
|
||||
|
||||
/* Specifies thread priority explicitly. Will be used only if paWinWasapiThreadPriority flag
|
||||
is specified.
|
||||
|
||||
Please note, if Input/Output streams are opened simultaniously (Full-Duplex mode)
|
||||
you shall specify same value for threadPriority or othervise one of the values will be used
|
||||
to setup thread priority.
|
||||
*/
|
||||
PaWasapiThreadPriority threadPriority;
|
||||
}
|
||||
PaWasapiStreamInfo;
|
||||
|
||||
|
||||
/** Returns default sound format for device. Format is represented by PaWinWaveFormat or
|
||||
WAVEFORMATEXTENSIBLE structure.
|
||||
|
||||
@param pFormat pointer to PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure.
|
||||
@param nFormatSize pize of PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure in bytes.
|
||||
@param nDevice device index.
|
||||
|
||||
@return A non-negative value indicating the number of bytes copied into format decriptor
|
||||
or, a PaErrorCode (which are always negative) if PortAudio is not initialized
|
||||
or an error is encountered.
|
||||
*/
|
||||
int PaWasapi_GetDeviceDefaultFormat( void *pFormat, unsigned int nFormatSize, PaDeviceIndex nDevice );
|
||||
|
||||
|
||||
/** Returns device role (PaWasapiDeviceRole enum).
|
||||
|
||||
@param nDevice device index.
|
||||
|
|
@ -160,18 +191,13 @@ int/*PaWasapiDeviceRole*/ PaWasapi_GetDeviceRole( PaDeviceIndex nDevice );
|
|||
@param hTask a handle to pointer to priority task. Must be used with PaWasapi_RevertThreadPriority
|
||||
method to revert thread priority to initial state.
|
||||
|
||||
@param nPriorityClass an Id of thread priority: 1 - Audio
|
||||
2 - Capture
|
||||
3 - Distribution
|
||||
4 - Games
|
||||
5 - Playback
|
||||
6 - Pro Audio
|
||||
7 - Window Manager
|
||||
@param nPriorityClass an Id of thread priority of PaWasapiThreadPriority type. Specifying
|
||||
eThreadPriorityNone does nothing.
|
||||
|
||||
@return Error code indicating success or failure.
|
||||
@see PaWasapi_RevertThreadPriority
|
||||
*/
|
||||
PaError PaWasapi_ThreadPriorityBoost( void **hTask, int nPriorityClass );
|
||||
PaError PaWasapi_ThreadPriorityBoost( void **hTask, PaWasapiThreadPriority nPriorityClass );
|
||||
|
||||
|
||||
/** Boost thread priority of calling thread (MMCSS). Use it for Blocking Interface only for thread
|
||||
|
|
|
|||
|
|
@ -97,6 +97,8 @@ PA_THREAD_FUNC ProcThreadPoll(void *param);
|
|||
|
||||
enum { S_INPUT = 0, S_OUTPUT, S_COUNT };
|
||||
|
||||
#define STATIC_ARRAY_SIZE(array) (sizeof(array)/sizeof(array[0]))
|
||||
|
||||
#define PRINT(x) PA_DEBUG(x);
|
||||
|
||||
#define PA_SKELETON_SET_LAST_HOST_ERROR( errorCode, errorText ) \
|
||||
|
|
@ -315,6 +317,9 @@ typedef struct PaWasapiStream
|
|||
|
||||
// Av Task (MM thread management)
|
||||
HANDLE hAvTask;
|
||||
|
||||
// Thread priority level
|
||||
PaWasapiThreadPriority nThreadPriority;
|
||||
}
|
||||
PaWasapiStream;
|
||||
|
||||
|
|
@ -893,7 +898,7 @@ static inline PaWasapiHostApiRepresentation *GetHostApi(PaError *_error = NULL)
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
int PaWasapi_GetDeviceDefaultFormat( void *pFormat, int nFormatSize, PaDeviceIndex nDevice )
|
||||
int PaWasapi_GetDeviceDefaultFormat( void *pFormat, unsigned int nFormatSize, PaDeviceIndex nDevice )
|
||||
{
|
||||
if (pFormat == NULL)
|
||||
return paBadBufferPtr;
|
||||
|
|
@ -907,10 +912,10 @@ int PaWasapi_GetDeviceDefaultFormat( void *pFormat, int nFormatSize, PaDeviceInd
|
|||
if (paWasapi == NULL)
|
||||
return ret;
|
||||
|
||||
if (nDevice >= (int)paWasapi->deviceCount)
|
||||
if ((UINT32)nDevice >= paWasapi->deviceCount)
|
||||
return paInvalidDevice;
|
||||
|
||||
int size = min(nFormatSize, sizeof(paWasapi->devInfo[ nDevice ].DefaultFormat));
|
||||
UINT32 size = min(nFormatSize, (UINT32)sizeof(paWasapi->devInfo[ nDevice ].DefaultFormat));
|
||||
memcpy(pFormat, &paWasapi->devInfo[ nDevice ].DefaultFormat, size);
|
||||
|
||||
return size;
|
||||
|
|
@ -1560,6 +1565,9 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
|
|||
goto error;
|
||||
}
|
||||
|
||||
// Default thread priority is Audio: for exclusive mode we will use Pro Audio.
|
||||
stream->nThreadPriority = eThreadPriorityAudio;
|
||||
|
||||
// Try create device: Input
|
||||
if (inputParameters != NULL)
|
||||
{
|
||||
|
|
@ -1572,7 +1580,20 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
|
|||
// Select Exclusive/Shared mode
|
||||
stream->in.shareMode = AUDCLNT_SHAREMODE_SHARED;
|
||||
if ((inputStreamInfo != NULL) && (inputStreamInfo->flags & paWinWasapiExclusive))
|
||||
{
|
||||
// Boost thread priority
|
||||
stream->nThreadPriority = eThreadPriorityProAudio;
|
||||
// Make Exclusive
|
||||
stream->in.shareMode = AUDCLNT_SHAREMODE_EXCLUSIVE;
|
||||
}
|
||||
|
||||
// If user provided explicit thread priority level, use it
|
||||
if ((inputStreamInfo != NULL) && (inputStreamInfo->flags & paWinWasapiThreadPriority))
|
||||
{
|
||||
if ((inputStreamInfo->threadPriority > eThreadPriorityNone) &&
|
||||
(inputStreamInfo->threadPriority <= eThreadPriorityWindowManager))
|
||||
stream->nThreadPriority = inputStreamInfo->threadPriority;
|
||||
}
|
||||
|
||||
// Choose processing mode
|
||||
stream->in.streamFlags = AUDCLNT_STREAMFLAGS_EVENTCALLBACK;
|
||||
|
|
@ -1661,7 +1682,20 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
|
|||
// Select Exclusive/Shared mode
|
||||
stream->out.shareMode = AUDCLNT_SHAREMODE_SHARED;
|
||||
if ((outputStreamInfo != NULL) && (outputStreamInfo->flags & paWinWasapiExclusive))
|
||||
{
|
||||
// Boost thread priority
|
||||
stream->nThreadPriority = eThreadPriorityProAudio;
|
||||
// Make Exclusive
|
||||
stream->out.shareMode = AUDCLNT_SHAREMODE_EXCLUSIVE;
|
||||
}
|
||||
|
||||
// If user provided explicit thread priority level, use it
|
||||
if ((outputStreamInfo != NULL) && (outputStreamInfo->flags & paWinWasapiThreadPriority))
|
||||
{
|
||||
if ((outputStreamInfo->threadPriority > eThreadPriorityNone) &&
|
||||
(outputStreamInfo->threadPriority <= eThreadPriorityWindowManager))
|
||||
stream->nThreadPriority = outputStreamInfo->threadPriority;
|
||||
}
|
||||
|
||||
// Choose processing mode
|
||||
stream->out.streamFlags = AUDCLNT_STREAMFLAGS_EVENTCALLBACK;
|
||||
|
|
@ -2440,13 +2474,14 @@ void MMCSS_deactivate(HANDLE hTask)
|
|||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
PaError PaWasapi_ThreadPriorityBoost(void **hTask, int nPriorityClass)
|
||||
PaError PaWasapi_ThreadPriorityBoost(void **hTask, PaWasapiThreadPriority nPriorityClass)
|
||||
{
|
||||
if (hTask == NULL)
|
||||
return paUnanticipatedHostError;
|
||||
|
||||
static const char *mmcs_name[7] =
|
||||
static const char *mmcs_name[] =
|
||||
{
|
||||
NULL,
|
||||
"Audio",
|
||||
"Capture",
|
||||
"Distribution",
|
||||
|
|
@ -2455,7 +2490,7 @@ PaError PaWasapi_ThreadPriorityBoost(void **hTask, int nPriorityClass)
|
|||
"Pro Audio",
|
||||
"Window Manager"
|
||||
};
|
||||
if ((UINT32)nPriorityClass >= 7)
|
||||
if ((UINT32)nPriorityClass >= STATIC_ARRAY_SIZE(mmcs_name))
|
||||
return paUnanticipatedHostError;
|
||||
|
||||
HANDLE task = MMCSS_activate(mmcs_name[nPriorityClass]);
|
||||
|
|
@ -2546,7 +2581,7 @@ void _OnStreamStop(PaWasapiStream *stream)
|
|||
// Restore thread priority
|
||||
if (stream->hAvTask != NULL)
|
||||
{
|
||||
MMCSS_deactivate(stream->hAvTask);
|
||||
PaWasapi_ThreadPriorityRevert(stream->hAvTask);
|
||||
stream->hAvTask = NULL;
|
||||
}
|
||||
|
||||
|
|
@ -2584,7 +2619,8 @@ PA_THREAD_FUNC ProcThreadEvent(void *param)
|
|||
}
|
||||
|
||||
// Boost thread priority
|
||||
stream->hAvTask = MMCSS_activate("Pro Audio");
|
||||
stream->hAvTask = NULL;
|
||||
PaWasapi_ThreadPriorityBoost((void **)&stream->hAvTask, stream->nThreadPriority);
|
||||
|
||||
// Initialize event & start INPUT stream
|
||||
if (stream->in.client)
|
||||
|
|
@ -2693,7 +2729,8 @@ PA_THREAD_FUNC ProcThreadPoll(void *param)
|
|||
processor[S_OUTPUT] = (stream->hostProcessOverrideOutput.processor != NULL ? stream->hostProcessOverrideOutput : defaultProcessor);
|
||||
|
||||
// Boost thread priority
|
||||
stream->hAvTask = MMCSS_activate("Pro Audio");
|
||||
stream->hAvTask = NULL;
|
||||
PaWasapi_ThreadPriorityBoost((void **)&stream->hAvTask, stream->nThreadPriority);
|
||||
|
||||
// Initialize event & start INPUT stream
|
||||
if (stream->in.client)
|
||||
|
|
|
|||
Loading…
Reference in a new issue