Created
May 27, 2018 22:15
-
-
Save spycrab/9c5a258ce37ee1e374f5d3ebf95d813c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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