PCMはできた

ZYBO基板向けのI2S-DAI-DAC基板が無事に動きました。

DAC基板側に2つの発振器を載せていて、再生するファイルのサンプリング周波数が44.1kHzの倍数か、48kHzの倍数かに応じて2つの発振器出力(22.5792MHz/24.576MHz)のイネーブル・ディセーブルを切り替えてZYBO側のI2Sコントローラ回路と、DACの双方に供給するというものです。

当面、PCM信号再生ならMPDからこの「出力先」へ信号を流して楽しむことができそうです。

次のステップは、ZYBOに搭載されたZYNQのAXIバスにぶら下がる形のDSDコントローラをインプリメントし、I2S-DAI-DAC基板にDSDファイルも出力できるようにすることです。

ところで、ZYBO上でこのZYNQプロセッサに繋がっている「カニ」さんは”realtek,RTL8211E”です。きちんと速度を検証していませんが、USDA_MINI基板をつないで、nfsマウントしたQNAPのTS119からDSD11.2MHzのファイルを30分連続で再生したところ、幸運にも音飛びが気になるようなことはありませんでした。ギガビットのおかげ?

先を越されました

先ずは実用的な状態でLinux のUSB Native 転送の動作確認をしようと思い、ZYBOにMPDを導入しました。https://github.com/lintweaker/mpd-dsd-018

ZYBOで同じような事をしていて、SDカードイメージを公開しているケースが見あたりませんでしたので、自分でソースファイルからクロスコンパイルしてZYNQ (ARM) 用 のMPDを作りました。FLACや各種AUDIOファイルアクセス用のライブラリも仕方なく全てソースからARM用にビルドしました。

まだシリアルコンソールから操作しないとIPアドレスの設定やSDカードのマウントなどができませんが、とりあえずMPODからSDカード内のFLACファイルやDSDファイルを選択して再生することができるようになりました。

ZYNQのUSBは、USB-シリアル変換用と、USB On-The-Go の2通り搭載していて、USBDACはOn-The-Goの方につなぎます。ですから、On-The-GoケーブルでつないでおかないとHOSTモードにならず、USBDACを認識しません。On-The-Goケーブルをつないでおけば、きちんとPnP動作をしてくれます。

予想通り、DSD Native転送になっています。ここでいうNativeというのは、DSD-PCM変換された信号ではなくてオリジナルのDSD信号を転送する、という次元の話ではなく、USBを使ったDSD転送において、DoP方式ではなくDSDのために定義された転送モードで送り出す、という意味です。

上のキャプチャはDSD256のファイルを転送中のUSBアナライザの画面です。1uフレーム期間(125us)に平均して352.8バイトのデータをUSDA_MINI基板へ送り込んでいます。

重要なのは、DSD256に対応できるということよりも、DSD64/128の場合も含めて、DoP転送よりも転送に必要な負荷が少ないことが期待できる、ということになります。

ただ、DoP転送、Native転送にかかわらずDSD転送の場合には少し問題があります。というのは、再生開始直後に、少しの期間”ゼロ”を送ってくるため、再生の頭でノイズが出てしまいます。ゼロではなくて”0x96,0x69,0x96,0x69,….” などを送ってくれれば良いのですが、そうはなっていません。

0x96,0x69,…ならば、1bitに展開すると”10010110….”といった1bit列になり、フィルタするとDCになりますが、”0x0,0x0,0x0,0x0,…”を送られると、bit列は”00000000….”となり、フィルタすると負のフルスケールに張り付いた値になりますので、どうしても再生の頭でノイズになってしまいます。

再生の頭だけはアンプのボリュームで回避して、アルバム単位で聴いていれば実用上問題はないのですが。Linuxのソースのどこを修正すればよいのかまだ調べていません。

ちなみに、lightMPDはすでにBBB用にDSD Native転送対応のバージョンがUPされています(先を越されました:笑)。対象のDDCをお持ちの方はお試しになる価値はあると思います。UDA2はうまく動作するか未確認なので多少不安ですが、USDA_MINIではとりあえずNative転送で動作しています。

USBなら本当はraspberry pi 2で動作すればクアッドコアですし一番コスパが高くて良さそうなのですが、何事も思った通りには行かないものです・・・。それともDoPはNGでもNativeはOKということなのでしょうか?

さて、 ひとまずUSBは置いておいて、I2Sを試してからAXIバスにぶら下がるDSDインターフェース設計を始めたいと考えています。

おまけ

前回の記事で、最近の新しいLinuxカーネルには、「一部のUSBオーディオ基板向けを想定して拡張フォーマットが新たに用意されている」 という旨を述べました。

再生しようとする信号のフォーマットを、ALSAアプリと出力先のデバイス・ドライバとの間で教え合うためのフラグのようなものなのですが、”SNDRV_PCM_FMTBIT_DSD_U32_LE” という「もの」と、”SNDRV_PCM_FMTBIT_DSD_U32_BE” といった「もの」などが追加されているのです。

そこで、とりあえず前者をI2Sコントローラ用に採用して定義しましたが、実は、「一部のUSBオーディオ基板」 にはUDA2基板、USBDAC基板やUSDA_MINI基板を含めることができることに気がつきました。

