Dec 19, 2020

ソフトを起動する順番を変えてみる ~ pulseaudioによる音声データ転送 使い方まとめ(2021.01.31. 06.26. 追記)

2021年1月31日、タイトルに「まとめ」と書いている割にまとまってないので、下の方、構成を変えて多少追記した。

6月26日、追記。
やっぱりまとまってないので、思い付いたら適宜追記加筆訂正再編していくことにした。
だからこのエントリーに関しては、本編文章では追記の断り書きを記載しないことにする。
読みやすくなっていくかどうかは神のみぞ知るだ。

以前のエントリーでブレイクスルーは無いだろうと書いたことがあったが、以外なところからノイズの解決策が見つかった。
ソフトを起動する順番を変えることで、ノイズが消えてしまった。

思えば、Pulseaudioによる音声データ転送を今のシステムで始めた頃は、いつノイズが出るのか分からないような状態で、対策も闇雲な感があった。
しかし、daemon.confの「nice-level」を設定して以降から状況が変わってきた。使用開始時の再生音はノイズが増えたが(考えてみたら、これも原因不明なんだよね、、)、Pulseaudio serverを再起動したら、その後はノイズがすっかり消えてずっと安定するようになったのだ。

ただ、最初の起動時点からノイズ無しに再生できるようにする方法が見えなかった。
再起動しなければずっとノイズが続く。
サーバーで「top」を打って確認したら、再起動前後ではCPUの使用%も違う。ノイズが出ているときの方が負荷が大きい。

設定を弄るばかりで行き詰まってしまったので、操作方法とノイズの有無について再確認してみようと思い付いた。

まずサーバー起動し、Firefox、Deezerを起動し音を出したら、ノイズまみれの音になる。
ここでサーバーを再起動したら、ノイズが無くなる。 サーバー再起動の変わりにFirefoxの再起動やDeezerの再起動では、ノイズは無くならない。改めてサーバーを再起動したら、そこでノイズは無くなる。サーバーを再起動しないことにはノイズは無くならないようだ。

手順についてあれこれ考え試みているうちに、最初のサーバー起動と再起動とで何が違うのかというと、FirefoxとDeezerが動いているかどうかだ、ということに気付いた。
ここで最初の音出しに際しての手順については、今まで全く検討していないことに思い至った。
つまり、サーバーを起動した後にクライアントを動かすものだという、固定観念があったのだ。

試しに、先にFirefox、Deezerを起動して後に、サーバーを起動してみたら、ノイズがない音が再生された。
ちょっと呆れてものも言えない。

何時またノイズが出始めるか分からないので、これで最終型と言い難いのだけど、本当にこれで完成して欲しい。そんなこといいながら、実はノイズの原因とか、ほとんど原因不明なままだ。そんなことでいいのかな、という気持ちもないではないのだけど。でも解明するには分からないことが多すぎかな。

はああ、しかし取り敢えず、何とかなったぜ、、、

しかし、ここまでの記載内容は、2020年度までのシステム運用上で大事だったことで、21年春からDaphile経由でDeezerを再生できるようになってからは、pulseaudio経由で音源をアップサンプリングすることはなくなった。pulseaudioサーバーは別建てになり、Raspberry Pi2ベースでシンプルな運用になり要求する内容も軽くなって、サーバーとクライアントどっちが先かなんて、気にしなくてもよくなった。
本来あるべき、無理のない運用だと感じられる。まあ、いろいろ勉強になったかな、、、

取ってつけたようだが、取り敢えずまとめ

