控制音量混合器
Posted
技术标签:
【中文标题】控制音量混合器【英文标题】:Controlling Volume Mixer 【发布时间】:2018-01-06 13:17:32 【问题描述】:我想控制其他应用程序的音量(firefox)。
我可以用Volume Mixer
做到这一点
Volume Mixer
的库是什么?
【问题讨论】:
一点谷歌回馈这个:dreamincode.net/forums/topic/… 这是由 WASAPI,Windows 音频会话 API 在 Windows 中实现的。你需要一个包装器,通过搜索“c# wasapi”找到谷歌点击 @Simon Mourier 我认为这段代码控制系统音量。我只想控制 firefox 音量。 我一直在处理CoreAudio library for .NET。该库是免费和开源的。商业版MixerProNET Library 上提供了更强大的实现 【参考方案1】:这是一个示例 C# 控制台应用程序。它基于Windows Core Audio Library。它仅适用于 Windows 7 及更高版本。
using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
namespace SetAppVolumne
class Program
static void Main(string[] args)
const string app = "Mozilla Firefox";
foreach (string name in EnumerateApplications())
Console.WriteLine("name:" + name);
if (name == app)
// display mute state & volume level (% of master)
Console.WriteLine("Mute:" + GetApplicationMute(app));
Console.WriteLine("Volume:" + GetApplicationVolume(app));
// mute the application
SetApplicationMute(app, true);
// set the volume to half of master volume (50%)
SetApplicationVolume(app, 50);
public static float? GetApplicationVolume(string name)
ISimpleAudioVolume volume = GetVolumeObject(name);
if (volume == null)
return null;
float level;
volume.GetMasterVolume(out level);
return level * 100;
public static bool? GetApplicationMute(string name)
ISimpleAudioVolume volume = GetVolumeObject(name);
if (volume == null)
return null;
bool mute;
volume.GetMute(out mute);
return mute;
public static void SetApplicationVolume(string name, float level)
ISimpleAudioVolume volume = GetVolumeObject(name);
if (volume == null)
return;
Guid guid = Guid.Empty;
volume.SetMasterVolume(level / 100, ref guid);
public static void SetApplicationMute(string name, bool mute)
ISimpleAudioVolume volume = GetVolumeObject(name);
if (volume == null)
return;
Guid guid = Guid.Empty;
volume.SetMute(mute, ref guid);
public static IEnumerable<string> EnumerateApplications()
// get the speakers (1st render + multimedia) device
IMMDeviceEnumerator deviceEnumerator = (IMMDeviceEnumerator)(new MMDeviceEnumerator());
IMMDevice speakers;
deviceEnumerator.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia, out speakers);
// activate the session manager. we need the enumerator
Guid IID_IAudiosessionManager2 = typeof(IAudioSessionManager2).GUID;
object o;
speakers.Activate(ref IID_IAudioSessionManager2, 0, IntPtr.Zero, out o);
IAudioSessionManager2 mgr = (IAudioSessionManager2)o;
// enumerate sessions for on this device
IAudioSessionEnumerator sessionEnumerator;
mgr.GetSessionEnumerator(out sessionEnumerator);
int count;
sessionEnumerator.GetCount(out count);
for (int i = 0; i < count; i++)
IAudioSessionControl ctl;
sessionEnumerator.GetSession(i, out ctl);
string dn;
ctl.GetDisplayName(out dn);
yield return dn;
Marshal.ReleaseComObject(ctl);
Marshal.ReleaseComObject(sessionEnumerator);
Marshal.ReleaseComObject(mgr);
Marshal.ReleaseComObject(speakers);
Marshal.ReleaseComObject(deviceEnumerator);
private static ISimpleAudioVolume GetVolumeObject(string name)
// get the speakers (1st render + multimedia) device
IMMDeviceEnumerator deviceEnumerator = (IMMDeviceEnumerator)(new MMDeviceEnumerator());
IMMDevice speakers;
deviceEnumerator.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia, out speakers);
// activate the session manager. we need the enumerator
Guid IID_IAudioSessionManager2 = typeof(IAudioSessionManager2).GUID;
object o;
speakers.Activate(ref IID_IAudioSessionManager2, 0, IntPtr.Zero, out o);
IAudioSessionManager2 mgr = (IAudioSessionManager2)o;
// enumerate sessions for on this device
IAudioSessionEnumerator sessionEnumerator;
mgr.GetSessionEnumerator(out sessionEnumerator);
int count;
sessionEnumerator.GetCount(out count);
// search for an audio session with the required name
// NOTE: we could also use the process id instead of the app name (with IAudioSessionControl2)
ISimpleAudioVolume volumeControl = null;
for (int i = 0; i < count; i++)
IAudioSessionControl ctl;
sessionEnumerator.GetSession(i, out ctl);
string dn;
ctl.GetDisplayName(out dn);
if (string.Compare(name, dn, StringComparison.OrdinalIgnoreCase) == 0)
volumeControl = ctl as ISimpleAudioVolume;
break;
Marshal.ReleaseComObject(ctl);
Marshal.ReleaseComObject(sessionEnumerator);
Marshal.ReleaseComObject(mgr);
Marshal.ReleaseComObject(speakers);
Marshal.ReleaseComObject(deviceEnumerator);
return volumeControl;
[ComImport]
[Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")]
internal class MMDeviceEnumerator
internal enum EDataFlow
eRender,
eCapture,
eAll,
EDataFlow_enum_count
internal enum ERole
eConsole,
eMultimedia,
eCommunications,
ERole_enum_count
[Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IMMDeviceEnumerator
int NotImpl1();
[PreserveSig]
int GetDefaultAudioEndpoint(EDataFlow dataFlow, ERole role, out IMMDevice ppDevice);
// the rest is not implemented
[Guid("D666063F-1587-4E43-81F1-B948E807363F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IMMDevice
[PreserveSig]
int Activate(ref Guid iid, int dwClsCtx, IntPtr pActivationParams, [MarshalAs(UnmanagedType.IUnknown)] out object ppInterface);
// the rest is not implemented
[Guid("77AA99A0-1BD6-484F-8BC7-2C654C9A9B6F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IAudioSessionManager2
int NotImpl1();
int NotImpl2();
[PreserveSig]
int GetSessionEnumerator(out IAudioSessionEnumerator SessionEnum);
// the rest is not implemented
[Guid("E2F5BB11-0570-40CA-ACDD-3AA01277DEE8"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IAudioSessionEnumerator
[PreserveSig]
int GetCount(out int SessionCount);
[PreserveSig]
int GetSession(int SessionCount, out IAudioSessionControl Session);
[Guid("F4B1A599-7266-4319-A8CA-E70ACB11E8CD"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IAudioSessionControl
int NotImpl1();
[PreserveSig]
int GetDisplayName([MarshalAs(UnmanagedType.LPWStr)] out string pRetVal);
// the rest is not implemented
[Guid("87CE5498-68D6-44E5-9215-6DA47EF883D8"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface ISimpleAudioVolume
[PreserveSig]
int SetMasterVolume(float fLevel, ref Guid EventContext);
[PreserveSig]
int GetMasterVolume(out float pfLevel);
[PreserveSig]
int SetMute(bool bMute, ref Guid EventContext);
[PreserveSig]
int GetMute(out bool pbMute);
注意:我没有完全定义接口,只定义了代码工作所需要的。
【讨论】:
也许您可以尝试使用“Spotify”而不是“Mozilla Firefox” 已经尝试过了,但是音量混合器没有返回DisplayName
for Spotify,它只适用于 Firefox 和某种 .dll
在 Windows 7 上,有一个 IAudioSessionControl2 接口可以获取进程 ID。从那里您可以确定它是否是 spotify。如果您不知道该怎么做,请再问一个问题。
@bliss - 这是另一个问题,所以,就像我说的,你应该问另一个问题
@Simon Mourier - 我在 EnumerateApplications() 函数中遇到了这个错误 - 这是屏幕截图:i.imgur.com/YzbgOKH.png你能帮忙吗?【参考方案2】:
我知道这为时已晚,但我最近需要这个,我尝试了 Simon 的答案,但无法让它发挥作用,尝试了 ElektroStudios 的评论和Simon's other answer 仍然没有,我不知道我做错了什么,但是我放弃了。
我后来找到了this asnwer,并使用CSCore让它工作
private static void Main(string[] args)
using (var sessionManager = GetDefaultAudioSessionManager2(DataFlow.Render))
using (var sessionEnumerator = sessionManager.GetSessionEnumerator())
foreach (var session in sessionEnumerator)
using (var simpleVolume = session.QueryInterface<SimpleAudioVolume>())
using (var sessionControl = session.QueryInterface<AudioSessionControl2>())
if (sessionControl.ProcessID == 2436)
simpleVolume.MasterVolume = 0.5f;
Console.ReadKey();
private static AudioSessionManager2 GetDefaultAudioSessionManager2(DataFlow dataFlow)
using (var enumerator = new MMDeviceEnumerator())
using (var device = enumerator.GetDefaultAudioEndpoint(dataFlow, Role.Multimedia))
Debug.WriteLine("DefaultDevice: " + device.FriendlyName);
var sessionManager = AudioSessionManager2.FromMMDevice(device);
return sessionManager;
【讨论】:
以上是关于控制音量混合器的主要内容,如果未能解决你的问题,请参考以下文章