将主音频音量的变化确定为事件(音量变化监听器)
Posted
技术标签:
【中文标题】将主音频音量的变化确定为事件(音量变化监听器)【英文标题】:Determine changes of master audio volume as an event (volume change listener) 【发布时间】:2014-12-25 21:41:15 【问题描述】:我想将窗口的主音量绑定到我程序中的滑块。所以我搜索并找到了一些方法来GET
或SET
主卷+一些像这样的库:
NAudio
在某些地方我看到一个带有 LOOP 的代码来获取音量值:loop
有些地方我看到一个带有 TIMER 的代码来获取音量值... 我还看到了一些用于确定音量的示例,但在测试其中一个之后,我在 Windows 8 运行时看到了一些错误:C# – Adjust master volume in Vista and Windows 7编辑:
现在我有以下课程。我创建它的一个实例并使用propertchange 事件通过 Trace.WriteLine 显示音量。但是当我更改 Windows 音量时,它会导致一个未处理的错误!
public class AudioEndpointVolumeEnforcer : INotifyPropertyChanged
private MMDeviceEnumerator mmDeviceEnumerator;
private MMDevice mmDevice;
private AudioEndpointVolume audioEndpointVolume;
private bool _deviceIsMuted;
private int _desiredVolume;
private int _volumePercent;
public AudioEndpointVolumeEnforcer()
try
mmDeviceEnumerator = new MMDeviceEnumerator();
mmDevice = mmDeviceEnumerator.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia);
audioEndpointVolume = mmDevice.AudioEndpointVolume;
audioEndpointVolume.OnVolumeNotification += data =>
VolumePercent = Convert.ToInt16(data.MasterVolume*100);
_deviceIsMuted = data.Muted;
;
DesiredVolume = 65;
catch (Exception ex)
// Logging logic here
public int DesiredVolume
get return _desiredVolume;
private set
if (_desiredVolume == value) return;
_desiredVolume = value;
//NotifyOfPropertyChange();
OnPropertyChanged("DesiredVolume");
Enforce(_desiredVolume);
public int VolumePercent
get return _volumePercent;
private set
if (_volumePercent == value) return;
_volumePercent = value;
if (_volumePercent != _desiredVolume)
_volumePercent = _desiredVolume;
Enforce(_volumePercent);
public void Enforce(int pct, bool mute = false)
var adjusted = Convert.ToInt16(audioEndpointVolume.MasterVolumeLevelScalar*100);
if (adjusted != DesiredVolume)
audioEndpointVolume.MasterVolumeLevelScalar = pct/100f;
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged(string propertyName)
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
使用类:
// Inside my window cunstractor >>
audioVolume = new AudioEndpointVolumeEnforcer();
audioVolume.PropertyChanged += MasterAudioVolumeChanged;
private void MasterAudioVolumeChanged(object obj, PropertyChangedEventArgs eventArgs)
Trace.WriteLine(eventArgs.PropertyName+" - "+audioVolume.DesiredVolume);
运行时错误:
.......................
输出面板显示Access violation
错误:
The program '[18488] Audio.exe' has exited with code -1073741819 (0xc0000005) 'Access violation'
编辑
我通过断点和跟踪测试了上面的代码。上述错误有时发生在以下部分:
audioEndpointVolume.OnVolumeNotification += data =>
VolumePercent = Convert.ToInt16(data.MasterVolume*100);
_deviceIsMuted = data.Muted;
;
例如有时它发生在这一行:
_deviceIsMuted = data.Muted;
但是当我通过F11进入下一步时程序内部没有显示正常错误!它导致波纹管错误窗口和应用程序强制关闭!
.......................
Access violation
【问题讨论】:
无论哪种方式看起来都有希望。你尝试过其中任何一个吗?我想你已经回答了你自己的问题,因为你已经找到了很多可能的解决方案。 @kennyzx,我不知道.NET 中是否有基于“事件”的安全方法,或者我必须通过“计时器”来实现它......! @kennyzx,我添加了我选择的方式的代码。你怎么看它的错误? 你应该在你的方法的第一行设置一个断点,并逐步找出导致访问冲突的行。 @dymanoid,我更新了我的问题,添加了一些关于通过断点跟踪程序的信息......!现在你怎么看?! 【参考方案1】:您可以这样使用 NAudio 库:
using NAudio;
using NAudio.CoreAudioApi;
private static MMDeviceEnumerator enumer = new MMDeviceEnumerator();
private MMDevice dev = enumer.GetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia);
public void Form1_Load(object sender, EventArgs e)
dev.AudioEndpointVolume.OnVolumeNotification += AudioEndpointVolume_OnVolumeNotification;
void AudioEndpointVolume_OnVolumeNotification(AudioVolumeNotificationData data)
// This shows data.MasterVolume, you can do whatever you want here
MessageBox.Show(data.MasterVolume.ToString());
此示例使用 WinForms 项目,但您也可以在其他地方创建事件。
NAudio 可以作为 NuGet 包安装,也可以从 https://naudio.codeplex.com/ 安装
音量范围从 0.0f 到 1.0f,要得到 0-100 只需这样做:
(int)(data.MasterVolume * 100f)
【讨论】:
【参考方案2】:您的代码是否会更新控件以响应事件,例如轨迹栏或静音按钮?如果是这样,您可能需要使用线程安全的方法。控件只能由 UI 线程更新。 Me.InvokeRequired 检查是否是 UI 线程想要进行更新。如果不是,则返回 True。 Me.Invoke 然后使用委托来处理两个线程之间的通信。如果不使用 Me.Invoke,会出现访问冲突。
Delegate Sub UpdateCallback(Volume As Integer, Muted As Boolean)
Public Overloads Sub Update(Volume As Integer, Muted As Boolean)
If tbVolume.InvokeRequired Then
Dim d As New UpdateCallback(AddressOf Update)
Me.Invoke(d, Volume, Muted)
Else
tbVolume.Value = Volume
_Mute = Muted
btnMuteUnmute.BackgroundImage = DirectCast(If(_Mute, _
My.Resources.mute, My.Resources.Unmute), Icon).ToBitmap
End If
End Sub
【讨论】:
以上是关于将主音频音量的变化确定为事件(音量变化监听器)的主要内容,如果未能解决你的问题,请参考以下文章