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