Closed8

Ubuntu-22.04 on RPi4でオーディオシステムについてのメモ

kun432kun432

マイクとスピーカーは以下。

バッファロー BUFFALO PC用スピーカー USB電源コンパクトサイズ ホワイト BSSP105UWH
https://www.amazon.co.jp/dp/B07ZCYB9D5

DUNGZDUZ USB Microphone for Laptop and Desktopノートパソコン・デスクトップ用USBマイク
https://www.amazon.co.jp/dp/B0CNVZ27YH

スピーカーはオーディオジャック、マイクはUSBで接続している。

オーディオデバイスの確認

sudo apt update
sudo apt install -y alsa-utils

出力デバイスの確認

aplay -l
出力
**** List of PLAYBACK Hardware Devices ****
card 0: b1 [bcm2835 HDMI 1], device 0: bcm2835 HDMI 1 [bcm2835 HDMI 1]
  Subdevices: 4/4
  Subdevice #0: subdevice #0
  Subdevice #1: subdevice #1
  Subdevice #2: subdevice #2
  Subdevice #3: subdevice #3
card 1: Headphones [bcm2835 Headphones], device 0: bcm2835 Headphones [bcm2835 Headphones]
  Subdevices: 4/4
  Subdevice #0: subdevice #0
  Subdevice #1: subdevice #1
  Subdevice #2: subdevice #2
  Subdevice #3: subdevice #3

入力デバイスの確認

arecord -l
出力
**** List of CAPTURE Hardware Devices ****
card 2: Device [USB PnP Sound Device], device 0: USB Audio [USB Audio]
  Subdevices: 1/1
  Subdevice #0: subdevice #0

再生の確認

aplay /usr/share/sounds/alsa/Front_Center.wav

何も聞こえない。出力デバイスのデフォルトがどうやらHDMIの方になっているようなので、デバイスを明示的に指定する。

aplay -D plughw:1,0 /usr/share/sounds/alsa/Front_Center.wav

こちらは問題なく聞こえた。

録音の確認。5秒間録音する。入力デバイスもデフォルトが存在していないため、こちらも明示的にデバイスを指定する。

arecord -D plughw:2,0 -d 5 test.wav
aplay -D plughw:1,0 test.wav

録音した内容が聞こえればOK。

再生・録音デバイスのデフォルト設定を行う。~/.asoundrc もしくは /etc/asound.conf に設定する。今回は ~/.asoundrc に。

~/.asoundrc
# 再生用デバイスの定義
pcm.playback {
  type plug
  slave.pcm "hw:1,0"
}

# 録音用デバイスの定義
pcm.capture {
  type plug
  slave.pcm "hw:2,0"
}

# default を asym (playback + capture) にマップ
pcm.!default {
  type asym
  playback.pcm "playback"
  capture.pcm  "capture"
}

これでデバイス指定不要で使える。

arecord -d 5 test.wav
aplay test.wav

ステレオのテスト

speaker-test -c2 -twav

以下のように左右のスピーカーからそれぞれ聞こえてくればOK。

出力

speaker-test 1.2.6

Playback device is default
Stream parameters are 48000Hz, S16_LE, 2 channels
WAV file(s)
Rate set to 48000Hz (requested 48000Hz)
Buffer size range from 480 to 32768
Period size range from 480 to 32768
Using max buffer size 32768
Periods = 4
was set period_size = 8192
was set buffer_size = 32768
 0 - Front Left
 1 - Front Right
Time per period = 2.403406
 0 - Front Left
 1 - Front Right
Time per period = 3.069295
 0 - Front Left
 1 - Front Right
Time per period = 2.900497
 0 - Front Left
 1 - Front Right
Time per period = 3.069938
 0 - Front Left

ミキサーでボリュームなどの設定

amixer

HDMIが選択されている。

出力
Simple mixer control 'HDMI',0
  Capabilities: pvolume pvolume-joined pswitch pswitch-joined
  Playback channels: Mono
  Limits: Playback -10239 - 400
  Mono: Playback 0 [96%] [0.00dB] [on]

~/.asoundrcで設定したのは音声データの入出力(pcm)のデフォルトであって、音量はミュートなどミキサーの設定はctlで指定する必要がある。

とりあえず個別に指定する場合は-c カード番号で指定すれば良い。

スピーカー側

amixer -c 1
出力
Simple mixer control 'Headphone',0
  Capabilities: pvolume pvolume-joined pswitch pswitch-joined
  Playback channels: Mono
  Limits: Playback -10239 - 400
  Mono: Playback 31 [97%] [0.31dB] [on]

ボリュームの変更は以下のような感じで行える。

