]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - snd_mix.c
DP_SND_SOUND7_WIP1
[xonotic/darkplaces.git] / snd_mix.c
index 30e5a523e3f4749ba46d2d50f0c2236f89efadfe..6bec880eae3974665dcc699feff687b8a84779fb 100644 (file)
--- a/snd_mix.c
+++ b/snd_mix.c
@@ -183,23 +183,18 @@ CHANNEL MIXING
 
 static qboolean SND_PaintChannel (channel_t *ch, portable_sampleframe_t *paint, unsigned int count)
 {
-       int snd_vol, vol[SND_LISTENERS];
+       int vol[SND_LISTENERS];
        const snd_buffer_t *sb;
        unsigned int i, sb_offset;
+       sfx_t *sfx;
 
-       // If this channel manages its own volume
-       if (ch->flags & CHANNELFLAG_FULLVOLUME)
-               snd_vol = 256;
-       else
-               snd_vol = (int)(volume.value * 256);
+       sfx = ch->sfx; // fetch the volatile variable
+       if (!sfx) // given that this is called by the mixer thread, this never happens, but...
+               return false;
 
-       // calculate mixing volumes based on channel volumes and volume cvar
-       // also limit the volumes to values that won't clip
+       // move to the stack (do we need to?)
        for (i = 0;i < SND_LISTENERS;i++)
-       {
-               vol[i] = ch->listener_volume[i] * snd_vol;
-               vol[i] = bound(0, vol[i], 65536);
-       }
+               vol[i] = ch->listener_volume[i];
 
        // if volumes are all zero, just return
        for (i = 0;i < SND_LISTENERS;i++)
@@ -209,11 +204,11 @@ static qboolean SND_PaintChannel (channel_t *ch, portable_sampleframe_t *paint,
                return false;
 
        sb_offset = ch->pos;
-       sb = ch->sfx->fetcher->getsb (ch->sfx->fetcher_data, &ch->fetcher_data, &sb_offset, count);
+       sb = sfx->fetcher->getsb (sfx->fetcher_data, &ch->fetcher_data, &sb_offset, count);
        if (sb == NULL)
        {
                Con_DPrintf("SND_PaintChannel: ERROR: can't get sound buffer from sfx \"%s\"\n",
-                                       ch->sfx->name); // , count); // or add this? FIXME
+                                       sfx->name); // , count); // or add this? FIXME
                return false;
        }
        else
@@ -267,6 +262,15 @@ static qboolean SND_PaintChannel (channel_t *ch, portable_sampleframe_t *paint,
                                                samples += 2;
                                        }
                                }
+                               else if (vol[0] + vol[1] > 0 && ch->prologic_invert == -1)
+                               {
+                                       for (i = 0;i < count;i++)
+                                       {
+                                               paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
+                                               paint[i].sample[1] -= (samples[1] * vol[1]) >> 8;
+                                               samples += 2;
+                                       }
+                               }
                                else if (vol[0] + vol[1] > 0)
                                {
                                        for (i = 0;i < count;i++)
@@ -318,6 +322,15 @@ static qboolean SND_PaintChannel (channel_t *ch, portable_sampleframe_t *paint,
                                                samples += 1;
                                        }
                                }
+                               else if (vol[0] + vol[1] > 0 && ch->prologic_invert == -1)
+                               {
+                                       for (i = 0;i < count;i++)
+                                       {
+                                               paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
+                                               paint[i].sample[1] -= (samples[0] * vol[1]) >> 8;
+                                               samples += 1;
+                                       }
+                               }
                                else if (vol[0] + vol[1] > 0)
                                {
                                        for (i = 0;i < count;i++)
@@ -377,6 +390,15 @@ static qboolean SND_PaintChannel (channel_t *ch, portable_sampleframe_t *paint,
                                                samples += 2;
                                        }
                                }
+                               else if (vol[0] + vol[1] > 0 && ch->prologic_invert == -1)
+                               {
+                                       for (i = 0;i < count;i++)
+                                       {
+                                               paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
+                                               paint[i].sample[1] -= (samples[1] * vol[1]) >> 16;
+                                               samples += 2;
+                                       }
+                               }
                                else if (vol[0] + vol[1] > 0)
                                {
                                        for (i = 0;i < count;i++)
@@ -428,6 +450,15 @@ static qboolean SND_PaintChannel (channel_t *ch, portable_sampleframe_t *paint,
                                                samples += 1;
                                        }
                                }
+                               else if (vol[0] + vol[1] > 0 && ch->prologic_invert == -1)
+                               {
+                                       for (i = 0;i < count;i++)
+                                       {
+                                               paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
+                                               paint[i].sample[1] -= (samples[0] * vol[1]) >> 16;
+                                               samples += 1;
+                                       }
+                               }
                                else if (vol[0] + vol[1] > 0)
                                {
                                        for (i = 0;i < count;i++)
@@ -477,30 +508,34 @@ void S_MixToBuffer(void *stream, unsigned int bufferframes)
                                continue;
                        if (ch->flags & CHANNELFLAG_PAUSED)
                                continue;
+                       if (!sfx->total_length)
+                               continue;
+                       if (sfx->total_length > 1<<30)
+                               Sys_Error("S_MixToBuffer: sfx corrupt\n");
 
                        ltime = 0;
                        if (ch->pos < 0)
                        {
                                count = -ch->pos;
-                               count = min(count, frames - ltime);
+                               count = min(count, (int)frames - ltime);
                                ch->pos += count;
                                ltime += count;
                        }
 
-                       while (ltime < frames)
+                       while (ltime < (int)frames)
                        {
                                // paint up to end of buffer or of input, whichever is lower
                                count = sfx->total_length - ch->pos;
-                               count = bound(0, count, frames - ltime);
+                               count = bound(0, count, (int)frames - ltime);
+                               // mix the remaining samples
                                if (count)
                                {
                                        SND_PaintChannel (ch, paintbuffer + ltime, count);
                                        ch->pos += count;
                                        ltime += count;
                                }
-
                                // if at end of sfx, loop or stop the channel
-                               if (ch->pos >= (int)sfx->total_length)
+                               else
                                {
                                        if (sfx->loopstart < sfx->total_length)
                                                ch->pos = sfx->loopstart;
@@ -508,7 +543,7 @@ void S_MixToBuffer(void *stream, unsigned int bufferframes)
                                                ch->pos = 0;
                                        else
                                        {
-                                               S_StopChannel (ch - channels, false);
+                                               S_StopChannel (ch - channels, false, false);
                                                break;
                                        }
                                }