确定主音频卷的更改为事件(音量更改侦听器)

时间:2014-12-25 21:41:16

标签: c# wpf audio

我希望将Windows的主音量绑定到程序中的滑块。所以我搜索并找到了一些方法来GETSET主卷+一些像这样的库:


修改

现在我有以下课程。我创建了它的一个实例,并使用propertychange事件通过Trace.WriteLine显示音量。但是当我更改窗口音量时会导致无错误的错误!

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);
 }

运行时错误:

...................................... enter image description here

“输出”面板显示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 进入下一步时,它不会在程序中显示正常错误!它会导致波纹管错误窗口和应用程序强制关闭!< / p>

...................................... enter image description here

Access violation

2 个答案:

答案 0 :(得分:6)

您可以使用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)

答案 1 :(得分:0)

您的代码是否更新了控件以响应事件,例如轨迹栏或静音按钮?如果是这样,您可能需要使用线程安全的方法。控件只能由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