【続報】Raspberry Pi 4をUSB-DACにする方法
この記事の続報です
前置き
パスワード忘れてSSH接続できない(まぬけ)ので確認できませんが、多分これsoxr有効になっていません。
どういうこと?
時間をかけて得られた結論は
という無念なもの(ログに書いてた)
蛇足だけどalsaloopがダダ重いのは独自のリサンプルメソッドを使っているかららしいです(未確認)
でもこれ、考えてみればあまり前かも。
libcompositeではUAC2を再現しているものの、その組み合わせは1通り(前述では32bit 384KHz)のみ。
思い返すと、XMOSについて調べていた時に知ったことですが、ハードウェアなUSB-DACのUAC2は全ての組み合わせが定義されているんですよね。
ソフトウェアで再現している1通りのUAC2では違うサンプルレートのデータが来たらまともに流せなくなるので、データはほぼ間違いなくリサンプルされていると思います。
(ワンチャン出入りを固定値で一致させたら有効かもしれないけれど調べていない)
そこでその処理のメソッドに音質が良いとされるSoXRを指定したつもりだったのですが先述のとおり可変サンプルレートに対応しておらず、標準の(それも低負荷と引き換えに音質があまり良くないとされる)speex-float-1 に自動的に切り替えられている様子。
ということで、規定に戻らない中でラズパイ4で動く最良の選択肢と思われるspeex-float-8を使う設定を置いていきます。
(speex-float-9〜10は負荷が強すぎて音が途切れる)
ついでにlibcompositeを卒業(?)してg_audioに戻ってもいます。あとスケジューリングはタイマーベースに設定。
ディスクイメージはないよ!ごめんね!
かわりにコピペでいけるよう少し丁寧に書き残すから許して!
※OSのインストールは各自でお願いします
(Raspberry Pi OS (bullaeye)でしか試してません)
基本設定
config.txtの編集
sudo nano /boot/config.txt
内容
arm_64bit=1
arm_boost=1
#arm_freq=800
dtparam=i2c_arm=on
dtparam=i2s=on
dtparam=hdmi=off
[cm4]
otg_mode=1
[all]
dtoverlay=dwc2,dr_mode=peripheral
dtoverlay=hifiberry-dacplus
dtoverlay=disable-bt
dtoverlay=disable-wifi
start_x=0
gpu_mem=16
前回使用していたSoCの周波数制限はspeex-float-8を動かすためにコメント化して撤廃した。
アップデート、PulseAudioとインストール
アップデート
sudo apt update
sudo apt -y upgrade
インストール
sudo apt install -y pulseaudio
各種設定
modules.conf(追記)
sudo nano /etc/modules-load.d/modules.conf
内容
dwc2
g_audioもここでmodprobeしても良いが、後で書く設定でも起動するので敢えて省略した。
g_audio.sh(新規作成)
sudo nano g_audio.sh
内容
#!/bin/bash
sudo modprobe g_audio c_srate=384000 c_ssize=4 c_chmask=3 p_chmask=0
権限付与
sudo chmod +x g_audio.sh
libcomposite同様p_chmasc=0でパソコンでのキャプチャ(マイクとか)としての表示を消している。
g_audio.service(新規作成)
sudo nano /etc/systemd/system/g_audio.service
内容
[Unit]
Description=do something
[Service]
ExecStart=/usr/bin/bash /home/pi/g_audio.sh
[Install]
WantedBy=multi-user.target
serviseの再読込と有効化
sudo systemctl daemon-reload
sudo systemctl enable g_audio.service
/home/pi/g_audio.shのpiはユーザー名に合わせる。
再起動
sudo reboot
PulseAudioの設定
default.pa(置換)
sudo nano /etc/pulse/default.pa
内容
#!/usr/bin/pulseaudio -nF
.fail
### Automatically restore the volume of streams and devices
load-module module-device-restore
load-module module-stream-restore restore_device=false
load-module module-card-restore
### Automatically augment property information from .desktop files
### stored in /usr/share/application
load-module module-augment-properties
### Should be after module-*-restore but before module-*-detect
load-module module-switch-on-port-available
### Load audio drivers statically
### (it's probably better to not load these drivers manually, but instead
### use module-udev-detect -- see below -- for doing this automatically)
load-module module-alsa-sink device=hw:0,0
load-module module-alsa-source device=hw:1,0
load-module module-loopback adjust_time=0
### Automatically load driver modules depending on the hardware available
.ifexists module-udev-detect.so
load-module module-udev-detect
.else
### Use the static hardware detection module (for systems that lack udev support)
load-module module-detect
.endif
### Automatically connect sink and source if JACK server is present
.ifexists module-jackdbus-detect.so
.nofail
load-module module-jackdbus-detect channels=2
.fail
.endif
### Load several protocols
.ifexists module-esound-protocol-unix.so
load-module module-esound-protocol-unix
.endif
load-module module-native-protocol-unix
### Automatically restore the default sink/source when changed by the user
### during runtime
### NOTE: This should be loaded as early as possible so that subsequent modules
### that look up the default sink/source get the right value
load-module module-default-device-restore
### Make sure we always have a sink around, even if it is a null sink.
load-module module-always-sink
### Honour intended role device property
load-module module-intended-roles
### Automatically suspend sinks/sources that become idle for too long
load-module module-suspend-on-idle
### If autoexit on idle is enabled we want to make sure we only quit
### when no local session needs us anymore.
.ifexists module-console-kit.so
load-module module-console-kit
.endif
.ifexists module-systemd-login.so
load-module module-systemd-login
.endif
### Modules to allow autoloading of filters (such as echo cancellation)
### on demand. module-filter-heuristics tries to determine what filters
### make sense, and module-filter-apply does the heavy-lifting of
### loading modules and rerouting streams.
load-module module-filter-heuristics
load-module module-filter-apply
### Make some devices default
set-default-sink alsa_output.hw_0_0
set-default-source alsa_input.hw_1_0
省略したいけど変に消したりコメント化したりすると動作が不安定になりがちなので、置き換えるか
load-module module-alsa-sink device=hw:0,0
load-module module-alsa-source device=hw:1,0
load-module module-loopback adjust_time=0
だけを編集することを推奨
set-default-sink alsa_output.hw_0_0
set-default-source alsa_input.hw_1_0
は指定しなくてもconfig.txtで内蔵オーディオデバイスを動かしていないので問題なく動く。
deamon.conf(置換)
sudo nano /etc/pulse/daemon.conf
内容
lock-memory = yes
cpu-limit = no
high-priority = yes
nice-level = -11
realtime-scheduling = yes
realtime-priority = 5
resample-method = speex-float-8
avoid-resampling = false
enable-remixing = no
flat-volumes = no
default-sample-format = s32le
default-sample-rate = 384000
alternate-sample-rate = 38400
default-sample-channels = 2
default-channel-map = front-left,front-right
再読込
pulseaudio --kill
pulseaudio --start
音量制限(85%)
pacmd set-source-volume @DEFAULT_SOURCE@ 0xD999
その他設定
swap無効化
sudo dphys-swapfile swapoff
sudo systemctl stop dphys-swapfile.service
sudo systemctl disable dphys-swapfile.service
システム設定
sudo raspi-config
自動ログイン
システムドライブへの書込禁止
あとがき
走り書きしました!
例によりなんの保証もサポートもありません!
いそぎご報告まで