From 1f0693eca463f4e01df2907ecda87402ebf44f67 Mon Sep 17 00:00:00 2001 From: hendricks266 Date: Sat, 24 Nov 2012 09:12:15 +0000 Subject: [PATCH] Implement OGG looping support; musicians rejoice! Loops are controlled by two tags in the Vorbis Comment, both in PCM samples. LOOP_START holds the beginning of the loop, the position to which playback returns at the end of the loop. LOOP_END is optional; it holds the end of the loop, after which the game seeks to LOOP_START. If undefined, the end of the OGG is the end of the loop. The primary purpose of LOOP_END is if you want to give your file a proper ending for listening outside the game. To preview a looped OGG you have assembled, give it a ".logg" extension and play it using the vgmstream plugin for Winamp or foobar2000. git-svn-id: https://svn.eduke32.com/eduke32@3218 1a8010ca-5511-0410-912e-c29ae57300e0 --- polymer/eduke32/source/jaudiolib/src/vorbis.c | 60 ++++++++++++++++--- 1 file changed, 51 insertions(+), 9 deletions(-) diff --git a/polymer/eduke32/source/jaudiolib/src/vorbis.c b/polymer/eduke32/source/jaudiolib/src/vorbis.c index 7b5ef584c..8ec7a99dd 100644 --- a/polymer/eduke32/source/jaudiolib/src/vorbis.c +++ b/polymer/eduke32/source/jaudiolib/src/vorbis.c @@ -158,13 +158,27 @@ static playbackstatus MV_GetNextVorbisBlock do { bytes = ov_read(&vd->vf, vd->block + bytesread, BLOCKSIZE - bytesread, 0, 2, 1, &bitstream); //fprintf(stderr, "ov_read = %d\n", bytes); - if (bytes > 0) { bytesread += bytes; continue; } + if (bytes > 0) { + bytesread += bytes; + if ((ogg_int64_t)(intptr_t)voice->LoopEnd > 0 + && ov_pcm_tell(&vd->vf) >= (ogg_int64_t)(intptr_t)voice->LoopEnd) { + err = ov_pcm_seek(&vd->vf,(ogg_int64_t)(intptr_t)voice->LoopStart); + if (err != 0) { + MV_Printf("MV_GetNextVorbisBlock ov_pcm_seek: LOOP_START %l, LOOP_END %l, err %d\n", + (ogg_int64_t)(intptr_t)voice->LoopStart, (ogg_int64_t)(intptr_t)voice->LoopEnd, err); + } else { + continue; + } + } + continue; + } else if (bytes == OV_HOLE) continue; else if (bytes == 0) { - if (voice->LoopStart) { - err = ov_pcm_seek_page(&vd->vf, 0); + if (voice->LoopSize > 0) { + err = ov_pcm_seek(&vd->vf,(ogg_int64_t)(intptr_t)voice->LoopStart); if (err != 0) { - MV_Printf("MV_GetNextVorbisBlock ov_pcm_seek_page_lap: err %d\n", err); + MV_Printf("MV_GetNextVorbisBlock ov_pcm_seek: LOOP_START %l, err %d\n", + (ogg_int64_t)(intptr_t)voice->LoopStart, err); } else { continue; } @@ -319,8 +333,6 @@ int32_t MV_PlayLoopedVorbis int32_t status; vorbis_data * vd = 0; vorbis_info * vi = 0; - - UNREFERENCED_PARAMETER(loopend); if ( !MV_Installed ) { @@ -387,9 +399,39 @@ int32_t MV_PlayLoopedVorbis voice->prev = NULL; voice->priority = priority; voice->callbackval = callbackval; - voice->LoopStart = (char *) (intptr_t)(loopstart >= 0 ? TRUE : FALSE); - voice->LoopEnd = 0; - voice->LoopSize = 0; + + voice->LoopStart = (char *) (intptr_t)(loopstart >= 0 ? loopstart : 0); + voice->LoopEnd = (char *) (intptr_t)(loopstart >= 0 && loopend > 0 ? loopend : 0); + voice->LoopSize = (loopstart >= 0 ? 1 : 0); + + // load loop tags from metadata + if (loopstart < 1) + { + vorbis_comment * vc = ov_comment(&vd->vf, 0); + if (vc != NULL) + { + char *vc_loopstart = vorbis_comment_query(vc, "LOOP_START", 0); + if (vc_loopstart != NULL) + { + ogg_int64_t ov_loopstart = atol(vc_loopstart); + if (ov_loopstart >= 0) + { + char *vc_loopend = vorbis_comment_query(vc, "LOOP_END", 0); + + voice->LoopStart = (char *) (intptr_t) ov_loopstart; + voice->LoopSize = 1; + + if (vc_loopend != NULL) + { + ogg_int64_t ov_loopend = atol(vc_loopend); + if (ov_loopend > 0) + voice->LoopEnd = (char *) (intptr_t) ov_loopend; + } + } + } + } + } + voice->Playing = TRUE; voice->Paused = FALSE;