mirror of
https://github.com/libretro/RetroArch.git
synced 2024-11-23 16:09:47 +00:00
(Audio) Update
This commit is contained in:
parent
6c97a7514c
commit
fa00cdba20
@ -53,10 +53,6 @@
|
||||
#pragma comment(lib, "dxguid")
|
||||
#endif
|
||||
|
||||
/* Forward declarations */
|
||||
static ssize_t dsound_write_nonblock(void *data, const void *buf_, size_t size);
|
||||
static ssize_t dsound_write(void *data, const void *buf_, size_t size);
|
||||
|
||||
typedef struct dsound
|
||||
{
|
||||
LPDIRECTSOUND ds;
|
||||
@ -489,40 +485,6 @@ static void dsound_set_nonblock_state(void *data, bool state)
|
||||
dsound_t *ds = (dsound_t*)data;
|
||||
if (ds)
|
||||
ds->nonblock = state;
|
||||
|
||||
if (ds->nonblock)
|
||||
audio_dsound.write = dsound_write_nonblock;
|
||||
else
|
||||
audio_dsound.write = dsound_write;
|
||||
}
|
||||
|
||||
static ssize_t dsound_write_nonblock(void *data, const void *buf_, size_t size)
|
||||
{
|
||||
size_t written = 0;
|
||||
dsound_t *ds = (dsound_t*)data;
|
||||
const uint8_t *buf = (const uint8_t*)buf_;
|
||||
|
||||
if (!ds->thread_alive)
|
||||
return -1;
|
||||
|
||||
if (size > 0)
|
||||
{
|
||||
size_t avail;
|
||||
|
||||
EnterCriticalSection(&ds->crit);
|
||||
avail = fifo_write_avail(ds->buffer);
|
||||
if (avail > size)
|
||||
avail = size;
|
||||
|
||||
fifo_write(ds->buffer, buf, avail);
|
||||
LeaveCriticalSection(&ds->crit);
|
||||
|
||||
buf += avail;
|
||||
size -= avail;
|
||||
written += avail;
|
||||
}
|
||||
|
||||
return written;
|
||||
}
|
||||
|
||||
static ssize_t dsound_write(void *data, const void *buf_, size_t size)
|
||||
@ -550,7 +512,7 @@ static ssize_t dsound_write(void *data, const void *buf_, size_t size)
|
||||
size -= avail;
|
||||
written += avail;
|
||||
|
||||
if (!ds->thread_alive)
|
||||
if (ds->nonblock || !ds->thread_alive)
|
||||
break;
|
||||
|
||||
if (avail == 0)
|
||||
|
@ -40,12 +40,6 @@ typedef struct
|
||||
fifo_buffer_t *buffer; /* NULL in unbuffered shared mode */
|
||||
} wasapi_t;
|
||||
|
||||
/* forward declaration */
|
||||
static ssize_t wasapi_write_blocking_exclusive(void *wh, const void *data, size_t size);
|
||||
static ssize_t wasapi_write_blocking(void *wh, const void *data, size_t size);
|
||||
static ssize_t wasapi_write_ex(void *wh, const void *data, size_t size);
|
||||
static ssize_t wasapi_write_sh(void *wh, const void *data, size_t size);
|
||||
|
||||
static IMMDevice *wasapi_init_device(const char *id)
|
||||
{
|
||||
HRESULT hr;
|
||||
@ -583,21 +577,6 @@ static void *wasapi_init(const char *dev_id, unsigned rate, unsigned latency,
|
||||
w->running = true;
|
||||
w->blocking = settings->bools.audio_sync;
|
||||
|
||||
if (w->blocking)
|
||||
{
|
||||
if (w->exclusive)
|
||||
audio_wasapi.write = wasapi_write_blocking_exclusive;
|
||||
else
|
||||
audio_wasapi.write = wasapi_write_blocking;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (w->exclusive)
|
||||
audio_wasapi.write = wasapi_write_ex;
|
||||
else
|
||||
audio_wasapi.write = wasapi_write_sh;
|
||||
}
|
||||
|
||||
return w;
|
||||
|
||||
error:
|
||||
@ -651,7 +630,7 @@ static bool wasapi_flush_buffer(wasapi_t * w, size_t size)
|
||||
return true;
|
||||
}
|
||||
|
||||
static ssize_t wasapi_write_sh_blocking(wasapi_t *w, const void * data, size_t size)
|
||||
static ssize_t wasapi_write_sh(wasapi_t *w, const void * data, size_t size)
|
||||
{
|
||||
DWORD ir;
|
||||
HRESULT hr;
|
||||
@ -666,33 +645,39 @@ static ssize_t wasapi_write_sh_blocking(wasapi_t *w, const void * data, size_t s
|
||||
{
|
||||
size_t read_avail = 0;
|
||||
|
||||
if (w->blocking)
|
||||
{
|
||||
ir = WaitForSingleObject(w->write_event, INFINITE);
|
||||
if (!(ir == WAIT_OBJECT_0))
|
||||
return -1;
|
||||
}
|
||||
|
||||
hr = _IAudioClient_GetCurrentPadding(w->client, &padding);
|
||||
if (FAILED(hr))
|
||||
return -1;
|
||||
|
||||
read_avail = fifo_read_avail(w->buffer);
|
||||
write_avail = w->engine_buffer_size - padding * w->frame_size;
|
||||
written = read_avail < write_avail ? read_avail : write_avail;
|
||||
if (written)
|
||||
if (!wasapi_flush_buffer(w, written))
|
||||
return -1;
|
||||
}
|
||||
|
||||
write_avail = fifo_write_avail(w->buffer);
|
||||
written = size < write_avail ? size : write_avail;
|
||||
if (written)
|
||||
fifo_write(w->buffer, data, written);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (w->blocking)
|
||||
{
|
||||
ir = WaitForSingleObject(w->write_event, INFINITE);
|
||||
if (!(ir == WAIT_OBJECT_0))
|
||||
return -1;
|
||||
|
||||
hr = _IAudioClient_GetCurrentPadding(w->client, &padding);
|
||||
if (FAILED(hr))
|
||||
return -1;
|
||||
|
||||
read_avail = fifo_read_avail(w->buffer);
|
||||
write_avail = w->engine_buffer_size - padding * w->frame_size;
|
||||
written = read_avail < write_avail ? read_avail : write_avail;
|
||||
if (written)
|
||||
if (!wasapi_flush_buffer(w, written))
|
||||
return -1;
|
||||
}
|
||||
|
||||
write_avail = fifo_write_avail(w->buffer);
|
||||
written = size < write_avail ? size : write_avail;
|
||||
if (written)
|
||||
fifo_write(w->buffer, data, written);
|
||||
}
|
||||
else
|
||||
{
|
||||
ir = WaitForSingleObject(w->write_event, INFINITE);
|
||||
if (!(ir == WAIT_OBJECT_0))
|
||||
return -1;
|
||||
|
||||
hr = _IAudioClient_GetCurrentPadding(w->client, &padding);
|
||||
if (FAILED(hr))
|
||||
return -1;
|
||||
@ -710,135 +695,56 @@ static ssize_t wasapi_write_sh_blocking(wasapi_t *w, const void * data, size_t s
|
||||
return written;
|
||||
}
|
||||
|
||||
static ssize_t wasapi_write_sh(void *_data, const void * data, size_t size)
|
||||
static ssize_t wasapi_write_ex(wasapi_t *w, const void * data, size_t size)
|
||||
{
|
||||
DWORD ir;
|
||||
HRESULT hr;
|
||||
size_t write_avail = 0;
|
||||
ssize_t written = -1;
|
||||
UINT32 padding = 0;
|
||||
wasapi_t *w = (wasapi_t*)_data;
|
||||
ssize_t written = 0;
|
||||
size_t write_avail = fifo_write_avail(w->buffer);
|
||||
|
||||
if (w->buffer)
|
||||
if (!write_avail)
|
||||
{
|
||||
write_avail = fifo_write_avail(w->buffer);
|
||||
if (!write_avail)
|
||||
DWORD ir = WaitForSingleObject(
|
||||
w->write_event, w->blocking ? INFINITE : 0);
|
||||
if (ir != WAIT_OBJECT_0)
|
||||
{
|
||||
size_t read_avail = 0;
|
||||
|
||||
hr = _IAudioClient_GetCurrentPadding(w->client, &padding);
|
||||
if (FAILED(hr))
|
||||
if (w->blocking)
|
||||
return -1;
|
||||
|
||||
read_avail = fifo_read_avail(w->buffer);
|
||||
write_avail = w->engine_buffer_size - padding * w->frame_size;
|
||||
written = read_avail < write_avail ? read_avail : write_avail;
|
||||
if (written)
|
||||
if (!wasapi_flush_buffer(w, written))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
write_avail = fifo_write_avail(w->buffer);
|
||||
written = size < write_avail ? size : write_avail;
|
||||
if (written)
|
||||
fifo_write(w->buffer, data, written);
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = _IAudioClient_GetCurrentPadding(w->client, &padding);
|
||||
if (FAILED(hr))
|
||||
if (!wasapi_flush_buffer(w, w->engine_buffer_size))
|
||||
return -1;
|
||||
|
||||
write_avail = w->engine_buffer_size - padding * w->frame_size;
|
||||
if (!write_avail)
|
||||
return 0;
|
||||
write_avail = w->engine_buffer_size;
|
||||
}
|
||||
|
||||
written = size < write_avail ? size : write_avail;
|
||||
if (written)
|
||||
if (!wasapi_flush(w, data, written))
|
||||
written = size < write_avail ? size : write_avail;
|
||||
fifo_write(w->buffer, data, written);
|
||||
|
||||
return written;
|
||||
}
|
||||
|
||||
static ssize_t wasapi_write(void *wh, const void *data, size_t size)
|
||||
{
|
||||
size_t written;
|
||||
wasapi_t *w = (wasapi_t*)wh;
|
||||
|
||||
if (w->blocking)
|
||||
{
|
||||
ssize_t ir;
|
||||
for (written = 0, ir = -1; written < size; written += ir)
|
||||
{
|
||||
if (w->exclusive)
|
||||
ir = wasapi_write_ex(w, (char*)data + written, size - written);
|
||||
else
|
||||
ir = wasapi_write_sh(w, (char*)data + written, size - written);
|
||||
if (ir == -1)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return written;
|
||||
}
|
||||
|
||||
static ssize_t wasapi_write_ex_blocking(wasapi_t *w, const void * data, size_t size)
|
||||
{
|
||||
ssize_t written = 0;
|
||||
size_t write_avail = fifo_write_avail(w->buffer);
|
||||
|
||||
if (!write_avail)
|
||||
{
|
||||
DWORD ir = WaitForSingleObject(
|
||||
w->write_event, INFINITE);
|
||||
if (ir != WAIT_OBJECT_0)
|
||||
return -1;
|
||||
|
||||
if (!wasapi_flush_buffer(w, w->engine_buffer_size))
|
||||
return -1;
|
||||
|
||||
write_avail = w->engine_buffer_size;
|
||||
}
|
||||
|
||||
written = size < write_avail ? size : write_avail;
|
||||
fifo_write(w->buffer, data, written);
|
||||
|
||||
return written;
|
||||
}
|
||||
|
||||
static ssize_t wasapi_write_ex(void *_data, const void * data, size_t size)
|
||||
{
|
||||
ssize_t written = 0;
|
||||
wasapi_t *w = (wasapi_t*)_data;
|
||||
size_t write_avail = fifo_write_avail(w->buffer);
|
||||
|
||||
if (!write_avail)
|
||||
{
|
||||
DWORD ir = WaitForSingleObject(
|
||||
w->write_event, 0);
|
||||
if (ir != WAIT_OBJECT_0)
|
||||
return 0;
|
||||
|
||||
if (!wasapi_flush_buffer(w, w->engine_buffer_size))
|
||||
return -1;
|
||||
|
||||
write_avail = w->engine_buffer_size;
|
||||
}
|
||||
|
||||
written = size < write_avail ? size : write_avail;
|
||||
fifo_write(w->buffer, data, written);
|
||||
|
||||
return written;
|
||||
}
|
||||
|
||||
static ssize_t wasapi_write_blocking_exclusive(void *wh, const void *data, size_t size)
|
||||
{
|
||||
ssize_t ir;
|
||||
size_t written;
|
||||
wasapi_t *w = (wasapi_t*)wh;
|
||||
|
||||
for (written = 0, ir = -1; written < size; written += ir)
|
||||
{
|
||||
ir = wasapi_write_ex_blocking(w, (char*)data + written, size - written);
|
||||
if (ir == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return written;
|
||||
}
|
||||
|
||||
static ssize_t wasapi_write_blocking(void *wh, const void *data, size_t size)
|
||||
{
|
||||
ssize_t ir;
|
||||
size_t written;
|
||||
wasapi_t *w = (wasapi_t*)wh;
|
||||
|
||||
for (written = 0, ir = -1; written < size; written += ir)
|
||||
{
|
||||
ir = wasapi_write_sh_blocking(w, (char*)data + written, size - written);
|
||||
if (ir == -1)
|
||||
return -1;
|
||||
}
|
||||
else if (w->exclusive)
|
||||
written = wasapi_write_ex(w, data, size);
|
||||
else
|
||||
written = wasapi_write_sh(w, data, size);
|
||||
|
||||
return written;
|
||||
}
|
||||
@ -885,20 +791,6 @@ static void wasapi_set_nonblock_state(void *wh, bool nonblock)
|
||||
RARCH_LOG("[WASAPI]: Sync %s.\n", nonblock ? "off" : "on");
|
||||
|
||||
w->blocking = !nonblock;
|
||||
if (w->blocking)
|
||||
{
|
||||
if (w->exclusive)
|
||||
audio_wasapi.write = wasapi_write_blocking_exclusive;
|
||||
else
|
||||
audio_wasapi.write = wasapi_write_blocking;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (w->exclusive)
|
||||
audio_wasapi.write = wasapi_write_ex;
|
||||
else
|
||||
audio_wasapi.write = wasapi_write_sh;
|
||||
}
|
||||
}
|
||||
|
||||
static void wasapi_free(void *wh)
|
||||
@ -972,7 +864,7 @@ static size_t wasapi_buffer_size(void *wh)
|
||||
|
||||
audio_driver_t audio_wasapi = {
|
||||
wasapi_init,
|
||||
wasapi_write_sh,
|
||||
wasapi_write,
|
||||
wasapi_stop,
|
||||
wasapi_start,
|
||||
wasapi_alive,
|
||||
|
@ -322,73 +322,24 @@ static void *xa_init(const char *device, unsigned rate, unsigned latency,
|
||||
return xa;
|
||||
}
|
||||
|
||||
static ssize_t xa_write_nonblock(void *data, const void *buf, size_t size)
|
||||
static ssize_t xa_write(void *data, const void *buf, size_t size)
|
||||
{
|
||||
unsigned bytes;
|
||||
xa_t *xa = (xa_t*)data;
|
||||
xaudio2_t *handle = xa->xa;
|
||||
const uint8_t *buffer = (const uint8_t*)buf;
|
||||
size_t avail = XAUDIO2_WRITE_AVAILABLE(xa->xa);
|
||||
|
||||
if (avail == 0)
|
||||
return 0;
|
||||
if (avail < size)
|
||||
size = avail;
|
||||
|
||||
bytes = size;
|
||||
|
||||
while (bytes)
|
||||
if (xa->nonblock)
|
||||
{
|
||||
unsigned need = MIN(bytes, handle->bufsize - handle->bufptr);
|
||||
size_t avail = XAUDIO2_WRITE_AVAILABLE(xa->xa);
|
||||
|
||||
memcpy(handle->buf + handle->write_buffer *
|
||||
handle->bufsize + handle->bufptr,
|
||||
buffer, need);
|
||||
|
||||
handle->bufptr += need;
|
||||
buffer += need;
|
||||
bytes -= need;
|
||||
|
||||
if (handle->bufptr == handle->bufsize)
|
||||
{
|
||||
XAUDIO2_BUFFER xa2buffer;
|
||||
|
||||
while (handle->buffers == MAX_BUFFERS - 1)
|
||||
WaitForSingleObject(handle->hEvent, INFINITE);
|
||||
|
||||
xa2buffer.Flags = 0;
|
||||
xa2buffer.AudioBytes = handle->bufsize;
|
||||
xa2buffer.pAudioData = handle->buf + handle->write_buffer * handle->bufsize;
|
||||
xa2buffer.PlayBegin = 0;
|
||||
xa2buffer.PlayLength = 0;
|
||||
xa2buffer.LoopBegin = 0;
|
||||
xa2buffer.LoopLength = 0;
|
||||
xa2buffer.LoopCount = 0;
|
||||
xa2buffer.pContext = NULL;
|
||||
|
||||
if (FAILED(IXAudio2SourceVoice_SubmitSourceBuffer(
|
||||
handle->pSourceVoice, &xa2buffer, NULL)))
|
||||
{
|
||||
if (size > 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
InterlockedIncrement((LONG volatile*)&handle->buffers);
|
||||
handle->bufptr = 0;
|
||||
handle->write_buffer = (handle->write_buffer + 1) & MAX_BUFFERS_MASK;
|
||||
}
|
||||
if (avail == 0)
|
||||
return 0;
|
||||
if (avail < size)
|
||||
size = avail;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t xa_write(void *data, const void *buf, size_t size)
|
||||
{
|
||||
xa_t *xa = (xa_t*)data;
|
||||
xaudio2_t *handle = xa->xa;
|
||||
const uint8_t *buffer = (const uint8_t*)buf;
|
||||
unsigned bytes = size;
|
||||
bytes = size;
|
||||
|
||||
while (bytes)
|
||||
{
|
||||
@ -455,13 +406,7 @@ static void xa_set_nonblock_state(void *data, bool state)
|
||||
{
|
||||
xa_t *xa = (xa_t*)data;
|
||||
if (xa)
|
||||
{
|
||||
xa->nonblock = state;
|
||||
if (xa->nonblock)
|
||||
audio_xa.write = xa_write_nonblock;
|
||||
else
|
||||
audio_xa.write = xa_write;
|
||||
}
|
||||
xa->nonblock = state;
|
||||
}
|
||||
|
||||
static bool xa_start(void *data, bool is_shutdown)
|
||||
|
Loading…
Reference in New Issue
Block a user