cvar_t bgmvolume = {CVAR_SAVE, "bgmvolume", "1"};
cvar_t volume = {CVAR_SAVE, "volume", "0.7"};
+cvar_t snd_staticvolume = {CVAR_SAVE, "snd_staticvolume", "1"};
cvar_t nosound = {0, "nosound", "0"};
-cvar_t precache = {0, "precache", "1"};
+cvar_t snd_precache = {0, "snd_precache", "1"};
cvar_t bgmbuffer = {0, "bgmbuffer", "4096"};
cvar_t ambient_level = {0, "ambient_level", "0.3"};
cvar_t ambient_fade = {0, "ambient_fade", "100"};
*/
void S_Init (void)
{
- Con_Printf("\nSound Initialization\n");
+ Con_DPrintf("\nSound Initialization\n");
S_RawSamples_ClearQueue();
Cvar_RegisterVariable(&volume);
Cvar_RegisterVariable(&bgmvolume);
+ Cvar_RegisterVariable(&snd_staticvolume);
if (COM_CheckParm("-nosound") || COM_CheckParm("-safe"))
return;
Cmd_AddCommand("soundinfo", S_SoundInfo_f);
Cvar_RegisterVariable(&nosound);
- Cvar_RegisterVariable(&precache);
+ Cvar_RegisterVariable(&snd_precache);
Cvar_RegisterVariable(&bgmbuffer);
Cvar_RegisterVariable(&ambient_level);
Cvar_RegisterVariable(&ambient_fade);
if (!sound_started)
return;
- Con_Printf ("Sound sampling rate: %i\n", shm->speed);
+ Con_DPrintf ("Sound sampling rate: %i\n", shm->speed);
// provides a tick sound until washed clean
Sys_Error ("S_FindName: out of sfx_t");
sfx = &known_sfx[i];
+ memset(sfx, 0, sizeof(*sfx));
strcpy (sfx->name, name);
num_sfx++;
void S_TouchSound (char *name)
{
sfx_t *sfx;
-
+
if (!sound_started)
return;
sfx = S_FindName (name);
// cache it in
- if (precache.integer)
+ if (snd_precache.integer)
S_LoadSound (sfx, complain);
return sfx;
*/
channel_t *SND_PickChannel(int entnum, int entchannel)
{
- int ch_idx;
- int first_to_die;
- int life_left;
+ int ch_idx;
+ int first_to_die;
+ int life_left;
// Check for replacement sound, or find the best one to replace
- first_to_die = -1;
- life_left = 0x7fffffff;
- for (ch_idx=NUM_AMBIENTS ; ch_idx < NUM_AMBIENTS + MAX_DYNAMIC_CHANNELS ; ch_idx++)
- {
+ first_to_die = -1;
+ life_left = 0x7fffffff;
+ for (ch_idx=NUM_AMBIENTS ; ch_idx < NUM_AMBIENTS + MAX_DYNAMIC_CHANNELS ; ch_idx++)
+ {
if (entchannel != 0 // channel 0 never overrides
&& channels[ch_idx].entnum == entnum
&& (channels[ch_idx].entchannel == entchannel || entchannel == -1) )
life_left = channels[ch_idx].end - paintedtime;
first_to_die = ch_idx;
}
- }
+ }
if (first_to_die == -1)
return NULL;
if (channels[first_to_die].sfx)
channels[first_to_die].sfx = NULL;
- return &channels[first_to_die];
+ return &channels[first_to_die];
}
/*
SND_Spatialize
=================
*/
-void SND_Spatialize(channel_t *ch)
+void SND_Spatialize(channel_t *ch, int isstatic)
{
- vec_t dot;
- vec_t dist;
- vec_t lscale, rscale, scale;
- vec3_t source_vec;
+ vec_t dot;
+ vec_t dist;
+ vec_t lscale, rscale, scale;
+ vec3_t source_vec;
sfx_t *snd;
-// anything coming from the view entity will always be full volume
-// LordHavoc: make sounds with ATTN_NONE have no spatialization
+ // anything coming from the view entity will always be full volume
+ // LordHavoc: make sounds with ATTN_NONE have no spatialization
if (ch->entnum == cl.viewentity || ch->dist_mult == 0)
{
ch->leftvol = ch->master_vol;
ch->rightvol = ch->master_vol;
- return;
}
+ else
+ {
+ // update sound origin if we know about the entity
+ if (ch->entnum > 0 && cls.state == ca_connected && cl_entities[ch->entnum].state_current.active)
+ {
+ //Con_Printf("-- entnum %i origin %f %f %f neworigin %f %f %f\n", ch->entnum, ch->origin[0], ch->origin[1], ch->origin[2], cl_entities[ch->entnum].state_current.origin[0], cl_entities[ch->entnum].state_current.origin[1], cl_entities[ch->entnum].state_current.origin[2]);
+ VectorCopy(cl_entities[ch->entnum].state_current.origin, ch->origin);
+ if (cl_entities[ch->entnum].state_current.modelindex && cl.model_precache[cl_entities[ch->entnum].state_current.modelindex]->brush.TraceBox)
+ VectorMAMAM(1.0f, ch->origin, 0.5f, cl.model_precache[cl_entities[ch->entnum].state_current.modelindex]->normalmins, 0.5f, cl.model_precache[cl_entities[ch->entnum].state_current.modelindex]->normalmaxs, ch->origin);
+ }
+
+ // calculate stereo seperation and distance attenuation
+ snd = ch->sfx;
+ VectorSubtract(ch->origin, listener_origin, source_vec);
-// calculate stereo seperation and distance attenuation
+ dist = VectorNormalizeLength(source_vec) * ch->dist_mult;
- snd = ch->sfx;
- VectorSubtract(ch->origin, listener_origin, source_vec);
+ dot = DotProduct(listener_right, source_vec);
- dist = VectorNormalizeLength(source_vec) * ch->dist_mult;
+ if (shm->channels == 1)
+ {
+ rscale = 1.0;
+ lscale = 1.0;
+ }
+ else
+ {
+ rscale = 1.0 + dot;
+ lscale = 1.0 - dot;
+ }
- dot = DotProduct(listener_right, source_vec);
+ // add in distance effect
+ scale = (1.0 - dist) * rscale;
+ ch->rightvol = (int) (ch->master_vol * scale);
+ if (ch->rightvol < 0)
+ ch->rightvol = 0;
- if (shm->channels == 1)
- {
- rscale = 1.0;
- lscale = 1.0;
+ scale = (1.0 - dist) * lscale;
+ ch->leftvol = (int) (ch->master_vol * scale);
+ if (ch->leftvol < 0)
+ ch->leftvol = 0;
}
- else
+
+ // LordHavoc: allow adjusting volume of static sounds
+ if (isstatic)
{
- rscale = 1.0 + dot;
- lscale = 1.0 - dot;
+ ch->leftvol *= snd_staticvolume.value;
+ ch->rightvol *= snd_staticvolume.value;
}
-
-// add in distance effect
- scale = (1.0 - dist) * rscale;
- ch->rightvol = (int) (ch->master_vol * scale);
- if (ch->rightvol < 0)
- ch->rightvol = 0;
-
- scale = (1.0 - dist) * lscale;
- ch->leftvol = (int) (ch->master_vol * scale);
- if (ch->leftvol < 0)
- ch->leftvol = 0;
}
// spatialize
memset (target_chan, 0, sizeof(*target_chan));
+ /*
+ if (cls.state == ca_connected && entnum > 0 && cl_entities[entnum].state_current.active)
+ {
+ target_chan.follow = true;
+ VectorSubtract(origin, cl_entities[entnum].state_current.origin, target_chan.followoriginoffset);
+ }
+ */
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);
+ SND_Spatialize(target_chan, false);
if (!target_chan->leftvol && !target_chan->rightvol)
return; // not audible at all
target_chan->sfx = sfx;
target_chan->pos = 0.0;
- target_chan->end = paintedtime + sc->length;
+ target_chan->end = paintedtime + sc->length;
// 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++)
- {
+ for (ch_idx=NUM_AMBIENTS ; ch_idx < NUM_AMBIENTS + MAX_DYNAMIC_CHANNELS ; ch_idx++, check++)
+ {
if (check == target_chan)
continue;
if (check->sfx == sfx && !check->pos)
void S_StopAllSounds(qboolean clear)
{
- int i;
-
if (!sound_started)
return;
total_channels = MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS; // no statics
-
- for (i=0 ; i<MAX_CHANNELS ; i++)
- if (channels[i].sfx)
- channels[i].sfx = NULL;
-
memset(channels, 0, MAX_CHANNELS * sizeof(channel_t));
if (clear)
return;
}
- ss = &channels[total_channels];
- total_channels++;
-
sc = S_LoadSound (sfx, true);
if (!sc)
return;
if (sc->loopstart == -1)
- {
- Con_Printf ("Sound %s not looped\n", sfx->name);
- return;
- }
+ Con_DPrintf("Quake compatibility warning: Static sound \"%s\" is not looped\n", sfx->name);
+ ss = &channels[total_channels++];
+ memset(ss, 0, sizeof(*ss));
+ ss->forceloop = true;
ss->sfx = sfx;
VectorCopy (origin, ss->origin);
ss->master_vol = vol;
ss->dist_mult = (attenuation/64) / sound_nominal_clip_dist;
- ss->end = paintedtime + sc->length;
+ ss->end = paintedtime + sc->length;
- SND_Spatialize (ss);
+ SND_Spatialize (ss, true);
}
*/
void S_UpdateAmbientSounds (void)
{
- mleaf_t *l;
float vol;
int ambient_channel;
channel_t *chan;
+ qbyte ambientlevels[NUM_AMBIENTS];
// LordHavoc: kill ambient sounds until proven otherwise
for (ambient_channel = 0 ; ambient_channel < NUM_AMBIENTS;ambient_channel++)
channels[ambient_channel].sfx = NULL;
- if (!snd_ambient || !cl.worldmodel || ambient_level.value <= 0)
+ if (!snd_ambient || ambient_level.value <= 0 || !cl.worldmodel || !cl.worldmodel->brush.AmbientSoundLevelsForPoint)
return;
- l = Mod_PointInLeaf (listener_origin, cl.worldmodel);
- if (!l)
- return;
+ cl.worldmodel->brush.AmbientSoundLevelsForPoint(cl.worldmodel, listener_origin, ambientlevels, sizeof(ambientlevels));
// calc ambient sound levels
for (ambient_channel = 0 ; ambient_channel< NUM_AMBIENTS ; ambient_channel++)
{
+ if (ambient_sfx[ambient_channel] && ambient_sfx[ambient_channel]->silentlymissing)
+ continue;
chan = &channels[ambient_channel];
+ chan->forceloop = true;
chan->sfx = ambient_sfx[ambient_channel];
- vol = ambient_level.value * l->ambient_sound_level[ambient_channel];
+ vol = ambient_level.value * ambientlevels[ambient_channel];
if (vol < 8)
vol = 0;
{
if (!ch->sfx)
continue;
- SND_Spatialize(ch); // respatialize channel
+ SND_Spatialize(ch, i >= MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS); // respatialize channel
if (!ch->leftvol && !ch->rightvol)
continue;
break;
if (j == total_channels)
- {
combine = NULL;
- }
else
{
if (combine != ch)
// mix ahead of current position
endtime = soundtime + _snd_mixahead.value * shm->speed;
samps = shm->samples >> (shm->channels-1);
- if (endtime - soundtime > samps)
+ if (endtime > (unsigned int)(soundtime + samps))
endtime = soundtime + samps;
#ifdef _WIN32
void S_Play(void)
{
- static int hash=345;
int i;
char name[256];
sfx_t *sfx;
else
strcpy(name, Cmd_Argv(i));
sfx = S_PrecacheSound(name, true);
- S_StartSound(hash++, 0, sfx, listener_origin, 1.0, 1.0);
+ S_StartSound(-1, 0, sfx, listener_origin, 1.0, 1.0);
i++;
}
}
void S_Play2(void)
{
- static int hash=345;
int i;
char name[256];
sfx_t *sfx;
else
strcpy(name, Cmd_Argv(i));
sfx = S_PrecacheSound(name, true);
- S_StartSound(hash++, 0, sfx, listener_origin, 1.0, 0.0);
+ S_StartSound(-1, 0, sfx, listener_origin, 1.0, 0.0);
i++;
}
}
void S_PlayVol(void)
{
- static int hash=543;
int i;
float vol;
char name[256];
strcpy(name, Cmd_Argv(i));
sfx = S_PrecacheSound(name, true);
vol = atof(Cmd_Argv(i+1));
- S_StartSound(hash++, 0, sfx, listener_origin, vol, 1.0);
+ S_StartSound(-1, 0, sfx, listener_origin, vol, 1.0);
i+=2;
}
}
out[i] = in[i];
//Con_Printf("S_RawSamples_Dequeue: normal %i\n", l);
}
- if (l < length)
+ if (l < (int)length)
{
memset(samples + l * 2, 0, (length - l) * sizeof(int[2]));
//Con_Printf("S_RawSamples_Dequeue: padding with %i samples\n", length - l);