見出し画像

Raspberry Piを384KHz/32bitのUSB DAC化カスタム

設定を少しだけ解説したまとめ記事をアップしました

サンプルのディスクイメージは新しい記事にあります

まえがき

2週間くらい前にさまざま記事のお知恵を拝借してたどり着いたのが下記記事の96KHz/32bitのハイレゾ対応USB DAC化。

なんとか当初の目標のApple Music上限サンプルレートである192KHz/24bitに対応させたくて頑張りました!
目標を通り越し設定通り384KHz/32bitまで行けそうな勢いです!(タイトル詐欺ですが再生環境がないので試していない)
まだ細かな調整がしきれていない感もありますが、前回に比べると多少は洗練されたかとも思います笑笑

ダウンロード

「細けぇことなんざいいんだよ!さっさとブツを寄越しな!」なせっかちさん・・・嫌いじゃないかな笑笑

ほらよ、もっていきな!

ご注意
自己責任でお願いします
再配布はご容赦ください

最新→raspiod_015.img.xz (696.4MB)
軽量→raspiod_016.img.xz (608.8MB)

Raspberry Pi 4専用(3以下はOTG非対応)
手元の環境では192KHz/24bitまでしか動作を確認していませんが、もしより高レートでの確認がとれりしたら教えていただければ大満足です!
(015のbookworm 64bitと違い016はbullseye 32bitですがほぼ同設定でより省スペースです)

だいたいの仕様

