高品位サウンド
AC97が過去のものとなり,HDAがデフォールトとなって久しいわけですが。HDAというのは,1台目のHDDに見えてしまうのでなんとかなりませんか。どうでもいいことですが。
どうなんでしょうかね。ず~っと前から気になっているのですが,遅延についてどこまで真面目に考えていますか?
サウンドというのは根本的にストリームです。なので,リングバッファあるいは複数バッファをリンクドリストで管理することになるわけです。
PCIデバイス的にはメモリ(メインメモリまたはデバイス上のメモリ)とIO(AC97)間の単なるDMAです。DMAに息継ぎさせないようにするには,最低でもダブルバッファ構成が必要です。CPU側に余裕を持たせるには3つ以上のバッファを用いたいところでしょうね。と書くと最近のCPUは早いから大丈夫とかメモリが速いから大丈夫とか。うるさいぼけ。
どうなんですかね。割り込み処理(DMAの転送終了割り込み)つうのは,いわゆるメモリアクセスの局所性をぶち壊しますしパイプラインそっちのけですよね。だからこいつが短い周期でバンバン発生するだけで,いろんな努力の相当部分が無駄になるような気がします。
ここではCPUの性能についてはどうでも良いとしましょう。
メモリ←→デバイス間のDMAで,まず1段バッファがあるわけです。
さて,MMIOやDirectSoundで例えばwavデータを流し込む場合,複数のプロセス/スレッドから同時に流し込むことが可能です。ミキシングは適当にやってくれることになっています。これはハードウェアがやるのかソフトウェアがやるのかどちらでしょうかね。
DirectXの診断プログラム(dxdiag)でサウンドのところをいじくると,
ウチのカードはハードウェア上のバッファメモリがないらしいことがわかります。つうことはHALレベルで複数のバッファを持って,DMA転送する前段階でミキシングしている,ちゅうことになりませんか?当然のことですが,ビットレートや8/16ビット,モノラル/ステレオの変換もやってくれるようです。
これが2段目のバッファですわ。
チエンについて検討しましょう。この際パフォーマンスはメンドウなので考えず,ダブルバッファ前提で。どれくらいメンドウかは,DXのサンプルのCStreamingSound::HandleWaveStreamNotification()辺りを見れば分かるよろし。あるいは私自身がはげしくデジャヴュを感じた記事もどぞ。
話を単純にしましょう。(書くのめんどくなってきた)
2つのバッファのサイズは同じ。片方を転送中(つまり再生のために転送中でロック状態)にもう片方へデータを流し込むこととします。データを流し込みはじめる時間と,実際にデータが転送されはじめる時間の差は最大でバッファの長さ分ということになります。これを短くしたければ,ギリギリまで粘ることになります。それはバッファアンダーランとのチキンレースですね。とりあえず平均でバッファ長の半分にしておきましょう。これはかなり甘い見積りだということを覚えておいてください。
ということはバッファが1段あれば,バッファ長の半分をビットレートで除した時間のチエンが生じることになります。
計算例:
バッファ長:4096バイト
フォーマット:16ビットステレオ44100Hz(176.4kB/sec)
→4096/2/176.4kB=およそ11.6msec
です。これが2段ですと,23.2msec。
これつまり60fpsなら1フレーム以上ちゅうことになるわけですわ。
どんなにすごいサウンドハンドリングをしても,1フレーム遅れるんです。バッファを小さく小さくとてもピッコリーノにすりゃいいんじゃないの?ごもっともです。どぞどぞ。5.1chなら秒辺りのバイト数がもっと多いからそんなに気にしなくていいんじゃないの?ごもっともです。
ジジィの迷い箸として以下の点について書いておきます。
- サンプルレートを下げるとチエンは増大する
- モノラルなら倍のチエン
- 内部でフォーマット変換されるから関係ない
- 自前でミキシングなんて狂気の沙汰
上の計算を見ればあきらかですが,例えば44100を22050にすればチエンは倍増です。同じようにモノラルならさらに倍増です。つまり44100ステレオよりも22050モノラルの方がチエンが4倍になるということです。チエンはCPUやバスに与える負荷とはあまり関係ないのです。その点にぜひ目を向けていただきたい。
3点目は,2つの点についてひっくりかえす事実を突きつけます。そうです。モノラルで指定しようが,22050に指定しようが,どこかの誰かが勝手にフォーマットを変換します。おそらくDMA転送の1段目ではなくその上の2段目だと思われます。ということは,ここに書いたチエンの見積りはあまりアテにならないということです。
嗚呼なさけない。
ムカツクので,チエンの測定を検討しましょう。どうやって?
いいですか。現代的OS上では精度良く計測することなんてできません。
MMIOにwavデータを投げた瞬間にLEDを点灯させる
そんな簡単なことができないんです。しかしそれでもどこかにパラレルIOを繋いで測定しても無駄ではないでしょう。プリンタポート用のLED箱を持ってるジャン>ごみためまんよ
双方向に設定するのがメンドイ
そしてそんなことはきっとどこかの暇人がデータ収集済みなのです。どうせ環境依存度が高いデータです。メンドウなだけで再現性もなく,他人の環境では使えない。そんなデータを集めて一体なんの役に立つでしょうか。
ここがごみためだからやるんです。
(英語でググった方が速くないか?)
ごみためのランキングはこちら。
(2008.05.01追記)
たぶん、DTMでは遅延(レイテンシ)は一般的に認識されているのでしょうが、アマチュアは堂々巡りをするのがデフォルトなのかもしれません。そんな質問を見かけました。
DTMをしていますが
(2008.05.04追記)
MSDNのDirectSoundの解説記事で、遅延について触れている部分があります。
DirectSound によるドラム マシンの作成http://www.microsoft.com/japan/msdn/columns/code4fun/code4fun02032004.aspx
・・・再生の遅延を減らすために、バッファに追加するデータの量を一定量に抑えていることに注意してください。遅延は、着信するオーディオ ストリームの変化が生じてから、その変化が実際に耳に聞こえるまでのずれとして定義できます。このような遅延制御を行わなかった場合、平均的な遅延は合計のバッファ長とほぼ等しくなり、リアルタイムのシンセサイザには許容できない長さとなる可能性があります。・・・
とにかくそういうことです。
ただ単純にサンプルをつぎはぎしても、まともな出力は得られません。
発声の遅延は、難しい問題です。音が波であるということはご存知でしょうが、では波の開始点というものをどうやって知るかという問題があります。
まぁ考えてみてください。
| 固定リンク
「プログラミング」カテゴリの記事
- VS MS-Word Highlighter2013(2015.07.08)
- テストマシンと環境(2004.02.08)
- Eclipse on Debian(2004.03.02)
- VSSで普通のファイルを管理する その2(2004.06.21)
- WTL7.5をVC6で使ってみる(2004.06.23)
コメント