From 1ba6d3c95eb53beed44897b2fcdb846df7e2feef Mon Sep 17 00:00:00 2001 From: icculus Date: Wed, 31 Aug 2005 19:42:55 +0000 Subject: SDL-based audio. git-svn-id: svn://svn.icculus.org/quake3/trunk@51 edf5b092-35ff-0310-97b2-ce42778d08ea --- code/unix/Makefile | 6 ++ code/unix/linux_snd.c | 6 ++ code/unix/linux_snd_sdl.c | 245 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 257 insertions(+) create mode 100644 code/unix/linux_snd_sdl.c (limited to 'code/unix') diff --git a/code/unix/Makefile b/code/unix/Makefile index acee11a..0710b76 100644 --- a/code/unix/Makefile +++ b/code/unix/Makefile @@ -566,6 +566,7 @@ ifeq ($(PLATFORM),freebsd) $(B)/client/linux_glimp_sdl.o \ $(B)/client/linux_glimp.o \ $(B)/client/linux_snd.o \ + $(B)/client/linux_snd_sdl.o \ $(B)/client/snd_mixa.o \ $(B)/client/matha.o \ $(B)/client/ftol.o \ @@ -589,6 +590,7 @@ else $(B)/client/linux_glimp_sdl.o \ $(B)/client/linux_joystick.o \ $(B)/client/linux_snd.o \ + $(B)/client/linux_snd_sdl.o \ $(B)/client/snd_mixa.o \ $(B)/client/matha.o \ @@ -599,6 +601,7 @@ else $(B)/client/linux_glimp_smp.o \ $(B)/client/linux_joystick.o \ $(B)/client/linux_snd.o \ + $(B)/client/linux_snd_sdl.o \ $(B)/client/snd_mixa.o \ $(B)/client/matha.o @@ -770,6 +773,7 @@ $(B)/client/linux_joystick.o : $(UDIR)/linux_joystick.c; $(DO_CC) $(B)/client/linux_qgl.o : $(UDIR)/linux_qgl.c; $(DO_CC) $(GL_CFLAGS) $(B)/client/linux_input.o : $(UDIR)/linux_input.c; $(DO_CC) $(B)/client/linux_snd.o : $(UDIR)/linux_snd.c; $(DO_CC) +$(B)/client/linux_snd_sdl.o : $(UDIR)/linux_snd_sdl.c; $(DO_CC) $(B)/client/snd_mixa.o : $(UDIR)/snd_mixa.s; $(DO_AS) $(B)/client/matha.o : $(UDIR)/matha.s; $(DO_AS) @@ -1578,6 +1582,7 @@ Q3SOBJ = \ $(B)/q3static/linux_glimp.o \ $(B)/q3static/linux_joystick.o \ $(B)/q3static/linux_snd.o \ + $(B)/q3static/linux_snd_sdl.o \ $(B)/q3static/snd_mixa.o \ $(B)/q3static/matha.o @@ -1735,6 +1740,7 @@ $(B)/q3static/linux_joystick.o : $(UDIR)/linux_joystick.c; $(DO_CC) -DQ3_STATIC $(B)/q3static/linux_qgl.o : $(UDIR)/linux_qgl.c; $(DO_CC) -DQ3_STATIC $(B)/q3static/linux_input.o : $(UDIR)/linux_input.c; $(DO_CC) -DQ3_STATIC $(B)/q3static/linux_snd.o : $(UDIR)/linux_snd.c; $(DO_CC) -DQ3_STATIC +$(B)/q3static/linux_snd_sdl.o : $(UDIR)/linux_snd_sdl.c; $(DO_CC) -DQ3_STATIC $(B)/q3static/snd_mixa.o : $(UDIR)/snd_mixa.s; $(DO_AS) $(B)/q3static/matha.o : $(UDIR)/matha.s; $(DO_AS) $(B)/q3static/unzip.o : $(CMDIR)/unzip.c; $(DO_CC) -DQ3_STATIC diff --git a/code/unix/linux_snd.c b/code/unix/linux_snd.c index 0c63628..6c589bc 100644 --- a/code/unix/linux_snd.c +++ b/code/unix/linux_snd.c @@ -19,6 +19,9 @@ along with Foobar; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ + +#if !USE_SDL + #include #include #include @@ -291,3 +294,6 @@ void SNDDMA_Submit(void) void SNDDMA_BeginPainting (void) { } + +#endif // !USE_SDL + diff --git a/code/unix/linux_snd_sdl.c b/code/unix/linux_snd_sdl.c new file mode 100644 index 0000000..66e32bc --- /dev/null +++ b/code/unix/linux_snd_sdl.c @@ -0,0 +1,245 @@ +#if USE_SDL + +/* + * SDL implementation for Quake 3: Arena's GPL source release. + * + * This is a replacement of the Linux/OpenSoundSystem code with + * an SDL backend, since it allows us to trivially point just about any + * existing 2D audio backend known to man on any platform at the code, + * plus it benefits from all of SDL's tapdancing to support buggy drivers, + * etc, and gets us free ALSA support, too. + * + * This is the best idea for a direct modernization of the Linux sound code + * in Quake 3. However, it would be nice to replace this with true 3D + * positional audio, compliments of OpenAL... + * + * Written by Ryan C. Gordon (icculus@icculus.org). Please refer to + * http://icculus.org/quake3/ for the latest version of this code. + * + * Patches and comments are welcome at the above address. + * + * I cut-and-pasted this from linux_snd.c, and moved it to SDL line-by-line. + * There is probably some cruft that could be removed here. + * + * You should define USE_SDL=1 and then add this to the makefile. + * USE_SDL will disable the Open Sound System target. + * + * !!! FIXME: linux_snd_sdl.c isn't really "linux" specific. + */ + +/* +Original copyright on Q3A sources: +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. + +This file is part of Quake III Arena source code. + +Quake III Arena source code 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. + +Quake III Arena source code 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 Foobar; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include +#include + +#include "SDL.h" + +#include "../game/q_shared.h" +#include "../client/snd_local.h" + +int snd_inited=0; + +cvar_t *sndbits; +cvar_t *sndspeed; +cvar_t *sndchannels; +cvar_t *snddevice; + +static qboolean use_custom_memset = qfalse; +// https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=371 +void Snd_Memset (void* dest, const int val, const size_t count) +{ + int *pDest; + int i, iterate; + + if (!use_custom_memset) + { + Com_Memset(dest,val,count); + return; + } + iterate = count / sizeof(int); + pDest = (int*)dest; + for(i=0; i= dmasize) + dmapos = pos = 0; + + if (!snd_inited) /* shouldn't happen, but just in case... */ + { + memset(stream, '\0', len); + return; + } + else + { + int tobufend = dmasize - pos; /* bytes to buffer's end. */ + int len1 = len; + int len2 = 0; + + if (len1 > tobufend) + { + len1 = tobufend; + len2 = len - len1; + } + memcpy(stream, dma.buffer + pos, len1); + if (len2 <= 0) + dmapos += (len1 / (dma.samplebits/8)); + else /* wraparound? */ + { + memcpy(stream+len1, dma.buffer, len2); + dmapos = (len2 / (dma.samplebits/8)); + } + } + + if (dmapos >= dmasize) + dmapos = 0; +} + +qboolean SNDDMA_Init(void) +{ + char drivername[128]; + SDL_AudioSpec desired; + SDL_AudioSpec obtained; + int tmp; + + if (snd_inited) + return 1; + + if (!snddevice) { + sndbits = Cvar_Get("sndbits", "16", CVAR_ARCHIVE); + sndspeed = Cvar_Get("sndspeed", "22050", CVAR_ARCHIVE); + sndchannels = Cvar_Get("sndchannels", "2", CVAR_ARCHIVE); + snddevice = Cvar_Get("snddevice", "/dev/dsp", CVAR_ARCHIVE); + } + + if (!SDL_WasInit(SDL_INIT_AUDIO)) + { + Com_Printf( PRINT_ALL, "Calling SDL_Init(SDL_INIT_AUDIO)...\n"); + if (SDL_Init(SDL_INIT_AUDIO) == -1) + { + Com_Printf( PRINT_ALL, "SDL_Init(SDL_INIT_AUDIO) failed: %s\n", SDL_GetError()); + return qfalse; + } + Com_Printf( PRINT_ALL, "SDL_Init(SDL_INIT_AUDIO) passed.\n"); + } + + if (SDL_AudioDriverName(drivername, sizeof (drivername)) == NULL) + strcpy(drivername, "(UNKNOWN)"); + Com_Printf("SDL audio driver is \"%s\"\n", drivername); + + memset(&desired, '\0', sizeof (desired)); + memset(&obtained, '\0', sizeof (obtained)); + + tmp = ((int) sndbits->value); + if ((tmp != 16) && (tmp != 8)) + tmp = 16; + + desired.freq = (int) sndspeed->value; + desired.format = ((tmp == 16) ? AUDIO_S16SYS : AUDIO_U8); + + // I dunno if this is the best idea, but I'll give it a try... + // should probably check a cvar for this... + if (desired.freq <= 11025) + desired.samples = 512; + else if (desired.freq <= 22050) + desired.samples = 1024; + else if (desired.freq <= 44100) + desired.samples = 2048; + else + desired.samples = 4096; // (*shrug*) + + desired.channels = (int) sndchannels->value; + desired.callback = sdl_audio_callback; + + if (SDL_OpenAudio(&desired, &obtained) == -1) + { + Com_Printf("SDL_OpenAudio() failed: %s\n", SDL_GetError()); + SDL_QuitSubSystem(SDL_INIT_AUDIO); + return qfalse; + } // if + + dmapos = 0; + dma.samplebits = obtained.format & 0xFF; // first byte of format is bits. + dma.channels = obtained.channels; + dma.samples = 32768; //obtained.samples * obtained.channels; + dma.submission_chunk = 1; + dma.speed = obtained.freq; + dmasize = (dma.samples * (dma.samplebits/8)); + dma.buffer = calloc(1, dmasize); + + Com_Printf("Starting SDL audio callback...\n"); + SDL_PauseAudio(0); // start callback. + + Com_Printf("SDL audio initialized.\n"); + snd_inited = 1; + return qtrue; +} + +int SNDDMA_GetDMAPos(void) +{ + return dmapos; +} + +void SNDDMA_Shutdown(void) +{ + Com_Printf("Closing SDL audio device...\n"); + SDL_PauseAudio(1); + SDL_CloseAudio(); + SDL_QuitSubSystem(SDL_INIT_AUDIO); + free(dma.buffer); + dma.buffer = NULL; + dmapos = dmasize = 0; + snd_inited = 0; + Com_Printf("SDL audio device shut down.\n"); +} + +/* +============== +SNDDMA_Submit + +Send sound to device if buffer isn't really the dma buffer +=============== +*/ +void SNDDMA_Submit(void) +{ + SDL_UnlockAudio(); +} + +void SNDDMA_BeginPainting (void) +{ + SDL_LockAudio(); +} + +#endif // USE_SDL + +// end of linux_snd_sdl.c ... + -- cgit v1.2.3