Add XAudio2.7 as an compile-time audio driver for vanilla Windows 7
This commit is contained in:
parent
9ae2c9fd54
commit
fd6b734fd0
131
SDL/audio/xaudio2_7.c
Normal file
131
SDL/audio/xaudio2_7.c
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
#include "xaudio2_7.h"
|
||||||
|
#include "audio.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define AUDIO_FREQUENCY 96000
|
||||||
|
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 const WAVEFORMATEX wave_format = {
|
||||||
|
.wFormatTag = WAVE_FORMAT_PCM,
|
||||||
|
.nChannels = 2,
|
||||||
|
.nSamplesPerSec = AUDIO_FREQUENCY,
|
||||||
|
.nAvgBytesPerSec = AUDIO_FREQUENCY * 4,
|
||||||
|
.nBlockAlign = 4,
|
||||||
|
.wBitsPerSample = 16,
|
||||||
|
.cbSize = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline HRESULT XAudio2Create(IXAudio2 **ppXAudio2,
|
||||||
|
UINT32 Flags,
|
||||||
|
XAUDIO2_PROCESSOR XAudio2Processor)
|
||||||
|
{
|
||||||
|
IXAudio2 *pXAudio2;
|
||||||
|
LoadLibraryEx("xaudio2_7.dll", NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
|
||||||
|
|
||||||
|
HRESULT hr = CoCreateInstance(&CLSID_XAudio2, NULL, CLSCTX_INPROC_SERVER, &IID_IXAudio2, (void**)&pXAudio2);
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
hr = pXAudio2->lpVtbl->Initialize(pXAudio2, Flags, XAudio2Processor);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
*ppXAudio2 = pXAudio2;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pXAudio2->lpVtbl->Release(pXAudio2);
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GB_audio_is_playing(void)
|
||||||
|
{
|
||||||
|
return playing;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GB_audio_set_paused(bool paused)
|
||||||
|
{
|
||||||
|
if (paused) {
|
||||||
|
playing = false;
|
||||||
|
IXAudio2SourceVoice_Stop(source_voice, 0, XAUDIO2_COMMIT_NOW);
|
||||||
|
GB_audio_clear_queue();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
playing = true;
|
||||||
|
IXAudio2SourceVoice_Start(source_voice, 0, XAUDIO2_COMMIT_NOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void GB_audio_clear_queue(void)
|
||||||
|
{
|
||||||
|
pos = 0;
|
||||||
|
IXAudio2SourceVoice_FlushSourceBuffers(source_voice);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned GB_audio_get_frequency(void)
|
||||||
|
{
|
||||||
|
return AUDIO_FREQUENCY;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t GB_audio_get_queue_length(void)
|
||||||
|
{
|
||||||
|
static XAUDIO2_VOICE_STATE state;
|
||||||
|
IXAudio2SourceVoice_GetState(source_voice, &state);
|
||||||
|
|
||||||
|
return state.BuffersQueued * BATCH_SIZE + (pos & (BATCH_SIZE - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GB_audio_queue_sample(GB_sample_t *sample)
|
||||||
|
{
|
||||||
|
if (!playing) return;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GB_audio_init(void)
|
||||||
|
{
|
||||||
|
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
fprintf(stderr, "CoInitializeEx failed: %lx\n", hr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = XAudio2Create(&xaudio2, 0, XAUDIO2_DEFAULT_PROCESSOR);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
fprintf(stderr, "XAudio2Create failed: %lx\n", hr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
103
SDL/audio/xaudio2_7.h
Normal file
103
SDL/audio/xaudio2_7.h
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
#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 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;
|
||||||
|
|
||||||
|
void *RegisterForCallbacks;
|
||||||
|
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_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
|
Loading…
Reference in New Issue
Block a user