【続報】Raspberry Pi 4をUSB-DACにする方法

この記事の続報です

前置き

パスワード忘れてSSH接続できない(まぬけ)ので確認できませんが、多分これsoxr有効になっていません。

どういうこと?

時間をかけて得られた結論は

仕様によりPulseAudioのSoXRは可変サンプルレートに対応いていないため規定のspeex-float-1になる。

という無念なもの(ログに書いてた)

蛇足だけど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

自動ログイン

1 System Options → S5 Boot / Auto Login → B2 Console Autologin

システムドライブへの書込禁止

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

あとがき

走り書きしました!
例によりなんの保証もサポートもありません!

いそぎご報告まで

いいなと思ったら応援しよう!