X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=snd_main.c;h=87c223a44585c38ee0b66bab3a3ac28d3658df1f;hb=6565597d1fb3cdf77b34f2497e6a0d54c544a9c5;hp=4d4bf704db54132541787447f283430737558d13;hpb=a8fa60f5e8370fded3d26994136a924903d9508e;p=xonotic%2Fdarkplaces.git diff --git a/snd_main.c b/snd_main.c index 4d4bf704..87c223a4 100644 --- a/snd_main.c +++ b/snd_main.c @@ -25,6 +25,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "snd_ogg.h" #include "snd_modplug.h" #include "csprogs.h" +#include "cl_collision.h" #define SND_MIN_SPEED 8000 @@ -169,7 +170,8 @@ cvar_t snd_spatialization_control = {CVAR_SAVE, "snd_spatialization_control", "0 cvar_t snd_spatialization_occlusion = {CVAR_SAVE, "snd_spatialization_occlusion", "1", "enable occlusion testing on spatialized sounds, which simply quiets sounds that are blocked by the world"}; // Cvars declared in snd_main.h (shared with other snd_*.c files) -cvar_t _snd_mixahead = {CVAR_SAVE, "_snd_mixahead", "0.11", "how much sound to mix ahead of time"}; +cvar_t _snd_mixahead = {CVAR_SAVE, "_snd_mixahead", "0.15", "how much sound to mix ahead of time"}; +cvar_t snd_streaming = { CVAR_SAVE, "snd_streaming", "1", "enables keeping compressed ogg sound files compressed, decompressing them only as needed, otherwise they will be decompressed completely at load (may use a lot of memory)"}; cvar_t snd_swapstereo = {CVAR_SAVE, "snd_swapstereo", "0", "swaps left/right speakers for old ISA soundblaster cards"}; extern cvar_t v_flipped; cvar_t snd_channellayout = {0, "snd_channellayout", "0", "channel layout. Can be 0 (auto - snd_restart needed), 1 (standard layout), or 2 (ALSA layout)"}; @@ -260,7 +262,7 @@ static void S_Play_Common (float fvol, float attenuation) ch_ind = S_StartSound (-1, 0, sfx, listener_origin, fvol, attenuation); // Free the sfx if the file didn't exist - if (ch_ind < 0) + if (!sfx->fetcher) S_FreeSfx (sfx, false); else channels[ch_ind].flags |= CHANNELFLAG_LOCALSOUND; @@ -843,6 +845,7 @@ void S_Init(void) Cvar_RegisterVariable(&nosound); Cvar_RegisterVariable(&snd_precache); Cvar_RegisterVariable(&snd_initialized); + Cvar_RegisterVariable(&snd_streaming); Cvar_RegisterVariable(&ambient_level); Cvar_RegisterVariable(&ambient_fade); Cvar_RegisterVariable(&snd_noextraupdate); @@ -1097,6 +1100,27 @@ sfx_t *S_PrecacheSound (const char *name, qboolean complain, qboolean serversoun return sfx; } +/* +================== +S_SoundLength +================== +*/ + +float S_SoundLength(const char *name) +{ + sfx_t *sfx; + + if (!snd_initialized.integer) + return -1; + if (name == NULL || name[0] == 0) + return -1; + + sfx = S_FindName(name); + if (sfx == NULL) + return -1; + return sfx->total_length / (float) S_GetSoundRate(); +} + /* ================== S_IsSoundPrecached @@ -1251,8 +1275,10 @@ void SND_Spatialize(channel_t *ch, qboolean isstatic) } else if (cl.entities[ch->entnum].state_current.active) { + dp_model_t *model; //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]); - if (cl.entities[ch->entnum].state_current.modelindex && cl.model_precache[cl.entities[ch->entnum].state_current.modelindex] && cl.model_precache[cl.entities[ch->entnum].state_current.modelindex]->soundfromcenter) + model = CL_GetModelByIndex(cl.entities[ch->entnum].state_current.modelindex); + if (model && model->soundfromcenter) VectorMAM(0.5f, cl.entities[ch->entnum].render.mins, 0.5f, cl.entities[ch->entnum].render.maxs, ch->origin); else Matrix4x4_OriginFromMatrix(&cl.entities[ch->entnum].render.matrix, ch->origin); @@ -1400,7 +1426,8 @@ void SND_Spatialize(channel_t *ch, qboolean isstatic) // Start a sound effect // ======================================================================= -void S_PlaySfxOnChannel (sfx_t *sfx, channel_t *target_chan, unsigned int flags, vec3_t origin, float fvol, float attenuation, qboolean isstatic) +static void S_SetChannelVolume_WithSfx (unsigned int ch_ind, float fvol, sfx_t *sfx); +void S_PlaySfxOnChannel (sfx_t *sfx, channel_t *target_chan, unsigned int flags, vec3_t origin, float fvol, float attenuation, qboolean isstatic, int entnum, int entchannel, int startpos) { if (!sfx) { @@ -1420,35 +1447,40 @@ void S_PlaySfxOnChannel (sfx_t *sfx, channel_t *target_chan, unsigned int flags, memset (target_chan, 0, sizeof (*target_chan)); VectorCopy (origin, target_chan->origin); target_chan->flags = flags; - target_chan->pos = 0; // start of the sound + target_chan->pos = startpos; // start of the sound + target_chan->entnum = entnum; + target_chan->entchannel = entchannel; // If it's a static sound if (isstatic) { - if (sfx->loopstart >= sfx->total_length) + if (sfx->loopstart >= sfx->total_length && (cls.protocol == PROTOCOL_QUAKE || cls.protocol == PROTOCOL_QUAKEWORLD)) Con_DPrintf("Quake compatibility warning: Static sound \"%s\" is not looped\n", sfx->name); target_chan->dist_mult = attenuation / (64.0f * snd_soundradius.value); } else target_chan->dist_mult = attenuation / snd_soundradius.value; + // we have to set the channel volume AFTER the sfx because the function + // needs it for replaygain support + S_SetChannelVolume_WithSfx(target_chan - channels, fvol, sfx); + + // set the listener volumes + SND_Spatialize (target_chan, isstatic); + // Lock the SFX during play S_LockSfx (sfx); // finally, set the sfx pointer, so the channel becomes valid for playback // and will be noticed by the mixer target_chan->sfx = sfx; - - // we have to set the channel volume AFTER the sfx because the function - // needs it for replaygain support - S_SetChannelVolume(target_chan - channels, fvol); } -int S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation) +int S_StartSound_StartPosition (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation, float startposition) { channel_t *target_chan, *check, *ch; - int ch_idx; + int ch_idx, startpos; if (snd_renderbuffer == NULL || sfx == NULL || nosound.integer) return -1; @@ -1463,7 +1495,8 @@ int S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float f if (ch->entnum == entnum && (ch->entchannel == entchannel || entchannel == -1) ) { S_SetChannelVolume(ch_idx, fvol); - ch->dist_mult = attenuation / (64.0f * snd_soundradius.value); + ch->dist_mult = attenuation / snd_soundradius.value; + SND_Spatialize(ch, false); return ch_idx; } } @@ -1478,30 +1511,35 @@ int S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float f if (!target_chan) return -1; - 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 check = &channels[NUM_AMBIENTS]; - for (ch_idx=NUM_AMBIENTS ; ch_idx < NUM_AMBIENTS + MAX_DYNAMIC_CHANNELS ; ch_idx++, check++) + startpos = (int)(startposition * S_GetSoundRate()); + if (startpos == 0) { - if (check == target_chan) - continue; - if (check->sfx == sfx && !check->pos) + for (ch_idx=NUM_AMBIENTS ; ch_idx < NUM_AMBIENTS + MAX_DYNAMIC_CHANNELS ; ch_idx++, check++) { - // use negative pos offset to delay this sound effect - target_chan->pos += (int)lhrandom(0, -0.1 * snd_renderbuffer->format.speed); - break; + if (check == target_chan) + continue; + if (check->sfx == sfx && check->pos == 0) + { + // use negative pos offset to delay this sound effect + startpos = (int)lhrandom(0, -0.1 * snd_renderbuffer->format.speed); + break; + } } } + S_PlaySfxOnChannel (sfx, target_chan, CHANNELFLAG_NONE, origin, fvol, attenuation, false, entnum, entchannel, startpos); + return (target_chan - channels); } +int S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation) +{ + return S_StartSound_StartPosition(entnum, entchannel, sfx, origin, fvol, attenuation, 0); +} + void S_StopChannel (unsigned int channel_ind, qboolean lockmutex) { channel_t *ch; @@ -1617,9 +1655,8 @@ void S_PauseGameSounds (qboolean toggle) } } -void S_SetChannelVolume (unsigned int ch_ind, float fvol) +static void S_SetChannelVolume_WithSfx (unsigned int ch_ind, float fvol, sfx_t *sfx) { - sfx_t *sfx = channels[ch_ind].sfx; if(sfx->volume_peak > 0) { // Replaygain support @@ -1632,12 +1669,20 @@ void S_SetChannelVolume (unsigned int ch_ind, float fvol) channels[ch_ind].master_vol = (int)(fvol * 255.0f); } +void S_SetChannelVolume(unsigned int ch_ind, float fvol) +{ + sfx_t *sfx = channels[ch_ind].sfx; + S_SetChannelVolume_WithSfx(ch_ind, fvol, sfx); +} + float S_GetChannelPosition (unsigned int ch_ind) { // note: this is NOT accurate yet int s; channel_t *ch = &channels[ch_ind]; sfx_t *sfx = ch->sfx; + if (!sfx) + return -1; s = ch->pos; /* @@ -1647,7 +1692,19 @@ float S_GetChannelPosition (unsigned int ch_ind) return (s % sfx->total_length) / (float) S_GetSoundRate(); } +float S_GetEntChannelPosition(int entnum, int entchannel) +{ + channel_t *ch; + unsigned int i; + for (i = 0; i < total_channels; i++) + { + ch = &channels[i]; + if (ch->entnum == entnum && ch->entchannel == entchannel) + return S_GetChannelPosition(i); + } + return -1; // no playing sound in this channel +} /* ================= @@ -1673,9 +1730,7 @@ void S_StaticSound (sfx_t *sfx, vec3_t origin, float fvol, float attenuation) } target_chan = &channels[total_channels++]; - S_PlaySfxOnChannel (sfx, target_chan, CHANNELFLAG_FORCELOOP, origin, fvol, attenuation, true); - - SND_Spatialize (target_chan, true); + S_PlaySfxOnChannel (sfx, target_chan, CHANNELFLAG_FORCELOOP, origin, fvol, attenuation, true, 0, 0, 0); } @@ -1872,6 +1927,7 @@ static void S_PaintAndSubmit (void) oldsoundtime = soundtime; cls.soundstats.latency_milliseconds = (snd_renderbuffer->endframe - snd_renderbuffer->startframe) * 1000 / snd_renderbuffer->format.speed; + R_TimeReport("audiomix"); } /* @@ -1958,6 +2014,7 @@ void S_Update(const matrix4x4_t *listenermatrix) S_UpdateAmbientSounds (); combine = NULL; + R_TimeReport("audioprep"); // update spatialization for static and dynamic sounds cls.soundstats.totalsounds = 0; @@ -2011,6 +2068,7 @@ void S_Update(const matrix4x4_t *listenermatrix) if (k < SND_LISTENERS) cls.soundstats.mixedsounds++; } + R_TimeReport("audiospatialize"); sound_spatialized = true;