faudio.cpp: Begin rework of faudio implementation
This begins the rework of the faudio code begin with removing a good deal of the imme code that the driver used to poll audio interfaces Removed the use of HRESULT code since that's more windowisms. Also adapted more of the faudio stuff like WaveFormatEx is FAudioWaveFormatEx WAVE_FORMAT_PCM is FAUDIO_FORMAT_PCM. Also changed S_OK into R_OK but I'm pretty sure that isn't the way to go. That said and done, this is still a work in progress, but it compiles. But it doesn't initilize yet, I might need an extra set of eyes for that. Signed-off-by: Zach Bacon <zachbacon@vba-m.com>
This commit is contained in:
parent
215e3c5ae9
commit
75355eca4c
|
@ -8,10 +8,8 @@
|
||||||
#include "../common/SoundDriver.h"
|
#include "../common/SoundDriver.h"
|
||||||
|
|
||||||
// FAudio
|
// FAudio
|
||||||
#include <faudio.h>
|
#include <FAudio.h>
|
||||||
|
|
||||||
// MMDevice API
|
|
||||||
#include <mmdeviceapi.h>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -22,21 +20,16 @@
|
||||||
int GetFADevices(FAudio* fa, wxArrayString* names, wxArrayString* ids,
|
int GetFADevices(FAudio* fa, wxArrayString* names, wxArrayString* ids,
|
||||||
const wxString* match)
|
const wxString* match)
|
||||||
{
|
{
|
||||||
HRESULT hr;
|
uint32_t dev_count = 0;
|
||||||
UINT32 dev_count = 0;
|
|
||||||
|
|
||||||
hr = FAudio_GetDeviceCount(fa, &dev_count);
|
if (FAudio_GetDeviceCount(fa, &dev_count) != R_OK) {
|
||||||
|
|
||||||
if (hr != S_OK) {
|
|
||||||
wxLogError(_("FAudio: Enumerating devices failed!"));
|
wxLogError(_("FAudio: Enumerating devices failed!"));
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
FAudioDeviceDetails dd;
|
FAudioDeviceDetails dd;
|
||||||
|
|
||||||
for (UINT32 i = 0; i < dev_count; i++) {
|
for (uint32_t i = 0; i < dev_count; i++) {
|
||||||
hr = FAudio_GetDeviceDetails(fa, i, &dd);
|
if (FAudio_GetDeviceDetails(fa, i, &dd) != R_OK) {
|
||||||
|
|
||||||
if (hr != S_OK) {
|
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
if (ids) {
|
if (ids) {
|
||||||
|
@ -53,22 +46,18 @@ int GetFADevices(FAudio* fa, wxArrayString* names, wxArrayString* ids,
|
||||||
|
|
||||||
bool GetFADevices(wxArrayString& names, wxArrayString& ids)
|
bool GetFADevices(wxArrayString& names, wxArrayString& ids)
|
||||||
{
|
{
|
||||||
HRESULT hr;
|
|
||||||
FAudio* fa = NULL;
|
FAudio* fa = NULL;
|
||||||
UINT32 flags = 0;
|
uint32_t flags = 0;
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
flags = FAUDIO_DEBUG_ENGINE;
|
flags = FAUDIO_DEBUG_ENGINE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
hr = FAudioCreate(&fa, flags, FAUDIO_DEFAULT_PROCESSOR); //Apparently this needs 3 parameters, the processor.
|
if (FAudioCreate(&fa, flags, FAUDIO_DEFAULT_PROCESSOR) != R_OK) {
|
||||||
|
|
||||||
if (hr != S_OK) {
|
|
||||||
wxLogError(_("The FAudio interface failed to initialize!"));
|
wxLogError(_("The FAudio interface failed to initialize!"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
GetFADevices(fa, &names, &ids, NULL);
|
GetFADevices(fa, &names, &ids, NULL);
|
||||||
//fa->Release();
|
|
||||||
FAudio_Release(fa);
|
FAudio_Release(fa);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -87,148 +76,47 @@ class FAudio_Output;
|
||||||
|
|
||||||
static void faudio_device_changed(FAudio_Output*);
|
static void faudio_device_changed(FAudio_Output*);
|
||||||
|
|
||||||
class FAudio_Device_Notifier : public IMMNotificationClient {
|
class FAudio_Device_Notifier {
|
||||||
volatile LONG registered;
|
|
||||||
IMMDeviceEnumerator* pEnumerator;
|
|
||||||
|
|
||||||
std::wstring last_device;
|
std::wstring last_device;
|
||||||
|
|
||||||
CRITICAL_SECTION lock;
|
|
||||||
std::vector<FAudio_Output*> instances;
|
std::vector<FAudio_Output*> instances;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FAudio_Device_Notifier()
|
FAudio_Device_Notifier() = default;
|
||||||
: registered(0)
|
~FAudio_Device_Notifier() = default;
|
||||||
{
|
|
||||||
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)
|
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);
|
instances.push_back(p_instance);
|
||||||
LeaveCriticalSection(&lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_unregister(FAudio_Output* p_instance)
|
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) {
|
for (auto it = instances.begin(); it < instances.end(); ++it) {
|
||||||
if (*it == p_instance) {
|
if (*it == p_instance) {
|
||||||
instances.erase(it);
|
instances.erase(it);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
LeaveCriticalSection(&lock);
|
void OnDefaultDeviceChanged()
|
||||||
|
{
|
||||||
|
for (auto it = instances.begin(); it < instances.end(); ++it)
|
||||||
|
{
|
||||||
|
faudio_device_changed(*it);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} g_notifier;
|
} g_notifier;
|
||||||
|
|
||||||
// Synchronization Event
|
// Synchronization Event
|
||||||
class FAudio_BufferNotify : public FAudioVoiceCallback {
|
class FAudio_BufferNotify : public FAudioVoiceCallback {
|
||||||
public:
|
public:
|
||||||
HANDLE hBufferEndEvent;
|
void OnBufferEnd(void* pBufferContext) {}
|
||||||
|
void OnVoiceProcessingPassStart(uint32_t BytesRequired) {}
|
||||||
FAudio_BufferNotify()
|
void OnVoiceProcessingPassEnd() {}
|
||||||
{
|
void OnStreamEnd() {}
|
||||||
hBufferEndEvent = NULL;
|
void OnBufferStart(void* pBufferContext) {}
|
||||||
hBufferEndEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
void OnLoopEnd(void* pBufferContext) {}
|
||||||
assert(hBufferEndEvent != NULL);
|
void OnVoiceError(void* pBufferContext, int Error) {}
|
||||||
}
|
|
||||||
|
|
||||||
~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 Declaration
|
||||||
|
@ -258,9 +146,9 @@ private:
|
||||||
bool failed;
|
bool failed;
|
||||||
bool initialized;
|
bool initialized;
|
||||||
bool playing;
|
bool playing;
|
||||||
UINT32 freq;
|
uint32_t freq;
|
||||||
UINT32 bufferCount;
|
uint32_t bufferCount;
|
||||||
BYTE* buffers;
|
uint8_t* buffers;
|
||||||
int currentBuffer;
|
int currentBuffer;
|
||||||
int soundBufferLen;
|
int soundBufferLen;
|
||||||
|
|
||||||
|
@ -288,8 +176,8 @@ FAudio_Output::FAudio_Output()
|
||||||
faud = NULL;
|
faud = NULL;
|
||||||
mVoice = NULL;
|
mVoice = NULL;
|
||||||
sVoice = NULL;
|
sVoice = NULL;
|
||||||
ZeroMemory(&buf, sizeof(buf));
|
memset(&buf, NULL, sizeof(buf));
|
||||||
ZeroMemory(&vState, sizeof(vState));
|
memset(&vState, NULL, sizeof(vState));
|
||||||
g_notifier.do_register(this);
|
g_notifier.do_register(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -305,8 +193,7 @@ void FAudio_Output::close()
|
||||||
|
|
||||||
if (sVoice) {
|
if (sVoice) {
|
||||||
if (playing) {
|
if (playing) {
|
||||||
HRESULT hr = FAudioSourceVoice_Stop(sVoice, 0, FAUDIO_COMMIT_NOW);
|
assert(FAudioSourceVoice_Stop(sVoice, 0, FAUDIO_COMMIT_NOW) == R_OK);
|
||||||
assert(hr == S_OK);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FAudioVoice_DestroyVoice(sVoice);
|
FAudioVoice_DestroyVoice(sVoice);
|
||||||
|
@ -339,15 +226,13 @@ bool FAudio_Output::init(long sampleRate)
|
||||||
if (failed || initialized)
|
if (failed || initialized)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
HRESULT hr;
|
|
||||||
// Initialize FAudio
|
// Initialize FAudio
|
||||||
UINT32 flags = 0;
|
uint32_t flags = 0;
|
||||||
//#ifdef _DEBUG
|
//#ifdef _DEBUG
|
||||||
// flags = FAUDIO_DEBUG_ENGINE;
|
// flags = FAUDIO_DEBUG_ENGINE;
|
||||||
//#endif
|
//#endif
|
||||||
hr = FAudioCreate(&faud, flags, FAUDIO_DEFAULT_PROCESSOR);
|
|
||||||
|
|
||||||
if (hr != S_OK) {
|
if (FAudioCreate(&faud, flags, FAUDIO_DEFAULT_PROCESSOR) != R_OK) {
|
||||||
wxLogError(_("The FAudio interface failed to initialize!"));
|
wxLogError(_("The FAudio interface failed to initialize!"));
|
||||||
failed = true;
|
failed = true;
|
||||||
return false;
|
return false;
|
||||||
|
@ -359,27 +244,19 @@ bool FAudio_Output::init(long sampleRate)
|
||||||
soundBufferLen = (freq / 60) * 4;
|
soundBufferLen = (freq / 60) * 4;
|
||||||
// create own buffers to store sound data because it must not be
|
// create own buffers to store sound data because it must not be
|
||||||
// manipulated while the voice plays from it
|
// manipulated while the voice plays from it
|
||||||
buffers = (BYTE*)malloc((bufferCount + 1) * soundBufferLen);
|
buffers = (uint8_t*)malloc((bufferCount + 1) * soundBufferLen);
|
||||||
// + 1 because we need one temporary buffer when all others are in use
|
// + 1 because we need one temporary buffer when all others are in use
|
||||||
WAVEFORMATEX wfx;
|
FAudioWaveFormatEx wfx;
|
||||||
ZeroMemory(&wfx, sizeof(wfx));
|
memset(&wfx, NULL, sizeof(wfx));
|
||||||
wfx.wFormatTag = WAVE_FORMAT_PCM;
|
wfx.wFormatTag = FAUDIO_FORMAT_PCM;
|
||||||
wfx.nChannels = 2;
|
wfx.nChannels = 2;
|
||||||
wfx.nSamplesPerSec = freq;
|
wfx.nSamplesPerSec = freq;
|
||||||
wfx.wBitsPerSample = 16;
|
wfx.wBitsPerSample = 16;
|
||||||
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 = FAudio_CreateMasteringVoice(
|
|
||||||
faud,
|
|
||||||
&mVoice,
|
|
||||||
FAUDIO_DEFAULT_CHANNELS,
|
|
||||||
FAUDIO_DEFAULT_SAMPLERATE,
|
|
||||||
0,
|
|
||||||
FAGetDev(faud),
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (hr != S_OK) {
|
if (FAudio_CreateMasteringVoice(faud, &mVoice, FAUDIO_DEFAULT_CHANNELS, FAUDIO_DEFAULT_SAMPLERATE, 0, FAGetDev(faud), NULL) != R_OK) {
|
||||||
wxLogError(_("FAudio: Creating mastering voice failed!"));
|
wxLogError(_("FAudio: Creating mastering voice failed!"));
|
||||||
failed = true;
|
failed = true;
|
||||||
return false;
|
return false;
|
||||||
|
@ -388,9 +265,8 @@ bool FAudio_Output::init(long sampleRate)
|
||||||
// create sound emitter
|
// create sound emitter
|
||||||
//This should be FAudio_CreateSourceVoice()
|
//This should be FAudio_CreateSourceVoice()
|
||||||
//hr = faud->CreateSourceVoice(&sVoice, &wfx, 0, 4.0f, ¬ify);
|
//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) {
|
if (FAudio_CreateSourceVoice(faud, &sVoice, (const FAudioWaveFormatEx*)&wfx, 0, 4.0f, ¬ify, NULL, NULL) != R_OK) {
|
||||||
wxLogError(_("FAudio: Creating source voice failed!"));
|
wxLogError(_("FAudio: Creating source voice failed!"));
|
||||||
failed = true;
|
failed = true;
|
||||||
return false;
|
return false;
|
||||||
|
@ -399,9 +275,8 @@ bool FAudio_Output::init(long sampleRate)
|
||||||
if (gopts.upmix) {
|
if (gopts.upmix) {
|
||||||
// set up stereo upmixing
|
// set up stereo upmixing
|
||||||
FAudioDeviceDetails dd;
|
FAudioDeviceDetails dd;
|
||||||
ZeroMemory(&dd, sizeof(dd));
|
memset(&dd, NULL, sizeof(dd));
|
||||||
hr = FAudio_GetDeviceDetails(faud, 0, &dd);
|
assert(FAudio_GetDeviceDetails(faud, 0, &dd) == R_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);
|
||||||
|
|
||||||
|
@ -497,16 +372,14 @@ bool FAudio_Output::init(long sampleRate)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (matrixAvailable) {
|
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(FAudioVoice_SetOutputMatrix(sVoice, NULL, 2, dd.OutputFormat.Format.nChannels, matrix, FAUDIO_DEFAULT_CHANNELS) == R_OK);
|
||||||
assert(hr == S_OK);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
free(matrix);
|
free(matrix);
|
||||||
matrix = NULL;
|
matrix = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = FAudioSourceVoice_Start(sVoice, 0, FAUDIO_COMMIT_NOW);
|
assert(FAudioSourceVoice_Start(sVoice, 0, FAUDIO_COMMIT_NOW) == R_OK);
|
||||||
assert(hr == S_OK);
|
|
||||||
playing = true;
|
playing = true;
|
||||||
currentBuffer = 0;
|
currentBuffer = 0;
|
||||||
device_changed = false;
|
device_changed = false;
|
||||||
|
@ -516,7 +389,7 @@ bool FAudio_Output::init(long sampleRate)
|
||||||
|
|
||||||
void FAudio_Output::write(uint16_t* finalWave, int length)
|
void FAudio_Output::write(uint16_t* finalWave, int length)
|
||||||
{
|
{
|
||||||
UINT32 flags = 0;
|
uint32_t flags = 0;
|
||||||
if (!initialized || failed)
|
if (!initialized || failed)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -542,28 +415,27 @@ void FAudio_Output::write(uint16_t* finalWave, int length)
|
||||||
|
|
||||||
// there is at least one free buffer
|
// there is at least one free buffer
|
||||||
break;
|
break;
|
||||||
} else {
|
} //else {
|
||||||
// the maximum number of buffers is currently queued
|
// the maximum number of buffers is currently queued
|
||||||
if (!coreOptions.speedup && coreOptions.throttle && !gba_joybus_active) {
|
//if (!coreOptions.speedup && coreOptions.throttle && !gba_joybus_active) {
|
||||||
// wait for one buffer to finish playing
|
// wait for one buffer to finish playing
|
||||||
if (WaitForSingleObject(notify.hBufferEndEvent, 10000) == WAIT_TIMEOUT) {
|
// if (WaitForSingleObject(notify.hBufferEndEvent, 10000) == WAIT_TIMEOUT) {
|
||||||
device_changed = true;
|
// device_changed = true;
|
||||||
}
|
// }
|
||||||
} else {
|
//} else {
|
||||||
// drop current audio frame
|
// drop current audio frame
|
||||||
return;
|
// return;
|
||||||
}
|
//}
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy & protect the audio data in own memory area while playing it
|
// copy & protect the audio data in own memory area while playing it
|
||||||
CopyMemory(&buffers[currentBuffer * soundBufferLen], finalWave, soundBufferLen);
|
memcpy(&buffers[currentBuffer * soundBufferLen], finalWave, soundBufferLen);
|
||||||
buf.AudioBytes = soundBufferLen;
|
buf.AudioBytes = soundBufferLen;
|
||||||
buf.pAudioData = &buffers[currentBuffer * soundBufferLen];
|
buf.pAudioData = &buffers[currentBuffer * soundBufferLen];
|
||||||
currentBuffer++;
|
currentBuffer++;
|
||||||
currentBuffer %= (bufferCount + 1); // + 1 because we need one temporary buffer
|
currentBuffer %= (bufferCount + 1); // + 1 because we need one temporary buffer
|
||||||
HRESULT hr = FAudioSourceVoice_SubmitSourceBuffer(sVoice, &buf, NULL); // send buffer to queue.
|
assert(FAudioSourceVoice_SubmitSourceBuffer(sVoice, &buf, NULL) == R_OK);
|
||||||
assert(hr == S_OK);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FAudio_Output::pause()
|
void FAudio_Output::pause()
|
||||||
|
@ -572,8 +444,7 @@ void FAudio_Output::pause()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (playing) {
|
if (playing) {
|
||||||
HRESULT hr = FAudioSourceVoice_Stop(sVoice, 0, FAUDIO_COMMIT_NOW);
|
assert(FAudioSourceVoice_Stop(sVoice, 0, FAUDIO_COMMIT_NOW) == R_OK);
|
||||||
assert(hr == S_OK);
|
|
||||||
playing = false;
|
playing = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -584,8 +455,7 @@ void FAudio_Output::resume()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!playing) {
|
if (!playing) {
|
||||||
HRESULT hr = FAudioSourceVoice_Start(sVoice, 0, FAUDIO_COMMIT_NOW);
|
assert(FAudioSourceVoice_Start(sVoice, 0, FAUDIO_COMMIT_NOW) == R_OK);
|
||||||
assert(hr == S_OK);
|
|
||||||
playing = true;
|
playing = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -596,8 +466,7 @@ void FAudio_Output::reset()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (playing) {
|
if (playing) {
|
||||||
HRESULT hr = FAudioSourceVoice_Stop(sVoice, 0, FAUDIO_COMMIT_NOW);
|
assert(FAudioSourceVoice_Stop(sVoice, 0, FAUDIO_COMMIT_NOW) == R_OK);
|
||||||
assert(hr == S_OK);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FAudioSourceVoice_FlushSourceBuffers(sVoice);
|
FAudioSourceVoice_FlushSourceBuffers(sVoice);
|
||||||
|
@ -613,8 +482,7 @@ void FAudio_Output::setThrottle(unsigned short throttle_)
|
||||||
if (throttle_ == 0)
|
if (throttle_ == 0)
|
||||||
throttle_ = 100;
|
throttle_ = 100;
|
||||||
|
|
||||||
HRESULT hr = FAudioSourceVoice_SetFrequencyRatio(sVoice, (float)throttle_ / 100.0f, FAUDIO_MAX_FILTER_FREQUENCY);
|
assert(FAudioSourceVoice_SetFrequencyRatio(sVoice, (float)throttle_ / 100.0f, FAUDIO_MAX_FILTER_FREQUENCY) == R_OK);
|
||||||
assert(hr == S_OK);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void faudio_device_changed(FAudio_Output* instance)
|
void faudio_device_changed(FAudio_Output* instance)
|
||||||
|
|
Loading…
Reference in New Issue