Chris@55: #ifndef PA_WIN_WASAPI_H Chris@55: #define PA_WIN_WASAPI_H Chris@55: /* Chris@55: * $Id: $ Chris@55: * PortAudio Portable Real-Time Audio Library Chris@55: * DirectSound specific extensions Chris@55: * Chris@55: * Copyright (c) 1999-2007 Ross Bencina and Phil Burk Chris@55: * Chris@55: * Permission is hereby granted, free of charge, to any person obtaining Chris@55: * a copy of this software and associated documentation files Chris@55: * (the "Software"), to deal in the Software without restriction, Chris@55: * including without limitation the rights to use, copy, modify, merge, Chris@55: * publish, distribute, sublicense, and/or sell copies of the Software, Chris@55: * and to permit persons to whom the Software is furnished to do so, Chris@55: * subject to the following conditions: Chris@55: * Chris@55: * The above copyright notice and this permission notice shall be Chris@55: * included in all copies or substantial portions of the Software. Chris@55: * Chris@55: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, Chris@55: * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF Chris@55: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. Chris@55: * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR Chris@55: * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF Chris@55: * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION Chris@55: * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Chris@55: */ Chris@55: Chris@55: /* Chris@55: * The text above constitutes the entire PortAudio license; however, Chris@55: * the PortAudio community also makes the following non-binding requests: Chris@55: * Chris@55: * Any person wishing to distribute modifications to the Software is Chris@55: * requested to send the modifications to the original developer so that Chris@55: * they can be incorporated into the canonical version. It is also Chris@55: * requested that these non-binding requests be included along with the Chris@55: * license above. Chris@55: */ Chris@55: Chris@55: /** @file Chris@55: @ingroup public_header Chris@55: @brief WASAPI-specific PortAudio API extension header file. Chris@55: */ Chris@55: Chris@55: #include "portaudio.h" Chris@55: #include "pa_win_waveformat.h" Chris@55: Chris@55: #ifdef __cplusplus Chris@55: extern "C" Chris@55: { Chris@55: #endif /* __cplusplus */ Chris@55: Chris@55: Chris@55: /* Setup flags */ Chris@55: typedef enum PaWasapiFlags Chris@55: { Chris@55: /* puts WASAPI into exclusive mode */ Chris@55: paWinWasapiExclusive = (1 << 0), Chris@55: Chris@55: /* allows to skip internal PA processing completely */ Chris@55: paWinWasapiRedirectHostProcessor = (1 << 1), Chris@55: Chris@55: /* assigns custom channel mask */ Chris@55: paWinWasapiUseChannelMask = (1 << 2), Chris@55: Chris@55: /* selects non-Event driven method of data read/write Chris@55: Note: WASAPI Event driven core is capable of 2ms latency!!!, but Polling Chris@55: method can only provide 15-20ms latency. */ Chris@55: paWinWasapiPolling = (1 << 3), Chris@55: Chris@55: /* forces custom thread priority setting, must be used if PaWasapiStreamInfo::threadPriority Chris@55: is set to a custom value */ Chris@55: paWinWasapiThreadPriority = (1 << 4) Chris@55: } Chris@55: PaWasapiFlags; Chris@55: #define paWinWasapiExclusive (paWinWasapiExclusive) Chris@55: #define paWinWasapiRedirectHostProcessor (paWinWasapiRedirectHostProcessor) Chris@55: #define paWinWasapiUseChannelMask (paWinWasapiUseChannelMask) Chris@55: #define paWinWasapiPolling (paWinWasapiPolling) Chris@55: #define paWinWasapiThreadPriority (paWinWasapiThreadPriority) Chris@55: Chris@55: Chris@55: /* Host processor. Allows to skip internal PA processing completely. Chris@55: You must set paWinWasapiRedirectHostProcessor flag to PaWasapiStreamInfo::flags member Chris@55: in order to have host processor redirected to your callback. Chris@55: Use with caution! inputFrames and outputFrames depend solely on final device setup. Chris@55: To query maximal values of inputFrames/outputFrames use PaWasapi_GetFramesPerHostBuffer. Chris@55: */ Chris@55: typedef void (*PaWasapiHostProcessorCallback) (void *inputBuffer, long inputFrames, Chris@55: void *outputBuffer, long outputFrames, Chris@55: void *userData); Chris@55: Chris@55: /* Device role. */ Chris@55: typedef enum PaWasapiDeviceRole Chris@55: { Chris@55: eRoleRemoteNetworkDevice = 0, Chris@55: eRoleSpeakers, Chris@55: eRoleLineLevel, Chris@55: eRoleHeadphones, Chris@55: eRoleMicrophone, Chris@55: eRoleHeadset, Chris@55: eRoleHandset, Chris@55: eRoleUnknownDigitalPassthrough, Chris@55: eRoleSPDIF, Chris@55: eRoleHDMI, Chris@55: eRoleUnknownFormFactor Chris@55: } Chris@55: PaWasapiDeviceRole; Chris@55: Chris@55: Chris@55: /* Jack connection type. */ Chris@55: typedef enum PaWasapiJackConnectionType Chris@55: { Chris@55: eJackConnTypeUnknown, Chris@55: eJackConnType3Point5mm, Chris@55: eJackConnTypeQuarter, Chris@55: eJackConnTypeAtapiInternal, Chris@55: eJackConnTypeRCA, Chris@55: eJackConnTypeOptical, Chris@55: eJackConnTypeOtherDigital, Chris@55: eJackConnTypeOtherAnalog, Chris@55: eJackConnTypeMultichannelAnalogDIN, Chris@55: eJackConnTypeXlrProfessional, Chris@55: eJackConnTypeRJ11Modem, Chris@55: eJackConnTypeCombination Chris@55: } Chris@55: PaWasapiJackConnectionType; Chris@55: Chris@55: Chris@55: /* Jack geometric location. */ Chris@55: typedef enum PaWasapiJackGeoLocation Chris@55: { Chris@55: eJackGeoLocUnk = 0, Chris@55: eJackGeoLocRear = 0x1, /* matches EPcxGeoLocation::eGeoLocRear */ Chris@55: eJackGeoLocFront, Chris@55: eJackGeoLocLeft, Chris@55: eJackGeoLocRight, Chris@55: eJackGeoLocTop, Chris@55: eJackGeoLocBottom, Chris@55: eJackGeoLocRearPanel, Chris@55: eJackGeoLocRiser, Chris@55: eJackGeoLocInsideMobileLid, Chris@55: eJackGeoLocDrivebay, Chris@55: eJackGeoLocHDMI, Chris@55: eJackGeoLocOutsideMobileLid, Chris@55: eJackGeoLocATAPI, Chris@55: eJackGeoLocReserved5, Chris@55: eJackGeoLocReserved6, Chris@55: } Chris@55: PaWasapiJackGeoLocation; Chris@55: Chris@55: Chris@55: /* Jack general location. */ Chris@55: typedef enum PaWasapiJackGenLocation Chris@55: { Chris@55: eJackGenLocPrimaryBox = 0, Chris@55: eJackGenLocInternal, Chris@55: eJackGenLocSeparate, Chris@55: eJackGenLocOther Chris@55: } Chris@55: PaWasapiJackGenLocation; Chris@55: Chris@55: Chris@55: /* Jack's type of port. */ Chris@55: typedef enum PaWasapiJackPortConnection Chris@55: { Chris@55: eJackPortConnJack = 0, Chris@55: eJackPortConnIntegratedDevice, Chris@55: eJackPortConnBothIntegratedAndJack, Chris@55: eJackPortConnUnknown Chris@55: } Chris@55: PaWasapiJackPortConnection; Chris@55: Chris@55: Chris@55: /* Thread priority. */ Chris@55: typedef enum PaWasapiThreadPriority Chris@55: { Chris@55: eThreadPriorityNone = 0, Chris@55: eThreadPriorityAudio, //!< Default for Shared mode. Chris@55: eThreadPriorityCapture, Chris@55: eThreadPriorityDistribution, Chris@55: eThreadPriorityGames, Chris@55: eThreadPriorityPlayback, Chris@55: eThreadPriorityProAudio, //!< Default for Exclusive mode. Chris@55: eThreadPriorityWindowManager Chris@55: } Chris@55: PaWasapiThreadPriority; Chris@55: Chris@55: Chris@55: /* Stream descriptor. */ Chris@55: typedef struct PaWasapiJackDescription Chris@55: { Chris@55: unsigned long channelMapping; Chris@55: unsigned long color; /* derived from macro: #define RGB(r,g,b) ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16))) */ Chris@55: PaWasapiJackConnectionType connectionType; Chris@55: PaWasapiJackGeoLocation geoLocation; Chris@55: PaWasapiJackGenLocation genLocation; Chris@55: PaWasapiJackPortConnection portConnection; Chris@55: unsigned int isConnected; Chris@55: } Chris@55: PaWasapiJackDescription; Chris@55: Chris@55: Chris@55: /** Stream category. Chris@55: Note: Chris@55: - values are equal to WASAPI AUDIO_STREAM_CATEGORY enum Chris@55: - supported since Windows 8.0, noop on earler versions Chris@55: - values 1,2 are deprecated on Windows 10 and not included into enumeration Chris@55: Chris@55: @version Available as of 19.6.0 Chris@55: */ Chris@55: typedef enum PaWasapiStreamCategory Chris@55: { Chris@55: eAudioCategoryOther = 0, Chris@55: eAudioCategoryCommunications = 3, Chris@55: eAudioCategoryAlerts = 4, Chris@55: eAudioCategorySoundEffects = 5, Chris@55: eAudioCategoryGameEffects = 6, Chris@55: eAudioCategoryGameMedia = 7, Chris@55: eAudioCategoryGameChat = 8, Chris@55: eAudioCategorySpeech = 9, Chris@55: eAudioCategoryMovie = 10, Chris@55: eAudioCategoryMedia = 11 Chris@55: } Chris@55: PaWasapiStreamCategory; Chris@55: Chris@55: Chris@55: /** Stream option. Chris@55: Note: Chris@55: - values are equal to WASAPI AUDCLNT_STREAMOPTIONS enum Chris@55: - supported since Windows 8.1, noop on earler versions Chris@55: Chris@55: @version Available as of 19.6.0 Chris@55: */ Chris@55: typedef enum PaWasapiStreamOption Chris@55: { Chris@55: eStreamOptionNone = 0, //!< default Chris@55: eStreamOptionRaw = 1, //!< bypass WASAPI Audio Engine DSP effects, supported since Windows 8.1 Chris@55: eStreamOptionMatchFormat = 2 //!< force WASAPI Audio Engine into a stream format, supported since Windows 10 Chris@55: } Chris@55: PaWasapiStreamOption; Chris@55: Chris@55: Chris@55: /* Stream descriptor. */ Chris@55: typedef struct PaWasapiStreamInfo Chris@55: { Chris@55: unsigned long size; /**< sizeof(PaWasapiStreamInfo) */ Chris@55: PaHostApiTypeId hostApiType; /**< paWASAPI */ Chris@55: unsigned long version; /**< 1 */ Chris@55: Chris@55: unsigned long flags; /**< collection of PaWasapiFlags */ Chris@55: Chris@55: /** Support for WAVEFORMATEXTENSIBLE channel masks. If flags contains Chris@55: paWinWasapiUseChannelMask this allows you to specify which speakers Chris@55: to address in a multichannel stream. Constants for channelMask Chris@55: are specified in pa_win_waveformat.h. Will be used only if Chris@55: paWinWasapiUseChannelMask flag is specified. Chris@55: */ Chris@55: PaWinWaveFormatChannelMask channelMask; Chris@55: Chris@55: /** Delivers raw data to callback obtained from GetBuffer() methods skipping Chris@55: internal PortAudio processing inventory completely. userData parameter will Chris@55: be the same that was passed to Pa_OpenStream method. Will be used only if Chris@55: paWinWasapiRedirectHostProcessor flag is specified. Chris@55: */ Chris@55: PaWasapiHostProcessorCallback hostProcessorOutput; Chris@55: PaWasapiHostProcessorCallback hostProcessorInput; Chris@55: Chris@55: /** Specifies thread priority explicitly. Will be used only if paWinWasapiThreadPriority flag Chris@55: is specified. Chris@55: Chris@55: Please note, if Input/Output streams are opened simultaniously (Full-Duplex mode) Chris@55: you shall specify same value for threadPriority or othervise one of the values will be used Chris@55: to setup thread priority. Chris@55: */ Chris@55: PaWasapiThreadPriority threadPriority; Chris@55: Chris@55: /** Stream category. Chris@55: @see PaWasapiStreamCategory Chris@55: @version Available as of 19.6.0 Chris@55: */ Chris@55: PaWasapiStreamCategory streamCategory; Chris@55: Chris@55: /** Stream option. Chris@55: @see PaWasapiStreamOption Chris@55: @version Available as of 19.6.0 Chris@55: */ Chris@55: PaWasapiStreamOption streamOption; Chris@55: } Chris@55: PaWasapiStreamInfo; Chris@55: Chris@55: Chris@55: /** Returns default sound format for device. Format is represented by PaWinWaveFormat or Chris@55: WAVEFORMATEXTENSIBLE structure. Chris@55: Chris@55: @param pFormat Pointer to PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure. Chris@55: @param nFormatSize Size of PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure in bytes. Chris@55: @param nDevice Device index. Chris@55: Chris@55: @return Non-negative value indicating the number of bytes copied into format decriptor Chris@55: or, a PaErrorCode (which are always negative) if PortAudio is not initialized Chris@55: or an error is encountered. Chris@55: */ Chris@55: int PaWasapi_GetDeviceDefaultFormat( void *pFormat, unsigned int nFormatSize, PaDeviceIndex nDevice ); Chris@55: Chris@55: Chris@55: /** Returns device role (PaWasapiDeviceRole enum). Chris@55: Chris@55: @param nDevice device index. Chris@55: Chris@55: @return Non-negative value indicating device role or, a PaErrorCode (which are always negative) Chris@55: if PortAudio is not initialized or an error is encountered. Chris@55: */ Chris@55: int/*PaWasapiDeviceRole*/ PaWasapi_GetDeviceRole( PaDeviceIndex nDevice ); Chris@55: Chris@55: Chris@55: /** Boost thread priority of calling thread (MMCSS). Use it for Blocking Interface only for thread Chris@55: which makes calls to Pa_WriteStream/Pa_ReadStream. Chris@55: Chris@55: @param hTask Handle to pointer to priority task. Must be used with PaWasapi_RevertThreadPriority Chris@55: method to revert thread priority to initial state. Chris@55: Chris@55: @param nPriorityClass Id of thread priority of PaWasapiThreadPriority type. Specifying Chris@55: eThreadPriorityNone does nothing. Chris@55: Chris@55: @return Error code indicating success or failure. Chris@55: @see PaWasapi_RevertThreadPriority Chris@55: */ Chris@55: PaError PaWasapi_ThreadPriorityBoost( void **hTask, PaWasapiThreadPriority nPriorityClass ); Chris@55: Chris@55: Chris@55: /** Boost thread priority of calling thread (MMCSS). Use it for Blocking Interface only for thread Chris@55: which makes calls to Pa_WriteStream/Pa_ReadStream. Chris@55: Chris@55: @param hTask Task handle obtained by PaWasapi_BoostThreadPriority method. Chris@55: @return Error code indicating success or failure. Chris@55: @see PaWasapi_BoostThreadPriority Chris@55: */ Chris@55: PaError PaWasapi_ThreadPriorityRevert( void *hTask ); Chris@55: Chris@55: Chris@55: /** Get number of frames per host buffer. This is maximal value of frames of WASAPI buffer which Chris@55: can be locked for operations. Use this method as helper to findout maximal values of Chris@55: inputFrames/outputFrames of PaWasapiHostProcessorCallback. Chris@55: Chris@55: @param pStream Pointer to PaStream to query. Chris@55: @param nInput Pointer to variable to receive number of input frames. Can be NULL. Chris@55: @param nOutput Pointer to variable to receive number of output frames. Can be NULL. Chris@55: @return Error code indicating success or failure. Chris@55: @see PaWasapiHostProcessorCallback Chris@55: */ Chris@55: PaError PaWasapi_GetFramesPerHostBuffer( PaStream *pStream, unsigned int *nInput, unsigned int *nOutput ); Chris@55: Chris@55: Chris@55: /** Get number of jacks associated with a WASAPI device. Use this method to determine if Chris@55: there are any jacks associated with the provided WASAPI device. Not all audio devices Chris@55: will support this capability. This is valid for both input and output devices. Chris@55: @param nDevice device index. Chris@55: @param jcount Number of jacks is returned in this variable Chris@55: @return Error code indicating success or failure Chris@55: @see PaWasapi_GetJackDescription Chris@55: */ Chris@55: PaError PaWasapi_GetJackCount(PaDeviceIndex nDevice, int *jcount); Chris@55: Chris@55: Chris@55: /** Get the jack description associated with a WASAPI device and jack number Chris@55: Before this function is called, use PaWasapi_GetJackCount to determine the Chris@55: number of jacks associated with device. If jcount is greater than zero, then Chris@55: each jack from 0 to jcount can be queried with this function to get the jack Chris@55: description. Chris@55: @param nDevice device index. Chris@55: @param jindex Which jack to return information Chris@55: @param KSJACK_DESCRIPTION This structure filled in on success. Chris@55: @return Error code indicating success or failure Chris@55: @see PaWasapi_GetJackCount Chris@55: */ Chris@55: PaError PaWasapi_GetJackDescription(PaDeviceIndex nDevice, int jindex, PaWasapiJackDescription *pJackDescription); Chris@55: Chris@55: Chris@55: /* Chris@55: IMPORTANT: Chris@55: Chris@55: WASAPI is implemented for Callback and Blocking interfaces. It supports Shared and Exclusive Chris@55: share modes. Chris@55: Chris@55: Exclusive Mode: Chris@55: Chris@55: Exclusive mode allows to deliver audio data directly to hardware bypassing Chris@55: software mixing. Chris@55: Exclusive mode is specified by 'paWinWasapiExclusive' flag. Chris@55: Chris@55: Callback Interface: Chris@55: Chris@55: Provides best audio quality with low latency. Callback interface is implemented in Chris@55: two versions: Chris@55: Chris@55: 1) Event-Driven: Chris@55: This is the most powerful WASAPI implementation which provides glitch-free Chris@55: audio at around 3ms latency in Exclusive mode. Lowest possible latency for this mode is Chris@55: 3 ms for HD Audio class audio chips. For the Shared mode latency can not be Chris@55: lower than 20 ms. Chris@55: Chris@55: 2) Poll-Driven: Chris@55: Polling is another 2-nd method to operate with WASAPI. It is less efficient than Event-Driven Chris@55: and provides latency at around 10-13ms. Polling must be used to overcome a system bug Chris@55: under Windows Vista x64 when application is WOW64(32-bit) and Event-Driven method simply Chris@55: times out (event handle is never signalled on buffer completion). Please note, such WOW64 bug Chris@55: does not exist in Vista x86 or Windows 7. Chris@55: Polling can be setup by speciying 'paWinWasapiPolling' flag. Our WASAPI implementation detects Chris@55: WOW64 bug and sets 'paWinWasapiPolling' automatically. Chris@55: Chris@55: Thread priority: Chris@55: Chris@55: Normally thread priority is set automatically and does not require modification. Although Chris@55: if user wants some tweaking thread priority can be modified by setting 'paWinWasapiThreadPriority' Chris@55: flag and specifying 'PaWasapiStreamInfo::threadPriority' with value from PaWasapiThreadPriority Chris@55: enum. Chris@55: Chris@55: Blocking Interface: Chris@55: Chris@55: Blocking interface is implemented but due to above described Poll-Driven method can not Chris@55: deliver lowest possible latency. Specifying too low latency in Shared mode will result in Chris@55: distorted audio although Exclusive mode adds stability. Chris@55: Chris@55: Pa_IsFormatSupported: Chris@55: Chris@55: To check format with correct Share Mode (Exclusive/Shared) you must supply Chris@55: PaWasapiStreamInfo with flags paWinWasapiExclusive set through member of Chris@55: PaStreamParameters::hostApiSpecificStreamInfo structure. Chris@55: Chris@55: Pa_OpenStream: Chris@55: Chris@55: To set desired Share Mode (Exclusive/Shared) you must supply Chris@55: PaWasapiStreamInfo with flags paWinWasapiExclusive set through member of Chris@55: PaStreamParameters::hostApiSpecificStreamInfo structure. Chris@55: */ Chris@55: Chris@55: #ifdef __cplusplus Chris@55: } Chris@55: #endif /* __cplusplus */ Chris@55: Chris@55: #endif /* PA_WIN_WASAPI_H */