Voayage MPDの優先度をチューニングしてさらなる高みを目指す(2)

yanさんが解明してくれたMPDの秘密

さて、前回の設定では再生ソフトであるMPDを動作させるための一連のスレッドの優先度の設定が含まれていませんでした。実は、このスレッドは「chrt」と言うコマンドを使って簡単には優先度を変更することができないのです。

ちなみに、デフォルトではこうなっています。

# ps -eLo pid,lwp,rtprio,priority,time,cmd | egrep “mpd”
2128 2128 – 20 00:00:00 /usr/local/bin/mpd /etc/mpd.conf
2128 2130 – 20 00:00:00 /usr/local/bin/mpd /etc/mpd.conf
2128 2131 – 20 00:00:00 /usr/local/bin/mpd /etc/mpd.conf
2128 2249 – 20 00:00:00 /usr/local/bin/mpd /etc/mpd.conf
2251 2251 – 20 00:00:00 egrep mpd

上から全て「/usr/local/bin/mpd /etc/mpd.conf」となっているのですが、それぞれ順に「main thread、player thread、decoder thread、output thread」の優先度を表示しています。
見れば分かるように、全てのスレッドが「- 20」となっていますから、通常のLinuxのプロセスと同じ設定です。どのスレッドも特別に優先的な扱いを受けるようにはなっていません。
そこで、できることならば、この一連のスレッドに関しても優先度を弄ってみたいと思うのですが、残念ながら今までは手出しができませんでした。

と言うか、もっと正確に言えば、MPDという再生ソフトがこのようなスレッドで構成されていることは、全く知られていませんでした。ですから、そう言うスレッドの優先度を変更してみるという「発想」自体がなかったというのが正直なところです。

事の起こりは、yanさんが、MPDのソースコードを読み解いて、MPDが「main thread、player thread、decoder thread、output thread、update thread」というスレッドから成り立っていることを明らかにしてくれたことから始まります。
そして、MPDの設定ファイルである「/etc/mpd.conf」から上記のスレッドの優先度を設定できるようなパッチファイルを公開してくれたことで、私たちのようなド素人でも手を出すことが可能になったわけです。

ですから、ここの設定を変更したい方は、「みみず工房」さんのサイトへ行って、yanさんが公開してくれているパッチファイルを落としてきて、それを適用することが必須となります。ただし、これもまた、いささかハードルが高いのですが、yanさんが提供してくれているパッチは「mpd 0.17」にしか適用できません。
ですから、yanさんのパッチファイルを適用して、上記スレッドの優先度を弄ってみようと思えば、まず最初にソースコードを落としてきて「mpd 0.17」にバージョンアップする必要があります。

まずは、「mpd 0.17」にバージョンアップ

ソースコードを落としてきて、自前でコンパイルしてインストールする手順は既に報告してありますので、まずはそちらを参考にして、バージョンをアップしてください。

MPDをバージョンアップ(0.16→0.17)
MPD 0.17.0+ALSAで音が出ないという問題が解決しました。

以下には、とりあえずバージョンアップのためのコマンドだけ列挙しておきます。

# mpdを停止
/etc/init.d/mpd stop

# 基本ライブライリのインストール
apt-get install aptitude wget
apt-get install git binutils gcc make subversion autoconf automake autotools-dev libtool pkg-config
apt-get install build-essential libncurses5-dev libncursesw5-dev linux-headers-`uname -r` libglib2.0-dev

# 個別のライブラリをインストール
apt-get install libflac8 libflac-dev # flacをサポートします。(必須)
apt-get install libogg0 libogg-dev libvorbis0a libvorbis-dev # Ogg Vorbisをサポートします。
apt-get install libid3tag0 libid3tag0-dev libmad0 libmad0-dev # id3タグをサポートします。
apt-get install libcue-dev libcue1 # cue sheetをサポートします。
apt-get install libasound2 libasound-dev libasound2-dev # ALSAをサポートします。(必須)
apt-get install libsamplerate0 libsamplerate-dev # サンプリングレートの変更をサポートします。
apt-get install libavformat52 libavformat-dev libavcodec-dev libavcodec52 libavutil49 libavutil-dev # mp3、apeなどをサポートします。(必須)
apt-get install libsndfile-dev libsndfile1 libaudiofile0 libaudiofile-dev # WAVEファイルなどをサポートします。(必須)