# ボリュームを50%に設定
amixer -c 1 set Headphone 50%
出力
Simple mixer control 'Headphone',0
  Capabilities: pvolume pvolume-joined pswitch pswitch-joined
  Playback channels: Mono
  Limits: Playback -10239 - 400
  Mono: Playback -4919 [50%] [-49.19dB] [on]

ミュート

amixer -c 1 set Headphone mute

offになっている

出力
Simple mixer control 'Headphone',0
  Capabilities: pvolume pvolume-joined pswitch pswitch-joined
  Playback channels: Mono
  Limits: Playback -10239 - 400
  Mono: Playback -4919 [50%] [-49.19dB] [off]

ミュート解除しつつ音声を最大に。

amixer -c 1 set Headphone 100% unmute
出力
Simple mixer control 'Headphone',0
  Capabilities: pvolume pvolume-joined pswitch pswitch-joined
  Playback channels: Mono
  Limits: Playback -10239 - 400
  Mono: Playback 400 [100%] [4.00dB] [on]

次にマイク側

amixer -c 2

マイクは2つある。

出力
Simple mixer control 'Mic',0
  Capabilities: cvolume cvolume-joined cswitch cswitch-joined
  Capture channels: Mono
  Limits: Capture 0 - 16
  Mono: Capture 0 [0%] [0.00dB] [on]
Simple mixer control 'Auto Gain Control',0
  Capabilities: pswitch pswitch-joined
  Playback channels: Mono
  Mono: Playback [on]

マイク入力のゲインやミュートについてはスピーカーとやり方は同じ。で、マイク側には自動ゲイン調整もあって、入力レベルに応じて自動でゲインを調整してくれるらしい。あと、自動ゲイン調整はON/OFFもできるみたい。

ミキサーにはalsamixerもある。こちらはTUIで確認・設定ができる。

alsamixer

F6でデバイスを切り替えて、カーソルの上下で音量を変更できる。

kun432kun432

サウンドサーバ。ALSAとサウンドサーバの関係性は以下がわかりやすい。

https://mickey-happygolucky.hatenablog.com/entry/2015/04/04/105512

https://mickey-happygolucky.hatenablog.com/entry/2019/08/30/125038

https://wiki.ubuntulinux.jp/UbuntuStudioTips/Setup/UbuntuSoundSystem

ということで、o4-miniによると、Linuxの主なサウンドサーバには以下のようなものがある。

  • PulseAudio
    • 主な用途: 一般的なデスクトップ再生・録音
    • レイテンシ: 中程度(約10~30ms)
    • 互換性: ALSA クライアント多数、PulseAPI 依存アプリ広く対応
    • ルーティング: シンプルなシンク/ソース切替、仮想デバイス作成可
    • ネットワーク機能: RTP ストリーミング、module-raop(AirPlay)対応
    • Bluetooth: A2DP/LE、HSP/HFP(module-bluetooth)
    • 設定: GUI(pavucontrol)やシンプル設定ファイル
    • 備考: Ubuntu 22.04 標準、PipeWire へ移行中
  • PipeWire
    • 主な用途: オーディオ&ビデオの統合管理、低レイテンシ/高機能
    • レイテンシ: 低(設定次第で5ms以下も可能)
    • 互換性: PulseAudio と JACK クライアント両方をネイティブサポート
    • ルーティング: ノード&ポートを自由にグラフ状に接続(qpwgraph/helvum)
    • ネットワーク機能: RTP、RAOP、Bluetooth LE など内蔵
    • Bluetooth: libspa-bluetooth 経由で A2DP/LE、HFP/HSP
    • ビデオ対応: 映像ストリームも扱える
    • 設定: 設定ファイル多め、WirePlumber でポリシー管理
    • 備考: 将来性高、Linux のメディア統合プラットフォーム
  • JACK Audio Connection Kit
    • 主な用途: プロ音響・音楽制作、リアルタイムルーティング
    • レイテンシ: 極低(1ms台を狙える)
    • 互換性: ALSA バックエンド経由で多くのアプリ対応
    • ルーティング: ケーブル接続感覚でアプリ間を細かくルーティング
    • ネットワーク機能: ネイティブなし(外部プラグインで対応可)
    • Bluetooth: なし(外部ブリッジで実装可能)
    • 設定: 設定ファイル少なめ、qjackctl で GUI 操作可能
    • 備考: DAW/ソフトシンセ用に成熟、低レイテンシ重視環境に最適

で、自分の今回の目的はPipeWireを試すことなのだけれども、どのサウンドサーバを選ぶべきか?どういうステップで学ぶべきか?をo4-miniに聞いたところ、以下のような感じだった。

サウンドサーバー層(PulseAudio/PipeWire/JACK)に絞った選択ガイドと学習ステップです。

