7

背景: Windows Vista 以降では、拡張されたコア オーディオ API (Ray Molenkamp と Xavier Flix による) を使用して、DefaultAudioEndpoint の OnVolumeNotification をサブスクライブし、音量が変化したときに音量を設定することで、音量レベルを適用します。

問題:機能的には成功していますが、OnVolumeNotification へのサブスクリプションが登録されるとすぐに、CPU のパワーに応じて CPU が 30 ~ 50% に固定される傾向があります。Process Explorer と Process Monitor を詳しく調べた結果、explorer.exe と、場合によっては svchost.exe がレジストリ読み取り呼び出しによって消費されることが明らかになりました。どのレジストリ キーが不明です。サブスクリプションは慎重に管理しているため、有害な方法でこのイベントにサブスクライブしているとは思いません。1 回だけ配信されています。

ボリュームを強制する論理プロセス

  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 に答える