Pulseaudio関連のエントリーは、以下のとおり。

  1. Pulseaudioを使ってRaspberry piにAmazon Prime Musicを転送再生する(9月8日追記)
    http://blown-lei.net/endive/blosxom.cgi/audio_diary/20200906a.htm

  2. 音楽ストリーミングサービスのウェブプレーヤーを使う
    http://blown-lei.net/endive/blosxom.cgi/audio_diary/20200927a.htm

  3. Pulseaudioの備忘録
    http://blown-lei.net/endive/blosxom.cgi/audio_diary/20200930a.htm

  4. ストリーミング音源をpulseaudioで転送しアップサンプリング再生する(10月15日、追記)
    http://blown-lei.net/endive/blosxom.cgi/audio_diary/20201011a.htm

  5. pulseaudioサーバーを強化する(10月24、25日、11月01、05、10日、追記あり)
    http://blown-lei.net/endive/blosxom.cgi/audio_diary/20201017a.htm

  6. pulseaudioサーバーを強化する(その2:12月11日、追記あり)
    http://blown-lei.net/endive/blosxom.cgi/audio_diary/20201115a.htm

  7. pulseaudio クライアントのFirefoxを強化する
    http://blown-lei.net/endive/blosxom.cgi/audio_diary/20201212a.htm

  8. ソフトを起動する順番を変えてみる ~ pulseaudioによる音声データ転送 使い方まとめ(2021.01.31. 06.26. 追記)
    http://blown-lei.net/endive/blosxom.cgi/audio_diary/20201219a.htm

    (当エントリー)

  9. PulseaudioによるLan経由音声データ転送のデータ量が大きすぎる(未解決案件)
    http://blown-lei.net/endive/blosxom.cgi/audio_diary/20210216a.htm

Pulseaudio system

2020年末時点での運用は、図のようなイメージ。
普段、日常的な用途に使っているProbook 450G3を、pulseaudioクライアントとして運用。
音楽ストリーミングサービスdeezerのデータはCDと同等の音質で、ロスレスだ。
だから、これをpulseaudioサーバーにしたElitebook 2570pにLANを経由して送って、libsamplerateでアップサンプリングしてusb DACに送ることで、高音質再生を目指す。

このときの音質だけど、CD音源同等のストリーミングデータを、libsamplerateで384kHzにアップサンプリングし、SMSL M500、Brooklyn Ampで出力している音として、全く不満がない再生音が得られていた。Pulseaudioといえば、昔は音が良くないといわれていたようだけど、本当にそうなのかな?と思うだけの音が出ていた。
ADI-2 DAC、SM-SX100で鳴らしてみても、その印象は変わらなかった。

そういうわけで、Pulseaudio運用の記録を残しておく。

Pulseaudio クライアント

クライアントの扱いは前回のエントリーのとおり。
pulseaudio クライアントのFirefoxを強化する

しかし、2020年末、再生時にノイズが無くなった頃からは余り細かいことを気にしなくなった。前回エントリーの内容、クライアントの強化についても気にしない。
firefox以外のウェブブラウザを使ってみたりしたが、操作性以外に大きな差異はないようだ。

基本的に、一般的なワークステーション用Linux PCであればクライアントとして運用できるはず。大抵、pulseaudioはインストールされているからだ。
ウェブブラウザも一般的なので大抵は問題無いだろう。というか、問題があったら他のを使うだけだ。

クライアントの使い方は、過去のエントリーから一部引用し書き変えて記載しておく。

クライアント側の設定。設定というか、使い方だ。
先ずターミナルソフトでコマンドを打つ。

$ export PULSE_SERVER=192.168.1.xx

これで、このターミナルウィンドウから起動させるプロセスが、赤字のアドレスのpulseaudioサーバーに音声データを伝送できるようになる。
同じターミナルウィンドウからコマンドを打ってウェブブラウザ(例:firefox)を起動させる。

$ firefox

firefoxが起動したら、Deezerやyoutubeなど、聴きたい音源のサイトを開く。
続いて、pulseaudioサーバーでpulseaudioを起動した後、firefoxで音源を鳴らす操作を行う。
このfirefoxが出力する音声が、lanを通じてpulseaudioサーバーに転送される。うまくいけばサーバーで設定された出力から音が出る。

この順序が重要で、順序を間違えたら再生音にノイズが乗る。

以上、ざっと引用。

この順序を間違えたらノイズが乗るという案件なんだけど、Raspberry Pi2をpulseaudioサーバーにして、アップサンプリング無しで運用した場合には、まったく見られないようだ。
つまり、サーバー側でpulseaudioを起動したままにして(daemon.confに関連して後述)、好きな時にクライアント側の操作をしたら、サーバー側から音が出る。
扱い易いのはありがたい。
だけど、理由は分からないままになっている。

引き続いて、サーバーについての説明。
音質の追求や不具合への対処に付いては、複数のエントリーに渡ってああでもないこうでもないと色々やっていて、わけが分からない。

サーバー運用にあたって、最も大事なことが書いてあるのは最初のエントリー(Pulseaudioを使ってRaspberry piにAmazon Prime Musicを転送再生する(9月8日追記))かもしれない。ここにはpulseaudioのインストールとサーバー運用に必要な初期設定、pulseaudioで使うコマンド(音量調整など)についても幾つか説明を書いてある。

