]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - snd_main.c
changed loopstart from signed to unsigned, now un-looped sounds are
[xonotic/darkplaces.git] / snd_main.c
index d3f16b1193666404f169ed6f1220186df4e3e396..1734baeac2246df6ed7e55c73ebcc865dd6efcb2 100644 (file)
@@ -268,7 +268,7 @@ static void S_SoundList_f (void)
                        size = sfx->memsize;
                        format = sfx->fetcher->getfmt(sfx);
                        Con_Printf ("%c%c%c%c(%2db, %6s) %8i : %s\n",
-                                               (sfx->loopstart >= 0) ? 'L' : ' ',
+                                               (sfx->loopstart < sfx->total_length) ? 'L' : ' ',
                                                (sfx->flags & SFXFLAG_STREAMED) ? 'S' : ' ',
                                                (sfx->locks > 0) ? 'K' : ' ',
                                                (sfx->flags & SFXFLAG_PERMANENTLOCK) ? 'P' : ' ',
@@ -1043,41 +1043,42 @@ channel_t *SND_PickChannel(int entnum, int entchannel)
 // Check for replacement sound, or find the best one to replace
        first_to_die = -1;
        first_life_left = 0x7fffffff;
-       for (ch_idx=NUM_AMBIENTS ; ch_idx < NUM_AMBIENTS + MAX_DYNAMIC_CHANNELS ; ch_idx++)
+
+       // entity channels try to replace the existing sound on the channel
+       if (entchannel != 0)
        {
-               ch = &channels[ch_idx];
-               if (entchannel != 0)
+               for (ch_idx=NUM_AMBIENTS ; ch_idx < NUM_AMBIENTS + MAX_DYNAMIC_CHANNELS ; ch_idx++)
                {
-                       // try to override an existing channel
+                       ch = &channels[ch_idx];
                        if (ch->entnum == entnum && (ch->entchannel == entchannel || entchannel == -1) )
                        {
                                // always override sound from same entity
-                               first_to_die = ch_idx;
-                               break;
+                               S_StopChannel (ch_idx);
+                               return &channels[ch_idx];
                        }
                }
-               else
+       }
+
+       // there was no channel to override, so look for the first empty one
+       for (ch_idx=NUM_AMBIENTS ; ch_idx < NUM_AMBIENTS + MAX_DYNAMIC_CHANNELS ; ch_idx++)
+       {
+               ch = &channels[ch_idx];
+               if (!ch->sfx)
                {
-                       if (!ch->sfx)
-                       {
-                               // no sound on this channel
-                               first_to_die = ch_idx;
-                               break;
-                       }
+                       // no sound on this channel
+                       first_to_die = ch_idx;
+                       break;
                }
 
-               if (ch->sfx)
-               {
-                       // don't let monster sounds override player sounds
-                       if (ch->entnum == cl.viewentity && entnum != cl.viewentity)
-                               continue;
+               // don't let monster sounds override player sounds
+               if (ch->entnum == cl.viewentity && entnum != cl.viewentity)
+                       continue;
 
-                       // don't override looped sounds
-                       if ((ch->flags & CHANNELFLAG_FORCELOOP) || ch->sfx->loopstart >= 0)
-                               continue;
-               }
+               // don't override looped sounds
+               if ((ch->flags & CHANNELFLAG_FORCELOOP) || ch->sfx->loopstart < ch->sfx->total_length)
+                       continue;
+               life_left = ch->sfx->total_length - ch->pos;
 
-               life_left = (int)(ch->end - snd_renderbuffer->endframe);
                if (life_left < first_life_left)
                {
                        first_life_left = life_left;
@@ -1088,8 +1089,6 @@ channel_t *SND_PickChannel(int entnum, int entchannel)
        if (first_to_die == -1)
                return NULL;
 
-       S_StopChannel (first_to_die);
-
        return &channels[first_to_die];
 }
 
@@ -1164,14 +1163,13 @@ void S_PlaySfxOnChannel (sfx_t *sfx, channel_t *target_chan, unsigned int flags,
        VectorCopy (origin, target_chan->origin);
        target_chan->master_vol = (int)(fvol * 255);
        target_chan->sfx = sfx;
-       target_chan->end = snd_renderbuffer->endframe + sfx->total_length;
-       target_chan->lastptime = snd_renderbuffer->endframe;
        target_chan->flags = flags;
+       target_chan->pos = 0; // start of the sound
 
        // If it's a static sound
        if (isstatic)
        {
-               if (sfx->loopstart == -1)
+               if (sfx->loopstart >= sfx->total_length)
                        Con_DPrintf("Quake compatibility warning: Static sound \"%s\" is not looped\n", sfx->name);
                target_chan->dist_mult = attenuation / (64.0f * snd_soundradius.value);
        }
@@ -1187,7 +1185,6 @@ int S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float f
 {
        channel_t *target_chan, *check;
        int             ch_idx;
-       int             skip;
 
        if (snd_renderbuffer == NULL || sfx == NULL || nosound.integer)
                return -1;
@@ -1218,13 +1215,8 @@ int S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float f
                        continue;
                if (check->sfx == sfx && !check->pos)
                {
-                       skip = (int)(0.1 * snd_renderbuffer->format.speed);
-                       if (skip > (int)sfx->total_length)
-                               skip = (int)sfx->total_length;
-                       if (skip > 0)
-                               skip = rand() % skip;
-                       target_chan->pos += skip;
-                       target_chan->end -= skip;
+                       // use negative pos offset to delay this sound effect
+                       target_chan->pos += (int)lhrandom(0, -0.1 * snd_renderbuffer->format.speed);
                        break;
                }
        }
@@ -1256,7 +1248,6 @@ void S_StopChannel (unsigned int channel_ind)
 
                ch->sfx = NULL;
        }
-       ch->end = 0;
 }
 
 
@@ -1427,14 +1418,14 @@ void S_UpdateAmbientSounds (void)
 static void S_PaintAndSubmit (void)
 {
        unsigned int newsoundtime, paintedtime, endtime, maxtime, usedframes;
+       qboolean usesoundtimehack;
+       static qboolean soundtimehack = true;
 
        if (snd_renderbuffer == NULL || nosound.integer)
                return;
 
-       if (snd_blocked > 0 && !cls.timedemo && !(cls.capturevideo.soundrate && !cls.capturevideo.realtime))
-               return;
-
        // Update sound time
+       usesoundtimehack = true;
        if (cls.timedemo) // SUPER NASTY HACK to mix non-realtime sound for more reliable benchmarking
                newsoundtime = (unsigned int)((double)cl.mtime[0] * (double)snd_renderbuffer->format.speed);
        else if (cls.capturevideo.soundrate && !cls.capturevideo.realtime) // SUPER NASTY HACK to record non-realtime sound
@@ -1442,7 +1433,33 @@ static void S_PaintAndSubmit (void)
        else if (simsound)
                newsoundtime = (unsigned int)((realtime - snd_starttime) * (double)snd_renderbuffer->format.speed);
        else
+       {
                newsoundtime = SndSys_GetSoundTime();
+               usesoundtimehack = false;
+       }
+       // if the soundtimehack state changes we need to reset the soundtime
+       if (soundtimehack != usesoundtimehack)
+       {
+               snd_renderbuffer->startframe = snd_renderbuffer->endframe = soundtime = newsoundtime;
+
+               // Mute the contents of the submission buffer
+               if (simsound || SndSys_LockRenderBuffer ())
+               {
+                       int clear;
+                       size_t memsize;
+
+                       clear = (snd_renderbuffer->format.width == 1) ? 0x80 : 0;
+                       memsize = snd_renderbuffer->maxframes * snd_renderbuffer->format.width * snd_renderbuffer->format.channels;
+                       memset(snd_renderbuffer->ring, clear, memsize);
+
+                       if (!simsound)
+                               SndSys_UnlockRenderBuffer ();
+               }
+       }
+       soundtimehack = usesoundtimehack;
+
+       if (!soundtimehack && snd_blocked > 0)
+               return;
 
        newsoundtime += extrasoundtime;
        if (newsoundtime < soundtime)
@@ -1464,7 +1481,7 @@ static void S_PaintAndSubmit (void)
                        Con_DPrintf("S_PaintAndSubmit: new extra sound time = %u\n",
                                                extrasoundtime);
                }
-               else
+               else if (!soundtimehack)
                        Con_Printf("S_PaintAndSubmit: WARNING: newsoundtime < soundtime (%u < %u)\n",
                                           newsoundtime, soundtime);
        }
@@ -1506,9 +1523,6 @@ void S_Update(const matrix4x4_t *listenermatrix)
        if (snd_renderbuffer == NULL || nosound.integer)
                return;
 
-       if (snd_blocked > 0 && !cls.timedemo && !(cls.capturevideo.soundrate && !cls.capturevideo.realtime))
-               return;
-
        // If snd_swapstereo or snd_channellayout has changed, recompute the channel layout
        if (current_swapstereo != snd_swapstereo.integer ||
                current_channellayout != snd_channellayout.integer)