pa_win_wasapi.h
Go to the documentation of this file.
#ifndef PA_WIN_WASAPI_H
#define PA_WIN_WASAPI_H
/*
* $Id: $
* PortAudio Portable Real-Time Audio Library
* WASAPI specific extensions
*
* 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
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* 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
* license above.
*/
#include "portaudio.h"
#include "pa_win_waveformat.h"
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
/* Stream setup flags. */
typedef enum PaWasapiFlags
{
/* put WASAPI into exclusive mode */
paWinWasapiExclusive = (1 << 0),
/* allow to skip internal PA processing completely */
paWinWasapiRedirectHostProcessor = (1 << 1),
/* assign custom channel mask */
paWinWasapiUseChannelMask = (1 << 2),
/* use Polling method (Event method is the default, see details in the IMPORTANT notes) */
paWinWasapiPolling = (1 << 3),
/* force custom thread priority setting, must be used if PaWasapiStreamInfo::threadPriority
is set to a custom value */
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)
#define paWinWasapiRedirectHostProcessor (paWinWasapiRedirectHostProcessor)
#define paWinWasapiUseChannelMask (paWinWasapiUseChannelMask)
#define paWinWasapiPolling (paWinWasapiPolling)
#define paWinWasapiThreadPriority (paWinWasapiThreadPriority)
#define paWinWasapiExplicitSampleFormat (paWinWasapiExplicitSampleFormat)
#define paWinWasapiAutoConvert (paWinWasapiAutoConvert)
#define paWinWasapiPassthrough (paWinWasapiPassthrough)
/* 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 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 (*PaWasapiStreamStateCallback) (PaStream *pStream, unsigned int stateFlags,
unsigned int errorId, void *pUserData);
/* Device role. */
typedef enum PaWasapiDeviceRole
{
eRoleRemoteNetworkDevice = 0,
eRoleSpeakers,
eRoleLineLevel,
eRoleHeadphones,
eRoleMicrophone,
eRoleHeadset,
eRoleHandset,
eRoleUnknownDigitalPassthrough,
eRoleSPDIF,
eRoleHDMI,
eRoleUnknownFormFactor
}
PaWasapiDeviceRole;
/* Jack connection type. */
typedef enum PaWasapiJackConnectionType
{
eJackConnTypeUnknown,
eJackConnType3Point5mm,
eJackConnTypeQuarter,
eJackConnTypeAtapiInternal,
eJackConnTypeRCA,
eJackConnTypeOptical,
eJackConnTypeOtherDigital,
eJackConnTypeOtherAnalog,
eJackConnTypeMultichannelAnalogDIN,
eJackConnTypeXlrProfessional,
eJackConnTypeRJ11Modem,
eJackConnTypeCombination
}
PaWasapiJackConnectionType;
/* Jack geometric location. */
typedef enum PaWasapiJackGeoLocation
{
eJackGeoLocUnk = 0,
eJackGeoLocRear = 0x1, /* matches EPcxGeoLocation::eGeoLocRear */
eJackGeoLocFront,
eJackGeoLocLeft,
eJackGeoLocRight,
eJackGeoLocTop,
eJackGeoLocBottom,
eJackGeoLocRearPanel,
eJackGeoLocRiser,
eJackGeoLocInsideMobileLid,
eJackGeoLocDrivebay,
eJackGeoLocHDMI,
eJackGeoLocOutsideMobileLid,
eJackGeoLocATAPI,
eJackGeoLocReserved5,
eJackGeoLocReserved6,
}
PaWasapiJackGeoLocation;
/* Jack general location. */
typedef enum PaWasapiJackGenLocation
{
eJackGenLocPrimaryBox = 0,
eJackGenLocInternal,
eJackGenLocSeparate,
eJackGenLocOther
}
PaWasapiJackGenLocation;
/* Jack's type of port. */
typedef enum PaWasapiJackPortConnection
{
eJackPortConnJack = 0,
eJackPortConnIntegratedDevice,
eJackPortConnBothIntegratedAndJack,
eJackPortConnUnknown
}
PaWasapiJackPortConnection;
/* Thread priority. */
typedef enum PaWasapiThreadPriority
{
eThreadPriorityNone = 0,
eThreadPriorityAudio,
eThreadPriorityCapture,
eThreadPriorityDistribution,
eThreadPriorityGames,
eThreadPriorityPlayback,
eThreadPriorityProAudio,
eThreadPriorityWindowManager
}
PaWasapiThreadPriority;
/* Stream descriptor. */
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))) */
PaWasapiJackConnectionType connectionType;
PaWasapiJackGeoLocation geoLocation;
PaWasapiJackGenLocation genLocation;
PaWasapiJackPortConnection portConnection;
unsigned int isConnected;
}
PaWasapiJackDescription;
typedef enum PaWasapiStreamCategory
{
eAudioCategoryOther = 0,
eAudioCategoryCommunications = 3,
eAudioCategoryAlerts = 4,
eAudioCategorySoundEffects = 5,
eAudioCategoryGameEffects = 6,
eAudioCategoryGameMedia = 7,
eAudioCategoryGameChat = 8,
eAudioCategorySpeech = 9,
eAudioCategoryMovie = 10,
eAudioCategoryMedia = 11
}
PaWasapiStreamCategory;
typedef enum PaWasapiStreamOption
{
eStreamOptionNone = 0,
eStreamOptionRaw = 1,
eStreamOptionMatchFormat = 2
}
PaWasapiStreamOption;
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;
typedef struct PaWasapiStreamPassthrough
{
PaWasapiPassthroughFormat formatId;
unsigned int encodedSamplesPerSec;
unsigned int encodedChannelCount;
unsigned int averageBytesPerSec;
}
PaWasapiStreamPassthrough;
/* Stream descriptor. */
typedef struct PaWasapiStreamInfo
{
unsigned long size;
PaHostApiTypeId hostApiType;
unsigned long version;
unsigned long flags;
PaWinWaveFormatChannelMask channelMask;
PaWasapiHostProcessorCallback hostProcessorOutput;
PaWasapiHostProcessorCallback hostProcessorInput;
PaWasapiThreadPriority threadPriority;
PaWasapiStreamCategory streamCategory;
PaWasapiStreamOption streamOption;
PaWasapiStreamPassthrough passthrough;
}
PaWasapiStreamInfo;
PaError PaWasapi_GetAudioClient( PaStream *pStream, void **pAudioClient, int bOutput );
PaError PaWasapi_UpdateDeviceList();
int PaWasapi_GetDeviceCurrentFormat( PaStream *pStream, void *pFormat, unsigned int formatSize, int bOutput );
int PaWasapi_GetDeviceDefaultFormat( void *pFormat, unsigned int formatSize, PaDeviceIndex device );
int PaWasapi_GetDeviceMixFormat( void *pFormat, unsigned int formatSize, PaDeviceIndex device );
int/*PaWasapiDeviceRole*/ PaWasapi_GetDeviceRole( PaDeviceIndex device );
PaError PaWasapi_GetIMMDevice( PaDeviceIndex device, void **pIMMDevice );
int PaWasapi_IsLoopback( PaDeviceIndex device );
PaError PaWasapi_ThreadPriorityBoost( void **pTask, PaWasapiThreadPriority priorityClass );
PaError PaWasapi_ThreadPriorityRevert( void *pTask );
PaError PaWasapi_GetFramesPerHostBuffer( PaStream *pStream, unsigned int *pInput, unsigned int *pOutput );
PaError PaWasapi_GetJackCount( PaDeviceIndex device, int *pJackCount );
PaError PaWasapi_GetJackDescription( PaDeviceIndex device, int jackIndex, PaWasapiJackDescription *pJackDescription );
PaError PaWasapi_SetStreamStateHandler( PaStream *pStream, PaWasapiStreamStateCallback fnStateHandler, void *pUserData );
PaError PaWasapiWinrt_SetDefaultDeviceId( const unsigned short *pId, int bOutput );
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.
Exclusive Mode:
Exclusive mode allows to deliver audio data directly to hardware bypassing
software mixing.
Exclusive mode is specified by 'paWinWasapiExclusive' flag.
Callback Interface:
Provides best audio quality with low latency. Callback interface is implemented in
two versions:
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
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
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.
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
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 */
PaWasapi_GetAudioClient
PaError PaWasapi_GetAudioClient(PaStream *pStream, void **pAudioClient, int bOutput)
PaWasapiPassthroughFormat
PaWasapiPassthroughFormat
Definition pa_win_wasapi.h:321
PaWasapi_GetDeviceDefaultFormat
int PaWasapi_GetDeviceDefaultFormat(void *pFormat, unsigned int formatSize, PaDeviceIndex device)
PaWasapi_IsLoopback
int PaWasapi_IsLoopback(PaDeviceIndex device)
PaWasapiThreadPriority
PaWasapiThreadPriority
Definition pa_win_wasapi.h:244
eThreadPriorityAudio
@ eThreadPriorityAudio
Default for Shared mode.
Definition pa_win_wasapi.h:246
eThreadPriorityProAudio
@ eThreadPriorityProAudio
Default for Exclusive mode.
Definition pa_win_wasapi.h:251
PaWasapiStreamOption
PaWasapiStreamOption
Definition pa_win_wasapi.h:303
eStreamOptionRaw
@ eStreamOptionRaw
bypass WASAPI Audio Engine DSP effects, supported since Windows 8.1
Definition pa_win_wasapi.h:305
eStreamOptionNone
@ eStreamOptionNone
default
Definition pa_win_wasapi.h:304
eStreamOptionMatchFormat
@ eStreamOptionMatchFormat
force WASAPI Audio Engine into a stream format, supported since Windows 10
Definition pa_win_wasapi.h:306
PaWasapi_SetStreamStateHandler
PaError PaWasapi_SetStreamStateHandler(PaStream *pStream, PaWasapiStreamStateCallback fnStateHandler, void *pUserData)
PaWasapi_GetIMMDevice
PaError PaWasapi_GetIMMDevice(PaDeviceIndex device, void **pIMMDevice)
PaWasapiWinrt_PopulateDeviceList
PaError PaWasapiWinrt_PopulateDeviceList(const unsigned short **pId, const unsigned short **pName, const PaWasapiDeviceRole *pRole, unsigned int count, int bOutput)
PaWasapiWinrt_SetDefaultDeviceId
PaError PaWasapiWinrt_SetDefaultDeviceId(const unsigned short *pId, int bOutput)
PaWasapi_GetDeviceMixFormat
int PaWasapi_GetDeviceMixFormat(void *pFormat, unsigned int formatSize, PaDeviceIndex device)
PaWasapi_GetFramesPerHostBuffer
PaError PaWasapi_GetFramesPerHostBuffer(PaStream *pStream, unsigned int *pInput, unsigned int *pOutput)
PaWasapi_ThreadPriorityRevert
PaError PaWasapi_ThreadPriorityRevert(void *pTask)
PaWasapi_GetDeviceRole
int PaWasapi_GetDeviceRole(PaDeviceIndex device)
PaWasapi_ThreadPriorityBoost
PaError PaWasapi_ThreadPriorityBoost(void **pTask, PaWasapiThreadPriority priorityClass)
PaWasapiStreamCategory
PaWasapiStreamCategory
Definition pa_win_wasapi.h:280
PaWasapi_GetDeviceCurrentFormat
int PaWasapi_GetDeviceCurrentFormat(PaStream *pStream, void *pFormat, unsigned int formatSize, int bOutput)
PaWasapi_GetJackDescription
PaError PaWasapi_GetJackDescription(PaDeviceIndex device, int jackIndex, PaWasapiJackDescription *pJackDescription)
PaWasapi_UpdateDeviceList
PaError PaWasapi_UpdateDeviceList()
PaWasapi_GetJackCount
PaError PaWasapi_GetJackCount(PaDeviceIndex device, int *pJackCount)
pa_win_waveformat.h
Windows specific PortAudio API extension and utilities header file.
portaudio.h
The portable PortAudio API.
PaStream
void PaStream
Definition portaudio.h:643
PaError
int PaError
Definition portaudio.h:122
PaHostApiTypeId
PaHostApiTypeId
Definition portaudio.h:278
PaDeviceIndex
int PaDeviceIndex
Definition portaudio.h:214
PaWasapiJackDescription
Definition pa_win_wasapi.h:259
PaWasapiStreamInfo
Definition pa_win_wasapi.h:368
PaWasapiStreamInfo::hostProcessorOutput
PaWasapiHostProcessorCallback hostProcessorOutput
Definition pa_win_wasapi.h:388
PaWasapiStreamInfo::version
unsigned long version
Definition pa_win_wasapi.h:371
PaWasapiStreamInfo::channelMask
PaWinWaveFormatChannelMask channelMask
Definition pa_win_wasapi.h:381
PaWasapiStreamInfo::streamCategory
PaWasapiStreamCategory streamCategory
Definition pa_win_wasapi.h:404
PaWasapiStreamInfo::threadPriority
PaWasapiThreadPriority threadPriority
Definition pa_win_wasapi.h:398
PaWasapiStreamInfo::flags
unsigned long flags
Definition pa_win_wasapi.h:373
PaWasapiStreamInfo::passthrough
PaWasapiStreamPassthrough passthrough
Definition pa_win_wasapi.h:417
PaWasapiStreamInfo::hostApiType
PaHostApiTypeId hostApiType
Definition pa_win_wasapi.h:370
PaWasapiStreamInfo::streamOption
PaWasapiStreamOption streamOption
Definition pa_win_wasapi.h:410
PaWasapiStreamInfo::size
unsigned long size
Definition pa_win_wasapi.h:369
PaWasapiStreamPassthrough
Definition pa_win_wasapi.h:357