1. どれを選ぶべきか?(用途別ガイド)

  • 一般的なデスクトップ用途
    • PulseAudio
      • デスクトップアプリの音量管理や Bluetooth が手軽
      • GUI ツール(pavucontrol)が豊富で学習コストが低い
  • Audio+Video を統合して低レイテンシ運用したい
    • PipeWire
      • PulseAudio/JACK クライアントをそのまま動かせる
      • 低レイテンシかつ映像も含むメディア処理が可能
  • プロ向け・音楽制作向けのミキシング/ルーティング
    • JACK
      • 1ms 台の極低遅延
      • ケーブル接続感覚でアプリ同士を細かくパッチベイ接続

2. 学習ステップ

  1. PulseAudio 入門
    • インストール&起動
      sudo apt install pulseaudio pavucontrol
      systemctl --user enable --now pulseaudio
      
    • GUI で体験pavucontrol を使い、アプリごとのシンク/ソース切替を試す
    • CLI 操作pactl list-sinkspactl set-default-sink などで出力先変更を練習
  2. PipeWire(on Pulse) への移行
    • ブリッジ導入
      sudo apt install pipewire pipewire-pulse wireplumber
      systemctl --user disable pulseaudio
      systemctl --user enable --now pipewire pipewire-pulse wireplumber
      
    • 確認pactl info で “Server Name: PulseAudio (on PipeWire…)” を見る
    • GUI 操作:引き続き pavucontrol で動作を確かめる
  3. PipeWire ネイティブ操作
    • ネイティブツール体験
      • pw-cli list-objectspw-top でノード確認
      • qpwgraph or helvum でグラフ上にノード&ポートを繋いでみる
    • JACK クライアントも動かすlibspa-0.2-jack を入れて、jack_simple_client 等で接続テスト
  4. JACK 入門
    • 環境構築
      sudo apt install jackd2 qjackctl
      jack_control start
      
    • GUI でパッチベイ操作qjackctl でクライアント間ルーティングを体験
    • DAW 連携:Ardour などを繋いで、複数トラックのルーティングを練習
  5. 応用:マルチサーバ運用と自動化
    • PulseAudio と JACK(あるいは PipeWire 上の JACK)を併用する方法を学ぶ
    • WirePlumber のポリシー設定で、自動接続ルールを定義してみる

ポイント

  • まずは GUI で感覚を掴む → 次に CLI/ネイティブツールへ
  • 段階的に切り替え → PulseAudio → PipeWire(on Pulse) → PipeWire ネイティブ → JACK
  • 目的に合わせた最適解を選択 → デスクトップなら PulseAudio、制作なら JACK、統合なら PipeWire

以上の流れで進めれば、各サウンドサーバの特徴と操作感をしっかり学べます。

PulseAudioは以前少し触れているけども、改めておさらいしつつ、PipeWireを試そうと思う。JACKはちょっと今回はパスで。

kun432kun432

PulseAudio

インストール

sudo apt install -y pulseaudio pulseaudio-utils pavucontrol

ユーザサービスとして起動する。enable --nowとかあるの初めて知った。

systemctl --user enable --now pulseaudio
出力
Created symlink /home/kun432/.config/systemd/user/default.target.wants/pulseaudio.service → /usr/lib/systemd/user/pulseaudio.service.
Created symlink /home/kun432/.config/systemd/user/sockets.target.wants/pulseaudio.socket → /usr/lib/systemd/user/pulseaudio.socket.

出力先(sink)の確認

pactl list short sinks
出力
0	alsa_output.platform-bcm2835_audio.stereo-fallback	module-alsa-card.c	s16le 2ch 44100HzSUSPENDED
1	alsa_output.platform-bcm2835_audio.stereo-fallback.2	module-alsa-card.c	s16le 2ch 44100HzSUSPENDED

0がHDMIで、1がヘッドフォン。

入力元(source)の確認

pactl list short sources
出力
0	alsa_input.usb-C-Media_Electronics_Inc._USB_PnP_Sound_Device-00.analog-mono	module-alsa-card.cs16le 1ch 44100Hz	SUSPENDED
1	alsa_output.platform-bcm2835_audio.stereo-fallback.monitor	module-alsa-card.c	s16le 2ch 44100Hz	SUSPENDED
2	alsa_output.platform-bcm2835_audio.stereo-fallback.2.monitor	module-alsa-card.c	s16le 2ch 44100Hz	SUSPENDED

0 が USB マイクで、1、2はsinkのそれぞれのモニターになっている。

こういう感じか。

現在の設定を確認

