2010-10-13 21:04:59 +00:00
|
|
|
#include <SDL.h>
|
|
|
|
#include "../client/header/client.h"
|
|
|
|
#include "../client/sound/header/local.h"
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-13 21:04:59 +00:00
|
|
|
/* Global stuff */
|
|
|
|
int snd_inited = 0;
|
|
|
|
static int dmapos = 0;
|
|
|
|
static int dmasize = 0;
|
|
|
|
static dma_t *dmabackend;
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-13 21:04:59 +00:00
|
|
|
/* The callback */
|
|
|
|
static void
|
|
|
|
sdl_audio_callback(void *data, Uint8 *stream, int length)
|
|
|
|
{
|
|
|
|
int length1;
|
|
|
|
int length2;
|
|
|
|
int pos = (dmapos * (dmabackend->samplebits / 8));
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-13 21:04:59 +00:00
|
|
|
if (pos >= dmasize)
|
|
|
|
{
|
|
|
|
dmapos = pos = 0;
|
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-13 21:04:59 +00:00
|
|
|
/* This can't happen! */
|
|
|
|
if (!snd_inited)
|
|
|
|
{
|
|
|
|
memset(stream, '\0', length);
|
|
|
|
return;
|
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-13 21:04:59 +00:00
|
|
|
int tobufferend = dmasize - pos;
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-13 21:04:59 +00:00
|
|
|
if (length > tobufferend)
|
|
|
|
{
|
|
|
|
length1 = tobufferend;
|
|
|
|
length2 = length - length1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
length1= length;
|
|
|
|
length2 = 0;
|
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-13 21:04:59 +00:00
|
|
|
memcpy(stream, dmabackend->buffer + pos, length1);
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-13 21:04:59 +00:00
|
|
|
/* Set new position */
|
|
|
|
if (length2 <= 0)
|
|
|
|
{
|
|
|
|
dmapos += (length1 / (dmabackend->samplebits / 8));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
memcpy(stream + length1, dmabackend->buffer, length2);
|
|
|
|
dmapos = (length2 / (dmabackend->samplebits / 8));
|
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-10-13 21:04:59 +00:00
|
|
|
if (dmapos >= dmasize)
|
|
|
|
{
|
|
|
|
dmapos = 0;
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
qboolean
|
2010-10-13 21:04:59 +00:00
|
|
|
SNDDMA_Init(void)
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-10-13 21:04:59 +00:00
|
|
|
char drivername[128];
|
|
|
|
SDL_AudioSpec desired;
|
|
|
|
SDL_AudioSpec optained;
|
|
|
|
|
|
|
|
/* This should never happen,
|
|
|
|
but this is Quake 2 ... */
|
|
|
|
if (snd_inited)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int sndbits = (Cvar_Get("sndbits", "16", CVAR_ARCHIVE))->value;
|
|
|
|
int sndfreq = (Cvar_Get("s_khz", "0", CVAR_ARCHIVE))->value;
|
|
|
|
int sndchans = (Cvar_Get("sndchannels", "2", CVAR_ARCHIVE))->value;
|
|
|
|
|
|
|
|
if (!SDL_WasInit(SDL_INIT_AUDIO))
|
|
|
|
{
|
|
|
|
if (SDL_Init(SDL_INIT_AUDIO) == -1)
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
Com_Printf ("Couldn't init SDL audio: %s\n", SDL_GetError ());
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-13 21:04:59 +00:00
|
|
|
if (SDL_AudioDriverName(drivername, sizeof(drivername)) == NULL)
|
|
|
|
{
|
|
|
|
strcpy(drivername, "(UNKNOW)");
|
|
|
|
}
|
|
|
|
|
|
|
|
Com_Printf("SDL audio driver is \"%s\"\n", drivername);
|
|
|
|
|
|
|
|
memset(&desired, '\0', sizeof(desired));
|
|
|
|
memset(&optained, '\0', sizeof(optained));
|
|
|
|
|
|
|
|
/* Users are stupid */
|
|
|
|
if ((sndbits != 16) && (sndbits != 8))
|
|
|
|
{
|
|
|
|
sndbits = 16;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sndfreq == 22)
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
desired.freq = 22050;
|
2010-10-13 21:04:59 +00:00
|
|
|
}
|
|
|
|
else if (sndfreq == 11)
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
desired.freq = 11025;
|
|
|
|
}
|
2010-10-13 21:04:59 +00:00
|
|
|
|
|
|
|
desired.format = ((sndbits == 16) ? AUDIO_S16SYS : AUDIO_U8);
|
|
|
|
|
|
|
|
if (desired.freq <= 11025)
|
|
|
|
{
|
|
|
|
desired.samples = 256;
|
|
|
|
}
|
|
|
|
else if (desired.freq <= 22050)
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
desired.samples = 512;
|
2010-10-13 21:04:59 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
desired.samples = 2048;
|
|
|
|
}
|
|
|
|
|
|
|
|
desired.channels = sndchans;
|
|
|
|
desired.callback = sdl_audio_callback;
|
|
|
|
|
|
|
|
/* Okay, let's try our luck */
|
|
|
|
if (SDL_OpenAudio(&desired, &optained) == -1)
|
|
|
|
{
|
|
|
|
Com_Printf("SDL_OpenAudio() failed: %s\n", SDL_GetError());
|
|
|
|
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
2009-02-28 14:41:18 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-10-13 21:04:59 +00:00
|
|
|
/* Don't pollute the frontend dma_t */
|
|
|
|
dmabackend = &dma;
|
|
|
|
|
|
|
|
dmapos = 0;
|
|
|
|
dmabackend->samplebits = optained.format & 0xFF;
|
|
|
|
dmabackend->channels = optained.channels;
|
|
|
|
dmabackend->samples = 32768;
|
|
|
|
dmabackend->submission_chunk = 1;
|
|
|
|
dmabackend->speed = optained.freq;
|
|
|
|
dmasize = (dmabackend->samples * (dmabackend->samplebits / 8));
|
|
|
|
dmabackend->buffer = calloc(1, dmasize);
|
|
|
|
|
|
|
|
Com_Printf("Starting SDL audio callback...\n");
|
|
|
|
SDL_PauseAudio(0);
|
|
|
|
|
|
|
|
Com_Printf("SDL audio initialized.\n");
|
|
|
|
snd_inited = 1;
|
|
|
|
return 1;
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2010-10-13 21:04:59 +00:00
|
|
|
SNDDMA_GetDMAPos(void)
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-10-13 21:04:59 +00:00
|
|
|
return dmapos;
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-10-13 21:04:59 +00:00
|
|
|
SNDDMA_Shutdown(void)
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-10-13 21:04:59 +00:00
|
|
|
Com_Printf("Closing SDL audio device...\n");
|
|
|
|
SDL_PauseAudio(1);
|
|
|
|
SDL_CloseAudio();
|
|
|
|
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
|
|
|
free(dmabackend->buffer);
|
|
|
|
dmabackend->buffer = NULL;
|
|
|
|
dmapos = dmasize = 0;
|
|
|
|
snd_inited = 0;
|
|
|
|
Com_Printf("SDL audio device shut down.\n");
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
2010-10-13 21:04:59 +00:00
|
|
|
/*
|
|
|
|
* This sends the sound to the device,
|
|
|
|
* if the DMA isn't the device itself.
|
|
|
|
* This shouldn't be the case on all PCI
|
|
|
|
* and PCIe soundcards
|
|
|
|
*/
|
2009-02-28 14:41:18 +00:00
|
|
|
void
|
2010-10-13 21:04:59 +00:00
|
|
|
SNDDMA_Submit(void)
|
2009-02-28 14:41:18 +00:00
|
|
|
{
|
2010-10-13 21:04:59 +00:00
|
|
|
SDL_UnlockAudio();
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
2010-10-13 21:04:59 +00:00
|
|
|
void
|
|
|
|
SNDDMA_BeginPainting(void)
|
|
|
|
{
|
|
|
|
SDL_LockAudio();
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
2009-03-04 15:50:05 +00:00
|
|
|
|