うちではデフォルトでは使用できないlibsamplerateを使えるようにする必要があったので、pulseaudioをソースから再インストールする必要があり面倒だった。顛末は下記エントリーに記載。
ストリーミング音源をpulseaudioで転送しアップサンプリング再生する(10月15日、追記)
libsamplerateでアップサンプリングするなら、ハードにはそれなりのスペックが必要になる。

アップサンプリングに拘りがないのであれば、もっと簡単に運用できる。
基本的に、pulseaudioがインストールされているLinux PCであれば、設定さえすればサーバーとして機能する筈だ。うちでは21年初夏の時点でRaspberry Pi2に回帰した。簡単な運用であればそれでまったく問題ない。

使用前に「default.pa」ファイルで出力先と入力先を設定。「daemon.conf」ファイルでpulseaudioの優先度やアップサンプリングなど設定。
sshを使ってLan経由でサーバーの起動終了、音量とかを操作する。
しかし、慣れない人にはハードルが高いかも。
サーバーの設定は以下。

Pulseaudio サーバー default.paの設定

「/home/tc/.pulse/default.pa」の設定は下記の通り。

#load-module module-alsa-sink
load-module module-alsa-sink device=hw:0,0

.ifexists module-udev-detect.so
load-module module-udev-detect
# load-module module-udev-detect tsched=0
.else
### Use the static hardware detection module (for systems that lack udev support)
load-module module-detect
# load-module module-detect tsched=0
.endif

#load-module module-native-protocol-tcp
load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1;192.168.1.0/24

あれこれ運用した結果、「tsched=0」の設定を止めてデフォルトに戻している。
もともと特定のサウンドボードに対応するための設定だった筈で、実際、戻しても不具合は感じなかった。

出力先の設定が「load-module module-alsa-sink device=hw:0,0」。
aplay -lで音声データ出力先を確認し記載。

入力の設定が「load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1;192.168.1.0/24」。
この記載だと、LANネットワーク内のipアドレスが「192.168.1.xxx」であるクライアントから、音声データを受けることができる。

Pulseaudio サーバー daemon.confの設定

「/home/tc/.pulse/daemon.conf」の設定は以下。
項目が多いので分けて記載。

; shm-size-bytes = 0 # setting this 0 will use the system-default, usually 64 MiB
shm-size-bytes =32000000

; high-priority = yes
; nice-level = -11
high-priority = yes
nice-level = -18

libsamplerate(SRC)で高いサンプリング周波数にアップサンプリングするために「shm-size-bytes」は大きくとっている。
しかし、どの程度の数値が良いのかは、はっきり分からないままだ。
アップサンプリングしないなら設定不要だと思う。

優先度も「nice-level」で設定する必要がある。
設定して以降、384/32が問題なく鳴らせるようになった。



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

; rlimit-nice = 31
; rlimit-rtprio = 9
rlimit-nice = 38
rlimit-rtprio = 88

このあたりの設定は、結局よく分からないままだ。
過去のエントリー(pulseaudioサーバーを強化する(その2:12月11日、追記あり) )によると、あちこち他のサイトを参考にしながら計算した筈だけど、読み返しても何をやってるのか分からない。実際、分からないまま設定したのだ。
ちょっと引用。

GETRLIMIT https://linuxjm.osdn.jp/html/LDP_man-pages/man2/getrlimit.2.html

RLIMIT_NICE (Linux 2.6.12 以降, 下記の「バグ」の節も参照)

This specifies a ceiling to which the process's nice value can be raised using setpriority(2) or nice(2).
The actual ceiling for the nice value is calculated as 20 - rlim_cur.
The useful range for this limit is thus from 1 (corresponding to a nice value of 19) to 40 (corresponding to a nice value of -20).
This unusual choice of range was necessary because negative numbers cannot be specified as resource limit values, since they typically have special meanings.
For example, RLIM_INFINITY typically is the same as -1.
For more detail on the nice value, see sched(7).

nice-levelは、-20から19の間に設定。realtime-priorityは、0から99の間。
rlimit-niceは、20-(nice-level)で設定。
なんだか分からないが、20から引くということらしい。
rlimit-rtprioもよく分からないが、realtime-priorityに数値を合わせてみた。

このあたりは効果があったかどうかもはっきりしなかった。