想定のインストーラー=balenaEtcher(解凍せずにいけます)
015のイメージサイズ=4.03GB(あましている4GBのmicroSDに収まるかも
016のイメージサイズ=2.96GB(015が収まらなかったとき用)
主な再生テスト環境=iPhone 15 Pro、Raspberry Pi 4(4GB)、msBerryDAC(HPA実装済)
動作=384KHz/32bit設定、soxrによるリサンプリング、swapさせずOverlay File Systemでの読取専用化によるroot保護で電源ブツ切りに対応したつもり(起動中に切るのは良くない)

目次


使ったもの

前回とほぼ同じです。変更はUAC2に対応していなかったアイソレーターを省いたことくらい。

  • Raspberry Pi 4(4GBモデルですが、1GBモデルでもいけそう)

  • ラズパイ用電源(推奨)
    ※電源に繋いだMacbook Proの給電能力でラズパイが起動するところまでは確認してますがスマホからはほぼ無理かと(というかUSBの設定でスマホで消費電力警告でないようにしているので、スマホのバスパワーによる動作はどうなっても知りません)

  • MacBook Pro(主に設定、Intel入ってる古いやつ)

  • iPhone(14〜15で主に試聴、実際に使う機会が多いであろうことから)

  • microSDカード(4GB)

  • SDカードリーダー

  • Raspberry Pi OS

  • USB Type-Cケーブル(デバイス接続用)
    ※ホストとの接続はType-Aのポートではなく、通常は給電に使うType-Cポートを使います。AはOTGに対応しておらず動きません

  • V+の配線を切断したUSB延長ケーブル(ラズパイ直給電しない場合推奨)
    ※ラズパイ直給電+Type-Cケーブルで繋いでも特に不具合なく動きましたが、安全に利用できるか否かの確認が取れず、回路的に(?)も気持ち悪いので

  • i2sサウンドボード(好き好きで)

  • i2sサウンドボード用電源(お好みで)

  • ラズパイのケースとか放熱板とか(裸族も可)

実際の設定

細かな説明は省いて実装状況を掲載します(記述はここで最初に公開したraspiod_010あたりの内容で、ダウンロードされるものとは違うところがあります)
よりスマートな実装方法をご存知ならご教示いただけたら嬉しいです。

OSのインストールとアップデート

インストールはbalenaEtcherで簡単にできます。使い方は省略します。

アップデートリストのアップデート

sudo apt update

このとき「bullseye InRelease' changed its 'Suite' value from 'stable' to 'oldstable'」とか出てきたら下記も実行

sudo apt update --allow-releaseinfo-change

実際のアップデート

sudo apt -y upgrade

ついでに今回使うモジュールのインストール

sudo apt install -y pulseaudio

初期設定

主にハード寄りの設定を行います

config.txtの編集

sudo nano /boot/config.txt

内容は下記のような感じで追記したりコメントアウトしたり

# For more options and information see
# http://rpf.io/configtxt
# Some settings may impact device functionality. See link above for details

#Uncomment out when using the 64-bit version.
#arm_64bit=1

#uncomment to overclock the arm. 700 MHz is the default.
#arm_freq=800

# Uncomment some or all of these to enable the optional hardware interfaces
dtparam=i2c_arm=on
dtparam=i2s=on
#dtparam=spi=on

# Enable audio (loads snd_bcm2835)
#---dtparam=audio=on

[cm4]

[pi4]
# Run as fast as firmware / board allows
arm_boost=1

[all]
dtoverlay=dwc2,dr_mode=peripheral
dtoverlay=hifiberry-dacplus
dtoverlay=disable-audio
dtoverlay=disable-wifi
dtoverlay=disable-bt
dtoverlay=disable-hdmi
# dtoverlay=disable-bcmgenet

ご愛用のi2s_DACサウンドボードに合わせてドライバの記載を変更したりしてください(dtoverlay=hifiberry-dacplusの箇所)
あと使わなそうなBluetoothとかHDMIポートとか止めてます。HPAの実装によってはmsBerryDACの場合は誘導ノイズが乗るのでwifiも止めてます。

dwc2とlibcompositeのモジュール登録

sudo nano /etc/modules-load.d/modules.conf

下記を追記

dwc2
libcomposite

なお/boot/cmdline.txtにmodules-load=で追記する方法はレガシーで非推奨のようです。

libcompositeの設定

本当はスクリプトを別ファイルにして実行したいのですが、内容は同じなのになぜかうまく動かせずにrc.localに書きました。圧倒的理解不足ですね(rc.localへの記述はレガシーで非推奨のようです)

sudo nano /etc/rc.local

最下行のexit 0の上あたりに下記を追記

#!/bin/bash
mkdir -p /sys/kernel/config/usb_gadget/g2
cd /sys/kernel/config/usb_gadget/g2

echo 0x1d6b > idVendor
echo 0x0104 > idProduct
echo 0x0100 > bcdDevice
echo 0x0200 > bcdUSB

mkdir -p strings/0x409
echo "0000000001" > strings/0x409/serialnumber
echo "so-en-oj" > strings/0x409/manufacturer
echo "RasPiOD_Product" > strings/0x409/product

mkdir -p configs/c.1/strings/0x409
echo "rasPi_USB_Audio" > configs/c.1/strings/0x409/configuration
echo 10 > configs/c.1/MaxPower

mkdir -p functions/uac2.0
echo 384000 > functions/uac2.0/c_srate
echo 3 > functions/uac2.0/c_chmask
echo 4 > functions/uac2.0/c_ssize
echo 0 > functions/uac2.0/p_chmask

ln -s functions/uac2.0 configs/c.1
ls /sys/class/udc > UDC

exit 0

なぜ一般的なg_audioではなくlibcompositeなのかについて疑問に思う方もいらっしゃるかもしれません。おそらくここは96KHzの壁にぶち当たる多くの人の第一の関門です。
これには確証はありません。検索に検索を重ねた結果見えてきたことですが、恐らくg_audioにはUAC1仕様(96KHz/24bit上限)とUAC2仕様(それ以上可)があると思われます。断定はできていませんが今回使用したRaspberry Pi OS Liteのg_audioは前者の可能性が高いと判断しました。
g_audioの仕様変更はカーネルのビルドを伴う大変難易度の高いものだったので諦めざるを得ず、第二選択肢のlibcomposite一択となった次第です。

PulseAudioの設定

真っ先にインストールしていた再生担当であるPulseAudioの設定を行います。
それぞれの設定ファイルは#や;でコメント化されている行が多くありますが、記号を外したり追記したりします。

常駐プログラムの設定

sudo nano /etc/pulse/daemon.conf

設定内容を下記のようにします(抜粋)

; enable-shm = yes
; enable-memfd = yes
; shm-size-bytes = 0
lock-memory = yes
cpu-limit = no

high-priority = yes
nice-level = -11

; realtime-scheduling = yes
; realtime-priority = 5

flat-volumes = no

default-sample-format = s32le
default-sample-rate = 384000

; default-fragments = 4
; default-fragment-size-msec = 15

デフォルトモジュールやデバイスの指定

sudo nano /etc/pulse/default.pa

設定内容を下記のようにします(抜粋)

load-module module-alsa-sink device=hw:0,0
load-module module-alsa-source device=hw:1,0

load-module module-loopback

### Automatically load driver modules depending on the hardware available
#.ifexists module-udev-detect.so
#load-module module-udev-detect tsched=0
#.else
### Use the static hardware detection module (for systems that lack udev suppor>
#load-module module-detect
#.endif

set-default-sink alsa_output.hw_0_0
set-default-source alsa_input.hw_1_0

この辺りは環境により設定が変わるかもしれません。
aplay -l && arecord -lなりpacmd list-sinks | grep name:なりpacmd list-sources | grep name:なりで確認してください。

自動ログイン設定
PulseAudioの一通りの設定をしましたが、このままでは電源ONだけでは音が出ずSSH接続して音が出るという状況でした。
そんなことをせずとも音を出すために電源ONだけで内部で自動ログインするようにしてます。

sudo raspi-config

これを実行すると青いメニュー画面が出てくるので、次の手順で進めてください。タイミングよく再起動もできます。

1 System Options → S5 Boot / Auto Login → B2 Console Autologin → <Finish> → <Yes>(再起動)

ここでもなぜ一般的なalsaloopではなく、わざわざPulseAudioをインストールして設定するのかと疑問に思うかもしれません。そう、ここは恐らく第二の壁です。
topしてみてわかったことですがalsaloopはリソースを多量に消費してるっぽい。それが先述のg_audioの動作を圧迫している説もあるかもと思ってしまうほどです。

alsaloopの稼働状況

こんな余裕のないモジュールに96KHzを超える再生を任せるのは無理があるというもの。ということで代替を探して出てきた候補のひとつがPalseAudioでした(もうひとつはJACK2でしたが設定がわからなすぎた)

動作確認

ちょうどよく再起動できたので動作確認してみてください。再生できなければ設定が環境に合っていないかもしれないので、自力で調べてなんとかしてください。
解決するまでは決して次に進まないでください。
そして私には解決を聞かないでください。わかりませんって!

システム保護

いちいちログインしてからのpoweroffなんてやっていられないので電源ブチ切りたい。なので少しでもシステムファイルを保護するための対策をしました。
この手順を進めたら解除しない限り設定の変更はできなくなります。

スワップの無効化

sudo systemctl stop dphys-swapfile.service
sudo systemctl disable dphys-swapfile.service
sudo rm -rf /var/log

システムの読取専用化

sudo raspi-config

これを実行すると青いメニュー画面が出てくるので、次の手順で進めてください。タイミングよく再起動もできます。

4 Performance Options → P3 Overlay File System → <Yes> → <Ok> → <Yes> → <Ok> → <Finish> → <Yes>(再起動)

再起動後は設定の編集はできません。
試しにSSH接続でログインし、適当にファイルをtouchしてrebootしてみたら消えていたのでちゃんと機能していることが確認できます(たぶん)

更新履歴と問題点

数字はバージョンなんて崇高で管理されたものではなくて、単に試行錯誤(はじめからやり直し)の回数です笑笑
そう、前の記事からここまでの間には002〜009までのやり直しがあったりします。。

  • raspiod_010(公開終了)
    【記事の内容】
    短い間隔でプチプチとノイズのように途切れることがある(ある程度連続して稼働させ続けると比較的安定する・・・?)。これはpulseaudioがデータを送信するときの標準仕様がタイマースケジューリングと呼ばれるものが関係しているのかもしれない。というのもfragmentsの設定をしても全く反映されないので。。。

  • raspiod_011(未公開)
    タイマースケジューリングをオフにしてみた。こうすることでfragmentsの設定が反映され、予想通りプチプチ軽減に効果があった様子(ただし遅延する)ちょうどよさそうな設定の組み合わせを探しているところだが、ひとつ大きな問題が。。なぜか数分おきに1秒くらい途切れる謎。

  • raspiod_012(未公開)
    タイマーベースのスケジューリングの問題か、libcompositeの問題かはわからないけど設定を192KHzにすると安定すること、384KHzより大きくすると動作が不安定になることを発見。libcompositeの動作はUAC2のシミュレートなので、ハードウェア的な限界なのかも?リソースは余裕あるように見えるのだが、、、

  • raspiod_013(公開終了)
    スケジューリング問題とか関係なかったかも。ちょうど010の安定版的な仕上がりになったので公開(気分的にOSを"推奨"の32bitに戻した)
    音源によっては若干の歪みを感じるかも、時々チチッてノイズを感じる。あとなぜかホストのプレーヤーの反応が鈍くなることがある。
    ついでにsoxrでのリサンプリングを有効化。ソースが44.1KHzだろうが192KHzだろうが(強制的に)リサンプリングの様子。

  • raspiod_014(未公開)
    013でも時々途切れることがある様子なので、その考え方で割り込みスケジューリングにしてみたら割と好調。多少の遅延はあるけどプレーヤーが重たくなることもなし。これから設定する人はタイマーベースをオフにしてみるといいかもね。

  • raspiod_015(公開中)
    014がなかなか良かったのでOSも最新のbookwormにしてみた(32bitの推奨が外れたので再度64bitにした)。ようやく非推奨のrc.localから完全卒業してlibcompositeの設定をスクリプトに記述した。dwc2もlegacyされているけどdwc-otgはホスト役に全振りしているらしいので仕方なくdwc2で設定。
    【問題点①】384000Hzで設定しているはずなのに352800Hz(44.1KHz×8)のデバイスとして認識される=ドライバの問題?(これはPulseAudioのコマンドで確認した値でMacbookでの表示は384KHzとなる)(384KHzで再生確認したいが音源がない)
    【問題点②】iPhoneでは問題ないがMacbookだとノイズが入り、またflat-volumesの設定が無効になる

  • raspiod_016(公開中)
    015が目標の4GBをギリ超えてしまったので代替品として用意した軽量版。ひと世代前のbullseye 32bitベースなのとサイズダウンを頑張った以外、内容は015とほぼ同一(bookwormはOverlay File Systemの挙動が少し違う気がする)

  • raspiod_017?(未定)
    調べによるとDACチップ内部でオーバーサンプリングされる際オーバーシュートアンダーシュートがクリッピングされる例があるようなので回避のためsinkの標準ボリュームを90%に設定
    現状DACが常に有効なので、再生終了後(無音)時にノイズが入ることがある。再生状況によりDACの有効無効を切り替える設定があればしたい。

謝辞

ディスクイメージの作成には、今回使っているi2s_DAC「msBerryDAC」の設計者でもあるnabeさんの記事を参考にしています。お手軽な方でやっているためか結構大きいサイズになってしまっていますが、、、
そのほか国内外問わず数えきれないくらい様々な記事を拝読させていただきましたが、あまりにも膨大だったので紹介は控えさせていただきます。というかスミマセン、どこのどのタイミングでどの記事を読んだのかを正しく覚えていなくて汗

でも先駆者の方々のお知恵には頭が下がるばかりです。本当に感謝しています。記事の作成、公開をありがとうございます!

この記事が気に入ったらサポートをしてみませんか?