snd_dma.c: added SNDDMA_LockBuffer() as a new API, needed for, well, proper buffer

locking.  removed simsound. removed unused S_AmbientOff() and S_AmbientOn(). other
multiple cleanups and fixes.
snd_sdl.c: replaced the old broken implementation which used to cause LRU failures
with the one adapted from the uhexen2 project.
sound.h: added missing prototypes, including the new SNDDMA_LockBuffer().


git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@6 af15c1b1-3010-417e-b628-4374ebc0bcbd
This commit is contained in:
Ozkan Sezer 2010-02-15 23:45:06 +00:00
parent 141b4836ac
commit 5f028f87a3
3 changed files with 281 additions and 215 deletions

View file

@ -35,15 +35,13 @@ void S_StopAllSoundsC(void);
// ======================================================================= // =======================================================================
channel_t channels[MAX_CHANNELS]; channel_t channels[MAX_CHANNELS];
int total_channels; int total_channels;
int snd_blocked = 0; int snd_blocked = 0;
static qboolean snd_ambient = 1; qboolean snd_initialized = false;
qboolean snd_initialized = false;
// pointer should go away volatile dma_t *shm = NULL;
volatile dma_t *shm = 0; volatile dma_t sn;
volatile dma_t sn;
vec3_t listener_origin; vec3_t listener_origin;
vec3_t listener_forward; vec3_t listener_forward;
@ -51,17 +49,17 @@ vec3_t listener_right;
vec3_t listener_up; vec3_t listener_up;
vec_t sound_nominal_clip_dist=1000.0; vec_t sound_nominal_clip_dist=1000.0;
int soundtime; // sample PAIRS int soundtime; // sample PAIRS
int paintedtime; // sample PAIRS int paintedtime; // sample PAIRS
#define MAX_SFX 512 #define MAX_SFX 512
sfx_t *known_sfx; // hunk allocated [MAX_SFX] sfx_t *known_sfx; // hunk allocated [MAX_SFX]
int num_sfx; int num_sfx;
sfx_t *ambient_sfx[NUM_AMBIENTS]; sfx_t *ambient_sfx[NUM_AMBIENTS];
int sound_started=0; qboolean sound_started = false;
cvar_t bgmvolume = {"bgmvolume", "1", true}; cvar_t bgmvolume = {"bgmvolume", "1", true};
cvar_t volume = {"volume", "0.7", true}; cvar_t volume = {"volume", "0.7", true};
@ -78,33 +76,6 @@ cvar_t _snd_mixahead = {"_snd_mixahead", "0.1", true};
cvar_t sndspeed = {"sndspeed", "11025"}; cvar_t sndspeed = {"sndspeed", "11025"};
// ====================================================================
// User-setable variables
// ====================================================================
//
// Fake dma is a synchronous faking of the DMA progress used for
// isolating performance in the renderer. The fakedma_updates is
// number of times S_Update() is called per second.
//
qboolean fakedma = false;
int fakedma_updates = 15;
void S_AmbientOff (void)
{
snd_ambient = false;
}
void S_AmbientOn (void)
{
snd_ambient = true;
}
void S_SoundInfo_f(void) void S_SoundInfo_f(void)
{ {
if (!sound_started || !shm) if (!sound_started || !shm)
@ -113,14 +84,13 @@ void S_SoundInfo_f(void)
return; return;
} }
Con_Printf("%5d stereo\n", shm->channels - 1); Con_Printf("%d bit, %s, %d Hz\n", shm->samplebits,
Con_Printf("%5d samples\n", shm->samples); (shm->channels == 2) ? "stereo" : "mono", shm->speed);
Con_Printf("%5d samplepos\n", shm->samplepos); Con_Printf("%5d samples\n", shm->samples);
Con_Printf("%5d samplebits\n", shm->samplebits); Con_Printf("%5d samplepos\n", shm->samplepos);
Con_Printf("%5d submission_chunk\n", shm->submission_chunk); Con_Printf("%5d submission_chunk\n", shm->submission_chunk);
Con_Printf("%5d speed\n", shm->speed);
Con_Printf("0x%x dma buffer\n", shm->buffer);
Con_Printf("%5d total_channels\n", total_channels); Con_Printf("%5d total_channels\n", total_channels);
Con_Printf("%p dma buffer\n", shm->buffer);
} }
@ -137,21 +107,19 @@ void S_Startup (void)
if (!snd_initialized) if (!snd_initialized)
return; return;
if (!fakedma) sound_started = SNDDMA_Init();
if (!sound_started)
{ {
rc = SNDDMA_Init(); Con_Printf("Failed initializing sound\n");
}
if (!rc) else
{ {
#ifndef _WIN32 Con_Printf("Audio: %d bit, %s, %d Hz\n",
Con_Printf("S_Startup: SNDDMA_Init failed.\n"); shm->samplebits,
#endif (shm->channels == 2) ? "stereo" : "mono",
sound_started = 0; shm->speed);
return;
}
} }
sound_started = 1;
} }
@ -162,23 +130,11 @@ S_Init
*/ */
void S_Init (void) void S_Init (void)
{ {
if (COM_CheckParm("-nosound")) if (snd_initialized)
{
Con_Printf("Sound is already initialized\n");
return; return;
}
//johnfitz -- clean up init readouts
Con_Printf("Sound Initialization\n");
//Con_Printf("------------- Init Sound -------------\n");
//Con_Printf("%cSound Init\n", 2);
//johnfitz
if (COM_CheckParm("-simsound"))
fakedma = true;
Cmd_AddCommand("play", S_Play);
Cmd_AddCommand("playvol", S_PlayVol);
Cmd_AddCommand("stopsound", S_StopAllSoundsC);
Cmd_AddCommand("soundlist", S_SoundList);
Cmd_AddCommand("soundinfo", S_SoundInfo_f);
Cvar_RegisterVariable(&nosound, NULL); Cvar_RegisterVariable(&nosound, NULL);
Cvar_RegisterVariable(&volume, NULL); Cvar_RegisterVariable(&volume, NULL);
@ -191,7 +147,18 @@ void S_Init (void)
Cvar_RegisterVariable(&snd_noextraupdate, NULL); Cvar_RegisterVariable(&snd_noextraupdate, NULL);
Cvar_RegisterVariable(&snd_show, NULL); Cvar_RegisterVariable(&snd_show, NULL);
Cvar_RegisterVariable(&_snd_mixahead, NULL); Cvar_RegisterVariable(&_snd_mixahead, NULL);
Cvar_RegisterVariable(&sndspeed, NULL); Cvar_RegisterVariable(&sndspeed, NULL);
if (COM_CheckParm("-nosound"))
return;
Con_Printf("Sound Initialization\n");
Cmd_AddCommand("play", S_Play);
Cmd_AddCommand("playvol", S_PlayVol);
Cmd_AddCommand("stopsound", S_StopAllSoundsC);
Cmd_AddCommand("soundlist", S_SoundList);
Cmd_AddCommand("soundinfo", S_SoundInfo_f);
if (COM_CheckParm("-sndspeed")) if (COM_CheckParm("-sndspeed"))
{ {
@ -204,38 +171,18 @@ void S_Init (void)
Con_Printf ("loading all sounds as 8bit\n"); Con_Printf ("loading all sounds as 8bit\n");
} }
snd_initialized = true;
S_Startup ();
SND_InitScaletable (); SND_InitScaletable ();
known_sfx = Hunk_AllocName (MAX_SFX*sizeof(sfx_t), "sfx_t"); known_sfx = Hunk_AllocName (MAX_SFX*sizeof(sfx_t), "sfx_t");
num_sfx = 0; num_sfx = 0;
// create a piece of DMA memory snd_initialized = true;
if (fakedma) S_Startup ();
{ if (sound_started == 0)
shm = (void *) Hunk_AllocName(sizeof(*shm), "shm"); return;
shm->splitbuffer = 0;
shm->samplebits = 16;
shm->speed = 22050;
shm->channels = 2;
shm->samples = 32768;
shm->samplepos = 0;
shm->soundalive = true;
shm->gamealive = true;
shm->submission_chunk = 1;
shm->buffer = Hunk_AllocName(1<<16, "shmbuf");
}
Con_Printf ("Sound sampling rate: %i\n", shm->speed);
// provides a tick sound until washed clean // provides a tick sound until washed clean
// if (shm->buffer) // if (shm->buffer)
// shm->buffer[4] = shm->buffer[5] = 0x7f; // force a pop for debugging // shm->buffer[4] = shm->buffer[5] = 0x7f; // force a pop for debugging
@ -252,20 +199,16 @@ void S_Init (void)
void S_Shutdown(void) void S_Shutdown(void)
{ {
if (!sound_started) if (!sound_started)
return; return;
if (shm) if (shm)
shm->gamealive = 0; shm->gamealive = 0;
shm = 0;
sound_started = 0; sound_started = 0;
snd_blocked = 0;
if (!fakedma) SNDDMA_Shutdown();
{ shm = NULL;
SNDDMA_Shutdown();
}
} }
@ -285,17 +228,19 @@ sfx_t *S_FindName (char *name)
sfx_t *sfx; sfx_t *sfx;
if (!name) if (!name)
Sys_Error ("S_FindName: NULL\n"); Sys_Error ("S_FindName: NULL");
if (Q_strlen(name) >= MAX_QPATH) if (Q_strlen(name) >= MAX_QPATH)
Sys_Error ("Sound name too long: %s", name); Sys_Error ("Sound name too long: %s", name);
// see if already loaded // see if already loaded
for (i=0 ; i < num_sfx ; i++) for (i=0 ; i < num_sfx ; i++)
{
if (!Q_strcmp(known_sfx[i].name, name)) if (!Q_strcmp(known_sfx[i].name, name))
{ {
return &known_sfx[i]; return &known_sfx[i];
} }
}
if (num_sfx == MAX_SFX) if (num_sfx == MAX_SFX)
Sys_Error ("S_FindName: out of sfx_t"); Sys_Error ("S_FindName: out of sfx_t");
@ -406,12 +351,8 @@ void SND_Spatialize(channel_t *ch)
vec_t dist; vec_t dist;
vec_t lscale, rscale, scale; vec_t lscale, rscale, scale;
vec3_t source_vec; vec3_t source_vec;
sfx_t *snd;
/* unused -- kristian
vec_t ldist, rdist;
*/
// anything coming from the view entity will allways be full volume // anything coming from the view entity will always be full volume
if (ch->entnum == cl.viewentity) if (ch->entnum == cl.viewentity)
{ {
ch->leftvol = ch->master_vol; ch->leftvol = ch->master_vol;
@ -420,12 +361,8 @@ void SND_Spatialize(channel_t *ch)
} }
// calculate stereo seperation and distance attenuation // calculate stereo seperation and distance attenuation
snd = ch->sfx;
VectorSubtract(ch->origin, listener_origin, source_vec); VectorSubtract(ch->origin, listener_origin, source_vec);
dist = VectorNormalize(source_vec) * ch->dist_mult; dist = VectorNormalize(source_vec) * ch->dist_mult;
dot = DotProduct(listener_right, source_vec); dot = DotProduct(listener_right, source_vec);
if (shm->channels == 1) if (shm->channels == 1)
@ -460,7 +397,6 @@ void S_StartSound(int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float f
{ {
channel_t *target_chan, *check; channel_t *target_chan, *check;
sfxcache_t *sc; sfxcache_t *sc;
int vol;
int ch_idx; int ch_idx;
int skip; int skip;
@ -473,8 +409,6 @@ void S_StartSound(int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float f
if (nosound.value) if (nosound.value)
return; return;
vol = fvol*255;
// pick a channel to play on // pick a channel to play on
target_chan = SND_PickChannel(entnum, entchannel); target_chan = SND_PickChannel(entnum, entchannel);
if (!target_chan) if (!target_chan)
@ -484,7 +418,7 @@ void S_StartSound(int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float f
memset (target_chan, 0, sizeof(*target_chan)); memset (target_chan, 0, sizeof(*target_chan));
VectorCopy(origin, target_chan->origin); VectorCopy(origin, target_chan->origin);
target_chan->dist_mult = attenuation / sound_nominal_clip_dist; target_chan->dist_mult = attenuation / sound_nominal_clip_dist;
target_chan->master_vol = vol; target_chan->master_vol = (int) (fvol * 255);
target_chan->entnum = entnum; target_chan->entnum = entnum;
target_chan->entchannel = entchannel; target_chan->entchannel = entchannel;
SND_Spatialize(target_chan); SND_Spatialize(target_chan);
@ -520,7 +454,6 @@ void S_StartSound(int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float f
target_chan->end -= skip; target_chan->end -= skip;
break; break;
} }
} }
} }
@ -550,10 +483,12 @@ void S_StopAllSounds(qboolean clear)
total_channels = MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS; // no statics total_channels = MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS; // no statics
for (i=0 ; i<MAX_CHANNELS ; i++) for (i=0 ; i<MAX_CHANNELS ; i++)
{
if (channels[i].sfx) if (channels[i].sfx)
channels[i].sfx = NULL; channels[i].sfx = NULL;
}
Q_memset(channels, 0, MAX_CHANNELS * sizeof(channel_t)); memset(channels, 0, MAX_CHANNELS * sizeof(channel_t));
if (clear) if (clear)
S_ClearBuffer (); S_ClearBuffer ();
@ -568,7 +503,11 @@ void S_ClearBuffer (void)
{ {
int clear; int clear;
if (!sound_started || !shm || !shm->buffer) if (!sound_started || !shm)
return;
SNDDMA_LockBuffer ();
if (! shm->buffer)
return; return;
if (shm->samplebits == 8) if (shm->samplebits == 8)
@ -576,7 +515,9 @@ void S_ClearBuffer (void)
else else
clear = 0; clear = 0;
Q_memset(shm->buffer, clear, shm->samples * shm->samplebits/8); memset(shm->buffer, clear, shm->samples * shm->samplebits / 8);
SNDDMA_Submit ();
} }
@ -636,9 +577,6 @@ void S_UpdateAmbientSounds (void)
int ambient_channel; int ambient_channel;
channel_t *chan; channel_t *chan;
if (!snd_ambient)
return;
//johnfitz -- no ambients when disconnected //johnfitz -- no ambients when disconnected
if (cls.state != ca_connected) if (cls.state != ca_connected)
return; return;
@ -737,8 +675,10 @@ void S_Update(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up)
// search for one // search for one
combine = channels+MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS; combine = channels+MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS;
for (j=MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS ; j<i; j++, combine++) for (j=MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS ; j<i; j++, combine++)
{
if (combine->sfx == ch->sfx) if (combine->sfx == ch->sfx)
break; break;
}
if (j == total_channels) if (j == total_channels)
{ {
@ -755,8 +695,6 @@ void S_Update(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up)
continue; continue;
} }
} }
} }
// //
@ -767,11 +705,13 @@ void S_Update(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up)
total = 0; total = 0;
ch = channels; ch = channels;
for (i=0 ; i<total_channels; i++, ch++) for (i=0 ; i<total_channels; i++, ch++)
{
if (ch->sfx && (ch->leftvol || ch->rightvol) ) if (ch->sfx && (ch->leftvol || ch->rightvol) )
{ {
//Con_Printf ("%3i %3i %s\n", ch->leftvol, ch->rightvol, ch->sfx->name); //Con_Printf ("%3i %3i %s\n", ch->leftvol, ch->rightvol, ch->sfx->name);
total++; total++;
} }
}
Con_Printf ("----(%i)----\n", total); Con_Printf ("----(%i)----\n", total);
} }
@ -824,12 +764,17 @@ void S_ExtraUpdate (void)
void S_Update_(void) void S_Update_(void)
{ {
unsigned endtime; #if 1
int samps; unsigned int endtime;
int samps;
if (!sound_started || (snd_blocked > 0)) if (!sound_started || (snd_blocked > 0))
return; return;
SNDDMA_LockBuffer ();
if (! shm->buffer)
return;
// Updates DMA time // Updates DMA time
GetSoundtime(); GetSoundtime();
@ -848,7 +793,32 @@ void S_Update_(void)
S_PaintChannels (endtime); S_PaintChannels (endtime);
// SNDDMA_Submit (); SNDDMA_Submit ();
#endif
}
void S_BlockSound (void)
{
/* FIXME: do we really need the blocking at the
* driver level?
*/
if (sound_started && ++snd_blocked == 1)
{
S_ClearBuffer ();
if (shm)
SNDDMA_BlockSound();
}
}
void S_UnblockSound (void)
{
if (!sound_started || !snd_blocked)
return;
if (--snd_blocked == 0)
{
SNDDMA_UnblockSound();
S_ClearBuffer ();
}
} }
/* /*
@ -932,7 +902,7 @@ void S_SoundList(void)
} }
void S_LocalSound (char *sound) void S_LocalSound (char *name)
{ {
sfx_t *sfx; sfx_t *sfx;
@ -941,10 +911,10 @@ void S_LocalSound (char *sound)
if (!sound_started) if (!sound_started)
return; return;
sfx = S_PrecacheSound (sound); sfx = S_PrecacheSound (name);
if (!sfx) if (!sfx)
{ {
Con_Printf ("S_LocalSound: can't cache %s\n", sound); Con_Printf ("S_LocalSound: can't cache %s\n", name);
return; return;
} }
S_StartSound (cl.viewentity, -1, sfx, vec3_origin, 1, 1); S_StartSound (cl.viewentity, -1, sfx, vec3_origin, 1, 1);

View file

@ -1,125 +1,207 @@
/* /*
Copyright (C) 1996-2001 Id Software, Inc. snd_sdl2.c
Copyright (C) 2002-2005 John Fitzgibbons and others SDL audio driver for Hexen II: Hammer of Thyrion, based on the
Copyright (C) 2007-2008 Kristian Duske implementations found in the quakeforge and quake3-icculus.org
projects.
This program is free software; you can redistribute it and/or $Id: snd_sdl2.c,v 1.8 2010/01/23 12:01:23 sezero Exp $
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, This program is free software; you can redistribute it and/or
but WITHOUT ANY WARRANTY; without even the implied warranty of modify it under the terms of the GNU General Public License
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
See the GNU General Public License for more details. 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.
You should have received a copy of the GNU General Public License See the GNU General Public License for more details.
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
51 Franklin St, Fifth Floor,
Boston, MA 02110-1301 USA
*/ */
// stolen from http://www.libsdl.org/projects/quake/ -- apologies, I don't know the author's name
#include <stdio.h>
#include "quakedef.h" #include "quakedef.h"
#include "SDL.h"
static dma_t the_shm; static int buffersize;
static int snd_inited;
#define BUF_SIZE 512 static void paint_audio (void *unused, Uint8 *stream, int len)
static void paint_audio(void *unused, Uint8 *stream, int len)
{ {
if ( shm ) { int pos, tobufend;
shm->buffer = stream; int len1, len2;
shm->samplepos += len/(shm->samplebits/8)/2;
// Check for samplepos overflow? if (!shm)
S_PaintChannels (shm->samplepos); { /* 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(void) qboolean SNDDMA_Init (void)
{ {
SDL_AudioSpec desired, obtained; SDL_AudioSpec desired, obtained;
int tmp, val;
char drivername[128];
snd_inited = 0; if (SDL_InitSubSystem(SDL_INIT_AUDIO) == -1)
{
Con_Printf("Couldn't init SDL audio: %s\n", SDL_GetError());
return false;
}
/* Set up the desired format */ /* Set up the desired format */
desired.freq = sndspeed.value; desired.freq = tmp = sndspeed.value;
if (loadas8bit.value) { desired.format = (loadas8bit.value) ? AUDIO_U8 : AUDIO_S16SYS;
desired.format = AUDIO_U8; desired.channels = 2; /* = desired_channels; */
} else { if (desired.freq <= 11025)
if (SDL_BYTEORDER == SDL_BIG_ENDIAN) desired.samples = 256;
desired.format = AUDIO_S16MSB; else if (desired.freq <= 22050)
else desired.samples = 512;
desired.format = AUDIO_S16LSB; else if (desired.freq <= 44100)
} desired.samples = 1024;
desired.channels = 2; else
desired.samples = BUF_SIZE; desired.samples = 2048; /* shrug */
desired.callback = paint_audio; desired.callback = paint_audio;
desired.userdata = NULL;
/* Open the audio device */ /* Open the audio device */
if ( SDL_OpenAudio(&desired, &obtained) < 0 ) { if (SDL_OpenAudio(&desired, &obtained) == -1)
Con_Printf("Couldn't open SDL audio: %s\n", SDL_GetError()); {
return 0; Con_Printf("Couldn't open SDL audio: %s\n", SDL_GetError());
SDL_QuitSubSystem(SDL_INIT_AUDIO);
return false;
} }
/* Make sure we can support the audio format */ /* Make sure we can support the audio format */
switch (obtained.format) { switch (obtained.format)
case AUDIO_U8: {
/* Supported */ case AUDIO_U8:
break; case AUDIO_S16SYS:
case AUDIO_S16LSB: /* Supported */
case AUDIO_S16MSB: break;
if ( ((obtained.format == AUDIO_S16LSB) && default:
(SDL_BYTEORDER == SDL_LIL_ENDIAN)) || Con_Printf ("Unsupported audio format received (%u)\n", obtained.format);
((obtained.format == AUDIO_S16MSB) && SDL_CloseAudio();
(SDL_BYTEORDER == SDL_BIG_ENDIAN)) ) { SDL_QuitSubSystem(SDL_INIT_AUDIO);
/* Supported */ return false;
break;
}
/* Unsupported, fall through */;
default:
/* Not supported -- force SDL to do our bidding */
SDL_CloseAudio();
if ( SDL_OpenAudio(&desired, NULL) < 0 ) {
Con_Printf("Couldn't open SDL audio: %s\n",
SDL_GetError());
return 0;
}
memcpy(&obtained, &desired, sizeof(desired));
break;
} }
SDL_PauseAudio(0);
memset ((void *) &sn, 0, sizeof(dma_t));
shm = &sn;
/* Fill the audio DMA information block */ /* Fill the audio DMA information block */
shm = &the_shm; shm->samplebits = (obtained.format & 0xFF); /* first byte of format is bits */
shm->splitbuffer = 0; if (obtained.freq != tmp)
shm->samplebits = (obtained.format & 0xFF); Con_Printf ("Warning: Rate set (%d) didn't match requested rate (%d)!\n", obtained.freq, tmp);
shm->speed = obtained.freq; shm->speed = obtained.freq;
shm->channels = obtained.channels; shm->channels = obtained.channels;
shm->samples = obtained.samples*shm->channels; tmp = (obtained.samples * obtained.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->samplepos = 0;
shm->submission_chunk = 1; shm->submission_chunk = 1;
shm->buffer = NULL;
snd_inited = 1; Con_Printf ("SDL audio spec : %d Hz, %d samples, %d channels\n",
return 1; obtained.freq, obtained.samples, obtained.channels);
if (SDL_AudioDriverName(drivername, sizeof(drivername)) == NULL)
strcpy(drivername, "(UNKNOWN)");
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) int SNDDMA_GetDMAPos (void)
{ {
return shm->samplepos; return shm->samplepos;
} }
void SNDDMA_Shutdown(void) void SNDDMA_Shutdown (void)
{ {
if (snd_inited) if (shm)
{ {
Con_Printf ("Shutting down SDL sound\n");
SDL_PauseAudio(1);
SDL_LockAudio ();
SDL_CloseAudio(); SDL_CloseAudio();
snd_inited = 0; if (shm->buffer)
free (shm->buffer);
SDL_QuitSubSystem(SDL_INIT_AUDIO);
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);
}

View file

@ -102,6 +102,9 @@ void S_ClearBuffer (void);
void S_Update (vec3_t origin, vec3_t v_forward, vec3_t v_right, vec3_t v_up); void S_Update (vec3_t origin, vec3_t v_forward, vec3_t v_right, vec3_t v_up);
void S_ExtraUpdate (void); void S_ExtraUpdate (void);
void S_BlockSound (void);
void S_UnblockSound (void);
sfx_t *S_PrecacheSound (char *sample); sfx_t *S_PrecacheSound (char *sample);
void S_TouchSound (char *sample); void S_TouchSound (char *sample);
void S_ClearPrecache (void); void S_ClearPrecache (void);
@ -125,6 +128,18 @@ int SNDDMA_GetDMAPos(void);
// shutdown the DMA xfer. // shutdown the DMA xfer.
void SNDDMA_Shutdown(void); void SNDDMA_Shutdown(void);
/* validates & locks the dma buffer */
void SNDDMA_LockBuffer(void);
/* unlocks the dma buffer / sends sound to the device */
void SNDDMA_Submit(void);
/* blocks sound output upon window focus loss */
void SNDDMA_BlockSound(void);
/* unblocks the output upon window focus gain */
void SNDDMA_UnblockSound(void);
// ==================================================================== // ====================================================================
// User-setable variables // User-setable variables
// ==================================================================== // ====================================================================
@ -172,7 +187,6 @@ sfxcache_t *S_LoadSound (sfx_t *s);
wavinfo_t GetWavinfo (char *name, byte *wav, int wavlength); wavinfo_t GetWavinfo (char *name, byte *wav, int wavlength);
void SND_InitScaletable (void); void SND_InitScaletable (void);
void SNDDMA_Submit(void);
void S_AmbientOff (void); void S_AmbientOff (void);
void S_AmbientOn (void); void S_AmbientOn (void);