]> git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - snd_mem.c
Merge branch 'Mario/dpk_support' of gitlab.com:xonotic/darkplaces
[xonotic/darkplaces.git] / snd_mem.c
index a10b2631f62959b047ddadabd51f9219af3d86de..519ef0e27924a3049b533a8c6ee33ed64208161e 100644 (file)
--- a/snd_mem.c
+++ b/snd_mem.c
@@ -17,194 +17,66 @@ along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 */
-// snd_mem.c: sound caching
 
-#include "quakedef.h"
 
+#include "darkplaces.h"
+
+#include "snd_main.h"
 #include "snd_ogg.h"
 #include "snd_wav.h"
+#ifdef USEXMP
+#include "snd_xmp.h"
+#endif
+#include "sound.h"
 
+void SCR_PushLoadingScreen (const char *, float);
+void SCR_PopLoadingScreen (qbool);
 
 /*
-================
-ResampleSfx
-================
+====================
+Snd_CreateRingBuffer
+
+If "buffer" is NULL, the function allocates one buffer of "sampleframes" sample frames itself
+(if "sampleframes" is 0, the function chooses the size).
+====================
 */
-size_t ResampleSfx (const qbyte *in_data, size_t in_length, const snd_format_t* in_format, qbyte *out_data, const char* sfxname)
+snd_ringbuffer_t *Snd_CreateRingBuffer (const snd_format_t* format, unsigned int sampleframes, void* buffer)
 {
-       int samplefrac, fracstep;
-       size_t i, srcsample, srclength, outcount;
+       snd_ringbuffer_t *ringbuffer;
 
-       // this is usually 0.5 (128), 1 (256), or 2 (512)
-       fracstep = ((double) in_format->speed / (double) shm->format.speed) * 256.0;
+       // If the caller provides a buffer, it must give us its size
+       if (sampleframes == 0 && buffer != NULL)
+               return NULL;
 
-       srclength = in_length * in_format->channels;
+       ringbuffer = (snd_ringbuffer_t*)Mem_Alloc(snd_mempool, sizeof (*ringbuffer));
+       memset(ringbuffer, 0, sizeof(*ringbuffer));
+       memcpy(&ringbuffer->format, format, sizeof(ringbuffer->format));
 
-       outcount = (double) in_length * (double) shm->format.speed / (double) in_format->speed;
-       Con_DPrintf("ResampleSfx: resampling sound \"%s\" from %dHz to %dHz (%d samples to %d samples)\n",
-                               sfxname, in_format->speed, shm->format.speed, in_length, outcount);
+       // If we haven't been given a buffer
+       if (buffer == NULL)
+       {
+               unsigned int maxframes;
+               size_t memsize;
 
-// resample / decimate to the current source rate
+               if (sampleframes == 0)
+                       maxframes = (format->speed + 1) / 2;  // Make the sound buffer large enough for containing 0.5 sec of sound
+               else
+                       maxframes = sampleframes;
 
-       if (fracstep == 256)
-       {
-               // fast case for direct transfer
-               if (in_format->width == 1) // 8bit
-                       for (i = 0;i < srclength;i++)
-                               ((signed char *)out_data)[i] = ((unsigned char *)in_data)[i] - 128;
-               else //if (sb->width == 2) // 16bit
-                       for (i = 0;i < srclength;i++)
-                               ((short *)out_data)[i] = ((short *)in_data)[i];
+               memsize = maxframes * format->width * format->channels;
+               ringbuffer->ring = (unsigned char *) Mem_Alloc(snd_mempool, memsize);
+               ringbuffer->maxframes = maxframes;
        }
        else
        {
-               // general case
-               samplefrac = 0;
-               if ((fracstep & 255) == 0) // skipping points on perfect multiple
-               {
-                       srcsample = 0;
-                       fracstep >>= 8;
-                       if (in_format->width == 2)
-                       {
-                               short *out = (short*)out_data;
-                               const short *in = (const short*)in_data;
-                               if (in_format->channels == 2) // LordHavoc: stereo sound support
-                               {
-                                       fracstep <<= 1;
-                                       for (i=0 ; i<outcount ; i++)
-                                       {
-                                               *out++ = in[srcsample  ];
-                                               *out++ = in[srcsample+1];
-                                               srcsample += fracstep;
-                                       }
-                               }
-                               else
-                               {
-                                       for (i=0 ; i<outcount ; i++)
-                                       {
-                                               *out++ = in[srcsample];
-                                               srcsample += fracstep;
-                                       }
-                               }
-                       }
-                       else
-                       {
-                               signed char *out = out_data;
-                               const unsigned char *in = in_data;
-                               if (in_format->channels == 2)
-                               {
-                                       fracstep <<= 1;
-                                       for (i=0 ; i<outcount ; i++)
-                                       {
-                                               *out++ = in[srcsample  ] - 128;
-                                               *out++ = in[srcsample+1] - 128;
-                                               srcsample += fracstep;
-                                       }
-                               }
-                               else
-                               {
-                                       for (i=0 ; i<outcount ; i++)
-                                       {
-                                               *out++ = in[srcsample  ] - 128;
-                                               srcsample += fracstep;
-                                       }
-                               }
-                       }
-               }
-               else
-               {
-                       int sample;
-                       int a, b;
-                       if (in_format->width == 2)
-                       {
-                               short *out = (short*)out_data;
-                               const short *in = (const short*)in_data;
-                               if (in_format->channels == 2)
-                               {
-                                       for (i=0 ; i<outcount ; i++)
-                                       {
-                                               srcsample = (samplefrac >> 8) << 1;
-                                               a = in[srcsample  ];
-                                               if (srcsample+2 >= srclength)
-                                                       b = 0;
-                                               else
-                                                       b = in[srcsample+2];
-                                               sample = (((b - a) * (samplefrac & 255)) >> 8) + a;
-                                               *out++ = (short) sample;
-                                               a = in[srcsample+1];
-                                               if (srcsample+2 >= srclength)
-                                                       b = 0;
-                                               else
-                                                       b = in[srcsample+3];
-                                               sample = (((b - a) * (samplefrac & 255)) >> 8) + a;
-                                               *out++ = (short) sample;
-                                               samplefrac += fracstep;
-                                       }
-                               }
-                               else
-                               {
-                                       for (i=0 ; i<outcount ; i++)
-                                       {
-                                               srcsample = samplefrac >> 8;
-                                               a = in[srcsample  ];
-                                               if (srcsample+1 >= srclength)
-                                                       b = 0;
-                                               else
-                                                       b = in[srcsample+1];
-                                               sample = (((b - a) * (samplefrac & 255)) >> 8) + a;
-                                               *out++ = (short) sample;
-                                               samplefrac += fracstep;
-                                       }
-                               }
-                       }
-                       else
-                       {
-                               signed char *out = out_data;
-                               const unsigned char *in = in_data;
-                               if (in_format->channels == 2)
-                               {
-                                       for (i=0 ; i<outcount ; i++)
-                                       {
-                                               srcsample = (samplefrac >> 8) << 1;
-                                               a = (int) in[srcsample  ] - 128;
-                                               if (srcsample+2 >= srclength)
-                                                       b = 0;
-                                               else
-                                                       b = (int) in[srcsample+2] - 128;
-                                               sample = (((b - a) * (samplefrac & 255)) >> 8) + a;
-                                               *out++ = (signed char) sample;
-                                               a = (int) in[srcsample+1] - 128;
-                                               if (srcsample+2 >= srclength)
-                                                       b = 0;
-                                               else
-                                                       b = (int) in[srcsample+3] - 128;
-                                               sample = (((b - a) * (samplefrac & 255)) >> 8) + a;
-                                               *out++ = (signed char) sample;
-                                               samplefrac += fracstep;
-                                       }
-                               }
-                               else
-                               {
-                                       for (i=0 ; i<outcount ; i++)
-                                       {
-                                               srcsample = samplefrac >> 8;
-                                               a = (int) in[srcsample  ] - 128;
-                                               if (srcsample+1 >= srclength)
-                                                       b = 0;
-                                               else
-                                                       b = (int) in[srcsample+1] - 128;
-                                               sample = (((b - a) * (samplefrac & 255)) >> 8) + a;
-                                               *out++ = (signed char) sample;
-                                               samplefrac += fracstep;
-                                       }
-                               }
-                       }
-               }
+               ringbuffer->ring = (unsigned char *) buffer;
+               ringbuffer->maxframes = sampleframes;
        }
 
-       return outcount;
+       return ringbuffer;
 }
 
+
 //=============================================================================
 
 /*
@@ -212,67 +84,91 @@ size_t ResampleSfx (const qbyte *in_data, size_t in_length, const snd_format_t*
 S_LoadSound
 ==============
 */
-qboolean S_LoadSound (sfx_t *s, int complain)
+qbool S_LoadSound (sfx_t *sfx, qbool complain)
 {
-       char namebuffer[MAX_QPATH];
+       char namebuffer[MAX_QPATH + 16];
        size_t len;
-       qboolean modified_name = false;
 
-       // see if still in memory
-       if (!shm || !shm->format.speed)
-               return false;
-       if (s->fetcher != NULL)
-       {
-               if (s->format.speed != shm->format.speed)
-                       Sys_Error ("S_LoadSound: sound %s hasn't been resampled (%uHz instead of %uHz)", s->name);
+       // See if already loaded
+       if (sfx->fetcher != NULL)
                return true;
-       }
 
-       len = snprintf (namebuffer, sizeof (namebuffer), "sound/%s", s->name);
-       if (len >= sizeof (namebuffer))
+       // If we weren't able to load it previously, no need to retry
+       // Note: S_PrecacheSound clears this flag to cause a retry
+       if (sfx->flags & SFXFLAG_FILEMISSING)
                return false;
 
-       // Try to load it as a WAV file
-       if (S_LoadWavFile (namebuffer, s))
-               return true;
+       // No sound?
+       if (snd_renderbuffer == NULL)
+               return false;
 
-       // Else, try to load it as an Ogg Vorbis file
-       if (!strcasecmp (namebuffer + len - 4, ".wav"))
+       // Initialize volume peak to 0; if ReplayGain is supported, the loader will change this away
+       sfx->volume_peak = 0.0;
+
+       if (developer_loading.integer)
+               Con_Printf("loading sound %s\n", sfx->name);
+
+       SCR_PushLoadingScreen(sfx->name, 1);
+
+       // LadyHavoc: if the sound filename does not begin with sound/, try adding it
+       if (strncasecmp(sfx->name, "sound/", 6))
        {
-               strcpy (namebuffer + len - 3, "ogg");
-               modified_name = true;
+               dpsnprintf (namebuffer, sizeof(namebuffer), "sound/%s", sfx->name);
+               len = strlen(namebuffer);
+               if (len >= 4 && !strcasecmp (namebuffer + len - 4, ".wav"))
+               {
+                       if (S_LoadWavFile (namebuffer, sfx))
+                               goto loaded;
+                       memcpy (namebuffer + len - 3, "ogg", 4);
+               }
+               if (len >= 4 && !strcasecmp (namebuffer + len - 4, ".ogg"))
+               {
+                       if (OGG_LoadVorbisFile (namebuffer, sfx))
+                               goto loaded;
+               }
+#ifdef USEXMP
+               else if (len >= 1)
+               {
+                       if (XMP_LoadModFile (namebuffer, sfx))
+                               goto loaded;
+               }
+#endif
        }
-       if (OGG_LoadVorbisFile (namebuffer, s))
-               return true;
 
-       // Can't load the sound!
-       if (!complain)
-               s->flags |= SFXFLAG_SILENTLYMISSING;
-       else
-               s->flags &= ~SFXFLAG_SILENTLYMISSING;
-       if (complain)
+       // LadyHavoc: then try without the added sound/ as wav and ogg
+       dpsnprintf (namebuffer, sizeof(namebuffer), "%s", sfx->name);
+       len = strlen(namebuffer);
+       // request foo.wav: tries foo.wav, then foo.ogg
+       // request foo.ogg: tries foo.ogg only
+       // request foo.mod: tries foo.mod only
+       if (len >= 4 && !strcasecmp (namebuffer + len - 4, ".wav"))
        {
-               if (modified_name)
-                       strcpy (namebuffer + len - 3, "wav");
-               Con_Printf("Couldn't load %s\n", namebuffer);
+               if (S_LoadWavFile (namebuffer, sfx))
+                       goto loaded;
+               memcpy (namebuffer + len - 3, "ogg", 4);
        }
-       return false;
-}
-
-void S_UnloadSound(sfx_t *s)
-{
-       if (s->fetcher != NULL)
+       if (len >= 4 && !strcasecmp (namebuffer + len - 4, ".ogg"))
        {
-               unsigned int i;
+               if (OGG_LoadVorbisFile (namebuffer, sfx))
+                       goto loaded;
+       }
+#ifdef USEXMP
+       else if (len >= 1)
+       {
+               if (XMP_LoadModFile (namebuffer, sfx))
+                       goto loaded;
+       }
+#endif
 
-               s->fetcher = NULL;
-               s->fetcher_data = NULL;
-               Mem_FreePool(&s->mempool);
+       // Can't load the sound!
+       sfx->flags |= SFXFLAG_FILEMISSING;
+       if (complain)
+               Con_Printf(CON_ERROR "Failed to load sound \"%s\"\n", sfx->name);
 
-               // At this point, some per-channel data pointers may point to freed zones.
-               // Practically, it shouldn't be a problem; but it's wrong, so we fix that
-               for (i = 0; i < total_channels ; i++)
-                       if (channels[i].sfx == s)
-                               channels[i].fetcher_data = NULL;
-       }
+       SCR_PopLoadingScreen(false);
+       return false;
+
+loaded:
+       SCR_PopLoadingScreen(false);
+       return true;
 }