# mpdの最新版をインストールする
git clone git://git.musicpd.org/master/mpd.git
cd ./mpd
./autogen.sh
CFLAGS=”-O2 -mtune=`uname -m`” ./configure -disable-ipv6 -disable-sndfile # -disable-sndfileを忘れると、ALSAで音が出ないトラブルが起こるときもあります。
make
make install

# 起動させるmpdを変更する
echo DAEMON=/usr/local/bin/mpd >>/etc/default/mpd

/etc/init.d/mpd start # MPDを起動する。
mpc version # MPDのバージョンを確認する。

パッチファイルを適用する

次に、yanさんが公開してくれているパッチファイルを適用して、再度コンパイルしてインストールし直します。
まずは、みみず工房さんのサイトに行ってyanさんのパッチファイルを落としてきて適用します。

cd ./mpd # mpdのソースコードが展開されているディレクトリに移動する。
wget http://hpcgi3.nifty.com/yo_kubota/downlog.cgi?data/mpd-rtopt-2.tgz #パッチファイルをダウンロードする
tar zxvf mpd-rtopt-2.tgz # 解凍する
patch -p1 < mpd-0.17-0414-rtopt.diff # パッチファイルを適用する これで、MPDのソースコードにパッチファイルが適用されましたので、再度コンパイルし直してインストールします。 ./autogen.sh CFLAGS=”-O2 -mtune=`uname -m`” ./configure -disable-ipv6 -enable-rtopt -disable-sndfile # -enable-rtoptを追加することで「realtime_option」が有効になるので必須。 make make install 「realtime_option」は「memlock」と「audio_output」以外のスレッドの優先順位を指定するものなのでこれを忘れるとパッチファイルを適用した意味がなくなります。 configureのMPD CONFIGURATIONメッセージのOther features:欄に(+rtopt)となっていればrealtime_optionは有効になるので、その時点で必ずチェックしてください。 なお、「memlock」については私もあまり理解できていないのですが、これは、「Ubuntu」のコミュニティで音楽再生の論議が行われていて、その中でこれをオンにした方が音がいいという議論がなされているので適用されたみたいです。 ただし、ネット上の情報を見ていると、必ずしも「memlock」をオンにすれば音がよくなると言う単純なものではないようですので、最終的には自分の耳による判断が必要になると思います。 どうも、それぞれのPC環境によってかなり左右されるようです。

/etc/mpd.conf(設定ファイル)を編集する

パッチファイルが適用されれば、「/etc/mpd.conf」を編集することで、

main thread:MPDを起動し、クライアントとの通信を行う
player thread:プレーヤーのコマンド(再生、ストップなど)を管理する
decoder thread:音楽ファイルを読み込みPCMへ変換する
output thread:PCMデータをドライバーに受け渡す
update thread:tag_cacheのアップデートを行う

のスレッドの優先度を弄ることができるようになります。
やり方は、以下のような書式で追記するだけです。

vi /etc/mpd.conf

realtime_option {
memlock “yes”
stack_reserve “1024”
heap_reserve “10240”

main_priority “OTHER:0”
player_priority “FIFO:51”
decoder_priority “OTHER:0”
update_priority “OTHER:0”
}

これは全く存在しない記述ですので、これをコピーして「/etc/mpd.conf」の頭の部分に貼り付ければいいと思います。

最初の3行は「memlock」に関する記述です。

memlock “yes” //「memlock」をオンにする。
stack_reserve “1024” //「memlock」のパラメータ。
heap_reserve “10240” //「memlock」のパラメータ。

