mirror of
https://github.com/libretro/RetroArch
synced 2025-03-26 11:37:30 +00:00
Use OpenSL in a more correct fashion.
This commit is contained in:
parent
df9cc5653d
commit
aadff4658f
@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
#include "../driver.h"
|
#include "../driver.h"
|
||||||
#include "../general.h"
|
#include "../general.h"
|
||||||
#include "../fifo_buffer.h"
|
|
||||||
#include "../thread.h"
|
#include "../thread.h"
|
||||||
|
|
||||||
#include <SLES/OpenSLES.h>
|
#include <SLES/OpenSLES.h>
|
||||||
@ -36,19 +35,23 @@
|
|||||||
|
|
||||||
// TODO: Are these sane?
|
// TODO: Are these sane?
|
||||||
#define BUFFER_SIZE 4096
|
#define BUFFER_SIZE 4096
|
||||||
|
#define BUFFER_COUNT 8
|
||||||
|
|
||||||
typedef struct sl
|
typedef struct sl
|
||||||
{
|
{
|
||||||
uint8_t buffer[BUFFER_SIZE];
|
uint8_t buffer[BUFFER_COUNT][BUFFER_SIZE];
|
||||||
|
unsigned buffer_index;
|
||||||
|
unsigned buffer_ptr;
|
||||||
|
volatile unsigned buffered_blocks;
|
||||||
|
|
||||||
SLObjectItf engine_object;
|
SLObjectItf engine_object;
|
||||||
SLEngineItf engine;
|
SLEngineItf engine;
|
||||||
|
|
||||||
SLObjectItf output_mix;
|
SLObjectItf output_mix;
|
||||||
SLObjectItf buffer_queue_object;
|
SLObjectItf buffer_queue_object;
|
||||||
|
SLAndroidSimpleBufferQueueItf buffer_queue;
|
||||||
SLPlayItf player;
|
SLPlayItf player;
|
||||||
|
|
||||||
fifo_buffer_t *fifo;
|
|
||||||
slock_t *lock;
|
slock_t *lock;
|
||||||
scond_t *cond;
|
scond_t *cond;
|
||||||
bool nonblock;
|
bool nonblock;
|
||||||
@ -60,15 +63,9 @@ static void opensl_callback(SLAndroidSimpleBufferQueueItf bq, void *ctx)
|
|||||||
sl_t *sl = (sl_t*)ctx;
|
sl_t *sl = (sl_t*)ctx;
|
||||||
|
|
||||||
slock_lock(sl->lock);
|
slock_lock(sl->lock);
|
||||||
size_t read_avail = fifo_read_avail(sl->fifo);
|
sl->buffered_blocks--;
|
||||||
if (read_avail > BUFFER_SIZE)
|
|
||||||
read_avail = BUFFER_SIZE;
|
|
||||||
fifo_read(sl->fifo, sl->buffer, read_avail);
|
|
||||||
slock_unlock(sl->lock);
|
slock_unlock(sl->lock);
|
||||||
|
|
||||||
memset(sl->buffer + read_avail, 0, BUFFER_SIZE - read_avail);
|
|
||||||
(*bq)->Enqueue(bq, sl->buffer, BUFFER_SIZE);
|
|
||||||
|
|
||||||
scond_signal(sl->cond);
|
scond_signal(sl->cond);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,8 +92,6 @@ static void sl_free(void *data)
|
|||||||
if (sl->engine_object)
|
if (sl->engine_object)
|
||||||
SLObjectItf_Destroy(sl->engine_object);
|
SLObjectItf_Destroy(sl->engine_object);
|
||||||
|
|
||||||
if (sl->fifo)
|
|
||||||
fifo_free(sl->fifo);
|
|
||||||
if (sl->lock)
|
if (sl->lock)
|
||||||
slock_free(sl->lock);
|
slock_free(sl->lock);
|
||||||
if (sl->cond)
|
if (sl->cond)
|
||||||
@ -119,8 +114,6 @@ static void *sl_init(const char *device, unsigned rate, unsigned latency)
|
|||||||
SLInterfaceID id = SL_IID_ANDROIDSIMPLEBUFFERQUEUE;
|
SLInterfaceID id = SL_IID_ANDROIDSIMPLEBUFFERQUEUE;
|
||||||
SLboolean req = SL_BOOLEAN_TRUE;
|
SLboolean req = SL_BOOLEAN_TRUE;
|
||||||
|
|
||||||
SLAndroidSimpleBufferQueueItf buffer_queue = NULL;
|
|
||||||
|
|
||||||
SLresult res = 0;
|
SLresult res = 0;
|
||||||
sl_t *sl = (sl_t*)calloc(1, sizeof(sl_t));
|
sl_t *sl = (sl_t*)calloc(1, sizeof(sl_t));
|
||||||
if (!sl)
|
if (!sl)
|
||||||
@ -132,7 +125,7 @@ static void *sl_init(const char *device, unsigned rate, unsigned latency)
|
|||||||
GOTO_IF_FAIL(SLEngineItf_CreateOutputMix(sl->engine, &sl->output_mix, 0, NULL, NULL));
|
GOTO_IF_FAIL(SLEngineItf_CreateOutputMix(sl->engine, &sl->output_mix, 0, NULL, NULL));
|
||||||
GOTO_IF_FAIL(SLObjectItf_Realize(sl->output_mix, SL_BOOLEAN_FALSE));
|
GOTO_IF_FAIL(SLObjectItf_Realize(sl->output_mix, SL_BOOLEAN_FALSE));
|
||||||
|
|
||||||
sl->buf_count = 8;
|
sl->buf_count = BUFFER_COUNT;
|
||||||
|
|
||||||
RARCH_LOG("[SLES] : Setting audio latency (buffer size: [%d])..\n", sl->buf_count * BUFFER_SIZE);
|
RARCH_LOG("[SLES] : Setting audio latency (buffer size: [%d])..\n", sl->buf_count * BUFFER_SIZE);
|
||||||
|
|
||||||
@ -161,14 +154,18 @@ static void *sl_init(const char *device, unsigned rate, unsigned latency)
|
|||||||
GOTO_IF_FAIL(SLObjectItf_Realize(sl->buffer_queue_object, SL_BOOLEAN_FALSE));
|
GOTO_IF_FAIL(SLObjectItf_Realize(sl->buffer_queue_object, SL_BOOLEAN_FALSE));
|
||||||
|
|
||||||
GOTO_IF_FAIL(SLObjectItf_GetInterface(sl->buffer_queue_object, SL_IID_BUFFERQUEUE,
|
GOTO_IF_FAIL(SLObjectItf_GetInterface(sl->buffer_queue_object, SL_IID_BUFFERQUEUE,
|
||||||
&buffer_queue));
|
&sl->buffer_queue));
|
||||||
|
|
||||||
sl->cond = scond_new();
|
sl->cond = scond_new();
|
||||||
sl->lock = slock_new();
|
sl->lock = slock_new();
|
||||||
sl->fifo = fifo_new(BUFFER_SIZE * sl->buf_count);
|
|
||||||
|
|
||||||
(*buffer_queue)->RegisterCallback(buffer_queue, opensl_callback, sl);
|
(*sl->buffer_queue)->RegisterCallback(sl->buffer_queue, opensl_callback, sl);
|
||||||
(*buffer_queue)->Enqueue(buffer_queue, sl->buffer, BUFFER_SIZE);
|
|
||||||
|
// Enqueue a bit to get stuff rolling.
|
||||||
|
sl->buffered_blocks = BUFFER_COUNT;
|
||||||
|
sl->buffer_index = 0;
|
||||||
|
for (unsigned i = 0; i < BUFFER_COUNT; i++)
|
||||||
|
(*sl->buffer_queue)->Enqueue(sl->buffer_queue, sl->buffer[i], BUFFER_SIZE);
|
||||||
|
|
||||||
GOTO_IF_FAIL(SLObjectItf_GetInterface(sl->buffer_queue_object, SL_IID_PLAY, &sl->player));
|
GOTO_IF_FAIL(SLObjectItf_GetInterface(sl->buffer_queue_object, SL_IID_PLAY, &sl->player));
|
||||||
GOTO_IF_FAIL(SLPlayItf_SetPlayState(sl->player, SL_PLAYSTATE_PLAYING));
|
GOTO_IF_FAIL(SLPlayItf_SetPlayState(sl->player, SL_PLAYSTATE_PLAYING));
|
||||||
@ -213,28 +210,39 @@ static ssize_t sl_write(void *data, const void *buf_, size_t size)
|
|||||||
while (size)
|
while (size)
|
||||||
{
|
{
|
||||||
slock_lock(sl->lock);
|
slock_lock(sl->lock);
|
||||||
|
if (sl->nonblock)
|
||||||
size_t write_avail = fifo_write_avail(sl->fifo);
|
|
||||||
if (write_avail > size)
|
|
||||||
write_avail = size;
|
|
||||||
|
|
||||||
if (write_avail)
|
|
||||||
{
|
{
|
||||||
fifo_write(sl->fifo, buf, write_avail);
|
if (sl->buffered_blocks == BUFFER_COUNT)
|
||||||
slock_unlock(sl->lock);
|
{
|
||||||
written += write_avail;
|
slock_unlock(sl->lock);
|
||||||
size -= write_avail;
|
break;
|
||||||
buf += write_avail;
|
}
|
||||||
}
|
|
||||||
else if (!sl->nonblock)
|
|
||||||
{
|
|
||||||
scond_wait(sl->cond, sl->lock);
|
|
||||||
slock_unlock(sl->lock);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
while (sl->buffered_blocks == BUFFER_COUNT)
|
||||||
|
scond_wait(sl->cond, sl->lock);
|
||||||
|
}
|
||||||
|
slock_unlock(sl->lock);
|
||||||
|
|
||||||
|
size_t avail_write = min(BUFFER_SIZE - sl->buffer_ptr, size);
|
||||||
|
if (avail_write)
|
||||||
|
{
|
||||||
|
memcpy(sl->buffer[sl->buffer_index] + sl->buffer_ptr, buf, avail_write);
|
||||||
|
sl->buffer_ptr += avail_write;
|
||||||
|
buf += avail_write;
|
||||||
|
size -= avail_write;
|
||||||
|
written += avail_write;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sl->buffer_ptr >= BUFFER_SIZE)
|
||||||
|
{
|
||||||
|
slock_lock(sl->lock);
|
||||||
|
(*sl->buffer_queue)->Enqueue(sl->buffer_queue, sl->buffer[sl->buffer_index], BUFFER_SIZE);
|
||||||
|
sl->buffer_index = (sl->buffer_index + 1) & (BUFFER_COUNT - 1);
|
||||||
|
sl->buffered_blocks++;
|
||||||
slock_unlock(sl->lock);
|
slock_unlock(sl->lock);
|
||||||
break;
|
sl->buffer_ptr = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -245,15 +253,15 @@ static size_t sl_write_avail(void *data)
|
|||||||
{
|
{
|
||||||
sl_t *sl = (sl_t*)data;
|
sl_t *sl = (sl_t*)data;
|
||||||
slock_lock(sl->lock);
|
slock_lock(sl->lock);
|
||||||
size_t avail = fifo_write_avail(sl->fifo);
|
size_t avail = (BUFFER_COUNT - (int)sl->buffered_blocks - 1) * BUFFER_SIZE + (BUFFER_SIZE - (int)sl->buffer_ptr);
|
||||||
slock_unlock(sl->lock);
|
slock_unlock(sl->lock);
|
||||||
return avail;
|
return avail;
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t sl_buffer_size(void *data)
|
static size_t sl_buffer_size(void *data)
|
||||||
{
|
{
|
||||||
sl_t *sl = (sl_t*)data;
|
(void)data;
|
||||||
return BUFFER_SIZE * sl->buf_count;
|
return BUFFER_SIZE * BUFFER_COUNT;
|
||||||
}
|
}
|
||||||
|
|
||||||
const audio_driver_t audio_opensl = {
|
const audio_driver_t audio_opensl = {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user