投稿者 魔界の仮面弁士  (社会人) 投稿日時 2023/9/21 10:42:56
現在のターゲット フレームワークは .NET 6 / .NET 7 / .NET 8(RC1) ですか?
それとも .NET Framework 4.7.2~4.8.1 ですか?

 ターゲットフレームワークが異なると、C# で使える文法が幾許か変わってきますので、
出来れば明示していただけると答えやすいです。


> 偶然ですが音楽のループ、音量調整が出来ました。
漠然と『偶然』という言葉で片付けられても判断しにくいです。
「プログラムは思った通りには動かない。書いた通りに動くのだ。」という格言があります。
1 文字違っただけで動作が変わることもありますからね。

どのように書いたのかを示して頂かないことには、
それが正しいコードなのか間違っているのかの添削もできません。
正しいコードになっているかどうかを自己判断できないのであれば、
『現象を再現可能な最低限のコード』を提示したうえで、
そのコードのどの部分について知りたいのかを具体的に示しましょう。


> mciSendString("setaudio my_sound volume to 100", null, 0, 0);
> mciSendString($"open \"{fileName}\" alias {aliasName}", "", 0, IntPtr.Zero);
> mciSendString($"play {aliasName}", "", 0, IntPtr.Zero);

これについても、末尾の引数(第4引数)が、最初の質問では int で、その後の投稿では IntPtr になっていますね。

引数定義は DllImport 宣言時に決定されるものですが、API の 本来の型(C++向け)は
HANDLE 型ですので、int ではなく IntPtr (あるいは nint)で宣言すべきです。
https://learn.microsoft.com/ja-jp/previous-versions//dd757161%28v=vs.85%29
https://pinvoke.net/default.aspx/winmm/mciSendString.html


> ここの 3-3.サウンド再生のプログラム にある以下のコードでは
偶然であれ何であれ、既に調整できたのですよね。
その時のコードと現状のコードで何が違っているのか、もう一度比較してみてください。

また、mciSendString の戻り値の値が何になっているかも確認しましょう。
この戻り値の値はエラーコードであり、0 であれば成功、失敗時は 0 以外になりますので、
0 以外が返されるようであれば、API の呼び方が間違っていることになります。

たとえば 263(=MCIERR_INVALID_DEVICE_NAME) なら、エイリアス名の指定ミス。
https://learn.microsoft.com/ja-jp/windows/win32/multimedia/mcierr-return-values
https://gist.github.com/KirillOsenkov/e9313c2044da26a756c4b56a7f31c428#file-win32constants-cs-L6583

なお、エラーコードを説明文字列に変換するために、 mciGetErrorString API を併用することもできます。


> どのように音量調整が出来るようになるのでしょうか?
問題になっているのは設定と取得のいずれですか?

$"setaudio {aliasName} volume to {factor}" //設定
$"status {aliasName} volume" //取得



取得系のコマンドの場合は、バッファの指定にも気を配りましょう。

(1) 第2引数(バッファ変数)に、十分なメモリを確保した変数を渡します。
 →先に紹介した VB のサンプルでは、最大 253 文字まで取得可能なバッファを String 型で
   用意していましたが、C# では string ではなく StringBuilder を使うべきです。

(2) 第3引数(バッファの長さ)には、第2引数で確保したメモリのサイズを渡します。
 → StringBuilder なら Capacity プロパティを渡すと良いでしょう。


> これだけは成功しませんでした。
少なくも一度は、ループも音量調整もできたのですよね?
それが、別プログラムに組み込んでみたときに成功しなかった、と。

期待動作しないのであれば、どこまでが動作していて、どこで失敗しているのかを追跡しましょう。
エラーになるのであれば、どの行が何というエラーになるのかを示しましょう。
文法エラーでコンパイルすらできないのか、それとも実行時に例外になってしまうのか。
API なら、戻り値の値をチェックしたり、呼び出し直後の Marshal.GetLastWin32Error() を確認するのも有用です。