Win10での低遅延サウンド再生方式対応
まず、manifestを修正して、Win8.0互換モードで動かさないようにだけしてみました。その結果、Win10 Creators Update, オンマザーサウンドでバッファが
になりました。
なんでWASAPI排他で悪化するかなー。
一方、WASAPI共有はぎりぎり我慢できなくもないくらいの体感になりました。
その後、うちの環境で何度も実験してみましたが、どうも、manifestでWin10モードを使わないようにして、Win8.0互換で動かすようにしたほうが、バッファを小さく設定できて、動作負荷も軽いようです。(具体的な結果はひとつ前のコメントを参照ください)
Win8.0互換に戻そうかな・・・
うちの環境:
おつですー。
最近WASAPIの勉強しなおしてみようと思っていろいろなサイト見てたら気づいたんですけど、(低遅延じゃない場合の)WASAPI共有のバッファサイズって「遅延」じゃないっぽいですね。
ほぼすべての技術ページで(MSDNのLowLatencyAudioでも)「latency」じゃなく「period」と言ってるので、バッファサイズから算出できるのは、WASAPI排他でいう「更新間隔」だけなんじゃないかなと。
ついでに、その「バッファ」というのも「AudioEngineのバッファ」じゃなくて「アプリのバッファ」なんじゃないかなと。
また、実測によると、WASAPI共有モードでは指定したperiodが10msであるなら、バッファのサイズが22msであっても、10msごとにイベント駆動されてるなと。
結論、共有モードの実際の遅延はやっぱり100msくらいありそうですね……
WASAPI共有について、BASS.NET APIの、BassWasapi.BASS_WASAPI_Init Methodのところを読んでみると、最後にこんなことが書いてありました。
WASAPI共有時は "it's the other way round" (periodとbufferの依存関係が逆転する)、つまりbufferサイズにperiodが影響を受けて、更に結局それはdefperiodのサイズにアラインされるということです。FROMさんのご指摘は正解のようです。
In EXCLUSIVE mode, the "period" value will affect what's an acceptable "buffer" value (it appears that the buffer must be at least 4x the period).
In SHARED mode, it's the other way round, the "period" will be reduced to fit the "buffer" if necessary (with a minimum of the "defperiod" value).
The system will limit them to an acceptable range, so for example, you could use a very small value (eg. 0.0001) for both, to get the minimum possible latency.
初期化のロジックは、WASAPIの排他と共有で、別々に作りこまないといけなさそうですね。明日にでもコードを組みなおします。
WASAPI共有のラグが結局100msくらいありそうだというのには同感です。私の体感でも、その程度だと感じています。
# しかし、いい加減、WASAPI周りをこねくり回すのにも飽きてきました(苦笑;;;
つい先日、BASSWASAPIがWIndows10のlow latency audioに対応しました! これで試してみます。
BASSWASAPI 2.4.2 released
Adds support for lower latency shared mode on Windows 10, more precise latency measurement, buffer size specification in samples, and notification of unexpected stoppages.
というわけで、軽くテスト版を作りました。(実はちょっとてこずった・・・) お試しくださいますか。
https://osdn.net/users/yyagi/pf/DTXMania_TestBuilds/files/?id=2724
その後いろいろと頑張ってみましたが、
より小さく設定することができず、それがそのまま11ms, 14ms (7ms)というレイテンシになっているようです。
まあ、BASSだとこれくらい、ということなのでしょう。
WASAPI共有かつEventDriven有効時に、もう少しバッファサイズを減らせると思ったのですが・・・減りませんでした。残念。
少し修正を入れました。こちらをお試しいただけると幸いです。
コミットログには110からの更新点を記載していますが、先日のlow latency対応版からの違いはこちらです:
Rel111で対応完了したため、クローズします。
Win10 19H1 (1903)のせいなのか、それともPCをAMDモデルに新調したからなのかは分かりませんが、 自宅環境でWASAPI共有モードを使うと10ms前後のlatencyにならなくなりました。 WASAPI共有だとどうやっても44msくらいになってしまう。
WASAPI排他+WASAPIEventDriven=ONで8msにはなるのですが。
プログラムもソースコードやログ出力を見てもおかしなところはなく、 手動で最適な初期化パラメータをぶっこんでも44msになる。
うー切り分けが面倒くさい。とりあえず昔使っていたIntel機(RS5: 1810)で試して、 次にそいつを19H1(1903)に上げて再確認して・・・。又はサウンドドライバの問題か。
うちのドラムPCも今日やっと(1時間もかけて)1903にUpdateしたばかりなのですが、その後の DTXMania2(WASAPI共有のイベント駆動で固定)の試打では、特に問題はありませんでしたよ。
# FAST/SLOWのチェックをやってたので、遅延の問題があれば即わかる…… はず……?(自信なし
後日こちらでも試してみますね。
(1903になったらドラム用ユーザが部分的に初期化されててプチおこです💢)
1903の適用お疲れさまでした。適用時間は今までとあまり変わらないですよねぇ。ダウンタイムは確かに短くなってはいるのですが。
そちらの環境ではDTXMania2で問題なかったという情報、ありがとうございました。 こちらはその後こんな感じです。
うーむ。
だいたい解明できました。たぶん。
大きく3つの要因がありました。
(1) 共有モードのバッファサイズ「44ms」を計算している個所で、サンプルサイズを 2 と決め打ちしています。
→ sizeof(FLOAT) = 4 なので、これで計算しなおすと、正しくは「22ms」になります。
(2) イベント駆動共有モードでは、バッファサイズ(buffer)ではなくデバイス期間(period)が10ms固定になります(Win7以降)。で、バッファサイズはその2倍の20msになるようです。
→ うちのRealtekHDAudioの場合、デバイスのネイティブバッファサイズが 8448 バイト、イベント駆動時のバッファサイズが 7680 バイト、イベント発生時の更新可能サイズがその半分の 3840 バイトになりました。48kHzなので、3840バイト=480サンプル=10msとなり、バッファサイズは20msになります。(DTXManiaでは8448から計算しているので、22msです。)
(3) Win10以降の共有モードのイベント駆動では、(バッファサイズではなく)デバイス期間を10ms未満に設定することができます。ただし、サウンドドライバが対応している必要があります。
→ うちのRealtekHDAudioの最新のドライバでは480サンプル(48kHzで10ms)が下限でした。で、ドライバをMS謹製の「HDAudioデバイス」に変えると、128サンプル(48kHzで2.666...ms)が下限になりました。 (REALというアプリで、現在の既定のサウンドデバイスの最小・最大・デフォルトバッファサイズを手軽に確認できます。→ https://github.com/miniant-git/REAL )
結論:
現状、LowLatencyAudioに対応するのはMS謹製のHDAudioドライバだけ? orz
p.s.
DTXMania2も22msでした。
どうも、ごかくにんいただき、ありがとうございます。ご丁寧にご説明いただき、ありがとうございます。bufferとperiodのかんけいはりかいしていたつもりでしたが、最終表示の段でそれが全然生かされてなかったですね・・・
ちなみに、共有モードのバッファサイズ2倍という話、どこかにきさい、ありましたっけ。 イベント駆動時に2倍になるというのはありましたが、共有モード時に2倍というのは見つけられず。
・・・共有モードが実質イベント動作みたいなものですが。
仕事で手が回らないので、まずは御礼まで。REALでの環境調査等諸々、もう少々お時間ください。
共有モードのバッファサイズ2倍という話、どこかにきさい、ありましたっけ。 イベント駆動時に2倍になるというのはありましたが、共有モード時に2倍というのは見つけられず。
いえ、イベント駆動であれば、排他・共有ともに2倍になるようです。
イベント駆動でない排他モードは1倍でした。
イベント駆動でない共有モードは、試してないですが、1倍だと思われます。
そうそう、REALでの動作確認結果です。
→ うちのRealtekHDAudioの最新のドライバでは480サンプル(48kHzで10ms)が下限でした。で、ドライバをMS謹製の「HDAudioデバイス」に変えると、128サンプル(48kHzで2.666...ms)が下限になりました。
私の旧開発環境や、NECPCのモバイルPC、Surface Pro 2などでは、これと同じ結果になりました。これらは全部IntelのCPUです。(Win10 19H1 (1903)のせいか、ドライバ差し替え時に表示されたドライバ名は「High Definition Audio デバイス バージョン: 10.0.18362.1 [2019/03/18]」でした。)
一方で、今メインで使っているAMD CPUを搭載したPCでは、最新ドライバ適用後も480サンプルで、上記のMSドライバを入れるとサウンドの出力先が見えなくなり、DTXManiaでは使えなくなりました。デバイスマネージャーでは見えている(!もついていない)のですが、出力先が見えなくなります。
AMD環境はもう少し母数を増やして調査したいところですが、
結論: 現状、LowLatencyAudioに対応するのはMS謹製のHDAudioドライバだけ? orz
少なくとも、よくあるオンマザーのサウンド機能としては、残念ながらそういうことなのでしょう。ユーザーに手動でドライバの置き換えてもらうのは、ちょっと敷居が高いですね。(一応FAQにも書いておきます)
p.s.
# REALを試してみたい方はこちらをどうぞ: tp://27.120.112.29/real-app.zip
すみません、私がビルドしたREALはdebug buildだったので、ランタイムの準備でいろいろ面倒なことになります。
metageeksさんがReleaseビルド版を配布されていたので、興味がおありの方はこちらのバイナリをお使いください: https://www.majorgeeks.com/files/details/real.html
Win10では、WASAPI共有での出力遅延を10ms程度に収めるような実装が可能とのことで、これに対応する。
BASS_Mixerの出力まではBASSで扱って、最終出力を自力実装するような感じでしょうか。