pactl info
出力
erver String: /run/user/1000/pulse/native
Library Protocol Version: 35
Server Protocol Version: 35
Is Local: yes
Client Index: 5
Tile Size: 65496
User Name: kun432
Host Name: rpi2
Server Name: pulseaudio
Server Version: 15.99.1
Default Sample Specification: s16le 2ch 44100Hz
Default Channel Map: front-left,front-right
Default Sink: alsa_output.platform-bcm2835_audio.stereo-fallback.2
Default Source: alsa_input.usb-C-Media_Electronics_Inc._USB_PnP_Sound_Device-00.analog-mono
Cookie: 7eda:bc6c

ALSAのデフォルトと同じく、PulseAudioでも、ヘッドフォン・USBマイクがそれぞれデフォルトになっている。PulseAudio側でデフォルトを変えたい場合は以下のようにすれば良い。

pactl set-default-sink alsa_output.platform-bcm2835_audio.stereo-fallback
pactl set-default-source alsa_input.usb-C-Media_Electronics_Inc._USB_PnP_Sound_Device-00.analog-mono

ではテスト。

PulseAudio経由で再生させるにはpaplayを使う。

paplay /usr/share/sounds/alsa/Front_Center.wav

録音はparecparecは生のPCMデータ(ヘッダなどがないrawデータ)を出力するので、WAV等にするには変換が必要になる。ここではsoxを使ってWAVファイルに変換するが、ffmpegでもよい。

sudo apt install -y sox
parec --format=s16le --rate=44100 --channels=1 | sox -t raw -r 44100 -e signed-integer -b 16 -c 1 - test.wav
paplay test.wav

あとparecordを使うと、WAVでそのまま出力できる。こっちが楽だな。

parecord --file-format=wav test.wav
paplay test.wav

上記はデフォルトのsink/sourceが使用されていたが、デバイスを指定する場合は-d/--deviceでsink/source名を指定すればいいみたい。以下のような感じ。

# paplay
paplay
    --device=alsa_output.platform-bcm2835_audio.stereo-fallback.2 \
    /usr/share/sounds/alsa/Front_Center.wav

# parec
parec \
    --device=alsa_input.usb-C-Media_Electronics_Inc._USB_PnP_Sound_Device-00.analog-mono \
    --format=s16le --rate=44100 --channels=1 \
    | sox -t raw -r 44100 -e signed-integer -b 16 -c 1 - test.wav

# parecord
parecord \
    --device=alsa_input.usb-C-Media_Electronics_Inc._USB_PnP_Sound_Device-00.analog-mono \
    --file-format=wav test.wav

上でも少し触れたが、デフォルトのsink/sourceの切り替えやボリューム調整などはpactlで行える。例えば出力ボリュームの確認・変更。

まずボリュームの確認。デフォルトsink/sourceの場合は@DEFAULT_SINK@/ @DEFAULT_SOURCE@みたい。sink/sounceのそれぞれの名前を指定、または一覧時のインデックスで指定することもできるみたい。

pactl get-sink-volume @DEFAULT_SINK@
出力
Volume: front-left: 65536 / 100% / 0.00 dB,   front-right: 65536 / 100% / 0.00 dB
        balance 0.00

50%に変更

pactl set-sink-volume @DEFAULT_SINK@ 50%
pactl get-sink-volume @DEFAULT_SINK@
出力
Volume: front-left: 32768 /  50% / -18.06 dB,   front-right: 32768 /  50% / -18.06 dB
        balance 0.00

ミュートの確認

pactl get-sink-mute @DEFAULT_SINK@
出力
Mute: no

ミュート

pactl set-sink-mute @DEFAULT_SINK@ 1
pactl get-sink-mute @DEFAULT_SINK@
出力
Mute: yes

ミュート解除

pactl set-sink-mute @DEFAULT_SINK@ 0
pactl get-sink-mute @DEFAULT_SINK@
出力
Mute: no

同じことを対話っぽくできるpacmdというのもあるがパス。

GUIの場合は、pavucontrolを使えば良いみたいなのだが・・・

pavucontrol
出力
(pavucontrol:5606): Gtk-WARNING **: 06:41:48.851: cannot open display:

これはデスクトップ環境もしくはX11フォワーディングが必要にある・・・

TUIでできるものに ncpamixer というのがあるみたい。ただこれはパッケージがないので、ビルドする必要がありそう。

https://github.com/fulhax/ncpamixer

なお、上でいろいろPulseAudioの設定を変更しているが、これらはランタイムのみ有効で再起動するとリセットされるみたい。設定の永続化は、ユーザサービスの場合は ~/.config/pulse/default.pa を使うのが良さそう。/etc/pulse/default.paはシステム全体となる。


ncpamixer試してみた

git clone https://github.com/fulhax/ncpamixer && cd ncpamixer
sudo apt install -y build-essential cmake libncurses-dev libpulse-dev pandoc
make USE_WIDE=True
./build/ncpamixer

