Realtekが仕事しないから俺が仕事をした

どうも、お久しぶりな赤西真論です。

今回もまた、スクリプトエンジンにほとんど関係のない話となります。

まずですね、最近CF-J10というノートパソコンをヤフオクで買いました。

こいつ、性能の割に小さく軽くて非常に気に入っているのですが、一つ弱点を発見してしまいまして……

それは

スピーカーとヘッドホンジャックの音量が同期している!!

これは非常に大問題です。

簡単に説明してますと、例えばスピーカーをミュートの状態にしてヘッドホンを刺すとヘッドホンの音量もミュートになっている。逆にヘッドホンの音量を10にしていてヘッドホンを抜くとスピーカーの音量も10になるという非常に使い勝手が悪い状態なんです。

これじゃ、お外でエロゲ……じゃなくて動画が見れない。

こういうときはいろいろ設定を見回るものです。とりあえず、Realtekのチップが載っているのでその設定画面を見てみましょう。

SnapCrab_Realtek HD オーディオマネージャ_2017-2-20_22-41-58_No-00

なんか、設定少ないですか……

例えば、メインマシンの場合だったら

SnapCrab_NoName_2P-0034

こんな感じでデバイス詳細設定があって、ちゃんと分離できるようになっています。

Realtekさん、仕事してよ!

オーディオマネージャーは同じだから、レジストリからいけるだろって見ましたけどそんな感じの設定は見当たらず……

もう、諦めて自分で気を付けるようにするという手もありましたが、家では結構スピーカーから音を出すことが多いので多分やらかす。

で、よく考えるとイヤホンを刺したときに右下に通知が出るんですよね。

SnapCrab_NoName_2P-0035

こんなやつです。

ということはPC自体はヘッドホンが接続されたことを検出出来てる??

