This is soundsdl.c in view mode; [Download] [Up]
/* * soundsdl.c - Implementation of the Simple Directmedia Layer sound device * * Written by * Teemu Rantanen (tvr@cs.hut.fi) * * This file is part of VICE, the Versatile Commodore Emulator. * See README for copyright notice. * * This program 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 Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. * */ /* XXX: includes */ #include "SDL_audio.h" #include "SDL_sleep.h" #include "vice.h" #include "sound.h" static SWORD *sdl_buf = NULL; static const SDL_AudioSpec *sdl_spec = NULL; static volatile int sdl_inptr = 0; static volatile int sdl_outptr = 0; static volatile int sdl_len = 0; static void sdl_callback(void *userdata, Uint8 *stream, Uint16 len, Uint8 *lookahead) { int amount, total; total = 0; while (total < len/sizeof(SWORD)) { amount = sdl_inptr - sdl_outptr; if (amount < 0) amount = sdl_len - sdl_outptr; if (amount + total > len/sizeof(SWORD)) amount = len/sizeof(SWORD) - total; if (!amount) { if (!sdl_spec) { memset(stream + total*sizeof(SWORD), 0, len - total*sizeof(SWORD)); return; } Sleep(5); continue; } memcpy(stream + total*sizeof(SWORD), sdl_buf + sdl_outptr, amount*sizeof(SWORD)); total += amount; sdl_outptr += amount; if (sdl_outptr == sdl_len) sdl_outptr = 0; } } static int sdl_init(warn_t *w, char *param, int *speed, int *fragsize, int *fragnr, double bufsize) { SDL_AudioSpec spec; memset(&spec, 0, sizeof(spec)); spec.freq = *speed; spec.format = AUDIO_S16 | AUDIO_MONO; spec.samples = *fragsize; spec.callback = sdl_callback; sdl_spec = SDL_OpenAudio(&spec); if (!sdl_spec) return 1; if (sdl_spec->format != (AUDIO_S16 | AUDIO_MONO)) { sdl_spec = NULL; SDL_CloseAudio(); return 1; } sdl_len = (*fragsize)*(*fragnr) + 1; sdl_inptr = sdl_outptr = 0; sdl_buf = xmalloc(sizeof(SWORD)*sdl_len); if (!sdl_buf) { SDL_CloseAudio(); return 1; } *speed = sdl_spec->freq; SDL_PauseAudio(0); return 0; } static int sdl_write(warn_t *s, SWORD *pbuf, int nr) { int total, amount; total = 0; while (total < nr) { amount = sdl_outptr - sdl_inptr; if (amount <= 0) amount = sdl_len - sdl_inptr; if ((sdl_inptr + amount)%sdl_len == sdl_outptr) amount--; if (amount <= 0) { Sleep(5); continue; } if (total + amount > nr) amount = nr - total; memcpy(sdl_buf + sdl_inptr, pbuf + total, amount*sizeof(SWORD)); sdl_inptr += amount; total += amount; if (sdl_inptr == sdl_len) sdl_inptr = 0; } return 0; } static int sdl_bufferstatus(warn_t *s, int first) { int amount; amount = sdl_inptr - sdl_outptr; if (amount < 0) amount += sdl_len; return amount; } static void sdl_close(warn_t *w) { sdl_spec = NULL; SDL_CloseAudio(); free(sdl_buf); sdl_buf = NULL; sdl_inptr = sdl_outptr = sdl_len = 0; } static sound_device_t sdl_device = { "sdl", sdl_init, sdl_write, NULL, NULL, sdl_bufferstatus, sdl_close, NULL, NULL }; int sound_init_sdl_device(void) { return sound_register_device(&sdl_device); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.