web-dev-qa-db-ja.com

WASAPI共有モードを使用して10ミリ秒未満の遅延を取得するにはどうすればよいですか?

Microsoftによると、Windows 10以降、共有モードWASAPIを使用するアプリケーションは10ms未満のバッファーサイズを要求できます( https://msdn.Microsoft.com/en-us/library/windows/hardware/mt298187%を参照) 28v = vs.85%29.aspx )。

記事によると、このような低レイテンシーを達成するには、いくつかのドライバーの更新が必要です。排他モードのレンダリングおよびキャプチャストリームを使用して、約13ミリ秒の合計ラウンドトリップ遅延(ハードウェアループバックケーブルを使用)を測定しました。これは、エンドポイントの少なくとも1つが10ミリ秒未満の遅延を正常に達成していることを私に示唆しています。 (この仮定は正しいですか?)

この記事では、アプリケーションが新しい_IAudioClient3_インターフェイスを使用して、IAudioClient3::GetSharedModeEnginePeriod()を使用してWindowsオーディオエンジンでサポートされる最小バッファーサイズを照会できると述べています。ただし、この関数はシステムで常に10ミリ秒を返し、IAudioClient::Initialize()またはIAudioClient3::InitializeSharedAudioStream()を使用して10ミリ秒未満の周期でオーディオストリームを初期化しようとすると、常に_AUDCLNT_E_INVALID_DEVICE_PERIOD_になります。 。

念のため、オーディオドライバーのエフェクト処理も無効にしました。何が足りないのですか?共有モードから低遅延を実現することも可能ですか?サンプルコードについては、以下を参照してください。

_#include <windows.h>
#include <atlbase.h>
#include <mmdeviceapi.h>
#include <audioclient.h>
#include <iostream>

#define VERIFY(hr) do {                                    \
  auto temp = (hr);                                        \
  if(FAILED(temp)) {                                       \
    std::cout << "Error: " << #hr << ": " << temp << "\n"; \
    goto error;                                            \
  }                                                        \
} while(0)


int main(int argc, char** argv) {

  HRESULT hr;
  CComPtr<IMMDevice> device;
  AudioClientProperties props;
  CComPtr<IAudioClient> client;
  CComPtr<IAudioClient2> client2;
  CComPtr<IAudioClient3> client3;
  CComHeapPtr<WAVEFORMATEX> format;
  CComPtr<IMMDeviceEnumerator> enumerator; 

  REFERENCE_TIME minTime, maxTime, engineTime;
  UINT32 min, max, fundamental, default_, current;

  VERIFY(CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED));
  VERIFY(enumerator.CoCreateInstance(__uuidof(MMDeviceEnumerator)));
  VERIFY(enumerator->GetDefaultAudioEndpoint(eRender, eMultimedia, &device));
  VERIFY(device->Activate(__uuidof(IAudioClient), CLSCTX_ALL, nullptr, reinterpret_cast<void**>(&client)));
  VERIFY(client->QueryInterface(&client2));
  VERIFY(client->QueryInterface(&client3));

  VERIFY(client3->GetCurrentSharedModeEnginePeriod(&format, &current));

  // Always fails with AUDCLNT_E_OFFLOAD_MODE_ONLY.
  hr = client2->GetBufferSizeLimits(format, TRUE, &minTime, &maxTime);
  if(hr == AUDCLNT_E_OFFLOAD_MODE_ONLY)
    std::cout << "GetBufferSizeLimits returned AUDCLNT_E_OFFLOAD_MODE_ONLY.\n";
  else if(SUCCEEDED(hr))
    std::cout << "hw min = " << (minTime / 10000.0) << " hw max = " << (maxTime / 10000.0) << "\n";
  else
    VERIFY(hr);

  // Correctly? reports a minimum hardware period of 3ms and audio engine period of 10ms.
  VERIFY(client->GetDevicePeriod(&engineTime, &minTime));
  std::cout << "hw min = " << (minTime / 10000.0) << " engine = " << (engineTime / 10000.0) << "\n";

  // All values are set to a number of frames corresponding to 10ms.
  // This does not change if i change the device's sampling rate in the control panel.
  VERIFY(client3->GetSharedModeEnginePeriod(format, &default_, &fundamental, &min, &max));
  std::cout << "default = " << default_ 
            << " fundamental = " << fundamental 
            << " min = " << min 
            << " max = " << max 
            << " current = " << current << "\n";

  props.bIsOffload = FALSE;
  props.cbSize = sizeof(props);
  props.eCategory = AudioCategory_ForegroundOnlyMedia;
  props.Options = AUDCLNT_STREAMOPTIONS_RAW | AUDCLNT_STREAMOPTIONS_MATCH_FORMAT;

  // Doesn't seem to have any effect regardless of category/options values.
  VERIFY(client2->SetClientProperties(&props));

  format.Free();
  VERIFY(client3->GetCurrentSharedModeEnginePeriod(&format, &current));
  VERIFY(client3->GetSharedModeEnginePeriod(format, &default_, &fundamental, &min, &max));
  std::cout << "default = " << default_ 
            << " fundamental = " << fundamental 
            << " min = " << min 
            << " max = " << max 
            << " current = " << current << "\n";

error:
  CoUninitialize();
  return 0;
}
_
22

上記のコメントのハンスによると、低遅延オーディオの指示に従っていることを再確認してください ここ

念のため、マシンを再起動します。 Windowsは、そのようなことには少し厄介かもしれません。

0
TriskalJM