mirror of
				https://github.com/cookiengineer/audacity
				synced 2025-11-04 16:14:00 +01:00 
			
		
		
		
	Recreate and apply the WASAPI loopback patch
This commit is contained in:
		@@ -449,6 +449,9 @@ typedef struct PaWasapiDeviceInfo
 | 
			
		||||
 | 
			
		||||
	// Formfactor
 | 
			
		||||
	EndpointFormFactor formFactor;
 | 
			
		||||
 | 
			
		||||
	// Loopback indicator
 | 
			
		||||
	int loopBack;
 | 
			
		||||
}
 | 
			
		||||
PaWasapiDeviceInfo;
 | 
			
		||||
 | 
			
		||||
@@ -1674,6 +1677,8 @@ static PaError CreateDeviceList(PaWasapiHostApiRepresentation *paWasapi, PaHostA
 | 
			
		||||
	IMMDeviceEnumerator *pEnumerator = NULL;
 | 
			
		||||
#endif
 | 
			
		||||
	IAudioClient *tmpClient;
 | 
			
		||||
	UINT renderCount;
 | 
			
		||||
	INT devIndex;
 | 
			
		||||
 | 
			
		||||
	// Make sure device list empty
 | 
			
		||||
	if ((paWasapi->deviceCount != 0) || (hostApi->info.deviceCount != 0))
 | 
			
		||||
@@ -1738,6 +1743,19 @@ static PaError CreateDeviceList(PaWasapiHostApiRepresentation *paWasapi, PaHostA
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	hr = IMMDeviceEnumerator_EnumAudioEndpoints(pEnumerator, eRender, DEVICE_STATE_ACTIVE, &pEndPoints);
 | 
			
		||||
	// We need to set the result to a value otherwise we will return paNoError
 | 
			
		||||
	// [IF_FAILED_JUMP(hResult, error);]
 | 
			
		||||
	IF_FAILED_INTERNAL_ERROR_JUMP(hr, result, error);
 | 
			
		||||
 | 
			
		||||
	hr = IMMDeviceCollection_GetCount(pEndPoints, &renderCount);
 | 
			
		||||
	// We need to set the result to a value otherwise we will return paNoError
 | 
			
		||||
	// [IF_FAILED_JUMP(hResult, error);]
 | 
			
		||||
	IF_FAILED_INTERNAL_ERROR_JUMP(hr, result, error);
 | 
			
		||||
 | 
			
		||||
	SAFE_RELEASE(pEndPoints);
 | 
			
		||||
	pEndPoints = NULL;
 | 
			
		||||
 | 
			
		||||
    hr = IMMDeviceEnumerator_EnumAudioEndpoints(pEnumerator, eAll, DEVICE_STATE_ACTIVE, &pEndPoints);
 | 
			
		||||
	// We need to set the result to a value otherwise we will return paNoError
 | 
			
		||||
	// [IF_FAILED_JUMP(hResult, error);]
 | 
			
		||||
@@ -1748,6 +1766,7 @@ static PaError CreateDeviceList(PaWasapiHostApiRepresentation *paWasapi, PaHostA
 | 
			
		||||
	// [IF_FAILED_JUMP(hResult, error);]
 | 
			
		||||
	IF_FAILED_INTERNAL_ERROR_JUMP(hr, result, error);
 | 
			
		||||
 | 
			
		||||
	paWasapi->deviceCount += renderCount;
 | 
			
		||||
#else
 | 
			
		||||
	// Determine number of available devices by activating AudioClient for render and capture data flows
 | 
			
		||||
	if (SUCCEEDED(ActivateAudioInterface_WINRT(eRender, GetAudioClientIID(), &tmpClient)))
 | 
			
		||||
@@ -1797,7 +1816,7 @@ static PaError CreateDeviceList(PaWasapiHostApiRepresentation *paWasapi, PaHostA
 | 
			
		||||
        }
 | 
			
		||||
		memset(deviceInfoArray, 0, sizeof(PaDeviceInfo) * deviceCount);
 | 
			
		||||
 | 
			
		||||
        for (i = 0; i < paWasapi->deviceCount; ++i)
 | 
			
		||||
        for (devIndex = 0, i = 0; i < paWasapi->deviceCount; ++i, ++devIndex)
 | 
			
		||||
		{
 | 
			
		||||
            PaDeviceInfo *deviceInfo  = &deviceInfoArray[i];
 | 
			
		||||
            deviceInfo->structVersion = 2;
 | 
			
		||||
@@ -1807,7 +1826,7 @@ static PaError CreateDeviceList(PaWasapiHostApiRepresentation *paWasapi, PaHostA
 | 
			
		||||
			PA_DEBUG(("WASAPI: ---------------\n"));
 | 
			
		||||
 | 
			
		||||
		#ifndef PA_WINRT
 | 
			
		||||
            hr = IMMDeviceCollection_Item(pEndPoints, i, &paWasapi->devInfo[i].device);
 | 
			
		||||
            hr = IMMDeviceCollection_Item(pEndPoints, devIndex, &paWasapi->devInfo[i].device);
 | 
			
		||||
			// We need to set the result to a value otherwise we will return paNoError
 | 
			
		||||
			// [IF_FAILED_JUMP(hResult, error);]
 | 
			
		||||
			IF_FAILED_INTERNAL_ERROR_JUMP(hr, result, error);
 | 
			
		||||
@@ -2039,6 +2058,42 @@ static PaError CreateDeviceList(PaWasapiHostApiRepresentation *paWasapi, PaHostA
 | 
			
		||||
 | 
			
		||||
            hostApi->deviceInfos[i] = deviceInfo;
 | 
			
		||||
            ++hostApi->info.deviceCount;
 | 
			
		||||
 | 
			
		||||
			if (paWasapi->devInfo[i].flow == eRender)
 | 
			
		||||
			{
 | 
			
		||||
				char *deviceName;
 | 
			
		||||
 | 
			
		||||
				memcpy(&deviceInfoArray[i + 1], deviceInfo, sizeof(*deviceInfo));
 | 
			
		||||
				memcpy(&paWasapi->devInfo[i + 1], &paWasapi->devInfo[i], sizeof(*paWasapi->devInfo));
 | 
			
		||||
 | 
			
		||||
				i++;
 | 
			
		||||
				paWasapi->devInfo[i].loopBack = 1;
 | 
			
		||||
 | 
			
		||||
				deviceInfo = &deviceInfoArray[i];
 | 
			
		||||
 | 
			
		||||
				deviceInfo->maxInputChannels			= deviceInfo->maxOutputChannels;
 | 
			
		||||
				deviceInfo->defaultHighInputLatency		= deviceInfo->defaultHighOutputLatency;
 | 
			
		||||
				deviceInfo->defaultLowInputLatency		= deviceInfo->defaultLowOutputLatency;
 | 
			
		||||
				deviceInfo->maxOutputChannels			= 0;
 | 
			
		||||
				deviceInfo->defaultHighOutputLatency	= 0;
 | 
			
		||||
				deviceInfo->defaultLowOutputLatency		= 0;
 | 
			
		||||
				PA_DEBUG(("WASAPI:%d| def.SR[%d] max.CH[%d] latency{hi[%f] lo[%f]}\n", i, (UINT32)deviceInfo->defaultSampleRate,
 | 
			
		||||
						 deviceInfo->maxInputChannels, (float)deviceInfo->defaultHighInputLatency, (float)deviceInfo->defaultLowInputLatency));
 | 
			
		||||
 | 
			
		||||
				IMMDevice_AddRef(paWasapi->devInfo[i].device);
 | 
			
		||||
 | 
			
		||||
				deviceName = (char *)PaUtil_GroupAllocateMemory(paWasapi->allocations, MAX_STR_LEN + 1);
 | 
			
		||||
				if (deviceName == NULL)
 | 
			
		||||
				{
 | 
			
		||||
					result = paInsufficientMemory;
 | 
			
		||||
					goto error;
 | 
			
		||||
				}
 | 
			
		||||
				_snprintf(deviceName, MAX_STR_LEN-1, "%s (loopback)", deviceInfo->name);
 | 
			
		||||
				deviceInfo->name = deviceName;
 | 
			
		||||
 | 
			
		||||
				hostApi->deviceInfos[i] = deviceInfo;
 | 
			
		||||
				++hostApi->info.deviceCount;
 | 
			
		||||
			}
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
	#if defined(PA_WASAPI_MAX_CONST_DEVICE_COUNT) && (PA_WASAPI_MAX_CONST_DEVICE_COUNT > 0)
 | 
			
		||||
@@ -2392,6 +2447,29 @@ int PaWasapi_GetDeviceRole( PaDeviceIndex device )
 | 
			
		||||
	return paWasapi->devInfo[ index ].formFactor;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------
 | 
			
		||||
int PaWasapi_IsLoopback( PaDeviceIndex nDevice )
 | 
			
		||||
{
 | 
			
		||||
	PaError ret;
 | 
			
		||||
	PaDeviceIndex index;
 | 
			
		||||
 | 
			
		||||
	// Get API
 | 
			
		||||
	PaWasapiHostApiRepresentation *paWasapi = _GetHostApi(&ret);
 | 
			
		||||
	if (paWasapi == NULL)
 | 
			
		||||
		return paNotInitialized;
 | 
			
		||||
 | 
			
		||||
	// Get device index
 | 
			
		||||
	ret = PaUtil_DeviceIndexToHostApiDeviceIndex(&index, nDevice, &paWasapi->inheritedHostApiRep);
 | 
			
		||||
	if (ret != paNoError)
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
	// Validate index
 | 
			
		||||
	if ((UINT32)index >= paWasapi->deviceCount)
 | 
			
		||||
		return paInvalidDevice;
 | 
			
		||||
 | 
			
		||||
	return paWasapi->devInfo[ index ].loopBack;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------
 | 
			
		||||
PaError PaWasapi_GetFramesPerHostBuffer( PaStream *pStream, unsigned int *pInput, unsigned int *pOutput )
 | 
			
		||||
{
 | 
			
		||||
@@ -3055,7 +3133,7 @@ static HRESULT CreateAudioClient(PaWasapiStream *pStream, PaWasapiSubStream *pSu
 | 
			
		||||
	if ((params->channelCount == 1) && (pSub->wavex.Format.nChannels == 2))
 | 
			
		||||
	{
 | 
			
		||||
		// select mixer
 | 
			
		||||
		pSub->monoMixer = GetMonoToStereoMixer(&pSub->wavex, (pInfo->flow == eRender ? MIX_DIR__1TO2 : MIX_DIR__2TO1_L));
 | 
			
		||||
		pSub->monoMixer = GetMonoToStereoMixer(&pSub->wavex, (output ? MIX_DIR__1TO2 : MIX_DIR__2TO1_L));
 | 
			
		||||
		if (pSub->monoMixer == NULL)
 | 
			
		||||
		{
 | 
			
		||||
			(*pa_error) = paInvalidChannelCount;
 | 
			
		||||
@@ -3618,6 +3696,9 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
 | 
			
		||||
			((inputStreamInfo != NULL) && (inputStreamInfo->flags & paWinWasapiAutoConvert)))
 | 
			
		||||
			stream->in.streamFlags |= (AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM | AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY);
 | 
			
		||||
 | 
			
		||||
        if (info->flow == eRender)
 | 
			
		||||
            stream->in.streamFlags |= AUDCLNT_STREAMFLAGS_LOOPBACK;
 | 
			
		||||
 | 
			
		||||
		// Fill parameters for Audio Client creation
 | 
			
		||||
		stream->in.params.device_info       = info;
 | 
			
		||||
		stream->in.params.stream_params     = (*inputParameters);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user