stack_reserveとheap_reserve の数値に関してはまあこんなものでしょうから、ポイントは「memlock」をyes(オン)、no(オフ)にして聞き比べればいいかと思います。no(オフ)の方が好ましいと思えば、そちらを適用してください。

次の4行はMPDの「audio_output」以外のスレッドの優先順位を指定する記述です。

main_priority “OTHER:0″
player_priority “FIFO:49″
decoder_priority “OTHER:0″
update_priority “OTHER:0″

“OTHER:0″はlinuxの通常のプロセスと同じ扱いで言いと言うことを示しています。
“FIFO:49″は優先度を上げることを意味していて「1~99」の数値が割り当てられます。数値は大きいほど優先度が上がります。

次に、「audio_output」の優先度は、それぞれの「audio_output」ごとに割り当てます。
私の場合は「ALSA」しか使っていませんので、

audio_output {
type “alsa”
name “My ALSA Device”
device “hw:0,0”
priority “FIFO:52”
}

としています。

「priority “FIFO:52″」というのが優先度の設定です。
つまり、私の場合は「player thread」の優先度を「49」、「output thread」の優先度を「52」に変更して、それ以外のスレッドはデフォルトのままという設定です。

最後に設定ファイル(/etc/mpd.conf)の編集が終われば、MPDを再起動させて新しい設定を反映させます。

/etc/init.d/mpd stop
/etc/init.d/mpd start

次に設定が反映しているかどうか確認します。

ps -eLo pid,lwp,rtprio,priority,time,cmd | egrep “irq/16|irq/19|mpd|cifsd”

1151 1151 50 -51 00:00:00 [irq/19-ata_piix]
1159 1159 52 -53 00:00:00 [irq/19-uhci_hcd]
1161 1161 50 -51 00:00:00 [irq/16-uhci_hcd]
1504 1504 50 -51 00:00:00 [irq/16-i915]
1839 1839 53 -54 00:00:00 [irq/16-eth0]
1899 1899 53 -54 00:00:00 [cifsd]
2132 2132 – 20 00:00:00 /usr/local/bin/mpd /etc/mpd.conf
2132 2134 49 -50 00:00:00 /usr/local/bin/mpd /etc/mpd.conf
2132 2135 – 20 00:00:00 /usr/local/bin/mpd /etc/mpd.conf
2132 2203 52 -53 00:00:00 /usr/local/bin/mpd /etc/mpd.conf
2209 2209 – 20 00:00:00 egrep irq/16|irq/19|mpd|cifsd

優先度の設定がきちんと反映されていることが分かります。

最後に

ここで、一番問題となったのは、「decoder thread」の優先度をどうするかという問題なのですが、基本的には再生ファイルとして「Wave」しか使わないので、これは静かにしておいてもらった方がいいだろうと判断したわけです。これが、「FLAC」が主体だと判断はまた異なってくるのではないかと思われます。

次に頭を悩ませたのが、「player thread」と「output thread」の優先度をいくつに設定するかです。
これは、前回設定した「irq/19-uhci_hcd」「irq/16-eth0」「cifsd」の優先度とも兼ね合いを考える必要があります。

個人的には

「irq/16-eth0」(53)=「cifsd」(53)>「output thread」(52)=「irq/19-uhci_hcd」(52)>「player thread」(49)

としたのですが、今もいささか悩んでいるところです。
音楽データが川上から川下にスムーズに流れていくためには、川上重視と言うことで

「irq/16-eth0」(54)>「cifsd」(53)>「output thread」(52)>「irq/19-uhci_hcd」(51)>「player thread(49)

という設定もあるのかなと言う「考え」がひらめいたりもします。(理論的根拠は全くなくて、私の直感だけですが・・・)
<追記>
試してみましたが、これはダメでした。音が痩せてしまって明らかにまずい方向に向いてしまいました。
やはり、音の出口を優先した方がいいのかもしれません。
<追記、終わり>

しかし、これもまた、それぞれが使っている環境によってこのあたりの数値はずいぶん変わってくるのではないかと思われます。
ですから、最終的には自分の耳を信じて「カットアンドトライ」を繰り返して自分なりの「最適値」を探し出すことが重要なのだと思います。

