nkeynes@989: /** nkeynes@1021: * $Id$ nkeynes@989: * nkeynes@989: * The SDL sound driver nkeynes@989: * nkeynes@989: * Copyright (c) 2009 wahrhaft nkeynes@989: * nkeynes@989: * This program is free software; you can redistribute it and/or modify nkeynes@989: * it under the terms of the GNU General Public License as published by nkeynes@989: * the Free Software Foundation; either version 2 of the License, or nkeynes@989: * (at your option) any later version. nkeynes@989: * nkeynes@989: * This program is distributed in the hope that it will be useful, nkeynes@989: * but WITHOUT ANY WARRANTY; without even the implied warranty of nkeynes@989: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the nkeynes@989: * GNU General Public License for more details. nkeynes@989: */ nkeynes@989: #include nkeynes@989: #include nkeynes@989: #include nkeynes@989: #include nkeynes@989: #include "aica/audio.h" nkeynes@989: #include "lxdream.h" nkeynes@989: nkeynes@989: #define SDL_SAMPLES 512 //tweaking this value may help with audio dropouts nkeynes@989: #define BYTES_PER_SAMPLE 4 //should be changed if samples are not S16 stereo nkeynes@989: nkeynes@989: #define BUFFER_MIN_SIZE SDL_SAMPLES * BYTES_PER_SAMPLE * 4 nkeynes@989: #define BUFFER_MAX_SIZE SDL_SAMPLES * BYTES_PER_SAMPLE * 16 nkeynes@989: nkeynes@989: char *audio_buffer; nkeynes@989: int buffer_pos; nkeynes@989: nkeynes@989: void mix_audio(void *userdata, Uint8 *stream, int len); nkeynes@994: void audio_sdl_start(); nkeynes@989: nkeynes@989: gboolean audio_sdl_init( ) nkeynes@989: { nkeynes@989: int rate = DEFAULT_SAMPLE_RATE; nkeynes@989: int format = DEFAULT_SAMPLE_FORMAT; nkeynes@989: nkeynes@989: SDL_AudioSpec fmt; nkeynes@989: fmt.freq = rate; nkeynes@989: if (format & AUDIO_FMT_16BIT) nkeynes@989: fmt.format = AUDIO_S16; nkeynes@989: else nkeynes@989: fmt.format = AUDIO_U8; nkeynes@989: if (format & AUDIO_FMT_STEREO) nkeynes@989: fmt.channels = 2; nkeynes@989: else nkeynes@989: fmt.channels = 1; nkeynes@989: nkeynes@989: fmt.samples = SDL_SAMPLES; nkeynes@989: fmt.callback = mix_audio; nkeynes@989: fmt.userdata = NULL; nkeynes@989: nkeynes@989: if (SDL_OpenAudio(&fmt, NULL) < 0) nkeynes@989: { nkeynes@989: ERROR("Unable to open audio output (SDL)"); nkeynes@989: return FALSE; nkeynes@989: } nkeynes@989: buffer_pos = 0; nkeynes@989: audio_buffer = (char*)malloc(BUFFER_MAX_SIZE * sizeof(char)); nkeynes@989: if (audio_buffer == NULL) nkeynes@989: { nkeynes@989: ERROR("Could not allocate audio buffer (SDL)"); nkeynes@989: return FALSE; nkeynes@989: } nkeynes@989: nkeynes@989: //hmm, this doesn't seem to get called externally... nkeynes@989: audio_sdl_start(); nkeynes@989: nkeynes@989: return TRUE; nkeynes@989: } nkeynes@989: nkeynes@989: gboolean audio_sdl_process_buffer( audio_buffer_t buffer ) nkeynes@989: { nkeynes@989: SDL_LockAudio(); nkeynes@989: if (buffer_pos + buffer->length >= BUFFER_MAX_SIZE) nkeynes@989: { nkeynes@989: printf("Audio buffer full, dropping a chunk\n"); nkeynes@989: } nkeynes@989: else nkeynes@989: { nkeynes@989: memcpy(audio_buffer, buffer->data, buffer->length); nkeynes@989: buffer_pos += buffer->length; nkeynes@989: } nkeynes@989: SDL_UnlockAudio(); nkeynes@989: nkeynes@989: return TRUE; nkeynes@989: } nkeynes@989: nkeynes@989: void mix_audio(void *userdata, Uint8 *stream, int len) nkeynes@989: { nkeynes@989: if (len < buffer_pos) nkeynes@989: { nkeynes@989: memcpy(stream, audio_buffer, len); nkeynes@989: } nkeynes@989: if (buffer_pos > BUFFER_MIN_SIZE) nkeynes@989: { nkeynes@989: memcpy(audio_buffer, &audio_buffer[len], buffer_pos - len); nkeynes@989: buffer_pos -= len; nkeynes@989: } nkeynes@989: else nkeynes@989: { nkeynes@989: //printf("Audio buffer low, repeating a chunk\n"); nkeynes@989: } nkeynes@989: } nkeynes@989: nkeynes@989: gboolean audio_sdl_shutdown() nkeynes@989: { nkeynes@989: SDL_CloseAudio(); nkeynes@989: free(audio_buffer); nkeynes@989: return TRUE; nkeynes@989: } nkeynes@989: nkeynes@989: void audio_sdl_start() nkeynes@989: { nkeynes@989: SDL_PauseAudio(0); nkeynes@989: } nkeynes@989: nkeynes@989: void audio_sdl_stop() nkeynes@989: { nkeynes@989: SDL_PauseAudio(1); nkeynes@989: } nkeynes@989: nkeynes@989: struct audio_driver audio_sdl_driver = { nkeynes@989: "sdl", nkeynes@989: N_("SDL sound driver"), nkeynes@989: DEFAULT_SAMPLE_RATE, nkeynes@989: DEFAULT_SAMPLE_FORMAT, nkeynes@989: audio_sdl_init, nkeynes@989: audio_sdl_start, nkeynes@989: audio_sdl_process_buffer, nkeynes@989: audio_sdl_stop, nkeynes@989: audio_sdl_shutdown nkeynes@989: }; nkeynes@989: