#37 USB Audioについて(その5 bit数とSampling Rateはどのようにして決められるか)

 前回の図-36-1を理解していただけましたか? 同図のようにUSB信号線上はUSBの転送レート(この場合は12Mbps)によるPacket転送であり、USB Audio DataそのものはPacketの中の単なるバイナリデータとして扱われます。データはUSBの転送ルールにしたがってIsochronous転送されますので、USB-Host(PC)やUSB Audio Deviceのコネクタ部や基板パターン、PHY(Chipの物理層)周辺、ケーブルなどのどちらかといえばアナログ部の影響を受けます。何らかの問題がある場合はデータの不一致や誤認識、欠落が発生します。これが発生しないようにクリアすべき電気的な基準がUSB規格で規定されています。

 Full Speed(12Mbps)も低速とは言え高速シリアル転送ですのでジッタに関する規定もあり、測定時には一目で判定できるようにアイパターンが規定されています。これまでの私たちの経験では、USB Audio機器が正しく認識されないようなケーブルや、データ転送の途中で転送を止めてしまうようなケーブルはこのアイパターンテストで不合格となります。

 USBの転送時に使用されるClockは両側のUSBコントローラの発振回路(TAS1020Bでは6MHzの水晶を使用し、内部のPLL回路でFull Speed転送に必要な48MHzを作成しています。)でつくられていますが、Audio DataがIsochronous Packetとして転送される場合、受信側は送信側のSpeedに合わせるため、PLL回路を動作させて送信側のClockに追従してLockさせたClockを使用します。したがって、前回の図-36-1からもおわかりのようにPCからのUSB Clockおよび受信側のUSB ClockはAudio DataをI2Sに変換するためのAudio Clockとは全く別のClockです。Host(PC)から送り出されてくるUSB DataからS/PDIFのようにAudio用のClockを作成しているわけではありません。ましてやPCのClockがアプリケーションソフトウェアの動作により影響されてゆらいだままノイズを載せてUSB Audio機器に入り込んでくるということはありません。iTunesでCover Flowなどを動作させるとUSB Audio接続のAudio機器~ブツブツ音が聞こえるというのは別の原因です。

 PCとUSB Audio機器双方のUSBコントローラ相互間はSYNCモードですが、PC側と機器側のAudio Clock(LRCLK,MCLK)は完全に独立したClockを使用しますので一般的な定義ではASYNCということになります。しかし、サンプリング周波数と位相(LRCLK)、各Ch.のbit数が一致しないと音楽の始まりやつながり、テンポや音程が無茶苦茶になってしまいます。MIDIの場合は音符のコードや小節ごとの同期コードなどが決められていましたがUSB Audioの場合はそんなものは何もなく、いきなりバイナリ('0'と'1'の組み合わせ)データが送られてきます。したがって、単なるASYNCではStart bitもStop bitもありませんのでどこが曲の始まりか、どちらがL.Ch.のデータかR.Ch.のデータかわからなくなってしまいますので送り出し側(PC)と受信側(USB Audio機器)の間でSoftware(プロトコル)レベルで同期をとることが必要です。

 図-37-1を参照してください。前回の図-36-1ではfs(LRCLK)が48kHzで1mSのUSB Frame間に整数個のデータがきちんと収まる場合を図示していますが、図-37-1ではCDを非圧縮でRippingした44.1kHzのデータの場合を図示しています。CDがUSBよりも10年も前に普及し、音楽ソースとして無視できない存在ですのでUSB Audioの規格を決めた人達もずいぶん苦労されたようですが、この44.1kHzや88.2,176.4kHzというfs(1msで割り切れない)にはずいぶん苦労させられます。これまでも何度かお話しましたが、44.1kHzの場合、USB Audio Driverの10mS分のスタック上に1パケットあたり44サンプル分のデータが9パケット分と45サンプル分のデータが1パケット分積み上げられ、順番にUSB Bus上に送り出されます。

37_20100202a2

<図-37-1>fs=44.1kHzの場合

 以下は図-37-1を参照しながら読み進めてください。

 まず最初のPacketの受信が終了し、次のFrameのSOFが検出されると最初の44組のデータをI2Sに変換しなければなりません。ただし、LRCLKは44.1kHzですので次のSOHまでの1mSまでの期間に2.27μS(1.0mS – 1/44.1k x 44 )の隙間(GAP)ができてしまいます。音楽の途中でこんなGAPがあると音が狂ってしまったり、バチッというLPレコードの引っかき傷のような音が出てしまいます。そのため、次のパケットの先頭一組を取りだしてきてくっつけます。2番目のパケット内のデータを送り終わった後では4.54μS、3番目のパケット内のデータを送り終わった後では6.81μS…とだんだんGapが大きくなり、9番目のパケット内のデータを送り終わった後には20.43μSとなります。この時点で10番目のパケットの最初の組をくっつければ10番目を転送した直後は11番目(最初のFrameは転送しないので)のSOHに一致します。したがって、USB Audio機器側でもPacket10個分(10mS分)のバッファメモリを用意すればSoftwareやHardwareが簡単になりますが、16bit/44.1kHzで1,764バイト(4×441)、24bit/96kHzにも備えておくとすると5,760バイト(6×960)のRAMが必要となります。現時点で入手可能なUSB Audio StreamコントローラのTAS1020Bを例に取るとEndpointやBufferとして使えるRAMは最大で1304バイト程度ですので10mS分のバッファは用意できません。TAS1020Bではひとつながりのリング状にバッファを設定することに(Circular Buffaer)よって、この44.1kHzベースのAudio dataに対応しています。

  パケット内のデータを取り出しI2S(LPCM) Streamに変換するためには各Ch.(L,R)のbit数、fsに関する情報が必要です。USB DACやUSBトランスポートなどのIsochronous Out転送の場合、これらのパラメータを決定する主導権はPC上のSoftware(iTunes/QuickTime PlayerやMedia Player,KernelMixerなど)にあります。また、実際に使用する上でも、楽曲ファイルのフォーマットに従って転送が行われ、USB Audio機器側では何の操作する必要がないほうが最も使いやすいと思います。たとえば16bit/44.1kHzでRippingされた楽曲ファイルを選択すればUSB Audio機器やAudio機器側で何も操作せずとも16bit/44.1kHzで再生され、24bit/96kHzでRippingされた楽曲ファイルを選択すれば同様に24bit/96kHzで転送されて再生されるという具合です。

 Isochronousの転送モードがASYNCであるか、SYNCかAdaptiveであるのかに関係なくUSB AudioではHost側(PC)がUSB Audio Deviceから取得したDevice Descriptorを解析し、その機器が24bitにも対応しているのか、それとも16bitだけにしか対応していないのかInterface descriptorを元に判断します。そして、Audio Data Streamに関するInterface Setごとに、ReadyかどうかをRequestを出してUSB Audio機器側に問い合わせます。

 本Blogの#33-図-2に示すRAL-2496UT1の例ではInterface Set#1が16bit用、Interface set#2が24bit用として記述されていますので、PCからSet#2はReadyかどうか、Set#1はReadeyかどうかというRequestが発信されてきます。USB Audio機器(RAL-2496UT1)側ではこの時点ではPCからどんなフォーマットのAudio Data Streamが送られてくるのかということが不明ですので、とりあえず、すべてのRequestに対してReadyを返しておきます。

 PC側でiTunesやMediaPlayer,fooberなどのアプリケーションを起動するとQuickTime Player, Control panel, アプリケーション自体の設定に基づいて、bit数を指定するためのSet InterfaceRequestがUSB Audio機器に送られます。このRequestに対してUSB Audio機器がReadyを返せば、その時点でそれ以降のAudio Data Stream転送で使用されるbit数が決定されることになるわけです。RAL-2496UT1の場合は図-37-2のように音楽データ(Isochronous)に先立って、Set Interfaceが送られて来ます。ただし、bit数が既知(ひとつ前の楽曲再生と同じ場合はSet Interface Requestは発行されませんので、USB Audio機器側は同じbit数のモードを維持し続けなければなりません。次に再生する楽曲のbit数が変更される場合は前述のようにそのbit数に対応したSet InterfaceがHost(PC)から発行されます。図-37-2の場合は24bitのAudio Data Streamを送るということをPCからRAL-2496UT1に通知していることを示しています。

37-20100202b

Packet 5102 がSET_INTERFACE Request で Alternative Setting#2(02, Ch.あたり24bit)を指定しています。

<図-37-2 USB Host(PC)からUSB Audio Device に対するbit 数の指定>

 サンプリング周波数(fs)の指定に関しても同様にHost(PC)はInterface Descriptorを参照します。#33-図-2RAL-2496UT1の場合は16bit、24bitそれぞれのbit数で44.1,48,88.2,96kHzの4種類に対応していると記述していますのでPCはiTunesやMediaPlayerなどの指定にしたがって、どれかのサンプリング周波数に基づいてファイルから読み出したAudio Dataを{(bit数/8) x (fs/1000)}バイトずつ一つのパケットに詰め込みます。例えば24bit/96kHzの場合は(6 x 96)バイトを一つのパケット(1mS分)に詰め込むことになります。

 その後、Audio Dataが詰め込まれたパケットを10個ずつusbaudio.sysに渡して転送実行を命令します。これらのパケットがぞろぞろとUSB bus上を一列縦隊行進しながらUSB Audio機器にやってきます。ところがUSB Audio機器側には、bit数の時のように届く予定のAudio Dataに関してあらかじめfsに関する情報は何も通知されていません。したがって、USB Audio機器側では届いたPacket内のAudio Dataのバイト数からfsを算出しなければなりません。各Ch.のbit数はあらかじめわかっていますからバイト数を6(24bit)もしくは4(16bit)で割り、その商に1,000を掛けるとfsが得られます。前述のようにfsが44.1kHzの場合には商が44であったり45であったりしますが、それはF/Wでfs=44.1kHzと処理することにすればOKです。88.2kHzの場合には88組のパケット4個に続いて89組のパケットが1個という順番で送られてきますので商が88か89だったらfs=88.2kHzと処理することになります。

 Isochronous転送でモードがASYNCの場合にはプロトコルの規格上はDevice側で使用するfsを問い合わせるRequestとそれに対する応答用のEndpointがやり取りされることになっていますが、現実にはそんな面倒なことは行われていません。また、規格上はパケット内のバイト数をCheckしてfsを割り出すのはAdaptiveモードですが、Isochronous Out EndpointのMode bit(ASYNC、SYNC,AdaptiveのModeセット用)をいくら換えてもHost側の挙動には変化がありません。USB Audio機器側がfsを検出するためには、Host(PC)側はパケットサイズによって通知するしかありません。

 Deveice DescriptorのInterface Setの記述方法を一つのbit数/fsごとに記述する方法によりSet Interface requestでbit数/fsを選択する方法もありますが、KernelMixerなどが、機器が対応している最高の組み合わせに内部で勝手にサンプリングレート変換を行ってしまうという問題があります。また、USBマイコン側の問題としてはDevice Descriptor用にそんなに大きなEndpointを用意できないという問題もあり難しいところです。また、QuickTimeやFooberなども指定したbit数が常に使用されてしまうという問題がありますので、この記述方法は最近ではあまり使用されていません。 ただし、独自のfs、bit数設定用のApplicationをあらかじめインストールするタイプのUSB DACなどはこの方法を採用していますが、独自のアプリケーションやドライバをインストールしなければならないこと、OSやiTunes、MediaPlayerなどのVersionが変わるたびにそれらに対応した新しいドライバやアプリケーションが必要になるという問題などがあります。 また、FOSTEX HP-A3のように16/96kHzと24/96kHzにのみ対応と記述されたDevice Descriptorを持つUSB Audio機器の場合、KernelMixerなどがDescriptorに基づいてUSB Audio出力のfsをすべて96kHzにサンプルレート変換して送り出します。たとえば16/44.1kHzでRippingされた音楽ファイルを再生する際にはPC側のSoftwareでサンプルレート変換が行われます。この場合もfsの指定などのRequestはPCからは発行されず、すべてのIsochronousパケットのサイズ(バイト数)が576または384となるだけです。

 USB Audioでbit数やサンプリング周波数が決められている方法はこのようなシンプルな方法です。プロトコルの規格上はいろいろと面倒なことが記載されていますが、USB DACやUSBヘッドホン、USBスピーカーなどのIsochronous Out専用の場合はこのような簡単な方法が採用されています。

 「USB Audioでのサンプルレートの指定方法」について昨年10月にYHさんからコメントをいただいておりますので回答させて頂きます。

 ご質問の件は上記のように「パケット内のバイト数により指定されている」というのが現実です。USB Audioの規格書では「implicitな指定」と記述されています。また同じコメントで「データパケットの間隔をPLLで逓倍してDACのClock(I2SのLRCLKやMCLK)を作成している。」と記述されている他のblogに関しても言及されていましたが、これはYHさんのおっしゃるとおり正しくありません。DAC用のClockはPC側のクロックとは全く関係なくUSB機器側で作成します。USBで必要な48MHzや12MHzなど内部のマイコンの動作クロックの作成に使用される6MHz水晶発振子を共通に使用して周波数シンセサイザで24.576MHzや22.5792MHzを作成しています。あるいは別に搭載されているAudio専用の水晶発振回路でそれらの周波数のClockを作成しているかのどちらかです。どちらを選ぶかはそれらのMCLKそのものやMCLKから作成されたfs(LRCLK)のJitterが少ない方ということを基準にすればよいと思います。前回の#36でも説明しましたがUSBのSOFの間隔(Frame間隔・1ms)は一定ですが、パケットとパケットの間隔は一定ではありません。したがって、YHさんのご意見が正しいということになります。

 「バイナリデータの不一致」に関して「えるえむ」さんからも昨年12月にコメントをいただいております。今回の記事をお読みいただければおわかりのように、ファイルから読み出したバッファメモリ上の音楽データは、当然HDDなどに記録されたものと「バイナリ一致」が保証されていますが、usbaudio.sysへの10ms分・10個のパケットの引き渡し以降は一切、Errorチェックも訂正もありません。Isochronous Dataが壊れているというErrorは通知されますが再送要求などはありません。また、Isochronousデータは受信が終わって初めてサイズがわかるという代物です。なぜ、Errorチェックや再送要求があるBulk転送が使用されないのかということは別稿で説明します。

 USB Audio Streamの転送についてはこれくらいにして次回はJitterについて実測結果などをもとにお話を続けたいと思います。

#37 USB Audioについて(その5 bit数とSampling Rateはどのようにして決められるか)」への2件のコメント

  1. 大変詳細なご説明,いつも楽しく拝見しております。
    私が12月に申し上げた質問について,私の言い方が悪かったせいで,質問の趣旨が伝わっていないような気がいたしましたので,改めて書かせて頂きます。
    これは別の言い方をすれば,「Windowsのカーネルミキサーは信用ならない。ユーザーの知らないところで勝手に(通知せずに)リサンプリングを行っている。だから音楽データを正しく再生するにはカーネルミキサーを経由しない音楽再生手法(ASIOやKernelStreaming)が望ましい。」というよく言及される点について,どのようにお考えか,ということです(重大な問題だ,たいした問題ではない,等)。
    さらに別の言い方をするならば,
    (1)RAL-2496UT1はカーネルミキサーを経由するのですか?
    (2)RAL-2496UT1を使用した場合に,カーネルミキサーが勝手にバイナリを改変しないようにするための手段はあるのですか?
    ということをお伺いしたかったのです。
    本文の「Isochronous転送でモードがASYNCの場合にはプロトコルの規格上はDevice側で使用するfsを問い合わせるRequestとそれに対する応答用のEndpointがやり取りされることになっていますが、現実にはそんな面倒なことは行われていません。」というご指摘は大変興味深いもので,改めて考えさせられるものでした。
    このように,枠組みとしてはその通りだけれども,実際は違う,といったことがカーネルミキサーの点でもあり得ると思いますので,的外れな質問をしているようでしたら,平にご容赦ください。

  2. レート設定の疑問にお答え頂きありがとうございます。
    1パケット内のサンプル数により決定されているとの事ですが、44.1や88.2の際の処理を見るにその切替も大雑把に決定していて、43サンプルのデータが送られてくるからレートが43khzになるという訳では無いという解釈で問題ありませんでしょうか。
    (そもそもそんなサンプル数のデータが送られてくる事は無いと思われますが…)
    また、パケット間隔やSOF間隔を元にDACクロックを作ってはいないとの事ですが、その場合受信側バッファのオーバーフロー/アンダーフローの可能性があるかと思われますが、それに対してはどういった対処をされているのでしょうか。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です