読者です 読者をやめる 読者になる 読者になる

😃 mattintosh note 📝

Hello Raspberry Pi!

Linux同士でオーディオを転送する

Raspberry Pi PulseAudio

ここ数日、「母艦の音を PulseAudio で Raspberry Pi 1 Model B+ で再生する」というのをやっていたけど、ミュージックプレーヤーの2曲目がどうしても再生できないという問題を解決できず…。無線にしているのが悪いのかと思い有線にしてみたり、PulseAudio のモジュールを減らしてみたり追加したり。週末にようやくそれっぽい書き込みをいくつか見つけた。

raspberrypi.stackexchange.com

うーん、なんか Raspberry Pi 1 Model B+ だと難しいような気がしてきた…。

「module-native-protocol-tcp 以外にオーディオを転送する方法はあるのか?」

PulseAudio の module-native-protocol-tcp が上手く動かないので他の方法をいくつか検討してみた。

parec

まずは parec と pacat の組み合わせ。

module-native-protocol-tcp を手動で行うイメージか。module-native-protocol-tcp の時のようにまったく応答しなくなることはないが、細かく途切れている感じ。parec のデバイスの指定は alsa_output.pci-0000_00_1b.0.analog-stereo.monitor のように指定することもできるが、デバイス番号でも指定ができる。デバイス名は pactl list short | grep monitor などで調べることができる。

$ parec -d 0 | ssh 192.168.1.100 pacat

次に parec と aplay の組み合わせ。先ほどに比べて音切れは無く、良い感じ。ただ、若干タイムラグがある。aplay の -f cd は -f S16_LE -c2 -r44100 の略式。

$ parec -d 0 | ssh 192.168.1.100 aplay -t raw -f cd -
Playing raw data 'stdin' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo

parec で母艦の音をキャプチャする場合、母艦のスピーカーでもそのまま音が再生されるので alsamixier などでスピーカーの音をオフにしておいた方が都合がいいことがあるかもしれない。

f:id:mattintosh4:20160202150624p:plain

module-tunnel-sink

リモートのサウンドデバイスを母艦のデバイスとして扱える(?)。サーバを Raspberry Pi とした場合、母艦に bcm2835 ALSA Analog Stereo を接続できる。母艦に存在していることになっているので音量調整なんかもできる。

f:id:mattintosh4:20160202151517p:plain

まず、サーバ(Raspberry Pi)側で module-native-protocol-tcp を有効にしておく。認証方法の説明についてはここでは省略する。

load-module module-native-protocol-tcp auth-anonymous=1

クライアント側で module-tunnel-sink をロードする。また、引数でサーバ側の sink を指定することもできる。

(IP アドレスでは指定できない…?)

$ pacmd load-module module-tunnel-sink server=alarmpi.local

上手く接続されればクライアント側の sink リストに表示される。

$ pacmd list-sinks
:
    index: 1
        name: <tunnel-sink.alarmpi.local>
        driver: <module-tunnel.c>
        flags: NETWORK HW_MUTE_CTRL HW_VOLUME_CTRL LATENCY 
        state: SUSPENDED
        suspend cause: IDLE 
        priority: 0
        volume: 0:  69% 1:  69%
                balance 0.00
        base volume: 100%
        volume steps: 65537
        muted: no
        current latency: 0.00 ms
        max request: 0 KiB
        max rewind: 0 KiB
        monitor source: 3
        sample spec: s16le 2ch 44100Hz
        channel map: front-left,front-right
                     Stereo
        used by: 0
        linked by: 0
        fixed latency: 250.00 ms
        module: 22
        properties:
                device.description = "bcm2835 ALSA Analog Stereo on USERNAME@alarmpi.local"
                tunnel.remote.server = "alarmpi.local"
                device.icon_name = "audio-card"
                tunnel.remote_version = "30"
                tunnel.remote.user = "USERNAME"
                tunnel.remote.fqdn = "alarmpi.local"
                tunnel.remote.description = "bcm2835 ALSA Analog Stereo"

mplayer ではデバイスを直接指定することができるので以下のようにして PulseAudio のデバイスを指定できる。

$ mplayer -ao pulse::tunnel-sink.alarmpi.local sound.wav

デバイスを選択出来ないアプリケーションの場合は PULSE_SINK 環境変数を使う。

$ PULSE_SINK=tunnel-sink.alarmpi.local speaker-test

母艦で PulseAudio を使っている音声を全て module-tunnel-sink に流すならデフォルトの sink を変えてしまえばよい。この時の sink は名前以外に index で指定ができる(つまり、set-default-sink 0 とすればデフォルトのデバイスに戻る)。list-sinks をインデックスの隣に * が表示されるのでどれが現在のデフォルトかすぐわかる。

$ pacmd set-default-sink tunnel-sink.alarmpi.local
$ pacmd list-sinks
$ pacmd set-default-sink 0

で、肝心の音はどうなのよ、と言うと pacat を使った時とあまり変わらず…。しかもボリューム調整とかしなきゃ音が割れるのでむしろ pacat よりも難しいかもしれない。


とりあえずオーディオ遊びはこの辺まで…。