デバイスの音量を変更したい

投稿者:はにわ 投稿日:2018/09/08(Sat) 23:41:20 No.2227

こんにちは。はにわです。
いつもプロデルを使わせていただいております。

題名の通り、デバイスの音量の変更および取得をしたいのですが、できますでしょうか。リファレンス等を見る限り、見当たらなかったので質問をさせていただきます。
WMPやmidiの音量設定ではなく、デバイスごと音量の変更をしたいです。

できなければ、できないと一言で結構ですので、どなたか手順を教えていただくか、参考となる部分のリンクを貼っていただけると嬉しいです。
よろしくお願いします。

参考までに…

投稿者:アーク <info_nds-labo あっとまーくexcite.co.jp> 投稿日:2018/09/11(Tue) 18:29:29 No.2229

はにわさん、はじめまして。アークです。

本当は私ではなく詳しい方からコメントが付くと良かったのですが、
私も以前、調べた事が有ったので参考までに…。

Windows 10になってアプリ毎の音量調整が可能になった代わりに、
マスタ音量の変更が面倒になったようです。
今はMMDeviceAPIというのを使って実現するようです。
MMDeviceAPIは一応COMの形態を取っているようですが、
CreateObject()等で簡単に使えるような物では無いようです。

ネットを探してC#からMMDeviceAPIを使うサンプルを発見しましたが、
C#で遣っても結構大変です。
https://qiita.com/katabamisan/items/bfc17955093fef29a6a6

これをプロデルのコードに直せるとは思えないので、
そのまま使ってしまうのが良さそうです。

Re: 参考までに…

投稿者:ゆうと 投稿日:2018/09/20(Thu) 02:46:43 No.2235

こんばんは ゆうとです。

Vista以降、音量ミキサーの仕組みが複雑になりましたのでCOMを使うとアクセスできるのですが、一筋縄では変えられないと思います。

アプリケーションレベルのボリュームだと比較的短いコードで変更できるみたいです。
https://stackoverflow.com/questions/14306048/controlling-volume-mixer

全体のボリュームはIAudioEndpointVolumeがキーワードでしょうか。
GUIDが分かればプロデルでもアクセスできそうですが、次のプログラムは重要な所の断片なので、COMやC#の知識で調べないと難しそうです。
http://wiki.onakasuita.org/pukiwiki/?IAudioEndpointVolume

ゆうとさん

投稿者:アーク 投稿日:2018/09/20(Thu) 08:01:12 No.2236

おはようございます。アークです。

〉GUIDが分かればプロデルでもアクセスできそうですが、
おぉ、そうですか…。
分かりますよ。
下記はC#でクラスに纏められたコードです。
これをそのままコンパイルして使うという方法も有りますが、
残念ながら色々と付け足さないとコンパイルできません。
…なので私にはできません。
改めて下記ソースの大元を調査したところ「stackoverflow」のようです。
こちらは「Creative Commons Attribution Share-Alike」というライセンスのようですので、
同サイトからの引用である事を記します。
https://stackoverflow.com/questions/255419/how-can-i-mute-unmute-my-sound-from-powershell

