Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save spycrab/9c5a258ce37ee1e374f5d3ebf95d813c to your computer and use it in GitHub Desktop.
Save spycrab/9c5a258ce37ee1e374f5d3ebf95d813c to your computer and use it in GitHub Desktop.
From b83c80a6f1efda7fe7877928c6e9ad8b69e62f06 Mon Sep 17 00:00:00 2001
From: spycrab <spycrab@users.noreply.github.com>
Date: Mon, 28 May 2018 00:14:12 +0200
Subject: [PATCH] WASAPIStream: Use IAudioClient3
---
Source/Core/AudioCommon/WASAPIStream.cpp | 89 ++++++++++++++++++--------------
Source/Core/AudioCommon/WASAPIStream.h | 4 +-
2 files changed, 52 insertions(+), 41 deletions(-)
diff --git a/Source/Core/AudioCommon/WASAPIStream.cpp b/Source/Core/AudioCommon/WASAPIStream.cpp
index dd83ddb..e98430d 100644
--- a/Source/Core/AudioCommon/WASAPIStream.cpp
+++ b/Source/Core/AudioCommon/WASAPIStream.cpp
@@ -266,7 +266,7 @@ bool WASAPIStream::SetRunning(bool running)
PropVariantClear(&device_name);
// Get IAudioDevice
- result = device->Activate(__uuidof(IAudioClient), CLSCTX_INPROC_SERVER, nullptr,
+ result = device->Activate(__uuidof(IAudioClient3), CLSCTX_INPROC_SERVER, nullptr,
reinterpret_cast<LPVOID*>(&m_audio_client));
if (!HandleWinAPI("Failed to activate IAudioClient", result))
@@ -275,12 +275,26 @@ bool WASAPIStream::SetRunning(bool running)
return false;
}
- REFERENCE_TIME device_period = 0;
+ AudioClientProperties prop = {0};
+ prop.cbSize = sizeof(AudioClientProperties);
+ prop.bIsOffload = false;
+ prop.eCategory = AudioCategory_GameMedia;
- result = m_audio_client->GetDevicePeriod(nullptr, &device_period);
+ result = m_audio_client->SetClientProperties(&prop);
- device_period += SConfig::GetInstance().iLatency * (10000 / m_format.Format.nChannels);
- INFO_LOG(AUDIO, "Audio period set to %d", device_period);
+ if (!HandleWinAPI("Failed to set client properties", result))
+ {
+ return false;
+ }
+
+ UINT32 default_period = 0, fundamental_period = 0, min_period = 0, max_period = 0;
+
+ result = m_audio_client->GetSharedModeEnginePeriod(reinterpret_cast<WAVEFORMATEX*>(&m_format),
+ &default_period, &fundamental_period,
+ &min_period, &max_period);
+
+ // min_period += (SConfig::GetInstance().iLatency * (10000 / m_format.Format.nChannels));
+ INFO_LOG(AUDIO, "Audio period set to minimum (%d)", min_period);
if (!HandleWinAPI("Failed to obtain device period", result))
{
@@ -290,10 +304,9 @@ bool WASAPIStream::SetRunning(bool running)
return false;
}
- result = m_audio_client->Initialize(
- AUDCLNT_SHAREMODE_EXCLUSIVE,
- AUDCLNT_STREAMFLAGS_EVENTCALLBACK | AUDCLNT_STREAMFLAGS_NOPERSIST, device_period,
- device_period, reinterpret_cast<WAVEFORMATEX*>(&m_format), nullptr);
+ result = m_audio_client->InitializeSharedAudioStream(
+ AUDCLNT_STREAMFLAGS_EVENTCALLBACK, min_period, reinterpret_cast<WAVEFORMATEX*>(&m_format),
+ nullptr);
if (result == AUDCLNT_E_UNSUPPORTED_FORMAT)
{
@@ -303,21 +316,14 @@ bool WASAPIStream::SetRunning(bool running)
return false;
}
+ m_frames_in_buffer = min_period;
+
if (result == AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED)
{
- result = m_audio_client->GetBufferSize(&m_frames_in_buffer);
m_audio_client->Release();
- if (!HandleWinAPI("Failed to get aligned buffer size", result))
- {
- device->Release();
- m_audio_client->Release();
- m_audio_client = nullptr;
- return false;
- }
-
// Get IAudioDevice
- result = device->Activate(__uuidof(IAudioClient), CLSCTX_INPROC_SERVER, nullptr,
+ result = device->Activate(__uuidof(IAudioClient3), CLSCTX_INPROC_SERVER, nullptr,
reinterpret_cast<LPVOID*>(&m_audio_client));
if (!HandleWinAPI("Failed to reactivate IAudioClient", result))
@@ -326,28 +332,22 @@ bool WASAPIStream::SetRunning(bool running)
return false;
}
- device_period =
- static_cast<REFERENCE_TIME>(
- 10000.0 * 1000 * m_frames_in_buffer / m_format.Format.nSamplesPerSec + 0.5) +
- SConfig::GetInstance().iLatency * 10000;
+ // min_period = static_cast<REFERENCE_TIME>(
+ // 10000.0 * 1000 * m_frames_in_buffer / m_format.Format.nSamplesPerSec +
+ // 0.5) +
+ // SConfig::GetInstance().iLatency * 10000;
- result = m_audio_client->Initialize(
- AUDCLNT_SHAREMODE_EXCLUSIVE,
- AUDCLNT_STREAMFLAGS_EVENTCALLBACK | AUDCLNT_STREAMFLAGS_NOPERSIST, device_period,
- device_period, reinterpret_cast<WAVEFORMATEX*>(&m_format), nullptr);
- }
+ result = m_audio_client->InitializeSharedAudioStream(
+ AUDCLNT_STREAMFLAGS_EVENTCALLBACK, default_period,
+ reinterpret_cast<WAVEFORMATEX*>(&m_format), nullptr);
- if (!HandleWinAPI("Failed to initialize IAudioClient", result))
- {
- device->Release();
- m_audio_client->Release();
- m_audio_client = nullptr;
- return false;
- }
+ INFO_LOG(AUDIO, "Failed to use min. buffer size, falling back to default (%d)",
+ default_period);
- result = m_audio_client->GetBufferSize(&m_frames_in_buffer);
+ m_frames_in_buffer = default_period;
+ }
- if (!HandleWinAPI("Failed to get buffer size from IAudioClient", result))
+ if (!HandleWinAPI("Failed to initialize IAudioClient", result))
{
device->Release();
m_audio_client->Release();
@@ -434,7 +434,17 @@ void WASAPIStream::SoundLoop()
WaitForSingleObject(m_need_data_event, 1000);
- m_audio_renderer->GetBuffer(m_frames_in_buffer, &data);
+ HRESULT result = m_audio_renderer->GetBuffer(m_frames_in_buffer, &data);
+
+ if (result != S_OK)
+ {
+ INFO_LOG(AUDIO,
+ "Result not S_OK: %x (BUFFER: %d). This is usually a result of a buffer that is too "
+ "small",
+ result, m_frames_in_buffer);
+ continue;
+ }
+
GetMixer()->Mix(reinterpret_cast<s16*>(data), m_frames_in_buffer);
float volume = SConfig::GetInstance().m_IsMuted ? 0 : SConfig::GetInstance().m_Volume / 100.;
@@ -442,7 +452,8 @@ void WASAPIStream::SoundLoop()
for (u32 i = 0; i < m_frames_in_buffer * 2; i++)
reinterpret_cast<s16*>(data)[i] = static_cast<s16>(reinterpret_cast<s16*>(data)[i] * volume);
- m_audio_renderer->ReleaseBuffer(m_frames_in_buffer, 0);
+ // For some reason the buffer might not be available despite the event being triggered?
+ result = m_audio_renderer->ReleaseBuffer(m_frames_in_buffer, 0);
}
m_stopped = true;
diff --git a/Source/Core/AudioCommon/WASAPIStream.h b/Source/Core/AudioCommon/WASAPIStream.h
index 54becb6..8c2165f 100644
--- a/Source/Core/AudioCommon/WASAPIStream.h
+++ b/Source/Core/AudioCommon/WASAPIStream.h
@@ -18,7 +18,7 @@
#include "AudioCommon/SoundStream.h"
-struct IAudioClient;
+struct IAudioClient3;
struct IAudioRenderClient;
struct IMMDevice;
struct IMMDeviceEnumerator;
@@ -43,7 +43,7 @@ private:
std::atomic<bool> m_stopped = false;
std::thread m_thread;
- IAudioClient* m_audio_client = nullptr;
+ IAudioClient3* m_audio_client = nullptr;
IAudioRenderClient* m_audio_renderer = nullptr;
IMMDeviceEnumerator* m_enumerator = nullptr;
HANDLE m_need_data_event = nullptr;
--
2.8.1.windows.1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment