WASAPIを使うと譜面がガタ付く (フォーラムメッセージ #75049 からの引用)
あと、ASIOの場合は毎回の転送データ数が固定量なので、先述したとおり、最初だけ巻き戻って、あとは順当に進むことになります。 なので、ASIO4ALLで発生していた現象とも符合すると思います。
あ、最初の記事の「チャンネル数8のPCはチャンネル数2のPCより4倍多くのデータ転送を行うので、更新間隔が1回遅れると現在時刻も4倍過去へトリップ」の部分は誤りですね。累積転送数も4倍になっているはずなので……。
検証してみた結果、この仮説以前の問題があったのでまとめておきます。(仮説が課題に変わります。)
なので、WASAPIタイマは設計から見直しが必要になります。
であれば、なぜ今WASAPIで(あまり)問題なく演奏できているのかについては、
ということが関与していると思われます。 Windows8 タブレット(Atom Z3770)でも、ときどき突っかかる以外、譜面のスクロールは滑らかでした。
同時再生数が増えるなどでかなりの高負荷にならない限り、ASIOと同じ現象が(安定して)起きる、ということになります。
このチケットの課題はまだ残っているので、引き続き、このチケットにてWASAPIで正確なタイマが得られないかどうかの再設計を行いますね。
フォーラム ユーザフォーラム [#75049] からの引用
[forum: 75049]
ツイート、見てますね……?(ニヤリ
それはともかく、この件についてチケットを起こしておきます。 ソースとしては既にFDK23にて実装が終わっているのですが、利用する側が対応してないので未検証なのですよ。
この問題の仮説は、更新間隔ごとにtWASAPI処理()で行う処理であるところの
「BASSへデータ転送 → BASSから未再生データ取得 → 時刻算出 → 累積転送数へ今回の転送データ数を加算」
の順番が間違っているのでは?というものです。
BASSにデータを同期処理で送った後に未再生データ数を取得してるので、それにはさっき送ったばかりのデータの数も含まれているはずですよね。 でも、時刻算出時の累積転送数にはまだ反映されていない。 そして、現在時刻を(累積転送数-未再生数)で算出してます。
つまり、最初に転送したデータの分だけ過去に戻ってしまうのです。
しかし、ここでもし毎回のデータ転送数が固定量ならば、最初だけ遅れてそれ以降タイムトラベルは発生しないはずだったのですが……、 WASAPIでは固定値にはなりません。毎回転送するデータの数は、バッファ全体のサイズや再生位置と書込位置、サンプルのサイズ(サンプリングバイト数×チャンネル数)、PCの負荷(更新間隔呼び出しの遅れ)などによって増減します。 例えば、簡単に考えてみても、チャンネル数8のPCはチャンネル数2のPCより4倍多くのデータ転送を行うので、更新間隔が1回遅れると現在時刻も4倍過去へトリップします。
この仮説への対策は、累積転送数への加算を時刻算出より前に持ってくるだけです。 このチケットでは、それを検証してみたいと思います。
p.s. 古いVSとSVNとDirectX SDKをインストールせねば(汗