ここ数日、「例のトリッキーなやつ」(先日の投稿の、Spotifyアプリのログから音量正規化のための値(RG値)を抽出して正規化する方法)が諦めきれず、悪戦苦闘していた。何度も諦めたのだが、そのたびにアイデアが出て来てしまって再挑戦する羽目になり、今日は随分いい感じになったのたが、やっぱり駄目だった。

記念(または証拠)に、最良の状態での動作光景を載せる。画面左上はRG値取得用Spotifyアプリ、右上はミュート(上側)・ゲイン調整+リミッター(下側)用アンプ、左下はミニプレーヤー、中央から右下は再生用Spotifyアプリである。曲間でのアンプの設定の変化や、プレーヤーの切り替わり(アプリ下部の緑の帯)に着目されたい(もちろん、手で操作している訳ではないし、マウスなどを自動操作するツールを使っている訳でもない)。

Spotifyアプリから音量正規化のための値を抽出して音量正規化している画面

動作の流れは以下である。

  1. Spotifyアプリ(音量正規化: off)が再生を開始する(またはトラックが変わる)のを待つ。
  2. アンプでSpotifyアプリの出力をミュートする。
  3. プレーヤーをRG値取得用Spotifyアプリ(音量正規化: on)に切り替える。
  4. その曲のRG値が取得できるまで(再生して)待つ。
  5. アンプにRG値を元に計算したゲイン(増幅量)を設定する。
  6. プレーヤーを再生用Spotifyアプリに切り替える。
  7. 曲の先頭に戻る。
  8. アンプのミュートを解除する。
  9. 再生を開始する。

基本動作はできた※のだが、試しに少し(15分くらい)動かしていたら、RG値取得用アプリとSpotifyサーバの通信ができなくなってRG値が取れなくなってしまった。再生用アプリの動作は問題ないので、短時間(RG値取得用アプリに切り替わっている時間は約2秒)で切り替えるとうまく動かなくなってしまうのかも知れない。まあ、再生し始めたと思ったらすぐに切り替えるなんておかしな使い方を想定していないのはもっともだから、仕方ない。

※本方式での音量正規化処理自体は、全く問題なかった。性能(音量の揃い具合)はSpotifyアプリよりも良かった(とはいえ、大差ではない)。また、前回(「と思いきや」のあと)失敗した、プレビュー版のRG値とは異なる場合が多かったので、そちらには得体の知れない値が入っているようだ。

あと、不思議なことに、投稿用に動画を撮り直そうとして再度動かしてみたら、プレーヤー切り替えのタイミングがずれて※、曲間で余計な音(RG値取得中または曲の先頭に戻る前の音)が出るようになってしまった(上の動画はボツのテイクを投稿用に少し編集している。でも、ちゃんと動いていたのは確かで、夢や幻や捏造ではないw)。だから、SpotifyのアプリもWeb APIも、こういうタイムクリティカルな用途には無理があるようだ。

※アプリの切り替え時間(= RG値の取得・処理時間= 曲間)は最初は4秒くらいだったのだが、それでは遅過ぎるので(結構苦労して)高速化・最適化したら不安定になったようだ。元の遅い版ならもう少し安定なのだろうが、それでは気分が悪いw それどころか、最初は1秒以内にしたいくらいだった。

そもそも、(前回も書いたが、)これをやりたかった理由の一つはダイナミックレンジをなるべく減らしたくないことだが、再度計算してみたら、Spotifyの音量正規化のQuietモード(基準音量: -23LUFS)を使っても2ビットも落ちないことが分かった※ので、ポップ音楽でそこまでこだわる意味は全くないから無理する必要はない。

※先日の試算では、音量を-23LUFSにするのに23dB下げると考えたが、それは誤りで、SpotifyがRG値の計算に用いているReplayGainの基準音量は-14LUFSなので、(-14-(-23)=)9dB下げる程度であり、それは(9/6=)約1.5ビット相当である。

