Replace XAudio 2.7 and 2.9 with the redistrib version of XAudio 2.9

This commit is contained in:
Lior Halphon 2024-01-06 14:23:22 +02:00
parent 97e8df29c5
commit e9c2c866eb
5 changed files with 26 additions and 355 deletions

View File

@ -17,7 +17,7 @@ ifeq ($(PLATFORM),windows32)
_ := $(shell chcp 65001)
EXESUFFIX:=.exe
NATIVE_CC = clang -IWindows -Wno-deprecated-declarations --target=x86_64-pc-windows
SDL_AUDIO_DRIVERS ?= xaudio2 xaudio2_7 sdl
SDL_AUDIO_DRIVERS ?= xaudio2 sdl
else
EXESUFFIX:=
NATIVE_CC := cc
@ -224,6 +224,11 @@ CFLAGS += -IWindows -Drandom=rand --target=x86_64-pc-windows
LDFLAGS += -lmsvcrt -lcomdlg32 -luser32 -lshell32 -lole32 -lSDL2main -Wl,/MANIFESTFILE:NUL --target=x86_64-pc-windows
SDL_LDFLAGS := -lSDL2
GL_LDFLAGS := -lopengl32
ifneq ($(REDIST_XAUDIO),)
CFLAGS += -DREDIST_XAUDIO
LDFLAGS += -lxaudio2_9redist
sdl: $(BIN)/SDL/xaudio2_9redist.dll
endif
else
LDFLAGS += -lc -lm -ldl
endif
@ -542,9 +547,10 @@ $(OBJ)/%.res: %.rc
cvtres /OUT:"$@" $^
endif
# We must provide SDL2.dll with the Windows port.
$(BIN)/SDL/SDL2.dll:
@$(eval MATCH := $(shell where $$LIB:SDL2.dll))
# Copy required DLL files for the Windows port
$(BIN)/SDL/%.dll:
-@$(MKDIR) -p $(dir $@)
@$(eval MATCH := $(shell where $$LIB:$(notdir $@)))
cp "$(MATCH)" $@
# Tester

View File

