]> git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - snd_ogg.c
fix errors and warnings in MSVC when compiling as C++
[xonotic/darkplaces.git] / snd_ogg.c
index 28ccab1b9b38048ee194921a2ecf426fbcf33849..17ddc1b833d8537696a36fe26066dc4327bc61dc 100644 (file)
--- a/snd_ogg.c
+++ b/snd_ogg.c
@@ -353,16 +353,7 @@ qboolean OGG_OpenLibrary (void)
        // Load the DLLs
        // We need to load both by hand because some OSes seem to not load
        // the vorbis DLL automatically when loading the VorbisFile DLL
-       if (! Sys_LoadLibrary (dllnames_vo, &vo_dll, vorbisfuncs) ||
-               ! Sys_LoadLibrary (dllnames_vf, &vf_dll, vorbisfilefuncs))
-       {
-               Sys_UnloadLibrary (&vo_dll);
-               Con_Printf ("Ogg Vorbis support disabled\n");
-               return false;
-       }
-
-       Con_Printf ("Ogg Vorbis support enabled\n");
-       return true;
+       return Sys_LoadLibrary (dllnames_vo, &vo_dll, vorbisfuncs) && Sys_LoadLibrary (dllnames_vf, &vf_dll, vorbisfilefuncs);
 }
 
 
@@ -514,7 +505,7 @@ static const snd_buffer_t* OGG_FetchSound (void *sfxfetcher, void **chfetcherpoi
                }
                sb->nbframes = 0;
 
