Определить изменения громкости основного аудио в качестве события (прослушиватель громкости)

Я хочу связать основной объем звука окон с ползунком в моей программе. Поэтому я обыскал и нашел некоторые способы GET или SET master volume + некоторые библиотеки, подобные этим:

РЕДАКТИРОВАТЬ:

Теперь у меня есть следующий класс. Я создаю экземпляр этого файла и использую событие propertchange, чтобы показать объем 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);
 }

Ошибка выполнения:

......................................

На панели "Выход" отображается ошибка 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

2 ответа

Вы можете использовать библиотеку 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)


Ваш код обновляет элемент управления в ответ на событие, например, трек-бар или кнопку отключения звука? Если это так, вам может потребоваться использовать поточно-безопасный подход. Элементы управления могут обновляться только через поток пользовательского интерфейса. Me.InvokeRequired проверяет, хочет ли он поток пользовательского интерфейса, который хочет выполнить обновление. Если нет, он возвращает 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

licensed under cc by-sa 3.0 with attribution.