LoopbackAudioSource::LoopbackAudioSource()
{
	HRESULT hr;
	CComPtr<IMMDeviceEnumerator> enumerator;
	hr = enumerator.CoCreateInstance(__uuidof(MMDeviceEnumerator));
	assert(SUCCEEDED(hr));
	CComPtr<IMMDevice> device;
	hr = enumerator->GetDefaultAudioEndpoint(eRender, eConsole, &device);
	assert(SUCCEEDED(hr));

	hr = device->Activate(__uuidof(IAudioClient), CLSCTX_ALL, nullptr, (void **)&event_client_);
	assert(SUCCEEDED(hr));
	hr = event_client_->GetMixFormat(&format_);
	assert(SUCCEEDED(hr));
	hr = event_client_->Initialize(AUDCLNT_SHAREMODE_SHARED,
		                           AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
		                           0, 0, format_, nullptr);
	assert(SUCCEEDED(hr));
	event_handle_ = CreateEventW(nullptr, FALSE, FALSE, nullptr);
	assert(event_handle_);
	hr = event_client_->SetEventHandle(event_handle_);
	assert(SUCCEEDED(hr));
	hr = device->Activate(__uuidof(IAudioClient), CLSCTX_ALL, nullptr, (void **)&loopback_client_);
	assert(SUCCEEDED(hr));
	hr = loopback_client_->Initialize(AUDCLNT_SHAREMODE_SHARED,
		                              AUDCLNT_STREAMFLAGS_LOOPBACK,
		                              0, 0, format_, nullptr);
	assert(SUCCEEDED(hr));
	hr = loopback_client_->GetService(__uuidof(IAudioCaptureClient), (void **)&capture_client_);
	assert(SUCCEEDED(hr));
	hr = event_client_->Start();
	assert(SUCCEEDED(hr));
	hr = loopback_client_->Start();
	assert(SUCCEEDED(hr));
}
///////////////////////////////////////////////////////////////////////////
//
// Function:
//      DeviceBindTo
//
// Description:
//      Bind device to an IAudioClient interface.
//
//  Parameters:
//      eDataFlow: eRender for render device, eCapture for capture device
//      iDevIdx: Index of device in the enumeration list. If it is -1, use default device 
//      ppVoid: pointer pointer to IAudioClient interface.
//      ppszEndpointDeviceId: Device ID. Caller is responsible for freeing memeory
//              using CoTaskMemoryFree. If can be NULL if called doesn't need this info.
//
// Return:
//      S_OK if successful
//
///////////////////////////////////////////////////////////////////////////////
HRESULT DeviceBindTo(
        EDataFlow eDataFlow,    // eCapture/eRender
        INT iDevIdx,        // Device Index. -1 - default device. 
        IAudioClient **ppAudioClient,    // pointer pointer to IAudioClient interface
        IAudioEndpointVolume **ppEndpointVolume,
        WCHAR** ppszEndpointDeviceId)   // Device ID. Need to be freed in caller with CoTaskMemoryFree if it is not NULL
{
    HRESULT hResult;

    CComPtr<IMMDeviceEnumerator> spEnumerator;
    CComPtr<IMMDeviceCollection> spEndpoints;    
    CComPtr<IMMDevice> spDevice;
    WCHAR *pszDeviceId = NULL;

    if (ppAudioClient == NULL) 
        return E_POINTER;
    
    *ppAudioClient = NULL;

    hResult = spEnumerator.CoCreateInstance(__uuidof(MMDeviceEnumerator));
    IF_FAILED_JUMP(hResult, Exit);

    // use default device
    if (iDevIdx < 0 )
    {
        hResult = spEnumerator->GetDefaultAudioEndpoint(eDataFlow, eConsole, &spDevice);
        IF_FAILED_JUMP(hResult, Exit);
    }else{
        // User selected device
        hResult = spEnumerator->EnumAudioEndpoints(eDataFlow, DEVICE_STATE_ACTIVE, &spEndpoints);
        IF_FAILED_JUMP(hResult, Exit);

        hResult = spEndpoints->Item(iDevIdx, &spDevice);
        IF_FAILED_JUMP(hResult, Exit);
    }

    // get device ID and format
    hResult = spDevice->GetId(&pszDeviceId);
    IF_FAILED_JUMP(hResult, Exit);

    // Active device
    hResult = spDevice->Activate(__uuidof(IAudioClient), CLSCTX_INPROC_SERVER, NULL, (void**)ppAudioClient);
    IF_FAILED_JUMP(hResult, Exit);

    if (ppEndpointVolume)
    {
        hResult = spDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_INPROC_SERVER, NULL, (void **)ppEndpointVolume);
        IF_FAILED_JUMP(hResult, Exit);
    }
    