; exit-idle-time = 20
; scache-idle-time = 20

exit-idle-time = -1
scache-idle-time = 180


; default-script-file = /usr/local/etc/pulse/default.pa
default-script-file = /home/tc/.pulse/default.pa

上の例では「exit-idle-time」に「-1」を設定している。
デフォルトは「20」で、クライアントからの音声データが20秒間途切れたらシャットダウンする設定だ。
この数値をマイナスに設定したら、データが途切れてもシャットダウンせずに待機するようになる。
以下、ネット上のマニュアルから引用。

IDLE TIMES

exit-idle-time= Terminate the daemon after the last client quit and this time in seconds passed. Use a negative value to disable this feature. Defaults to 20. The --exit-idle-time command line option takes precedence.
scache-idle-time= Unload autoloaded sample cache entries after being idle for this time in seconds. Defaults to 20. The --scache-idle-time command line option takes precedence.

1つのハードでmpdサーバーとpulseaudioサーバーを切り替えて使うような環境だったら自動的にシャットダウンする設定もそれなりに意味があるけど、pulseaudioサーバー専用ハードでサーバーを建てた場合はむしろずっと動いてくれている方が運用しやすい。

「default-script-file」は「default.pa」のパス設定。
意外に設定する方が安定すると過去のエントリーに記載がある。



; resample-method = speex-float-1
resample-method = src-sinc-fastest

; flat-volumes = yes
flat-volumes = no

リサンプリングにlibsamplerate(SRC)を使う設定を「resample-method = src-sinc-fastest」で記載。

flat-volumesは一応、noに。
入力と出力のボリュームを合わせるということなのでデータが変わるかもしれないと思ったので。
設定する方がいいのかどうかは確認していない。



; default-sample-format = s16le
; default-sample-rate = 44100
; alternate-sample-rate = 48000

default-sample-format = float32le

default-sample-rate = 384000
alternate-sample-rate = 384000

アップコンバートの設定。
default-sample-formatに「s32le」ではなく「float32le」を設定することで、音質改善があった。



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

default-fragments = 2
default-fragment-size-msec = 20

; enable-deferred-volume = yes
enable-deferred-volume = no

これはあれこれやったけど、結局よく分からなかった。 pulseaudioのマニュアルから引用。

DEFAULT FRAGMENT SETTINGS

Some hardware drivers require the hardware playback buffer to be subdivided into several fragments.
It is possible to change these buffer metrics for machines with high scheduling latencies.
Not all possible values that may be configured here are available in all hardware.
The driver will to find the nearest setting supported.
Modern drivers that support timer-based scheduling ignore these options.

default-fragments= The default number of fragments. Defaults to 4.
default-fragment-size-msec=The duration of a single fragment. Defaults to 25ms (i.e. the total buffer is thus 100ms long).

Modern drivers that support timer-based scheduling ignore these options. とある。
タイマーベースのスケジューリングをサポートする最新のドライバーは、これらのオプションを無視します、と。、、、、

過去のエントリーから引用。

default-fragments関係の設定は初心に還って、計算値に合わせた。
20だろうが500だろうが、数値を何にしても大して挙動は変わらず、pulseaudioが最適値を勝手に決めているのだろうと思うに至ったのだけど、じゃあ、詳しいサイトに載っている計算に合わせた設定を書き込んでおいてもいいだろう。もうこれ以上は弄らないことにする。
参考にしたのはarchlinuxのサイト。
https://wiki.archlinux.jp/index.php/PulseAudio/トラブルシューティング
計算の仕方は下記。
コマンド「pactl list sinks」でusbデバイスへの伝送の状況が表示されるので、その数値から計算する。

pactl list sinks

Sample Specification: s32le 2ch 352800Hz
Properties:
 device.buffering.buffer_size = "1048576"
 device.buffering.fragment_size = "524288"

32*2*352800 = 22579200 (bps)
device.buffering.buffer_size (1048576) / 22579200 = 0.046439909 (50ms)
device.buffering.fragment_size (524288) / 22579200 = 0.023219955 (25ms) = default-fragment-size-msec

default-fragments = buffer_size/fragment_size = 0.046439909/0.023219955 =2

これも設定による明確な音質変化は分からなかった。まあ、これらのオプションは無視されていたのかも知れない。

Edit this entry...

wikieditish message: Ready to edit this entry.
















A quick preview will be rendered here when you click "Preview" button.