自分の環境はキーボードショートカットがあまり動かないのだが、マウスクリックは動く様子。


PulseAudioの少し凝った使い方

エコーキャンセラーをかます
https://zenn.dev/link/comments/178283e18ab24b

マイクの低遅延モニタリング(ハウリングするのでヘッドフォン推奨)

pactl load-module module-loopback \
  source=alsa_input.usb-C-Media_Electronics_Inc._USB_PnP_Sound_Device-00.analog-mono \
  sink=alsa_output.platform-bcm2835_audio.stereo-fallback.2 \
  latency_msec=1

# モニタリングを止める場合
pactl list short modules | grep loopback
# ex: 以下のように出力される
# 23	module-loopback	source=alsa_input.usb-C-Media_Electronics_Inc._USB_PnP_Sound_Device-00.analog-mono sink=alsa_output.platform-bcm2835_audio.stereo-fallback.2 latency_msec=1

# 該当のモジュ―ルのインデックス番号でアンロード
pactl unload-module 23
kun432kun432

再起動してたら色々変わった。

aplay -l
出力
**** List of PLAYBACK Hardware Devices ****
card 0: Headphones [bcm2835 Headphones], device 0: bcm2835 Headphones [bcm2835 Headphones]
  Subdevices: 8/8
  Subdevice #0: subdevice #0
  Subdevice #1: subdevice #1
  Subdevice #2: subdevice #2
  Subdevice #3: subdevice #3
  Subdevice #4: subdevice #4
  Subdevice #5: subdevice #5
  Subdevice #6: subdevice #6
  Subdevice #7: subdevice #7
arecord -l
出力
**** List of CAPTURE Hardware Devices ****
card 1: Device [USB PnP Sound Device], device 0: USB Audio [USB Audio]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
pactl list short sinks
出力
0	alsa_output.platform-bcm2835_audio.stereo-fallback	module-alsa-card.c	s16le 2ch 48000Hz	SUSPENDED
pactl list short sources
出力
0	alsa_input.usb-C-Media_Electronics_Inc._USB_PnP_Sound_Device-00.analog-mono	module-alsa-card.c	s16le 1ch 44100Hz	SUSPENDED
1	alsa_output.platform-bcm2835_audio.stereo-fallback.monitor	module-alsa-card.c	s16le 2ch 48000Hz	SUSPENDED

うーん、デバイスが1つづつしかないので、デフォルトもそれっぽく動いてるけど、.asoundrcの書き方は果たしてどうすべきかぁ・・・

とりあえずこれで。

~/.asoundrc
pcm.playback {
  type plug
  slave.pcm {
    type hw
    card "Headphones"
    device 0
  }
}

pcm.capture {
  type plug
  slave.pcm {
    type hw
    card "Device"
    device 0
  }
}

pcm.!default {
  type asym
  playback.pcm "playback"
  capture.pcm  "capture"
}
kun432kun432

PipeWire

PipeWireをインストール。

  • pipewire: Core デーモン
  • pipewire-pulse: PulseAudio クライアントの互換レイヤー
  • wireplumber: セッションマネージャ。PipeWire のポリシー を管理する。
sudo apt install -y pipewire pipewire-pulse wireplumber

PulseAudioを停止して無効化

systemctl --user disable --now pulseaudio.service pulseaudio.socket
systemctl --user mask --now pulseaudio.socket

PipeWireを起動して有効化、PulseAudio APIへのブリッジも。

systemctl --user enable --now pipewire pipewire-pulse wireplumber

確認

pactl info

"Server Name"にPipeWireと表示されていればOK

出力
Server String: /run/user/1000/pulse/native
Library Protocol Version: 35
Server Protocol Version: 35
Is Local: yes
Client Index: 75
Tile Size: 65496
User Name: kun432
Host Name: rpi2
Server Name: PulseAudio (on PipeWire 0.3.48)
Server Version: 15.0.0
Default Sample Specification: float32le 2ch 48000Hz
Default Channel Map: front-left,front-right
Default Sink: alsa_output.platform-bcm2835_audio.stereo-fallback
Default Source: alsa_input.usb-C-Media_Electronics_Inc._USB_PnP_Sound_Device-00.mono-fallback
Cookie: b1fc:16a8

PipeWireのネイティブなCLIで確認

pw-cli ls Node

PipeWireでは、PipeWireが管理するあらゆる要素を「ノード」と呼ぶらしい。例えば、ハードウェアデバイス、PulseAudioブリッジ、アプリケーション、WirePlumber・media-sessionなどが作成するポリシー管理ノード、などが「ノード」にあたる。

