aboutsummaryrefslogtreecommitdiffstats
path: root/code/unix
diff options
context:
space:
mode:
authoricculus <icculus@edf5b092-35ff-0310-97b2-ce42778d08ea>2005-08-31 19:42:55 +0000
committericculus <icculus@edf5b092-35ff-0310-97b2-ce42778d08ea>2005-08-31 19:42:55 +0000
commit1ba6d3c95eb53beed44897b2fcdb846df7e2feef (patch)
tree1303c23e454785f37d6107a3712ba288fc3393e5 /code/unix
parent227d86d227c6951ee2bd98388e7960c479c2b2e6 (diff)
downloadioquake3-aero-1ba6d3c95eb53beed44897b2fcdb846df7e2feef.tar.gz
ioquake3-aero-1ba6d3c95eb53beed44897b2fcdb846df7e2feef.zip
SDL-based audio.
git-svn-id: svn://svn.icculus.org/quake3/trunk@51 edf5b092-35ff-0310-97b2-ce42778d08ea
Diffstat (limited to 'code/unix')
-rw-r--r--code/unix/Makefile6
-rw-r--r--code/unix/linux_snd.c6
-rw-r--r--code/unix/linux_snd_sdl.c245
3 files changed, 257 insertions, 0 deletions
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 <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
@@ -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 <stdlib.h>
+#include <stdio.h>
+
+#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<iterate; i++)
+ {
+ pDest[i] = val;
+ }
+}
+
+/* The audio callback. All the magic happens here. */
+static int dmapos = 0;
+static int dmasize = 0;
+static void sdl_audio_callback(void *userdata, Uint8 *stream, int len)
+{
+ int pos = (dmapos * (dma.samplebits/8));
+ if (pos >= 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 ...
+