mirror of
https://github.com/hedge-dev/UnleashedRecomp.git
synced 2026-04-24 04:18:23 -05:00
audio gaming
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
uint32_t XAudioRegisterRenderDriverClient(XLPDWORD callback, XLPDWORD driver)
|
||||
{
|
||||
*driver = AUDIO_DRIVER_KEY;
|
||||
XAudioRegisterClient(KeFindHostFunction(*callback), callback[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -15,7 +16,8 @@ uint32_t XAudioUnregisterRenderDriverClient(DWORD driver)
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t XAudioSubmitRenderDriverFrame(XLPDWORD callback, XLPDWORD driver)
|
||||
uint32_t XAudioSubmitRenderDriverFrame(uint32_t driver, void* samples)
|
||||
{
|
||||
XAudioSubmitFrame(samples);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
SWA_API uint32_t XAudioRegisterRenderDriverClient(XLPDWORD callback, XLPDWORD driver);
|
||||
SWA_API uint32_t XAudioUnregisterRenderDriverClient(DWORD driver);
|
||||
SWA_API uint32_t XAudioSubmitRenderDriverFrame(XLPDWORD callback, XLPDWORD driver);
|
||||
#ifdef SWA_IMPL
|
||||
void XAudioInitializeSystem();
|
||||
void XAudioRegisterClient(PPCFunc* callback, uint32_t param);
|
||||
void XAudioSubmitFrame(void* samples);
|
||||
#endif
|
||||
|
||||
uint32_t XAudioRegisterRenderDriverClient(XLPDWORD callback, XLPDWORD driver);
|
||||
uint32_t XAudioUnregisterRenderDriverClient(DWORD driver);
|
||||
uint32_t XAudioSubmitRenderDriverFrame(uint32_t driver, void* samples);
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
#include <stdafx.h>
|
||||
#include "xaudio_driver.h"
|
||||
#include <xaudio2.h>
|
||||
|
||||
#include <cpu/code_cache.h>
|
||||
#include <cpu/guest_thread.h>
|
||||
#include <cpu/guest_code.h>
|
||||
#include <cpu/ppc_context.h>
|
||||
|
||||
#define XAUDIO_DRIVER_KEY (uint32_t)('XAUD')
|
||||
|
||||
PPCFunc* g_clientCallback{};
|
||||
DWORD g_clientCallbackParam{};
|
||||
DWORD g_driverThread{};
|
||||
|
||||
// TODO: Should use a counted ptr
|
||||
IXAudio2* g_audio{};
|
||||
IXAudio2MasteringVoice* g_masteringVoice{};
|
||||
IXAudio2SourceVoice* g_sourceVoice{};
|
||||
|
||||
constexpr uint32_t g_semaphoreCount = 16;
|
||||
constexpr uint32_t g_audioFrameSize = 256 * 6;
|
||||
HANDLE g_audioSemaphore{ CreateSemaphoreA(nullptr, g_semaphoreCount, g_semaphoreCount, nullptr) };
|
||||
uint32_t g_audioFrames[g_audioFrameSize * g_semaphoreCount];
|
||||
uint32_t g_audioFrameIndex = 0;
|
||||
|
||||
class VoiceCallback : public IXAudio2VoiceCallback
|
||||
{
|
||||
void OnVoiceProcessingPassStart(UINT32 BytesRequired) override {}
|
||||
void OnVoiceProcessingPassEnd() override {}
|
||||
|
||||
void OnBufferStart(void* pBufferContext) override {}
|
||||
void OnBufferEnd(void* pBufferContext) override
|
||||
{
|
||||
ReleaseSemaphore(g_audioSemaphore, 1, nullptr);
|
||||
}
|
||||
|
||||
void OnStreamEnd() override {}
|
||||
|
||||
void OnLoopEnd(void* pBufferContext) override {}
|
||||
void OnVoiceError(void* pBufferContext, HRESULT Error) override {}
|
||||
} gVoiceCallback;
|
||||
|
||||
inline PPC_FUNC(DriverLoop)
|
||||
{
|
||||
GuestThread::SetThreadName(GetCurrentThreadId(), "Audio Driver");
|
||||
|
||||
auto* cpu = GetPPCContext();
|
||||
while (true)
|
||||
{
|
||||
if (!g_clientCallback)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
WaitForSingleObject(g_audioSemaphore, INFINITE);
|
||||
|
||||
cpu->r3.u64 = g_clientCallbackParam;
|
||||
GuestCode::Run(g_clientCallback, cpu);
|
||||
}
|
||||
}
|
||||
|
||||
void XAudioInitializeSystem()
|
||||
{
|
||||
if (g_audio)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//reinterpret_cast<decltype(&XAudio2Create)>(
|
||||
// GetProcAddress(LoadLibraryA("XAudio2_8.dll"), "XAudio2Create"))(&gAudio, 0, 1);
|
||||
|
||||
XAudio2Create(&g_audio);
|
||||
g_audio->CreateMasteringVoice(&g_masteringVoice);
|
||||
|
||||
WAVEFORMATIEEEFLOATEX format{};
|
||||
format.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
|
||||
format.Format.cbSize = sizeof(format) - sizeof(format.Format);
|
||||
format.Format.nChannels = 6;
|
||||
format.Format.nSamplesPerSec = 48000;
|
||||
format.Format.wBitsPerSample = 32;
|
||||
format.Format.nBlockAlign = (format.Format.nChannels * format.Format.wBitsPerSample) / 8;
|
||||
format.Format.nAvgBytesPerSec = format.Format.nSamplesPerSec * format.Format.nBlockAlign;
|
||||
|
||||
format.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
|
||||
format.Samples.wValidBitsPerSample = format.Format.wBitsPerSample;
|
||||
format.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_CENTER | SPEAKER_FRONT_RIGHT |
|
||||
SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT;
|
||||
|
||||
g_audio->CreateSourceVoice(&g_sourceVoice, &format.Format, 0, 1024, &gVoiceCallback);
|
||||
g_sourceVoice->Start();
|
||||
|
||||
KeInsertHostFunction(XAUDIO_DRIVER_KEY, DriverLoop);
|
||||
GuestThread::Start(XAUDIO_DRIVER_KEY, 0, 0, &g_driverThread);
|
||||
}
|
||||
|
||||
void XAudioRegisterClient(PPCFunc* callback, uint32_t param)
|
||||
{
|
||||
g_clientCallback = callback;
|
||||
g_clientCallbackParam = param;
|
||||
}
|
||||
|
||||
void XAudioSubmitFrame(void* samples)
|
||||
{
|
||||
uint32_t* audioFrame = &g_audioFrames[g_audioFrameSize * g_audioFrameIndex];
|
||||
g_audioFrameIndex = (g_audioFrameIndex + 1) % g_semaphoreCount;
|
||||
|
||||
for (size_t i = 0; i < 256; i++)
|
||||
{
|
||||
for (size_t j = 0; j < 6; j++)
|
||||
audioFrame[i * 6 + j] = std::byteswap(((uint32_t*)samples)[j * 256 + i]);
|
||||
}
|
||||
|
||||
XAUDIO2_BUFFER buffer{};
|
||||
buffer.pAudioData = (BYTE*)audioFrame;
|
||||
buffer.AudioBytes = 256 * 6 * sizeof(float);
|
||||
buffer.PlayLength = 256;
|
||||
|
||||
g_sourceVoice->SubmitSourceBuffer(&buffer);
|
||||
}
|
||||
Reference in New Issue
Block a user