# C# core audio api 控制系统音量

C++导出函数

C#
#include <Windows.h>
#include <mmdeviceapi.h>
#include <endpointvolume.h>

BOOL APIENTRY DllMain(HMODULE hModule,
	DWORD  ul_reason_for_call,
	LPVOID lpReserved
)
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}


extern "C" __declspec(dllexport) IMMDeviceEnumerator * InitSystemDeviceEnumerator()
{
	CoUninitialize();
	HRESULT hr;
	hr = CoInitialize(nullptr);
	if (FAILED(hr))
	{
		return NULL;
	}

	IMMDeviceEnumerator* pEnumerator = NULL;
	hr = CoCreateInstance(
		__uuidof(MMDeviceEnumerator),
		NULL,
		CLSCTX_INPROC_SERVER,
		__uuidof(IMMDeviceEnumerator),
		(void**)&pEnumerator
	);
	if (FAILED(hr))
	{
		CoUninitialize();
		return NULL;
	}
	return pEnumerator;
}
extern "C" __declspec(dllexport) IMMDevice * InitSystemDevice(IMMDeviceEnumerator * pEnumerator)
{
	if (pEnumerator == NULL)
	{
		return NULL;
	}

	IMMDevice* pDevice = NULL;
	// 获取默认音频渲染设备
	HRESULT hr = pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pDevice);
	if (FAILED(hr)) {
		// 错误处理
		CoUninitialize();
		return NULL;
	}
	return pDevice;
}
extern "C" __declspec(dllexport) IAudioEndpointVolume * InitSystemAudioEndpointVolume(IMMDevice * pDevice)
{
	if (pDevice == NULL)
	{
		return NULL;
	}

	IAudioEndpointVolume* pEndpointVolume = NULL;
	HRESULT hr;
	hr = pDevice->Activate(
		__uuidof(IAudioEndpointVolume),
		CLSCTX_ALL,
		NULL,
		(void**)&pEndpointVolume
	);
	if (FAILED(hr))
	{
		CoUninitialize();
		return NULL;
	}
	return pEndpointVolume;
}
extern "C" __declspec(dllexport) IAudioMeterInformation * InitSystemAudioMeterInformation(IMMDevice * pDevice) {

	if (pDevice == NULL)
	{
		return NULL;
	}

	IAudioMeterInformation* pMeterInfo = NULL;
	HRESULT hr = pDevice->Activate(
		__uuidof(IAudioMeterInformation),
		CLSCTX_ALL,
		nullptr,
		(void**)(&pMeterInfo));

	if (FAILED(hr))
	{
		CoUninitialize();
		return NULL;
	}

	return pMeterInfo;
}

extern "C" __declspec(dllexport) bool FreeSystemDevice(IMMDeviceEnumerator * pEnumerator, IMMDevice * pDevice, IAudioEndpointVolume * pEndpointVolume, IAudioMeterInformation * pMeterInfo)
{
	if (pEnumerator != NULL)
	{
		pEnumerator->Release();
	}

	if (pDevice != NULL)
	{
		pDevice->Release();
	}
	if (pEndpointVolume != NULL)
	{
		pEndpointVolume->Release();
	}
	if (pMeterInfo != NULL)
	{
		pMeterInfo->Release();
	}

	CoUninitialize();
	return true;
}
extern "C" __declspec(dllexport) float GetSystemVolume(IAudioEndpointVolume * pEndpointVolume)
{
	if (pEndpointVolume == NULL)
	{
		return 0;
	}

	float volume = 0.0f;
	HRESULT hr = pEndpointVolume->GetMasterVolumeLevelScalar(&volume);
	if (FAILED(hr))
	{
		return 0;
	}
	return volume;
}
extern "C" __declspec(dllexport) bool SetSystemVolume(IAudioEndpointVolume * pEndpointVolume, float volume)
{
	if (pEndpointVolume == NULL)
	{
		return FALSE;
	}

	HRESULT hr = pEndpointVolume->SetMasterVolumeLevelScalar(volume, NULL);
	if (FAILED(hr))
	{
		return FALSE;
	}

	return true;
}

extern "C" __declspec(dllexport) float GetSystemMasterPeak(IAudioMeterInformation * pMeterInfo)
{
	if (pMeterInfo == NULL)
	{
		return 0;
	}

	float peakValue = 0.0f;
	HRESULT hr = pMeterInfo->GetPeakValue(&peakValue);
	if (FAILED(hr))
	{
		return 0;
	}
	return peakValue;
}

