From db5462372c22d04a44f2264262a9517f6ef8f1c8 Mon Sep 17 00:00:00 2001 From: Themaister Date: Sun, 22 Aug 2010 21:18:48 +0200 Subject: [PATCH 1/6] Shouldn't write in non-blocking, if it blocks. --- rsound.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rsound.c b/rsound.c index e37b62594b..181f0859c8 100644 --- a/rsound.c +++ b/rsound.c @@ -75,7 +75,7 @@ static ssize_t __rsd_write(void* data, const void* buf, size_t size) { rsd_t *rsd = data; - if ( rsd_delay_ms(rsd->rd) > rsd->latency && rsd->nonblock ) + if ( (rsd_delay_ms(rsd->rd) > rsd->latency || rsd_get_avail(rsd->rd) < size) && rsd->nonblock ) return 0; if ( size == 0 ) From 6067946fd5858d774e1fa623ee22c822de7eb725 Mon Sep 17 00:00:00 2001 From: Themaister Date: Wed, 25 Aug 2010 22:38:53 +0200 Subject: [PATCH 2/6] Something that should look like an openal driver. --- openal.c | 249 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 249 insertions(+) create mode 100644 openal.c diff --git a/openal.c b/openal.c new file mode 100644 index 0000000000..8432084c18 --- /dev/null +++ b/openal.c @@ -0,0 +1,249 @@ +/* SSNES - A Super Ninteno Entertainment System (SNES) Emulator frontend for libsnes. + * Copyright (C) 2010 - Hans-Kristian Arntzen + * + * Some code herein may be based on code found in BSNES. + * + * SSNES is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with SSNES. + * If not, see . + */ + + +#include "driver.h" +#include +#include + +#define BUFSIZE 128 + +typedef struct al +{ + ALuint source; + ALuint *buffers; + ALuint *res_buf; + int res_ptr; + ALenum format; + int num_buffers; + int rate; + int queue; + + uint8_t tmpbuf[BUFSIZE]; + int tmpbuf_ptr; + + ALCdevice *handle; + ALCcontext *ctx; + + bool nonblock; + +} al_t; + +static void* __al_init(const char* device, int rate, int latency) +{ + (void)device; + al_t *al = calloc(1, sizeof(rsd_t)); + if ( al == NULL ) + return NULL; + + al->handle = alcOpenDevice(NULL); + if (al->handle == NULL) + goto error; + + al->ctx = alcCreateContext(al->handle, NULL); + if (al->ctx == NULL) + goto error; + + alcMakeContextCurrent(al->ctx); + + al->rate = rate; + + al->num_buffers = (latency * rate * 2 * 2) / (1000 * BUFSIZE); + al->buffers = calloc(al->num_buffers, sizeof(ALuint)); + al->res_buf = calloc(al->num_buffers, sizeof(ALuint)); + if (al->buffers == NULL || al->res_buf == NULL) + goto error; + + alGetSources(1, &al->source); + alGenBuffers(al->num_buffers, al->buffers); + + return al; + +error: + if (al) + { + alcMakeContextCurrent(NULL); + if (al->ctx) + alcDestroyContext(al->ctx); + if (al->handle) + alcCloseDevice(al->handle); + if (al->buffers) + free(al->buffers); + if (al->res_buf) + free(al->res_buf); + free(al); + } + return NULL; +} + +static bool al_unqueue_buffers(al_t *al) +{ + ALint val; + + alGetSourcei(al->source, AL_BUFFERS_PROCESSED, &val); + + if (val > 0) + { + alSourceUnqueueBuffers(al->source, val, &al->res_buf[al->res_ptr]); + al->res_ptr += val; + return true; + } + + return false; +} + +static bool al_get_buffer(al_t *al, ALuint *buffer) +{ + if (al->res_ptr == 0) + { +#ifndef _WIN32 + struct timespec tv = { + .tv_sec = 0, + .tv_nsec = 1000000 + }; +#endif + + for(;;) + { + if (al_unqueue_buffers(al)) + break; + + if (al->nonblocking) + return false; + +#ifdef _WIN32 + Sleep(1); +#else + nanosleep(&tv, NULL); +#endif + } + } + + *buffer = al->res_buf[--al->res_ptr]; + return true; +} + +static size_t al_fill_internal_buf(al_t *al, const void* buf, size_t size) +{ + size_t read_size = (BUFSIZE - al->tmpbuf_ptr > size) ? size : (BUFSIZE - al->tmpbuf_ptr); + memcpy(al->tmpbuf + al->tmpbuf_ptr, buf, read_size); + al->tmpbuf_ptr += read_size; + return read_size; +} + +static ssize_t __al_write(void* data, const void* buf, size_t size) +{ + al_t *al = data; + + size_t written = 0; + while (written < size) + { + size_t rc = al_fill_internal_buf(al, (const char*)buf + written, size - written); + written += rc; + + if (al->tmpbuf_ptr != BUFSIZE) + break; + + if (al->queue < al->num_buffers) + { + alBufferData(al->buffers[al->queue++], AL_FORMAT_STEREO16, al->tmpbuf, BUFSIZE, al->rate); + al->tmpbuf_ptr = 0; + if ( alGetError() != AL_NO_ERROR ) + { + return -1; + } + + if ( al->queue == al->num_buffers ) + { + alSourceQueueBuffers(al->source, al->num_buffers, al->buffers); + alSourcePlay(al->source); + if ( alGetError() != AL_NO_ERROR ) + { + return -1; + } + } + } + else + { + ALuint buffer; + if (!al_get_buffer(al, &buffer)) + return 0; + + alBufferData(buffer, AL_FORMAT_STEREO16, al->tmpbuf, BUFSIZE, al->rate); + al->tmpbuf_ptr = 0; + alSourceQueueBuffers(al->source, 1, &buffer); + if (alGetError() != AL_NO_ERROR) + return -1; + + ALint val; + alGetSourcei(al->source, AL_SOURCE_STATE, &val); + if (val != AL_PLAYING) + alSourcePlay(al->source); + + if (alGetError() != AL_NO_ERROR) + return -1; + } + } + + return size; +} + +static bool __al_stop(void *data) +{ + (void)data; + return true; +} + +static void __al_set_nonblock_state(void *data, bool state) +{ + al_t *al = data; + al->nonblock = state; +} + +static bool __al_start(void *data) +{ + (void)data; + return true; +} + +static void __al_free(void *data) +{ + al_t *al= data; + if (al) + { + alSourceStop(al->source); + alDeleteSources(1, &al->source); + if ( al->buffers ) + { + alDeleteBuffers(al->num_buffers, al->buffers); + free(al->buffers); + free(al->res_buf); + } + } + free(al); +} + +const audio_driver_t audio_openal = { + .init = __al_init, + .write = __al_write, + .stop = __al_stop, + .start = __al_start, + .set_nonblock_state = __al_set_nonblock_state, + .free = __al_free +}; + + From fbd8dc6314c077dc6a4f5b35c41eaecc3a2136ce Mon Sep 17 00:00:00 2001 From: Themaister Date: Wed, 25 Aug 2010 22:40:43 +0200 Subject: [PATCH 3/6] Makefile stuff. --- Makefile | 4 ++++ config.h | 3 ++- config.mk | 3 ++- openal.c | 1 + ssnes.c | 2 ++ 5 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index f72c17c173..3121f2c2b7 100644 --- a/Makefile +++ b/Makefile @@ -20,6 +20,10 @@ ifeq ($(BUILD_ROAR), 1) OBJ += roar.o LIBS += -lroar endif +ifeq ($(BUILD_AL), 1) + OBJ += openal.o + LIBS += -lopenal +endif ifeq ($(BUILD_OPENGL), 1) OBJ += gl.o diff --git a/config.h b/config.h index 14e50760c4..dc2a16aa8d 100644 --- a/config.h +++ b/config.h @@ -36,11 +36,12 @@ #define AUDIO_OSS 2 #define AUDIO_ALSA 3 #define AUDIO_ROAR 4 +#define AUDIO_AL 5 //////////////////////// // Chooses which video and audio subsystem to use. Remember to update config.mk if you change these. #define VIDEO_DRIVER VIDEO_GL -#define AUDIO_DRIVER AUDIO_ALSA +#define AUDIO_DRIVER AUDIO_AL //////////////// diff --git a/config.mk b/config.mk index fbce73ec6a..f0dd8700ee 100644 --- a/config.mk +++ b/config.mk @@ -4,8 +4,9 @@ BUILD_FILTER = 0 BUILD_RSOUND = 0 BUILD_OSS = 0 -BUILD_ALSA = 1 +BUILD_ALSA = 0 BUILD_ROAR = 0 +BUILD_AL = 1 PREFIX = /usr/local diff --git a/openal.c b/openal.c index 8432084c18..05582dd2f0 100644 --- a/openal.c +++ b/openal.c @@ -19,6 +19,7 @@ #include "driver.h" #include #include +#include #define BUFSIZE 128 diff --git a/ssnes.c b/ssnes.c index a7d02ca3fa..1e9e840b71 100644 --- a/ssnes.c +++ b/ssnes.c @@ -57,6 +57,8 @@ static driver_t driver = { .audio = &audio_alsa, #elif AUDIO_DRIVER == AUDIO_ROAR .audio = &audio_roar, +#elif AUDIO_DRIVER == AUDIO_AL + .audio = &audio_openal, #else #error "Define a valid audio driver in config.h" #endif From cb6ea2a26f91fe1384bdee6f3223ccddb5b73218 Mon Sep 17 00:00:00 2001 From: Themaister Date: Wed, 25 Aug 2010 22:42:09 +0200 Subject: [PATCH 4/6] It compiles ... --- openal.c | 9 +++++---- ssnes.c | 1 + 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/openal.c b/openal.c index 05582dd2f0..207670873d 100644 --- a/openal.c +++ b/openal.c @@ -19,7 +19,8 @@ #include "driver.h" #include #include -#include +#include +#include #define BUFSIZE 128 @@ -47,7 +48,7 @@ typedef struct al static void* __al_init(const char* device, int rate, int latency) { (void)device; - al_t *al = calloc(1, sizeof(rsd_t)); + al_t *al = calloc(1, sizeof(al_t)); if ( al == NULL ) return NULL; @@ -69,7 +70,7 @@ static void* __al_init(const char* device, int rate, int latency) if (al->buffers == NULL || al->res_buf == NULL) goto error; - alGetSources(1, &al->source); + alGenSources(1, &al->source); alGenBuffers(al->num_buffers, al->buffers); return al; @@ -123,7 +124,7 @@ static bool al_get_buffer(al_t *al, ALuint *buffer) if (al_unqueue_buffers(al)) break; - if (al->nonblocking) + if (al->nonblock) return false; #ifdef _WIN32 diff --git a/ssnes.c b/ssnes.c index 1e9e840b71..5c8bb16135 100644 --- a/ssnes.c +++ b/ssnes.c @@ -39,6 +39,7 @@ extern const audio_driver_t audio_rsound; extern const audio_driver_t audio_oss; extern const audio_driver_t audio_alsa; extern const audio_driver_t audio_roar; +extern const audio_driver_t audio_openal; extern const video_driver_t video_gl; //////////////////////////////////////////////// From 83fb1390fa0072ceea8845f1769b25c3c984b855 Mon Sep 17 00:00:00 2001 From: Themaister Date: Wed, 25 Aug 2010 22:53:52 +0200 Subject: [PATCH 5/6] Some fixes. --- openal.c | 53 +++++++++++++++++------------------------------------ 1 file changed, 17 insertions(+), 36 deletions(-) diff --git a/openal.c b/openal.c index 207670873d..e704747bbd 100644 --- a/openal.c +++ b/openal.c @@ -73,6 +73,9 @@ static void* __al_init(const char* device, int rate, int latency) alGenSources(1, &al->source); alGenBuffers(al->num_buffers, al->buffers); + memcpy(al->res_buf, al->buffers, al->num_buffers * sizeof(ALuint)); + al->res_ptr = al->num_buffers; + return al; error: @@ -160,45 +163,23 @@ static ssize_t __al_write(void* data, const void* buf, size_t size) if (al->tmpbuf_ptr != BUFSIZE) break; - if (al->queue < al->num_buffers) - { - alBufferData(al->buffers[al->queue++], AL_FORMAT_STEREO16, al->tmpbuf, BUFSIZE, al->rate); - al->tmpbuf_ptr = 0; - if ( alGetError() != AL_NO_ERROR ) - { - return -1; - } + ALuint buffer; + if (!al_get_buffer(al, &buffer)) + return 0; - if ( al->queue == al->num_buffers ) - { - alSourceQueueBuffers(al->source, al->num_buffers, al->buffers); - alSourcePlay(al->source); - if ( alGetError() != AL_NO_ERROR ) - { - return -1; - } - } - } - else - { - ALuint buffer; - if (!al_get_buffer(al, &buffer)) - return 0; + alBufferData(buffer, AL_FORMAT_STEREO16, al->tmpbuf, BUFSIZE, al->rate); + al->tmpbuf_ptr = 0; + alSourceQueueBuffers(al->source, 1, &buffer); + if (alGetError() != AL_NO_ERROR) + return -1; - alBufferData(buffer, AL_FORMAT_STEREO16, al->tmpbuf, BUFSIZE, al->rate); - al->tmpbuf_ptr = 0; - alSourceQueueBuffers(al->source, 1, &buffer); - if (alGetError() != AL_NO_ERROR) - return -1; + ALint val; + alGetSourcei(al->source, AL_SOURCE_STATE, &val); + if (val != AL_PLAYING) + alSourcePlay(al->source); - ALint val; - alGetSourcei(al->source, AL_SOURCE_STATE, &val); - if (val != AL_PLAYING) - alSourcePlay(al->source); - - if (alGetError() != AL_NO_ERROR) - return -1; - } + if (alGetError() != AL_NO_ERROR) + return -1; } return size; From d56e3ec89f83dbb8f22b7c6ae4addf01f192c01a Mon Sep 17 00:00:00 2001 From: Themaister Date: Wed, 25 Aug 2010 22:54:25 +0200 Subject: [PATCH 6/6] tihi --- config.h | 2 +- config.mk | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/config.h b/config.h index dc2a16aa8d..92066ad7e1 100644 --- a/config.h +++ b/config.h @@ -41,7 +41,7 @@ // Chooses which video and audio subsystem to use. Remember to update config.mk if you change these. #define VIDEO_DRIVER VIDEO_GL -#define AUDIO_DRIVER AUDIO_AL +#define AUDIO_DRIVER AUDIO_ALSA //////////////// diff --git a/config.mk b/config.mk index f0dd8700ee..4a8dae50e4 100644 --- a/config.mk +++ b/config.mk @@ -4,9 +4,9 @@ BUILD_FILTER = 0 BUILD_RSOUND = 0 BUILD_OSS = 0 -BUILD_ALSA = 0 +BUILD_ALSA = 1 BUILD_ROAR = 0 -BUILD_AL = 1 +BUILD_AL = 0 PREFIX = /usr/local