Raspberry Pi製品には高音質なI2S接続サウンドカードやUSB DACを付けて音楽鑑賞をする用途があり、OS(ディストリビューション)の形で配布されているソフトウェアもあるが、Raspberry Pi OSを動かしている場合であっても音楽再生ソフトを使えば実現できる。
本記事では音楽再生用途のサウンドデーモン “Music Player Daemon (MPD)” を用いる形でPC上の音楽ファイルなどを再生してRaspberry Pi側のサウンドデバイスから出力するための環境についてを扱う。
手元の環境ではPi Zeroをイーサネットガジェットとして動かして接続している。
/boot/config.txt
においてサウンドカードに合ったdtoverlay=
などの記述の追加後に起動しておくIPアドレスについては、どちらも固定されていることを前提とする。
音楽データのあるマシンはPiから見るとリモートマシンとなるため、MPDにおけるSMB(libsmbclient
)またはNFS(libnfs
)のクライアント機能を有効にする必要がある。
これはLinuxカーネルのファイルシステムサポートとは異なる。カーネルの機能でマウントしたリモートマシン上の場所にある音楽ファイルを再生すると音が途切れることがあるため、ユーザ空間のライブラリを用いて処理を行う必要がある。
Raspberry Pi OSを含むディストリのパッケージのMPDではSMBやNFSの機能は有効になっていることが多い。
libsmbclient
を用いる場合、データベースの更新時や更新後の再生開始のタイミングでMPDが落ちることがある。安定した動作が重要であればNFSを用いたほうがいいかもしれない。
MPDを普通のやり方で設定すると、Pi側にデータベースが作成されて管理される。
この場合、データベースを更新すると音楽データのあるPCなどの側から音楽ファイルを片っ端から転送する上、低速なPiのCPUで読み込むことにもなり、非常に時間がかかる上にネットワーク帯域も浪費してしまうという問題がある。
そこで、PCなどの側でもう一つMPDを動かすようにしてデータベースの設定を適切に行うと、データベース更新をPCなどの側にあるMPDに依頼して新しくできたデータベースだけを受け取るようにする構成(Satellite setup)にすることができ、データベース更新にかかる時間とネットワーク帯域の使用を大幅に削減できる。
この機能にはlibmpdclient
ライブラリとMPD自体の同ライブラリのサポートが必要。これもRaspberry Pi OSを含むディストリのパッケージのMPDでは有効になっていることが多い。
リモートマシン上の音楽ディレクトリとして
smb://
nfs://
のURLで記述し、対応する入力プラグインについての記述も追加する。
mpd.conf
(Pi側)
# SMBの場合
music_directory "smb://user:password@ipaddress/sharename/path"
input {
plugin "smbclient"
}
# NFSの場合
music_directory "nfs://ipaddress/path"
input {
plugin "nfs"
}
上の例で強調されている行の値は、環境に合わせたものにする。
既定の設定ファイルではdb_file
という項目でローカルのデータベースファイルの場所を定義するのだが、ここではPi側において以下の編集を行う。
db_file
の記述は削除またはコメントアウトdatabase
セクションでproxy
プラグインを設定
host
),そこで動作しているMPDのポート番号(port
)とパスワード(password
)を環境に合わせて設定mpd.conf
(Pi側)
database {
plugin "proxy"
host "ipaddress"
port "6600"
password "mypassword"
}
音楽ファイルのあるPCなどの側では、music_directory
でPi側から共有されている最上位のディレクトリを指定した上で、db_file
を記述する形でローカルにデータベースを配置しておく。
mpd.conf
(PCなどの側)
# SMBやNFSで共有される最上位の音楽ディレクトリを指定
# Pi側の設定ファイルで指し示されている階層に対応するようにする
music_directory "/path/to/shared_music_directory"
# ローカルのストレージにデータベースファイルを配置
db_file "/path/to/mpd/tag_cache"
また、PCなどの側がLinuxの場合、以下の設定の記述を行うと、Linuxカーネルの “inotify” の仕組みを用いて、音楽ディレクトリ内に変更があった際にカーネルから通知を受け取って自動的にデータベースの更新を行うことが可能。
mpd.conf
(PCなどの側)
# 以下の設定項目は初期状態の設定ファイルではコメントアウトされた形で入っている
# 音楽ディレクトリ内が変更されたら自動的にデータベースを更新
auto_update "yes"
# 監視するディレクトリの深さの制限を必要に応じて指定
auto_update_depth "3"
この機能はディストリのパッケージになっているMPDを使用していれば有効になっていることが多い。
音声の出力先デバイスを指定したり、MPDクライアント(Cantataなど)からの音量調整が正しく動作するように記述を行う。
手元の環境(JustBoom DAC Zero)では、ALSAのドライバにおける情報は
[Raspberry Pi]# cat /proc/asound/cards
0 [sndrpijustboomd]: JustBoomDac - snd_rpi_justboom_dac
snd_rpi_justboom_dac
となっており、音量調整についてはalsamixer
を使ったときに主にDigital
というミキサー項目で調整する形1なので
mpd.conf
(Pi側)
audio_output {
type "alsa"
name "snd_rpi_justboom_dac"
device "hw:sndrpijustboomd"
mixer_control "Digital"
}
という設定を記述して、音量調整も含めて正しく動作している。
上の例を参考にする場合、得られた情報のどの部分が設定ファイルのどの部分に対応しているかを見て設定値を決めるとよい。
MPDはJACKを用いることもできるのだが、JACKを用いる設定にすると、ALSAのミキサー項目がいじれないため音量調整機能が動かない。
手元の環境では、netjack2を使用したいときだけMPDクライアントを終了後にJACKを起動し、MPDを使うときになったらkillall jackd
でJACKを終了させている。
MPDデーモンについては、前述のデータベースのプロキシ機能を用いる場合は音楽ファイルのあるPCなどの側で先に起動しておく必要がある。
その後でPi側のMPDを起動して、PCなどの側にある好みのMPDクライアント(Cantataなど)を設定する。
設定項目 | 値 |
---|---|
ホスト(MPDサーバ) | PiのIPアドレス |
ポート | Piの側で動作しているMPDのポート番号 |
パスワード | Piの側で動作しているMPDのパスワード |
これでデータベースの更新を行えばプレーヤとしての環境は出来上がりで、自動データベース更新を有効にしていれば、その後の音楽ディレクトリへの変更が自動で反映される。
手元の環境では、update-initramfs
で作成されたinitrdのみで動く最小限構成のシステムをPi Zero WHで動かしている。
ここでは、その中でMPDを使用する上のメモを扱う。
以下、この関連記事で扱っている “initrdのみの環境” についての内容を前提とする。
MPDの設定ファイル内のコメントによると、MPDはroot
ではなく一般ユーザの権限で動かすべきとされている。一方で、オーディオデバイスを扱えるようになっている必要もある。
/dev/snd/
以下のオーディオデバイスファイルは初期状態では所有者root
しか書き込めないため
audio
を作成mpd
2を追加audio
のメンバ全員がオーディオデバイスファイルに書き込めるようにアクセス権を設定の3つを実行する。
また、サウンド関係のプログラムの動作には/usr/share/alsa/alsa.conf
が必要で、このファイルが一般ユーザから読み込めるようにアクセス権を修正する必要もある。
#! /bin/sh
# ユーザとグループの準備
echo "audio:x:333:mpd" >> "/etc/group"
echo "mpd:x:222:333::/nonexistent:/usr/sbin/nologin" >> "/etc/passwd"
# アクセス権の修正
chmod go+rx /usr /usr/share /usr/share/alsa /usr/share/alsa/*
chmod g+rw /dev/snd/*
chown root:audio /dev/snd/*
alsa.conf
については、initramfs-toolsのhooks
のスクリプトにてcopy_file()
またはcopy_exec()
を用いてinitrdの作成時に含めるようにできる。
/etc/initramfs-tools/hooks/custom
# Raspberry Pi OSのalsa.confをコピー
copy_file config /usr/share/alsa/alsa.conf
# 自分でビルドしたMPD(strip済み)を含める
copy_exec /usr/local/bin/mpd
これとは別にmpd.conf
も必要となるが、その中には平文のパスワードも含まれるため、Raspberry Pi OSのchroot環境に配置してhooks
のスクリプトで中に含めるようにする場合は扱いに注意が必要。
USBデバイスブートでinitrdのみで動くシステムを動かす際には、initrdの圧縮後のサイズに制約があってOSの容量に余裕がないため、自分の用途で必要ないものはなるべく無効にして手動でビルドしている。
下はそのビルド設定を自動化した例。
configure-mpd.sh
# 初代PiやZero系の場合はarmv6向けの指定だが
# 新しいモデルではより新しい世代用の指定で高速化できる
CFLAGS="-march=armv6 -mfpu=vfp -mfloat-abi=hard -O2" \
CXXFLAGS="-march=armv6 -mfpu=vfp -mfloat-abi=hard -O2" \
meson _build \
-Ddocumentation=disabled \
-Dtest=false \
-Dsyslog=disabled \
-Dinotify=false \
-Dsystemd=disabled \
-Dipv6=disabled \
-Ddsd=false \
-Dupnp=disabled \
-Dlibmpdclient=enabled \
-Dneighbor=false \
-Dudisks=disabled \
-Dwebdav=disabled \
-Dcdio_paranoia=disabled \
-Dcurl=enabled \
-Dmms=disabled \
-Dnfs=disabled \
-Dsmbclient=enabled \
-Dqobuz=disabled \
-Dsoundcloud=disabled \
-Dtidal=disabled \
-Dbzip2=disabled \
-Diso9660=disabled \
-Dzzip=enabled \
-Did3tag=enabled \
-Dchromaprint=disabled \
-Dadplug=disabled \
-Daudiofile=disabled \
-Dfaad=disabled \
-Dffmpeg=enabled \
-Dflac=enabled \
-Dfluidsynth=disabled \
-Dgme=disabled \
-Dmad=disabled \
-Dmikmod=disabled \
-Dmpcdec=disabled \
-Dmpg123=disabled \
-Dopus=enabled \
-Dsidplay=disabled \
-Dsndfile=disabled \
-Dtremor=disabled \
-Dvorbis=enabled \
-Dwavpack=disabled \
-Dwildmidi=disabled \
-Dvorbisenc=disabled \
-Dlame=disabled \
-Dtwolame=disabled \
-Dshine=disabled \
-Dwave_encoder=false \
-Dlibsamplerate=enabled \
-Dsoxr=disabled \
-Dalsa=enabled \
-Dao=disabled \
-Dfifo=false \
-Dhttpd=false \
-Djack=enabled \
-Dopenal=disabled \
-Doss=disabled \
-Dpipe=false \
-Dpulse=disabled \
-Drecorder=false \
-Dshout=disabled \
-Dsndio=disabled \
-Ddbus=enabled \
-Dexpat=enabled \
-Dicu=enabled \
-Diconv=enabled \
-Dpcre=disabled \
-Dsqlite=disabled \
-Dyajl=disabled \
-Dzlib=enabled \
-Dzeroconf=disabled
[mpd-x.y.z]$ /path/to/configure-mpd.sh
[mpd-x.y.z]$ meson compile -C _build
[mpd-x.y.z]# meson install -C _build
Pi側に音楽ファイルのストレージを接続する使い方では-Dinotify=false
の代わりに-Dinotify=true
を付けてデータベース自動更新機能が使えるようにしたほうがよい。