出力
	id 28, type PipeWire:Interface:Node/3
 		object.serial = "28"
 		factory.id = "10"
 		priority.driver = "20000"
 		node.name = "Dummy-Driver"
	id 29, type PipeWire:Interface:Node/3
 		object.serial = "29"
 		factory.id = "10"
 		priority.driver = "19000"
 		node.name = "Freewheel-Driver"
	id 36, type PipeWire:Interface:Node/3
 		object.serial = "37"
 		factory.id = "10"
 		client.id = "34"
 		node.name = "Midi-Bridge"
 		media.class = "Midi/Bridge"
	id 55, type PipeWire:Interface:Node/3
 		object.serial = "56"
 		object.path = "v4l2:/dev/video14"
 		factory.id = "10"
 		client.id = "34"
 		device.id = "46"
 		node.description = "bcm2835-isp"
 		node.name = "v4l2_input.platform-bcm2835-isp.2"
 		media.class = "Video/Source"
 		media.role = "Camera"
	id 57, type PipeWire:Interface:Node/3
 		object.serial = "58"
 		object.path = "v4l2:/dev/video15"
 		factory.id = "10"
 		client.id = "34"
 		device.id = "47"
 		node.description = "bcm2835-isp"
 		node.name = "v4l2_input.platform-bcm2835-isp.3"
 		media.class = "Video/Source"
 		media.role = "Camera"
	id 59, type PipeWire:Interface:Node/3
 		object.serial = "60"
 		object.path = "v4l2:/dev/video21"
 		factory.id = "10"
 		client.id = "34"
 		device.id = "50"
 		node.description = "bcm2835-isp"
 		node.name = "v4l2_input.platform-bcm2835-isp.6"
 		media.class = "Video/Source"
 		media.role = "Camera"
	id 61, type PipeWire:Interface:Node/3
 		object.serial = "62"
 		object.path = "v4l2:/dev/video22"
 		factory.id = "10"
 		client.id = "34"
 		device.id = "51"
 		node.description = "bcm2835-isp"
 		node.name = "v4l2_input.platform-bcm2835-isp.7"
 		media.class = "Video/Source"
 		media.role = "Camera"
	id 67, type PipeWire:Interface:Node/3
 		object.serial = "68"
 		object.path = "alsa:pcm:1:hw:1:capture"
 		factory.id = "18"
 		client.id = "34"
 		device.id = "53"
 		priority.session = "2000"
 		priority.driver = "2000"
 		node.description = "PCM2902 Audio Codec Mono"
 		node.name = "alsa_input.usb-C-Media_Electronics_Inc._USB_PnP_Sound_Device-00.mono-fallback"
 		node.nick = "USB PnP Sound Device"
 		media.class = "Audio/Source"
	id 68, type PipeWire:Interface:Node/3
 		object.serial = "69"
 		object.path = "alsa:pcm:0:hw:0:playback"
 		factory.id = "18"
 		client.id = "34"
 		device.id = "54"
 		priority.session = "1000"
 		priority.driver = "1000"
 		node.description = "Built-in Audio Stereo"
 		node.name = "alsa_output.platform-bcm2835_audio.stereo-fallback"
 		node.nick = "bcm2835 Headphones"
 		media.class = "Audio/Sink"

上記のうち、以下がマイクとヘッドフォンのノード。

出力
	id 67, type PipeWire:Interface:Node/3
        (snip)
 		node.description = "PCM2902 Audio Codec Mono"
 		node.name = "alsa_input.usb-C-Media_Electronics_Inc._USB_PnP_Sound_Device-00.mono-fallback"
 		node.nick = "USB PnP Sound Device"
 		media.class = "Audio/Source"
	id 68, type PipeWire:Interface:Node/3
        (snip)
 		node.description = "Built-in Audio Stereo"
 		node.name = "alsa_output.platform-bcm2835_audio.stereo-fallback"
 		node.nick = "bcm2835 Headphones"
 		media.class = "Audio/Sink"

次に「ポート」。「ポート」は各ノードの入出力ポートを示す。つまりノード間のつながりやルーティングを確認できる。

