Raspberry Pi でHDMI音声出力(LPCM 8ch 96kHz 24bit)

Qiitaに書いた記事の焼き直しです。

目次

はじめに

時は2015年、私は自作スピーカーと市販のチャンネルデバイダを使っていました。 そこそこ満足できる音はでていたものの、高価で調整ソフトがブラックボックス、かゆいところに手が届かない。 そんなわけで安価で自由に設定できるPCによるマルチアンプシステムに移行しようと考えました。 安価なマルチアンプシステムを組むのにはHDMI+AVアンプが最適です。 アンプが1台で済むし、ボーリュームコントーロールもリモコンでできます。

ちょうどその頃 Raspberry Pi2 が発売になりました。初代に比べて4coreになり格段に処理能力が増えています。 これなら「FIRフィルタを使ったチャンデバ」が安価に実現できる!とよく調べもしないで購入してしまいました。

問題点

Raspberry Pi は初代からハードウェア的にはHDMIからLPCM・8ch・96kHz・24bitで出力できます。 しかし初代が発売されてから数年がたっても(2015年頃)HDMIからの8ch出力はできませんでした。 ネットで調べても成功したと言う情報はありませんでした。
2022年現在では8ch・48kHzで出力できるようになりましたが、16bitまでに制限されています。 RaspberryPiのハードウェアの仕様はオープンにされていないので能力を活かせないのです。

Raspberry Piの利点は安価・簡単に入手できることでしたが、2022年8月時点では品薄で入手困難となっています。 マルチアンプのために新規にRaspberryPiを購入するのはお勧めとは言い難くなってます。
2万円程度で購入できる普通のminiPCのほうが簡単です。

公式のサンプルプログラム

実は初代RaspberryPiから既にHDMIからLPCM・8ch・96kHz・24bitで出力できるサンプルプログラムが付属してます。 ただしALSAからではなくOpenMAXという規格でライブラリのソースコードは公開されていません。 サンプルプログラムは以下のディレクトリにありました(過去形)。 /opt/vc/src/hello_pi/hello_audio/

/opt/vc/ はRaspberryPi OS から消されてしまいましたが、 https://github.com/raspberrypi/firmware にあります(32bit版のみ)。

そうだ、プログラムを作ろう!

ライブラリはプロプライエタリですが、サンプルプログラム自体は改変・再配布自由のライセンスです。 サンプルプログラムを改造すればどうにかなるかもしれません。 プロのエンジニアに依頼する?そんなお金はありません。
自分でどーにかするしかありません

C言語じゃん

サンプルプログラム
audio.c
どこからどー見てもC言語で書かれています。しかも426行(ライセンス表記含む)もあります。 C言語は上級者向けで素人が手を出してもろくなことはなさそうなイメージです。 私はエンジニアでもプログラマでもありません。なんとかできるのか? ありがたいことにネット上にはC言語の入門サイトが数多くあるのでそれを見ながらなんとかしていきます。

バッファにデータを入れているところを探す

main関数から読んでいきます。 最初にコマンドライン引数から出力先・サンプリングレート・ch数・bitdepthを設定してます。これをHDMI・8ch・32bit決め打ちにしてサンプルレートのみコマンドライン引数から設定するように変更します。

出力しているのは play_api_test という関数のようです。 この関数の中を見ていきます。

for文で5秒間のループを回しているのをwhileの無限ループに変更します。

出力しているのは
ret = audioplay_play_buffer(st, buf, buffer_size);

この手前でforループでポインタを使ってバッファにテスト信号を書き込んでいるようです。

標準入力から読み込むように変更

C言語入門サイトを検索して標準入力からバッファに読み込む命令を探します。

なるほど、fread を使えば良さそうです。

テスト信号の読み込みを削除して
ret_n = fread(p,sizeof(int32_t),BUFFER_SIZE_SAMPLES * 8, stdin);
とします。

ChannelMapping 変更

サンプルプログラムのバグでAVアンプのメーカによって出力できないのを修正、Pi4とそれ以外でChannelMappingが変わってしまうのを無理やし修正して完成です。

インストール法

OSのインストール

Raspberry Pi OS Lite をmicroSDカードにインストールします。 64-bit 版では動きません。 Ubuntu でも動きません。 32bit版のRaspberry Pi OS にしてください。
with desktop でも動作すると思いますが試してません。

/opt/vc をコピー してライブラリのパスを通す

git clone --depth 1 https://github.com/raspberrypi/firmware.git
sudo rsync -av firmware/opt /
#rm -rf firmware
sudo sh -c "echo '/opt/vc/lib' > /etc/ld.so.conf.d/00-vmcs.conf"
sudo ldconfig

サンプルプログラム make

cd /opt/vc/src/hello_pi/libs/ilclient
make

hdmi_play2 をインストール

git clone https://github.com/assi-dangomushi/hdmi_play.git
cd hdmi_play
make
strip hdmi_play2.bin

出来上がった hdmi_play2.bin をパスが通った場所にコピーします。

使い方

標準入力から「32bit int LittleEndian 8ch」の音声データを受取り、指定したサンプリングレートでHDMIに出力します。 音声のフォーマットは決め打ちですのでAVアンプは7.1ch対応のものを使ってください。5.1chまでだと勝手にmixされてしまいます。

入力データは32bitですが、下8bitは切り捨てて24bitのデータをHDMIに送っていると思われます(HDMIの規格は24bitまでになってるので)。

32bit int、8chの音声を出力するプログラムとパイプでつないで使ってください。 chrtで優先度を上げるのがおすすめです。 aplay、sox、bruteFIR などは標準出力に対応してます。

32bit8chの音声を出力するプログラム | hdmi_play2.bin 44100

ChannelMapping
0 : LF
1 : RF
2 : LB
3 : RB
4 : CF
5 : LFE
6 : LS
7 : RS

一応pi4とそれ以外を判別してますが 環境によってChannelMappingが変わる可能性があります。 必ず確認してから使用してください。

このソフトは 無保証 なので高価なツィーターを飛ばしても責任持てません。

最後に

素人の作った酷いプログラムですが、なんとか動かすことができました。
いい音しますよ!(自画自賛)
2015年から2022年までの間にPi2からPi3、Pi4と変わりましたが我が家のオーディオシステムの中核はこのプログラムです。

もっともminiPCならこんな苦労をしなくても普通にALSAを使ってHDMI・8ch・24bitで出力できますけどね。