Realtekさん、仕事してよ!(2回目

なら、どこかにそれが見当たるはずです。探してみましょう。

見つけました。サウンド設定の再生デバイスです。

ここでメインマシンとCF-J10の設定を見比べてみます。(右メインマシン、左CF-J10)

SnapCrab_サウンド_2P-0000SnapCrab_サウンド_2017-2-20_23-0-28_No-00

メインマシンにはある2nd outputが見えてませんね。これでは分離されません。

では、CF-J10のスピーカーのプロパティーを見てみます。

SnapCrab_スピーカーのプロパティ_2017-2-20_22-16-21_No-00

まあ、普通ですね。で、ここで注目するのがジャック情報です。今はヘッドホンを接続していない状態なのでATAPI 内部コネクタしか表示されていません。

ヘッドホンを接続してみます。

SnapCrab_スピーカーのプロパティ_2017-2-20_22-16-54_No-00

なんか追加されましたね。フロントパネル 3.5mm ジャックです。これを使えば切り替えることが出来るのではないでしょうか。

ということで、お仕事します。

まず、検出できるのかどうかからです。これに関しては下のブログを参考にしました。

DeviceTopology API を使ってみる – すらりん日記

はい、僕のやりたいことがそのままのように載っていました。非常にありがたいのですが、なんかIMMDeviceインターフェースが取得できてる前提のようです。Core Audio APIなんて知らなかったレベルの人が取得できるはずがありません。もっと調べてみます。

MMDevice APIを利用してマスター音量を操作する – Qiita

世の中って素晴らしいですね。欲しい情報がいっぱい出てきます。

さて、こちらの2つのサイトを主に参考にしながら適当に3時間ぐらいで書いてみました。

marron-akanishi/VolumeChanger: Separate volume between speaker and headphone

かっこ悪いプロジェクト名ですが、最初完成するとは思わなかったので適当な名前です。

  • ダウンロード
    今回は初めてGitHubのReleaseページを使ってみました。下のリンクからVolumeChanger.zipをダウンロードしてください。

Releases · marron-akanishi/VolumeChanger

  • 使い方
    では、使い方の説明です。ダウンロードしたファイルの中には下の2つのファイルが入っています。
    setting.ini –> 設定ファイル
    VolumeChanger.exe –> 実行ファイル本体
    まず、setting.iniを開いてください。これは初期設定として使用します。
    • [Default]

 

    • SpeakerCount=1

 

    • SpeakerVol=0.2

 

    • SpeakerMute=True

 

    • HeadphoneVol=0.08

 

    LoopDelay=200
    こんな感じのテキストが書いてあると思います。
    上から順番に説明していきます。
    SpeakerCountではスピーカーのみの状態でジャック情報がいくつあるかを示しています。
    例えば

SnapCrab_スピーカーのプロパティ_2017-2-20_22-16-21_No-00

    この状態でしたら、1つですので1と書いておきます。
    SpeakerVolではスピーカーの音量を指定します。あくまでも初期設定ですので、ヘッドホンを接続すると接続前の音量を記憶し、抜くと自動的にその音量に戻します。また、起動時にスピーカーの状態であれば、その値を使用します。この値は%指定なのですが、プログラム側が0~1の実数値で扱うので、0.2などの値になっています。つまり、20%であれば0.2とし、37%でしたら0.37と書きます。
    SpeakerMuteはスピーカーのミュート状態を指定します。これもあくまで初期設定です。起動時にヘッドホンを接続しているとスピーカーの値を取得できません。つまり、ミュートかどうかも判断ができません。その為、初期設定を使用してヘッドホンを抜いた際に自動的にミュートにします。そのための設定となっています。ミュートにする場合はTrue、しない場合はFalseと書いてください。
    HeadphoneVolはヘッドホンの音量です。ほとんどSpeakerVolと同じですので説明は省略します。
    LoopDelayはメインループの処理時間を設定します。これは、プログラムの仕様として一定間隔でジャック情報を取得し、状態が変化したら音量を変更する方法を取っています。その取得間隔を指定します。単位はms(ミリ秒)となっています。200msで大丈夫だと思うのですが、CPU使用率が高いなどの問題がある場合はここの値を大きくしてください。で、その際の注意点ですが、あまりにも長い時間を設定すると取得が間に合わず音が外に出てします危険があります。出来れば1000ms(1秒)以下に設定してください。また、あまり短くしてもほとんど意味はありません。
    設定が出来たら、保存をします。
    次に実行ファイルを実行します。

SnapCrab_VolumeChanger_2P-0000

    このようなメッセージが出れば、起動しています。ヘッドホンを刺したりして動作を確認してください。音量が変化すれば成功です。
    終了方法が全くないので、タスクマネージャーから強制的に落としてください。スタートアップに登録するといいかもしれません。

いつも忘れるのでスタートアップフォルダーの位置のメモ

C:Users[ユーザー名]AppDataRoamingMicrosoftWindowsStart MenuProgramsStartup

  • 注意点・仕様等

動作はCF-J10でしか確認していません。他のPCで動くかどうかなんて保証は出来ませんので、ご了承ください。また、仕様としてヘッドホンのミュート状態は全く監視していません。強制的にミュートが解除されます。元々僕しか使う予定が無かったようなプログラムなのでそこら辺は我慢してw
あと、iniを実行ファイルが書き換えるようなことはしないので、再起動すると自動的に初期設定に戻ってしまいます。初期設定は自分がいつも設定している音量にしておくことがベストです。

また、上の示したようなダイアログを出しているのには理由があります。スタートアップに登録しているといつ起動するか分かりません。起動していないときにヘッドホンを抜き差しすると、正しい音量を取得出来ない可能性があるのでダイアログを出しています。もしも、出る前に抜き差ししても音量を調節すれば記憶し直すはずです。

ソースコードは公開していますが、いつものように(?)サンプルのパクリばかりです。また、午前4時とかいう頭の悪い時間に書いたので、超汚いです。(時間は関係なく汚いか)

はい、こんな感じでどうでしょうか。

初めてCore Audio APIなんて叩きましたし、C++も久々に書きました。(僕が追記したところはほとんどCのような書き方ですが)
メモリリークにも遭遇したりして……

とりあえず、今日はこれで

投稿者: 赤西 真論

アイマスに人生を変えられ、コードを書くのが嫌いになった大学生

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください