aboutsummaryrefslogtreecommitdiffstats
path: root/WinQuake/snd_sdl.c
diff options
context:
space:
mode:
authorwyatt8740 <wyattfward@gmail.com>2021-01-19 14:40:32 -0500
committerwyatt8740 <wyattfward@gmail.com>2021-01-19 14:40:32 -0500
commit6f34ea985bc389605b9e03645ab258259ba49c81 (patch)
tree98874957c6baaae857ed8ce70e0c624c1f8ba50c /WinQuake/snd_sdl.c
parent9b671e8d4380c6cdf4b70fbf954e29481b9fdf85 (diff)
downloadquake-pum-6f34ea985bc389605b9e03645ab258259ba49c81.tar.gz
SDL2 audio backend, retrofitted from quakespasm (Music still requires either a CD drive with analogue audio playback or CD drive emulator software like cdemu, but SFX no longer require OSS DMA for playback and Quake no longer inherently prevents other software from making sound while running)
Diffstat (limited to 'WinQuake/snd_sdl.c')
-rw-r--r--WinQuake/snd_sdl.c213
1 files changed, 213 insertions, 0 deletions
diff --git a/WinQuake/snd_sdl.c b/WinQuake/snd_sdl.c
new file mode 100644
index 0000000..326621a
--- /dev/null
+++ b/WinQuake/snd_sdl.c
@@ -0,0 +1,213 @@
+/*
+ * snd_sdl.c - SDL audio driver for Hexen II: Hammer of Thyrion (uHexen2)
+ * based on implementations found in the quakeforge and ioquake3 projects.
+ *
+ * Copyright (C) 1999-2005 Id Software, Inc.
+ * Copyright (C) 2005-2012 O.Sezer <sezero@users.sourceforge.net>
+ * Copyright (C) 2010-2014 QuakeSpasm developers
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "quakedef.h"
+
+#if defined(SDL_FRAMEWORK) || defined(NO_SDL_CONFIG)
+#if defined(USE_SDL2)
+#include <SDL2/SDL.h>
+#else
+#include <SDL/SDL.h>
+#endif
+#else
+#include "SDL.h"
+#endif
+
+static int buffersize;
+
+
+static void SDLCALL paint_audio (void *unused, Uint8 *stream, int len)
+{
+ int pos, tobufend;
+ int len1, len2;
+
+ if (!shm)
+ { /* shouldn't happen, but just in case */
+ memset(stream, 0, len);
+ return;
+ }
+
+ pos = (shm->samplepos * (shm->samplebits / 8));
+ if (pos >= buffersize)
+ shm->samplepos = pos = 0;
+
+ tobufend = buffersize - pos; /* bytes to buffer's end. */
+ len1 = len;
+ len2 = 0;
+
+ if (len1 > tobufend)
+ {
+ len1 = tobufend;
+ len2 = len - len1;
+ }
+
+ memcpy(stream, shm->buffer + pos, len1);
+
+ if (len2 <= 0)
+ {
+ shm->samplepos += (len1 / (shm->samplebits / 8));
+ }
+ else
+ { /* wraparound? */
+ memcpy(stream + len1, shm->buffer, len2);
+ shm->samplepos = (len2 / (shm->samplebits / 8));
+ }
+
+ if (shm->samplepos >= buffersize)
+ shm->samplepos = 0;
+}
+
+qboolean SNDDMA_Init (dma_t *dma)
+{
+ SDL_AudioSpec desired;
+ int tmp, val;
+ char drivername[128];
+
+ if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
+ {
+ Con_Printf("Couldn't init SDL audio: %s\n", SDL_GetError());
+ return false;
+ }
+
+ /* Set up the desired format */
+/* desired.freq = snd_mixspeed.value;*/
+ desired.freq = 44100;
+ desired.format = (loadas8bit.value) ? AUDIO_U8 : AUDIO_S16SYS;
+ desired.channels = 2; /* = desired_channels; */
+ if (desired.freq <= 11025)
+ desired.samples = 256;
+ else if (desired.freq <= 22050)
+ desired.samples = 512;
+ else if (desired.freq <= 44100)
+ desired.samples = 1024;
+ else if (desired.freq <= 56000)
+ desired.samples = 2048; /* for 48 kHz */
+ else
+ desired.samples = 4096; /* for 96 kHz */
+ desired.callback = paint_audio;
+ desired.userdata = NULL;
+
+ /* Open the audio device */
+ if (SDL_OpenAudio(&desired, NULL) == -1)
+ {
+ Con_Printf("Couldn't open SDL audio: %s\n", SDL_GetError());
+ SDL_QuitSubSystem(SDL_INIT_AUDIO);
+ return false;
+ }
+
+ memset ((void *) dma, 0, sizeof(dma_t));
+ shm = dma;
+
+ /* Fill the audio DMA information block */
+ /* Since we passed NULL as the 'obtained' spec to SDL_OpenAudio(),
+ * SDL will convert to hardware format for us if needed, hence we
+ * directly use the desired values here. */
+ shm->samplebits = (desired.format & 0xFF); /* first byte of format is bits */
+/* shm->signed8 = (desired.format == AUDIO_S8);*/
+ shm->speed = desired.freq;
+ shm->channels = desired.channels;
+ tmp = (desired.samples * desired.channels) * 10;
+ if (tmp & (tmp - 1))
+ { /* make it a power of two */
+ val = 1;
+ while (val < tmp)
+ val <<= 1;
+
+ tmp = val;
+ }
+ shm->samples = tmp;
+ shm->samplepos = 0;
+ shm->submission_chunk = 1;
+
+ Con_Printf ("SDL audio spec : %d Hz, %d samples, %d channels\n",
+ desired.freq, desired.samples, desired.channels);
+#if defined(USE_SDL2)
+ {
+ const char *driver = SDL_GetCurrentAudioDriver();
+ const char *device = SDL_GetAudioDeviceName(0, SDL_FALSE);
+ snprintf(drivername, sizeof(drivername), "%s - %s",
+ driver != NULL ? driver : "(UNKNOWN)",
+ device != NULL ? device : "(UNKNOWN)");
+ }
+#else
+ if (SDL_AudioDriverName(drivername, sizeof(drivername)) == NULL)
+ strcpy(drivername, "(UNKNOWN)");
+#endif
+ buffersize = shm->samples * (shm->samplebits / 8);
+ Con_Printf ("SDL audio driver: %s, %d bytes buffer\n", drivername, buffersize);
+
+ shm->buffer = (unsigned char *) calloc (1, buffersize);
+ if (!shm->buffer)
+ {
+ SDL_CloseAudio();
+ SDL_QuitSubSystem(SDL_INIT_AUDIO);
+ shm = NULL;
+ Con_Printf ("Failed allocating memory for SDL audio\n");
+ return false;
+ }
+
+ SDL_PauseAudio(0);
+
+ return true;
+}
+
+int SNDDMA_GetDMAPos (void)
+{
+ return shm->samplepos;
+}
+
+void SNDDMA_Shutdown (void)
+{
+ if (shm)
+ {
+ Con_Printf ("Shutting down SDL sound\n");
+ SDL_CloseAudio();
+ SDL_QuitSubSystem(SDL_INIT_AUDIO);
+ if (shm->buffer)
+ free (shm->buffer);
+ shm->buffer = NULL;
+ shm = NULL;
+ }
+}
+
+void SNDDMA_LockBuffer (void)
+{
+ SDL_LockAudio ();
+}
+
+void SNDDMA_Submit (void)
+{
+ SDL_UnlockAudio();
+}
+
+void SNDDMA_BlockSound (void)
+{
+ SDL_PauseAudio(1);
+}
+
+void SNDDMA_UnblockSound (void)
+{
+ SDL_PauseAudio(0);
+}
+