-               real_start = (float)ogg_start / per_sfx->format.speed * snd_renderbuffer->format.speed;
+               real_start = (unsigned int) ((float)ogg_start / per_sfx->format.speed * snd_renderbuffer->format.speed);
                if (*start - real_start + nbsampleframes > sb->maxframes)
                {
                        Con_Printf ("OGG_FetchSound: stream buffer too small after seek (%u sample frames required)\n",
@@ -611,6 +602,56 @@ static const snd_format_t* OGG_GetFormat (sfx_t* sfx)
 
 static const snd_fetcher_t ogg_fetcher = { OGG_FetchSound, OGG_FetchEnd, OGG_FreeSfx, OGG_GetFormat };
 
+static void OGG_DecodeTags(vorbis_comment *vc, unsigned int *start, unsigned int *length, double samplesfactor, unsigned int numsamples, double *peak, double *gaindb)
+{
+       const char *startcomment = NULL, *lengthcomment = NULL, *endcomment = NULL, *thiscomment = NULL;
+
+       *start = numsamples;
+       *length = numsamples;
+       *peak = 0.0;
+       *gaindb = 0.0;
+
+       if(!vc)
+               return;
+
+       thiscomment = qvorbis_comment_query(vc, "REPLAYGAIN_TRACK_PEAK", 0);
+       if(thiscomment)
+               *peak = atof(thiscomment);
+       thiscomment = qvorbis_comment_query(vc, "REPLAYGAIN_TRACK_GAIN", 0);
+       if(thiscomment)
+               *gaindb = atof(thiscomment);
+       
+       startcomment = qvorbis_comment_query(vc, "LOOP_START", 0); // DarkPlaces, and some Japanese app
+       if(startcomment)
+       {
+               endcomment = qvorbis_comment_query(vc, "LOOP_END", 0);
+               if(!endcomment)
+                       lengthcomment = qvorbis_comment_query(vc, "LOOP_LENGTH", 0);
+       }
+       else
+       {
+               startcomment = qvorbis_comment_query(vc, "LOOPSTART", 0); // RPG Maker VX
+               if(startcomment)
+               {
+                       lengthcomment = qvorbis_comment_query(vc, "LOOPLENGTH", 0);
+                       if(!lengthcomment)
+                               endcomment = qvorbis_comment_query(vc, "LOOPEND", 0);
+               }
+               else
+               {
+                       startcomment = qvorbis_comment_query(vc, "LOOPPOINT", 0); // Sonic Robo Blast 2
+               }
+       }
+
+       if(startcomment)
+       {
+               *start = (unsigned int) bound(0, atof(startcomment) * samplesfactor, numsamples);
+               if(endcomment)
+                       *length = (unsigned int) bound(0, atof(endcomment) * samplesfactor, numsamples);
+               else if(lengthcomment)
+                       *length = (unsigned int) bound(0, *start + atof(lengthcomment) * samplesfactor, numsamples);
+       }
+}
 
 /*
 ====================
@@ -622,13 +663,13 @@ Load an Ogg Vorbis file into memory
 qboolean OGG_LoadVorbisFile (const char *filename, sfx_t *sfx)
 {
        unsigned char *data;
-       const char *loopcomment;
        fs_offset_t filesize;
        ov_decode_t ov_decode;
        OggVorbis_File vf;
        vorbis_info *vi;
        vorbis_comment *vc;
        ogg_int64_t len, buff_len;
+       double peak, gaindb;
 
        if (!vf_dll)
                return false;
@@ -642,7 +683,8 @@ qboolean OGG_LoadVorbisFile (const char *filename, sfx_t *sfx)
        if (data == NULL)
                return false;
 
-       Con_DPrintf ("Loading Ogg Vorbis file \"%s\"\n", filename);
+       if (developer_loading.integer >= 2)
+               Con_Printf ("Loading Ogg Vorbis file \"%s\"\n", filename);
 
        // Open it with the VorbisFile API
        ov_decode.buffer = data;
@@ -674,7 +716,8 @@ qboolean OGG_LoadVorbisFile (const char *filename, sfx_t *sfx)
        {
                ogg_stream_persfx_t* per_sfx;
 
-               Con_DPrintf ("\"%s\" will be streamed\n", filename);
+               if (developer_loading.integer >= 2)
+                       Con_Printf ("Ogg sound file \"%s\" will be streamed\n", filename);
                per_sfx = (ogg_stream_persfx_t *)Mem_Alloc (snd_mempool, sizeof (*per_sfx));
                strlcpy(per_sfx->name, sfx->name, sizeof(per_sfx->name));
                sfx->memsize += sizeof (*per_sfx);
@@ -689,15 +732,11 @@ qboolean OGG_LoadVorbisFile (const char *filename, sfx_t *sfx)
                sfx->fetcher_data = per_sfx;
                sfx->fetcher = &ogg_fetcher;
                sfx->flags |= SFXFLAG_STREAMED;
-               per_sfx->total_length = sfx->total_length = (int)((size_t)len / (per_sfx->format.channels * 2) * ((double)snd_renderbuffer->format.speed / per_sfx->format.speed));
-               sfx->loopstart = sfx->total_length;
+               sfx->total_length = (int)((size_t)len / (per_sfx->format.channels * 2) * ((double)snd_renderbuffer->format.speed / per_sfx->format.speed));
                vc = qov_comment(&vf, -1);
-               if(vc)
-               {
-                       loopcomment = qvorbis_comment_query(vc, "LOOP_START", 0);
-                       if(loopcomment)
-                               sfx->loopstart = bound(0, (unsigned int) (atof(loopcomment) * (double)snd_renderbuffer->format.speed / (double)per_sfx->format.speed), sfx->total_length);
-               }
+               OGG_DecodeTags(vc, &sfx->loopstart, &sfx->total_length, (double)snd_renderbuffer->format.speed / (double)per_sfx->format.speed, sfx->total_length, &peak, &gaindb);
+               per_sfx->total_length = sfx->total_length;
+               qov_clear (&vf);
        }
        else
        {
@@ -708,7 +747,8 @@ qboolean OGG_LoadVorbisFile (const char *filename, sfx_t *sfx)
                snd_buffer_t *sb;
                snd_format_t ogg_format;
 
-               Con_DPrintf ("\"%s\" will be cached\n", filename);
+               if (developer_loading.integer >= 2)
+                       Con_Printf ("Ogg sound file \"%s\" will be cached\n", filename);
 
                // Decode it
                buff = (char *)Mem_Alloc (snd_mempool, (int)len);
@@ -741,20 +781,22 @@ qboolean OGG_LoadVorbisFile (const char *filename, sfx_t *sfx)
                sfx->total_length = sb->nbframes;
                sfx->memsize += sb->maxframes * sb->format.channels * sb->format.width + sizeof (*sb) - sizeof (sb->samples);
 
-               sfx->loopstart = sfx->total_length;
                sfx->flags &= ~SFXFLAG_STREAMED;
                vc = qov_comment(&vf, -1);
-               if(vc)
-               {
-                       loopcomment = qvorbis_comment_query(vc, "LOOP_START", 0);
-                       if(loopcomment)
-                               sfx->loopstart = bound(0, (unsigned int) (atoi(loopcomment) * (double)snd_renderbuffer->format.speed / (double)sb->format.speed), sfx->total_length);
-               }
-
+               OGG_DecodeTags(vc, &sfx->loopstart, &sfx->total_length, (double)snd_renderbuffer->format.speed / (double)sb->format.speed, sfx->total_length, &peak, &gaindb);
+               sb->nbframes = sfx->total_length;
                qov_clear (&vf);
                Mem_Free (data);
                Mem_Free (buff);
        }
 
+       if(peak)
+       {
+               sfx->volume_mult = min(1.0f / peak, exp(gaindb * 0.05f * log(10.0f)));
+               sfx->volume_peak = peak;
+               if (developer_loading.integer >= 2)
+                       Con_Printf ("Ogg sound file \"%s\" uses ReplayGain (gain %f, peak %f)\n", filename, sfx->volume_mult, sfx->volume_peak);
+       }
+
        return true;
 }