Aug 15, 2020

PPAP back-Endの設定を考え直す(hwとplughw)(8月20日追記)

修理から戻ってきたアンプは好調で、クールな音を聴かせてくれている。
今回はアンプとは関係ない。
ずいぶん前に、PPAP back-Endの「aplay」の設定が釈然としないという話をアップした。
あちこちネット上を徘徊して調べて音が出るようにはしたんだけど、今回はそれをもう少し解明してみた。
aplayコマンドのオプション設定「-D hw:0,0」と「-D plughw:0,0」についての備忘録みたいなものなんだけど、このエントリーだけ読んでも、何が何だか分からないという人が多いような気がする。

8月20日追記。
読み返してみて、いくら自分用の備忘録だからといって「何が何だか分からないという人が多いような気がする」とか「上に挙げたエントリーに書いてある」とかで、背景説明を終わらせてるというのも凄いので、過去の経緯を簡単に追記する。

2年前にpiCoreでPPAPを運用し始めた数か月後、再生データのサンプリング周波数が指定通りのサンプリング周波数にならずに、48kHzに変換されて再生されていたことに気が付いた。
変換されるのはalsa、dmixのデフォルト設定だと思い至り、変換されないようにする方法をネット上で探したところ、aplayのコマンドに「-D hw:0,0」というオプションを追加すればいい、という情報を得た。これを試みたが、何故かmpdが止まって音が出なくなった。
更にネット上を探したところ「-D plughw:0,0」というオプションで再生する方法があるという情報があり、試みたところ、48kHzに変換されることなく指定通りのサンプリング周波数で再生されるようになった。

ちゃんと指定通りに再生されるようになったのは良かったのだけど、当惑したのは「-D plughw:0,0」は一般的には「48kHz/16bitに変換して再生するオプション設定」とされていることだ。
つまり、うちでは通常と全く逆になった。
原因不明で、ずっとその設定で運用していたのだけど。
今回はその原因がやっと分かったというエントリーだ。要は、何処其処が間違ってましたという話である。

piCore7でppap (piped pcm audio play)を試みる
http://blown-lei.net/endive/blosxom.cgi/audio_diary/20180301a.htm
PPAP Back-EndのUSB出力が48kHzになっていたので修正した
http://blown-lei.net/endive/blosxom.cgi/audio_diary/20180523a.htm
piCore7で作るPPAP Back-End
http://blown-lei.net/endive/blosxom.cgi/audio_diary/20180527a.htm

これらのエントリーでBack-Endの作り方を書いている。
ちょっとBack-Endとして機能させるためのコマンドを引用する。

下記は24/192のデータを受ける場合。
192kHzがaplayで扱うことができるサンプリング周波数の上限なので、PPAPの上限も192kHzになる。

/usr/local/bin/ncat -kl 4444 -e "/usr/local/bin/aplay -D plughw:0,0 -M --period-size=512 --buffer-size=4096 -t raw -f S24_LE -r192000 -c2"

当時、PPAP back-EndのUSB出力が48kHzになっていたのに気付かず使っていて、分かった時にはずいぶん驚いた。
上記のようにコマンドに「-D plughw:0,0」を加えることで、なんとか修正して設定どおりのサンプリング周波数で出力されるようにしたが、どうなってるんだろうと思ったまま、そのままになっていた(どうしてどうなってるんだろうと思ったのかは、上に挙げたエントリーに書いてある)。

アンプの調子もいいことでありがたいことだなあ、などと思ううちに、ふと脈絡なく思い出し、改めて調べ始めた。
以下、資料。実際は他にもあちこち見てまわったんだけど、省略。

PCM - MultimediaWiki
https://wiki.multimedia.cx/index.php/PCM
みみず工房本館 10センチの穴
http://mimizukobo.sakura.ne.jp/articles/articles007.html
Auraliti PK90の新機能とLinuxのインテジャーモード: Music TO GO!
http://vaiopocket.seesaa.net/article/223714988.html
ALSAでbit perfect再生するには ナカタの Digital Wonder Land
http://www.nakata-jp.org/computer/howto/audio/alsa.html

まず、みみず工房から引用。
2011年、9年も前の記事だ。原発のことも書かれていたりする。
この頃はうちではまだlinuxは使っていなかった。AirMac ExpressでPCオーディオをやっていた。

