diff options
Diffstat (limited to '3rdparty/portaudio/include/pa_win_wasapi.h')
-rw-r--r-- | 3rdparty/portaudio/include/pa_win_wasapi.h | 579 |
1 files changed, 475 insertions, 104 deletions
diff --git a/3rdparty/portaudio/include/pa_win_wasapi.h b/3rdparty/portaudio/include/pa_win_wasapi.h index 1d86896caef..ca75acb8b33 100644 --- a/3rdparty/portaudio/include/pa_win_wasapi.h +++ b/3rdparty/portaudio/include/pa_win_wasapi.h @@ -3,9 +3,11 @@ /* * $Id: $ * PortAudio Portable Real-Time Audio Library - * DirectSound specific extensions + * WASAPI specific extensions * - * Copyright (c) 1999-2007 Ross Bencina and Phil Burk + * Copyright (c) 1999-2018 Ross Bencina and Phil Burk + * Copyright (c) 2006-2010 David Viens + * Copyright (c) 2010-2022 Dmitry Kostjuchenko * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files @@ -28,13 +30,13 @@ */ /* - * The text above constitutes the entire PortAudio license; however, + * The text above constitutes the entire PortAudio license; however, * the PortAudio community also makes the following non-binding requests: * * Any person wishing to distribute modifications to the Software is * requested to send the modifications to the original developer so that - * they can be incorporated into the canonical version. It is also - * requested that these non-binding requests be included along with the + * they can be incorporated into the canonical version. It is also + * requested that these non-binding requests be included along with the * license above. */ @@ -52,26 +54,40 @@ extern "C" #endif /* __cplusplus */ -/* Setup flags */ +/* Stream setup flags. */ typedef enum PaWasapiFlags { - /* puts WASAPI into exclusive mode */ + /* put WASAPI into exclusive mode */ paWinWasapiExclusive = (1 << 0), - /* allows to skip internal PA processing completely */ + /* allow to skip internal PA processing completely */ paWinWasapiRedirectHostProcessor = (1 << 1), - /* assigns custom channel mask */ + /* assign custom channel mask */ paWinWasapiUseChannelMask = (1 << 2), - /* selects non-Event driven method of data read/write - Note: WASAPI Event driven core is capable of 2ms latency!!!, but Polling - method can only provide 15-20ms latency. */ + /* use Polling method (Event method is the default, see details in the IMPORTANT notes) */ paWinWasapiPolling = (1 << 3), - /* forces custom thread priority setting, must be used if PaWasapiStreamInfo::threadPriority + /* force custom thread priority setting, must be used if PaWasapiStreamInfo::threadPriority is set to a custom value */ - paWinWasapiThreadPriority = (1 << 4) + paWinWasapiThreadPriority = (1 << 4), + + /* force explicit sample format and do not allow PA to select suitable working format, API will + fail if provided sample format is not supported by audio hardware in Exclusive mode + or system mixer in Shared mode */ + paWinWasapiExplicitSampleFormat = (1 << 5), + + /* allow API to insert system-level channel matrix mixer and sample rate converter to allow + playback formats that do not match the current configured system settings. + this is in particular required for streams not matching the system mixer sample rate. + only applies in Shared mode. */ + paWinWasapiAutoConvert = (1 << 6), + + /* use Passthrough mode for sending encoded audio data in PCM containers to the audio device, + refer to Microsoft documentation "Representing Formats for IEC 61937 Transmissions" for more + details about data representation and stream configuration */ + paWinWasapiPassthrough = (1 << 7), } PaWasapiFlags; #define paWinWasapiExclusive (paWinWasapiExclusive) @@ -79,17 +95,67 @@ PaWasapiFlags; #define paWinWasapiUseChannelMask (paWinWasapiUseChannelMask) #define paWinWasapiPolling (paWinWasapiPolling) #define paWinWasapiThreadPriority (paWinWasapiThreadPriority) +#define paWinWasapiExplicitSampleFormat (paWinWasapiExplicitSampleFormat) +#define paWinWasapiAutoConvert (paWinWasapiAutoConvert) +#define paWinWasapiPassthrough (paWinWasapiPassthrough) -/* Host processor. Allows to skip internal PA processing completely. - You must set paWinWasapiRedirectHostProcessor flag to PaWasapiStreamInfo::flags member - in order to have host processor redirected to your callback. +/* Stream state. + + @note Multiple states can be united into a bitmask. + @see PaWasapiStreamStateCallback, PaWasapi_SetStreamStateHandler +*/ +typedef enum PaWasapiStreamState +{ + /* state change was caused by the error: + + Example: + 1) If thread execution stopped due to AUDCLNT_E_RESOURCES_INVALIDATED then state + value will contain paWasapiStreamStateError|paWasapiStreamStateThreadStop. + */ + paWasapiStreamStateError = (1 << 0), + + /* processing thread is preparing to start execution */ + paWasapiStreamStateThreadPrepare = (1 << 1), + + /* processing thread started execution (enters its loop) */ + paWasapiStreamStateThreadStart = (1 << 2), + + /* processing thread stopped execution */ + paWasapiStreamStateThreadStop = (1 << 3) +} +PaWasapiStreamState; +#define paWasapiStreamStateError (paWasapiStreamStateError) +#define paWasapiStreamStateThreadPrepare (paWasapiStreamStateThreadPrepare) +#define paWasapiStreamStateThreadStart (paWasapiStreamStateThreadStart) +#define paWasapiStreamStateThreadStop (paWasapiStreamStateThreadStop) + + +/* Host processor. + + Allows to skip internal PA processing completely. paWinWasapiRedirectHostProcessor flag + must be set to the PaWasapiStreamInfo::flags member in order to have host processor + redirected to this callback. + Use with caution! inputFrames and outputFrames depend solely on final device setup. - To query maximal values of inputFrames/outputFrames use PaWasapi_GetFramesPerHostBuffer. + To query max values of inputFrames/outputFrames use PaWasapi_GetFramesPerHostBuffer. +*/ +typedef void (*PaWasapiHostProcessorCallback) (void *inputBuffer, long inputFrames, + void *outputBuffer, long outputFrames, void *userData); + + +/* Stream state handler. + + @param pStream Pointer to PaStream object. + @param stateFlags State flags, a collection of values from PaWasapiStreamState enum. + @param errorId Error id provided by system API (HRESULT). + @param userData Pointer to user data. + + @see PaWasapiStreamState */ -typedef void (*PaWasapiHostProcessorCallback) (void *inputBuffer, long inputFrames, - void *outputBuffer, long outputFrames, - void *userData); +typedef void (*PaWasapiStreamStateCallback) (PaStream *pStream, unsigned int stateFlags, + unsigned int errorId, void *pUserData); + /* Device role. */ typedef enum PaWasapiDeviceRole @@ -124,7 +190,7 @@ typedef enum PaWasapiJackConnectionType eJackConnTypeXlrProfessional, eJackConnTypeRJ11Modem, eJackConnTypeCombination -} +} PaWasapiJackConnectionType; @@ -147,7 +213,7 @@ typedef enum PaWasapiJackGeoLocation eJackGeoLocATAPI, eJackGeoLocReserved5, eJackGeoLocReserved6, -} +} PaWasapiJackGeoLocation; @@ -158,7 +224,7 @@ typedef enum PaWasapiJackGenLocation eJackGenLocInternal, eJackGenLocSeparate, eJackGenLocOther -} +} PaWasapiJackGenLocation; @@ -169,7 +235,7 @@ typedef enum PaWasapiJackPortConnection eJackPortConnIntegratedDevice, eJackPortConnBothIntegratedAndJack, eJackPortConnUnknown -} +} PaWasapiJackPortConnection; @@ -177,7 +243,7 @@ PaWasapiJackPortConnection; typedef enum PaWasapiThreadPriority { eThreadPriorityNone = 0, - eThreadPriorityAudio, //!< Default for Shared mode. + eThreadPriorityAudio, //!< Default for Shared mode. eThreadPriorityCapture, eThreadPriorityDistribution, eThreadPriorityGames, @@ -189,7 +255,7 @@ PaWasapiThreadPriority; /* Stream descriptor. */ -typedef struct PaWasapiJackDescription +typedef struct PaWasapiJackDescription { unsigned long channelMapping; unsigned long color; /* derived from macro: #define RGB(r,g,b) ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16))) */ @@ -205,7 +271,7 @@ PaWasapiJackDescription; /** Stream category. Note: - values are equal to WASAPI AUDIO_STREAM_CATEGORY enum - - supported since Windows 8.0, noop on earler versions + - supported since Windows 8.0, noop on earlier versions - values 1,2 are deprecated on Windows 10 and not included into enumeration @version Available as of 19.6.0 @@ -229,7 +295,7 @@ PaWasapiStreamCategory; /** Stream option. Note: - values are equal to WASAPI AUDCLNT_STREAMOPTIONS enum - - supported since Windows 8.1, noop on earler versions + - supported since Windows 8.1, noop on earlier versions @version Available as of 19.6.0 */ @@ -242,8 +308,63 @@ typedef enum PaWasapiStreamOption PaWasapiStreamOption; +/** Passthrough format. + + Format ids are obtained from the Microsoft documentation "Representing Formats for IEC 61937 Transmissions" + and are composed by such formula where GUID is the guid of passthrough format: + GUID.Data1 << 16 | GUID.Data2. + + @see PaWasapiStreamPassthrough + @version Available as of 19.8.0 +*/ +typedef enum PaWasapiPassthroughFormat +{ + ePassthroughFormatPcmIec60958 = 0x00000000, + ePassthroughFormatDolbyDigital = 0x00920000, + ePassthroughFormatMpeg1 = 0x00030cea, + ePassthroughFormatMpeg3 = 0x00040cea, + ePassthroughFormatMpeg2 = 0x00050cea, + ePassthroughFormatAac = 0x00060cea, + ePassthroughFormatDts = 0x00080cea, + ePassthroughFormatDolbyDigitalPlus = 0x000a0cea, + ePassthroughFormatDolbyDigitalPlusAtmos = 0x010a0cea, + ePassthroughFormatDtsHd = 0x000b0cea, + ePassthroughFormatDtsXE1 = 0x010b0cea, + ePassthroughFormatDtsXE2 = 0x030b0cea, + ePassthroughFormatDolbyMlp = 0x000c0cea, + ePassthroughFormatDolbyMat20 = 0x010c0cea, + ePassthroughFormatDolbyMat21 = 0x030c0cea, + ePassthroughFormatWmaPro = 0x01640000, + ePassthroughFormatAtrac = 0x00080cea, + ePassthroughFormatOneBitAudio = 0x00090cea, + ePassthroughFormatDst = 0x000d0cea, +} +PaWasapiPassthroughFormat; + + +/** Passthrough details. + + Passthrough details provide direct link to the additional members in WAVEFORMATEXTENSIBLE_IEC61937. + Passthrough mode allows to pass encoded data inside the PCM containers to the audio device. + + Detailed description about supported formats and examples are provided in Microsoft documentation + "Representing Formats for IEC 61937 Transmissions". + + @see paWinWasapiPassthrough + @version Available as of 19.8.0 +*/ +typedef struct PaWasapiStreamPassthrough +{ + PaWasapiPassthroughFormat formatId; + unsigned int encodedSamplesPerSec; + unsigned int encodedChannelCount; + unsigned int averageBytesPerSec; +} +PaWasapiStreamPassthrough; + + /* Stream descriptor. */ -typedef struct PaWasapiStreamInfo +typedef struct PaWasapiStreamInfo { unsigned long size; /**< sizeof(PaWasapiStreamInfo) */ PaHostApiTypeId hostApiType; /**< paWASAPI */ @@ -252,16 +373,16 @@ typedef struct PaWasapiStreamInfo unsigned long flags; /**< collection of PaWasapiFlags */ /** Support for WAVEFORMATEXTENSIBLE channel masks. If flags contains - paWinWasapiUseChannelMask this allows you to specify which speakers + 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 + 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 + 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; @@ -270,7 +391,7 @@ typedef struct PaWasapiStreamInfo /** 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) + Please note, if Input/Output streams are opened simultaneously (Full-Duplex mode) you shall specify same value for threadPriority or othervise one of the values will be used to setup thread priority. */ @@ -287,103 +408,289 @@ typedef struct PaWasapiStreamInfo @version Available as of 19.6.0 */ PaWasapiStreamOption streamOption; -} + + /** Passthrough details. + @note paWinWasapiPassthrough flag must be specified in PaWasapiStreamInfo::flags to enable Passthrough mode. + @see paWinWasapiPassthrough + @version Available as of 19.7.0 + */ + PaWasapiStreamPassthrough passthrough; +} PaWasapiStreamInfo; -/** Returns default sound format for device. Format is represented by PaWinWaveFormat or - WAVEFORMATEXTENSIBLE structure. +/** Returns pointer to WASAPI's IAudioClient object of the stream. + + @param pStream Pointer to PaStream object. + @param pAudioClient Pointer to pointer of IAudioClient. + @param bOutput TRUE (1) for output stream, FALSE (0) for input stream. + + @return Error code indicating success or failure. +*/ +PaError PaWasapi_GetAudioClient( PaStream *pStream, void **pAudioClient, int bOutput ); + + +/** Update device list. + + This function is available if PA_WASAPI_MAX_CONST_DEVICE_COUNT is defined during compile time + with maximum constant WASAPI device count (recommended value - 32). + If PA_WASAPI_MAX_CONST_DEVICE_COUNT is set to 0 (or not defined) during compile time the implementation + will not define PaWasapi_UpdateDeviceList() and thus updating device list can only be possible by calling + Pa_Terminate() and then Pa_Initialize(). + + @return Error code indicating success or failure. +*/ +PaError PaWasapi_UpdateDeviceList(); + + +/** Get current audio format of the device assigned to the opened stream. + + Format is represented by PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure. + Use this function to reconfirm format if PA's processor is overridden and + paWinWasapiRedirectHostProcessor flag is specified. - @param pFormat Pointer to PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure. - @param nFormatSize Size of PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure in bytes. - @param nDevice Device index. + @param pStream Pointer to PaStream object. + @param pFormat Pointer to PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure. + @param formatSize Size of PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure in bytes. + @param bOutput TRUE (1) for output stream, FALSE (0) for input stream. - @return Non-negative value indicating the number of bytes copied into format decriptor - or, a PaErrorCode (which are always negative) if PortAudio is not initialized + @return Non-negative value indicating the number of bytes copied into format descriptor + or, a PaErrorCode (which is always negative) if PortAudio is not initialized or an error is encountered. */ -int PaWasapi_GetDeviceDefaultFormat( void *pFormat, unsigned int nFormatSize, PaDeviceIndex nDevice ); +int PaWasapi_GetDeviceCurrentFormat( PaStream *pStream, void *pFormat, unsigned int formatSize, int bOutput ); + + +/** Get default audio format for the device in Shared Mode. + + Format is represented by PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure and obtained + by getting the device property with a PKEY_AudioEngine_DeviceFormat key. + + @param pFormat Pointer to PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure. + @param formatSize Size of PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure in bytes. + @param device Device index. + + @return Non-negative value indicating the number of bytes copied into format descriptor + or, a PaErrorCode (which is always negative) if PortAudio is not initialized + or an error is encountered. +*/ +int PaWasapi_GetDeviceDefaultFormat( void *pFormat, unsigned int formatSize, PaDeviceIndex device ); + + +/** Get mix audio format for the device in Shared Mode. + + Format is represented by PaWinWaveFormat or WAVEFORMATEXTENSIBLE structureand obtained by + IAudioClient::GetMixFormat. + + @param pFormat Pointer to PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure. + @param formatSize Size of PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure in bytes. + @param device Device index. + + @return Non-negative value indicating the number of bytes copied into format descriptor + or, a PaErrorCode (which is always negative) if PortAudio is not initialized + or an error is encountered. +*/ +int PaWasapi_GetDeviceMixFormat( void *pFormat, unsigned int formatSize, PaDeviceIndex device ); + + +/** Get device role (PaWasapiDeviceRole enum). + + @param device Device index. + + @return Non-negative value indicating device role or, a PaErrorCode (which is always negative) + if PortAudio is not initialized or an error is encountered. +*/ +int/*PaWasapiDeviceRole*/ PaWasapi_GetDeviceRole( PaDeviceIndex device ); + + +/** Get device IMMDevice pointer. + + @param device Device index. + @param pAudioClient Pointer to pointer of IMMDevice. + + @return Error code indicating success or failure. +*/ +PaError PaWasapi_GetIMMDevice( PaDeviceIndex device, void **pIMMDevice ); + +/** Get device loopback state: -/** Returns device role (PaWasapiDeviceRole enum). + 0 - Not loopback, + 1 - Loopback, + negative - PaErrorCode. - @param nDevice device index. + @param device Device index. - @return Non-negative value indicating device role or, a PaErrorCode (which are always negative) + @return Non-negative value indicating loopback state or, a PaErrorCode (which is always negative) if PortAudio is not initialized or an error is encountered. */ -int/*PaWasapiDeviceRole*/ PaWasapi_GetDeviceRole( PaDeviceIndex nDevice ); +int PaWasapi_IsLoopback( PaDeviceIndex device ); -/** Boost thread priority of calling thread (MMCSS). Use it for Blocking Interface only for thread - which makes calls to Pa_WriteStream/Pa_ReadStream. +/** Boost thread priority of calling thread (MMCSS). - @param hTask Handle to pointer to priority task. Must be used with PaWasapi_RevertThreadPriority - method to revert thread priority to initial state. + Use it for Blocking Interface only inside the thread which makes calls to Pa_WriteStream/Pa_ReadStream. - @param nPriorityClass Id of thread priority of PaWasapiThreadPriority type. Specifying - eThreadPriorityNone does nothing. + @param pTask Handle to pointer to priority task. Must be used with PaWasapi_RevertThreadPriority + method to revert thread priority to initial state. + + @param priorityClass 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, PaWasapiThreadPriority nPriorityClass ); +PaError PaWasapi_ThreadPriorityBoost( void **pTask, PaWasapiThreadPriority priorityClass ); + + +/** Boost thread priority of calling thread (MMCSS). + Use it for Blocking Interface only inside the thread which makes calls to Pa_WriteStream/Pa_ReadStream. -/** Boost thread priority of calling thread (MMCSS). Use it for Blocking Interface only for thread - which makes calls to Pa_WriteStream/Pa_ReadStream. + @param pTask Task handle obtained by PaWasapi_BoostThreadPriority method. - @param hTask Task handle obtained by PaWasapi_BoostThreadPriority method. @return Error code indicating success or failure. @see PaWasapi_BoostThreadPriority */ -PaError PaWasapi_ThreadPriorityRevert( void *hTask ); +PaError PaWasapi_ThreadPriorityRevert( void *pTask ); + + +/** Get number of frames per host buffer. + It is max value of frames of WASAPI buffer which can be locked for operations. + Use this method as helper to find out max values of inputFrames/outputFrames + of PaWasapiHostProcessorCallback. -/** Get number of frames per host buffer. This is maximal value of frames of WASAPI buffer which - can be locked for operations. Use this method as helper to findout maximal values of - inputFrames/outputFrames of PaWasapiHostProcessorCallback. + @param pStream Pointer to PaStream object. + @param pInput Pointer to variable to receive number of input frames. Can be NULL. + @param pOutput Pointer to variable to receive number of output frames. Can be NULL. - @param pStream Pointer to PaStream to query. - @param nInput Pointer to variable to receive number of input frames. Can be NULL. - @param nOutput Pointer to variable to receive number of output frames. Can be NULL. @return Error code indicating success or failure. @see PaWasapiHostProcessorCallback */ -PaError PaWasapi_GetFramesPerHostBuffer( PaStream *pStream, unsigned int *nInput, unsigned int *nOutput ); +PaError PaWasapi_GetFramesPerHostBuffer( PaStream *pStream, unsigned int *pInput, unsigned int *pOutput ); + + +/** Get number of jacks associated with a WASAPI device. + + Use this method to determine if there are any jacks associated with the provided WASAPI device. + Not all audio devices will support this capability. This is valid for both input and output devices. + + @note Not available on UWP platform. + @param device Device index. + @param pJackCount Pointer to variable to receive number of jacks. -/** Get number of jacks associated with a WASAPI device. Use this method to determine if - there are any jacks associated with the provided WASAPI device. Not all audio devices - will support this capability. This is valid for both input and output devices. - @param nDevice device index. - @param jcount Number of jacks is returned in this variable - @return Error code indicating success or failure - @see PaWasapi_GetJackDescription + @return Error code indicating success or failure. + @see PaWasapi_GetJackDescription */ -PaError PaWasapi_GetJackCount(PaDeviceIndex nDevice, int *jcount); +PaError PaWasapi_GetJackCount( PaDeviceIndex device, int *pJackCount ); + +/** Get the jack description associated with a WASAPI device and jack number. -/** Get the jack description associated with a WASAPI device and jack number Before this function is called, use PaWasapi_GetJackCount to determine the number of jacks associated with device. If jcount is greater than zero, then each jack from 0 to jcount can be queried with this function to get the jack description. - @param nDevice device index. - @param jindex Which jack to return information - @param KSJACK_DESCRIPTION This structure filled in on success. - @return Error code indicating success or failure + + @note Not available on UWP platform. + + @param device Device index. + @param jackIndex Jack index. + @param pJackDescription Pointer to PaWasapiJackDescription. + + @return Error code indicating success or failure. @see PaWasapi_GetJackCount */ -PaError PaWasapi_GetJackDescription(PaDeviceIndex nDevice, int jindex, PaWasapiJackDescription *pJackDescription); +PaError PaWasapi_GetJackDescription( PaDeviceIndex device, int jackIndex, PaWasapiJackDescription *pJackDescription ); + + +/** Set stream state handler. + + @param pStream Pointer to PaStream object. + @param fnStateHandler Pointer to state handling function. + @param pUserData Pointer to user data. + + @return Error code indicating success or failure. +*/ +PaError PaWasapi_SetStreamStateHandler( PaStream *pStream, PaWasapiStreamStateCallback fnStateHandler, void *pUserData ); + + +/** Set default device Id. + + By default implementation will use the DEVINTERFACE_AUDIO_RENDER and + DEVINTERFACE_AUDIO_CAPTURE Ids if device Id is not provided explicitly. These default Ids + will not allow to use Exclusive mode on UWP/WinRT platform and thus you must provide + device Id explicitly via this API before calling the Pa_OpenStream(). + + Device Ids on UWP platform are obtainable via: + Windows::Media::Devices::MediaDevice::GetDefaultAudioRenderId() or + Windows::Media::Devices::MediaDevice::GetDefaultAudioCaptureId() API. + + After the call completes, memory referenced by pointers can be freed, as implementation keeps its own copy. + + Call this function before calling Pa_IsFormatSupported() when Exclusive mode is requested. + + See an example in the IMPORTANT notes. + + @note UWP/WinRT platform only. + + @param pId Device Id, pointer to the 16-bit Unicode string (WCHAR). If NULL then device Id + will be reset to the default, e.g. DEVINTERFACE_AUDIO_RENDER or DEVINTERFACE_AUDIO_CAPTURE. + @param bOutput TRUE (1) for output (render), FALSE (0) for input (capture). + + @return Error code indicating success or failure. Will return paIncompatibleStreamHostApi if library is not compiled + for UWP/WinRT platform. If Id is longer than PA_WASAPI_DEVICE_ID_LEN characters paBufferTooBig will + be returned. +*/ +PaError PaWasapiWinrt_SetDefaultDeviceId( const unsigned short *pId, int bOutput ); + + +/** Populate the device list. + + By default the implementation will rely on DEVINTERFACE_AUDIO_RENDER and DEVINTERFACE_AUDIO_CAPTURE as + default devices. If device Id is provided by PaWasapiWinrt_SetDefaultDeviceId() then those + device Ids will be used as default and only devices for the device list. + + By populating the device list you can provide an additional available audio devices of the system to PA + which are obtainable by: + Windows::Devices::Enumeration::DeviceInformation::FindAllAsync(selector) where selector is obtainable by + Windows::Media::Devices::MediaDevice::GetAudioRenderSelector() or + Windows::Media::Devices::MediaDevice::GetAudioCaptureSelector() API. + + After the call completes, memory referenced by pointers can be freed, as implementation keeps its own copy. + + You must call PaWasapi_UpdateDeviceList() to update the internal device list of the implementation after + calling this function. + + See an example in the IMPORTANT notes. + + @note UWP/WinRT platform only. + + @param pId Array of device Ids, pointer to the array of pointers of 16-bit Unicode string (WCHAR). If NULL + and count is also 0 then device Ids will be reset to the default. Required. + @param pName Array of device Names, pointer to the array of pointers of 16-bit Unicode string (WCHAR). Optional. + @param pRole Array of device Roles, see PaWasapiDeviceRole and PaWasapi_GetDeviceRole() for more details. Optional. + @param count Number of devices, the number of array elements (pId, pName, pRole). Maximum count of devices + is limited by PA_WASAPI_DEVICE_MAX_COUNT. + @param bOutput TRUE (1) for output (render), FALSE (0) for input (capture). + + @return Error code indicating success or failure. Will return paIncompatibleStreamHostApi if library is not compiled + for UWP/WinRT platform. If Id is longer than PA_WASAPI_DEVICE_ID_LEN characters paBufferTooBig will + be returned. If Name is longer than PA_WASAPI_DEVICE_NAME_LEN characters paBufferTooBig will + be returned. +*/ +PaError PaWasapiWinrt_PopulateDeviceList( const unsigned short **pId, const unsigned short **pName, + const PaWasapiDeviceRole *pRole, unsigned int count, int bOutput ); /* IMPORTANT: WASAPI is implemented for Callback and Blocking interfaces. It supports Shared and Exclusive - share modes. - + share modes. + Exclusive Mode: Exclusive mode allows to deliver audio data directly to hardware bypassing @@ -392,52 +699,116 @@ PaError PaWasapi_GetJackDescription(PaDeviceIndex nDevice, int jindex, PaWasapiJ Callback Interface: - Provides best audio quality with low latency. Callback interface is implemented in + Provides best audio quality with low latency. Callback interface is implemented in two versions: - 1) Event-Driven: - This is the most powerful WASAPI implementation which provides glitch-free - audio at around 3ms latency in Exclusive mode. Lowest possible latency for this mode is - 3 ms for HD Audio class audio chips. For the Shared mode latency can not be - lower than 20 ms. - - 2) Poll-Driven: - Polling is another 2-nd method to operate with WASAPI. It is less efficient than Event-Driven - and provides latency at around 10-13ms. Polling must be used to overcome a system bug - under Windows Vista x64 when application is WOW64(32-bit) and Event-Driven method simply - times out (event handle is never signalled on buffer completion). Please note, such WOW64 bug - does not exist in Vista x86 or Windows 7. - Polling can be setup by speciying 'paWinWasapiPolling' flag. Our WASAPI implementation detects - WOW64 bug and sets 'paWinWasapiPolling' automatically. + 1) Event-driven: + It is the most powerful data processing method which provides glitch-free audio with + around 3 ms latency in Exclusive mode. Lowest possible latency for this mode is + 3 ms for HD Audio class audio chips. For the Shared mode latency can not be + lower than 20 ms. This method consumes slightly less CPU in comparison to Polling. + It is the default processing method unless 'paWinWasapiPolling' is specified. + + 2) Poll-driven: + Polling is an alternative to Event-driven processing. Due to its nature Polling consumes + slightly more CPU. This method is less efficient than Event-driven and its lowest possible + latency is around 10-13 ms. + Note: Newer Windows versions (for example 11) allow to achieve similar to Event-driven + low latency. + Note: Polling must be used to overcome system bug of Windows Vista (x64) when application + is WOW64 (32-bit process running on 64-bit OS) that results in WASAPI callback timeout if + Event-driven method is selected (event handle is never signalled on buffer completion). + This WOW64 bug does not exist in Windows Vista (x86) or Windows 7 or newer Windows versions. + Polling can be activated by specifying 'paWinWasapiPolling' flag. Our implementation + detects WOW64 bug and sets 'paWinWasapiPolling' automatically. Thread priority: Normally thread priority is set automatically and does not require modification. Although if user wants some tweaking thread priority can be modified by setting 'paWinWasapiThreadPriority' - flag and specifying 'PaWasapiStreamInfo::threadPriority' with value from PaWasapiThreadPriority + flag and specifying 'PaWasapiStreamInfo::threadPriority' with value from PaWasapiThreadPriority enum. Blocking Interface: Blocking interface is implemented but due to above described Poll-Driven method can not - deliver lowest possible latency. Specifying too low latency in Shared mode will result in + deliver lowest possible latency. Specifying too low latency in Shared mode will result in distorted audio although Exclusive mode adds stability. + 8.24 format: + + If paCustomFormat is specified as sample format then the implementation will understand it + as valid 24-bits inside 32-bit container (e.g. wBitsPerSample = 32, Samples.wValidBitsPerSample = 24). + + By using paCustomFormat there will be small optimization when samples are be copied + with Copy_24_To_24 by PA processor instead of conversion from packed 3-byte (24-bit) data + with Int24_To_Int32. + Pa_IsFormatSupported: - To check format with correct Share Mode (Exclusive/Shared) you must supply - PaWasapiStreamInfo with flags paWinWasapiExclusive set through member of - PaStreamParameters::hostApiSpecificStreamInfo structure. + To check format with correct Share Mode (Exclusive/Shared) you must supply PaWasapiStreamInfo + with flags paWinWasapiExclusive set through member of PaStreamParameters::hostApiSpecificStreamInfo + structure. + + If paWinWasapiExplicitSampleFormat flag is provided then implementation will not try to select + suitable close format and will return an error instead of paFormatIsSupported. By specifying + paWinWasapiExplicitSampleFormat flag it is possible to find out what sample formats are + supported by Exclusive or Shared modes. Pa_OpenStream: To set desired Share Mode (Exclusive/Shared) you must supply - PaWasapiStreamInfo with flags paWinWasapiExclusive set through member of + PaWasapiStreamInfo with flags paWinWasapiExclusive set through member of PaStreamParameters::hostApiSpecificStreamInfo structure. + + Coding style for parameters and structure members of the public API: + + 1) bXXX - boolean, [1 (TRUE), 0 (FALSE)] + 2) pXXX - pointer + 3) fnXXX - pointer to function + 4) structure members are never prefixed with a type distinguisher + + + UWP/WinRT: + + This platform has number of limitations which do not allow to enumerate audio devices without + an additional external help. Enumeration is possible though from C++/CX, check the related API + Windows::Devices::Enumeration::DeviceInformation::FindAllAsync(). + + The main limitation is an absence of the device enumeration from inside the PA's implementation. + This problem can be solved by using the following functions: + + PaWasapiWinrt_SetDefaultDeviceId() - to set default input/output device, + PaWasapiWinrt_PopulateDeviceList() - to populate device list with devices. + + Here is an example of populating the device list which can also be updated dynamically depending on + whether device was removed from or added to the system: + + ---------------- + + std::vector<const UINT16 *> ids, names; + std::vector<PaWasapiDeviceRole> role; + + ids.resize(count); + names.resize(count); + role.resize(count); + + for (UINT32 i = 0; i < count; ++i) + { + ids[i] = (const UINT16 *)device_ids[i].c_str(); + names[i] = (const UINT16 *)device_names[i].c_str(); + role[i] = eRoleUnknownFormFactor; + } + + PaWasapiWinrt_SetDefaultDeviceId((const UINT16 *)default_device_id.c_str(), !capture); + PaWasapiWinrt_PopulateDeviceList(ids.data(), names.data(), role.data(), count, !capture); + PaWasapi_UpdateDeviceList(); + + ---------------- */ #ifdef __cplusplus } #endif /* __cplusplus */ -#endif /* PA_WIN_WASAPI_H */ +#endif /* PA_WIN_WASAPI_H */ |