1. PowerDVD Ultra 18等で『DLNA TV 二か国語放送主福切り替え』がブロークンなのを対策してみる
これはQiitaに投稿した記事https://qiita.com/docnao/items/d1572cb5f1907e4bddbdの改訂版です。
サブタイトルのような支障(仕様ともいふ)をなんとかしたいわけです。最低限左chの日本語音声と右chの英語音声が混ざっているのが不快ですが、PowerDVD Ultra側では切り替えができません。Windows 11の場合ならば、下記で、
左チャンネルを0にして右を100とか、逆に右チャンネルを0にして左チャンネルを100とかに変更すれば一応右左(例えば英語と日本語)が同時に聞こえるというのは防げます。もっとも定位はセンターからズレますし、音量レベルも下がるのが不都合ですけど、これを手動で行うのはあまりにも面倒なので、プログラムで実現したいわけです。
#include <windows.h>
#include <mmdeviceapi.h>
#include <endpointvolume.h>
#include <stdio.h>
int main(int argc, char** argv) {
HRESULT hr;
IMMDeviceEnumerator* pEnum = NULL;
IMMDevice* pEndpoint = NULL;
IAudioEndpointVolume* pAudioEndVol = NULL;
hr = CoInitializeEx(0, COINIT_MULTITHREADED);// Coおまじない
// MMDevice インターフェースを取得
hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, IID_PPV_ARGS(&pEnum));
if (FAILED(hr)) {
CoUninitialize();
return 1;
}
// defaultのオーディオエンドポイントを取得
hr = pEnum->GetDefaultAudioEndpoint(eRender, eConsole, &pEndpoint);
if (FAILED(hr)) {
if (pEnum)
pEnum->Release();
CoUninitialize();
return 2;
}
// ボリュームオブジェクトを作成
hr = pEndpoint->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_ALL, NULL, (void**)&pAudioEndVol);
if (FAILED(hr)) {
if (pEndpoint)
pEndpoint->Release();
if (pEnum)
pEnum->Release();
CoUninitialize();
return 3;
}
// 左右のチャンネルの音量をセット
char* pfile;
pfile = argv[0] + strlen(argv[0]);
for (; pfile > argv[0]; pfile--)
{
if ((*pfile == '\\') || (*pfile == '/'))
{
pfile++;
break;
}
}
if (!_stricmp(pfile, "left.exe")) {
pAudioEndVol->SetChannelVolumeLevelScalar(0, 1.0, &GUID_NULL); // Left
pAudioEndVol->SetChannelVolumeLevelScalar(1, 0.0, &GUID_NULL); // right
}
else if (!_stricmp(pfile, "right.exe")) {
pAudioEndVol->SetChannelVolumeLevelScalar(0, 0.0, &GUID_NULL); // Left
pAudioEndVol->SetChannelVolumeLevelScalar(1, 1.0, &GUID_NULL); // right
}
else {
pAudioEndVol->SetChannelVolumeLevelScalar(0, 1.0, &GUID_NULL); // Left
pAudioEndVol->SetChannelVolumeLevelScalar(1, 1.0, &GUID_NULL); // right
}
if (pAudioEndVol)
pAudioEndVol->Release();
if (pEndpoint)
pEndpoint->Release();
if (pEnum)
pEnum->Release();
CoUninitialize();
return 0;
}
これを例えばrestore.cppとしてセーブして。コマンドラインのC Compilerである、bcc32cでコンパイルすればbuild完了で、restore.exeができます。restore.cppが存在するディレクトリで”Open Git Bash here”した後、
jakeb@Orbit-11 MINGW64 ~/OneDrive/Desktop/restore
$ vi restore.cpp
jakeb@Orbit-11 MINGW64 ~/OneDrive/Desktop/restore
$ bcc32c restore.cpp
Embarcadero C++ 7.70 for Win32 Copyright (c) 2012-2024 Embarcadero Technologies, Inc.
restore.cpp:
Turbo Incremental Link 6.99 Copyright (c) 1997-2024 Embarcadero Technologies, Inc.
jakeb@Orbit-11 MINGW64 ~/OneDrive/Desktop/restore
$ ls -alt
total 336
-rw-r--r-- 1 jakeb 197609 196608 1月 24 11:18 restore.tds
drwxr-xr-x 1 jakeb 197609 0 1月 24 11:18 ./
-rwxr-xr-x 1 jakeb 197609 75264 1月 24 11:18 restore.exe*
-rw-r--r-- 1 jakeb 197609 1874 1月 24 11:18 restore.cpp
drwxr-xr-x 1 jakeb 197609 0 1月 24 11:17 ../
jakeb@Orbit-11 MINGW64 ~/OneDrive/Desktop/restore
$ cp restore.exe left.exe
jakeb@Orbit-11 MINGW64 ~/OneDrive/Desktop/restore
$ cp restore.exe right.exe
等として、restore.exeをleft.exeおよびright.exeとしてもCopyしてください。ソースを読めばわかりますが、LinuxというかUnixの基本的手法のargv[0]で挙動を変えるという仕掛けです。標準のUnixコマンドにもそのような仕掛けをもったものがちらほらあります。(かなりのオールドタイマーでないと知らないかも。筆者なんざBSD/386の時代から…..。)
これでright.exeを起動(ダブルクリックでおけ)すれば、
となり、left.exeを起動すれば、
元に戻したければ、restore.exeを起動すれば
と元に戻ります。お試しあれ。なおこれらは100対0にするので、それが不満な場合は、いったん
HRESULT GetChannelVolumeLevelScalar(
[in] UINT nChannel,
[out] float *pfLevel
);
で現在の値を取り出しておいて、ファイルなどへ書き出しておき、restore.exeで戻す等は可能です。
真面目に定位まで含めて対策するのであれば、元記事にあるようにapo equalizer等で
Copy: L=L R=L
なるスクリプトを末端に置けばいいです。普通の状態に戻すのは、このスクリプトをremoveすればいいです。(意外に面倒ですけど。)
ちなみにVisual StudioでもIDEからなら正常にコンパイルできました。
コメント