WASAPI共有モードのレイテンシ

公開:2011-11-04 18:04
更新:2020-02-15 04:36
カテゴリ:wasapi,c++,dawもどきの作成,windows,audio,windows api

ドライバ設定画面はそこそこ動いている。私のハードの場合内蔵サウンドとE-mu0404の2種類のデバイスを選択できる。でもデバイスを指定するのではなくてWASAPIではあくまで端子(エンドポイント)単位である。アプリ側で出力を自由に切り替えられるのはWASAPIのいいところ。

共有モードのレイテンシ

共有モードで気になっているのはレイテンシ(遅延時間)。レイテンシとはデータを送ってから発音するまでの遅延時間のことである。共有モードは排他モードにくらべてレイテンシが大きい。共有モードのサンプルでは50ms以下を設定しようとしてもエラーで返すようになっている。


bool CWASAPIRenderer::Initialize(UINT32 EngineLatency)
{
    if (EngineLatency < 50)
    {
        printf("Engine latency in shared mode timer driven cannot be less than 50ms\n");
        return false;
    }
.
.

でもPlayPcmWinの情報では30ms以下はエラーという記述がされていて、ひょっとするとハードごとに異なるのかもしれない。

デバイスの遅延時間はIAudioClient::GetDevicePeriod()でデフォルトの値、最短の値を取得できる。私のデバイスではデフォルトが10ms、最短が3msであった。MSDNの解説によればデフォルト値が共有モードでの値、最短は排他モードでの値のようなことが書いてある。そうすると共有モードでも10msのレイテンシが指定できるのではないか。

そういえば「What's New for Core Audio APIs in Windows 7」にWindows 7は共有モードで低レイテンシ再生できるようになったと書いてあった。試しに10msのレイテンシで設定を試みたところ再生できた。

ちなみに10ms以下も設定できるが音が歪んでくる。Vistaの時はこんなに低レンテンシ再生はサポートされていないようなので、サンプルコードは互換性を重視して書かれているのかもしれない。

ただ私の場合、IAudioCLient::InitializeのBufferDuration値にレイテンシ×4つ分の値を指定しているので、実際は10ms×4のレイテンシかもしれない。BufferPeriod値がレイテンシだと思っていたけど、そうじゃないのかもしれない。このあたりまだよくわかっていない。。。

あとでレイテンシ×1にしてみたけど、やっぱり再生できた。この時気づいたけれど共有モードの時はBufferDurationにレイテンシ時間・BufferPeriodは0にセットするのだった。ちょっと凡ミス。またBufferDuration=レイテンシという認識も誤っているかもしれない。IAudioClient::GetStreamLatency()の返す値がそうなのかもしれない。しかしなんか変なんだよね。この値。。

ちなみに排他モードでは最短で1msまで短くできるただこれはハードによって異なり、私のデバイスでは最短で3msである。3msで再生するためにはプロセスの優先順位を「高」、MMCSSのcharacteristicsを「Pro Audio」にしないときちんと再生できなかった。