はじめに
Raspberry Pi 楽しいですよね。私は専らオーディオ用に使っています。
普通はピンヘッダのI2S出力をDACに繋いでハイレゾ再生するようですが2chしか出力できません。HDMI出力を使えばAVアンプに接続して8ch出力することができます。ところがネット上を検索してもHDMIからの8ch出力に関しての情報は乏しいようです。
そこで今回はHDMIから8ch出力する簡単な方法を示します。
環境
OS:標準のRaspbian(buster、 stretch)
機種:pi0w、pi2B、pi3B、pi4B (pi3B+は持ってない)
もちろんpi4にはbusterが必要です。
8ch出力の使い道
8ch出力なんて何に使うの?サラウンド?
もちろんサラウンドやマルチチャンネルの音楽ソフトの再生に使ってもよいのですが私はfirの畳み込みソフトと組み合わせてマルチアンプシステムに使ってます。
マルチアンプシステムって何?サラウンドと違うの?という方はググって下さい。
簡単に言うと適当に作った自作スピーカーから素晴らしい音質で音楽を再生することができます。
HDMIから8ch出力するサンプルプログラムが最初からあった!
raspbian をインストールすると /opt/vc/src/hello_pi/
の下にサンプルプログラムのソースコードがあります。音声出力のサンプルプログラム(C言語)は/opt/vc/src/hello_pi/hello_audio/
にあります。
ちなみにこのプログラムはALSAではなくopenMAXというAPIを使っています。
著作権者はBroadcom Europe Ltd、ライセンスは3条項BSD(で合ってるよね?)なのでありがたく使わせてもらいます。
サンプルプログラムではビット深度が16bitまたは32bitとなってます。
RaspberryPiのHDMI出力は24bitとなっているので下位の8bitは切り捨てられていると思われます。
サンプルプログラムがバグってる?
サンプルプログラムをmakeして実行ファイルを作って8ch出力を試します。私が試した結果では「マランツ」のAVアンプでは8ch出力できるのに、「SONY」「YAMAHA」のAVアンプでは8ch出力できません(pi0w、pi2、pi3の場合。pi4は8ch出力できる)。いろいろ試した結果、ChマッピングのLEFをCSに変えると8ch出力できるようになりました。他のメーカーのAVアンプは試してないのでわかりません。openMAXに詳しい方がいたら教えて下さい
// pcm.eChannelMapping[3] = OMX_AUDIO_ChannelLFE;
pcm.eChannelMapping[3] = OMX_AUDIO_ChannelCS;
サンプルプログラムを修正する
CannelMappingの修正以外にやったこと
出力をHDMI 8ch、bitdepthを32bitに決め打ちしました(私がそれ以外のフォーマットを必要としないので)。
バッファにテスト信号をコピーしている部分をfreadで標準入力からデータを読み込むようにしました。
これだけでサンプルプログラムが実用になるプログラムになります。
githubに上げてみた
https://github.com/assi-dangomushi/hdmi_play
githubも初めて使うのでqiitaの記事を調べながら登録してみました。
最初にライブラリをコンパイルしておいてください。
makeすれば実行ファイル"hdmi_play.bin"が出来上がるのでパスの通った場所にコピーします。
cd /opt/vc/src/hello_pi/libs/ilclient/
make
cd ~
git clone https://github.com/assi-dangomushi/hdmi_play.git
cd hdmi_play
make
sudo cp hdmi_play.bin /usr/bin/
使い方
このプログラムはALSAではないので、余計な出力を避けるために/boot/config.txt
でaudioを無効にしておいたほうが良いです。
# dtparam=audio=on
コマンドライン引数はサンプリングレートのみです。データは標準入力から読み込みます。
データは32bit符号付き整数、リトルエンディアン、8個(8ch分)のデータで1サンプル分です。
linux の音声ソフトは標準入出力に対応したものが結構あります。
sox、aplay、arecord、mpd、bruteFIRなど
入力フォーマットが決め打ちなので出力側でこれに合わせて変換する必要が有ります。
使用例
sox 8chの音声ファイル -t s32 -r 96000 - | hdmi_play.bin 96000
AVアンプの設定はstraightとかDirectとか、HDMIからの入力をサラウンド処理しないでそのまま再生するように設定して下さい。
問題点
何故かpi4とそれ以外でchが入れ替わる。
原因不明。個人で使う分には気をつけていればよいが、公開するプログラムとしてはいかがなものか。機種を判別してchの順序を統一するべきだろう。
pi0w pi2B pi3B の順序
Lf, Rf, Lfe, Cf, Ls, Rs, Lb, Rb
pi4B の順序
Lf, Rf, Lb, Rb, Cf, Lfe, Ls, Rs
pi3B+は持っていないので確認できません。
AVアンプによってはHDMIから音声信号を受けて再生し始めるのに時間がかかる。
このため、一曲ごとにhdmi_play.binを起動すると曲の頭が欠けてしまう。
これを避けるためにはhdmi_play.binを起動し続けて名前付きパイプからデーターをリダイレクトするようにすれば良い。ただし複数ソフトからデータが送られると正常に再生できない。
hdmi_play.bin 自身を複数起動すると正常に再生できない。
サービスとしてsystemdから起動したほうが良いのだろう。
まとめ
- Raspberry PiからHDMIにLPCM8ch出力(96kHz 24bit)は簡単に実現できるよ。
- 残念な出来だが実用になるプログラムをgithubに上げてみた(高音質だよ!)。
- 誰かもっとマシなプログラムを作ってくれ。
追記
機種判別してpi4とそれ以外でチャンネルマッピングを統一しました(かなり無理やり)。
2020/03/08
追記2
Raspberry Pi OS 2020-08-20 からアップグレードを掛けたら音がでなくなった。 プロプラ部分に依存してるから手の施しようがない。
とりあえずアップグレードから除外するパッケージを指定して乗り切る。
次のバージョンからは最初から音がでなくなりそう。
sudo apt-mark hold libraspberrypi-doc raspberrypi-bootloader libraspberrypi0 libraspberrypi-bin libraspberrypi-dev
2020/11/29