@ -15,7 +15,6 @@ bool GB_audio_init(void)
const GB_audio_driver_t *drivers[] = {
#ifdef _WIN32
GB_AUDIO_DRIVER_REF(XAudio2),
GB_AUDIO_DRIVER_REF(XAudio2_7),
#endif
GB_AUDIO_DRIVER_REF(SDL),
#ifdef ENABLE_OPENAL
@ -97,7 +96,6 @@ const char *GB_audio_driver_name_at_index(unsigned index)
const GB_audio_driver_t *drivers[] = {
#ifdef _WIN32
GB_AUDIO_DRIVER_REF(XAudio2),
GB_AUDIO_DRIVER_REF(XAudio2_7),
#endif
GB_AUDIO_DRIVER_REF(SDL),
#ifdef ENABLE_OPENAL

View File

@ -1,9 +1,25 @@
#define COBJMACROS
#include "audio.h"
#include <Windows.h>
#ifdef REDIST_XAUDIO
#include <xaudio2redist.h>
#else
#include <xaudio2.h>
#endif
#include <initguid.h>
#include <Mmdeviceapi.h>
// This is a hack, but Windows itself is a hack so I don't care
#define DEFINE_CLSID(className, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
DEFINE_GUID(CLSID_##className, 0x##l, 0x##w1, 0x##w2, 0x##b1, 0x##b2, 0x##b3, 0x##b4, 0x##b5, 0x##b6, 0x##b7, 0x##b8)
#define DEFINE_IID(interfaceName, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
DEFINE_GUID(IID_##interfaceName, 0x##l, 0x##w1, 0x##w2, 0x##b1, 0x##b2, 0x##b3, 0x##b4, 0x##b5, 0x##b6, 0x##b7, 0x##b8)
DEFINE_CLSID(MMDeviceEnumerator, bcde0395, e52f, 467c, 8e, 3d, c4, 57, 92, 91, 69, 2e);
DEFINE_IID(IMMDeviceEnumerator, a95664d2, 9614, 4f35, a7, 46, de, 8d, b6, 36, 17, e6);
static unsigned audio_frequency = 48000;
static IXAudio2 *xaudio2 = NULL;
static IXAudio2MasteringVoice *master_voice = NULL;

View File

@ -1,225 +0,0 @@
#define COBJMACROS
#include "xaudio2_7.h"
#include "audio.h"
#include <Mmdeviceapi.h>
static unsigned audio_frequency = 48000;
static IXAudio2 *xaudio2 = NULL;
static IXAudio2MasteringVoice *master_voice = NULL;
static IXAudio2SourceVoice *source_voice = NULL;
static bool playing = false;
static GB_sample_t sample_pool[0x2000];
static unsigned pos = 0;
#define BATCH_SIZE 256
static WAVEFORMATEX wave_format = {
.wFormatTag = WAVE_FORMAT_PCM,
.nChannels = 2,
.nBlockAlign = 4,
.wBitsPerSample = 16,
.cbSize = 0
};
static inline HRESULT XAudio2Create(IXAudio2 **out,
UINT32 Flags,
XAUDIO2_PROCESSOR XAudio2Processor)
{
IXAudio2 *xaudio2;
LoadLibraryEx("xaudio2_7.dll", NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
HRESULT hr = CoCreateInstance(&CLSID_XAudio2, NULL, CLSCTX_INPROC_SERVER, &IID_IXAudio2, (void **)&xaudio2);
if (SUCCEEDED(hr)) {
hr = xaudio2->lpVtbl->Initialize(xaudio2, Flags, XAudio2Processor);
}
if (SUCCEEDED(hr)) {
*out = xaudio2;
}
else if (xaudio2) {
xaudio2->lpVtbl->Release(xaudio2);
}
return hr;
}
static bool _audio_is_playing(void)
{
return playing;
}
static void _audio_clear_queue(void)
{
pos = 0;
IXAudio2SourceVoice_FlushSourceBuffers(source_voice);
}
static void _audio_set_paused(bool paused)
{
if (paused) {
playing = false;
IXAudio2SourceVoice_Stop(source_voice, 0, XAUDIO2_COMMIT_NOW);
_audio_clear_queue();
}
else {
playing = true;
IXAudio2SourceVoice_Start(source_voice, 0, XAUDIO2_COMMIT_NOW);
}
}
#define _DEFINE_PROPERTYKEY(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8, pid) static const PROPERTYKEY name = { { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }, pid }
_DEFINE_PROPERTYKEY(_PKEY_AudioEngine_DeviceFormat, 0xf19f064d, 0x82c, 0x4e27, 0xbc, 0x73, 0x68, 0x82, 0xa1, 0xbb, 0x8e, 0x4c, 0);
static void update_frequency(void)
{
HRESULT hr;
IMMDevice *device = NULL;
IMMDeviceEnumerator *enumerator = NULL;
IPropertyStore *store = NULL;
PWAVEFORMATEX deviceFormatProperties;
PROPVARIANT prop;
hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, &IID_IMMDeviceEnumerator, (LPVOID *)&enumerator);
if (FAILED(hr)) return;
// get default audio endpoint
hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(enumerator, eRender, eMultimedia, &device);
if (FAILED(hr)) return;
hr = IMMDevice_OpenPropertyStore(device, STGM_READ, &store);
if (FAILED(hr)) return;
hr = IPropertyStore_GetValue(store, &_PKEY_AudioEngine_DeviceFormat, &prop);
if (FAILED(hr)) return;
deviceFormatProperties = (PWAVEFORMATEX)prop.blob.pBlobData;
audio_frequency = deviceFormatProperties->nSamplesPerSec;
if (audio_frequency < 8000 || audio_frequency > 192000) {
// Bogus value, revert to 48KHz
audio_frequency = 48000;
}
}
static unsigned _audio_get_frequency(void)
{
return audio_frequency;
}
static void nop(IXAudio2EngineCallback *this)
{
}
static bool _audio_init(void);
static _Atomic bool needs_restart = false;
static void critical_error(IXAudio2EngineCallback *this, HRESULT error)
{
needs_restart = true;
}
static size_t _audio_get_queue_length(void)
{
if (needs_restart) {
_audio_init();
if (!xaudio2) return 0;
_audio_set_paused(!playing);
}
static XAUDIO2_VOICE_STATE state;
IXAudio2SourceVoice_GetState(source_voice, &state);
return state.BuffersQueued * BATCH_SIZE + (pos & (BATCH_SIZE - 1));
}
static void _audio_queue_sample(GB_sample_t *sample)
{
if (!playing) return;
if (needs_restart) {
_audio_init();
if (!xaudio2) return;
_audio_set_paused(!playing);
}
static XAUDIO2_BUFFER buffer = {.AudioBytes = sizeof(*sample) * BATCH_SIZE, };
sample_pool[pos] = *sample;
buffer.pAudioData = (void *)&sample_pool[pos & ~(BATCH_SIZE - 1)];
pos++;
pos &= 0x1fff;
if ((pos & (BATCH_SIZE - 1)) == 0) {
IXAudio2SourceVoice_SubmitSourceBuffer(source_voice, &buffer, NULL);
}
}
static bool _audio_init(void)
{
if (needs_restart) {
needs_restart = false;
if (xaudio2) {
xaudio2->lpVtbl->Release(xaudio2);
xaudio2 = NULL;
}
}
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if (FAILED(hr)) {
fprintf(stderr, "CoInitializeEx failed: %lx\n", hr);
return false;
}
hr = XAudio2Create(&xaudio2, 0, XAUDIO2_DEFAULT_PROCESSOR);
if (FAILED(hr)) {
fprintf(stderr, "XAudio2Create failed: %lx\n", hr);
return false;
}
update_frequency();
hr = IXAudio2_CreateMasteringVoice(xaudio2, &master_voice,
2, // 2 channels
audio_frequency,
0, // Flags
0, // Device index
NULL // Effect chain
);
if (FAILED(hr)) {
fprintf(stderr, "CreateMasteringVoice failed: %lx\n", hr);
return false;
}
wave_format.nSamplesPerSec = audio_frequency;
wave_format.nAvgBytesPerSec = audio_frequency * 4;
hr = IXAudio2_CreateSourceVoice(xaudio2, &source_voice, &wave_format, 0, XAUDIO2_DEFAULT_FREQ_RATIO, NULL, NULL, NULL);
if (FAILED(hr)) {
fprintf(stderr, "CreateSourceVoice failed: %lx\n", hr);
return false;
}
static IXAudio2EngineCallbackVtbl callbacks = {
nop,
nop,
.OnCriticalError = critical_error
};
static IXAudio2EngineCallback callbackObject = {
.lpVtbl = &callbacks
};
IXAudio2SourceVoice_RegisterForCallbacks(xaudio2, &callbackObject);
return true;
}
static void _audio_deinit(void)
{
_audio_set_paused(true);
}
GB_AUDIO_DRIVER(XAudio2_7);

View File

@ -1,124 +0,0 @@
#define INITGUID
#include <Windows.h>
/* Minimal definitions for XAudio2.7 */
typedef UINT32 XAUDIO2_PROCESSOR;
typedef struct XAUDIO2_BUFFER {
UINT32 Flags;
UINT32 AudioBytes;
const BYTE *pAudioData;
UINT32 PlayBegin;
UINT32 PlayLength;
UINT32 LoopBegin;
UINT32 LoopLength;
UINT32 LoopCount;
void *pContext;
} XAUDIO2_BUFFER;
typedef struct XAUDIO2_VOICE_STATE {
void *pCurrentBufferContext;
UINT32 BuffersQueued;
UINT64 SamplesPlayed;
} XAUDIO2_VOICE_STATE;
typedef struct IXAudio2SourceVoice {
struct IXAudio2SourceVoiceVtbl *lpVtbl;
} IXAudio2SourceVoice;
typedef struct IXAudio2SourceVoiceVtbl IXAudio2SourceVoiceVtbl;
#undef INTERFACE
#define INTERFACE IXAudio2SourceVoice
struct IXAudio2SourceVoiceVtbl {
void *voiceMethods[19]; // Unused inherited methods
STDMETHOD(Start) (THIS_ UINT32 Flags, UINT32 OperationSet) PURE;
STDMETHOD(Stop) (THIS_ UINT32 Flags, UINT32 OperationSet) PURE;
STDMETHOD(SubmitSourceBuffer) (THIS_ __in const XAUDIO2_BUFFER *pBuffer, __in_opt const void *pBufferWMA) PURE;
STDMETHOD(FlushSourceBuffers) (THIS) PURE;
STDMETHOD(Discontinuity) (THIS) PURE;
STDMETHOD(ExitLoop) (THIS_ UINT32 OperationSet) PURE;
STDMETHOD_(void, GetState) (THIS_ __out XAUDIO2_VOICE_STATE *pVoiceState) PURE;
};
typedef struct IXAudio2 {
struct IXAudio2Vtbl *lpVtbl;
} IXAudio2;
typedef struct IXAudio2Vtbl IXAudio2Vtbl;
typedef void *IXAudio2MasteringVoice;
#undef INTERFACE
#define INTERFACE IXAudio2EngineCallback
DECLARE_INTERFACE(IXAudio2EngineCallback)
{
// Called by XAudio2 just before an audio processing pass begins.
STDMETHOD_(void, OnProcessingPassStart) (THIS) PURE;
// Called just after an audio processing pass ends.
STDMETHOD_(void, OnProcessingPassEnd) (THIS) PURE;
// Called in the event of a critical system error which requires XAudio2
// to be closed down and restarted. The error code is given in Error.
STDMETHOD_(void, OnCriticalError) (THIS_ HRESULT Error) PURE;
};
#undef INTERFACE
#define INTERFACE IXAudio2
struct IXAudio2Vtbl {
void *QueryInterface;
STDMETHOD_(ULONG, AddRef) (THIS) PURE;
STDMETHOD_(ULONG, Release) (THIS) PURE;
void *GetDeviceCount;
void *GetDeviceDetails;
STDMETHOD(Initialize) (THIS_ UINT32 Flags,
XAUDIO2_PROCESSOR XAudio2Processor) PURE;
STDMETHOD(RegisterForCallbacks) (THIS_ __in IXAudio2EngineCallback *pCallback) PURE;
void *UnregisterForCallbacks;
STDMETHOD(CreateSourceVoice) (THIS_ __deref_out IXAudio2SourceVoice **ppSourceVoice,
__in const WAVEFORMATEX *pSourceFormat,
UINT32 Flags,
float MaxFrequencyRatio,
__in_opt void *pCallback,
__in_opt const void *pSendList,
__in_opt const void *pEffectChain) PURE;
void *CreateSubmixVoice;
STDMETHOD(CreateMasteringVoice) (THIS_ __deref_out IXAudio2MasteringVoice **ppMasteringVoice,
UINT32 InputChannels,
UINT32 InputSampleRate,
UINT32 Flags, UINT32 DeviceIndex,
__in_opt const void *pEffectChain) PURE;
};
#define DEFINE_CLSID(className, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
DEFINE_GUID(CLSID_##className, 0x##l, 0x##w1, 0x##w2, 0x##b1, 0x##b2, 0x##b3, 0x##b4, 0x##b5, 0x##b6, 0x##b7, 0x##b8)
#define DEFINE_IID(interfaceName, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
DEFINE_GUID(IID_##interfaceName, 0x##l, 0x##w1, 0x##w2, 0x##b1, 0x##b2, 0x##b3, 0x##b4, 0x##b5, 0x##b6, 0x##b7, 0x##b8)
DEFINE_CLSID(XAudio2, 5a508685, a254, 4fba, 9b, 82, 9a, 24, b0, 03, 06, af);
DEFINE_IID(IXAudio2, 8bcf1f58, 9fe7, 4583, 8a, c6, e2, ad, c4, 65, c8, bb);
#define IXAudio2SourceVoice_RegisterForCallbacks(This, pCallback) ((This)->lpVtbl->RegisterForCallbacks(This,pCallback))
#define IXAudio2SourceVoice_Start(This,Flags,OperationSet) ((This)->lpVtbl->Start(This,Flags,OperationSet))
#define IXAudio2SourceVoice_Stop(This,Flags,OperationSet) ((This)->lpVtbl->Stop(This,Flags,OperationSet))
#define IXAudio2SourceVoice_SubmitSourceBuffer(This,pBuffer,pBufferWMA) ((This)->lpVtbl->SubmitSourceBuffer(This,pBuffer,pBufferWMA))
#define IXAudio2SourceVoice_FlushSourceBuffers(This) ((This)->lpVtbl->FlushSourceBuffers(This))
#define IXAudio2SourceVoice_GetState(This,pVoiceState) ((This)->lpVtbl->GetState(This,pVoiceState))
#define IXAudio2_CreateMasteringVoice(This,ppMasteringVoice,InputChannels,InputSampleRate,Flags,DeviceIndex,pEffectChain) ((This)->lpVtbl->CreateMasteringVoice(This,ppMasteringVoice,InputChannels,InputSampleRate,Flags,DeviceIndex,pEffectChain))
#define IXAudio2_CreateSourceVoice(This,ppSourceVoice,pSourceFormat,Flags,MaxFrequencyRatio,pCallback,pSendList,pEffectChain) ((This)->lpVtbl->CreateSourceVoice(This,ppSourceVoice,pSourceFormat,Flags,MaxFrequencyRatio,pCallback,pSendList,pEffectChain))
#define XAUDIO2_COMMIT_NOW 0
#define XAUDIO2_DEFAULT_PROCESSOR 0xffffffff
#define XAUDIO2_DEFAULT_FREQ_RATIO 2.0f
// WASAPI extras. This is a hack, but Windows itself is a hack so I don't care
DEFINE_CLSID(MMDeviceEnumerator, bcde0395, e52f, 467c, 8e, 3d, c4, 57, 92, 91, 69, 2e);
DEFINE_IID(IMMDeviceEnumerator, a95664d2, 9614, 4f35, a7, 46, de, 8d, b6, 36, 17, e6);