X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=snd_ogg.c;h=17ddc1b833d8537696a36fe26066dc4327bc61dc;hb=bbfa10a406fd3f7ae77aa2d3ec8bfba1da795f88;hp=ccedb504c5e7260d69c3b6e5bc5d7246871425d1;hpb=f7d63b738768163fd9cdd0bfcfaba910d2b6587a;p=xonotic%2Fdarkplaces.git diff --git a/snd_ogg.c b/snd_ogg.c index ccedb504..17ddc1b8 100644 --- 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", @@ -567,23 +558,16 @@ static const snd_buffer_t* OGG_FetchSound (void *sfxfetcher, void **chfetcherpoi OGG_FetchEnd ==================== */ -static void OGG_FetchEnd (channel_t* ch) +static void OGG_FetchEnd (void *chfetcherdata) { - ogg_stream_perchannel_t* per_ch; + ogg_stream_perchannel_t* per_ch = (ogg_stream_perchannel_t *)chfetcherdata; - per_ch = (ogg_stream_perchannel_t *)ch->fetcher_data; if (per_ch != NULL) { - size_t buff_len; - // Free the ogg vorbis decoder qov_clear (&per_ch->vf); - buff_len = per_ch->sb.maxframes * per_ch->sb.format.channels * per_ch->sb.format.width; - ch->sfx->memsize -= sizeof (*per_ch) - sizeof (per_ch->sb.samples) + buff_len; - Mem_Free (per_ch); - ch->fetcher_data = NULL; } } @@ -593,20 +577,15 @@ static void OGG_FetchEnd (channel_t* ch) OGG_FreeSfx ==================== */ -static void OGG_FreeSfx (sfx_t* sfx) +static void OGG_FreeSfx (void *sfxfetcherdata) { - ogg_stream_persfx_t* per_sfx = (ogg_stream_persfx_t *)sfx->fetcher_data; + ogg_stream_persfx_t* per_sfx = (ogg_stream_persfx_t *)sfxfetcherdata; // Free the Ogg Vorbis file Mem_Free(per_sfx->file); - sfx->memsize -= per_sfx->filesize; // Free the stream structure Mem_Free(per_sfx); - sfx->memsize -= sizeof (*per_sfx); - - sfx->fetcher_data = NULL; - sfx->fetcher = NULL; } @@ -623,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); + } +} /* ==================== @@ -634,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; @@ -654,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; @@ -686,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); @@ -701,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 { @@ -720,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); @@ -753,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; }