From d50445e9045ddea0d49857346597c57c129029e0 Mon Sep 17 00:00:00 2001 From: molivier Date: Wed, 13 Oct 2004 07:03:57 +0000 Subject: [PATCH] Lots of minor fixes and improvements to the sound engine, plus a few more important changes: - moved the internal structures and API into a separate file (snd_main.h) - added a lock mecanism on SFXs to free them as soon as they're no longer used - simplified the sound API - minor fixes and comment changes here and there - independent sound volume for fake CD tracks - updated MSVC and Dev-C++ project files accordingly - removed unused functions - added a SFX flag to make sure the engine complains at most one time for each missing sound file - made the SFX list a linked list to remove the hardcoded limit for the number of SFX a client can handle - changed the way ambient sounds are managed to be more consistent with the new API - factorized some code - removed the useless IN_Accumulate in the Win32 specific code - removed the table for 8bit sound mixing (snd_scaletable) git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@4624 d7cf8633-e32d-0410-b094-e92efae38249 --- cd_shared.c | 9 +- cdaudio.h | 2 + cl_main.c | 2 +- cl_parse.c | 37 ++-- cl_screen.c | 2 +- darkplaces.dev | 12 +- darkplaces.dsp | 4 + dpvsimpledecode.c | 2 +- menu.c | 1 - prvm_cmds.c | 13 +- quakedef.h | 2 - snd_alsa.c | 4 - snd_bsd.c | 1 + snd_dma.c | 443 ++++++++++++++++++++++------------------------ snd_main.h | 143 +++++++++++++++ snd_mem.c | 26 +-- snd_mix.c | 98 +++++----- snd_null.c | 37 ++-- snd_ogg.c | 3 +- snd_oss.c | 1 + snd_sdl.c | 1 + snd_wav.c | 1 + snd_win.c | 1 + sound.h | 184 ++++--------------- todo | 4 +- vid_wgl.c | 36 +--- 26 files changed, 517 insertions(+), 552 deletions(-) create mode 100644 snd_main.h diff --git a/cd_shared.c b/cd_shared.c index 998f76f4..c486fe56 100644 --- a/cd_shared.c +++ b/cd_shared.c @@ -110,14 +110,15 @@ void CDAudio_Play (qbyte track, qboolean looping) CDAudio_Stop (); // Try playing a fake track (sound file) first - sfx = S_PrecacheSound (va ("cdtracks/track%02u.wav", track), false, true); + sfx = S_PrecacheSound (va ("cdtracks/track%02u.wav", track), false, true, false); if (sfx != NULL) { faketrack = S_StartSound (-1, 0, sfx, vec3_origin, cdvolume, 0); if (faketrack != -1) { if (looping) - S_LoopChannel (faketrack, true); + S_SetChannelFlag (faketrack, CHANNELFLAG_FORCELOOP, true); + S_SetChannelFlag (faketrack, CHANNELFLAG_FULLVOLUME, true); Con_DPrintf ("Fake CD track %u playing...\n", track); } } @@ -177,7 +178,7 @@ void CDAudio_Pause (void) return; if (faketrack != -1) - S_PauseChannel (faketrack, true); + S_SetChannelFlag (faketrack, CHANNELFLAG_PAUSED, true); else if (CDAudio_SysPause() == -1) return; @@ -192,7 +193,7 @@ void CDAudio_Resume (void) return; if (faketrack != -1) - S_PauseChannel (faketrack, false); + S_SetChannelFlag (faketrack, CHANNELFLAG_PAUSED, false); else if (CDAudio_SysResume() == -1) return; cdPlaying = true; diff --git a/cdaudio.h b/cdaudio.h index e58e766c..eefb0c98 100644 --- a/cdaudio.h +++ b/cdaudio.h @@ -23,6 +23,8 @@ extern qboolean cdPlaying; extern qboolean cdPlayLooping; extern qbyte cdPlayTrack; +extern cvar_t cdaudioinitialized; + int CDAudio_Init(void); void CDAudio_Open(void); void CDAudio_Close(void); diff --git a/cl_main.c b/cl_main.c index 1fef3cea..6151d019 100644 --- a/cl_main.c +++ b/cl_main.c @@ -170,7 +170,7 @@ void CL_Disconnect(void) Con_DPrintf("CL_Disconnect\n"); // stop sounds (especially looping!) - S_StopAllSounds (true); + S_StopAllSounds (); // clear contents blends cl.cshifts[0].percent = 0; diff --git a/cl_parse.c b/cl_parse.c index d3f52ac2..5d3b55e0 100644 --- a/cl_parse.c +++ b/cl_parse.c @@ -152,7 +152,7 @@ void CL_ParseStartSoundPacket(int largesoundindex) MSG_ReadVector(pos, cl.protocol); - S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation); + S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0f, attenuation); } /* @@ -407,13 +407,7 @@ void CL_ParseServerInfo (void) Mod_PurgeUnused(); // do the same for sounds - S_ClearUsed(); - for (i = 1;i < numsounds;i++) - { - CL_KeepaliveMessage(); - S_TouchSound(parse_sound_precache[i], true); - } - S_PurgeUnused(); + S_ServerSounds (parse_sound_precache, numsounds); // now we try to load everything that is new @@ -435,7 +429,9 @@ void CL_ParseServerInfo (void) for (i=1 ; isndchan = S_StartSound (-1, 0, sfx, vec3_origin, 1.0f, 0); else diff --git a/menu.c b/menu.c index 735ec3c2..e99bf9ce 100644 --- a/menu.c +++ b/menu.c @@ -1215,7 +1215,6 @@ void M_Menu_Options_f (void) m_entersound = true; } -extern cvar_t snd_staticvolume; extern cvar_t slowmo; extern dllhandle_t jpeg_dll; extern cvar_t gl_texture_anisotropy; diff --git a/prvm_cmds.c b/prvm_cmds.c index 0ab773f4..6b390e7b 100644 --- a/prvm_cmds.c +++ b/prvm_cmds.c @@ -624,14 +624,13 @@ void VM_localsound(void) s = PRVM_G_STRING(OFS_PARM0); - if(!S_GetCached(s, true)) + if(!S_LocalSound(s, true)) { - Con_Printf("VM_localsound: %s : %s not cached !\n", PRVM_NAME, s); + Con_Printf("VM_localsound: Failed to play %s for %s !\n", s, PRVM_NAME); PRVM_G_FLOAT(OFS_RETURN) = -4; return; } - S_LocalSound(s, true); PRVM_G_FLOAT(OFS_RETURN) = 1; } @@ -1104,13 +1103,7 @@ void VM_precache_sound (void) PRVM_G_INT(OFS_RETURN) = PRVM_G_INT(OFS_PARM0); VM_CheckEmptyString (s); - if(S_GetCached(s, true)) - { - Con_Printf("VM_precache_sound: %s already cached (%s)\n", s, PRVM_NAME); - return; - } - - if(!S_PrecacheSound(s,true, true)) + if(!S_PrecacheSound(s,true, true, true)) Con_Printf("VM_precache_sound: Failed to load %s for %s\n", s, PRVM_NAME); } diff --git a/quakedef.h b/quakedef.h index 5165ef93..48a28d3c 100644 --- a/quakedef.h +++ b/quakedef.h @@ -177,8 +177,6 @@ extern char *buildstring; // LordHavoc: increased name limit from 32 to 64 characters #define MAX_SCOREBOARDNAME 64 -#define SOUND_CHANNELS 8 - #include "zone.h" #include "fs.h" #include "common.h" diff --git a/snd_alsa.c b/snd_alsa.c index d3d2d068..031185b6 100644 --- a/snd_alsa.c +++ b/snd_alsa.c @@ -31,7 +31,6 @@ #include "quakedef.h" static int snd_inited; -static int snd_blocked = 0; static snd_pcm_uframes_t buffer_size; static const char *pcmname = NULL; @@ -307,9 +306,6 @@ void SNDDMA_Submit (void) snd_pcm_uframes_t nframes; snd_pcm_uframes_t offset; - if (snd_blocked) - return; - nframes = count / shm->format.channels; snd_pcm_avail_update (pcm); diff --git a/snd_bsd.c b/snd_bsd.c index ce4c26d5..0ca754f1 100644 --- a/snd_bsd.c +++ b/snd_bsd.c @@ -28,6 +28,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include #include "quakedef.h" +#include "snd_main.h" static const int tryrates[] = {44100, 22050, 11025, 8000}; diff --git a/snd_dma.c b/snd_dma.c index a0ffbc86..73c55534 100644 --- a/snd_dma.c +++ b/snd_dma.c @@ -21,6 +21,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" +#include "snd_main.h" +#include "snd_ogg.h" + +// TODO: find a better solution instead of using a define +#if defined( _WIN32 ) && !defined( USE_SDL ) +# define USE_DSOUND +#endif + #ifdef USE_DSOUND #include #include @@ -29,16 +37,12 @@ extern LPDIRECTSOUND pDS; extern LPDIRECTSOUNDBUFFER pDSBuf; #endif -#include "snd_ogg.h" - void S_Play(void); void S_PlayVol(void); void S_Play2(void); void S_SoundList(void); void S_Update_(); -void S_StopAllSounds(qboolean clear); -void S_StopAllSoundsC(void); void S_ClearBuffer (void); @@ -68,12 +72,8 @@ int soundtime; int paintedtime; -//LordHavoc: increased the client sound limit from 512 to 4096 for the Nehahra movie -#define MAX_SFX 4096 -sfx_t *known_sfx; // allocated [MAX_SFX] -int num_sfx; - -sfx_t *ambient_sfx[NUM_AMBIENTS]; +// Linked list of known sfx +sfx_t *known_sfx = NULL; int sound_started = 0; @@ -99,12 +99,10 @@ cvar_t snd_swapstereo = {CVAR_SAVE, "snd_swapstereo", "0"}; // // 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. +// isolating performance in the renderer. // qboolean fakedma = false; -int fakedma_updates = 15; void S_SoundInfo_f(void) @@ -124,19 +122,6 @@ void S_SoundInfo_f(void) Con_Printf("%5u total_channels\n", total_channels); } -void S_UnloadSounds(void) -{ - int i; - for (i = 0;i < num_sfx;i++) - S_UnloadSound(known_sfx + i); -} - -void S_LoadSounds(void) -{ - int i; - for (i = 0;i < num_sfx;i++) - S_LoadSound(known_sfx + i, false); -} void S_Startup(void) { @@ -146,8 +131,7 @@ void S_Startup(void) shm = &sn; memset((void *)shm, 0, sizeof(*shm)); -// create a piece of DMA memory - + // create a piece of DMA memory if (fakedma) { shm->format.width = 2; @@ -172,9 +156,7 @@ void S_Startup(void) Con_DPrintf("Sound sampling rate: %i\n", shm->format.speed); - //S_LoadSounds(); - - S_StopAllSounds(true); + S_StopAllSounds (); } void S_Shutdown(void) @@ -182,8 +164,6 @@ void S_Shutdown(void) if (!sound_started) return; - //S_UnloadSounds(); - if (fakedma) Mem_Free(shm->buffer); else @@ -225,7 +205,7 @@ void S_Init(void) Cmd_AddCommand("play", S_Play); Cmd_AddCommand("play2", S_Play2); Cmd_AddCommand("playvol", S_PlayVol); - Cmd_AddCommand("stopsound", S_StopAllSoundsC); + Cmd_AddCommand("stopsound", S_StopAllSounds); Cmd_AddCommand("soundlist", S_SoundList); Cmd_AddCommand("soundinfo", S_SoundInfo_f); Cmd_AddCommand("snd_restart", S_Restart_f); @@ -240,17 +220,11 @@ void S_Init(void) Cvar_RegisterVariable(&snd_noextraupdate); Cvar_RegisterVariable(&snd_show); Cvar_RegisterVariable(&_snd_mixahead); - Cvar_RegisterVariable(&snd_swapstereo); // LordHavoc: for people with backwards sound wiring + Cvar_RegisterVariable(&snd_swapstereo); // for people with backwards sound wiring Cvar_SetValueQuick(&snd_initialized, true); - known_sfx = Mem_Alloc(snd_mempool, MAX_SFX*sizeof(sfx_t)); - num_sfx = 0; - - SND_InitScaletable (); - - ambient_sfx[AMBIENT_WATER] = S_PrecacheSound ("ambience/water1.wav", false, true); - ambient_sfx[AMBIENT_SKY] = S_PrecacheSound ("ambience/wind2.wav", false, true); + known_sfx = NULL; total_channels = MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS; // no statics memset(channels, 0, MAX_CHANNELS * sizeof(channel_t)); @@ -264,115 +238,125 @@ void S_Init(void) // ======================================================================= /* -========= -S_GetCached +================== +S_FindName -========= +================== */ -sfx_t *S_GetCached (const char *name, qboolean stdpath) +sfx_t *S_FindName (const char *name, qboolean stdpath) { - char namebuffer [MAX_QPATH]; + sfx_t *sfx; size_t len; - int i; + char namebuffer [MAX_QPATH]; if (!snd_initialized.integer) return NULL; - if (!name) - Host_Error("S_GetCached: NULL"); - // Add the default sound directory to the path len = snprintf (namebuffer, sizeof (namebuffer), stdpath ? "sound/%s" : "%s", name); if (len >= sizeof (namebuffer)) - Host_Error ("S_GetCached: sound name too long (%s)", name); + Host_Error ("S_FindName: sound name too long (%s)", name); + + // Look for this sound in the list of known sfx + for (sfx = known_sfx; sfx != NULL; sfx = sfx->next) + if(!strcmp (sfx->name, namebuffer)) + return sfx; - for(i = 0;i < num_sfx;i++) - if(!strcmp(known_sfx[i].name, namebuffer)) - return &known_sfx[i]; + // Add a sfx_t struct for this sound + sfx = Mem_Alloc (snd_mempool, sizeof (*sfx)); + memset (sfx, 0, sizeof(*sfx)); + strlcpy (sfx->name, namebuffer, sizeof (sfx->name)); + sfx->next = known_sfx; + known_sfx = sfx; - return NULL; + return sfx; } + /* ================== -S_FindName +S_FreeSfx ================== */ -sfx_t *S_FindName (const char *name, qboolean stdpath) +void S_FreeSfx (sfx_t *sfx) { - sfx_t *sfx; - - if (!snd_initialized.integer) - return NULL; + // Never free a locked sfx + if (sfx->locks > 0) + return; - sfx = S_GetCached (name, stdpath); + Con_DPrintf ("S_FreeSfx: freeing %s\n", sfx->name); - // If we haven't allocated a sfx_t struct for it yet - if (sfx == NULL) + // Remove it from the list of known sfx + if (sfx == known_sfx) + known_sfx = known_sfx->next; + else { - if (num_sfx == MAX_SFX) - Sys_Error ("S_FindName: out of sfx_t"); + sfx_t *prev_sfx; - sfx = &known_sfx[num_sfx++]; - memset (sfx, 0, sizeof(*sfx)); - snprintf (sfx->name, sizeof (sfx->name), stdpath ? "sound/%s" : "%s", name); + for (prev_sfx = known_sfx; prev_sfx != NULL; prev_sfx = prev_sfx->next) + if (prev_sfx->next == sfx) + { + prev_sfx->next = sfx->next; + break; + } + if (prev_sfx == NULL) + Sys_Error ("S_FreeSfx: Can't find SFX %s in the list!\n", sfx->name); } - return sfx; + + // Free it + Mem_FreePool (&sfx->mempool); + Mem_Free (sfx); } /* ================== -S_TouchSound +S_ServerSounds ================== */ -void S_TouchSound (const char *name, qboolean stdpath) +void S_ServerSounds (char serversound [][MAX_QPATH], unsigned int numsounds) { sfx_t *sfx; + unsigned int i; - sfx = S_FindName (name, stdpath); - - // Set the "used" flag for this sound - if (sfx != NULL) - sfx->flags |= SFXFLAG_USED; -} - - -/* -================== -S_ClearUsed - -Reset the "used" flag of all precached sounds -================== -*/ -void S_ClearUsed (void) -{ - int i; + // Start the ambient sounds and make them loop + channels[AMBIENT_WATER].sfx = S_PrecacheSound ("ambience/water1.wav", false, true, true); + channels[AMBIENT_SKY].sfx = S_PrecacheSound ("ambience/wind2.wav", false, true, true); + for (i = 0; i < NUM_AMBIENTS; i++) + channels[i].flags |= CHANNELFLAG_FORCELOOP; - for (i = 0; i < num_sfx; i++) - known_sfx[i].flags &= ~SFXFLAG_USED; -} + // Remove 1 lock from all sfx with the SFXFLAG_SERVERSOUND flag, and remove the flag + for (sfx = known_sfx; sfx != NULL; sfx = sfx->next) + if (sfx->flags & SFXFLAG_SERVERSOUND) + { + sfx->locks--; + sfx->flags &= ~SFXFLAG_SERVERSOUND; + } + // Add 1 lock and the SFXFLAG_SERVERSOUND flag to each sfx in "serversound" + for (i = 1; i < numsounds; i++) + { + sfx = S_FindName (serversound[i], true); + if (sfx != NULL) + { + sfx->locks++; + sfx->flags |= SFXFLAG_SERVERSOUND; + } + } -/* -================== -S_PurgeUnused + // Free all unlocked sfx + sfx = known_sfx; + while (sfx != NULL) + { + sfx_t* crtsfx; -Free all precached sounds without the "used" flag -================== -*/ -void S_PurgeUnused (void) -{ - int i; - sfx_t *sfx; + // We may lose the "next" pointer after S_FreeSfx + crtsfx = sfx; + sfx = sfx->next; - for (i = 0; i < num_sfx; i++) - { - sfx = &known_sfx[i]; - if (! (sfx->flags & SFXFLAG_USED)) - S_UnloadSound (sfx); + S_FreeSfx (crtsfx); } } @@ -383,7 +367,7 @@ S_PrecacheSound ================== */ -sfx_t *S_PrecacheSound (const char *name, qboolean complain, qboolean stdpath) +sfx_t *S_PrecacheSound (const char *name, qboolean complain, qboolean stdpath, qboolean lock) { sfx_t *sfx; @@ -391,6 +375,11 @@ sfx_t *S_PrecacheSound (const char *name, qboolean complain, qboolean stdpath) return NULL; sfx = S_FindName (name, stdpath); + if (sfx == NULL) + return NULL; + + if (lock) + sfx->locks++; if (!nosound.integer && snd_precache.integer) S_LoadSound(sfx, complain); @@ -398,6 +387,19 @@ sfx_t *S_PrecacheSound (const char *name, qboolean complain, qboolean stdpath) return sfx; } +/* +================== +S_UnlockSfx + +Remove a lock from a SFX and freed it if possible +================== +*/ +void S_UnlockSfx (sfx_t *sfx) +{ + sfx->locks--; + S_FreeSfx (sfx); +} + //============================================================================= @@ -448,8 +450,7 @@ channel_t *SND_PickChannel(int entnum, int entchannel) if (first_to_die == -1) return NULL; - if (channels[first_to_die].sfx) - channels[first_to_die].sfx = NULL; + S_StopChannel (first_to_die); return &channels[first_to_die]; } @@ -461,7 +462,7 @@ SND_Spatialize Spatializes a channel ================= */ -void SND_Spatialize(channel_t *ch, int isstatic) +void SND_Spatialize(channel_t *ch, qboolean isstatic) { vec_t dist, scale, pan; vec3_t source_vec; @@ -496,7 +497,7 @@ void SND_Spatialize(channel_t *ch, int isstatic) ch->rightvol = (int) (scale - pan); } - // LordHavoc: allow adjusting volume of static sounds + // Adjust volume of static sounds if (isstatic) { ch->leftvol *= snd_staticvolume.value; @@ -513,51 +514,57 @@ void SND_Spatialize(channel_t *ch, int isstatic) // Start a sound effect // ======================================================================= -int S_StartSound(int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation) +void S_PlaySfxOnChannel (sfx_t *sfx, channel_t *target_chan, unsigned int flags, vec3_t origin, float fvol, float attenuation, qboolean isstatic) +{ + // Initialize the channel + memset (target_chan, 0, sizeof (*target_chan)); + VectorCopy (origin, target_chan->origin); + target_chan->master_vol = fvol * 255; + target_chan->sfx = sfx; + target_chan->end = paintedtime + sfx->total_length; + target_chan->lastptime = paintedtime; + target_chan->flags = flags; + + // If it's a static sound + if (isstatic) + { + if (sfx->loopstart == -1) + Con_DPrintf("Quake compatibility warning: Static sound \"%s\" is not looped\n", sfx->name); + target_chan->dist_mult = attenuation / (64.0f * sound_nominal_clip_dist); + } + else + target_chan->dist_mult = attenuation / sound_nominal_clip_dist; + + // Lock the SFX during play + sfx->locks++; +} + + +int S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation) { channel_t *target_chan, *check; - int vol; int ch_idx; size_t skip; if (!sound_started || !sfx || !sfx->fetcher || nosound.integer) return -1; - vol = fvol*255; - -// pick a channel to play on + // Pick a channel to play on target_chan = SND_PickChannel(entnum, entchannel); if (!target_chan) return -1; -// spatialize - memset (target_chan, 0, sizeof(*target_chan)); - VectorCopy(origin, target_chan->origin); - target_chan->dist_mult = attenuation / sound_nominal_clip_dist; - target_chan->master_vol = vol; - target_chan->entnum = entnum; - target_chan->entchannel = entchannel; - SND_Spatialize(target_chan, false); - - // LordHavoc: spawn the sound anyway because the player might teleport to it - //if (!target_chan->leftvol && !target_chan->rightvol) - // return; // not audible at all - - // new channel if (!S_LoadSound (sfx, true)) - { - target_chan->sfx = NULL; return -1; // couldn't load the sound's data - } - target_chan->sfx = sfx; - target_chan->flags = CHANNELFLAG_NONE; - target_chan->pos = 0.0; - target_chan->end = paintedtime + sfx->total_length; - target_chan->lastptime = paintedtime; + S_PlaySfxOnChannel (sfx, target_chan, CHANNELFLAG_NONE, origin, fvol, attenuation, false); + target_chan->entnum = entnum; + target_chan->entchannel = entchannel; + + SND_Spatialize(target_chan, false); -// if an identical sound has also been started this frame, offset the pos -// a bit to keep it from just making the first one louder + // if an identical sound has also been started this frame, offset the pos + // a bit to keep it from just making the first one louder check = &channels[NUM_AMBIENTS]; for (ch_idx=NUM_AMBIENTS ; ch_idx < NUM_AMBIENTS + MAX_DYNAMIC_CHANNELS ; ch_idx++, check++) { @@ -565,7 +572,6 @@ int S_StartSound(int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fv continue; if (check->sfx == sfx && !check->pos) { - // LordHavoc: fixed skip calculations skip = 0.1 * sfx->format.speed; if (skip > sfx->total_length) skip = sfx->total_length; @@ -590,31 +596,40 @@ void S_StopChannel (unsigned int channel_ind) ch = &channels[channel_ind]; if (ch->sfx != NULL) { - if (ch->sfx->fetcher != NULL) + sfx_t *sfx = ch->sfx; + + if (sfx->fetcher != NULL) { - snd_fetcher_end_t fetcher_end = ch->sfx->fetcher->end; + snd_fetcher_end_t fetcher_end = sfx->fetcher->end; if (fetcher_end != NULL) fetcher_end (ch); } + + // Remove the lock it holds + S_UnlockSfx (sfx); + ch->sfx = NULL; } ch->end = 0; } -void S_PauseChannel (unsigned int channel_ind, qboolean toggle) -{ - if (toggle) - channels[channel_ind].flags |= CHANNELFLAG_PAUSED; - else - channels[channel_ind].flags &= ~CHANNELFLAG_PAUSED; -} -void S_LoopChannel (unsigned int channel_ind, qboolean toggle) +qboolean S_SetChannelFlag (unsigned int ch_ind, unsigned int flag, qboolean value) { - if (toggle) - channels[channel_ind].flags |= CHANNELFLAG_FORCELOOP; + if (ch_ind >= total_channels) + return false; + + if (flag != CHANNELFLAG_FORCELOOP && + flag != CHANNELFLAG_PAUSED && + flag != CHANNELFLAG_FULLVOLUME) + return false; + + if (value) + channels[ch_ind].flags |= flag; else - channels[channel_ind].flags &= ~CHANNELFLAG_FORCELOOP; + channels[ch_ind].flags &= ~flag; + + return true; } void S_StopSound(int entnum, int entchannel) @@ -629,7 +644,7 @@ void S_StopSound(int entnum, int entchannel) } } -void S_StopAllSounds(qboolean clear) +void S_StopAllSounds (void) { unsigned int i; @@ -639,30 +654,10 @@ void S_StopAllSounds(qboolean clear) total_channels = MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS; // no statics memset(channels, 0, MAX_CHANNELS * sizeof(channel_t)); - if (clear) - S_ClearBuffer(); -} - -void S_StopAllSoundsC(void) -{ - S_StopAllSounds(true); -} - -void S_PauseGameSounds (void) -{ - unsigned int i; - - for (i = 0; i < total_channels; i++) - { - channel_t *ch; - - ch = &channels[i]; - if (ch->sfx != NULL && ! (ch->flags & CHANNELFLAG_LOCALSOUND)) - ch->flags |= CHANNELFLAG_PAUSED; - } + S_ClearBuffer (); } -void S_ResumeGameSounds (void) +void S_PauseGameSounds (qboolean toggle) { unsigned int i; @@ -672,7 +667,7 @@ void S_ResumeGameSounds (void) ch = &channels[i]; if (ch->sfx != NULL && ! (ch->flags & CHANNELFLAG_LOCALSOUND)) - ch->flags &= ~CHANNELFLAG_PAUSED; + S_SetChannelFlag (i, CHANNELFLAG_PAUSED, toggle); } } @@ -730,16 +725,16 @@ void S_ClearBuffer(void) #endif if (shm->buffer) { - int setsize = shm->samples * shm->format.width; - char *buf = shm->buffer; + int setsize = shm->samples * shm->format.width; + unsigned char *buf = shm->buffer; while (setsize--) *buf++ = clear; -// on i586/i686 optimized versions of glibc, glibc *wrongly* IMO, -// reads the memory area before writing to it causing a seg fault -// since the memory is PROT_WRITE only and not PROT_READ|PROT_WRITE -// memset(shm->buffer, clear, shm->samples * shm->samplebits/8); + // on i586/i686 optimized versions of glibc, glibc *wrongly* IMO, + // reads the memory area before writing to it causing a seg fault + // since the memory is PROT_WRITE only and not PROT_READ|PROT_WRITE + //memset(shm->buffer, clear, shm->samples * shm->format.width); } } @@ -749,9 +744,9 @@ void S_ClearBuffer(void) S_StaticSound ================= */ -void S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation) +void S_StaticSound (sfx_t *sfx, vec3_t origin, float fvol, float attenuation) { - channel_t *ss; + channel_t *target_chan; if (!sfx) return; @@ -765,20 +760,10 @@ void S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation) if (!S_LoadSound (sfx, true)) return; - if (sfx->loopstart == -1) - Con_DPrintf("Quake compatibility warning: Static sound \"%s\" is not looped\n", sfx->name); + target_chan = &channels[total_channels++]; + S_PlaySfxOnChannel (sfx, target_chan, CHANNELFLAG_FORCELOOP, origin, fvol, attenuation, true); - ss = &channels[total_channels++]; - memset(ss, 0, sizeof(*ss)); - ss->flags = CHANNELFLAG_FORCELOOP; - ss->sfx = sfx; - VectorCopy (origin, ss->origin); - ss->master_vol = vol; - ss->dist_mult = (attenuation/64) / sound_nominal_clip_dist; - ss->end = paintedtime + sfx->total_length; - ss->lastptime = paintedtime; - - SND_Spatialize (ss, true); + SND_Spatialize (target_chan, true); } @@ -787,6 +772,7 @@ void S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation) /* =================== S_UpdateAmbientSounds + =================== */ void S_UpdateAmbientSounds (void) @@ -796,30 +782,27 @@ void S_UpdateAmbientSounds (void) channel_t *chan; qbyte ambientlevels[NUM_AMBIENTS]; - // LordHavoc: kill ambient sounds until proven otherwise + // Mute ambient sounds until proven otherwise for (ambient_channel = 0 ; ambient_channel < NUM_AMBIENTS;ambient_channel++) - channels[ambient_channel].sfx = NULL; + channels[ambient_channel].master_vol = 0; if (ambient_level.value <= 0 || !cl.worldmodel || !cl.worldmodel->brush.AmbientSoundLevelsForPoint) return; cl.worldmodel->brush.AmbientSoundLevelsForPoint(cl.worldmodel, listener_origin, ambientlevels, sizeof(ambientlevels)); -// calc ambient sound levels + // Calc ambient sound levels for (ambient_channel = 0 ; ambient_channel< NUM_AMBIENTS ; ambient_channel++) { - if (ambient_sfx[ambient_channel] && - (ambient_sfx[ambient_channel]->flags & SFXFLAG_SILENTLYMISSING)) - continue; chan = &channels[ambient_channel]; - chan->flags |= CHANNELFLAG_FORCELOOP; - chan->sfx = ambient_sfx[ambient_channel]; + if (chan->sfx == NULL || (chan->sfx->flags & SFXFLAG_FILEMISSING)) + continue; vol = ambient_level.value * ambientlevels[ambient_channel]; if (vol < 8) vol = 0; - // don't adjust volume too fast + // Don't adjust volume too fast if (chan->master_vol < vol) { chan->master_vol += host_realframetime * ambient_fade.value; @@ -944,7 +927,7 @@ void GetSoundtime(void) { // time to chop things off to avoid 32 bit limits buffers = 0; paintedtime = fullsamples; - S_StopAllSounds (true); + S_StopAllSounds (); } } oldsamplepos = samplepos; @@ -952,15 +935,8 @@ void GetSoundtime(void) soundtime = buffers * fullsamples + samplepos / shm->format.channels; } -void IN_Accumulate (void); - void S_ExtraUpdate (void) { - -#ifdef USE_DSOUND - IN_Accumulate (); -#endif - if (snd_noextraupdate.integer) return; // don't pollute timings S_Update_(); @@ -1032,7 +1008,7 @@ static void S_Play_Common(float fvol, float attenuation) snprintf(name, sizeof(name), "%s.wav", Cmd_Argv(i)); else strlcpy(name, Cmd_Argv(i), sizeof(name)); - sfx = S_PrecacheSound(name, true, true); + sfx = S_PrecacheSound(name, true, true, false); // If we need to get the volume from the command line if (fvol == -1.0f) @@ -1044,7 +1020,11 @@ static void S_Play_Common(float fvol, float attenuation) i++; ch_ind = S_StartSound(-1, 0, sfx, listener_origin, fvol, attenuation); - if (ch_ind >= 0) + + // Free the sfx if the file didn't exist + if (ch_ind < 0) + S_FreeSfx (sfx); + else channels[ch_ind].flags |= CHANNELFLAG_LOCALSOUND; } } @@ -1066,12 +1046,12 @@ void S_PlayVol(void) void S_SoundList(void) { - int i; + unsigned int i; sfx_t *sfx; int size, total; total = 0; - for (sfx=known_sfx, i=0 ; inext, i++) { if (sfx->fetcher != NULL) { @@ -1081,7 +1061,7 @@ void S_SoundList(void) (sfx->loopstart >= 0) ? 'L' : ' ', (sfx->flags & SFXFLAG_STREAMED) ? 'S' : ' ', sfx->format.width * 8, - (sfx->format.channels == 2) ? "stereo" : "mono", + (sfx->format.channels == 1) ? "mono" : "stereo", size, sfx->name); } @@ -1090,22 +1070,25 @@ void S_SoundList(void) } -void S_LocalSound (const char *sound, qboolean stdpath) +qboolean S_LocalSound (const char *sound, qboolean stdpath) { sfx_t *sfx; int ch_ind; if (!snd_initialized.integer || nosound.integer) - return; + return true; - sfx = S_PrecacheSound (sound, true, stdpath); + sfx = S_PrecacheSound (sound, true, stdpath, false); if (!sfx) { Con_Printf("S_LocalSound: can't precache %s\n", sound); - return; + return false; } ch_ind = S_StartSound (cl.viewentity, 0, sfx, vec3_origin, 1, 1); - if (ch_ind >= 0) - channels[ch_ind].flags |= CHANNELFLAG_LOCALSOUND; + if (ch_ind < 0) + return false; + + channels[ch_ind].flags |= CHANNELFLAG_LOCALSOUND; + return true; } diff --git a/snd_main.h b/snd_main.h new file mode 100644 index 00000000..d9ecb0c6 --- /dev/null +++ b/snd_main.h @@ -0,0 +1,143 @@ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifndef SND_MAIN_H +#define SND_MAIN_H + +#include "sound.h" + + +typedef struct +{ + size_t length; + size_t offset; + qbyte data[4]; // variable sized +} sfxbuffer_t; + +typedef struct +{ + unsigned int speed; + unsigned int width; + unsigned int channels; +} snd_format_t; + +// sfx_t flags +#define SFXFLAG_NONE 0 +#define SFXFLAG_FILEMISSING (1 << 0) // wasn't able to load the associated sound file +#define SFXFLAG_SERVERSOUND (1 << 1) // the sfx is part of the server precache list +#define SFXFLAG_STREAMED (1 << 2) // informative only. You shouldn't need to know that + +typedef struct snd_fetcher_s snd_fetcher_t; +struct sfx_s +{ + char name[MAX_QPATH]; + sfx_t *next; + mempool_t *mempool; + unsigned int locks; // A locked sfx_t must not be freed. + // Locks are added by S_PrecacheSound and S_ServerSounds. + // SFX can be freed by S_UnlockSfx or S_ServerSounds. + unsigned int flags; // cf SFXFLAG_* defines + snd_format_t format; + int loopstart; + size_t total_length; + const snd_fetcher_t *fetcher; + void *fetcher_data; // Per-sfx data for the sound fetching functions +}; + +typedef struct +{ + snd_format_t format; + int samples; // mono samples in buffer + int samplepos; // in mono samples + unsigned char *buffer; + int bufferlength; // used only by certain drivers +} dma_t; + +typedef struct +{ + sfx_t *sfx; // sfx number + unsigned int flags; // cf CHANNELFLAG_* defines + int master_vol; // 0-255 master volume + int leftvol; // 0-255 volume + int rightvol; // 0-255 volume + int end; // end time in global paintsamples + int lastptime; // last time this channel was painted + int pos; // sample position in sfx + int entnum; // to allow overriding a specific sound + int entchannel; + vec3_t origin; // origin of sound effect + vec_t dist_mult; // distance multiplier (attenuation/clipK) + void *fetcher_data; // Per-channel data for the sound fetching function +} channel_t; + +typedef const sfxbuffer_t* (*snd_fetcher_getsb_t) (channel_t* ch, unsigned int start, unsigned int nbsamples); +typedef void (*snd_fetcher_end_t) (channel_t* ch); +struct snd_fetcher_s +{ + snd_fetcher_getsb_t getsb; + snd_fetcher_end_t end; +}; + +void S_PaintChannels(int endtime); + +// initializes cycling through a DMA buffer and returns information on it +qboolean SNDDMA_Init(void); + +// gets the current DMA position +int SNDDMA_GetDMAPos(void); + +void SNDDMA_Submit(void); + +// shutdown the DMA xfer. +void SNDDMA_Shutdown(void); + +qboolean S_LoadSound (sfx_t *s, qboolean complain); +void S_UnloadSound(sfx_t *s); + +void *S_LockBuffer(void); +void S_UnlockBuffer(void); + +extern size_t ResampleSfx (const qbyte *in_data, size_t in_length, const snd_format_t* in_format, qbyte *out_data, const char* sfxname); + +// ==================================================================== +// User-setable variables +// ==================================================================== + +// 0 to NUM_AMBIENTS - 1 = water, etc +// NUM_AMBIENTS to NUM_AMBIENTS + MAX_DYNAMIC_CHANNELS - 1 = normal entity sounds +// NUM_AMBIENTS + MAX_DYNAMIC_CHANNELS to total_channels = static sounds +#define MAX_CHANNELS 516 +#define MAX_DYNAMIC_CHANNELS 128 + +extern channel_t channels[MAX_CHANNELS]; + +extern unsigned int total_channels; + +extern int paintedtime; +extern int soundtime; +extern volatile dma_t *shm; + +extern cvar_t snd_swapstereo; +extern cvar_t snd_streaming; + +extern int snd_blocked; + + +#endif diff --git a/snd_mem.c b/snd_mem.c index f61a5a98..2ef31444 100644 --- a/snd_mem.c +++ b/snd_mem.c @@ -21,6 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" +#include "snd_main.h" #include "snd_ogg.h" #include "snd_wav.h" @@ -156,9 +157,14 @@ qboolean S_LoadSound (sfx_t *s, qboolean complain) size_t len; qboolean modified_name = false; - // see if still in memory if (!shm || !shm->format.speed) return false; + + // If we wasn't able to load it previously, no need to retry + if (s->flags & SFXFLAG_FILEMISSING) + return false; + + // See if in memory if (s->fetcher != NULL) { if (s->format.speed != shm->format.speed) @@ -184,10 +190,7 @@ qboolean S_LoadSound (sfx_t *s, qboolean complain) return true; // Can't load the sound! - if (!complain) - s->flags |= SFXFLAG_SILENTLYMISSING; - else - s->flags &= ~SFXFLAG_SILENTLYMISSING; + s->flags |= SFXFLAG_FILEMISSING; if (complain) { if (modified_name) @@ -197,20 +200,19 @@ qboolean S_LoadSound (sfx_t *s, qboolean complain) return false; } -void S_UnloadSound(sfx_t *s) +void S_UnloadSound (sfx_t *s) { if (s->fetcher != NULL) { unsigned int i; + // Stop all channels that use this sound + for (i = 0; i < total_channels ; i++) + if (channels[i].sfx == s) + S_StopChannel (i); + s->fetcher = NULL; s->fetcher_data = NULL; Mem_FreePool(&s->mempool); - - // At this point, some per-channel data pointers may point to freed zones. - // Practically, it shouldn't be a problem; but it's wrong, so we fix that - for (i = 0; i < total_channels ; i++) - if (channels[i].sfx == s) - channels[i].fetcher_data = NULL; } } diff --git a/snd_mix.c b/snd_mix.c index efd562c2..4e42a967 100644 --- a/snd_mix.c +++ b/snd_mix.c @@ -20,6 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // snd_mix.c -- portable code to mix sounds for snd_dma.c #include "quakedef.h" +#include "snd_main.h" typedef struct { @@ -30,7 +31,6 @@ typedef struct // LordHavoc: was 512, expanded to 2048 #define PAINTBUFFER_SIZE 2048 portable_samplepair_t paintbuffer[PAINTBUFFER_SIZE]; -int snd_scaletable[32][256]; // FIXME: it desyncs with the video too easily extern cvar_t cl_avidemo; @@ -111,6 +111,7 @@ void S_CaptureAVISound(portable_samplepair_t *buf, size_t length) } } +// TODO: rewrite this function void S_TransferPaintBuffer(int endtime) { void *pbuf; @@ -118,12 +119,10 @@ void S_TransferPaintBuffer(int endtime) { int i; int *snd_p; - int snd_vol; int lpaintedtime; int snd_linear_count; int val; snd_p = (int *) paintbuffer; - snd_vol = volume.value*256; lpaintedtime = paintedtime; if (shm->format.width == 2) { @@ -145,20 +144,16 @@ void S_TransferPaintBuffer(int endtime) { for (i = 0;i < snd_linear_count;i += 2) { - val = (snd_p[i + 1] * snd_vol) >> 8; - snd_out[i ] = bound(-32768, val, 32767); - val = (snd_p[i ] * snd_vol) >> 8; - snd_out[i + 1] = bound(-32768, val, 32767); + snd_out[i ] = bound(-32768, snd_p[i + 1], 32767); + snd_out[i + 1] = bound(-32768, snd_p[i ], 32767); } } else { for (i = 0;i < snd_linear_count;i += 2) { - val = (snd_p[i ] * snd_vol) >> 8; - snd_out[i ] = bound(-32768, val, 32767); - val = (snd_p[i + 1] * snd_vol) >> 8; - snd_out[i + 1] = bound(-32768, val, 32767); + snd_out[i ] = bound(-32768, snd_p[i ], 32767); + snd_out[i + 1] = bound(-32768, snd_p[i + 1], 32767); } } snd_p += snd_linear_count; @@ -178,7 +173,7 @@ void S_TransferPaintBuffer(int endtime) snd_linear_count = endtime - lpaintedtime; for (i = 0;i < snd_linear_count;i++) { - val = ((snd_p[i * 2 + 0] + snd_p[i * 2 + 1]) * snd_vol) >> 9; + val = (snd_p[i * 2 + 0] + snd_p[i * 2 + 1]) >> 1; snd_out[i] = bound(-32768, val, 32767); } snd_p += snd_linear_count << 1; @@ -206,9 +201,9 @@ void S_TransferPaintBuffer(int endtime) { for (i = 0;i < snd_linear_count;i += 2) { - val = ((snd_p[i + 1] * snd_vol) >> 16) + 128; + val = (snd_p[i + 1] >> 8) + 128; snd_out[i ] = bound(0, val, 255); - val = ((snd_p[i ] * snd_vol) >> 16) + 128; + val = (snd_p[i ] >> 8) + 128; snd_out[i + 1] = bound(0, val, 255); } } @@ -216,9 +211,9 @@ void S_TransferPaintBuffer(int endtime) { for (i = 0;i < snd_linear_count;i += 2) { - val = ((snd_p[i ] * snd_vol) >> 16) + 128; + val = (snd_p[i ] >> 8) + 128; snd_out[i ] = bound(0, val, 255); - val = ((snd_p[i + 1] * snd_vol) >> 16) + 128; + val = (snd_p[i + 1] >> 8) + 128; snd_out[i + 1] = bound(0, val, 255); } } @@ -239,7 +234,7 @@ void S_TransferPaintBuffer(int endtime) snd_linear_count = endtime - lpaintedtime; for (i = 0;i < snd_linear_count;i++) { - val = (((snd_p[i * 2] + snd_p[i * 2 + 1]) * snd_vol) >> 17) + 128; + val = ((snd_p[i * 2] + snd_p[i * 2 + 1]) >> 9) + 128; snd_out[i ] = bound(0, val, 255); } snd_p += snd_linear_count << 1; @@ -325,7 +320,7 @@ void S_PaintChannels(int endtime) // If the sound is looped if (loopstart >= 0) ch->pos = (ch->pos - sfx->total_length) % (sfx->total_length - loopstart) + loopstart; - else + else ch->pos = sfx->total_length; ch->end = paintedtime + sfx->total_length - ch->pos; } @@ -350,9 +345,9 @@ void S_PaintChannels(int endtime) ch->rightvol = 255; if (sfx->format.width == 1) - stop_paint = !SND_PaintChannelFrom8(ch, count); + stop_paint = !SND_PaintChannelFrom8 (ch, count); else - stop_paint = !SND_PaintChannelFrom16(ch, count); + stop_paint = !SND_PaintChannelFrom16 (ch, count); if (!stop_paint) { @@ -391,48 +386,45 @@ void S_PaintChannels(int endtime) } } -void SND_InitScaletable (void) -{ - int i, j; - - for (i = 0;i < 32;i++) - for (j = 0;j < 256;j++) - snd_scaletable[i][j] = ((signed char)j) * i * 8; -} - +// TODO: Try to merge SND_PaintChannelFrom8 and SND_PaintChannelFrom16 qboolean SND_PaintChannelFrom8 (channel_t *ch, int count) { - int *lscale, *rscale; - unsigned char *sfx; + int snd_vol, leftvol, rightvol; + const signed char *sfx; const sfxbuffer_t *sb; - int i, n; + int i; + + // If this channel manages its own volume + if (ch->flags & CHANNELFLAG_FULLVOLUME) + snd_vol = 256; + else + snd_vol = volume.value * 256; - lscale = snd_scaletable[ch->leftvol >> 3]; - rscale = snd_scaletable[ch->rightvol >> 3]; + leftvol = ch->leftvol * snd_vol; + rightvol = ch->rightvol * snd_vol; sb = ch->sfx->fetcher->getsb (ch, ch->pos, count); if (sb == NULL) return false; + // Stereo sound support if (ch->sfx->format.channels == 2) { - // LordHavoc: stereo sound support, and optimizations - sfx = (unsigned char *)sb->data + (ch->pos - sb->offset) * 2; + sfx = sb->data + (ch->pos - sb->offset) * 2; for (i = 0;i < count;i++) { - paintbuffer[i].left += lscale[*sfx++]; - paintbuffer[i].right += rscale[*sfx++]; + paintbuffer[i].left += (*sfx++ * leftvol) >> 8; + paintbuffer[i].right += (*sfx++ * rightvol) >> 8; } } else { - sfx = (unsigned char *)sb->data + ch->pos - sb->offset; + sfx = sb->data + ch->pos - sb->offset; for (i = 0;i < count;i++) { - n = *sfx++; - paintbuffer[i].left += lscale[n]; - paintbuffer[i].right += rscale[n]; + paintbuffer[i].left += (*sfx * leftvol) >> 8; + paintbuffer[i].right += (*sfx++ * rightvol) >> 8; } } @@ -442,27 +434,33 @@ qboolean SND_PaintChannelFrom8 (channel_t *ch, int count) qboolean SND_PaintChannelFrom16 (channel_t *ch, int count) { - int leftvol, rightvol; + int snd_vol, leftvol, rightvol; signed short *sfx; const sfxbuffer_t *sb; int i; - leftvol = ch->leftvol; - rightvol = ch->rightvol; + // If this channel manages its own volume + if (ch->flags & CHANNELFLAG_FULLVOLUME) + snd_vol = 256; + else + snd_vol = volume.value * 256; + + leftvol = ch->leftvol * snd_vol; + rightvol = ch->rightvol * snd_vol; sb = ch->sfx->fetcher->getsb (ch, ch->pos, count); if (sb == NULL) return false; + // Stereo sound support if (ch->sfx->format.channels == 2) { - // LordHavoc: stereo sound support, and optimizations sfx = (signed short *)sb->data + (ch->pos - sb->offset) * 2; for (i=0 ; i> 8; - paintbuffer[i].right += (*sfx++ * rightvol) >> 8; + paintbuffer[i].left += (*sfx++ * leftvol) >> 16; + paintbuffer[i].right += (*sfx++ * rightvol) >> 16; } } else @@ -471,8 +469,8 @@ qboolean SND_PaintChannelFrom16 (channel_t *ch, int count) for (i=0 ; i> 8; - paintbuffer[i].right += (*sfx++ * rightvol) >> 8; + paintbuffer[i].left += (*sfx * leftvol) >> 16; + paintbuffer[i].right += (*sfx++ * rightvol) >> 16; } } diff --git a/snd_null.c b/snd_null.c index df43df4f..6e089e6f 100755 --- a/snd_null.c +++ b/snd_null.c @@ -44,23 +44,15 @@ void S_Shutdown (void) { } -void S_TouchSound (const char *sample, qboolean stdpath) +void S_ServerSounds (char serversound [][MAX_QPATH], unsigned int numsounds) { } -void S_ClearUsed (void) +void S_StaticSound (sfx_t *sfx, vec3_t origin, float fvol, float attenuation) { } -void S_PurgeUnused (void) -{ -} - -void S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation) -{ -} - -int S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation) +int S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation) { return -1; } @@ -69,23 +61,16 @@ void S_StopChannel (unsigned int channel_ind) { } -void S_PauseChannel (unsigned int channel_ind, qboolean toggle) -{ -} - -void S_LoopChannel (unsigned int channel_ind, qboolean toggle) +qboolean S_SetChannelFlag (unsigned int ch_ind, unsigned int flag, qboolean value) { + return false; } void S_StopSound (int entnum, int entchannel) { } -void S_PauseGameSounds (void) -{ -} - -void S_ResumeGameSounds (void) +void S_PauseGameSounds (qboolean toggle) { } @@ -93,21 +78,20 @@ void S_SetChannelVolume (unsigned int ch_ind, float fvol) { } -sfx_t *S_GetCached(const char *name, qboolean stdpath) +sfx_t *S_PrecacheSound (const char *sample, qboolean complain, qboolean stdpath, qboolean lock) { return NULL; } -sfx_t *S_PrecacheSound (const char *sample, qboolean complain, qboolean stdpath) +void S_UnlockSfx (sfx_t *sfx) { - return NULL; } void S_Update(const matrix4x4_t *matrix) { } -void S_StopAllSounds (qboolean clear) +void S_StopAllSounds (void) { } @@ -115,6 +99,7 @@ void S_ExtraUpdate (void) { } -void S_LocalSound (const char *s, qboolean stdpath) +qboolean S_LocalSound (const char *s, qboolean stdpath) { + return false; } diff --git a/snd_ogg.c b/snd_ogg.c index fa64393b..74a2e193 100644 --- a/snd_ogg.c +++ b/snd_ogg.c @@ -23,6 +23,7 @@ #include "quakedef.h" +#include "snd_main.h" #include "snd_ogg.h" #include "snd_wav.h" @@ -587,7 +588,7 @@ qboolean OGG_LoadVorbisFile (const char *filename, sfx_t *s) long ret; sfxbuffer_t *sb; - Con_DPrintf ("\"%s\" will be streamed\n", filename); + Con_DPrintf ("\"%s\" will be cached\n", filename); // Decode it buff = Mem_Alloc (s->mempool, (int)len); diff --git a/snd_oss.c b/snd_oss.c index c2ae5101..bdb8afcf 100644 --- a/snd_oss.c +++ b/snd_oss.c @@ -28,6 +28,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include #include #include "quakedef.h" +#include "snd_main.h" int audio_fd; int snd_inited; diff --git a/snd_sdl.c b/snd_sdl.c index 5dcaf529..4b262a69 100644 --- a/snd_sdl.c +++ b/snd_sdl.c @@ -17,6 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "quakedef.h" +#include "snd_main.h" #include /* diff --git a/snd_wav.c b/snd_wav.c index 8d4f986b..3904df50 100644 --- a/snd_wav.c +++ b/snd_wav.c @@ -23,6 +23,7 @@ #include "quakedef.h" +#include "snd_main.h" #include "snd_wav.h" diff --git a/snd_win.c b/snd_win.c index a66bae5c..d031645b 100644 --- a/snd_win.c +++ b/snd_win.c @@ -18,6 +18,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "quakedef.h" +#include "snd_main.h" #include #include diff --git a/sound.h b/sound.h index ecbdb78a..27682799 100644 --- a/sound.h +++ b/sound.h @@ -17,183 +17,67 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -// sound.h -- client sound i/o functions #ifndef SOUND_H #define SOUND_H #include "matrixlib.h" -//AK: TODO: find a better solution instead of using a define -#if defined( _WIN32 ) && !defined( USE_SDL ) -# define USE_DSOUND -#endif + +// ==================================================================== +// Constants +// ==================================================================== #define DEFAULT_SOUND_PACKET_VOLUME 255 #define DEFAULT_SOUND_PACKET_ATTENUATION 1.0 -typedef struct -{ - size_t length; - size_t offset; - qbyte data[4]; // variable sized -} sfxbuffer_t; - -typedef struct -{ - unsigned int speed; - unsigned int width; - unsigned int channels; -} snd_format_t; - -// sfx_t flags -#define SFXFLAG_NONE 0 -#define SFXFLAG_SILENTLYMISSING (1 << 0) // if the sfx is missing and loaded with complain = false -#define SFXFLAG_USED (1 << 1) -#define SFXFLAG_STREAMED (1 << 2) // informative only. You shouldn't need to know that - -typedef struct snd_fetcher_s snd_fetcher_t; -typedef struct sfx_s -{ - char name[MAX_QPATH]; - mempool_t *mempool; - unsigned int flags; // cf SFXFLAG_* defines - snd_format_t format; - int loopstart; - size_t total_length; - const snd_fetcher_t *fetcher; - void *fetcher_data; // Per-sfx data for the sound fetching functions -} sfx_t; - -typedef struct -{ - snd_format_t format; - int samples; // mono samples in buffer - int samplepos; // in mono samples - unsigned char *buffer; - int bufferlength; // used only by certain drivers -} dma_t; - -// channel_t flags +// Channel flags #define CHANNELFLAG_NONE 0 #define CHANNELFLAG_FORCELOOP (1 << 0) // force looping even if the sound is not looped -#define CHANNELFLAG_LOCALSOUND (1 << 1) // non-game sound (ex: menu sound) +#define CHANNELFLAG_LOCALSOUND (1 << 1) // INTERNAL USE. Not settable by S_SetChannelFlag #define CHANNELFLAG_PAUSED (1 << 2) +#define CHANNELFLAG_FULLVOLUME (1 << 3) // isn't affected by the general volume -typedef struct -{ - sfx_t *sfx; // sfx number - unsigned int flags; // cf CHANNELFLAG_* defines - int leftvol; // 0-255 volume - int rightvol; // 0-255 volume - int end; // end time in global paintsamples - int lastptime; // last time this channel was painted - int pos; // sample position in sfx - int looping; // where to loop, -1 = no looping - int entnum; // to allow overriding a specific sound - int entchannel; - vec3_t origin; // origin of sound effect - vec_t dist_mult; // distance multiplier (attenuation/clipK) - int master_vol; // 0-255 master volume - void *fetcher_data; // Per-channel data for the sound fetching function -} channel_t; - -typedef const sfxbuffer_t* (*snd_fetcher_getsb_t) (channel_t* ch, unsigned int start, unsigned int nbsamples); -typedef void (*snd_fetcher_end_t) (channel_t* ch); -struct snd_fetcher_s -{ - snd_fetcher_getsb_t getsb; - snd_fetcher_end_t end; -}; - -void S_Init (void); -void S_Startup (void); -void S_Shutdown (void); -// S_StartSound returns the channel index, or -1 if an error occurred -int S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation); -void S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation); -void S_StopChannel (unsigned int channel_ind); -void S_PauseChannel (unsigned int channel_ind, qboolean toggle); -void S_LoopChannel (unsigned int channel_ind, qboolean toggle); -void S_StopSound (int entnum, int entchannel); -void S_StopAllSounds(qboolean clear); -void S_PauseGameSounds (void); -void S_ResumeGameSounds (void); -void S_SetChannelVolume (unsigned int ch_ind, float fvol); -void S_Update(const matrix4x4_t *listenermatrix); -void S_ExtraUpdate (void); - -sfx_t *S_GetCached(const char *name, qboolean stdpath); -sfx_t *S_PrecacheSound (const char *sample, qboolean complain, qboolean stdpath); -void S_TouchSound (const char *sample, qboolean stdpath); -void S_ClearUsed (void); -void S_PurgeUnused (void); -void S_PaintChannels(int endtime); -void S_InitPaintChannels (void); - -// initializes cycling through a DMA buffer and returns information on it -qboolean SNDDMA_Init(void); - -// gets the current DMA position -int SNDDMA_GetDMAPos(void); - -// shutdown the DMA xfer. -void SNDDMA_Shutdown(void); - -extern size_t ResampleSfx (const qbyte *in_data, size_t in_length, const snd_format_t* in_format, qbyte *out_data, const char* sfxname); // ==================================================================== -// User-setable variables +// Types and variables // ==================================================================== -// LordHavoc: increased from 128 to 516 (4 for NUM_AMBIENTS) -#define MAX_CHANNELS 516 -// LordHavoc: increased maximum sound channels from 8 to 128 -#define MAX_DYNAMIC_CHANNELS 128 +typedef struct sfx_s sfx_t; +extern cvar_t bgmvolume; +extern cvar_t volume; +extern cvar_t snd_initialized; +extern cvar_t snd_staticvolume; -extern channel_t channels[MAX_CHANNELS]; -// 0 to MAX_DYNAMIC_CHANNELS-1 = normal entity sounds -// MAX_DYNAMIC_CHANNELS to MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS -1 = water, etc -// MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS to total_channels = static sounds - -extern unsigned int total_channels; -// -// 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. -// +// ==================================================================== +// Functions +// ==================================================================== -extern qboolean fakedma; -extern int fakedma_updates; -extern int paintedtime; -extern int soundtime; -extern vec3_t listener_vieworigin; -extern vec3_t listener_viewforward; -extern vec3_t listener_viewleft; -extern vec3_t listener_viewup; -extern volatile dma_t *shm; -extern vec_t sound_nominal_clip_dist; +void S_Init (void); +void S_Startup (void); +void S_Shutdown (void); -extern cvar_t bgmvolume; -extern cvar_t volume; -extern cvar_t snd_swapstereo; +void S_Update(const matrix4x4_t *listenermatrix); +void S_ExtraUpdate (void); -extern cvar_t cdaudioinitialized; -extern cvar_t snd_initialized; -extern cvar_t snd_streaming; +sfx_t *S_PrecacheSound (const char *sample, qboolean complain, qboolean stdpath, qboolean lock); +void S_ServerSounds (char serversound [][MAX_QPATH], unsigned int numsounds); +void S_UnlockSfx (sfx_t *sfx); -extern int snd_blocked; +// S_StartSound returns the channel index, or -1 if an error occurred +int S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation); +qboolean S_LocalSound (const char *s, qboolean stdpath); -void S_LocalSound (const char *s, qboolean stdpath); -qboolean S_LoadSound (sfx_t *s, qboolean complain); -void S_UnloadSound(sfx_t *s); +void S_StaticSound (sfx_t *sfx, vec3_t origin, float fvol, float attenuation); +void S_StopSound (int entnum, int entchannel); +void S_StopAllSounds (void); +void S_PauseGameSounds (qboolean toggle); -void SND_InitScaletable (void); -void SNDDMA_Submit(void); +void S_StopChannel (unsigned int channel_ind); +qboolean S_SetChannelFlag (unsigned int ch_ind, unsigned int flag, qboolean value); +void S_SetChannelVolume (unsigned int ch_ind, float fvol); -void *S_LockBuffer(void); -void S_UnlockBuffer(void); #endif diff --git a/todo b/todo index fd6fb6d9..b0412486 100644 --- a/todo +++ b/todo @@ -2,6 +2,7 @@ -(Baalz) d darkplaces input bug: figure out what's wrong with ctrl key in Linux, hitting character keys tends to do nothing, and holding a character key and then hitting ctrl tends to leave the character key stuck on, this sounds like a window manager issue, but somehow quake3 works around it (Baalz) -(Kinn) d darkplaces client: all glow trails are bright blue (Kinn) -(Kinn) d darkplaces renderer: fix the sometimes non-animating framegroups on sprites (Kinn) +-(fuh) d darkplaces sound: make sound precaching not allocate an sfx if the sound is not found, so it complains only once about missing sounds when you connect, rather than constantly, and also so using "play" commands for non-existent files won't eat up sfx slots (fuh) 0 darkplaces client: add DP_LITSPRITES extension to document the fact that any sprite with a ! in its filename is lit rather than fullbright 0 darkplaces client: add a swinging weapon motion to replace the removed forward/back movement of the weapon, should be controllable with cl_bob_* cvars (Joel Murdoch) 0 darkplaces client: add back cl_particles_lighting cvar and add back the particle lighting (romi) @@ -87,8 +88,6 @@ 0 darkplaces server: make fopen have the ability to disable fopen builtin access to read /, read data/, write data/, or disable fopen builtin entirely 0 darkplaces server: make server able to work without models, just for sake of completeness 0 darkplaces sound: Lordhavoc needs to talk to fuh about snd_macos.c (fuh) -0 darkplaces sound: make sound precaching not allocate an sfx if the sound is not found, so it complains only once about missing sounds when you connect, rather than constantly, and also so using "play" commands for non-existent files won't eat up sfx slots (fuh) -0 darkplaces sound: non-cd music tracks should not be affected by sound volume setting (Urre) 0 darkplaces sound: the new sound engine should have a cvar for random variations of pitch on sounds like in doom (RenegadeC) 0 dpmod: add flame thrower enforcers back (scar3crow) 0 dpmod: add flame thrower weapon, and make its altfire drop a canister of fuel (10 fuel units?), which can be ignited to set off as a bomb about the size of a rocket blast, plus some fireballs raining down (scar3crow) @@ -415,6 +414,7 @@ d darkplaces server: make qc profile command post an error message instead of cr d darkplaces server: prevent player name changes faster than once every 5 seconds (sublim3) d darkplaces server: stop sound before loading a level to get rid of looping noise (Edward Holness) d darkplaces sound: dsound broken, needs to be managed as part of video system (jeremy janzen) +d darkplaces sound: non-cd music tracks should not be affected by sound volume setting (Urre) d darkplaces video: add vid_vsync cvar and also to options menu (metlslime) d darkplaces: Host_Name_f validate player names, stripping \r and \n d darkplaces: PF_traceline/PF_tracebox now work with world as the edict diff --git a/vid_wgl.c b/vid_wgl.c index 8f9c2dc8..2200c87e 100644 --- a/vid_wgl.c +++ b/vid_wgl.c @@ -79,7 +79,6 @@ static DEVMODE gdevmode; static qboolean vid_initialized = false; static qboolean vid_wassuspended = false; static int vid_usingmouse; -extern qboolean mouseactive; // from in_win.c static HICON hIcon; HWND mainwindow; @@ -145,7 +144,7 @@ HRESULT (WINAPI *pDirectInputCreate)(HINSTANCE hinst, DWORD dwVersion, int mouse_buttons; int mouse_oldbuttonstate; POINT current_pos; -int mouse_x, mouse_y, old_mouse_x, old_mouse_y, mx_accum, my_accum; +int mouse_x, mouse_y, old_mouse_x, old_mouse_y; static qboolean restore_spi; static int originalmouseparms[3], newmouseparms[3] = {0, 0, 1}; @@ -1453,10 +1452,8 @@ void IN_MouseMove (usercmd_t *cmd) else { GetCursorPos (¤t_pos); - mx = current_pos.x - window_center_x + mx_accum; - my = current_pos.y - window_center_y + my_accum; - mx_accum = 0; - my_accum = 0; + mx = current_pos.x - window_center_x; + my = current_pos.y - window_center_y; } IN_Mouse(cmd, mx, my); @@ -1482,29 +1479,6 @@ void IN_Move (usercmd_t *cmd) } -/* -=========== -IN_Accumulate -=========== -*/ -void IN_Accumulate (void) -{ - if (mouseactive) - { - if (!dinput) - { - GetCursorPos (¤t_pos); - - mx_accum += current_pos.x - window_center_x; - my_accum += current_pos.y - window_center_y; - - // force the mouse to the center, so there's room to move - SetCursorPos (window_center_x, window_center_y); - } - } -} - - /* =================== IN_ClearStates @@ -1513,11 +1487,7 @@ IN_ClearStates void IN_ClearStates (void) { if (mouseactive) - { - mx_accum = 0; - my_accum = 0; mouse_oldbuttonstate = 0; - } } -- 2.39.2