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