From 7510caa0c5ef3db320d1065f869d14c0eddecf79 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 10 Nov 2013 23:39:22 +0100 Subject: ao_openal: support non-interleaved output Since ao_openal simulates multi-channel audio by placing a bunch of mono-sources in 3D space, non-interleaved audio is a perfect match for it. We just have to remove the interleaving code. --- audio/out/ao_openal.c | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) (limited to 'audio/out/ao_openal.c') diff --git a/audio/out/ao_openal.c b/audio/out/ao_openal.c index 256e50f281..c126852389 100644 --- a/audio/out/ao_openal.c +++ b/audio/out/ao_openal.c @@ -45,12 +45,12 @@ #define MAX_CHANS MP_NUM_CHANNELS #define NUM_BUF 128 #define CHUNK_SIZE 512 +#define CHUNK_SAMPLES (CHUNK_SIZE / 2) static ALuint buffers[MAX_CHANS][NUM_BUF]; static ALuint sources[MAX_CHANS]; static int cur_buf[MAX_CHANS]; static int unqueue_buf[MAX_CHANS]; -static int16_t *tmpbuf; static struct ao *ao_data; @@ -169,8 +169,7 @@ static int init(struct ao *ao) alcGetIntegerv(dev, ALC_FREQUENCY, 1, &freq); if (alcGetError(dev) == ALC_NO_ERROR && freq) ao->samplerate = freq; - ao->format = AF_FORMAT_S16_NE; - tmpbuf = malloc(CHUNK_SIZE); + ao->format = AF_FORMAT_S16P; return 0; err_out: @@ -182,7 +181,6 @@ static void uninit(struct ao *ao, bool immed) { ALCcontext *ctx = alcGetCurrentContext(); ALCdevice *dev = alcGetContextsDevice(ctx); - free(tmpbuf); if (!immed) { ALint state; alGetSourcei(sources[0], AL_SOURCE_STATE, &state); @@ -251,7 +249,7 @@ static int get_space(struct ao *ao) queued = NUM_BUF - queued - 3; if (queued < 0) return 0; - return (queued * CHUNK_SIZE * ao->channels.num) / ao->sstride; + return queued * CHUNK_SAMPLES; } /** @@ -260,26 +258,21 @@ static int get_space(struct ao *ao) static int play(struct ao *ao, void **data, int samples, int flags) { ALint state; - int i, j, k; - int ch; - int16_t *d = data[0]; - int len = samples * ao->sstride; - len /= ao->channels.num * CHUNK_SIZE; - for (i = 0; i < len; i++) { - for (ch = 0; ch < ao->channels.num; ch++) { - for (j = 0, k = ch; j < CHUNK_SIZE / 2; j++, k += ao->channels.num) - tmpbuf[j] = d[k]; - alBufferData(buffers[ch][cur_buf[ch]], AL_FORMAT_MONO16, tmpbuf, + int num = samples / CHUNK_SAMPLES; + for (int i = 0; i < num; i++) { + for (int ch = 0; ch < ao->channels.num; ch++) { + int16_t *d = data[ch]; + d += i * CHUNK_SAMPLES; + alBufferData(buffers[ch][cur_buf[ch]], AL_FORMAT_MONO16, d, CHUNK_SIZE, ao->samplerate); alSourceQueueBuffers(sources[ch], 1, &buffers[ch][cur_buf[ch]]); cur_buf[ch] = (cur_buf[ch] + 1) % NUM_BUF; } - d += ao->channels.num * CHUNK_SIZE / 2; } alGetSourcei(sources[0], AL_SOURCE_STATE, &state); if (state != AL_PLAYING) // checked here in case of an underrun alSourcePlayv(ao->channels.num, sources); - return len * ao->channels.num * CHUNK_SIZE / ao->sstride; + return num * CHUNK_SAMPLES; } static float get_delay(struct ao *ao) @@ -287,7 +280,7 @@ static float get_delay(struct ao *ao) ALint queued; unqueue_buffers(); alGetSourcei(sources[0], AL_BUFFERS_QUEUED, &queued); - return queued * CHUNK_SIZE / 2 / (float)ao->samplerate; + return queued * CHUNK_SAMPLES / (float)ao->samplerate; } #define OPT_BASE_STRUCT struct priv -- cgit v1.2.3