mirror of https://github.com/PCSX2/pcsx2.git
Migrated SndOut_XAudio2
This commit is contained in:
parent
f343614640
commit
bdb4ff0d83
|
@ -19,15 +19,18 @@
|
||||||
|
|
||||||
#include <xaudio2.h>
|
#include <xaudio2.h>
|
||||||
#include <cguid.h>
|
#include <cguid.h>
|
||||||
#include <atlcomcli.h>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include <wil/com.h>
|
||||||
|
#include <wil/resource.h>
|
||||||
|
#include <wil/win32_helpers.h>
|
||||||
|
|
||||||
namespace Exception
|
namespace Exception
|
||||||
{
|
{
|
||||||
class XAudio2Error : public std::runtime_error
|
class XAudio2Error final : public std::runtime_error
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
static std::string CreateErrorMessage(const HRESULT result, const std::string& msg)
|
static std::string CreateErrorMessage(const HRESULT result, const std::string& msg)
|
||||||
|
@ -59,7 +62,7 @@ namespace Exception
|
||||||
|
|
||||||
static const double SndOutNormalizer = (double)(1UL << (SndOutVolumeShift + 16));
|
static const double SndOutNormalizer = (double)(1UL << (SndOutVolumeShift + 16));
|
||||||
|
|
||||||
class XAudio2Mod : public SndOutModule
|
class XAudio2Mod final : public SndOutModule
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
static const int PacketsPerBuffer = 8;
|
static const int PacketsPerBuffer = 8;
|
||||||
|
@ -76,7 +79,7 @@ private:
|
||||||
const uint m_BufferSize;
|
const uint m_BufferSize;
|
||||||
const uint m_BufferSizeBytes;
|
const uint m_BufferSizeBytes;
|
||||||
|
|
||||||
CRITICAL_SECTION cs;
|
wil::critical_section cs;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int GetEmptySampleCount()
|
int GetEmptySampleCount()
|
||||||
|
@ -86,11 +89,6 @@ private:
|
||||||
return state.SamplesPlayed & (m_BufferSize - 1);
|
return state.SamplesPlayed & (m_BufferSize - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~BaseStreamingVoice()
|
|
||||||
{
|
|
||||||
DeleteCriticalSection(&cs);
|
|
||||||
}
|
|
||||||
|
|
||||||
BaseStreamingVoice(uint numChannels)
|
BaseStreamingVoice(uint numChannels)
|
||||||
: pSourceVoice(nullptr)
|
: pSourceVoice(nullptr)
|
||||||
, m_nBuffers(Config_XAudio2.NumBuffers)
|
, m_nBuffers(Config_XAudio2.NumBuffers)
|
||||||
|
@ -98,7 +96,6 @@ private:
|
||||||
, m_BufferSize(SndOutPacketSize * m_nChannels * PacketsPerBuffer)
|
, m_BufferSize(SndOutPacketSize * m_nChannels * PacketsPerBuffer)
|
||||||
, m_BufferSizeBytes(m_BufferSize * sizeof(s16))
|
, m_BufferSizeBytes(m_BufferSize * sizeof(s16))
|
||||||
{
|
{
|
||||||
InitializeCriticalSection(&cs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void Init(IXAudio2* pXAudio2) = 0;
|
virtual void Init(IXAudio2* pXAudio2) = 0;
|
||||||
|
@ -129,7 +126,7 @@ private:
|
||||||
throw Exception::XAudio2Error(hr, "XAudio2 CreateSourceVoice failure: ");
|
throw Exception::XAudio2Error(hr, "XAudio2 CreateSourceVoice failure: ");
|
||||||
}
|
}
|
||||||
|
|
||||||
EnterCriticalSection(&cs);
|
auto lock = cs.lock();
|
||||||
|
|
||||||
pSourceVoice->FlushSourceBuffers();
|
pSourceVoice->FlushSourceBuffers();
|
||||||
pSourceVoice->Start(0, 0);
|
pSourceVoice->Start(0, 0);
|
||||||
|
@ -145,8 +142,6 @@ private:
|
||||||
buf.pAudioData = (BYTE*)buf.pContext;
|
buf.pAudioData = (BYTE*)buf.pContext;
|
||||||
pSourceVoice->SubmitSourceBuffer(&buf);
|
pSourceVoice->SubmitSourceBuffer(&buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
LeaveCriticalSection(&cs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
STDMETHOD_(void, OnVoiceProcessingPassStart)
|
STDMETHOD_(void, OnVoiceProcessingPassStart)
|
||||||
|
@ -190,9 +185,8 @@ private:
|
||||||
// blocking, and the documentation states no callbacks are called
|
// blocking, and the documentation states no callbacks are called
|
||||||
// or audio data is read after it returns, so it's safe to free up
|
// or audio data is read after it returns, so it's safe to free up
|
||||||
// resources.
|
// resources.
|
||||||
EnterCriticalSection(&cs);
|
auto lock = cs.lock();
|
||||||
m_buffer = nullptr;
|
m_buffer = nullptr;
|
||||||
LeaveCriticalSection(&cs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Init(IXAudio2* pXAudio2)
|
void Init(IXAudio2* pXAudio2)
|
||||||
|
@ -229,14 +223,13 @@ private:
|
||||||
STDMETHOD_(void, OnBufferEnd)
|
STDMETHOD_(void, OnBufferEnd)
|
||||||
(void* context)
|
(void* context)
|
||||||
{
|
{
|
||||||
EnterCriticalSection(&cs);
|
auto lock = cs.lock();
|
||||||
|
|
||||||
// All of these checks are necessary because XAudio2 is wonky shizat.
|
// All of these checks are necessary because XAudio2 is wonky shizat.
|
||||||
// XXX: The pSourceVoice nullptr check seems a bit self-inflicted
|
// XXX: The pSourceVoice nullptr check seems a bit self-inflicted
|
||||||
// due to the destructor logic.
|
// due to the destructor logic.
|
||||||
if (pSourceVoice == nullptr || context == nullptr)
|
if (pSourceVoice == nullptr || context == nullptr)
|
||||||
{
|
{
|
||||||
LeaveCriticalSection(&cs);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -251,30 +244,29 @@ private:
|
||||||
buf.pContext = context;
|
buf.pContext = context;
|
||||||
|
|
||||||
pSourceVoice->SubmitSourceBuffer(&buf);
|
pSourceVoice->SubmitSourceBuffer(&buf);
|
||||||
LeaveCriticalSection(&cs);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
HMODULE xAudio2DLL = nullptr;
|
wil::unique_couninitialize_call xaudio2CoInitialize;
|
||||||
decltype(&XAudio2Create) pXAudio2Create = nullptr;
|
wil::unique_hmodule xAudio2DLL;
|
||||||
CComPtr<IXAudio2> pXAudio2;
|
wil::com_ptr_nothrow<IXAudio2> pXAudio2;
|
||||||
IXAudio2MasteringVoice* pMasteringVoice = nullptr;
|
IXAudio2MasteringVoice* pMasteringVoice = nullptr;
|
||||||
std::unique_ptr<BaseStreamingVoice> m_voiceContext;
|
std::unique_ptr<BaseStreamingVoice> m_voiceContext;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
s32 Init()
|
s32 Init()
|
||||||
{
|
{
|
||||||
CoInitializeEx(nullptr, COINIT_MULTITHREADED);
|
xaudio2CoInitialize = wil::CoInitializeEx_failfast(COINIT_MULTITHREADED);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
xAudio2DLL = LoadLibraryEx(XAUDIO2_DLL, nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
|
xAudio2DLL.reset(LoadLibraryEx(XAUDIO2_DLL, nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32));
|
||||||
if (xAudio2DLL == nullptr)
|
if (xAudio2DLL == nullptr)
|
||||||
throw std::runtime_error("Could not load " XAUDIO2_DLL_A ". Error code:" + std::to_string(GetLastError()));
|
throw std::runtime_error("Could not load " XAUDIO2_DLL_A ". Error code:" + std::to_string(GetLastError()));
|
||||||
|
|
||||||
pXAudio2Create = reinterpret_cast<decltype(&XAudio2Create)>(GetProcAddress(xAudio2DLL, "XAudio2Create"));
|
auto pXAudio2Create = GetProcAddressByFunctionDeclaration(xAudio2DLL.get(), XAudio2Create);
|
||||||
if (pXAudio2Create == nullptr)
|
if (pXAudio2Create == nullptr)
|
||||||
throw std::runtime_error("XAudio2Create not found. Error code: " + std::to_string(GetLastError()));
|
throw std::runtime_error("XAudio2Create not found. Error code: " + std::to_string(GetLastError()));
|
||||||
|
|
||||||
|
@ -350,7 +342,7 @@ public:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_voiceContext->Init(pXAudio2);
|
m_voiceContext->Init(pXAudio2.get());
|
||||||
}
|
}
|
||||||
catch (std::runtime_error& ex)
|
catch (std::runtime_error& ex)
|
||||||
{
|
{
|
||||||
|
@ -380,15 +372,9 @@ public:
|
||||||
|
|
||||||
pMasteringVoice = nullptr;
|
pMasteringVoice = nullptr;
|
||||||
|
|
||||||
pXAudio2.Release();
|
pXAudio2.reset();
|
||||||
CoUninitialize();
|
xAudio2DLL.reset();
|
||||||
|
xaudio2CoInitialize.reset();
|
||||||
if (xAudio2DLL)
|
|
||||||
{
|
|
||||||
FreeLibrary(xAudio2DLL);
|
|
||||||
xAudio2DLL = nullptr;
|
|
||||||
pXAudio2Create = nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void Configure(uptr parent)
|
virtual void Configure(uptr parent)
|
||||||
|
|
Loading…
Reference in New Issue