Computer Audiophileの[New mpd feature = cleaner signal](http://www.computeraudiophile.com/content/New-mpd-feature-cleaner-signal)という記事の情報によると、24-bit USB DAC に対する音質改善のため、mpdの改良が行われています。この記事はMPDの音質に関する大変興味深いやりとりがあり参考になります。例えば以下のような書き込みがあります。 S24_3LEハードでmpd.confのaudio_outputの「hw:n,n」を「plughw:n,n」と変えると(「hw:n,n」の行をコメントアウトしても同じ)、wavファイルは再生できるようなるのですが、音質は悪化します。これは上記の記事にあるように「plughw:n,n」を指定するとビットレートが48000、16ビットに固定されて、余分なフォーマット変換が入ってしまうためです。

2年前にうちで起きたのと同じようなことが書いてある。
ただ、音質が悪化したとは感じなかった。PPAPによる改善のほうが上回ったのだと思う。

早々に追記。
読みかえしてみて、「同じような事が書いてある」というのは大きな誤解を招くと思った。同じ事というのは「データが48kHzに変換される」ということだけで、plughwについては、うちではplughwを使うことで変換を回避したのだから、引用している内容とは真逆である。この、定説とは逆になったということが2年前からの疑問だったのだ。
あまりに記述が大雑把だったので加筆訂正する。

アドレスが書かれてあるComputer Audiophileのスレッドにも興味深い記載があった。

S24_3LE is a 24-bit format also known as "packed 24-bit". All 24-bit USB DACs only support S24_3LE. Since mpd didn't support this format before, it converted everything to a 32-bit format and then ALSA was needed to convert that 32-bit format to S24_3LE for a 24-bit USB DAC. That's why I could never get mpd to send audio straight to the Wavelength Proton with hw:0,0. I had to use plughw:0,0 instead because that allowed ALSA to make the conversion. hw:0,0 sends the audio straight to the DAC without any conversion. No other mpd.conf configuration is necessary besides specifying hw:0,0.

Music TO GO!から引用。こっちも2011年。

ALSAではDACなどのデバイス(ALSAでいうcard)に対してデータを送るときにいくつかのインターフェース(転送モードみたいなもの)を指定します。たとえばhwとplughwです。hwを使用した場合はDACにたいしてデータの改変なく(つまりダイレクトに)データを送出します。その代わりDACで扱えるデータのタイプをプログラム(再生ソフト)側で気にする必要があります。plughwを指定したときはALSAシステム側でなんらかの処理の後にデバイスに送出されます。たとえばデバイスが扱えないデータタイプを変換してくれますのでプログラムから見るともっと手軽です。
(中略)
この「ALSAのインテジャーモード」を使用するさいにはダイレクトに送るわけですから上に書いたようにhwインターフェースを使用する必要があります。問題はWAVを再生したときにここでエラーがおこると言うことです。
解決策としては上のCAスレッドにあるようにplughwを介してデータをいったん整数から小数点形式に変換するとエラーを回避することができます。つまりplughwインターフェースを介することによってWAVも問題なく再生できますが、先に書いたhwでの「ALSAインテジャーモード」のダイレクトアクセスのメリットは消失してしまいます。

ALSAでbit perfect再生するには、から引用。

非bit perfect再生
aplayを使用してわざわざ非bit perfect再生することもないと思いますが, 念のために書いておきます。 サウンドカードが対応していないサンプリング周波数やビット長のデータを、 無理やり再生することができます。 Bit perfect再生する時のhwパラメータをplughwに置き換えます。
hostname:~> aplay -D plughw:0,0 sample.wav
aplayの制限
aplayは、試験用に作られたプログラムのようで,制限があります。 特に,オーディオ再生として使用する場合の一番の制限は、 再生ファイルのデータフォーマットと、 デバイスのデータフォーマットが一致していなければならないことです。 デバイスが24bit linear PCM little endianだった場合, 再生するファイルも24bti linear PCM little endianでなければなりません。 ファイルが16bit だったり、big endianだったりすると、 この例ではbit perfect再生してくれません。 ここは注意してください。

次に、うちのサイトから引用。

以前に使っていた、
/usr/local/bin/ncat -kl 4444 -e "/usr/local/bin/aplay -M --period-size=512 --buffer-size=4096 -t raw -f S24_LE -r192000 -c2"
というようなコマンドだと、前述の通り音が出ない。alsa-dev.tcz alsa-doc.tcz alsaequal.tcz alsa-locale.tcz、、まあ、どれが働くのかわからないけど、これらがインストールされていたらdmixが働いて48kHzに変換された上で、音が出る。

/usr/local/bin/ncat -kl 4444 -e "/usr/local/bin/aplay -D hw:0,0 -M --period-size=512 --buffer-size=4096 -t raw -f S24_LE -r192000 -c2"
だったら「paused」が表示されて音が出ないんだけど、alsa-dev.tcz alsa-doc.tcz alsaequal.tcz alsa-locale.tczを追加インストールしても、「paused」で音が出なかった。「-D hw:0,0」はあちこちでdmixによるリサンプリングをさせない設定とされているんだけど、どうもpiCore7ではうまく機能しない。

/usr/local/bin/ncat -kl 4444 -e "/usr/local/bin/aplay -D plughw:0,0 -M --period-size=512 --buffer-size=4096 -t raw -f S24_LE -r192000 -c2"
これだったら、こちらの求めるように機能して音が出る。どこかでそうなるように設定されているのかもしれないけど、よく分からない。
現状、変換せずに音が出てくれたらいい、という感じだ。

上記の引用は読むだけでは分かりにくいと思ったので表にして8月20日追記した。


alsa-modules-4.1.13-piCore_v7+.tcz alsa.tcz
(最低限のalsaインストール。dmix使用不可)

(以下tcz追加しdmix使用可能)
alsa-dev.tcz alsa-doc.tcz alsaequal.tcz alsa-locale.tcz

/usr/local/bin/ncat -kl 4444 -e "/usr/local/bin/aplay -M --period-size=512 --buffer-size=4096 -t raw -f S24_LE -r192000 -c2"

paused

dmixが48kHz/16bitに変換し再生

/usr/local/bin/ncat -kl 4444 -e "/usr/local/bin/aplay -D hw:0,0 -M --period-size=512 --buffer-size=4096 -t raw -f S24_LE -r192000 -c2"

paused

paused

/usr/local/bin/ncat -kl 4444 -e "/usr/local/bin/aplay -D plughw:0,0 -M --period-size=512 --buffer-size=4096 -t raw -f S24_LE -r192000 -c2"

サンプリング周波数を変換せず再生

未確認

なんだか、ちょっと見えてきたような感じ。
2年前の僕はpiCoreのせいにしてるけど、実はデータフォーマット設定が合っていなかったから音が出なかった可能性がありそうだ。「S24_LE」とかコマンドに書き込んでるけど、24bitだからこれかな、みたいな感じで記述していて、理解してないままなのだ。endianのことなんて考慮していない。
というか、調べたけど全く分からなかったので考慮を放棄したというのがあるんだけど。

当時はnano iDSD LEや、fireface UCXをCCモードで使っていた。
CCモードなんて基本的にiPad用だ。どういうフォーマットなのだろう、、、

DACが受け取れないフォーマットだったら「paused」で音が出ないということはあり得るだろう。
受け取れなかったのを「plughw」設定でなんとかして、音が出るようになっていたのかもしれない。plughwは、必ずしもサンプリング周波数やビット深度を変えるというものではなくて、データ伝送先が受け取れられるように擦り合わせるという設定なのかも。
dmixがあったら48kHzに変換されるというのも、たぶん、あったらそうするのであって、なかったらなかったで他の何らかの伝送できるフォーマットで送るようになっているのではないか。

もしかして、過去のエントリーの記録に痕跡が残ってないかしら、、、

、、、、、みつけた、、、、、

そんなこんなで、fireface UCXにCCモード上限の96kHzで入力できるようになった。
バックエンドで「cat /proc/asound/card*/pcm0p/sub0/hw_params」を打つと「96000」と表示される。

tc@box:~$ cat /proc/asound/card*/pcm0p/sub0/hw_params
access: MMAP_INTERLEAVED
format: S32_LE
subformat: STD
channels: 2
rate: 96000 (96000/1)
period_size: 256
buffer_size: 2048
tc@box:~$ 

あんた、format: S32_LE、ってはっきり出てますやん!コマンドは「S24_LE」だったんとちゃいますのん?その何処見とるか分からん目は節穴どすか!

なにか脳内で聞こえた気がしたけど気にしない。PCM - MultimediaWikiから引用。Google翻訳も併記する。

Integer Or Floating Point
Most PCM formats encode samples using integers. However, some applications which demand higher precision will store and process PCM samples using floating point numbers.
Floating-point PCM samples (32- or 64-bit in size) are zero-centred and varies in the interval [-1.0, 1.0], thus signed values.

整数または浮動小数点
ほとんどのPCM形式は、整数を使用してサンプルをエンコードします。 ただし、より高い精度を必要とする一部のアプリケーションでは、浮動小数点数を使用してPCMサンプルを保存および処理します。
浮動小数点PCMサンプル(サイズが32ビットまたは64ビット)はゼロ中心であり、間隔[-1.0、1.0]で変化するため、符号付きの値になります。

浮動小数点PCMサンプルは32bitか64bitと書いてある。
Music TO GO!の「plughwを介してデータをいったん整数から小数点形式に変換するとエラーを回避することができます」という記載と、うちでS24_LEだった筈のデータがS32_LEに変換されて聴けるようになったのと、整合性があるように思われる。

こうなると、現在メインで使っているADI-2 DACはどうなってるんだろう?と気になってくる。
現在はapu2、tiny Core pure64でPPAP Back-Endを運用している。
http://blown-lei.net/endive/blosxom.cgi/audio_diary/20200320a.htm
700kHz台でPPAP(22日、4月7日追記)

サウンドカードが対応しているデータフォーマットの詳細を確認できるコマンドがあるとのことで、sshでapu2にログインし使ってみる。

tc@box:~$ cat /proc/asound/card0/stream0
RME ADI-2 DAC (52973504) at usb-0000:00:10.0-1, high speed : USB Audio

Playback:
  Status: Stop
  Interface 1
    Altset 1
    Format: S32_LE
    Channels: 2
    Endpoint: 2 OUT (ASYNC)
    Rates: 44100, 48000, 88200, 96000, 176400, 192000, 352800, 384000, 705600, 768000
    Data packet interval: 125 us
    Bits: 32

Capture:
  Status: Stop
  Interface 2
    Altset 1
    Format: S32_LE
    Channels: 2
    Endpoint: 1 IN (ASYNC)
    Rates: 44100, 48000, 88200, 96000, 176400, 192000, 352800, 384000, 705600, 768000
    Data packet interval: 125 us
    Bits: 32

Capture:って、、ADI-2 DACにはADCの機能がある?と何処かで読んだ記憶があるのだけど、こういう表示になるのね。
DAC機能のほうはPlaybackの項目に書かれている。Format: S32_LE、ということだ。

今迄使っていたコマンド(bootlocal.shに書き込んである)は下記の通り。plughwを使っている。
/usr/local/bin/ncat -kl 4444 -e "/usr/local/bin/aplay -D plughw:0,0 -M --period-size=2048 --buffer-size=32768 -t raw -f S32_LE -r768000 -c2"
偶然、S32_LEになっている。
これは、768kHz/32bitにアップサンプリングするから、ぐらいの考えで書いたものだ。
これを下記のようにhw使用に書き換えて再起動してみる。

/usr/local/bin/ncat -kl 4400 -e "/usr/local/bin/aplay -D hw:0,0 -M --period-size=4096 --buffer-size=32768 -t raw -f S32_LE -r768000 -c2"

全く問題なく音は出た。
なんということか。
音質には差がない。いや、多少、固い音か?、気のせいかな、区別は付かない。
しかし、これでビットパーフェクト、なのかな?
アップサンプリングしてるから今更ビットパーフェクトとか関係ないけど、アップサンプリングしたデータを正確に伝送しているということなんだろうか。

それにしても、僕はapu2をPPAPで使用開始するにあたって、44.1、96、192、384と、24bitとかで試してきているのだ。その際に、S24_LEとかS16_LEとか、書いてたような気がする。問題なく音が出ていたのは、plughwで設定していたからだ、ということになる?
もしかしたら、plughwのほうが気軽に扱いやすい設定方法という一面もあるのだろうか。

しかしとりあえず、夏が終わる前に宿題が一つ片付いて、よかったかなと思っている。

Edit this entry...

wikieditish message: Ready to edit this entry.
















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