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