extern "C" __declspec(dllexport) bool GetSystemMute(IAudioEndpointVolume * pEndpointVolume)
{
	if (pEndpointVolume == NULL)
	{
		return FALSE;
	}

	BOOL mute;
	HRESULT hr = pEndpointVolume->GetMute(&mute);
	if (FAILED(hr))
	{
		return FALSE;
	}
	return mute;
}
extern "C" __declspec(dllexport) bool SetSystemMute(IAudioEndpointVolume * pEndpointVolume, BOOL mute)
{
	if (pEndpointVolume == NULL)
	{
		return FALSE;
	}

	HRESULT hr = pEndpointVolume->SetMute(mute, NULL);
	if (FAILED(hr))
	{
		return FALSE;
	}
	return true;
}

C#调用

C#
[DllImport("cmonitor.volume.dll")]
public static extern IntPtr InitSystemDeviceEnumerator();
[DllImport("cmonitor.volume.dll")]
public static extern IntPtr InitSystemDevice(IntPtr pEnumerator);
[DllImport("cmonitor.volume.dll")]
public static extern IntPtr InitSystemAudioEndpointVolume(IntPtr pDevice);
[DllImport("cmonitor.volume.dll")]
public static extern IntPtr InitSystemAudioMeterInformation(IntPtr pDevice);
[DllImport("cmonitor.volume.dll")]
public static extern bool FreeSystemDevice(IntPtr pEnumerator, IntPtr pDevice, IntPtr pEndpointVolume, IntPtr pMeterInfo);

[DllImport("cmonitor.volume.dll")]
public static extern float GetSystemVolume(IntPtr pEndpointVolume);
[DllImport("cmonitor.volume.dll")]
public static extern bool SetSystemVolume(IntPtr pEndpointVolume, float volume);
[DllImport("cmonitor.volume.dll")]
public static extern float GetSystemMasterPeak(IntPtr pMeterInfo);
[DllImport("cmonitor.volume.dll")]
public static extern bool GetSystemMute(IntPtr pEndpointVolume);
[DllImport("cmonitor.volume.dll")]
public static extern bool SetSystemMute(IntPtr pEndpointVolume, bool mute);

private IntPtr pEnumerator = IntPtr.Zero;
private IntPtr pDevice = IntPtr.Zero;
private IntPtr pEndpointVolume = IntPtr.Zero;
private IntPtr pMeterInfo = IntPtr.Zero;
private void Init()
{
    if (OperatingSystem.IsWindows())
    {
        try
        {
            pEnumerator = InitSystemDeviceEnumerator();
            if (pEnumerator != IntPtr.Zero)
            {
                pDevice = InitSystemDevice(pEnumerator);
                if (pDevice != IntPtr.Zero)
                {
                    pEndpointVolume = InitSystemAudioEndpointVolume(pDevice);
                    pMeterInfo = InitSystemAudioMeterInformation(pDevice);
                }
            }
            FreeDevice();
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
        }
    }
}
private void FreeDevice()
{
    FreeSystemDevice(pEnumerator, pDevice, IntPtr.Zero, IntPtr.Zero);
    pEnumerator = IntPtr.Zero;
    pDevice = IntPtr.Zero;
}

private float GetVolume()
{
    try
    {
        if (pEndpointVolume != IntPtr.Zero)
        {
            return GetSystemVolume(pEndpointVolume) * 100;
        }
    }
    catch (Exception)
    {
    }
    return 0;
}
private float GetMasterPeakValue()
{
    try
    {
        if (pMeterInfo != IntPtr.Zero)
        {
            return GetSystemMasterPeak(pMeterInfo) * 100;
        }
    }
    catch (Exception)
    {
    }
    return 0;
}
private bool GetVolumeMute()
{
    try
    {
        if (pEndpointVolume != IntPtr.Zero)
        {
            return GetSystemMute(pEndpointVolume);
        }
    }
    catch (Exception)
    {
    }
    return false;
}
public void SetVolume(float volume)
{
    try
    {
        volume = Math.Max(0, Math.Min(1, volume));
        if (pEndpointVolume != IntPtr.Zero)
        {
            SetSystemVolume(pEndpointVolume, volume);
        }
    }
    catch (Exception)
    {
    }
}
public void SetVolumeMute(bool mute)
{
    try
    {
        if (pEndpointVolume != IntPtr.Zero)
        {
            SetSystemMute(pEndpointVolume, mute);
        }
    }
    catch (Exception)
    {
    }
}