pw-cli ls Port
出力
	id 31, type PipeWire:Interface:Port/3
 		object.serial = "70"
 		object.path = "alsa:pcm:1:hw:1:capture:capture_0"
 		format.dsp = "32 bit float mono audio"
 		node.id = "67"
 		audio.channel = "MONO"
 		port.id = "0"
 		port.name = "capture_MONO"
 		port.direction = "out"
 		port.physical = "true"
 		port.terminal = "true"
 		port.alias = "USB PnP Sound Device:capture_MONO"
	id 37, type PipeWire:Interface:Port/3
 		object.serial = "38"
 		object.path = "alsa:seq:default:client_14:playback_0"
 		format.dsp = "8 bit raw midi"
 		node.id = "36"
 		port.id = "0"
 		port.name = "Midi Through:(playback_0) Midi Through Port-0"
 		port.direction = "in"
 		port.physical = "true"
 		port.terminal = "true"
 		port.alias = "Midi Through:Midi Through Port-0"
	id 38, type PipeWire:Interface:Port/3
 		object.serial = "39"
 		object.path = "alsa:seq:default:client_14:capture_0"
 		format.dsp = "8 bit raw midi"
 		node.id = "36"
 		port.id = "0"
 		port.name = "Midi Through:(capture_0) Midi Through Port-0"
 		port.direction = "out"
 		port.physical = "true"
 		port.terminal = "true"
 		port.alias = "Midi Through:Midi Through Port-0"
	id 56, type PipeWire:Interface:Port/3
 		object.serial = "57"
 		node.id = "55"
 		port.id = "0"
 		port.name = "out_0"
 		port.direction = "out"
 		port.physical = "true"
 		port.terminal = "true"
	id 58, type PipeWire:Interface:Port/3
 		object.serial = "59"
 		node.id = "57"
 		port.id = "0"
 		port.name = "out_0"
 		port.direction = "out"
 		port.physical = "true"
 		port.terminal = "true"
	id 60, type PipeWire:Interface:Port/3
 		object.serial = "61"
 		node.id = "59"
 		port.id = "0"
 		port.name = "out_0"
 		port.direction = "out"
 		port.physical = "true"
 		port.terminal = "true"
	id 62, type PipeWire:Interface:Port/3
 		object.serial = "63"
 		node.id = "61"
 		port.id = "0"
 		port.name = "out_0"
 		port.direction = "out"
 		port.physical = "true"
 		port.terminal = "true"
	id 63, type PipeWire:Interface:Port/3
 		object.serial = "74"
 		object.path = "alsa:pcm:0:hw:0:playback:monitor_1"
 		format.dsp = "32 bit float mono audio"
 		node.id = "68"
 		audio.channel = "FR"
 		port.id = "1"
 		port.name = "monitor_FR"
 		port.direction = "out"
 		port.monitor = "true"
 		port.alias = "bcm2835 Headphones:monitor_FR"
	id 64, type PipeWire:Interface:Port/3
 		object.serial = "72"
 		object.path = "alsa:pcm:0:hw:0:playback:monitor_0"
 		format.dsp = "32 bit float mono audio"
 		node.id = "68"
 		audio.channel = "FL"
 		port.id = "0"
 		port.name = "monitor_FL"
 		port.direction = "out"
 		port.monitor = "true"
 		port.alias = "bcm2835 Headphones:monitor_FL"
	id 65, type PipeWire:Interface:Port/3
 		object.serial = "73"
 		object.path = "alsa:pcm:0:hw:0:playback:playback_1"
 		format.dsp = "32 bit float mono audio"
 		node.id = "68"
 		audio.channel = "FR"
 		port.id = "1"
 		port.name = "playback_FR"
 		port.direction = "in"
 		port.physical = "true"
 		port.terminal = "true"
 		port.alias = "bcm2835 Headphones:playback_FR"
	id 66, type PipeWire:Interface:Port/3
 		object.serial = "71"
 		object.path = "alsa:pcm:0:hw:0:playback:playback_0"
 		format.dsp = "32 bit float mono audio"
 		node.id = "68"
 		audio.channel = "FL"
 		port.id = "0"
 		port.name = "playback_FL"
 		port.direction = "in"
 		port.physical = "true"
 		port.terminal = "true"
 		port.alias = "bcm2835 Headphones:playback_FL"

上記のうち、以下が、

  • マイク音声を他のノードに出力するポート
  • ヘッドフォン向けの左右2チャンネルの入力ポート

になる

出力
	id 31, type PipeWire:Interface:Port/3
        (snip)
 		node.id = "67"
        (snip)
 		port.name = "capture_MONO"
 		port.direction = "out"
        (snip)
	id 65, type PipeWire:Interface:Port/3
        (snip)
 		node.id = "68"
        (snip)
 		port.name = "playback_FR"
 		port.direction = "in"
        (snip)
	id 66, type PipeWire:Interface:Port/3
        (snip)
 		node.id = "68"
        (snip)
   		port.name = "playback_FL"
 		port.direction = "in"
        (snip)

再生・録音の確認。

再生はpw-playを使う。

pw-play /usr/share/sounds/alsa/Front_Center.wav

録音はpw-recordを使う。

pw-record --format s16 \
    --channels 1 \
    --rate 44100 \
    test.wav

pw-play test.wav

