Merge pull request #337 from visualboyadvance-m/light-weight
Light weight
This commit is contained in:
commit
514f355664
File diff suppressed because it is too large
Load Diff
|
@ -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)
|
||||||
|
@ -595,6 +605,7 @@ TARGET_LINK_LIBRARIES (
|
||||||
${DIRECTX_LIBRARIES}
|
${DIRECTX_LIBRARIES}
|
||||||
${GTK_LIBRARIES}
|
${GTK_LIBRARIES}
|
||||||
${OPENAL_LIBRARY}
|
${OPENAL_LIBRARY}
|
||||||
|
faudio
|
||||||
)
|
)
|
||||||
|
|
||||||
if(ENABLE_FFMPEG)
|
if(ENABLE_FFMPEG)
|
||||||
|
|
|
@ -0,0 +1,629 @@
|
||||||
|
#ifndef NO_FAUDIO
|
||||||
|
|
||||||
|
// Application
|
||||||
|
#include "wxvbam.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
// Interface
|
||||||
|
#include "../common/ConfigManager.h"
|
||||||
|
#include "../common/SoundDriver.h"
|
||||||
|
|
||||||
|
// FAudio
|
||||||
|
#include <faudio.h>
|
||||||
|
|
||||||
|
// MMDevice API
|
||||||
|
#include <mmdeviceapi.h>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
// Internals
|
||||||
|
#include "../System.h" // for systemMessage()
|
||||||
|
#include "../gba/Globals.h"
|
||||||
|
|
||||||
|
int GetFADevices(FAudio* fa, wxArrayString* names, wxArrayString* ids,
|
||||||
|
const wxString* match)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
UINT32 dev_count = 0;
|
||||||
|
hr = FAudio_GetDeviceCount(fa, &dev_count);
|
||||||
|
|
||||||
|
if (hr != S_OK) {
|
||||||
|
wxLogError(_("FAudio: Enumerating devices failed!"));
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
FAudioDeviceDetails dd;
|
||||||
|
|
||||||
|
for (UINT32 i = 0; i < dev_count; i++) {
|
||||||
|
hr = FAudio_GetDeviceDetails(fa, i, &dd);
|
||||||
|
|
||||||
|
if (hr != S_OK) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
if (ids) {
|
||||||
|
ids->push_back((wchar_t*) dd.DeviceID); //FAudio is an interesting beast, but not that hard to adapt... once you get used to it, XAudio2 wouldn't need this, but FAudio declares FAudioDeviceDetails as int32_t
|
||||||
|
names->push_back((wchar_t*) dd.DisplayName);
|
||||||
|
} else if (*match == dd.DeviceID)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GetFADevices(wxArrayString& names, wxArrayString& ids)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
FAudio* fa = NULL;
|
||||||
|
UINT32 flags = 0;
|
||||||
|
#ifdef _DEBUG
|
||||||
|
flags = FAUDIO_DEBUG_ENGINE;
|
||||||
|
#endif
|
||||||
|
hr = FAudioCreate(&fa, flags, FAUDIO_DEFAULT_PROCESSOR); //Apparently this needs 3 parameters, the processor.
|
||||||
|
|
||||||
|
if (hr != S_OK) {
|
||||||
|
wxLogError(_("The FAudio interface failed to initialize!"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
GetFADevices(fa, &names, &ids, NULL);
|
||||||
|
//fa->Release();
|
||||||
|
FAudio_Release(fa);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int FAGetDev(FAudio* fa)
|
||||||
|
{
|
||||||
|
if (gopts.audio_dev.empty())
|
||||||
|
return 0;
|
||||||
|
else {
|
||||||
|
int ret = GetFADevices(fa, NULL, NULL, &gopts.audio_dev);
|
||||||
|
return ret < 0 ? 0 : ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FAudio_Output;
|
||||||
|
|
||||||
|
static void faudio_device_changed(FAudio_Output*);
|
||||||
|
|
||||||
|
class FAudio_Device_Notifier : public IMMNotificationClient {
|
||||||
|
volatile LONG registered;
|
||||||
|
IMMDeviceEnumerator* pEnumerator;
|
||||||
|
|
||||||
|
std::wstring last_device;
|
||||||
|
|
||||||
|
CRITICAL_SECTION lock;
|
||||||
|
std::vector<FAudio_Output*> instances;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FAudio_Device_Notifier()
|
||||||
|
: registered(0)
|
||||||
|
{
|
||||||
|
InitializeCriticalSection(&lock);
|
||||||
|
}
|
||||||
|
~FAudio_Device_Notifier()
|
||||||
|
{
|
||||||
|
DeleteCriticalSection(&lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG STDMETHODCALLTYPE AddRef()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG STDMETHODCALLTYPE Release()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, VOID** ppvInterface)
|
||||||
|
{
|
||||||
|
if (IID_IUnknown == riid) {
|
||||||
|
*ppvInterface = (IUnknown*)this;
|
||||||
|
} else if (__uuidof(IMMNotificationClient) == riid) {
|
||||||
|
*ppvInterface = (IMMNotificationClient*)this;
|
||||||
|
} else {
|
||||||
|
*ppvInterface = NULL;
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR pwstrDeviceId)
|
||||||
|
{
|
||||||
|
if (flow == eRender && last_device.compare(pwstrDeviceId) != 0) {
|
||||||
|
last_device = pwstrDeviceId;
|
||||||
|
EnterCriticalSection(&lock);
|
||||||
|
|
||||||
|
for (auto it = instances.begin(); it < instances.end(); ++it) {
|
||||||
|
faudio_device_changed(*it);
|
||||||
|
}
|
||||||
|
|
||||||
|
LeaveCriticalSection(&lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE OnDeviceAdded(LPCWSTR pwstrDeviceId) { return S_OK; }
|
||||||
|
HRESULT STDMETHODCALLTYPE OnDeviceRemoved(LPCWSTR pwstrDeviceId) { return S_OK; }
|
||||||
|
HRESULT STDMETHODCALLTYPE OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState) { return S_OK; }
|
||||||
|
HRESULT STDMETHODCALLTYPE OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key) { return S_OK; }
|
||||||
|
|
||||||
|
void do_register(FAudio_Output* p_instance)
|
||||||
|
{
|
||||||
|
if (InterlockedIncrement(®istered) == 1) {
|
||||||
|
pEnumerator = NULL;
|
||||||
|
HRESULT hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, __uuidof(IMMDeviceEnumerator), (void**)&pEnumerator);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
pEnumerator->RegisterEndpointNotificationCallback(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EnterCriticalSection(&lock);
|
||||||
|
instances.push_back(p_instance);
|
||||||
|
LeaveCriticalSection(&lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void do_unregister(FAudio_Output* p_instance)
|
||||||
|
{
|
||||||
|
if (InterlockedDecrement(®istered) == 0) {
|
||||||
|
if (pEnumerator) {
|
||||||
|
pEnumerator->UnregisterEndpointNotificationCallback(this);
|
||||||
|
pEnumerator->Release();
|
||||||
|
pEnumerator = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EnterCriticalSection(&lock);
|
||||||
|
|
||||||
|
for (auto it = instances.begin(); it < instances.end(); ++it) {
|
||||||
|
if (*it == p_instance) {
|
||||||
|
instances.erase(it);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LeaveCriticalSection(&lock);
|
||||||
|
}
|
||||||
|
} g_notifier;
|
||||||
|
|
||||||
|
// Synchronization Event
|
||||||
|
class FAudio_BufferNotify : public FAudioVoiceCallback {
|
||||||
|
public:
|
||||||
|
HANDLE hBufferEndEvent;
|
||||||
|
|
||||||
|
FAudio_BufferNotify()
|
||||||
|
{
|
||||||
|
hBufferEndEvent = NULL;
|
||||||
|
hBufferEndEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||||
|
assert(hBufferEndEvent != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
~FAudio_BufferNotify()
|
||||||
|
{
|
||||||
|
CloseHandle(hBufferEndEvent);
|
||||||
|
hBufferEndEvent = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHOD_(void, OnBufferEnd)
|
||||||
|
(void* pBufferContext)
|
||||||
|
{
|
||||||
|
assert(hBufferEndEvent != NULL);
|
||||||
|
SetEvent(hBufferEndEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// dummies:
|
||||||
|
STDMETHOD_(void, OnVoiceProcessingPassStart)
|
||||||
|
(UINT32 BytesRequired) {}
|
||||||
|
STDMETHOD_(void, OnVoiceProcessingPassEnd)
|
||||||
|
() {}
|
||||||
|
STDMETHOD_(void, OnStreamEnd)
|
||||||
|
() {}
|
||||||
|
STDMETHOD_(void, OnBufferStart)
|
||||||
|
(void* pBufferContext) {}
|
||||||
|
STDMETHOD_(void, OnLoopEnd)
|
||||||
|
(void* pBufferContext) {}
|
||||||
|
STDMETHOD_(void, OnVoiceError)
|
||||||
|
(void* pBufferContext, HRESULT Error){};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Class Declaration
|
||||||
|
class FAudio_Output
|
||||||
|
: public SoundDriver {
|
||||||
|
public:
|
||||||
|
FAudio_Output();
|
||||||
|
~FAudio_Output();
|
||||||
|
|
||||||
|
// Initialization
|
||||||
|
bool init(long sampleRate);
|
||||||
|
|
||||||
|
// Sound Data Feed
|
||||||
|
void write(uint16_t* finalWave, int length);
|
||||||
|
|
||||||
|
// Play Control
|
||||||
|
void pause();
|
||||||
|
void resume();
|
||||||
|
void reset();
|
||||||
|
void close();
|
||||||
|
void device_change();
|
||||||
|
|
||||||
|
// Configuration Changes
|
||||||
|
void setThrottle(unsigned short throttle);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool failed;
|
||||||
|
bool initialized;
|
||||||
|
bool playing;
|
||||||
|
UINT32 freq;
|
||||||
|
UINT32 bufferCount;
|
||||||
|
BYTE* buffers;
|
||||||
|
int currentBuffer;
|
||||||
|
int soundBufferLen;
|
||||||
|
|
||||||
|
volatile bool device_changed;
|
||||||
|
|
||||||
|
FAudio* faud;
|
||||||
|
FAudioMasteringVoice* mVoice; // listener
|
||||||
|
FAudioSourceVoice* sVoice; // sound source
|
||||||
|
FAudioBuffer buf;
|
||||||
|
FAudioVoiceState vState;
|
||||||
|
FAudio_BufferNotify notify; // buffer end notification
|
||||||
|
};
|
||||||
|
|
||||||
|
// Class Implementation
|
||||||
|
FAudio_Output::FAudio_Output()
|
||||||
|
{
|
||||||
|
failed = false;
|
||||||
|
initialized = false;
|
||||||
|
playing = false;
|
||||||
|
freq = 0;
|
||||||
|
bufferCount = gopts.audio_buffers;
|
||||||
|
buffers = NULL;
|
||||||
|
currentBuffer = 0;
|
||||||
|
device_changed = false;
|
||||||
|
faud = NULL;
|
||||||
|
mVoice = NULL;
|
||||||
|
sVoice = NULL;
|
||||||
|
ZeroMemory(&buf, sizeof(buf));
|
||||||
|
ZeroMemory(&vState, sizeof(vState));
|
||||||
|
g_notifier.do_register(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
FAudio_Output::~FAudio_Output()
|
||||||
|
{
|
||||||
|
g_notifier.do_unregister(this);
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FAudio_Output::close()
|
||||||
|
{
|
||||||
|
initialized = false;
|
||||||
|
|
||||||
|
if (sVoice) {
|
||||||
|
if (playing) {
|
||||||
|
HRESULT hr = FAudioSourceVoice_Stop(sVoice, 0, FAUDIO_COMMIT_NOW);
|
||||||
|
assert(hr == S_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
FAudioVoice_DestroyVoice(sVoice);
|
||||||
|
sVoice = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffers) {
|
||||||
|
free(buffers);
|
||||||
|
buffers = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mVoice) {
|
||||||
|
FAudioVoice_DestroyVoice(mVoice);
|
||||||
|
mVoice = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (faud) {
|
||||||
|
FAudio_Release(faud);
|
||||||
|
faud = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FAudio_Output::device_change()
|
||||||
|
{
|
||||||
|
device_changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FAudio_Output::init(long sampleRate)
|
||||||
|
{
|
||||||
|
if (failed || initialized)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
HRESULT hr;
|
||||||
|
// Initialize FAudio
|
||||||
|
UINT32 flags = 0;
|
||||||
|
//#ifdef _DEBUG
|
||||||
|
// flags = FAUDIO_DEBUG_ENGINE;
|
||||||
|
//#endif
|
||||||
|
hr = FAudioCreate(&faud, flags, FAUDIO_DEFAULT_CHANNELS);
|
||||||
|
|
||||||
|
if (hr != S_OK) {
|
||||||
|
wxLogError(_("The FAudio interface failed to initialize!"));
|
||||||
|
failed = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
freq = sampleRate;
|
||||||
|
// calculate the number of samples per frame first
|
||||||
|
// then multiply it with the size of a sample frame (16 bit * stereo)
|
||||||
|
soundBufferLen = (freq / 60) * 4;
|
||||||
|
// create own buffers to store sound data because it must not be
|
||||||
|
// manipulated while the voice plays from it
|
||||||
|
buffers = (BYTE*)malloc((bufferCount + 1) * soundBufferLen);
|
||||||
|
// + 1 because we need one temporary buffer when all others are in use
|
||||||
|
WAVEFORMATEX wfx;
|
||||||
|
ZeroMemory(&wfx, sizeof(wfx));
|
||||||
|
wfx.wFormatTag = WAVE_FORMAT_PCM;
|
||||||
|
wfx.nChannels = 2;
|
||||||
|
wfx.nSamplesPerSec = freq;
|
||||||
|
wfx.wBitsPerSample = 16;
|
||||||
|
wfx.nBlockAlign = wfx.nChannels * (wfx.wBitsPerSample / 8);
|
||||||
|
wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
|
||||||
|
// create sound receiver
|
||||||
|
hr = FAudio_CreateMasteringVoice(
|
||||||
|
faud,
|
||||||
|
&mVoice,
|
||||||
|
FAUDIO_DEFAULT_CHANNELS,
|
||||||
|
FAUDIO_DEFAULT_SAMPLERATE,
|
||||||
|
0,
|
||||||
|
FAGetDev(faud),
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (hr != S_OK) {
|
||||||
|
wxLogError(_("FAudio: Creating mastering voice failed!"));
|
||||||
|
failed = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create sound emitter
|
||||||
|
//This should be FAudio_CreateSourceVoice()
|
||||||
|
//hr = faud->CreateSourceVoice(&sVoice, &wfx, 0, 4.0f, ¬ify);
|
||||||
|
hr = FAudio_CreateSourceVoice(faud, &sVoice, (const FAudioWaveFormatEx*)&wfx, 0, 4.0f, ¬ify, NULL, NULL);
|
||||||
|
|
||||||
|
if (hr != S_OK) {
|
||||||
|
wxLogError(_("FAudio: Creating source voice failed!"));
|
||||||
|
failed = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gopts.upmix) {
|
||||||
|
// set up stereo upmixing
|
||||||
|
FAudioDeviceDetails dd;
|
||||||
|
ZeroMemory(&dd, sizeof(dd));
|
||||||
|
hr = FAudio_GetDeviceDetails(faud, 0, &dd);
|
||||||
|
assert(hr == S_OK);
|
||||||
|
float* matrix = NULL;
|
||||||
|
matrix = (float*)malloc(sizeof(float) * 2 * dd.OutputFormat.Format.nChannels);
|
||||||
|
|
||||||
|
if (matrix == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool matrixAvailable = true;
|
||||||
|
|
||||||
|
switch (dd.OutputFormat.Format.nChannels) {
|
||||||
|
case 4: // 4.0
|
||||||
|
//Speaker \ Left Source Right Source
|
||||||
|
/*Front L*/ matrix[0] = 1.0000f;
|
||||||
|
matrix[1] = 0.0000f;
|
||||||
|
/*Front R*/ matrix[2] = 0.0000f;
|
||||||
|
matrix[3] = 1.0000f;
|
||||||
|
/*Back L*/ matrix[4] = 1.0000f;
|
||||||
|
matrix[5] = 0.0000f;
|
||||||
|
/*Back R*/ matrix[6] = 0.0000f;
|
||||||
|
matrix[7] = 1.0000f;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5: // 5.0
|
||||||
|
//Speaker \ Left Source Right Source
|
||||||
|
/*Front L*/ matrix[0] = 1.0000f;
|
||||||
|
matrix[1] = 0.0000f;
|
||||||
|
/*Front R*/ matrix[2] = 0.0000f;
|
||||||
|
matrix[3] = 1.0000f;
|
||||||
|
/*Front C*/ matrix[4] = 0.7071f;
|
||||||
|
matrix[5] = 0.7071f;
|
||||||
|
/*Side L*/ matrix[6] = 1.0000f;
|
||||||
|
matrix[7] = 0.0000f;
|
||||||
|
/*Side R*/ matrix[8] = 0.0000f;
|
||||||
|
matrix[9] = 1.0000f;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 6: // 5.1
|
||||||
|
//Speaker \ Left Source Right Source
|
||||||
|
/*Front L*/ matrix[0] = 1.0000f;
|
||||||
|
matrix[1] = 0.0000f;
|
||||||
|
/*Front R*/ matrix[2] = 0.0000f;
|
||||||
|
matrix[3] = 1.0000f;
|
||||||
|
/*Front C*/ matrix[4] = 0.7071f;
|
||||||
|
matrix[5] = 0.7071f;
|
||||||
|
/*LFE */ matrix[6] = 0.0000f;
|
||||||
|
matrix[7] = 0.0000f;
|
||||||
|
/*Side L*/ matrix[8] = 1.0000f;
|
||||||
|
matrix[9] = 0.0000f;
|
||||||
|
/*Side R*/ matrix[10] = 0.0000f;
|
||||||
|
matrix[11] = 1.0000f;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 7: // 6.1
|
||||||
|
//Speaker \ Left Source Right Source
|
||||||
|
/*Front L*/ matrix[0] = 1.0000f;
|
||||||
|
matrix[1] = 0.0000f;
|
||||||
|
/*Front R*/ matrix[2] = 0.0000f;
|
||||||
|
matrix[3] = 1.0000f;
|
||||||
|
/*Front C*/ matrix[4] = 0.7071f;
|
||||||
|
matrix[5] = 0.7071f;
|
||||||
|
/*LFE */ matrix[6] = 0.0000f;
|
||||||
|
matrix[7] = 0.0000f;
|
||||||
|
/*Side L*/ matrix[8] = 1.0000f;
|
||||||
|
matrix[9] = 0.0000f;
|
||||||
|
/*Side R*/ matrix[10] = 0.0000f;
|
||||||
|
matrix[11] = 1.0000f;
|
||||||
|
/*Back C*/ matrix[12] = 0.7071f;
|
||||||
|
matrix[13] = 0.7071f;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 8: // 7.1
|
||||||
|
//Speaker \ Left Source Right Source
|
||||||
|
/*Front L*/ matrix[0] = 1.0000f;
|
||||||
|
matrix[1] = 0.0000f;
|
||||||
|
/*Front R*/ matrix[2] = 0.0000f;
|
||||||
|
matrix[3] = 1.0000f;
|
||||||
|
/*Front C*/ matrix[4] = 0.7071f;
|
||||||
|
matrix[5] = 0.7071f;
|
||||||
|
/*LFE */ matrix[6] = 0.0000f;
|
||||||
|
matrix[7] = 0.0000f;
|
||||||
|
/*Back L*/ matrix[8] = 1.0000f;
|
||||||
|
matrix[9] = 0.0000f;
|
||||||
|
/*Back R*/ matrix[10] = 0.0000f;
|
||||||
|
matrix[11] = 1.0000f;
|
||||||
|
/*Side L*/ matrix[12] = 1.0000f;
|
||||||
|
matrix[13] = 0.0000f;
|
||||||
|
/*Side R*/ matrix[14] = 0.0000f;
|
||||||
|
matrix[15] = 1.0000f;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
matrixAvailable = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matrixAvailable) {
|
||||||
|
hr = FAudioVoice_SetOutputMatrix(sVoice, NULL, 2, dd.OutputFormat.Format.nChannels, matrix, FAUDIO_DEFAULT_CHANNELS); //What I have here for the OperationSet maybe wrong...
|
||||||
|
assert(hr == S_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(matrix);
|
||||||
|
matrix = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = FAudioSourceVoice_Start(sVoice, 0, FAUDIO_COMMIT_NOW);
|
||||||
|
assert(hr == S_OK);
|
||||||
|
playing = true;
|
||||||
|
currentBuffer = 0;
|
||||||
|
device_changed = false;
|
||||||
|
initialized = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FAudio_Output::write(uint16_t* finalWave, int length)
|
||||||
|
{
|
||||||
|
UINT32 flags = 0;
|
||||||
|
if (!initialized || failed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (device_changed) {
|
||||||
|
close();
|
||||||
|
|
||||||
|
if (!init(freq))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FAudioSourceVoice_GetState(sVoice, &vState, flags);
|
||||||
|
assert(vState.BuffersQueued <= bufferCount);
|
||||||
|
|
||||||
|
if (vState.BuffersQueued < bufferCount) {
|
||||||
|
if (vState.BuffersQueued == 0) {
|
||||||
|
// buffers ran dry
|
||||||
|
if (systemVerbose & VERBOSE_SOUNDOUTPUT) {
|
||||||
|
static unsigned int i = 0;
|
||||||
|
log("FAudio: Buffers were not refilled fast enough (i=%i)\n", i++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// there is at least one free buffer
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
// the maximum number of buffers is currently queued
|
||||||
|
if (!speedup && throttle && !gba_joybus_active) {
|
||||||
|
// wait for one buffer to finish playing
|
||||||
|
if (WaitForSingleObject(notify.hBufferEndEvent, 10000) == WAIT_TIMEOUT) {
|
||||||
|
device_changed = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// drop current audio frame
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy & protect the audio data in own memory area while playing it
|
||||||
|
CopyMemory(&buffers[currentBuffer * soundBufferLen], finalWave, soundBufferLen);
|
||||||
|
buf.AudioBytes = soundBufferLen;
|
||||||
|
buf.pAudioData = &buffers[currentBuffer * soundBufferLen];
|
||||||
|
currentBuffer++;
|
||||||
|
currentBuffer %= (bufferCount + 1); // + 1 because we need one temporary buffer
|
||||||
|
HRESULT hr = FAudioSourceVoice_SubmitSourceBuffer(sVoice, &buf, NULL); // send buffer to queue.
|
||||||
|
assert(hr == S_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FAudio_Output::pause()
|
||||||
|
{
|
||||||
|
if (!initialized || failed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (playing) {
|
||||||
|
HRESULT hr = FAudioSourceVoice_Stop(sVoice, 0, FAUDIO_COMMIT_NOW);
|
||||||
|
assert(hr == S_OK);
|
||||||
|
playing = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FAudio_Output::resume()
|
||||||
|
{
|
||||||
|
if (!initialized || failed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!playing) {
|
||||||
|
HRESULT hr = FAudioSourceVoice_Start(sVoice, 0, FAUDIO_COMMIT_NOW);
|
||||||
|
assert(hr == S_OK);
|
||||||
|
playing = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FAudio_Output::reset()
|
||||||
|
{
|
||||||
|
if (!initialized || failed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (playing) {
|
||||||
|
HRESULT hr = FAudioSourceVoice_Stop(sVoice, 0, FAUDIO_COMMIT_NOW);
|
||||||
|
assert(hr == S_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
FAudioSourceVoice_FlushSourceBuffers(sVoice);
|
||||||
|
FAudioSourceVoice_Start(sVoice, 0, FAUDIO_COMMIT_NOW);
|
||||||
|
playing = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FAudio_Output::setThrottle(unsigned short throttle_)
|
||||||
|
{
|
||||||
|
if (!initialized || failed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (throttle_ == 0)
|
||||||
|
throttle_ = 100;
|
||||||
|
|
||||||
|
HRESULT hr = FAudioSourceVoice_SetFrequencyRatio(sVoice, (float)throttle_ / 100.0f, FAUDIO_MAX_FILTER_FREQUENCY);
|
||||||
|
assert(hr == S_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
void faudio_device_changed(FAudio_Output* instance)
|
||||||
|
{
|
||||||
|
instance->device_change();
|
||||||
|
}
|
||||||
|
|
||||||
|
SoundDriver* newFAudio_Output()
|
||||||
|
{
|
||||||
|
return new FAudio_Output();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // #ifndef NO_FAUDIO
|
|
@ -2236,7 +2236,7 @@ void GLDrawingPanel::DrawArea(wxWindowDC& dc)
|
||||||
#define DIRECT3D_VERSION 0x0900
|
#define DIRECT3D_VERSION 0x0900
|
||||||
#include <d3d9.h> // main include file
|
#include <d3d9.h> // main include file
|
||||||
//#include <d3dx9core.h> // required for font rendering
|
//#include <d3dx9core.h> // required for font rendering
|
||||||
//#include <dxerr9.h> // contains debug functions
|
#include <dxerr9.h> // contains debug functions
|
||||||
|
|
||||||
DXDrawingPanel::DXDrawingPanel(wxWindow* parent, int _width, int _height)
|
DXDrawingPanel::DXDrawingPanel(wxWindow* parent, int _width, int _height)
|
||||||
: DrawingPanel(parent, _width, _height)
|
: DrawingPanel(parent, _width, _height)
|
||||||
|
@ -2247,6 +2247,7 @@ DXDrawingPanel::DXDrawingPanel(wxWindow* parent, int _width, int _height)
|
||||||
|
|
||||||
void DXDrawingPanel::DrawArea(wxWindowDC& dc)
|
void DXDrawingPanel::DrawArea(wxWindowDC& dc)
|
||||||
{
|
{
|
||||||
|
|
||||||
// FIXME: implement
|
// FIXME: implement
|
||||||
if (!did_init) {
|
if (!did_init) {
|
||||||
DrawingPanelInit();
|
DrawingPanelInit();
|
||||||
|
|
|
@ -120,6 +120,13 @@
|
||||||
<flag>wxALL|wxEXPAND</flag>
|
<flag>wxALL|wxEXPAND</flag>
|
||||||
<border>5</border>
|
<border>5</border>
|
||||||
</object>
|
</object>
|
||||||
|
<object class="sizeritem">
|
||||||
|
<object class="wxRadioButton" name="FAudio">
|
||||||
|
<label>FAudio</label>
|
||||||
|
</object>
|
||||||
|
<flag>wxALL|wxEXPAND</flag>
|
||||||
|
<border>5</border>
|
||||||
|
</object>
|
||||||
<object class="sizeritem">
|
<object class="sizeritem">
|
||||||
<object class="wxRadioButton" name="DirectSound">
|
<object class="wxRadioButton" name="DirectSound">
|
||||||
<label>DirectSound</label>
|
<label>DirectSound</label>
|
||||||
|
|
Loading…
Reference in New Issue