我一直在网上搜索从C#控制我的电脑音频的方法。我发现这个代码工作正常。
public static float GetMasterVolume()
{
// get the speakers (1st render + multimedia) device
IMMDeviceEnumerator deviceEnumerator = (IMMDeviceEnumerator)(new MMDeviceEnumerator());
IMMDevice speakers;
const int eRender = 0;
const int eMultimedia = 1;
deviceEnumerator.GetDefaultAudioEndpoint(eRender, eMultimedia, out speakers);
object o;
speakers.Activate(typeof(IAudioEndpointVolume).GUID, 0, IntPtr.Zero, out o);
IAudioEndpointVolume aepv = (IAudioEndpointVolume)o;
float volume = aepv.GetMasterVolumeLevelScalar();
Marshal.ReleaseComObject(aepv);
Marshal.ReleaseComObject(speakers);
Marshal.ReleaseComObject(deviceEnumerator);
return volume;
}
[ComImport]
[Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")]
private class MMDeviceEnumerator
{
}
[Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IAudioEndpointVolume
{
void _VtblGap1_6();
float GetMasterVolumeLevelScalar();
}
[Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IMMDeviceEnumerator
{
void _VtblGap1_1();
[PreserveSig]
int GetDefaultAudioEndpoint(int dataFlow, int role, out IMMDevice ppDevice);
}
[Guid("D666063F-1587-4E43-81F1-B948E807363F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IMMDevice
{
[PreserveSig]
int Activate([MarshalAs(UnmanagedType.LPStruct)] Guid iid, int dwClsCtx, IntPtr pActivationParams, [MarshalAs(UnmanagedType.IUnknown)] out object ppInterface);
}
那是getVolume函数。我认为必须采用类似的方式设置音量。我遇到过这种方法:
HRESULT SetMasterVolumeLevelScalar(
[in] float fLevel,
[in] LPCGUID pguidEventContext
);
但我无法理解第二个参数。任何帮助,将不胜感激。
我看到你已经解决了这个问题但想给其他好奇或需要帮助的人提供一个正式的答案。
当你调用SetMasterVolumeLevelScalar
时,你将体积百分比从0.0传递到1.0并传入一个GUID。你也可以传入Null;然而。传递GUID的原因是任何其他应用程序更改都可以检查更改并查看它是否是他们或其他应用程序。例如:
如果您注册OnNotify
进行音量更改,则每次音量更改时都会收到一个结构。结构中的第一个字段是GUID。如果你传入一个常量GUID来改变音量,那么这个结构将显示你自己的GUID;你可以比较它,忽略它或其他什么。如果结构传递的是NULL或不同的GUID,那么您知道另一个应用程序已经更改了卷,并且您可能希望在此时执行不同的操作。
希望这可以帮助 :)
定义你的界面......
[Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IAudioEndpointVolume
{
// ...
Int32 GetMasterVolumeLevelScalar(ref Single pfLevel);
Int32 SetMasterVolumeLevelScalar(Single fLevel, Guid pguidEventContext);
// ...
}
然后,在你的课堂上,例如:
public class EndpointVolume
{
private readonly Guid m_GuidEventContext;
private IAudioEndpointVolume m_AudioEndpoint;
public EndpointVolume()
{
m_GuidEventContext = Guid.NewGuid();
m_AudioEndpoint = ...
}
public Single MasterVolume
{
get
{
Single level = 0.0f;
Int32 res = m_AudioEndpoint.GetMasterVolumeLevelScalar(ref level);
if (retVal != 0)
throw new Exception("AudioEndpointVolume.GetMasterVolumeLevelScalar()");
return level;
}
set
{
Single level = value;
if (level < 0.0f)
level = 0.0f;
else if (level > 1.0f)
level = 0.0f;
Int32 res = m_AudioEndpoint.SetMasterVolumeLevelScalar(level, m_GuidEventContext);
if (res!= 0)
throw new Exception("AudioEndpointVolume.SetMasterVolumeLevelScalar()");
}
}
// ...
}
pguidEventContext
参数用于定义当前事件上下文,以便对主卷进行的更改将反映到所有其他客户端。来自official documentation:
IAudioEndpointVolumeCallback :: OnNotify方法的上下文值。此参数指向事件上下文GUID。如果SetMasterVolumeLevelScalar调用更改了端点的卷级别,则已注册IAudioEndpointVolumeCallback与该端点的所有客户端都将收到通知。在其OnNotify方法的实现中,客户端可以检查事件上下文GUID以发现它或其他客户端是否是卷更改事件的源。如果调用者为此参数提供NULL指针,则通知例程将接收上下文GUID值GUID_NULL。