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-2018 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  /* select non-Event driven method of data read/write
70  Note: WASAPI Event driven core is capable of 2ms latency!!!, but Polling
71  method can only provide 15-20ms latency. */
72  paWinWasapiPolling = (1 << 3),
73 
74  /* force custom thread priority setting, must be used if PaWasapiStreamInfo::threadPriority
75  is set to a custom value */
76  paWinWasapiThreadPriority = (1 << 4),
77 
78  /* force explicit sample format and do not allow PA to select suitable working format, API will
79  fail if provided sample format is not supported by audio hardware in Exclusive mode
80  or system mixer in Shared mode */
81  paWinWasapiExplicitSampleFormat = (1 << 5),
82 
83  /* allow API to insert system-level channel matrix mixer and sample rate converter to allow
84  playback formats that do not match the current configured system settings.
85  this is in particular required for streams not matching the system mixer sample rate.
86  only applies in Shared mode. */
87  paWinWasapiAutoConvert = (1 << 6)
88 }
89 PaWasapiFlags;
90 #define paWinWasapiExclusive (paWinWasapiExclusive)
91 #define paWinWasapiRedirectHostProcessor (paWinWasapiRedirectHostProcessor)
92 #define paWinWasapiUseChannelMask (paWinWasapiUseChannelMask)
93 #define paWinWasapiPolling (paWinWasapiPolling)
94 #define paWinWasapiThreadPriority (paWinWasapiThreadPriority)
95 #define paWinWasapiExplicitSampleFormat (paWinWasapiExplicitSampleFormat)
96 #define paWinWasapiAutoConvert (paWinWasapiAutoConvert)
97 
98 
99 /* Stream state.
100 
101  @note Multiple states can be united into a bitmask.
102  @see PaWasapiStreamStateCallback, PaWasapi_SetStreamStateHandler
103 */
104 typedef enum PaWasapiStreamState
105 {
106  /* state change was caused by the error:
107 
108  Example:
109  1) If thread execution stopped due to AUDCLNT_E_RESOURCES_INVALIDATED then state
110  value will contain paWasapiStreamStateError|paWasapiStreamStateThreadStop.
111  */
112  paWasapiStreamStateError = (1 << 0),
113 
114  /* processing thread is preparing to start execution */
115  paWasapiStreamStateThreadPrepare = (1 << 1),
116 
117  /* processing thread started execution (enters its loop) */
118  paWasapiStreamStateThreadStart = (1 << 2),
119 
120  /* processing thread stopped execution */
121  paWasapiStreamStateThreadStop = (1 << 3)
122 }
123 PaWasapiStreamState;
124 #define paWasapiStreamStateError (paWasapiStreamStateError)
125 #define paWasapiStreamStateThreadPrepare (paWasapiStreamStateThreadPrepare)
126 #define paWasapiStreamStateThreadStart (paWasapiStreamStateThreadStart)
127 #define paWasapiStreamStateThreadStop (paWasapiStreamStateThreadStop)
128 
129 
130 /* Host processor.
131 
132  Allows to skip internal PA processing completely. paWinWasapiRedirectHostProcessor flag
133  must be set to the PaWasapiStreamInfo::flags member in order to have host processor
134  redirected to this callback.
135 
136  Use with caution! inputFrames and outputFrames depend solely on final device setup.
137  To query max values of inputFrames/outputFrames use PaWasapi_GetFramesPerHostBuffer.
138 */
139 typedef void (*PaWasapiHostProcessorCallback) (void *inputBuffer, long inputFrames,
140  void *outputBuffer, long outputFrames, void *userData);
141 
142 
143 /* Stream state handler.
144 
145  @param pStream Pointer to PaStream object.
146  @param stateFlags State flags, a collection of values from PaWasapiStreamState enum.
147  @param errorId Error id provided by system API (HRESULT).
148  @param userData Pointer to user data.
149 
150  @see PaWasapiStreamState
151 */
152 typedef void (*PaWasapiStreamStateCallback) (PaStream *pStream, unsigned int stateFlags,
153  unsigned int errorId, void *pUserData);
154 
155 
156 /* Device role. */
157 typedef enum PaWasapiDeviceRole
158 {
159  eRoleRemoteNetworkDevice = 0,
160  eRoleSpeakers,
161  eRoleLineLevel,
162  eRoleHeadphones,
163  eRoleMicrophone,
164  eRoleHeadset,
165  eRoleHandset,
166  eRoleUnknownDigitalPassthrough,
167  eRoleSPDIF,
168  eRoleHDMI,
169  eRoleUnknownFormFactor
170 }
171 PaWasapiDeviceRole;
172 
173 
174 /* Jack connection type. */
175 typedef enum PaWasapiJackConnectionType
176 {
177  eJackConnTypeUnknown,
178  eJackConnType3Point5mm,
179  eJackConnTypeQuarter,
180  eJackConnTypeAtapiInternal,
181  eJackConnTypeRCA,
182  eJackConnTypeOptical,
183  eJackConnTypeOtherDigital,
184  eJackConnTypeOtherAnalog,
185  eJackConnTypeMultichannelAnalogDIN,
186  eJackConnTypeXlrProfessional,
187  eJackConnTypeRJ11Modem,
188  eJackConnTypeCombination
189 }
190 PaWasapiJackConnectionType;
191 
192 
193 /* Jack geometric location. */
194 typedef enum PaWasapiJackGeoLocation
195 {
196  eJackGeoLocUnk = 0,
197  eJackGeoLocRear = 0x1, /* matches EPcxGeoLocation::eGeoLocRear */
198  eJackGeoLocFront,
199  eJackGeoLocLeft,
200  eJackGeoLocRight,
201  eJackGeoLocTop,
202  eJackGeoLocBottom,
203  eJackGeoLocRearPanel,
204  eJackGeoLocRiser,
205  eJackGeoLocInsideMobileLid,
206  eJackGeoLocDrivebay,
207  eJackGeoLocHDMI,
208  eJackGeoLocOutsideMobileLid,
209  eJackGeoLocATAPI,
210  eJackGeoLocReserved5,
211  eJackGeoLocReserved6,
212 }
213 PaWasapiJackGeoLocation;
214 
215 
216 /* Jack general location. */
217 typedef enum PaWasapiJackGenLocation
218 {
219  eJackGenLocPrimaryBox = 0,
220  eJackGenLocInternal,
221  eJackGenLocSeparate,
222  eJackGenLocOther
223 }
224 PaWasapiJackGenLocation;
225 
226 
227 /* Jack's type of port. */
228 typedef enum PaWasapiJackPortConnection
229 {
230  eJackPortConnJack = 0,
231  eJackPortConnIntegratedDevice,
232  eJackPortConnBothIntegratedAndJack,
233  eJackPortConnUnknown
234 }
235 PaWasapiJackPortConnection;
236 
237 
238 /* Thread priority. */
240 {
241  eThreadPriorityNone = 0,
243  eThreadPriorityCapture,
244  eThreadPriorityDistribution,
245  eThreadPriorityGames,
246  eThreadPriorityPlayback,
248  eThreadPriorityWindowManager
249 }
251 
252 
253 /* Stream descriptor. */
255 {
256  unsigned long channelMapping;
257  unsigned long color; /* derived from macro: #define RGB(r,g,b) ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16))) */
258  PaWasapiJackConnectionType connectionType;
259  PaWasapiJackGeoLocation geoLocation;
260  PaWasapiJackGenLocation genLocation;
261  PaWasapiJackPortConnection portConnection;
262  unsigned int isConnected;
263 }
265 
266 
276 {
277  eAudioCategoryOther = 0,
278  eAudioCategoryCommunications = 3,
279  eAudioCategoryAlerts = 4,
280  eAudioCategorySoundEffects = 5,
281  eAudioCategoryGameEffects = 6,
282  eAudioCategoryGameMedia = 7,
283  eAudioCategoryGameChat = 8,
284  eAudioCategorySpeech = 9,
285  eAudioCategoryMovie = 10,
286  eAudioCategoryMedia = 11
287 }
289 
290 
299 {
303 }
305 
306 
307 /* Stream descriptor. */
308 typedef struct PaWasapiStreamInfo
309 {
310  unsigned long size;
312  unsigned long version;
314  unsigned long flags;
322  PaWinWaveFormatChannelMask channelMask;
323 
329  PaWasapiHostProcessorCallback hostProcessorOutput;
330  PaWasapiHostProcessorCallback hostProcessorInput;
331 
340 
346 
352 }
354 
355 
364 PaError PaWasapi_GetAudioClient( PaStream *pStream, void **pAudioClient, int bOutput );
365 
366 
378 
379 
395 int PaWasapi_GetDeviceCurrentFormat( PaStream *pStream, void *pFormat, unsigned int formatSize, int bOutput );
396 
397 
411 int PaWasapi_GetDeviceDefaultFormat( void *pFormat, unsigned int formatSize, PaDeviceIndex device );
412 
413 
427 int PaWasapi_GetDeviceMixFormat( void *pFormat, unsigned int formatSize, PaDeviceIndex device );
428 
429 
437 int/*PaWasapiDeviceRole*/ PaWasapi_GetDeviceRole( PaDeviceIndex device );
438 
439 
447 PaError PaWasapi_GetIMMDevice( PaDeviceIndex device, void **pIMMDevice );
448 
449 
462 
463 
478 
479 
490 
491 
505 PaError PaWasapi_GetFramesPerHostBuffer( PaStream *pStream, unsigned int *pInput, unsigned int *pOutput );
506 
507 
521 PaError PaWasapi_GetJackCount( PaDeviceIndex device, int *pJackCount );
522 
523 
540 PaError PaWasapi_GetJackDescription( PaDeviceIndex device, int jackIndex, PaWasapiJackDescription *pJackDescription );
541 
542 
551 PaError PaWasapi_SetStreamStateHandler( PaStream *pStream, PaWasapiStreamStateCallback fnStateHandler, void *pUserData );
552 
553 
581 PaError PaWasapiWinrt_SetDefaultDeviceId( const unsigned short *pId, int bOutput );
582 
583 
618 PaError PaWasapiWinrt_PopulateDeviceList( const unsigned short **pId, const unsigned short **pName,
619  const PaWasapiDeviceRole *pRole, unsigned int count, int bOutput );
620 
621 
622 /*
623  IMPORTANT:
624 
625  WASAPI is implemented for Callback and Blocking interfaces. It supports Shared and Exclusive
626  share modes.
627 
628  Exclusive Mode:
629 
630  Exclusive mode allows to deliver audio data directly to hardware bypassing
631  software mixing.
632  Exclusive mode is specified by 'paWinWasapiExclusive' flag.
633 
634  Callback Interface:
635 
636  Provides best audio quality with low latency. Callback interface is implemented in
637  two versions:
638 
639  1) Event-Driven:
640  This is the most powerful WASAPI implementation which provides glitch-free
641  audio at around 3ms latency in Exclusive mode. Lowest possible latency for this mode is
642  3 ms for HD Audio class audio chips. For the Shared mode latency can not be
643  lower than 20 ms.
644 
645  2) Poll-Driven:
646  Polling is another 2-nd method to operate with WASAPI. It is less efficient than Event-Driven
647  and provides latency at around 10-13ms. Polling must be used to overcome a system bug
648  under Windows Vista x64 when application is WOW64(32-bit) and Event-Driven method simply
649  times out (event handle is never signalled on buffer completion). Please note, such WOW64 bug
650  does not exist in Vista x86 or Windows 7.
651  Polling can be setup by specifying 'paWinWasapiPolling' flag. Our WASAPI implementation detects
652  WOW64 bug and sets 'paWinWasapiPolling' automatically.
653 
654  Thread priority:
655 
656  Normally thread priority is set automatically and does not require modification. Although
657  if user wants some tweaking thread priority can be modified by setting 'paWinWasapiThreadPriority'
658  flag and specifying 'PaWasapiStreamInfo::threadPriority' with value from PaWasapiThreadPriority
659  enum.
660 
661  Blocking Interface:
662 
663  Blocking interface is implemented but due to above described Poll-Driven method can not
664  deliver lowest possible latency. Specifying too low latency in Shared mode will result in
665  distorted audio although Exclusive mode adds stability.
666 
667  8.24 format:
668 
669  If paCustomFormat is specified as sample format then the implementation will understand it
670  as valid 24-bits inside 32-bit container (e.g. wBitsPerSample = 32, Samples.wValidBitsPerSample = 24).
671 
672  By using paCustomFormat there will be small optimization when samples are be copied
673  with Copy_24_To_24 by PA processor instead of conversion from packed 3-byte (24-bit) data
674  with Int24_To_Int32.
675 
676  Pa_IsFormatSupported:
677 
678  To check format with correct Share Mode (Exclusive/Shared) you must supply PaWasapiStreamInfo
679  with flags paWinWasapiExclusive set through member of PaStreamParameters::hostApiSpecificStreamInfo
680  structure.
681 
682  If paWinWasapiExplicitSampleFormat flag is provided then implementation will not try to select
683  suitable close format and will return an error instead of paFormatIsSupported. By specifying
684  paWinWasapiExplicitSampleFormat flag it is possible to find out what sample formats are
685  supported by Exclusive or Shared modes.
686 
687  Pa_OpenStream:
688 
689  To set desired Share Mode (Exclusive/Shared) you must supply
690  PaWasapiStreamInfo with flags paWinWasapiExclusive set through member of
691  PaStreamParameters::hostApiSpecificStreamInfo structure.
692 
693  Coding style for parameters and structure members of the public API:
694 
695  1) bXXX - boolean, [1 (TRUE), 0 (FALSE)]
696  2) pXXX - pointer
697  3) fnXXX - pointer to function
698  4) structure members are never prefixed with a type distinguisher
699 
700 
701  UWP/WinRT:
702 
703  This platform has number of limitations which do not allow to enumerate audio devices without
704  an additional external help. Enumeration is possible though from C++/CX, check the related API
705  Windows::Devices::Enumeration::DeviceInformation::FindAllAsync().
706 
707  The main limitation is an absence of the device enumeration from inside the PA's implementation.
708  This problem can be solved by using the following functions:
709 
710  PaWasapiWinrt_SetDefaultDeviceId() - to set default input/output device,
711  PaWasapiWinrt_PopulateDeviceList() - to populate device list with devices.
712 
713  Here is an example of populating the device list which can also be updated dynamically depending on
714  whether device was removed from or added to the system:
715 
716  ----------------
717 
718  std::vector<const UINT16 *> ids, names;
719  std::vector<PaWasapiDeviceRole> role;
720 
721  ids.resize(count);
722  names.resize(count);
723  role.resize(count);
724 
725  for (UINT32 i = 0; i < count; ++i)
726  {
727  ids[i] = (const UINT16 *)device_ids[i].c_str();
728  names[i] = (const UINT16 *)device_names[i].c_str();
729  role[i] = eRoleUnknownFormFactor;
730  }
731 
732  PaWasapiWinrt_SetDefaultDeviceId((const UINT16 *)default_device_id.c_str(), !capture);
733  PaWasapiWinrt_PopulateDeviceList(ids.data(), names.data(), role.data(), count, !capture);
734  PaWasapi_UpdateDeviceList();
735 
736  ----------------
737 */
738 
739 #ifdef __cplusplus
740 }
741 #endif /* __cplusplus */
742 
743 #endif /* PA_WIN_WASAPI_H */
PaError PaWasapi_GetAudioClient(PaStream *pStream, void **pAudioClient, int bOutput)
int PaWasapi_GetDeviceDefaultFormat(void *pFormat, unsigned int formatSize, PaDeviceIndex device)
int PaWasapi_IsLoopback(PaDeviceIndex device)
PaWasapiThreadPriority
@ eThreadPriorityAudio
Default for Shared mode.
@ eThreadPriorityProAudio
Default for Exclusive mode.
PaWasapiStreamOption
@ eStreamOptionRaw
bypass WASAPI Audio Engine DSP effects, supported since Windows 8.1
@ eStreamOptionNone
default
@ eStreamOptionMatchFormat
force WASAPI Audio Engine into a stream format, supported since Windows 10
PaError PaWasapi_SetStreamStateHandler(PaStream *pStream, PaWasapiStreamStateCallback fnStateHandler, void *pUserData)
PaError PaWasapi_GetIMMDevice(PaDeviceIndex device, void **pIMMDevice)
PaError PaWasapiWinrt_PopulateDeviceList(const unsigned short **pId, const unsigned short **pName, const PaWasapiDeviceRole *pRole, unsigned int count, int bOutput)
PaError PaWasapiWinrt_SetDefaultDeviceId(const unsigned short *pId, int bOutput)
int PaWasapi_GetDeviceMixFormat(void *pFormat, unsigned int formatSize, PaDeviceIndex device)
PaError PaWasapi_GetFramesPerHostBuffer(PaStream *pStream, unsigned int *pInput, unsigned int *pOutput)
PaError PaWasapi_ThreadPriorityRevert(void *pTask)
int PaWasapi_GetDeviceRole(PaDeviceIndex device)
PaError PaWasapi_ThreadPriorityBoost(void **pTask, PaWasapiThreadPriority priorityClass)
PaWasapiStreamCategory
int PaWasapi_GetDeviceCurrentFormat(PaStream *pStream, void *pFormat, unsigned int formatSize, int bOutput)
PaError PaWasapi_GetJackDescription(PaDeviceIndex device, int jackIndex, PaWasapiJackDescription *pJackDescription)
PaError PaWasapi_UpdateDeviceList()
PaError PaWasapi_GetJackCount(PaDeviceIndex device, int *pJackCount)
Windows specific PortAudio API extension and utilities header file.
The portable PortAudio API.
void PaStream
Definition: portaudio.h:637
int PaError
Definition: portaudio.h:121
PaHostApiTypeId
Definition: portaudio.h:276
int PaDeviceIndex
Definition: portaudio.h:212
PaWasapiHostProcessorCallback hostProcessorOutput
unsigned long version
PaWinWaveFormatChannelMask channelMask
PaWasapiStreamCategory streamCategory
PaWasapiThreadPriority threadPriority
unsigned long flags
PaHostApiTypeId hostApiType
PaWasapiStreamOption streamOption
unsigned long size