aboutsummaryrefslogtreecommitdiffstats
path: root/code/unix/sdl_snd.c
diff options
context:
space:
mode:
authortma <tma@edf5b092-35ff-0310-97b2-ce42778d08ea>2005-11-13 18:58:14 +0000
committertma <tma@edf5b092-35ff-0310-97b2-ce42778d08ea>2005-11-13 18:58:14 +0000
commit38baaa2274a458f03f576dea5a6d3cd9e25f8063 (patch)
tree64500262c0756817893a96b4d6556e6a31d2ce8f /code/unix/sdl_snd.c
parentc37663e2d7c564e85af9d17afed0ee1dd283bfb5 (diff)
downloadioquake3-aero-38baaa2274a458f03f576dea5a6d3cd9e25f8063.tar.gz
ioquake3-aero-38baaa2274a458f03f576dea5a6d3cd9e25f8063.zip
* OpenAL support, from BlackAura aka Stuart Dalton <badcdev@gmail.com>
+ An abstract codec system, simplifying support for new formats + Changes versus BlackAura's patch: o Consolidated the OpenAL parts into one file o Changed the function naming scheme to more closely resemble Q3 o Changed the interface to fall back on the "base" sound system if loading OpenAL fails + This is enabled on Linux and MinGW for now, but should work on the other *nixs with appropriate additions to the Makefile + NOT enabled on OS X or MSVC Windows builds + Probably breaks the Windows build again * Retabulated sdl_snd.c and made the messages less verbose since there do not seem to be many having problems with SDL sound now git-svn-id: svn://svn.icculus.org/quake3/trunk@343 edf5b092-35ff-0310-97b2-ce42778d08ea
Diffstat (limited to 'code/unix/sdl_snd.c')
-rw-r--r--code/unix/sdl_snd.c428
1 files changed, 241 insertions, 187 deletions
diff --git a/code/unix/sdl_snd.c b/code/unix/sdl_snd.c
index 3caf85a..ac4a614 100644
--- a/code/unix/sdl_snd.c
+++ b/code/unix/sdl_snd.c
@@ -56,233 +56,285 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "../qcommon/q_shared.h"
#include "../client/snd_local.h"
-int snd_inited=0;
+qboolean snd_inited = qfalse;
-cvar_t *sndbits;
-cvar_t *sndspeed;
-cvar_t *sndchannels;
-cvar_t *snddevice;
-cvar_t *sdldevsamps;
-cvar_t *sdlmixsamps;
+cvar_t *s_sdlBits;
+cvar_t *s_sdlSpeed;
+cvar_t *s_sdlChannels;
+cvar_t *s_sdlDevSamps;
+cvar_t *s_sdlMixSamps;
static qboolean use_custom_memset = qfalse;
-// https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=371
+
+/*
+===============
+Snd_Memset
+
+https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=371
+
+<TTimo> some shitty mess with DMA buffers
+<TTimo> the mmap'ing permissions were write only
+<TTimo> and glibc optimized for mmx would do memcpy with a prefetch and a read
+<TTimo> causing segfaults
+<TTimo> some other systems would not let you mmap the DMA with read permissions
+<TTimo> so I think I ended up attempting opening with read/write, then try write only
+<TTimo> and use my own copy instead of the glibc crap
+===============
+*/
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;
- }
+ 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;
+
+/*
+===============
+sdl_audio_callback
+===============
+*/
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;
+ 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;
}
+static struct
+{
+ Uint16 enumFormat;
+ char *stringFormat;
+} formatToStringTable[ ] =
+{
+ { AUDIO_U8, "AUDIO_U8" },
+ { AUDIO_S8, "AUDIO_S8" },
+ { AUDIO_U16LSB, "AUDIO_U16LSB" },
+ { AUDIO_S16LSB, "AUDIO_S16LSB" },
+ { AUDIO_U16MSB, "AUDIO_U16MSB" },
+ { AUDIO_S16MSB, "AUDIO_S16MSB" }
+};
+
+static int formatToStringTableSize =
+ sizeof( formatToStringTable ) / sizeof( formatToStringTable[ 0 ] );
+
+/*
+===============
+print_audiospec
+===============
+*/
static void print_audiospec(const char *str, const SDL_AudioSpec *spec)
{
- Com_Printf("%s:\n", str);
-
- // I'm sorry this is nasty.
- #define PRINT_AUDIO_FMT(x) \
- if (spec->format == x) Com_Printf("Format: %s\n", #x); else
- PRINT_AUDIO_FMT(AUDIO_U8)
- PRINT_AUDIO_FMT(AUDIO_S8)
- PRINT_AUDIO_FMT(AUDIO_U16LSB)
- PRINT_AUDIO_FMT(AUDIO_S16LSB)
- PRINT_AUDIO_FMT(AUDIO_U16MSB)
- PRINT_AUDIO_FMT(AUDIO_S16MSB)
- Com_Printf("Format: UNKNOWN\n");
- #undef PRINT_AUDIO_FMT
-
- Com_Printf("Freq: %d\n", (int) spec->freq);
- Com_Printf("Samples: %d\n", (int) spec->samples);
- Com_Printf("Channels: %d\n", (int) spec->channels);
- Com_Printf("\n");
+ int i;
+ char *fmt = NULL;
+
+ Com_Printf("%s:\n", str);
+
+ for( i = 0; i < formatToStringTableSize; i++ ) {
+ if( spec->format == formatToStringTable[ i ].enumFormat ) {
+ fmt = formatToStringTable[ i ].stringFormat;
+ }
+ }
+
+ if( fmt ) {
+ Com_Printf( " Format: %s\n", fmt );
+ } else {
+ Com_Printf( " Format: " S_COLOR_RED "UNKNOWN\n", fmt );
+ }
+
+ Com_Printf( " Freq: %d\n", (int) spec->freq );
+ Com_Printf( " Samples: %d\n", (int) spec->samples );
+ Com_Printf( " Channels: %d\n", (int) spec->channels );
}
+/*
+===============
+SNDDMA_Init
+===============
+*/
qboolean SNDDMA_Init(void)
{
- char drivername[128];
- SDL_AudioSpec desired;
- SDL_AudioSpec obtained;
+ char drivername[128];
+ SDL_AudioSpec desired;
+ SDL_AudioSpec obtained;
int tmp;
if (snd_inited)
- return 1;
+ return qtrue;
- Com_Printf("SDL Audio driver initializing...\n");
+ Com_Printf("Initializing SDL audio driver...\n");
- if (!snddevice) {
- sndbits = Cvar_Get("sndbits", "16", CVAR_ARCHIVE);
- sndspeed = Cvar_Get("sndspeed", "0", CVAR_ARCHIVE);
- sndchannels = Cvar_Get("sndchannels", "2", CVAR_ARCHIVE);
- snddevice = Cvar_Get("snddevice", "/dev/dsp", CVAR_ARCHIVE);
- sdldevsamps = Cvar_Get("sdldevsamps", "0", CVAR_ARCHIVE);
- sdlmixsamps = Cvar_Get("sdlmixsamps", "0", CVAR_ARCHIVE);
+ if (!s_sdlBits) {
+ s_sdlBits = Cvar_Get("s_sdlBits", "16", CVAR_ARCHIVE);
+ s_sdlSpeed = Cvar_Get("s_sdlSpeed", "0", CVAR_ARCHIVE);
+ s_sdlChannels = Cvar_Get("s_sdlChannels", "2", CVAR_ARCHIVE);
+ s_sdlDevSamps = Cvar_Get("s_sdlDevSamps", "0", CVAR_ARCHIVE);
+ s_sdlMixSamps = Cvar_Get("s_sdlMixSamps", "0", CVAR_ARCHIVE);
}
- if (!SDL_WasInit(SDL_INIT_AUDIO))
- {
- Com_Printf("Calling SDL_Init(SDL_INIT_AUDIO)...\n");
- if (SDL_Init(SDL_INIT_AUDIO) == -1)
- {
- Com_Printf("SDL_Init(SDL_INIT_AUDIO) failed: %s\n", SDL_GetError());
- return qfalse;
- }
- Com_Printf("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;
- if(!desired.freq) desired.freq = 22050;
- 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 (sdldevsamps->value)
- desired.samples = sdldevsamps->value;
- else
- {
- // just pick a sane default.
- if (desired.freq <= 11025)
- desired.samples = 256;
- else if (desired.freq <= 22050)
- desired.samples = 512;
- else if (desired.freq <= 44100)
- desired.samples = 1024;
- else
- desired.samples = 2048; // (*shrug*)
- }
-
- desired.channels = (int) sndchannels->value;
- desired.callback = sdl_audio_callback;
-
- print_audiospec("Format we requested from SDL audio device", &desired);
-
- if (SDL_OpenAudio(&desired, &obtained) == -1)
- {
- Com_Printf("SDL_OpenAudio() failed: %s\n", SDL_GetError());
- SDL_QuitSubSystem(SDL_INIT_AUDIO);
- return qfalse;
- } // if
-
- print_audiospec("Format we actually got", &obtained);
-
- // dma.samples needs to be big, or id's mixer will just refuse to
- // work at all; we need to keep it significantly bigger than the
- // amount of SDL callback samples, and just copy a little each time
- // the callback runs.
- // 32768 is what the OSS driver filled in here on my system. I don't
- // know if it's a good value overall, but at least we know it's
- // reasonable...this is why I let the user override.
- tmp = sdlmixsamps->value;
- if (!tmp)
- tmp = (obtained.samples * obtained.channels) * 10;
-
- if (tmp & (tmp - 1)) // not a power of two? Seems to confuse something.
- {
- int val = 1;
- while (val < tmp)
- val <<= 1;
-
- Com_Printf("WARNING: sdlmixsamps wasn't a power of two (%d),"
- " so we made it one (%d).\n", tmp, val);
- tmp = val;
- }
-
- dmapos = 0;
+ if (!SDL_WasInit(SDL_INIT_AUDIO))
+ {
+ if (SDL_Init(SDL_INIT_AUDIO) == -1)
+ {
+ Com_Printf("SDL_Init(SDL_INIT_AUDIO) failed: %s\n", SDL_GetError());
+ return qfalse;
+ }
+ }
+
+ 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) s_sdlBits->value);
+ if ((tmp != 16) && (tmp != 8))
+ tmp = 16;
+
+ desired.freq = (int) s_sdlSpeed->value;
+ if(!desired.freq) desired.freq = 22050;
+ 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 (s_sdlDevSamps->value)
+ desired.samples = s_sdlDevSamps->value;
+ else
+ {
+ // just pick a sane default.
+ if (desired.freq <= 11025)
+ desired.samples = 256;
+ else if (desired.freq <= 22050)
+ desired.samples = 512;
+ else if (desired.freq <= 44100)
+ desired.samples = 1024;
+ else
+ desired.samples = 2048; // (*shrug*)
+ }
+
+ desired.channels = (int) s_sdlChannels->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
+
+ print_audiospec("SDL_AudioSpec", &obtained);
+
+ // dma.samples needs to be big, or id's mixer will just refuse to
+ // work at all; we need to keep it significantly bigger than the
+ // amount of SDL callback samples, and just copy a little each time
+ // the callback runs.
+ // 32768 is what the OSS driver filled in here on my system. I don't
+ // know if it's a good value overall, but at least we know it's
+ // reasonable...this is why I let the user override.
+ tmp = s_sdlMixSamps->value;
+ if (!tmp)
+ tmp = (obtained.samples * obtained.channels) * 10;
+
+ if (tmp & (tmp - 1)) // not a power of two? Seems to confuse something.
+ {
+ int val = 1;
+ while (val < tmp)
+ val <<= 1;
+
+ tmp = val;
+ }
+
+ dmapos = 0;
dma.samplebits = obtained.format & 0xFF; // first byte of format is bits.
- dma.channels = obtained.channels;
- dma.samples = tmp;
+ dma.channels = obtained.channels;
+ dma.samples = tmp;
dma.submission_chunk = 1;
dma.speed = obtained.freq;
- dmasize = (dma.samples * (dma.samplebits/8));
+ 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("Starting SDL audio callback...\n");
+ SDL_PauseAudio(0); // start callback.
- Com_Printf("SDL audio initialized.\n");
- snd_inited = 1;
+ Com_Printf("SDL audio initialized.\n");
+ snd_inited = qtrue;
return qtrue;
}
+/*
+===============
+SNDDMA_GetDMAPos
+===============
+*/
int SNDDMA_GetDMAPos(void)
{
- return dmapos;
+ return dmapos;
}
+/*
+===============
+SNDDMA_Shutdown
+===============
+*/
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");
+ 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 = qfalse;
+ Com_Printf("SDL audio device shut down.\n");
}
/*
-==============
+===============
SNDDMA_Submit
Send sound to device if buffer isn't really the dma buffer
@@ -290,15 +342,17 @@ Send sound to device if buffer isn't really the dma buffer
*/
void SNDDMA_Submit(void)
{
- SDL_UnlockAudio();
+ SDL_UnlockAudio();
}
+/*
+===============
+SNDDMA_BeginPainting
+===============
+*/
void SNDDMA_BeginPainting (void)
{
- SDL_LockAudio();
+ SDL_LockAudio();
}
#endif // USE_SDL_SOUND
-
-// end of linux_snd_sdl.c ...
-