This should allow faudio to be supported in vba-m, next is to further modify cmake to find faudio

This commit is contained in:
ZachBacon 2018-12-18 08:59:11 -05:00
parent e00aca18df
commit eab039cd78
2 changed files with 79 additions and 69 deletions

View File

@ -13,6 +13,8 @@ if( WIN32 )
option( ENABLE_XAUDIO2 "Enable xaudio2 sound output for the wxWidgets port" ON ) option( ENABLE_XAUDIO2 "Enable xaudio2 sound output for the wxWidgets port" ON )
endif( WIN32 ) endif( WIN32 )
option(ENABLE_FAUDIO "Enable FAudio sound output for the wxWidgets port" ON)
option(ENABLE_OPENAL "Enable OpenAL for the wxWidgets port" OFF) option(ENABLE_OPENAL "Enable OpenAL for the wxWidgets port" OFF)
IF(APPLE) IF(APPLE)
@ -23,6 +25,10 @@ if( NOT ENABLE_XAUDIO2 )
ADD_DEFINITIONS (-DNO_XAUDIO2) ADD_DEFINITIONS (-DNO_XAUDIO2)
endif( NOT ENABLE_XAUDIO2 ) endif( NOT ENABLE_XAUDIO2 )
if( NOT ENABLE_FAUDIO )
ADD_DEFINITIONS (-DNO_FAUDIO)
endif( NOT ENABLE_FAUDIO )
if(NOT ENABLE_DIRECT3D) if(NOT ENABLE_DIRECT3D)
ADD_DEFINITIONS(-DNO_D3D) ADD_DEFINITIONS(-DNO_D3D)
endif(NOT ENABLE_DIRECT3D) endif(NOT ENABLE_DIRECT3D)
@ -552,6 +558,10 @@ IF(ENABLE_XAUDIO2)
SET( SRC_WX ${SRC_WX} xaudio2.cpp ) SET( SRC_WX ${SRC_WX} xaudio2.cpp )
ENDIF(ENABLE_XAUDIO2) ENDIF(ENABLE_XAUDIO2)
IF(ENABLE_FAUDIO)
SET( SRC_WX ${SRC_WX} faudio.cpp )
ENDIF(ENABLE_FAUDIO)
IF( WIN32 ) IF( WIN32 )
SET( SRC_WX ${SRC_WX} wxvbam.rc dsound.cpp ) SET( SRC_WX ${SRC_WX} wxvbam.rc dsound.cpp )
SET(DIRECTX_LIBRARIES dxguid dsound ws2_32) SET(DIRECTX_LIBRARIES dxguid dsound ws2_32)

View File