--------------------------------------------------
using System.Runtime.InteropServices;
[Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IAudioEndpointVolume {
// f(), g(), ... are unused COM method slots. Define these if you care
int f(); int g(); int h(); int i();
int SetMasterVolumeLevelScalar(float fLevel, System.Guid pguidEventContext);
int j();
int GetMasterVolumeLevelScalar(out float pfLevel);
int k(); int l(); int m(); int n();
int SetMute([MarshalAs(UnmanagedType.Bool)] bool bMute, System.Guid pguidEventContext);
int GetMute(out bool pbMute);
}
[Guid("D666063F-1587-4E43-81F1-B948E807363F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IMMDevice {
int Activate(ref System.Guid id, int clsCtx, int activationParams, out IAudioEndpointVolume aev);
}
[Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IMMDeviceEnumerator {
int f(); // Unused
int GetDefaultAudioEndpoint(int dataFlow, int role, out IMMDevice endpoint);
}
[ComImport, Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")] class MMDeviceEnumeratorComObject { }
public class Audio {
static IAudioEndpointVolume Vol() {
var enumerator = new MMDeviceEnumeratorComObject() as IMMDeviceEnumerator;
IMMDevice dev = null;
Marshal.ThrowExceptionForHR(enumerator.GetDefaultAudioEndpoint(/*eRender*/ 0, /*eMultimedia*/ 1, out dev));
IAudioEndpointVolume epv = null;
var epvid = typeof(IAudioEndpointVolume).GUID;
Marshal.ThrowExceptionForHR(dev.Activate(ref epvid, /*CLSCTX_ALL*/ 23, 0, out epv));
return epv;
}
public static float Volume {
get {float v = -1; Marshal.ThrowExceptionForHR(Vol().GetMasterVolumeLevelScalar(out v)); return v;}
set {Marshal.ThrowExceptionForHR(Vol().SetMasterVolumeLevelScalar(value, System.Guid.Empty));}
}
public static bool Mute {
get { bool mute; Marshal.ThrowExceptionForHR(Vol().GetMute(out mute)); return mute; }
set { Marshal.ThrowExceptionForHR(Vol().SetMute(value, System.Guid.Empty)); }
}
}
--------------------------------------------------

Re: デバイスの音量を変更したい

投稿者:ゆうと 投稿日:2018/09/20(Thu) 02:38:07 No.2234

こんばんは ゆうとです。

個人的な用途で使うだけならば、VolumeUp/VolumeDownキーをAPI関数で押させることで、音量を変更したりミュートにできます。
https://rdr.utopiat.net/cgi/progbbs/forump.php?mode=viewcode&id=73&rtn=63

参考にしてください。

はにわさん

投稿者:アーク 投稿日:2018/09/20(Thu) 08:18:01 No.2237

おはようございます。アークです。

No.2236で書いたようにC#のソースは有るのですが、
C#はコマンドライン コンパイラを数回使った程度なので、
私にはアプリケーションとして完成させることができません。

私自身が以前必要になった時にはこれをそのまま使いました。
PowershellにはC#のソースをアセンブリ参照して使う便利な機能が有ります。
これを利用して下記の様なPowershellスクリプトを書き,
「setVolume.ps1」として保存します。

--------------------------------------------------------
Add-Type -TypeDefinition @'

using System.Runtime.InteropServices;
[Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IAudioEndpointVolume {
// f(), g(), ... are unused COM method slots. Define these if you care
int f(); int g(); int h(); int i();
int SetMasterVolumeLevelScalar(float fLevel, System.Guid pguidEventContext);
int j();
int GetMasterVolumeLevelScalar(out float pfLevel);
int k(); int l(); int m(); int n();
int SetMute([MarshalAs(UnmanagedType.Bool)] bool bMute, System.Guid pguidEventContext);
int GetMute(out bool pbMute);
}
[Guid("D666063F-1587-4E43-81F1-B948E807363F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IMMDevice {
int Activate(ref System.Guid id, int clsCtx, int activationParams, out IAudioEndpointVolume aev);
}
[Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IMMDeviceEnumerator {
int f(); // Unused
int GetDefaultAudioEndpoint(int dataFlow, int role, out IMMDevice endpoint);
}
[ComImport, Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")] class MMDeviceEnumeratorComObject { }
public class Audio {
static IAudioEndpointVolume Vol() {
var enumerator = new MMDeviceEnumeratorComObject() as IMMDeviceEnumerator;
IMMDevice dev = null;
Marshal.ThrowExceptionForHR(enumerator.GetDefaultAudioEndpoint(/*eRender*/ 0, /*eMultimedia*/ 1, out dev));
IAudioEndpointVolume epv = null;
var epvid = typeof(IAudioEndpointVolume).GUID;
Marshal.ThrowExceptionForHR(dev.Activate(ref epvid, /*CLSCTX_ALL*/ 23, 0, out epv));
return epv;
}
public static float Volume {
get {float v = -1; Marshal.ThrowExceptionForHR(Vol().GetMasterVolumeLevelScalar(out v)); return v;}
set {Marshal.ThrowExceptionForHR(Vol().SetMasterVolumeLevelScalar(value, System.Guid.Empty));}
}
public static bool Mute {
get { bool mute; Marshal.ThrowExceptionForHR(Vol().GetMute(out mute)); return mute; }
set { Marshal.ThrowExceptionForHR(Vol().SetMute(value, System.Guid.Empty)); }
}
}

'@
[audio]::Volume = $Args[0]
[audio]::Mute = $Args[1]
--------------------------------------------------------

尚、上記コードの最下行の二行を除いては下記「stackoverflow」サイトからの引用です。
同サイトのコードには「Creative Commons Attribution Share-Alike」ライセンスが適用されます。
https://stackoverflow.com/questions/255419/how-can-i-mute-unmute-my-sound-from-powershell

次に下記のサンプルプログラムをプロデルで作り「音量テスト.rdr」として保存します。

--------------------------------------------------------
メイン画面を表示する
待機する

メイン画面とは
  ウィンドウを継承する
  はじめの手順
    初期化する
    //貼り付けた部品に対する操作をここに書きます
    ミュートは、0
  終わり
  初期化する手順
  //自動生成された手順です。ここにプログラムを書き加えても消える場合があります
  この内部領域大きさを{439,130}に変える
  この内容を「メイン画面」に変える
  ボタン5というボタンを作る
    その位置と大きさを{292,80,65,27}に変える
    その内容を「閉じる」に変える
    その移動順を7に変える
  ボタン4というボタンを作る
    その位置と大きさを{209,80,64,28}に変える
    その内容を「ミュート」に変える
    その移動順を6に変える
  ボタン3というボタンを作る
    その位置と大きさを{128,80,66,28}に変える
    その内容を「ミキサー」に変える
    その移動順を5に変える
  ボタン2というボタンを作る
    その位置と大きさを{41,80,72,28}に変える
    その内容を「サウンド」に変える
    その移動順を4に変える
  ボタン1というボタンを作る
    その位置と大きさを{321,17,66,31}に変える
    その内容を「音量設定」に変える
    その移動順を2に変える
  スライダ1というスライダを作る
  スライダ1を初期化開始する
    その位置と大きさを{72,17,243,45}に変える
    その目盛り間隔を5に変える
    その最大値を100に変える
    その移動順を1に変える
  スライダ1を初期化終了する
  ラベル1というラベルを作る
    その位置と大きさを{17,17,49,33}に変える
    そのフォントを「MS UI Gothic,24」に変える
    その自動調整を×に変える
    その枠を「線」に変える
    その文字配置を「右」に変える
    その移動順を3に変える
終わり

  開いた時の手順
  終わり

  ボタン1がクリックされた時の手順
    マスタボリュームを変更する
  終わり

  ボタン2がクリックされた時の手順
    サウンド項目を表示する
  終わり

  ボタン3がクリックされた時の手順
    ミキサーを表示する
  終わり

  ボタン4がクリックされた時の手順
    もしミュートが0なら
      ミュートを1に変える
      ラベル1の有効を×に変える
    そうでないなら
      ミュートを0に変える
      ラベル1の有効を○に変える
    もし終わり
  終わり

  ボタン5がクリックされた時の手順
    終了する
  終わり

  スライダ1がスライドした時の手順
    ラベル1の内容を[スライダ1の値]に変える
  終わり

  マスタボリュームを変更する時の手順
    音量は、(スライダ1の値を100で割ったもの)
    「@PowerShell.exe ".\setVolume.ps1" [音量] [ミュート]」をコマンド実行する
  終わり

  サウンド項目を表示する時の手順
    メイン画面の最前面を×に変える
    「control /name Microsoft.Sound」をコマンド実行する
  終わり

  ミキサーを表示する時の手順
    メイン画面の最前面を×に変える
    「[システムフォルダ]SndVol.exe」を起動する
  終わり

終わり
--------------------------------------------------------

プロデルだけで解決している訳では無いの参考にならないかも知れませんが、
一応、はにわさんの遣りたい事はできるようになります。

プラグインをつくってみました

投稿者: 投稿日:2018/09/20(Thu) 13:16:52 No.2239

 こんにちは、お世話になります。

 アークさんが書かれていたC#のソースコードを参考に、プラグインにしてみました。
 本当はWindowsXPでもマスターボリュームの取得等ができるようにしたかったのですが、C#でその辺を扱う資料が見つからなかったので、とりあえず、現状ではWindowsVista以降専用です。
 もし、何か方法もしくは参考となるサイト等をご存知でしたら、お教えいただけると幸いです。

 さて、少し前置きが長くなりましたが、プラグインは下記ページに置いていますので、よければ使ってみてください。

https://riku22.net/soft/rdr_plugin.php

 なお、プラグインの説明への直リンクはこちらです。

https://riku22.net/soft/info.php/rdr_mv

 詳しいことは、同梱している説明書やサンプルをごらんいただければと思います。

 以上、参考になれば幸いです。

Re: プラグインをつくってみました

投稿者:アーク 投稿日:2018/09/20(Thu) 21:16:55 No.2240

陸さん、こんばんは。アークです。

陸さんはC#も遣られるのですね。
プラグインですか…。
プロデルにもう少し慣れてきたら遣ってみたいとは思いますが…。

P.S. ゆうとさんのアプローチも見てみたいですね。

少し改良してみました

投稿者:アーク 投稿日:2018/09/20(Thu) 21:26:26 No.2241

前回のサンプルを少し改良してみました。

前回のPowershellプログラムの最後の2行を下記と差し替えます。

----------------------------------------------------
if ($args.Length -eq 0) {
  $a = [audio]::Volume;
  $b = [audio]::Mute;
  if ($b -eq $true) {
    $c = "m";
  } else {
    $c = "n";
  }
  echo $a+$c;
} else {
  [audio]::Volume = $Args[0];
  [audio]::Mute = $Args[1];
}
----------------------------------------------------

プロデルの方は全面的に書き換えました。

----------------------------------------------------
メイン画面を表示する
待機する

メイン画面とは
  ウィンドウを継承する
  はじめの手順
    初期化する
    //貼り付けた部品に対する操作をここに書きます
    ミュートは、0
  終わり
  初期化する手順
  //自動生成された手順です。ここにプログラムを書き加えても消える場合があります
  この内部領域大きさを{332,130}に変える
  この内容を「メイン画面」に変える
  ボタン5というボタンを作る
    その位置と大きさを{250,80,65,27}に変える
    その内容を「閉じる」に変える
    その移動順を7に変える
  ボタン4というボタンを作る
    その位置と大きさを{167,80,64,28}に変える
    その内容を「ミュート」に変える
    その移動順を6に変える
  ボタン3というボタンを作る
    その位置と大きさを{95,80,66,28}に変える
    その内容を「ミキサー」に変える
    その移動順を5に変える
  ボタン2というボタンを作る
    その位置と大きさを{17,80,72,28}に変える
    その内容を「サウンド」に変える
    その移動順を4に変える
  スライダ1というスライダを作る
  スライダ1を初期化開始する
    その位置と大きさを{72,17,243,45}に変える
    その目盛り間隔を5に変える
    その最大値を100に変える
    その移動順を1に変える
  スライダ1を初期化終了する
  ラベル1というラベルを作る
    その位置と大きさを{17,17,49,33}に変える
    そのフォントを「MS UI Gothic,24」に変える
    その自動調整を×に変える
    その枠を「線」に変える
    その文字配置を「右」に変える
    その移動順を3に変える
終わり

  開いた時の手順
    結果は、「@PowerShell.exe ".\setVolume.ps1"」をコマンド実行したもの
    配列は、結果を「+」で区切ったもの
    ラベル1の内容を([配列(1)]*100)に変える
    スライダ1の値は、(ラベル1の内容)の整数
    もし配列(2)が「m[改行]」なら
      ラベル1の有効を×に変える
    もし終わり
  終わり

  ボタン2がクリックされた時の手順
    サウンド項目を表示する
  終わり

  ボタン3がクリックされた時の手順
    ミキサーを表示する
  終わり

  ボタン4がクリックされた時の手順
    もしラベル1の有効が○なら
      ミュートを1に変える
      音量は、-1
      ラベル1の有効を×に変える
    そうでないなら
      ミュートを0に変える
      音量は、(スライダ1の値を100で割ったもの)
      ラベル1の有効を○に変える
    もし終わり
    「@PowerShell.exe ".\setVolume.ps1" [音量] [ミュート]」をコマンド実行する
  終わり

  ボタン5がクリックされた時の手順
    終了する
  終わり

  スライダ1がスライドした時の手順
    ラベル1の内容を[スライダ1の値]に変える
  終わり

  サウンド項目を表示する時の手順
    メイン画面の最前面を×に変える
    「control /name Microsoft.Sound」をコマンド実行する
  終わり

  ミキサーを表示する時の手順
    メイン画面の最前面を×に変える
    「[システムフォルダ]SndVol.exe」を起動する
  終わり
  
  スライダ1のマウスのボタンが離された時の手順
    音量は、(スライダ1の値を100で割ったもの)
    「@PowerShell.exe ".\setVolume.ps1" [音量] [ミュート]」をコマンド実行する
  終わり
終わり
----------------------------------------------------

これで音量もミュート共に取得と設定をリアルタイムに行えます。

▲ページの先頭へ

- WebForum -