X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=sndout_sdl.c;fp=sndout_sdl.c;h=83b3ea2e3a7c195d4f32b2364489a3e5bcc03d17;hb=26d3ca0d29e87a14943d29fcafc93da753df60cd;hp=0000000000000000000000000000000000000000;hpb=20b143089cc395dbcd51cac516a9e36f4ab6f5ac;p=libpicofe.git diff --git a/sndout_sdl.c b/sndout_sdl.c new file mode 100644 index 0000000..83b3ea2 --- /dev/null +++ b/sndout_sdl.c @@ -0,0 +1,151 @@ +/* + * (C) notaz, 2013 + * + * This work is licensed under the terms of any of these licenses + * (at your option): + * - GNU GPL, version 2 or later. + * - GNU LGPL, version 2.1 or later. + * - MAME license. + * See the COPYING file in the top-level directory. + */ + +#include +#include "sndout_sdl.h" + +// ~1/3s at 44kHz +// set this to power of 2 +#define BUF_LEN 32768 +#define BUF_MASK (BUF_LEN - 1) + +static short buf[BUF_LEN]; +static int buf_w, buf_r; +static int started; + +static void callback(void *userdata, Uint8 *stream, int len) +{ + int have = (buf_w - buf_r) & BUF_MASK; + int buf_left = BUF_LEN - buf_r; + + len /= 2; + if (have > len) + have = len; + if (have > 0) { + if (have > buf_left) { + memcpy(stream, buf + buf_r, buf_left * 2); + stream += buf_left * 2; + buf_r = 0; + have -= buf_left; + len -= buf_left; + } + memcpy(stream, buf + buf_r, have * 2); + stream += have * 2; + buf_r = (buf_r + have) & BUF_MASK; + len -= have; + } + + if (len > 0) { + // put in some silence.. + memset(stream, 0, len * 2); + } +} + +int sndout_sdl_init(void) +{ + int ret; + + ret = SDL_InitSubSystem(SDL_INIT_AUDIO); + if (ret != 0) + return -1; + + return 0; +} + +int sndout_sdl_start(int rate, int stereo) +{ + SDL_AudioSpec desired; + int samples, shift; + int ret; + + if (started) + sndout_sdl_stop(); + + desired.freq = rate; + desired.format = AUDIO_S16LSB; + desired.channels = stereo ? 2 : 1; + desired.callback = callback; + desired.userdata = NULL; + + samples = rate * 4 * 16 / 1000; + for (shift = 8; (1 << shift) < samples; shift++) + ; + desired.samples = 1 << shift; + + ret = SDL_OpenAudio(&desired, NULL); + if (ret != 0) { + fprintf(stderr, "SDL_OpenAudio: %s\n", SDL_GetError()); + return -1; + } + + buf_w = buf_r = 0; + + SDL_PauseAudio(0); + started = 1; + + return 0; +} + +void sndout_sdl_stop(void) +{ + SDL_PauseAudio(1); + SDL_CloseAudio(); + started = 0; +} + +void sndout_sdl_wait(void) +{ + int left; + + while (1) + { + left = (buf_r - buf_w - 2) & BUF_MASK; + if (left >= BUF_LEN / 2) + break; + + SDL_Delay(4); + } +} + +int sndout_sdl_write_nb(const void *samples, int len) +{ + int maxlen = (buf_r - buf_w - 2) & BUF_MASK; + int buf_left = BUF_LEN - buf_w; + int retval; + + len /= 2; + if (len > maxlen) + // not enough space + len = maxlen; + if (len == 0) + // totally full + return 0; + + retval = len; + + if (len > buf_left) { + memcpy(buf + buf_w, samples, buf_left * 2); + samples = (const short *)samples + buf_left; + len -= buf_left; + buf_w = 0; + } + memcpy(buf + buf_w, samples, len * 2); + buf_w = (buf_w + len) & BUF_MASK; + + return retval; +} + +void sndout_sdl_exit(void) +{ + if (started) + sndout_sdl_stop(); + SDL_QuitSubSystem(SDL_INIT_AUDIO); +}