PortAudio  2.0
pa_win_wasapi.h
Go to the documentation of this file.
1 #ifndef PA_WIN_WASAPI_H
2 #define PA_WIN_WASAPI_H
3 /*
4  * $Id: $
5  * PortAudio Portable Real-Time Audio Library
6  * WASAPI specific extensions
7  *
8  * Copyright (c) 1999-2018 Ross Bencina and Phil Burk
9  * Copyright (c) 2006-2010 David Viens
10  * Copyright (c) 2010-2022 Dmitry Kostjuchenko
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining
13  * a copy of this software and associated documentation files
14  * (the "Software"), to deal in the Software without restriction,
15  * including without limitation the rights to use, copy, modify, merge,
16  * publish, distribute, sublicense, and/or sell copies of the Software,
17  * and to permit persons to whom the Software is furnished to do so,
18  * subject to the following conditions:
19  *
20  * The above copyright notice and this permission notice shall be
21  * included in all copies or substantial portions of the Software.
22  *
23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
26  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
27  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
28  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30  */
31 
32 /*
33  * The text above constitutes the entire PortAudio license; however,
34  * the PortAudio community also makes the following non-binding requests:
35  *
36  * Any person wishing to distribute modifications to the Software is
37  * requested to send the modifications to the original developer so that
38  * they can be incorporated into the canonical version. It is also
39  * requested that these non-binding requests be included along with the
40  * license above.
41  */
42 
48 #include "portaudio.h"
49 #include "pa_win_waveformat.h"
50 
51 #ifdef __cplusplus
52 extern "C"
53 {
54 #endif /* __cplusplus */
55 
56 
57 /* Stream setup flags. */
58 typedef enum PaWasapiFlags
59 {
60  /* put WASAPI into exclusive mode */
61  paWinWasapiExclusive = (1 << 0),
62 
63  /* allow to skip internal PA processing completely */
64  paWinWasapiRedirectHostProcessor = (1 << 1),
65 
66  /* assign custom channel mask */
67  paWinWasapiUseChannelMask = (1 << 2),
68 
69  /* use Polling method (Event method is the default, see details in the IMPORTANT notes) */
70  paWinWasapiPolling = (1 << 3),
71 
72  /* force custom thread priority setting, must be used if PaWasapiStreamInfo::threadPriority
73  is set to a custom value */
74  paWinWasapiThreadPriority = (1 << 4),
75 
76  /* force explicit sample format and do not allow PA to select suitable working format, API will
77  fail if provided sample format is not supported by audio hardware in Exclusive mode
78  or system mixer in Shared mode */
79  paWinWasapiExplicitSampleFormat = (1 << 5),
80 
81  /* allow API to insert system-level channel matrix mixer and sample rate converter to allow
82  playback formats that do not match the current configured system settings.
83  this is in particular required for streams not matching the system mixer sample rate.
84  only applies in Shared mode. */
85  paWinWasapiAutoConvert = (1 << 6),
86 
87  /* use Passthrough mode for sending encoded audio data in PCM containers to the audio device,
88  refer to Microsoft documentation "Representing Formats for IEC 61937 Transmissions" for more
89  details about data representation and stream configuration */
90  paWinWasapiPassthrough = (1 << 7),
91 }
92 PaWasapiFlags;
93 #define paWinWasapiExclusive (paWinWasapiExclusive)
94 #define paWinWasapiRedirectHostProcessor (paWinWasapiRedirectHostProcessor)
95 #define paWinWasapiUseChannelMask (paWinWasapiUseChannelMask)
96 #define paWinWasapiPolling (paWinWasapiPolling)
97 #define paWinWasapiThreadPriority (paWinWasapiThreadPriority)
98 #define paWinWasapiExplicitSampleFormat (paWinWasapiExplicitSampleFormat)
99 #define paWinWasapiAutoConvert (paWinWasapiAutoConvert)
100 #define paWinWasapiPassthrough (paWinWasapiPassthrough)
101 
102 
103 /* Stream state.
104 
105  @note Multiple states can be united into a bitmask.
106  @see PaWasapiStreamStateCallback, PaWasapi_SetStreamStateHandler
107 */
108 typedef enum PaWasapiStreamState
109 {
110  /* state change was caused by the error:
111 
112  Example:
113  1) If thread execution stopped due to AUDCLNT_E_RESOURCES_INVALIDATED then state
114  value will contain paWasapiStreamStateError|paWasapiStreamStateThreadStop.
115  */
116  paWasapiStreamStateError = (1 << 0),
117 
118  /* processing thread is preparing to start execution */
119  paWasapiStreamStateThreadPrepare = (1 << 1),
120 
121  /* processing thread started execution (enters its loop) */
122  paWasapiStreamStateThreadStart = (1 << 2),
123 
124  /* processing thread stopped execution */
125  paWasapiStreamStateThreadStop = (1 << 3)
126 }
127 PaWasapiStreamState;
128 #define paWasapiStreamStateError (paWasapiStreamStateError)
129 #define paWasapiStreamStateThreadPrepare (paWasapiStreamStateThreadPrepare)
130 #define paWasapiStreamStateThreadStart (paWasapiStreamStateThreadStart)
131 #define paWasapiStreamStateThreadStop (paWasapiStreamStateThreadStop)
132 
133 
134 /* Host processor.
135 
136  Allows to skip internal PA processing completely. paWinWasapiRedirectHostProcessor flag
137  must be set to the PaWasapiStreamInfo::flags member in order to have host processor
138  redirected to this callback.
139 
140  Use with caution! inputFrames and outputFrames depend solely on final device setup.
141  To query max values of inputFrames/outputFrames use PaWasapi_GetFramesPerHostBuffer.
142 */
143 typedef void (*PaWasapiHostProcessorCallback) (void *inputBuffer, long inputFrames,
144  void *outputBuffer, long outputFrames, void *userData);
145 
146 
147 /* Stream state handler.
148 
149  @param pStream Pointer to PaStream object.
150  @param stateFlags State flags, a collection of values from PaWasapiStreamState enum.
151  @param errorId Error id provided by system API (HRESULT).
152  @param userData Pointer to user data.
153 
154  @see PaWasapiStreamState
155 */
156 typedef void (*PaWasapiStreamStateCallback) (PaStream *pStream, unsigned int stateFlags,
157  unsigned int errorId, void *pUserData);
158 
159 
160 /* Device role. */
161 typedef enum PaWasapiDeviceRole
162 {
163  eRoleRemoteNetworkDevice = 0,
164  eRoleSpeakers,
165  eRoleLineLevel,
166  eRoleHeadphones,
167  eRoleMicrophone,
168  eRoleHeadset,
169  eRoleHandset,
170  eRoleUnknownDigitalPassthrough,
171  eRoleSPDIF,
172  eRoleHDMI,
173  eRoleUnknownFormFactor
174 }
175 PaWasapiDeviceRole;
176 
177 
178 /* Jack connection type. */
179 typedef enum PaWasapiJackConnectionType
180 {
181  eJackConnTypeUnknown,
182  eJackConnType3Point5mm,
183  eJackConnTypeQuarter,
184  eJackConnTypeAtapiInternal,
185  eJackConnTypeRCA,
186  eJackConnTypeOptical,
187  eJackConnTypeOtherDigital,
188  eJackConnTypeOtherAnalog,
189  eJackConnTypeMultichannelAnalogDIN,
190  eJackConnTypeXlrProfessional,
191  eJackConnTypeRJ11Modem,
192  eJackConnTypeCombination
193 }
194 PaWasapiJackConnectionType;
195 
196 
197 /* Jack geometric location. */
198 typedef enum PaWasapiJackGeoLocation
199 {
200  eJackGeoLocUnk = 0,
201  eJackGeoLocRear = 0x1, /* matches EPcxGeoLocation::eGeoLocRear */
202  eJackGeoLocFront,
203  eJackGeoLocLeft,
204  eJackGeoLocRight,
205  eJackGeoLocTop,
206  eJackGeoLocBottom,
207  eJackGeoLocRearPanel,
208  eJackGeoLocRiser,
209  eJackGeoLocInsideMobileLid,
210  eJackGeoLocDrivebay,
211  eJackGeoLocHDMI,
212  eJackGeoLocOutsideMobileLid,
213  eJackGeoLocATAPI,
214  eJackGeoLocReserved5,
215  eJackGeoLocReserved6,
216 }
217 PaWasapiJackGeoLocation;
218 
219 
220 /* Jack general location. */
221 typedef enum PaWasapiJackGenLocation
222 {
223  eJackGenLocPrimaryBox = 0,
224  eJackGenLocInternal,
225  eJackGenLocSeparate,
226  eJackGenLocOther
227 }
228 PaWasapiJackGenLocation;
229 
230 
231 /* Jack's type of port. */
232 typedef enum PaWasapiJackPortConnection
233 {
234  eJackPortConnJack = 0,
235  eJackPortConnIntegratedDevice,
236  eJackPortConnBothIntegratedAndJack,
237  eJackPortConnUnknown
238 }
239 PaWasapiJackPortConnection;
240 
241 
242 /* Thread priority. */
244 {
245  eThreadPriorityNone = 0,
247  eThreadPriorityCapture,
248  eThreadPriorityDistribution,
249  eThreadPriorityGames,
250  eThreadPriorityPlayback,
252  eThreadPriorityWindowManager
253 }
255 
256 
257 /* Stream descriptor. */
259 {
260  unsigned long channelMapping;
261  unsigned long color; /* derived from macro: #define RGB(r,g,b) ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16))) */
262  PaWasapiJackConnectionType connectionType;
263  PaWasapiJackGeoLocation geoLocation;
264  PaWasapiJackGenLocation genLocation;
265  PaWasapiJackPortConnection portConnection;
266  unsigned int isConnected;
267 }
269 
270 
280 {
281  eAudioCategoryOther = 0,
282  eAudioCategoryCommunications = 3,
283  eAudioCategoryAlerts = 4,
284  eAudioCategorySoundEffects = 5,
285  eAudioCategoryGameEffects = 6,
286  eAudioCategoryGameMedia = 7,
287  eAudioCategoryGameChat = 8,
288  eAudioCategorySpeech = 9,
289  eAudioCategoryMovie = 10,
290  eAudioCategoryMedia = 11
291 }
293 
294 
303 {
307 }
309 
310 
321 {
322  ePassthroughFormatPcmIec60958 = 0x00000000,
323  ePassthroughFormatDolbyDigital = 0x00920000,
324  ePassthroughFormatMpeg1 = 0x00030cea,
325  ePassthroughFormatMpeg3 = 0x00040cea,
326  ePassthroughFormatMpeg2 = 0x00050cea,
327  ePassthroughFormatAac = 0x00060cea,
328  ePassthroughFormatDts = 0x00080cea,
329  ePassthroughFormatDolbyDigitalPlus = 0x000a0cea,
330  ePassthroughFormatDolbyDigitalPlusAtmos = 0x010a0cea,
331  ePassthroughFormatDtsHd = 0x000b0cea,
332  ePassthroughFormatDtsXE1 = 0x010b0cea,
333  ePassthroughFormatDtsXE2 = 0x030b0cea,
334  ePassthroughFormatDolbyMlp = 0x000c0cea,
335  ePassthroughFormatDolbyMat20 = 0x010c0cea,
336  ePassthroughFormatDolbyMat21 = 0x030c0cea,
337  ePassthroughFormatWmaPro = 0x01640000,
338  ePassthroughFormatAtrac = 0x00080cea,
339  ePassthroughFormatOneBitAudio = 0x00090cea,
340  ePassthroughFormatDst = 0x000d0cea,
341 }
343 
344 
357 {
358  PaWasapiPassthroughFormat formatId;
359  unsigned int encodedSamplesPerSec;
360  unsigned int encodedChannelCount;
361  unsigned int averageBytesPerSec;
362 }
364 
365 
366 /* Stream descriptor. */
367 typedef struct PaWasapiStreamInfo
368 {
369  unsigned long size;
371  unsigned long version;
373  unsigned long flags;
381  PaWinWaveFormatChannelMask channelMask;
382 
388  PaWasapiHostProcessorCallback hostProcessorOutput;
389  PaWasapiHostProcessorCallback hostProcessorInput;
390 
399 
405 
411 
418 }
420 
421 
430 PaError PaWasapi_GetAudioClient( PaStream *pStream, void **pAudioClient, int bOutput );
431 
432 
444 
445 
461 int PaWasapi_GetDeviceCurrentFormat( PaStream *pStream, void *pFormat, unsigned int formatSize, int bOutput );
462 
463 
477 int PaWasapi_GetDeviceDefaultFormat( void *pFormat, unsigned int formatSize, PaDeviceIndex device );
478 
479 
493 int PaWasapi_GetDeviceMixFormat( void *pFormat, unsigned int formatSize, PaDeviceIndex device );
494 
495 
503 int/*PaWasapiDeviceRole*/ PaWasapi_GetDeviceRole( PaDeviceIndex device );
504 
505 
513 PaError PaWasapi_GetIMMDevice( PaDeviceIndex device, void **pIMMDevice );
514 
515 
527 int PaWasapi_IsLoopback( PaDeviceIndex device );
528 
529 
543 PaError PaWasapi_ThreadPriorityBoost( void **pTask, PaWasapiThreadPriority priorityClass );
544 
545 
556 
557 
571 PaError PaWasapi_GetFramesPerHostBuffer( PaStream *pStream, unsigned int *pInput, unsigned int *pOutput );
572 
573 
587 PaError PaWasapi_GetJackCount( PaDeviceIndex device, int *pJackCount );
588 
589 
606 PaError PaWasapi_GetJackDescription( PaDeviceIndex device, int jackIndex, PaWasapiJackDescription *pJackDescription );
607 
608 
617 PaError PaWasapi_SetStreamStateHandler( PaStream *pStream, PaWasapiStreamStateCallback fnStateHandler, void *pUserData );
618 
619 
647 PaError PaWasapiWinrt_SetDefaultDeviceId( const unsigned short *pId, int bOutput );
648 
649 
684 PaError PaWasapiWinrt_PopulateDeviceList( const unsigned short **pId, const unsigned short **pName,
685  const PaWasapiDeviceRole *pRole, unsigned int count, int bOutput );
686 
687 
688 /*
689  IMPORTANT:
690 
691  WASAPI is implemented for Callback and Blocking interfaces. It supports Shared and Exclusive
692  share modes.
693 
694  Exclusive Mode:
695 
696  Exclusive mode allows to deliver audio data directly to hardware bypassing
697  software mixing.
698  Exclusive mode is specified by 'paWinWasapiExclusive' flag.
699 
700  Callback Interface:
701 
702  Provides best audio quality with low latency. Callback interface is implemented in
703  two versions:
704 
705  1) Event-driven:
706  It is the most powerful data processing method which provides glitch-free audio with
707  around 3 ms latency in Exclusive mode. Lowest possible latency for this mode is
708  3 ms for HD Audio class audio chips. For the Shared mode latency can not be
709  lower than 20 ms. This method consumes slightly less CPU in comparison to Polling.
710  It is the default processing method unless 'paWinWasapiPolling' is specified.
711 
712  2) Poll-driven:
713  Polling is an alternative to Event-driven processing. Due to its nature Polling consumes
714  slightly more CPU. This method is less efficient than Event-driven and its lowest possible
715  latency is around 10-13 ms.
716  Note: Newer Windows versions (for example 11) allow to achieve similar to Event-driven
717  low latency.
718  Note: Polling must be used to overcome system bug of Windows Vista (x64) when application
719  is WOW64 (32-bit process running on 64-bit OS) that results in WASAPI callback timeout if
720  Event-driven method is selected (event handle is never signalled on buffer completion).
721  This WOW64 bug does not exist in Windows Vista (x86) or Windows 7 or newer Windows versions.
722  Polling can be activated by specifying 'paWinWasapiPolling' flag. Our implementation
723  detects WOW64 bug and sets 'paWinWasapiPolling' automatically.
724 
725  Thread priority:
726 
727  Normally thread priority is set automatically and does not require modification. Although
728  if user wants some tweaking thread priority can be modified by setting 'paWinWasapiThreadPriority'
729  flag and specifying 'PaWasapiStreamInfo::threadPriority' with value from PaWasapiThreadPriority
730  enum.
731 
732  Blocking Interface:
733 
734  Blocking interface is implemented but due to above described Poll-Driven method can not
735  deliver lowest possible latency. Specifying too low latency in Shared mode will result in
736  distorted audio although Exclusive mode adds stability.
737 
738  8.24 format:
739 
740  If paCustomFormat is specified as sample format then the implementation will understand it
741  as valid 24-bits inside 32-bit container (e.g. wBitsPerSample = 32, Samples.wValidBitsPerSample = 24).
742 
743  By using paCustomFormat there will be small optimization when samples are be copied
744  with Copy_24_To_24 by PA processor instead of conversion from packed 3-byte (24-bit) data
745  with Int24_To_Int32.
746 
747  Pa_IsFormatSupported:
748 
749  To check format with correct Share Mode (Exclusive/Shared) you must supply PaWasapiStreamInfo
750  with flags paWinWasapiExclusive set through member of PaStreamParameters::hostApiSpecificStreamInfo
751  structure.
752 
753  If paWinWasapiExplicitSampleFormat flag is provided then implementation will not try to select
754  suitable close format and will return an error instead of paFormatIsSupported. By specifying
755  paWinWasapiExplicitSampleFormat flag it is possible to find out what sample formats are
756  supported by Exclusive or Shared modes.
757 
758  Pa_OpenStream:
759 
760  To set desired Share Mode (Exclusive/Shared) you must supply
761  PaWasapiStreamInfo with flags paWinWasapiExclusive set through member of
762  PaStreamParameters::hostApiSpecificStreamInfo structure.
763 
764  Coding style for parameters and structure members of the public API:
765 
766  1) bXXX - boolean, [1 (TRUE), 0 (FALSE)]
767  2) pXXX - pointer
768  3) fnXXX - pointer to function
769  4) structure members are never prefixed with a type distinguisher
770 
771 
772  UWP/WinRT:
773 
774  This platform has number of limitations which do not allow to enumerate audio devices without
775  an additional external help. Enumeration is possible though from C++/CX, check the related API
776  Windows::Devices::Enumeration::DeviceInformation::FindAllAsync().
777 
778  The main limitation is an absence of the device enumeration from inside the PA's implementation.
779  This problem can be solved by using the following functions:
780 
781  PaWasapiWinrt_SetDefaultDeviceId() - to set default input/output device,
782  PaWasapiWinrt_PopulateDeviceList() - to populate device list with devices.
783 
784  Here is an example of populating the device list which can also be updated dynamically depending on
785  whether device was removed from or added to the system:
786 
787  ----------------
788 
789  std::vector<const UINT16 *> ids, names;
790  std::vector<PaWasapiDeviceRole> role;
791 
792  ids.resize(count);
793  names.resize(count);
794  role.resize(count);
795 
796  for (UINT32 i = 0; i < count; ++i)
797  {
798  ids[i] = (const UINT16 *)device_ids[i].c_str();
799  names[i] = (const UINT16 *)device_names[i].c_str();
800  role[i] = eRoleUnknownFormFactor;
801  }
802 
803  PaWasapiWinrt_SetDefaultDeviceId((const UINT16 *)default_device_id.c_str(), !capture);
804  PaWasapiWinrt_PopulateDeviceList(ids.data(), names.data(), role.data(), count, !capture);
805  PaWasapi_UpdateDeviceList();
806 
807  ----------------
808 */
809 
810 #ifdef __cplusplus
811 }
812 #endif /* __cplusplus */
813 
814 #endif /* PA_WIN_WASAPI_H */
Default for Shared mode.
PaWasapiThreadPriority
PaError PaWasapi_GetFramesPerHostBuffer(PaStream *pStream, unsigned int *pInput, unsigned int *pOutput)
PaError PaWasapi_SetStreamStateHandler(PaStream *pStream, PaWasapiStreamStateCallback fnStateHandler, void *pUserData)
PaWasapiHostProcessorCallback hostProcessorOutput
PaError PaWasapi_ThreadPriorityBoost(void **pTask, PaWasapiThreadPriority priorityClass)
int PaWasapi_IsLoopback(PaDeviceIndex device)
bypass WASAPI Audio Engine DSP effects, supported since Windows 8.1
void PaStream
Definition: portaudio.h:644
PaError PaWasapi_GetIMMDevice(PaDeviceIndex device, void **pIMMDevice)
int PaWasapi_GetDeviceDefaultFormat(void *pFormat, unsigned int formatSize, PaDeviceIndex device)
unsigned long flags
PaError PaWasapi_GetJackCount(PaDeviceIndex device, int *pJackCount)
PaWasapiStreamCategory streamCategory
PaWasapiThreadPriority threadPriority
PaWasapiStreamPassthrough passthrough
PaError PaWasapi_GetAudioClient(PaStream *pStream, void **pAudioClient, int bOutput)
int PaDeviceIndex
Definition: portaudio.h:214
Default for Exclusive mode.
force WASAPI Audio Engine into a stream format, supported since Windows 10
The portable PortAudio API.
unsigned long size
PaError PaWasapi_UpdateDeviceList()
PaError PaWasapi_GetJackDescription(PaDeviceIndex device, int jackIndex, PaWasapiJackDescription *pJackDescription)
PaWasapiPassthroughFormat
PaHostApiTypeId hostApiType
PaWinWaveFormatChannelMask channelMask
int PaError
Definition: portaudio.h:122
PaHostApiTypeId
Definition: portaudio.h:277
int PaWasapi_GetDeviceMixFormat(void *pFormat, unsigned int formatSize, PaDeviceIndex device)
PaError PaWasapiWinrt_SetDefaultDeviceId(const unsigned short *pId, int bOutput)
unsigned long version
PaWasapiStreamCategory
PaWasapiStreamOption
Windows specific PortAudio API extension and utilities header file.
PaError PaWasapi_ThreadPriorityRevert(void *pTask)
int PaWasapi_GetDeviceCurrentFormat(PaStream *pStream, void *pFormat, unsigned int formatSize, int bOutput)
struct PaWasapiStreamPassthrough PaWasapiStreamPassthrough
PaError PaWasapiWinrt_PopulateDeviceList(const unsigned short **pId, const unsigned short **pName, const PaWasapiDeviceRole *pRole, unsigned int count, int bOutput)
PaWasapiStreamOption streamOption
int PaWasapi_GetDeviceRole(PaDeviceIndex device)