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)