Exit:
    if (ppszEndpointDeviceId)
        *ppszEndpointDeviceId = pszDeviceId;
    else if (pszDeviceId)
        CoTaskMemFree(pszDeviceId);
    
    return hResult;
}
示例#3
0
HRESULT AudioSessionService::RefreshAudioSessions()
{
    CleanUpAudioSessions();

    CComPtr<IMMDeviceEnumerator> deviceEnumerator;
    FAST_FAIL(CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_INPROC, IID_PPV_ARGS(&deviceEnumerator)));

    // TIP: Role parameter is not actually used https://msdn.microsoft.com/en-us/library/windows/desktop/dd371401.aspx
    CComPtr<IMMDevice> device;
    FAST_FAIL(deviceEnumerator->GetDefaultAudioEndpoint(EDataFlow::eRender, ERole::eMultimedia, &device));

    CComPtr<IAudioSessionManager2> audioSessionManager;
    FAST_FAIL(device->Activate(__uuidof(IAudioSessionManager2), CLSCTX_INPROC, nullptr, (void**)&audioSessionManager));

    CComPtr<IAudioSessionEnumerator> audioSessionEnumerator;
    FAST_FAIL(audioSessionManager->GetSessionEnumerator(&audioSessionEnumerator));

    int sessionCount;
    FAST_FAIL(audioSessionEnumerator->GetCount(&sessionCount));

    for (int i = 0; i < sessionCount; i++)
    {
        EarTrumpetAudioSession audioSession;
        if (SUCCEEDED(CreateEtAudioSessionFromAudioSession(audioSessionEnumerator, i, &audioSession)))
        {
            _sessions.push_back(audioSession);
        }
    }

    return S_OK;
}
/**
	Static function to create a template select dialog.
**/
void CTemplateSelectDialog::DoDialog()
{
#ifdef WWHIZ_VSNET
	CComPtr<EnvDTE::Document> document;
	g_pDTE->get_ActiveDocument(&document);
#endif WWHIZ_VSNET

	while (g_wwhizTemplateManager->GetCount() == 0)
	{
		CTemplateFileListDialog dlg;
		if (dlg.DoModal() == IDCANCEL)
			return;
	}

	CTemplateSelectDialog dlg;
	if (dlg.DoModal() == IDCANCEL)
		return;

	if (dlg.m_code)
	{
#ifdef WWHIZ_VSNET
		if (document)
			document->Activate();
#endif WWHIZ_VSNET

		WWhizCommands::PutTemplate(*dlg.m_code);
	}
}
示例#5
0
HRESULT AudioDeviceService::GetAudioDeviceVolume(LPWSTR deviceId, float* volume)
{
    CComPtr<IMMDevice> device;
    FAST_FAIL(this->GetDeviceByDeviceId(deviceId, &device));

    CComPtr<IAudioEndpointVolume> audioEndpointVol;
    FAST_FAIL(device->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_INPROC, nullptr, reinterpret_cast<void**>(&audioEndpointVol)));

    return audioEndpointVol->GetMasterVolumeLevelScalar(volume);
}
示例#6
0
HRESULT AudioDeviceService::SetMuteBoolForDevice(LPWSTR deviceId, BOOL value)
{
    CComPtr<IMMDevice> device;
    FAST_FAIL(this->GetDeviceByDeviceId(deviceId, &device));

    CComPtr<IAudioEndpointVolume> audioEndpointVol;
    FAST_FAIL(device->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_INPROC, nullptr, reinterpret_cast<void**>(&audioEndpointVol)));

    return audioEndpointVol->SetMute(value, nullptr);
}
示例#7
0
bool initAudio(){
	if (!IsWindowsVistaOrGreater()) return false;
	CComPtr<IMMDevice> pDevice; // get Mgr & EndpointVolume
	CComPtr<IMMDeviceEnumerator> pDeviceEnumerator; // select output device
	CComPtr<IAudioSessionManager2> pAudioSessionManager2; // get enumerator

	// Init
	CoInitializeEx(NULL, COINIT_MULTITHREADED);
	// Device Enumerator
	pDeviceEnumerator.CoCreateInstance(__uuidof(MMDeviceEnumerator));
	// get Default Audio Endpoint Device
	pDeviceEnumerator->GetDefaultAudioEndpoint(eRender, eMultimedia, &pDevice);
	// get AudioSessionMgr2 and AudioEndpointVolume
	pDevice->Activate(__uuidof(IAudioSessionManager2), CLSCTX_ALL, NULL, (VOID**)&pAudioSessionManager2);
	pDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_ALL, NULL, (VOID**)&pEpVol);
	// get Audio Session Enumerator
	pAudioSessionManager2->GetSessionEnumerator(&pAudioSessionEnumerator);

	return true;
}
示例#8
0
/* Retrieves the default audio device from the Core Audio API
 To be used for WASAPI mode
 To be improved : choose a device (ask albain on doom9/ffdshow-tryout for sample code)
*/
HRESULT CMpcAudioRenderer::GetDefaultAudioDevice(IAudioClient **ppAudioClient)
{
	HRESULT hr;
	CComPtr<IMMDeviceEnumerator> enumerator;
	CComPtr<IMMDevice> device;

	hr = enumerator.CoCreateInstance(__uuidof(MMDeviceEnumerator));
	hr = enumerator->GetDefaultAudioEndpoint(eRender, eConsole,
							 &device);
	hr = device->Activate(__uuidof(IAudioClient), CLSCTX_ALL, NULL, reinterpret_cast<void**>(ppAudioClient));
	return hr;
}
bool FVSAccessorModule::OpenVisualStudioFileAtLineInternal(const FString& FullPath, int32 LineNumber, int32 ColumnNumber)
{
	// Check that the file actually exists first
	if (!FPaths::FileExists(FullPath))
	{
		OpenFileFailed.Broadcast(FullPath);
		return false;
	}

	// Initialize the com library, if not already by this thread
	if (!FWindowsPlatformMisc::CoInitialize())
	{
		UE_LOG(LogVSAccessor, Error, TEXT( "ERROR - Could not initialize COM library!" ));
		return false;
	}
	
	bool bDefer = false, bSuccess = false;
	CComPtr<EnvDTE::_DTE> DTE;
	if (AccessVisualStudio(DTE, SolutionPath, Locations))
	{
		// Set Focus on Visual Studio
		CComPtr<EnvDTE::Window> MainWindow;
		if (SUCCEEDED(DTE->get_MainWindow(&MainWindow)) &&
			SUCCEEDED(MainWindow->Activate()))
		{
			// Get ItemOperations
			CComPtr<EnvDTE::ItemOperations> ItemOperations;
			if (SUCCEEDED(DTE->get_ItemOperations(&ItemOperations)))
			{
				// Open File
				auto ANSIPath = StringCast<ANSICHAR>(*FullPath);
				CComBSTR COMStrFileName(ANSIPath.Get());
				CComBSTR COMStrKind(EnvDTE::vsViewKindTextView);
				CComPtr<EnvDTE::Window> Window;
				if (SUCCEEDED(ItemOperations->OpenFile(COMStrFileName, COMStrKind, &Window)))
				{
					// Scroll to Line Number
					CComPtr<EnvDTE::Document> Document;
					CComPtr<IDispatch> SelectionDispatch;
					CComPtr<EnvDTE::TextSelection> Selection;
					if (SUCCEEDED(DTE->get_ActiveDocument(&Document)) &&
						SUCCEEDED(Document->get_Selection(&SelectionDispatch)) &&
						SUCCEEDED(SelectionDispatch->QueryInterface(&Selection)) &&
						SUCCEEDED(Selection->GotoLine(LineNumber, true)))
					{
						if (ColumnNumber > 0 &&
							SUCCEEDED(Selection->MoveToLineAndOffset(LineNumber, ColumnNumber, false)))
						{
							bSuccess = true;
						}
						else
						{
							UE_LOG(LogVSAccessor, Warning, TEXT("Couldn't goto column number '%i' of line '%i' in '%s'"), ColumnNumber, LineNumber, *FullPath);
						}
					}
					else
					{
						UE_LOG(LogVSAccessor, Warning, TEXT("Couldn't goto line number '%i' in '%s'"), LineNumber, *FullPath);
					}
				}
				else
				{
					UE_LOG(LogVSAccessor, Warning, TEXT("Couldn't open file '%s'."), *FullPath);
				}

				VSLaunchFinished( true );
			}
			else
			{
				UE_LOG(LogVSAccessor, Log, TEXT("Couldn't get item operations. Visual Studio may still be initializing."), *FullPath);
				bDefer = true;
			}
		}
		else
		{
			UE_LOG(LogVSAccessor, Warning, TEXT("Couldn't set focus on Visual Studio."));
		}
	}
	else
	{
		bDefer = true;

		// We can't process until we're in the main thread, if we aren't initially defer until we are
		if ( IsInGameThread() )
		{
			// If we haven't already attempted to launch VS do so now
			if (!IsVSLaunchInProgress())
			{
				// If there's no valid instance of VS running, run one if we have it installed
				if ( !RunVisualStudioAndOpenSolution() )
				{
					bDefer = false;
				}
				else
				{
					VSLaunchStarted();
				}
			}
		}
	}

	// If we have attempted to launch VS, and it's taken too long, timeout so the user can try again
	if ( IsVSLaunchInProgress() && ( FPlatformTime::Seconds() - VSLaunchTime ) > 300 )
	{
		// We need todo this incase the process died or was kill prior to the code gaining focus of it
		bDefer = false;
		VSLaunchFinished( false );

		// We failed to open the solution and file, so lets just use the platforms default opener.
		FPlatformProcess::LaunchFileInDefaultExternalApplication( *FullPath );
	}

	// Defer the request until VS is available to take hold of
	if ( bDefer )
	{
		const FString DeferCommand = FString::Printf( TEXT( "OPEN_VS %s %d %d" ), *FullPath, LineNumber, ColumnNumber);
		LaunchVSDeferred.Broadcast( DeferCommand );
	}
	else
	{
		UE_LOG(LogVSAccessor, Warning, TEXT("Couldn't access Visual Studio"));
	}

	// Uninitialize the com library, if we initialized it above (don't call if S_FALSE)
	FWindowsPlatformMisc::CoUninitialize();

	return bSuccess;
}
// ----------------------------------------------------------------------------
// Function:
//      CSwapPropPage::OnApply
//
// Description:
//      Handle the pressing of the apply button
//
// Parameters:
//      hwndDlg - [in] Handle to the dialog box
//
// Return values:
//      TRUE to set keyboard focus on control
// ----------------------------------------------------------------------------
BOOL CSwapPropPage::OnApply
(
    HWND hwndDlg
)
{
    HRESULT hr = S_OK;

    // Commit the settings
    hr = SetSysFXState();
    IF_FAILED_JUMP(hr, Exit);

    hr = SetSwapSFXState();
    IF_FAILED_JUMP(hr, Exit);

    hr = SetSwapMFXState();
    IF_FAILED_JUMP(hr, Exit);

    hr = SetDelaySFXState();
    IF_FAILED_JUMP(hr, Exit);

    hr = SetDelayMFXState();
    IF_FAILED_JUMP(hr, Exit);
    
    if (NULL != m_pAudioFXExtParams && NULL != m_pAudioFXExtParams->pFxProperties)
    {
        hr = m_pAudioFXExtParams->pFxProperties->Commit();
        IF_FAILED_JUMP(hr, Exit);

        if (m_fReset)
        {
            // something changed that forces us to reset the format support
            CComPtr<IMMDeviceEnumerator>    spEnumerator;
            CComPtr<IMMDevice>              spMMDevice;

            // Create device enumerator and get IMMDevice from the device ID
            hr = spEnumerator.CoCreateInstance(__uuidof(MMDeviceEnumerator));
            IF_FAILED_JUMP(hr, Exit);

            hr = spEnumerator->GetDevice(m_pAudioFXExtParams->pwstrEndpointID, &spMMDevice);
            IF_FAILED_JUMP(hr, Exit);

            CComPtr<IAudioEndpointFormatControl> spEndpointFormat;  
            hr = spMMDevice->Activate(__uuidof(IAudioEndpointFormatControl), CLSCTX_ALL, NULL, (void **)&spEndpointFormat);
            IF_FAILED_JUMP(hr, Exit);

            spEndpointFormat->ResetToDefault(ENDPOINT_FORMAT_RESET_MIX_ONLY);
            m_fReset = FALSE;
        }
    }
    
Exit:
    if (SUCCEEDED(hr))
    {
        SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
    }
    else
    {
        SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_INVALID);
    }

    return(TRUE);
}
///////////////////////////////////////////////////////////////////////////////
// Function:
//      GetMicArrayGeometry()
//
// Description:
//      Obtains the geometry for the specified mic array.
//
// Parameters:  szDeviceId -- The requested device ID, which can be obtained
//                            from calling EnumAudioCaptureDevices()
//              
//              ppGeometry -- Address of the pointer to the mic-array gemometry.  
//                            Caller is ressponsible for calling CoTaskMemFree()
//                            if the call is successfull.
//
//              cbSize -- size of the geometry structure
//
// Returns:     S_OK on success
///////////////////////////////////////////////////////////////////////////////
HRESULT GetMicArrayGeometry(wchar_t szDeviceId[], KSAUDIO_MIC_ARRAY_GEOMETRY** ppGeometry, ULONG& cbSize)
{
    HRESULT hr = S_OK;

    if (szDeviceId == NULL)
        return E_INVALIDARG;
    if (ppGeometry == NULL)
        return E_POINTER;
   
    cbSize = 0;
    CComPtr<IMMDeviceEnumerator> spEnumerator;
    CComPtr<IMMDevice>           spDevice;
    CComQIPtr<IPart>             spPart;
    bool bIsMicArray;

    hr = spEnumerator.CoCreateInstance(__uuidof(MMDeviceEnumerator));
    IF_FAILED_RETURN(hr);

    hr = spEnumerator->GetDevice(szDeviceId, &spDevice);
    IF_FAILED_RETURN(hr);

    hr = EndpointIsMicArray(spDevice, bIsMicArray);
    IF_FAILED_RETURN(hr);

    if (!bIsMicArray)
        return E_FAIL;
    
    UINT nPartId = 0;
    hr = GetInputJack(spDevice, spPart);
    IF_FAILED_RETURN(hr);

    hr = spPart->GetLocalId(&nPartId);
    IF_FAILED_RETURN(hr);

    CComPtr<IDeviceTopology>     spTopology;
    CComPtr<IMMDeviceEnumerator> spEnum;
    CComPtr<IMMDevice>           spJackDevice;
    CComPtr<IKsControl>          spKsControl;
    wchar_t *                    pwstrDevice = 0;

    // Get the topology object for the part
    hr = spPart->GetTopologyObject(&spTopology);
    IF_FAILED_RETURN(hr);

    // Get the id of the IMMDevice that this topology object describes.
    hr = spTopology->GetDeviceId(&pwstrDevice);
    IF_FAILED_RETURN(hr);

    // Get an IMMDevice pointer using the ID
    hr = spEnum.CoCreateInstance(__uuidof(MMDeviceEnumerator));
    IF_FAILED_JUMP(hr, Exit);

    hr = spEnum->GetDevice(pwstrDevice, &spJackDevice);
    IF_FAILED_JUMP(hr, Exit);

    // Activate IKsControl on the IMMDevice
    hr = spJackDevice->Activate(__uuidof(IKsControl), CLSCTX_INPROC_SERVER, 
                               NULL, reinterpret_cast<void**>(&spKsControl));
    IF_FAILED_JUMP(hr, Exit);

    // At this point we can use IKsControl just as we would use DeviceIoControl
    KSP_PIN ksp;
    ULONG   cbData     = 0;
    ULONG   cbGeometry = 0;

    // Inititialize the pin property
    ::ZeroMemory(&ksp, sizeof(ksp));
    ksp.Property.Set     = KSPROPSETID_Audio;
    ksp.Property.Id      = KSPROPERTY_AUDIO_MIC_ARRAY_GEOMETRY;
    ksp.Property.Flags   = KSPROPERTY_TYPE_GET;
    ksp.PinId            = nPartId & PARTID_MASK;  

    // Get data size by passing NULL
    hr = spKsControl->KsProperty(reinterpret_cast<PKSPROPERTY>(&ksp), 
                                sizeof(ksp), NULL, 0, &cbGeometry);
    IF_FAILED_JUMP(hr, Exit);
   
    // Allocate memory for the microphone array geometry
    *ppGeometry = reinterpret_cast<KSAUDIO_MIC_ARRAY_GEOMETRY*>
                                   (::CoTaskMemAlloc(cbGeometry));

    if(*ppGeometry == 0)
    {
        hr = E_OUTOFMEMORY;
    }
    IF_FAILED_JUMP(hr, Exit);
   
    // Now retriev the mic-array structure...
    DWORD cbOut = 0;
    hr = spKsControl->KsProperty(reinterpret_cast<PKSPROPERTY>(&ksp), 
                                sizeof(ksp), *ppGeometry, cbGeometry,
                                &cbOut);
    IF_FAILED_JUMP(hr, Exit);
    cbSize = cbGeometry;
   
Exit:
    if(pwstrDevice != 0)
    {
        ::CoTaskMemFree(pwstrDevice);
    }
    return hr;
}//GetMicArrayGeometry()
示例#12
0
HRESULT ClientReader::Initialize(bool IsLoopback, FLOAT SampleRate, HANDLE WaitEvent, CComPtr<IMMDevice> InputDevice, CComPtr<IDXAudioCallback> Callback) {
	HRESULT hr = S_OK;
	BYTE* Buffer = nullptr;
	int error = 0;

	m_Callback = Callback;

	//Create the SRC_STATE object
	m_ResampleState = src_new (
		SRC_SINC_FASTEST, //More than adequate for a real time stream
		2,				  //Two channels (stereo)
		&error
	); if (error != 0) {
		m_Callback->OnObjectFailure (
			FILENAME,
			__LINE__,
			E_FAIL
		); return E_FAIL;
	}

	//"Activate" the device (create the IAudioClient interface)
	hr = InputDevice->Activate (
		__uuidof(IAudioClient),
		CLSCTX_ALL,
		nullptr,
		(void**)(&m_Client)
	); RETURN_HR(__LINE__);

	//Retrieves the device period - this is how often new information is provided
	//to the stream, in 100-nanosecond units.
	hr = m_Client->GetDevicePeriod (
		&m_Period,
		nullptr
	); RETURN_HR(__LINE__);

	//Retrieves the mix format - this is the format in which the audio endpoint gives
	//us the data.  This data will need to be resampled, so we need to know what form
	//it's in.
	hr = m_Client->GetMixFormat (
		(WAVEFORMATEX**)(&m_WaveFormat)
	); RETURN_HR(__LINE__);

	//Initialize the client, marking how we're going to be using it
	hr = m_Client->Initialize (
		AUDCLNT_SHAREMODE_SHARED, //Always use shared - exclusive is meant for drivers and is unpredictable otherwise
		WaitEvent ? AUDCLNT_STREAMFLAGS_EVENTCALLBACK : NULL | //Use an event callback if specified
		IsLoopback ? AUDCLNT_STREAMFLAGS_LOOPBACK : NULL, //Make this a loopback stream if specified
		m_Period, //Creates a buffer large enough to store one packet
		m_Period, //Use the endpoint's periodicity (this can't ve any other value)
		(WAVEFORMATEX*)(m_WaveFormat), //Pass in the wave format we just retrieved
		NULL //No audio session stuff
	); RETURN_HR(__LINE__);

	//Create the IAudioCaptureClient interface
	hr = m_Client->GetService (
		IID_PPV_ARGS(&m_CaptureClient)
	); RETURN_HR(__LINE__);

	//If using an event callback mechanism, provide the event handle (this is from CDXAudioStream)
	if (WaitEvent != NULL) {
		hr = m_Client->SetEventHandle (
			WaitEvent
		); RETURN_HR(__LINE__);
	}

	//Calculate the number of frames the endpoint is going to give us each period.
	m_PeriodFrames = (UINT32)(ceil(DOUBLE(m_Period * m_WaveFormat->Format.nSamplesPerSec) / 10000000));

	//Calculate the resample ratio - this is the ratio of the output sample rate to the input sample rate, IE
	//the sample rate specified by the application developer divided by the sample rate used by the endpoint.
	//This value is used by libsamplerate.
	m_ResampleRatio = DOUBLE(SampleRate) / DOUBLE(m_WaveFormat->Format.nSamplesPerSec); //Output sample rate / input sample rate

	return S_OK;
}
示例#13
-1
HRESULT AudioDeviceService::RefreshAudioDevices()
{
    CleanUpAudioDevices();

    CComPtr<IMMDeviceEnumerator> deviceEnumerator;
    FAST_FAIL(CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_INPROC, IID_PPV_ARGS(&deviceEnumerator)));

    CComPtr<IMMDeviceCollection> deviceCollection;
    FAST_FAIL(deviceEnumerator->EnumAudioEndpoints(EDataFlow::eRender, ERole::eMultimedia, &deviceCollection));

    CComPtr<IMMDevice> defaultDevice;
    FAST_FAIL(deviceEnumerator->GetDefaultAudioEndpoint(EDataFlow::eRender, ERole::eMultimedia, &defaultDevice));

    CComHeapPtr<wchar_t> defaultDeviceId;
    FAST_FAIL(defaultDevice->GetId(&defaultDeviceId));

    UINT numDevices;
    FAST_FAIL(deviceCollection->GetCount(&numDevices));

    for (UINT i = 0; i < numDevices; i++)
    {
        CComPtr<IMMDevice> device;
        if (FAILED(deviceCollection->Item(i, &device)))
        {
            continue;
        }

        CComHeapPtr<wchar_t> deviceId;
        FAST_FAIL(device->GetId(&deviceId));

        CComPtr<IPropertyStore> propertyStore;
        FAST_FAIL(device->OpenPropertyStore(STGM_READ, &propertyStore));

        PROPVARIANT friendlyName;
        PropVariantInit(&friendlyName);
        FAST_FAIL(propertyStore->GetValue(PKEY_Device_FriendlyName, &friendlyName));
        
        CComPtr<IAudioEndpointVolume> audioEndpointVol;
        FAST_FAIL(device->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_INPROC, nullptr, reinterpret_cast<void**>(&audioEndpointVol)));

        BOOL isMuted;
        FAST_FAIL(audioEndpointVol->GetMute(&isMuted));

        EarTrumpetAudioDevice audioDevice = {};
        FAST_FAIL(SHStrDup(friendlyName.pwszVal, &audioDevice.DisplayName));
        FAST_FAIL(SHStrDup(deviceId, &audioDevice.Id));
        audioDevice.IsDefault = (wcscmp(defaultDeviceId, deviceId) == 0);
        audioDevice.IsMuted = !!isMuted;
        _devices.push_back(audioDevice);

        PropVariantClear(&friendlyName);
    }

    return S_OK;
}