We are currently migrating Bugzilla to GitHub issues.
Any changes made to the bug tracker now will be lost, so please do not post new bugs or make changes to them.
When we're done, all bug URLs will redirect to their equivalent location on the new bug tracker.

Bug 463

Summary: OGG Music Looping Isn't Seamless
Product: SDL_mixer Reporter: Alec Holowka <zaphire>
Component: miscAssignee: Ryan C. Gordon <icculus>
Status: RESOLVED FIXED QA Contact: Sam Lantinga <slouken>
Severity: major    
Priority: P2    
Version: unspecified   
Hardware: All   
OS: Other   

Description Alec Holowka 2007-07-20 06:35:22 UTC
Can be reproduced with playmus -l

Test file:

http://zaphire.ca/sdl_mixer/test.ogg
Comment 1 Sam Lantinga 2007-07-21 00:48:59 UTC
It looks like this will take a fair bit of rework of the music mixing loop.  Ryan, you want to tackle that for SDL_mixer 1.2.9?
Comment 2 Alec Holowka 2007-07-21 01:11:48 UTC
Some info:

This thread on GameDev.net has some example code for looping to fill up the buffer from ov_read for seamless looping: http://www.gamedev.net/community/forums/topic.asp?topic_id=221938

It seems like that needs to be implemented in OGG_getsome(...)

One question is how OGG_getsome(...) should get access to the loop counter. The loop stuff is done at the higher level (checked in music_halt_or_loop), but for seamless it needs to be implemented at the buffer level.

I'd try to mess with it myself, but I'm not really sure how to go about tweaking the design.
Comment 3 Alec Holowka 2007-07-21 07:35:17 UTC
this seems to make looping seamless for me, but i'm not sure how robust/solid it is.

hacky: not sure how to get at the real loop variable, etc. (always loops)

#define OGG_BUFFER_SIZE 4096
/* Read some Ogg stream data and convert it for output */
static void OGG_getsome(OGG_music *music)
{

	int section;
	int len;
	char data[OGG_BUFFER_SIZE];
	SDL_AudioCVT *cvt;

	int looping = 1;
	int total_len = 0;

	while (total_len < OGG_BUFFER_SIZE)
	{

#ifdef OGG_USE_TREMOR
		len = vorbis.ov_read(&music->vf, data + total_len, OGG_BUFFER_SIZE - total_len, &section);
#else
		len = vorbis.ov_read(&music->vf, data + total_len, OGG_BUFFER_SIZE - total_len, 0, 2, 1, &section);
#endif

		total_len += len;

		if(len <= 0)
		{
			if(looping==1)
			{
				vorbis.ov_time_seek(&music->vf, 0);
			}
			else 
			{
				music->playing = 0;
				return;
			}
		}
		else
		{
			break;
		}
	}
Comment 4 Sam Lantinga 2009-10-02 07:16:34 UTC
This is fixed for the next release, thanks!