まさに、趣味性満点の試みだと思います。
興味をひかれた方は、是非ともトライしてみてください。

現時点での私の設定(追記)

いろいろな方の情報も参考にして、自分自身も試行錯誤を繰り返して、現時点では以下の設定が一番納得のいくものかと考えています。

[/etc/mpd.confの設定]

realtime_option {
memlock “yes”
stack_reserve “1024”
heap_reserve “10240”

main_priority “OTHER:0”
player_priority “FIFO:51”
decoder_priority “OTHER:0”
update_priority “OTHER:0”
}

audio_output {
type “alsa”
name “My ALSA Device”
device “hw:0,0″
priority “FIFO:53”
}

[/etc/rc.localの設定]

chrt -f -p 99 `pgrep irq/19-uhci_hcd`
chrt -f -p 52 `pgrep irq/16-eth0`
chrt -f -p 52 `pgrep cifsd`

基本的な考え方は「出口」優先です。理由はよく分かりませんが、「入り口」優先よりは「出口」優先のほうが音質が改善されます。それも、じっくり聞いてみて「何となく」というようなレベルではなく、だれが聞いてもはっきりと分かるほどに違いがあります。

そこで、
まず、全プロセスの中で一番優先度が高いのは[migration/0]と[posixcputmr/0]で、それぞれ「99」が割り当てられているので、音の出口にあたる「irq/19-uhci_hcd」にも「99」を割り当てます。
次に高い優先度が与えられているのが[irq/14-ide0]などの「50」ですから、優先度を上げたいプロセスには「51~98」の間で数値を割り振ればいいと言うことになります。
そこで、音の出口に近い方から高い数値を割り当てていきます。「audio_output」に「53」を割り振っていますが、この「53」という数字には大きな意味はありません。

「output thread」(53)>「irq/16-eth0」(52)=「cifsd」(52)>「player thread」(51)

となるように「51~98」の間で適当に数値を割り振っただけです。
ですから、何か別のプロセスが高い優先度で動いているような環境ならば、それにあわせて数値を変えればいいと思います。

さて、この設定で再生される音楽なのですが、デフォルトの状態と比べると全ての要素でワンランク以上グレードアップした感じです。
まずは、この手のシステムの一番の得意分野である「透明度」「解像度」ですが、明らかにワンランクアップしています。まさに「検聴器」という言葉を呈したいほどで、アナログ初期の録音だとテープの編集箇所まで指摘できるほどです。
また、往々にしてこのような「高解像度」とバーター関係にあるように思われる「音色」についても、全くきつさや固さは感じません。それどころか、一つ一つの楽器の音像はよりしっかりとして太さを増したようにすら感じられます。特に、チェロやコントラバスのような低弦楽器の響きは出色です。ピアノの低音部の深々とした響きも同様です。
つまり、本来ならば、同時に成り立つことは考えにくいようなことが起こっているわけです。

ただ、楽器の持っている「色気」みたいなものを描き出すのはあまり得意ではないようです。
つまり、このシステムはデフォルトでもそうなのですが、基本的には蒸留水のような「淡泊」さが持ち味で、音楽を濃厚に描き出すようなことは絶対にしません。
ただし、それは録音の中にそのような「濃厚さ」を演出するような要素がもともと含まれていないためだと私は考えています。
しかし、オーディオというのは基本的のは趣味の世界ですから、音楽をそのように濃厚に描き出してほしいと思う人がいてもそれは当然のことであって、そのような方にとっては物足りないシステムだと思われるかもしれません。

あと、「音場」の広がりですが、これはデフォルトの状態とあまり大きな違いは感じませんでした。
おそらく、デフォルトの状態でもその三次元的な広がりの素晴らしさは感じていましたから、頭打ちと言うことでしょうか。

ざっと、こんな感じですが、やはり「音」を言葉で表現するというのはもどかしいですね。
ただ、このレベルを実感すると、やはり「チューニング」は必須と思われます。