]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - snd_mix.c
strncpy -> {strlcpy,memcpy}. Replaced the "forceloop" boolean in "channel_t" by a...
[xonotic/darkplaces.git] / snd_mix.c
index e9325085348f6a4582af37d1224ceb3a28792ab2..f6cd8e889aec496fe909e440e0479da639978379 100644 (file)
--- a/snd_mix.c
+++ b/snd_mix.c
@@ -21,9 +21,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 #include "quakedef.h"
 
-#ifdef _WIN32
-#include "winquake.h"
-#endif
+typedef struct
+{
+       int left;
+       int right;
+} portable_samplepair_t;
 
 // LordHavoc: was 512, expanded to 2048
 #define        PAINTBUFFER_SIZE 2048
@@ -44,8 +46,7 @@ void S_CaptureAVISound(portable_samplepair_t *buf, int length)
        {
                if (cl_avidemo_soundfile == NULL)
                {
-                       sprintf (filename, "%s/dpavi.wav", com_gamedir);
-                       cl_avidemo_soundfile = fopen(filename, "wb");
+                       cl_avidemo_soundfile = FS_Open ("dpavi.wav", "wb", false);
                        memset(out, 0, 44);
                        fwrite(out, 1, 44, cl_avidemo_soundfile);
                        // header will be filled out when file is closed
@@ -66,7 +67,7 @@ void S_CaptureAVISound(portable_samplepair_t *buf, int length)
                if (fwrite(out, 4, length, cl_avidemo_soundfile) < length)
                {
                        Cvar_SetValueQuick(&cl_avidemo, 0);
-                       Con_Printf("avi saving sound failed, out of disk space?  stopping avi demo capture.\n");
+                       Con_Print("avi saving sound failed, out of disk space?  stopping avi demo capture.\n");
                }
        }
        else if (cl_avidemo_soundfile)
@@ -126,11 +127,11 @@ void S_TransferPaintBuffer(int endtime)
                snd_p = (int *) paintbuffer;
                snd_vol = volume.value*256;
                lpaintedtime = paintedtime;
-               if (shm->samplebits == 16)
+               if (shm->format.width == 2)
                {
                        // 16bit
                        short *snd_out;
-                       if (shm->channels == 2)
+                       if (shm->format.channels == 2)
                        {
                                // 16bit 2 channels (stereo)
                                while (lpaintedtime < endtime)
@@ -191,7 +192,7 @@ void S_TransferPaintBuffer(int endtime)
                {
                        // 8bit
                        unsigned char *snd_out;
-                       if (shm->channels == 2)
+                       if (shm->format.channels == 2)
                        {
                                // 8bit 2 channels (stereo)
                                while (lpaintedtime < endtime)
@@ -262,15 +263,15 @@ CHANNEL MIXING
 ===============================================================================
 */
 
-void SND_PaintChannelFrom8 (channel_t *ch, sfxcache_t *sc, int endtime);
-void SND_PaintChannelFrom16 (channel_t *ch, sfxcache_t *sc, int endtime);
+qboolean SND_PaintChannelFrom8 (channel_t *ch, int endtime);
+qboolean SND_PaintChannelFrom16 (channel_t *ch, int endtime);
 
 void S_PaintChannels(int endtime)
 {
-       int i;
+       unsigned int i;
        int end;
        channel_t *ch;
-       sfxcache_t *sc;
+       sfx_t *sfx;
        int ltime, count;
 
        while (paintedtime < endtime)
@@ -287,18 +288,45 @@ void S_PaintChannels(int endtime)
                ch = channels;
                for (i=0; i<total_channels ; i++, ch++)
                {
-                       if (!ch->sfx)
+                       sfx = ch->sfx;
+                       if (!sfx)
                                continue;
                        if (!ch->leftvol && !ch->rightvol)
                                continue;
-                       sc = S_LoadSound (ch->sfx, true);
-                       if (!sc)
+                       if (!S_LoadSound (sfx, true))
                                continue;
 
-                       ltime = paintedtime;
+                       // if the sound hasn't been painted last time, update his position
+                       if (ch->lastptime < paintedtime)
+                       {
+                               ch->pos += paintedtime - ch->lastptime;
+
+                               // If the sound should have ended by then
+                               if ((unsigned int)ch->pos > sfx->total_length)
+                               {
+                                       int loopstart;
 
+                                       if (ch->flags & CHANNELFLAG_FORCELOOP)
+                                               loopstart = 0;
+                                       else
+                                               loopstart = -1;
+                                       if (sfx->loopstart >= 0)
+                                               loopstart = sfx->loopstart;
+
+                                       // If the sound is looped
+                                       if (loopstart >= 0)
+                                               ch->pos = (ch->pos - sfx->total_length) % (sfx->total_length - loopstart) + loopstart;
+                                       else 
+                                               ch->pos = sfx->total_length;
+                                       ch->end = paintedtime + sfx->total_length - ch->pos;
+                               }
+                       }
+
+                       ltime = paintedtime;
                        while (ltime < end)
                        {
+                               qboolean stop_paint;
+
                                // paint up to end
                                if (ch->end < end)
                                        count = ch->end - ltime;
@@ -307,28 +335,39 @@ void S_PaintChannels(int endtime)
 
                                if (count > 0)
                                {
-                                       if (sc->width == 1)
-                                               SND_PaintChannelFrom8(ch, sc, count);
+                                       if (sfx->format.width == 1)
+                                               stop_paint = !SND_PaintChannelFrom8(ch, count);
                                        else
-                                               SND_PaintChannelFrom16(ch, sc, count);
+                                               stop_paint = !SND_PaintChannelFrom16(ch, count);
 
-                                       ltime += count;
+                                       if (!stop_paint)
+                                       {
+                                               ltime += count;
+                                               ch->lastptime = ltime;
+                                       }
                                }
+                               else
+                                       stop_paint = false;
 
-                               // if at end of loop, restart
                                if (ltime >= ch->end)
                                {
-                                       if (sc->loopstart >= 0)
+                                       // if at end of loop, restart
+                                       if ((sfx->loopstart >= 0 || (ch->flags & CHANNELFLAG_FORCELOOP)) && !stop_paint)
                                        {
-                                               ch->pos = sc->loopstart;
-                                               ch->end = ltime + sc->length - ch->pos;
+                                               ch->pos = bound(0, sfx->loopstart, (int)sfx->total_length - 1);
+                                               ch->end = ltime + sfx->total_length - ch->pos;
                                        }
+                                       // channel just stopped
                                        else
-                                       {
-                                               // channel just stopped
-                                               ch->sfx = NULL;
-                                               break;
-                                       }
+                                               stop_paint = true;
+                               }
+
+                               if (stop_paint)
+                               {
+                                       if (ch->sfx->fetcher->end != NULL)
+                                               ch->sfx->fetcher->end (ch);
+                                       ch->sfx = NULL;
+                                       break;
                                }
                        }
                }
@@ -350,10 +389,11 @@ void SND_InitScaletable (void)
 }
 
 
-void SND_PaintChannelFrom8 (channel_t *ch, sfxcache_t *sc, int count)
+qboolean SND_PaintChannelFrom8 (channel_t *ch, int count)
 {
        int *lscale, *rscale;
        unsigned char *sfx;
+       const sfxbuffer_t *sb;
        int i, n;
 
        if (ch->leftvol > 255)
@@ -363,10 +403,15 @@ void SND_PaintChannelFrom8 (channel_t *ch, sfxcache_t *sc, int count)
 
        lscale = snd_scaletable[ch->leftvol >> 3];
        rscale = snd_scaletable[ch->rightvol >> 3];
-       if (sc->stereo)
+
+       sb = ch->sfx->fetcher->getsb (ch, ch->pos, count);
+       if (sb == NULL)
+               return false;
+
+       if (ch->sfx->format.channels == 2)
        {
                // LordHavoc: stereo sound support, and optimizations
-               sfx = (unsigned char *)sc->data + ch->pos * 2;
+               sfx = (unsigned char *)sb->data + (ch->pos - sb->offset) * 2;
                for (i = 0;i < count;i++)
                {
                        paintbuffer[i].left += lscale[*sfx++];
@@ -375,7 +420,7 @@ void SND_PaintChannelFrom8 (channel_t *ch, sfxcache_t *sc, int count)
        }
        else
        {
-               sfx = (unsigned char *)sc->data + ch->pos;
+               sfx = (unsigned char *)sb->data + ch->pos - sb->offset;
                for (i = 0;i < count;i++)
                {
                        n = *sfx++;
@@ -385,20 +430,27 @@ void SND_PaintChannelFrom8 (channel_t *ch, sfxcache_t *sc, int count)
 
        }
        ch->pos += count;
+       return true;
 }
 
-void SND_PaintChannelFrom16 (channel_t *ch, sfxcache_t *sc, int count)
+qboolean SND_PaintChannelFrom16 (channel_t *ch, int count)
 {
        int leftvol, rightvol;
        signed short *sfx;
+       const sfxbuffer_t *sb;
        int i;
 
        leftvol = ch->leftvol;
        rightvol = ch->rightvol;
-       if (sc->stereo)
+
+       sb = ch->sfx->fetcher->getsb (ch, ch->pos, count);
+       if (sb == NULL)
+               return false;
+
+       if (ch->sfx->format.channels == 2)
        {
                // LordHavoc: stereo sound support, and optimizations
-               sfx = (signed short *)sc->data + ch->pos * 2;
+               sfx = (signed short *)sb->data + (ch->pos - sb->offset) * 2;
 
                for (i=0 ; i<count ; i++)
                {
@@ -408,7 +460,7 @@ void SND_PaintChannelFrom16 (channel_t *ch, sfxcache_t *sc, int count)
        }
        else
        {
-               sfx = (signed short *)sc->data + ch->pos;
+               sfx = (signed short *)sb->data + ch->pos - sb->offset;
 
                for (i=0 ; i<count ; i++)
                {
@@ -418,5 +470,6 @@ void SND_PaintChannelFrom16 (channel_t *ch, sfxcache_t *sc, int count)
        }
 
        ch->pos += count;
+       return true;
 }