]> Repos - portaudio/commitdiff
wasapi: get channels count and sample rate from a mix format (IAudioClient::GetMixFor...
authordmitrykos <dmitrykos@neutroncode.com>
Mon, 10 Dec 2018 08:50:31 +0000 (10:50 +0200)
committerdmitrykos <dmitrykos@neutroncode.com>
Mon, 10 Dec 2018 08:50:31 +0000 (10:50 +0200)
include/pa_win_wasapi.h
src/hostapi/wasapi/pa_win_wasapi.c

index 3c5d792c2341784a46d90067fc2531eff5c71147..a899bf93c836a1f5944c0802029f5df4fc71e065 100644 (file)
@@ -320,7 +320,7 @@ PaError PaWasapi_GetAudioClient( PaStream *pStream, void **pAudioClient, int bOu
 PaError PaWasapi_UpdateDeviceList();
 
 
-/** Returns current sound format of the device assigned to the opened stream. Format is represented by 
+/** Returns current audio format of the device assigned to the opened stream. Format is represented by 
     PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure. Use this function to reconfirm format if 
     PA's processor is overriden and paWinWasapiRedirectHostProcessor flag is specified.
 
@@ -336,8 +336,9 @@ PaError PaWasapi_UpdateDeviceList();
 int PaWasapi_GetDeviceCurrentFormat( PaStream *pStream, void *pFormat, unsigned int nFormatSize, int bOutput );
 
 
-/** Returns default sound format for device. Format is represented by PaWinWaveFormat or 
-    WAVEFORMATEXTENSIBLE structure.
+/** Returns default audio format for device in Shared Mode. Format is represented by
+    PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure and obtained by getting
+    the device property with a PKEY_AudioEngine_DeviceFormat key.
 
  @param  pFormat     Pointer to PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure.
  @param  nFormatSize Size of PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure in bytes.
@@ -350,6 +351,21 @@ int PaWasapi_GetDeviceCurrentFormat( PaStream *pStream, void *pFormat, unsigned
 int PaWasapi_GetDeviceDefaultFormat( void *pFormat, unsigned int nFormatSize, PaDeviceIndex nDevice );
 
 
+/** Returns mix audio format for device in Shared Mode. Format is represented by
+    PaWinWaveFormat or WAVEFORMATEXTENSIBLE structureand obtained by
+    IAudioClient::GetMixFormat.
+
+ @param  pFormat     Pointer to PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure.
+ @param  nFormatSize Size of PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure in bytes.
+ @param  nDevice     Device index.
+
+ @return Non-negative value indicating the number of bytes copied into format decriptor
+         or, a PaErrorCode (which are always negative) if PortAudio is not initialized
+         or an error is encountered.
+*/
+int PaWasapi_GetDeviceMixFormat( void *pFormat, unsigned int nFormatSize, PaDeviceIndex nDevice );
+
+
 /** Returns device role (PaWasapiDeviceRole enum).
 
  @param  nDevice Device index.
index 32e6d2d36901c163bbcf9c0924d19521d420e1fa..b95c7775d331716f1027e848f98e2dbf862301b1 100644 (file)
@@ -422,6 +422,9 @@ typedef struct PaWasapiDeviceInfo
        // Default format (setup through Control Panel by user)
        WAVEFORMATEXTENSIBLE DefaultFormat;
 
+       // Mix format (internal format used by WASAPI audio engine)
+       WAVEFORMATEXTENSIBLE MixFormat;
+
     // Fields filled from IMMEndpoint'sGetDataFlow
     EDataFlow flow;
 
@@ -1586,8 +1589,6 @@ static PaError CreateDeviceList(PaWasapiHostApiRepresentation *paWasapi, PaHostA
 #ifndef PA_WINRT
     IMMDeviceCollection* pEndPoints = NULL;
        IMMDeviceEnumerator *pEnumerator = NULL;
-#else
-       WAVEFORMATEX *mixFormat;
 #endif
        IAudioClient *tmpClient;
 
@@ -1866,9 +1867,20 @@ static PaError CreateDeviceList(PaWasapiHostApiRepresentation *paWasapi, PaHostA
                                        hr = S_OK;
                                }
                                
+                               // Get mix format
+                               {
+                                       WAVEFORMATEX *mixFormat;
+
+                                       hr = IAudioClient_GetMixFormat(tmpClient, &mixFormat);
+                                       if (SUCCEEDED(hr))
+                                       {
+                                               memcpy(&paWasapi->devInfo[i].MixFormat, mixFormat, min(sizeof(paWasapi->devInfo[i].MixFormat), (sizeof(*mixFormat) + mixFormat->cbSize)));
+                                               CoTaskMemFree(mixFormat);
+                                       }
+                               }
+
+                               // Register WINRT device
                        #ifdef PA_WINRT
-                               // Get mix format which will treat as default device format
-                               hr = IAudioClient_GetMixFormat(tmpClient, &mixFormat);
                                if (SUCCEEDED(hr))
                                {
                                        // Default device
@@ -1880,9 +1892,8 @@ static PaError CreateDeviceList(PaWasapiHostApiRepresentation *paWasapi, PaHostA
                                        // State
                                        paWasapi->devInfo[i].state = DEVICE_STATE_ACTIVE;
 
-                                       // Default format
-                                       memcpy(&paWasapi->devInfo[i].DefaultFormat, mixFormat, min(sizeof(paWasapi->devInfo[i].DefaultFormat), (sizeof(*mixFormat) + mixFormat->cbSize)));
-                                       CoTaskMemFree(mixFormat);
+                                       // Default format is always a mix format
+                                       paWasapi->devInfo[i].DefaultFormat = paWasapi->devInfo[i].MixFormat;
 
                                        // Form-factor
                                        paWasapi->devInfo[i].formFactor = UnknownFormFactor;
@@ -1917,18 +1928,18 @@ static PaError CreateDeviceList(PaWasapiHostApiRepresentation *paWasapi, PaHostA
             // we can now fill in portaudio device data
             deviceInfo->maxInputChannels  = 0;
             deviceInfo->maxOutputChannels = 0;
-                       deviceInfo->defaultSampleRate = paWasapi->devInfo[i].DefaultFormat.Format.nSamplesPerSec;
+                       deviceInfo->defaultSampleRate = paWasapi->devInfo[i].MixFormat.Format.nSamplesPerSec;
             switch (paWasapi->devInfo[i].flow)
                        {
                        case eRender: {
-                deviceInfo->maxOutputChannels           = paWasapi->devInfo[i].DefaultFormat.Format.nChannels;
+                deviceInfo->maxOutputChannels           = paWasapi->devInfo[i].MixFormat.Format.nChannels;
                 deviceInfo->defaultHighOutputLatency = nano100ToSeconds(paWasapi->devInfo[i].DefaultDevicePeriod);
                 deviceInfo->defaultLowOutputLatency  = nano100ToSeconds(paWasapi->devInfo[i].MinimumDevicePeriod);
                                PA_DEBUG(("WASAPI:%d| def.SR[%d] max.CH[%d] latency{hi[%f] lo[%f]}\n", i, (UINT32)deviceInfo->defaultSampleRate,
                                        deviceInfo->maxOutputChannels, (float)deviceInfo->defaultHighOutputLatency, (float)deviceInfo->defaultLowOutputLatency));
                                break;}
                        case eCapture: {
-                deviceInfo->maxInputChannels           = paWasapi->devInfo[i].DefaultFormat.Format.nChannels;
+                deviceInfo->maxInputChannels           = paWasapi->devInfo[i].MixFormat.Format.nChannels;
                 deviceInfo->defaultHighInputLatency = nano100ToSeconds(paWasapi->devInfo[i].DefaultDevicePeriod);
                 deviceInfo->defaultLowInputLatency  = nano100ToSeconds(paWasapi->devInfo[i].MinimumDevicePeriod);
                                PA_DEBUG(("WASAPI:%d| def.SR[%d] max.CH[%d] latency{hi[%f] lo[%f]}\n", i, (UINT32)deviceInfo->defaultSampleRate,
@@ -2223,6 +2234,39 @@ int PaWasapi_GetDeviceDefaultFormat( void *pFormat, unsigned int nFormatSize, Pa
        return size;
 }
 
+// ------------------------------------------------------------------------------------------
+int PaWasapi_GetDeviceMixFormat( void *pFormat, unsigned int nFormatSize, PaDeviceIndex nDevice )
+{
+       PaError ret;
+       PaWasapiHostApiRepresentation *paWasapi;
+       UINT32 size;
+       PaDeviceIndex index;
+
+       if (pFormat == NULL)
+               return paBadBufferPtr;
+       if (nFormatSize <= 0)
+               return paBufferTooSmall;
+
+       // Get API
+       paWasapi = _GetHostApi(&ret);
+       if (paWasapi == NULL)
+               return ret;
+
+       // Get device index
+       ret = PaUtil_DeviceIndexToHostApiDeviceIndex(&index, nDevice, &paWasapi->inheritedHostApiRep);
+    if (ret != paNoError)
+        return ret;
+
+       // Validate index
+       if ((UINT32)index >= paWasapi->deviceCount)
+               return paInvalidDevice;
+       
+       size = min(nFormatSize, (UINT32)sizeof(paWasapi->devInfo[ index ].MixFormat));
+       memcpy(pFormat, &paWasapi->devInfo[ index ].MixFormat, size);
+
+       return size;
+}
+
 // ------------------------------------------------------------------------------------------
 int PaWasapi_GetDeviceRole( PaDeviceIndex nDevice )
 {