diff --git a/android/phoenix/res/xml/prefs.xml b/android/phoenix/res/xml/prefs.xml
index 4ffa8b1dcf..0b3142b73c 100644
--- a/android/phoenix/res/xml/prefs.xml
+++ b/android/phoenix/res/xml/prefs.xml
@@ -98,6 +98,12 @@
android:summary="Enable dynamic rate control (recommended)."
android:title="Dynamic Rate Control"
android:dependency="audio_enable" />
+
diff --git a/android/phoenix/src/org/retroarch/browser/CoreSelection.java b/android/phoenix/src/org/retroarch/browser/CoreSelection.java
index 70675051f3..44f59f267e 100644
--- a/android/phoenix/src/org/retroarch/browser/CoreSelection.java
+++ b/android/phoenix/src/org/retroarch/browser/CoreSelection.java
@@ -219,6 +219,7 @@ public class CoreSelection extends Activity implements
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
config.setBoolean("audio_rate_control", prefs.getBoolean("audio_rate_control", true));
config.setInt("audio_out_rate", getOptimalSamplingRate());
+ config.setInt("audio_latency", prefs.getBoolean("audio_high_latency", false) ? 160 : 64);
config.setBoolean("audio_enable", prefs.getBoolean("audio_enable", true));
config.setBoolean("video_smooth", prefs.getBoolean("video_smooth", true));
config.setBoolean("video_allow_rotate", prefs.getBoolean("video_allow_rotate", true));
diff --git a/audio/opensl.c b/audio/opensl.c
index 5339bbb3b6..068e42a7a2 100644
--- a/audio/opensl.c
+++ b/audio/opensl.c
@@ -33,13 +33,10 @@
#define SLPlayItf_SetPlayState(a, ...) ((*(a))->SetPlayState(a, __VA_ARGS__))
-// TODO: Are these sane?
-#define BUFFER_SIZE (2 * 1024)
-#define BUFFER_COUNT 16
-
typedef struct sl
{
- uint8_t buffer[BUFFER_COUNT][BUFFER_SIZE];
+ uint8_t **buffer;
+ uint8_t *buffer_chunk;
unsigned buffer_index;
unsigned buffer_ptr;
volatile unsigned buffered_blocks;
@@ -55,6 +52,7 @@ typedef struct sl
slock_t *lock;
scond_t *cond;
bool nonblock;
+ unsigned buf_size;
unsigned buf_count;
} sl_t;
@@ -93,6 +91,8 @@ static void sl_free(void *data)
if (sl->cond)
scond_free(sl->cond);
+ free(sl->buffer);
+ free(sl->buffer_chunk);
free(sl);
}
@@ -122,11 +122,23 @@ 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(SLObjectItf_Realize(sl->output_mix, SL_BOOLEAN_FALSE));
+ sl->buf_size = next_pow2(32 * latency);
sl->buf_count = (latency * 4 * out_rate + 500) / 1000;
- sl->buf_count = (sl->buf_count + BUFFER_SIZE / 2) / BUFFER_SIZE;
- sl->buf_count = min(sl->buf_count, BUFFER_COUNT);
+ sl->buf_count = (sl->buf_count + sl->buf_size / 2) / sl->buf_size;
- RARCH_LOG("[SLES] : Setting audio latency (buffer size: [%d]) ...\n", sl->buf_count * BUFFER_SIZE);
+ sl->buffer = (uint8_t**)calloc(sizeof(uint8_t*), sl->buf_count);
+ if (!sl->buffer)
+ goto error;
+
+ sl->buffer_chunk = (uint8_t*)calloc(sl->buf_count, sl->buf_size);
+ if (!sl->buffer_chunk)
+ goto error;
+
+ for (unsigned i = 0; i < sl->buf_count; i++)
+ sl->buffer[i] = sl->buffer_chunk + i * sl->buf_size;
+
+ RARCH_LOG("[SLES] : Setting audio latency: Block size = %u, Blocks = %u, Total = %u ...\n",
+ sl->buf_size, sl->buf_count, sl->buf_size * sl->buf_count);
fmt_pcm.formatType = SL_DATAFORMAT_PCM;
fmt_pcm.numChannels = 2;
@@ -164,7 +176,7 @@ static void *sl_init(const char *device, unsigned rate, unsigned latency)
sl->buffered_blocks = sl->buf_count;
sl->buffer_index = 0;
for (unsigned i = 0; i < sl->buf_count; i++)
- (*sl->buffer_queue)->Enqueue(sl->buffer_queue, sl->buffer[i], BUFFER_SIZE);
+ (*sl->buffer_queue)->Enqueue(sl->buffer_queue, sl->buffer[i], sl->buf_size);
GOTO_IF_FAIL(SLObjectItf_GetInterface(sl->buffer_queue_object, SL_IID_PLAY, &sl->player));
GOTO_IF_FAIL(SLPlayItf_SetPlayState(sl->player, SL_PLAYSTATE_PLAYING));
@@ -218,7 +230,7 @@ static ssize_t sl_write(void *data, const void *buf_, size_t size)
slock_unlock(sl->lock);
}
- size_t avail_write = min(BUFFER_SIZE - sl->buffer_ptr, size);
+ size_t avail_write = min(sl->buf_size - sl->buffer_ptr, size);
if (avail_write)
{
memcpy(sl->buffer[sl->buffer_index] + sl->buffer_ptr, buf, avail_write);
@@ -228,9 +240,9 @@ static ssize_t sl_write(void *data, const void *buf_, size_t size)
written += avail_write;
}
- if (sl->buffer_ptr >= BUFFER_SIZE)
+ if (sl->buffer_ptr >= sl->buf_size)
{
- SLresult res = (*sl->buffer_queue)->Enqueue(sl->buffer_queue, sl->buffer[sl->buffer_index], BUFFER_SIZE);
+ SLresult res = (*sl->buffer_queue)->Enqueue(sl->buffer_queue, sl->buffer[sl->buffer_index], sl->buf_size);
sl->buffer_index = (sl->buffer_index + 1) % sl->buf_count;
__sync_fetch_and_add(&sl->buffered_blocks, 1);
sl->buffer_ptr = 0;
@@ -243,22 +255,20 @@ static ssize_t sl_write(void *data, const void *buf_, size_t size)
}
}
- //RARCH_LOG("Blocks: %u\n", sl->buffered_blocks);
-
return written;
}
static size_t sl_write_avail(void *data)
{
sl_t *sl = (sl_t*)data;
- size_t avail = (sl->buf_count - (int)sl->buffered_blocks - 1) * BUFFER_SIZE + (BUFFER_SIZE - (int)sl->buffer_ptr);
+ size_t avail = (sl->buf_count - (int)sl->buffered_blocks - 1) * sl->buf_size + (sl->buf_size - (int)sl->buffer_ptr);
return avail;
}
static size_t sl_buffer_size(void *data)
{
sl_t *sl = (sl_t*)data;
- return BUFFER_SIZE * sl->buf_count;
+ return sl->buf_size * sl->buf_count;
}
static bool sl_use_float(void *data)