mirror of https://github.com/LIJI32/SameBoy.git
Replace XAudio 2.7 and 2.9 with the redistrib version of XAudio 2.9
This commit is contained in:
parent
97e8df29c5
commit
e9c2c866eb
14
Makefile
14
Makefile
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
|
@ -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);
|
Loading…
Reference in New Issue