PipeWireを入れたときに、pipewire-pulseもインストールしてあった。

https://note.com/vsrx/n/n249632faef0b

このフレームワークは、マルチメディアルーティングとパイプライン処理を行う事ができ、Pulse AudioとJack Audio Connection KitとGStreamerの代替サーバを含んでいます。つまり、PipeWireを導入する事でPulse AudioとJackとGStreamerが持つ機能をひとまとめにして管理し易くなります。

これで、PipeWireでPulseAudioの互換インタフェースが提供されることになる。これを確認する。

まずターミナルを立ち上げてpw-topを起動する。pw-topは現在動いているデバイスやノードの状態をリアルタイムに確認することができるツール。

pw-top

別ターミナルを開いてpaplayでWAVファイルを再生してみる。わかりやすいようにちょっと長めの音声ファイルを用意した。

paplay sample_5min.wav

どうやらPipeWire経由で再生が動いている様子。

この時、pw-cli ls Nodeを見てみると以下のようにアプリケーションがノードとして表示される。

出力
	id 69, type PipeWire:Interface:Node/3
 		object.serial = "99"
 		factory.id = "6"
 		client.id = "74"
 		application.name = "paplay"
 		node.name = "paplay"
 		media.class = "Stream/Output/Audio"

また、pw-cli ls Portにも同様に以下のポートが表示されている。

出力
	id 71, type PipeWire:Interface:Port/3
 		object.serial = "101"
 		object.path = "paplay:output_1"
 		format.dsp = "32 bit float mono audio"
 		node.id = "69"
 		audio.channel = "FR"
 		port.id = "1"
 		port.name = "output_FR"
 		port.direction = "out"
 		port.alias = "paplay:output_FR"
	id 73, type PipeWire:Interface:Port/3
 		object.serial = "100"
 		object.path = "paplay:output_0"
 		format.dsp = "32 bit float mono audio"
 		node.id = "69"
 		audio.channel = "FL"
 		port.id = "0"
 		port.name = "output_FL"
 		port.direction = "out"
 		port.alias = "paplay:output_FL"

なお、aplayでも同様。

pw-cli ls Node

出力
	id 69, type PipeWire:Interface:Node/3
 		object.serial = "111"
 		factory.id = "6"
 		client.id = "74"
 		application.name = "ALSA plug-in [aplay]"
 		node.name = "ALSA plug-in [aplay]"
 		media.class = "Stream/Output/Audio"

pw-cli ls Port

出力
	id 71, type PipeWire:Interface:Port/3
 		object.serial = "112"
 		object.path = "ALSA plug-in [aplay]:output_0"
 		format.dsp = "32 bit float mono audio"
 		node.id = "69"
 		audio.channel = "FL"
 		port.id = "0"
 		port.name = "output_FL"
 		port.direction = "out"
 		port.alias = "ALSA plug-in [aplay]:output_FL"
	id 72, type PipeWire:Interface:Port/3
 		object.serial = "113"
 		object.path = "ALSA plug-in [aplay]:output_1"
 		format.dsp = "32 bit float mono audio"
 		node.id = "69"
 		audio.channel = "FR"
 		port.id = "1"
 		port.name = "output_FR"
 		port.direction = "out"
 		port.alias = "ALSA plug-in [aplay]:output_FR"

色々見てると、ALSAに直接アクセスする場合の処理をPipeWireに横取りさせるには pipewire-audio-client-librariesパッケージが必要みたいなのだけど、上の結果だけ見てると動いてるように見えるんだけどな。自分の理解が違うんだろうか?

kun432kun432

オーディオのルーティングは、

  • CLI
    • WirePlumber
  • GUI
    • qpwgraph
    • Helvum

あたりを使うみたい。で、GUIの場合はデスクトップが必要になるのだけど、X11フォワーディングでMac側でGUIを表示してみようと思う。

Mac側でXQuartzをインストール

brew install xquartz

XQuartzを起動して、設定で以下を設定。

XQuartzの「アプリケーション」→「ターミナル」でxhosts +localhost

XQuartzのターミナルからSSHでRPiにログイン。X転送を許可しておく。

ssh -Y kun432@rpi

RPiにログインしたらDISPLAY変数を確認

echo $DISPLAY

こんな感じで表示されればOKみたい。

出力
localhost:10.0

qpwgraphやHelbumはFlatpakを使うのが一般的みたいなのだが、Flatpakをインストールしてパッケージを追加しようとすると以下となる

出力
error: Nothing matches org.pipewire.Helvum in remote flathub

んー、アーキテクチャが対応していないとかなのだろうか?

kun432kun432

ちょっとデスクトップ環境でやり直そうかな。

このスクラップは3ヶ月前にクローズされました