@ -1,4 +1,4 @@
#ifndef NO_XAUDIO2 #ifndef NO_FAUDIO
// Application // Application
#include "wxvbam.h" #include "wxvbam.h"
@ -8,7 +8,7 @@
#include "../common/ConfigManager.h" #include "../common/ConfigManager.h"
#include "../common/SoundDriver.h" #include "../common/SoundDriver.h"
// XAudio2 // Faudio
#include <faudio.h> #include <faudio.h>
#endif #endif
@ -21,21 +21,21 @@
#include "../System.h" // for systemMessage() #include "../System.h" // for systemMessage()
#include "../gba/Globals.h" #include "../gba/Globals.h"
int GetXA2Devices(IXAudio2* xa, wxArrayString* names, wxArrayString* ids, int GetFA2Devices(Faudio* fa, wxArrayString* names, wxArrayString* ids,
const wxString* match) const wxString* match)
{ {
HRESULT hr; HRESULT hr;
UINT32 dev_count = 0; UINT32 dev_count = 0;
hr = xa->FAudio_GetDeviceCount(&dev_count); hr = fa->FAudio_GetDeviceCount(&dev_count);
if (hr != S_OK) { if (hr != S_OK) {
wxLogError(_("XAudio2: Enumerating devices failed!")); wxLogError(_("FAudio: Enumerating devices failed!"));
return true; return true;
} else { } else {
XAUDIO2_DEVICE_DETAILS dd; FaudioDeviceDetails dd;
for (UINT32 i = 0; i < dev_count; i++) { for (UINT32 i = 0; i < dev_count; i++) {
hr = xa->GetDeviceDetails(i, &dd); hr = fa->GetDeviceDetails(i, &dd);
if (hr != S_OK) { if (hr != S_OK) {
continue; continue;
@ -52,56 +52,56 @@ int GetXA2Devices(IXAudio2* xa, wxArrayString* names, wxArrayString* ids,
return -1; return -1;
} }
bool GetXA2Devices(wxArrayString& names, wxArrayString& ids) bool GetFA2Devices(wxArrayString& names, wxArrayString& ids)
{ {
HRESULT hr; HRESULT hr;
IXAudio2* xa = NULL; FAudio* fa = NULL;
UINT32 flags = 0; UINT32 flags = 0;
#ifdef _DEBUG #ifdef _DEBUG
flags = FAUDIO_DEBUG_ENGINE; flags = FAUDIO_DEBUG_ENGINE;
#endif #endif
hr = XAudio2Create(&xa, flags); hr = FAudioreate(&xa, flags);
if (hr != S_OK) { if (hr != S_OK) {
wxLogError(_("The XAudio2 interface failed to initialize!")); wxLogError(_("The FAudio interface failed to initialize!"));
return false; return false;
} }
GetXA2Devices(xa, &names, &ids, NULL); GetFA2Devices(fa, &names, &ids, NULL);
xa->Release(); fa->Release();
return true; return true;
} }
static int XA2GetDev(IXAudio2* xa) static int FAGetDev(Faudio* fa)
{ {
if (gopts.audio_dev.empty()) if (gopts.audio_dev.empty())
return 0; return 0;
else { else {
int ret = GetXA2Devices(xa, NULL, NULL, &gopts.audio_dev); int ret = GetFA2Devices(fa, NULL, NULL, &gopts.audio_dev);
return ret < 0 ? 0 : ret; return ret < 0 ? 0 : ret;
} }
} }
class XAudio2_Output; class FAudio_Output;
static void xaudio2_device_changed(XAudio2_Output*); static void faudio_device_changed(FAudio_Output*);
class XAudio2_Device_Notifier : public IMMNotificationClient { class FAudio_Device_Notifier : public IMMNotificationClient {
volatile LONG registered; volatile LONG registered;
IMMDeviceEnumerator* pEnumerator; IMMDeviceEnumerator* pEnumerator;
std::wstring last_device; std::wstring last_device;
CRITICAL_SECTION lock; CRITICAL_SECTION lock;
std::vector<XAudio2_Output*> instances; std::vector<FAudio_Output*> instances;
public: public:
XAudio2_Device_Notifier() FAudio_Device_Notifier()
: registered(0) : registered(0)
{ {
InitializeCriticalSection(&lock); InitializeCriticalSection(&lock);
} }
~XAudio2_Device_Notifier() ~FAudio_Device_Notifier()
{ {
DeleteCriticalSection(&lock); DeleteCriticalSection(&lock);
} }
@ -137,7 +137,7 @@ public:
EnterCriticalSection(&lock); EnterCriticalSection(&lock);
for (auto it = instances.begin(); it < instances.end(); ++it) { for (auto it = instances.begin(); it < instances.end(); ++it) {
xaudio2_device_changed(*it); faudio_device_changed(*it);
} }
LeaveCriticalSection(&lock); LeaveCriticalSection(&lock);
@ -151,7 +151,7 @@ public:
HRESULT STDMETHODCALLTYPE OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState) { return S_OK; } HRESULT STDMETHODCALLTYPE OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState) { return S_OK; }
HRESULT STDMETHODCALLTYPE OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key) { return S_OK; } HRESULT STDMETHODCALLTYPE OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key) { return S_OK; }
void do_register(XAudio2_Output* p_instance) void do_register(FAudio_Output* p_instance)
{ {
if (InterlockedIncrement(&registered) == 1) { if (InterlockedIncrement(&registered) == 1) {
pEnumerator = NULL; pEnumerator = NULL;
@ -167,7 +167,7 @@ public:
LeaveCriticalSection(&lock); LeaveCriticalSection(&lock);
} }
void do_unregister(XAudio2_Output* p_instance) void do_unregister(FAudio_Output* p_instance)
{ {
if (InterlockedDecrement(&registered) == 0) { if (InterlockedDecrement(&registered) == 0) {
if (pEnumerator) { if (pEnumerator) {
@ -191,18 +191,18 @@ public:
} g_notifier; } g_notifier;
// Synchronization Event // Synchronization Event
class XAudio2_BufferNotify : public IXAudio2VoiceCallback { class FAudio_BufferNotify : public FAudioVoiceCallback {
public: public:
HANDLE hBufferEndEvent; HANDLE hBufferEndEvent;
XAudio2_BufferNotify() FAudio_BufferNotify()
{ {
hBufferEndEvent = NULL; hBufferEndEvent = NULL;
hBufferEndEvent = CreateEvent(NULL, FALSE, FALSE, NULL); hBufferEndEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
assert(hBufferEndEvent != NULL); assert(hBufferEndEvent != NULL);
} }
~XAudio2_BufferNotify() ~FAudio_BufferNotify()
{ {
CloseHandle(hBufferEndEvent); CloseHandle(hBufferEndEvent);
hBufferEndEvent = NULL; hBufferEndEvent = NULL;
@ -231,11 +231,11 @@ public:
}; };
// Class Declaration // Class Declaration
class XAudio2_Output class FAudio_Output
: public SoundDriver { : public SoundDriver {
public: public:
XAudio2_Output(); FAudio_Output();
~XAudio2_Output(); ~FAudio_Output();
// Initialization // Initialization
bool init(long sampleRate); bool init(long sampleRate);
@ -265,16 +265,16 @@ private:
volatile bool device_changed; volatile bool device_changed;
IXAudio2* xaud; FAudio* faud;
IXAudio2MasteringVoice* mVoice; // listener FAudioMasteringVoice* mVoice; // listener
IXAudio2SourceVoice* sVoice; // sound source FAudioSourceVoice* sVoice; // sound source
XAUDIO2_BUFFER buf; FAudioBuffer buf;
XAUDIO2_VOICE_STATE vState; FAudioVoiceState vState;
XAudio2_BufferNotify notify; // buffer end notification FAudio_BufferNotify notify; // buffer end notification
}; };
// Class Implementation // Class Implementation
XAudio2_Output::XAudio2_Output() FAudio_Output::FAudio_Output()
{ {
failed = false; failed = false;
initialized = false; initialized = false;
@ -284,7 +284,7 @@ XAudio2_Output::XAudio2_Output()
buffers = NULL; buffers = NULL;
currentBuffer = 0; currentBuffer = 0;
device_changed = false; device_changed = false;
xaud = NULL; faud = NULL;
mVoice = NULL; mVoice = NULL;
sVoice = NULL; sVoice = NULL;
ZeroMemory(&buf, sizeof(buf)); ZeroMemory(&buf, sizeof(buf));
@ -292,13 +292,13 @@ XAudio2_Output::XAudio2_Output()
g_notifier.do_register(this); g_notifier.do_register(this);
} }
XAudio2_Output::~XAudio2_Output() FAudio_Output::~FAudio_Output()
{ {
g_notifier.do_unregister(this); g_notifier.do_unregister(this);
close(); close();
} }
void XAudio2_Output::close() void FAudio_Output::close()
{ {
initialized = false; initialized = false;
@ -322,32 +322,32 @@ void XAudio2_Output::close()
mVoice = NULL; mVoice = NULL;
} }
if (xaud) { if (faud) {
xaud->Release(); faud->Release();
xaud = NULL; faud = NULL;
} }
} }
void XAudio2_Output::device_change() void FAudio_Output::device_change()
{ {
device_changed = true; device_changed = true;
} }
bool XAudio2_Output::init(long sampleRate) bool FAudio_Output::init(long sampleRate)
{ {
if (failed || initialized) if (failed || initialized)
return false; return false;
HRESULT hr; HRESULT hr;
// Initialize XAudio2 // Initialize FAudio
UINT32 flags = 0; UINT32 flags = 0;
//#ifdef _DEBUG //#ifdef _DEBUG
// flags = XAUDIO2_DEBUG_ENGINE; // flags = FAUDIO_DEBUG_ENGINE;
//#endif //#endif
hr = XAudio2Create(&xaud, flags); hr = FAudioCreate(&faud, flags);
if (hr != S_OK) { if (hr != S_OK) {
wxLogError(_("The XAudio2 interface failed to initialize!")); wxLogError(_("The FAudio interface failed to initialize!"));
failed = true; failed = true;
return false; return false;
} }
@ -369,34 +369,34 @@ bool XAudio2_Output::init(long sampleRate)
wfx.nBlockAlign = wfx.nChannels * (wfx.wBitsPerSample / 8); wfx.nBlockAlign = wfx.nChannels * (wfx.wBitsPerSample / 8);
wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
// create sound receiver // create sound receiver
hr = xaud->CreateMasteringVoice( hr = faud->CreateMasteringVoice(
&mVoice, &mVoice,
XAUDIO2_DEFAULT_CHANNELS, FAUDIO_DEFAULT_CHANNELS,
XAUDIO2_DEFAULT_SAMPLERATE, FAUDIO_DEFAULT_SAMPLERATE,
0, 0,
XA2GetDev(xaud), FAGetDev(faud),
NULL); NULL);
if (hr != S_OK) { if (hr != S_OK) {
wxLogError(_("XAudio2: Creating mastering voice failed!")); wxLogError(_("FAudio: Creating mastering voice failed!"));
failed = true; failed = true;
return false; return false;
} }
// create sound emitter // create sound emitter
hr = xaud->CreateSourceVoice(&sVoice, &wfx, 0, 4.0f, &notify); hr = faud->CreateSourceVoice(&sVoice, &wfx, 0, 4.0f, &notify);
if (hr != S_OK) { if (hr != S_OK) {
wxLogError(_("XAudio2: Creating source voice failed!")); wxLogError(_("FAudio: Creating source voice failed!"));
failed = true; failed = true;
return false; return false;
} }
if (gopts.upmix) { if (gopts.upmix) {
// set up stereo upmixing // set up stereo upmixing
XAUDIO2_DEVICE_DETAILS dd; FAudioDeviceDetails dd;
ZeroMemory(&dd, sizeof(dd)); ZeroMemory(&dd, sizeof(dd));
hr = xaud->FAudio_GetDeviceDetails(0, &dd); hr = faud->FAudio_GetDeviceDetails(0, &dd);
assert(hr == S_OK); assert(hr == S_OK);
float* matrix = NULL; float* matrix = NULL;
matrix = (float*)malloc(sizeof(float) * 2 * dd.OutputFormat.Format.nChannels); matrix = (float*)malloc(sizeof(float) * 2 * dd.OutputFormat.Format.nChannels);
@ -510,7 +510,7 @@ bool XAudio2_Output::init(long sampleRate)
return true; return true;
} }
void XAudio2_Output::write(uint16_t* finalWave, int length) void FAudio_Output::write(uint16_t* finalWave, int length)
{ {
if (!initialized || failed) if (!initialized || failed)
return; return;
@ -531,7 +531,7 @@ void XAudio2_Output::write(uint16_t* finalWave, int length)
// buffers ran dry // buffers ran dry
if (systemVerbose & VERBOSE_SOUNDOUTPUT) { if (systemVerbose & VERBOSE_SOUNDOUTPUT) {
static unsigned int i = 0; static unsigned int i = 0;
log("XAudio2: Buffers were not refilled fast enough (i=%i)\n", i++); log("FAudio: Buffers were not refilled fast enough (i=%i)\n", i++);
} }
} }
@ -561,7 +561,7 @@ void XAudio2_Output::write(uint16_t* finalWave, int length)
assert(hr == S_OK); assert(hr == S_OK);
} }
void XAudio2_Output::pause() void FAudio_Output::pause()
{ {
if (!initialized || failed) if (!initialized || failed)
return; return;
@ -573,7 +573,7 @@ void XAudio2_Output::pause()
} }
} }
void XAudio2_Output::resume() void FAudio_Output::resume()
{ {
if (!initialized || failed) if (!initialized || failed)
return; return;
@ -585,7 +585,7 @@ void XAudio2_Output::resume()
} }
} }
void XAudio2_Output::reset() void FAudio_Output::reset()
{ {
if (!initialized || failed) if (!initialized || failed)
return; return;
@ -600,7 +600,7 @@ void XAudio2_Output::reset()
playing = true; playing = true;
} }
void XAudio2_Output::setThrottle(unsigned short throttle_) void FAudio_Output::setThrottle(unsigned short throttle_)
{ {
if (!initialized || failed) if (!initialized || failed)
return; return;
@ -612,14 +612,14 @@ void XAudio2_Output::setThrottle(unsigned short throttle_)
assert(hr == S_OK); assert(hr == S_OK);
} }
void xaudio2_device_changed(XAudio2_Output* instance) void faudio_device_changed(FAudio_Output* instance)
{ {
instance->device_change(); instance->device_change();
} }
SoundDriver* newXAudio2_Output() SoundDriver* newFAudio_Output()
{ {
return new XAudio2_Output(); return new FAudio_Output();
} }
#endif // #ifndef NO_XAUDIO2 #endif // #ifndef NO_FAUDIO