8
\$\begingroup\$

I'm programming a little Music Engine for my game in C# and XNA, and one aspect from it is the possibility to loop a section from a song. For example, my song has an intropart, and when the song reached the end ( or any other specific point ), it jumps back where the intropart is just over. ( A - B - B - B ... )

Now I'm using IrrKlank, which is working perfectly, without any gaps, but I have a problem:

The point where to jump back is a bit inaccurate. Here's some example code:

public bool Passed(float time)
    {
        if ( PlayPosition >= time )
            return true;
        return false;
    }
//somewhere else
if( song.Passed( 10.0f ) )
   song.JumpTo( 5.0f );

Now the problem is, the song passes the 10 seconds, but play a few milliseconds until 10.1f or so, and then jumps to 5 seconds. It's not that dramatic, but very incorrect for my needs. I tried to fix it like that:

public bool Passed( float time )
{
      if( PlayPosition + 3 * dt >= time && PlayPosition <= time )
             return true;
      return false;
}

( dt is the delta time, the elapsed time since the last frame )

But I don't think, that's a good solution for that.

I hope, you can understand my problem ( and my english, yay /o/ ) and help me :)

\$\endgroup\$
6
  • \$\begingroup\$ Can you choose between streaming the sound or loading it all at once? \$\endgroup\$
    – tesselode
    Commented Sep 22, 2012 at 14:56
  • \$\begingroup\$ I think it's possible. At the moment I'm loading the complete song, because I thought, jumping around in the song would be faster. I'm trying Multithreading to solve this problem, but I'm still unlucky :/ \$\endgroup\$
    – Teflo
    Commented Sep 22, 2012 at 17:16
  • \$\begingroup\$ Try streaming the sound instead. After all, it should be able to load a small chunk of the song almost instantly. \$\endgroup\$
    – tesselode
    Commented Sep 22, 2012 at 18:05
  • \$\begingroup\$ How is your song encoded? \$\endgroup\$ Commented Sep 22, 2012 at 18:44
  • \$\begingroup\$ Perhaps instead of using "passed" you could add ques ( like events ) that do a callback function. I don't know how you manage your time. But couldn't you use the amount of bytes read so far and compare it to the total amount of bytes an translate it to an accurate time? You should be able to calculate how much data is read in one second. I don't know how fast this would go though. But maybe then you could read the time more precise. \$\endgroup\$
    – Sidar
    Commented Sep 23, 2012 at 8:42

2 Answers 2

3
\$\begingroup\$

In my opinion, a simpler and more usual solution is having two different tracks: an intro and a loop section. Then, the only problem is detecting when the intro ends (quite easy, albeit not perfectly precise if using 30fps). Then the second track can be played with looping enabled.

Thus, you reduce the errors in the reproduction to a slight delay when starting the loop for the first time, instead of everytime the loop section has to be rewinded.

\$\endgroup\$
0
\$\begingroup\$

The ideal solution would be to know beforehand which parts of the song need to be loaded next into the buffer. Each 'section' A - B - C would have a start and end time, and it would be your lower level streaming system that would load the correct parts of the file in the correct order. You would have to have a fixed bitrate for this to work though, and it could be quite difficult finding where in the file you need to skip to next.

I had a quick look at the irrKlang site and they boast about the possibility to write your own file format readers/decoders to extend the engine with it, so you may want to give that a shot.

There is also a tutorial here to override the file access - you could give my original idea a shot, or you could mix it up with multiple sounds like Elideb said. You could extend your CMyReadFile class to have access to multiple files (like PartA.wav, PartB.wav, PartC.wav), and you could override the read method, so rather than just :

return (s32)fread(buffer, 1, sizeToRead, File);

You could do something like :

switch(CurrentSectionToPlay)
{
case A:
    return (s32)fread(buffer, 1, sizeToRead, FileA);
case B:
    return (s32)fread(buffer, 1, sizeToRead, FileB);
}

Which means the song would seamlessly change section without having to synchro Plays & Stops.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .