Add high latency audio support for Android.

Should fix ghetto hardware again.
This commit is contained in:
Themaister 2013-08-12 20:13:06 +02:00
parent 3122dbf4e6
commit 16ca310f93
3 changed files with 33 additions and 16 deletions

View File

@ -98,6 +98,12 @@
android:summary="Enable dynamic rate control (recommended)."
android:title="Dynamic Rate Control"
android:dependency="audio_enable" />
<CheckBoxPreference
android:defaultValue="false"
android:key="audio_high_latency"
android:summary="Use (very) high latency audio. Necessary for older Android devices with poor audio drivers."
android:title="High latency audio"
android:dependency="audio_enable" />
</PreferenceCategory>
</PreferenceScreen>
<PreferenceScreen android:title="Input Options" >

View File

@ -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));

View File

@ -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)