あと、RG値取得用アプリが駄目になる問題は、例えば、通信できなくなったらしばらく(数分?)待ってアプリを再起動すれば回復できるだろうが、たとえ自動的にするとしても、再起動されるまでは聴けなくなって気分が良くないし、音量正規化のon/off切り替え時にアプリを再起動したくないからこの方法にしようとしたのに、(再生用ではないけど)やっぱり再起動が要るのでは馬鹿らしい。それに、上に書いたように、タイミングが変動して安定して動かないのでは、とても実用にはならない。

そんな訳で、結果的には無駄なことをして疲れたが、いろいろ(細かい)発見があっておもしろかったせいか、余りがっかりはしていない。むしろ、事前の予想どおり駄目だったものの、基本的には目論見どおりに動作して満足したし、方が付いてせいせいしたw

 

最後に、開発中に分かったことなどを少し書く。

  • Spotifyアプリを外部から制御するにはWeb APIとDbusの2種類でできるが、プレーヤーを切り替えて使う場合はWeb APIだけを使った方がいい。Dbusで操作すると、どのプレーヤーが対象か分からなくなったり、意図したプレーヤーが操作されなかったり、プレーヤーの切り替えがうまくいかない場合がある。
    • Web APIはかなり遅い(数百ms/回)のでDbus(数十ms/回)で高速化したかったのだが、残念ながら駄目だった。
  • SpotifyのWeb APIを短時間に頻繁に使うとサーバがエラーを返すようだ(本文に書いたエラーもこれと同様)。HTTP 500なのでアクセス制限(rate limit)ではないようだが・・・
  • 更に、頻繁に使わなくても謎の動作をする場合がある。Dbusを使わなくてもおかしくなることがあるようだ。
  • 曲の開始直後に先頭にシークすると前の曲にジャンプしてしまうようで、少し待たないといけないようだ。
  • Linuxのサウンド系には謎の損失(音量低下)があるようで、どこかで4dBくらい音量が下がる。PulseAudio(実際にはALSA)からJACKに入るところか、JACKからサウンドカード(実際にはALSA)に出るところかと想像している。
    • ポップ音楽用の音量正規化の場合、目標の音量をReplayGainと同じ-14LUFSにしたので、理論上はアンプのゲインをRG値そのものにすれば良いはずなのだが、この損失を戻すためのゲイン(4.5dB)を加算した。
    • なお、クラシック音楽用ではその損失を加味して、4dB下げるだけで目標の音量(-23LUFS)になった。
  • (書いても誰も分からない気がするが、)本方式の制御プログラムでは、2つのイベント入力(SpotifyアプリのログとDbusのイベント)を混ぜて受信することで、両方ともタイムアウトなしの受信にすることができ、イベントに対するレスポンス時間の短縮と負荷の軽減ができた。でも、本文に書いたように、高速化したら逆効果だったようだw

 

PS. それにしても、昨日(12/29)までは年末という気がしなかったのだが、今日(12/30)になったら急に「今年ももう終わりか」モードになって、妙に慌ただしい気分になってしまった。そして、「年末なのにプログラミングなんてしている場合かっ?」て気もしたが、特に他にすることもないので問題ないw

  •   0
  •   0

2件のコメント

  1. naoki:

    明けましておめでとうございます(通常進行ですが)。

    動画、メッチャ格好良かったです。BTTFでアインシュタインに餌をやる装置、いや違う……YMOとかのビデオで自動でツマミが動く機器のシーンとかのイメージです。

    •   0
    •   1
  2. れんと:

    ●おめでとうございます(実家で寒いうえに退屈ですw)。

    ありがとうございます。まさにBTTFの給餌装置をイメージしてましたが、確かに、自動で動くミキサー(僕も昔のPVで見たことがあります)のほうが近いですね^^

    •   1
    •   0

コメントを書く

名前    

メール 

URL