カーネル・ソースの、/sound/usb/quirks.c のコードに下図の赤丸で囲んだ記述を追加することで、対応サンプリング周波数がDSD256にまで拡張され、同じサンプリング周波数のファイルを再生するためのCPUの仕事量が2/3に減り、かつ16bitにパックしたDSD信号にDoPマーカを付け足すという不毛な仕事からCPUが解放されます。 (すみません、256対応は実験上は未確認です) 。

quirks.c に該当する関数がない場合には、古いソースだと考えられます。また、連動してALSAのライブラリも新しいものにする必要があります・・・。 どうせなので最新版に・・・。

ZYBOのUSBでテストアプリを作って確認できました。他のARM系のボードでもおそらく大丈夫だと思います。BBBやRas-Piでもいけるのではないかと思います。もちろんパソコン上の各種ディストリビューションでも同様に行けるのではないでしょうか。

カーネルの再コンパイルをご自身でやらなければならないので、決してお勧めするわけではありませんが・・・。

もしかしたら、ですが、BBBやRas-Pi上のMPD再生で、音切れ対策に、ひょっとしたらですが、多少効果があるかもしれません。ネットワーク上のトラフィックに変化はないはずですが、USBバス上に送り出す時の負荷は減るはずですので・・・。

※動作を保証するものではございませんので、どうかご了承をお願いします。

目処が立つ

前回予想したとおり、このI2Sコントローラに入力するオーディオ系クロックを12.288MHzから倍の24.576MHzに変更するだけで、つまりZYNQプロセッサのペリフェラル・クロックのPLLコンフィギュレーションを変えるだけで、I2Sコントローラの回路やデバイス・ドライバを変更することなく、192kHzまでのサンプリング周波数に対応できることが動作確認できました。

気を良くして、サンプリング周波数が48kHzの倍数 (あるいはやろうと思えば44.1kHzの倍数) にしか対応できないという現行の装置の限界を破るべく、再生オーディオファイルのサンプリング周波数に応じて、このシステムクロックの周波数を、2つのクリスタル発振器、24.576MHzか22.5792MHzのいずれかを切り替えて供給できるようにI2Sコントローラと、そのデバイス・ドライバを改造してみました。

当然、ALSA準拠のアプリ再生で切り替わるようにしてあります。まずはI2Sコントローラに発振器切り換え用のレジスタを追加しました。そして、アプリからALSA経由で再生サンプリング周波数のパラメータを受け取ったデバイス・ドライバが、その追加したレジスタに値をセットすると改造I2Sコントローラが発振器の切り替えセレクタを制御する、という寸法です。なのでデバイス・ドライバにも変更を入れました。

これで、UDAなどと同じように、愚直に原始的に、ではありますが、ピュア・オーディオ品質のクロックが使えるI2Sコントローラができあがりました。 そういうことで必然的にDAC基板も作らざるを得なくなります。

クリスタル発振器はDACが載った基板上に2個置かれることになります。選択されたクロックがDAC ICとZYBOに供給されます。

DAC ICとしてPCM1792Aを載せましたので、CPU(ARM)から設定ができるようになる (する) 予定です。LinuxにはPCM1792Aのデバイス・ドライバも入っていますので、こちらも改造して使うことになると思います。

改造が必要になる理由はDSD対応です。今回の検討で、I2SコントローラにDSD対応の機能を追加すれば普通にNative DSD再生ができるはずであることを確認しました。

最近のALSAライブラリには、”SND_PCM_FORMAT_DSD_U32_LE” というフォーマットが追加されています。調べてみると、元来、一部のUSBオーディオ基板向けに新たに用意された拡張フォーマットのようですが、自作のALSAアプリからARMのAXIバスにぶら下がる形のこのI2Sコントローラに対しても、再生時にデバイス・ドライバ経由でこのフォーマット情報を伝えることが可能であると実験で確認しました。

つまり、アプリが再生開始する直前に、再生信号のフォーマット情報 として “SND_PCM_FORMAT_S32_LE” を送ってくればI2Sモードに、”SND_PCM_FORMAT_DSD_U32_LE” を送ってくればDSDモードへと、I2Sコントローラの機能が切り替わるようにI2Sコントローラのロジック回路とデバイス・ドライバを作りこんでおけば良いというわけです。

おそらくは、最近のMPDではこのフォーマット、”SND_PCM_FORMAT_DSD_U32_LE” がサポートされているはずですので、ZYBOにも組み込んであげることで、出力対象がUSBアダプタではありませんが、Native DSD再生ができるようになるものと思われます。

ちなみにですが、ZYNQプロセッサのベンダであるxilinxや、あるいはZYBO基板をリリースしているDigilentが公開しているramdiskにはALSAのライブラリは組み込まれていませんので、自分で最新版のソースを引っ張ってきて、ノートPCにインストールしたLinux上でクロス・コンパイルして突っ込みました。

ALSAアプリにしても、デバイス・ドライバにしても、もちろんOS本体のカーネルにしても、すべてクロス・コンパイルということになってしまうのは同じですが・・・。