7

背景:在 Windows Vista 及更高版本中,使用扩展的核心音频 API(由 Ray Molenkamp 和 Xavier Flix 编写)通过订阅 DefaultAudioEndpoint 的 OnVolumeNotification 并在音量发生变化时设置音量来强制音量级别。

问题:功能上是成功的,但是一旦注册了对 OnVolumeNotification 的订阅,CPU 往往会固定在 30-50%,具体取决于 CPU 的功率。在使用 Process Explorer 和 Process Monitor 进行大量挖掘后,发现 explorer.exe 和有时 svchost.exe 会被注册表读取调用消耗。我不确定哪个注册表项。我不相信我以有害的方式订阅此事件,因为我仔细管理订阅 - 它只被解雇一次。

强制卷的逻辑过程

  1. 取消订阅端点 OnVolumeNotification
  2. 设置端点体积标量属性(立即生效)
  3. 订阅端点 OnVolumeNotification

Core Audio API 中涉及的底层 win32 方法是RegisterControlChangeNotifyUnregisterControlChangeNotify。问题是否可能是由这些或事件订阅的实现引起的?

4

1 回答 1

0

而不是:

  1. 退订
  2. 改变音量/设置静音
  3. 重新订阅

我修改了我的逻辑,基本上使用属性中的逻辑和支持字段来管理何时更新。它并不完美,但它非常接近,它不会占用任何 CPU,并且它允许从完全支持 INPC 的滑块进行外部输入。

public EndpointVolumeEnforcer() {
  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();
    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;
  }
}
于 2012-10-11T19:16:52.163 回答