views:

447

answers:

1

Can someone with FMOD experience please stop me from losing it. I cannot get these syncpoints to behave. I have some game music that consists of two pieces, an intro and a loop. They are separate sounds, and after the intro finishes, it begins the loop section which repeats forever. I set a syncpoint at the end of the intro to fire off the loop. It works just fine, until I try stopping and restarting the music (for example when the player dies). No matter what, the syncpoint insists on firing as soon as the intro is restarted, even though it's set for the end of the intro. The effect is that both sections of music are playing simultaneously - and on a single channel it seems, since I'm telling it to reuse the channel. Is that even possible? Here's some of my code (note that system, intro, loop, and channel are member variables):

public void Play()
{
    if (intro != null)
    {
        CHANNELINDEX index = (channel == null) ? CHANNELINDEX.FREE : CHANNELINDEX.REUSE;
        system.playSound(index, intro, false, ref channel);
        uint length = 0;
        intro.getLength(ref length, TIMEUNIT.MS);
        intro.addSyncPoint(length, TIMEUNIT.MS, "StartLoop", ref loopPtr);
        channel.setCallback(callback);
    }
    else system.playSound(CHANNELINDEX.FREE, loop, false, ref channel);
    Playing = true;
}

And here's the syncpoint:

private FMOD.RESULT SyncCallback(IntPtr c, CHANNEL_CALLBACKTYPE type, IntPtr a, IntPtr b)
{
    if (Playing)
    {
        RESULT result = intro.getSyncPoint(0, ref loopPtr);
        intro.deleteSyncPoint(loopPtr);
        system.playSound(CHANNELINDEX.REUSE, loop, false, ref channel);
    }
    return RESULT.OK;
}

At least, that's one version of the callback. I've tried about 20 others. Notice that I am telling it to delete the syncpoint - and when I checked the return it was OK. I tried a loop.deleteSyncPoint as well just in case. I also did a getsyncpointinfo on it to make sure it was my StartLoop syncpoint that was firing. Yet still it fires when play is called again, after a call to stop:

public void Stop()
{
    Playing = false;
    if (intro != null && loopPtr != IntPtr.Zero)
    {
        IntPtr ptr = IntPtr.Zero;
        RESULT result = intro.getSyncPoint(0, ref ptr);
        result = intro.deleteSyncPoint(ptr);
        result = intro.getSyncPoint(0, ref ptr);
        loopPtr = IntPtr.Zero;
    }
    channel.stop();
    channel.setPosition(0, TIMEUNIT.MS);
}

Notice that Stop() also tries to remove the syncpoint, but it fails to do so as well (even though the result comes back OK). I tried setting the channel position to 0 when stopping, that made it worse. I tried channel.stop() in my syncpoint after the deletesyncpoint() call, and yet that caused a stack overflow, because it kept calling the syncpoint on each call to stop, despite the attempt to remove it. Am I giving it the wrong pointer or something? I've tried making up some kind of flag to say to just not play the loop section, but I can't because it would be set in the middle of Play(), and the syncpoint is called right after Play() finishes, on the next call to the system update. Is FMOD broken or am I missing something obvious? Or something really obscure and undocumented...

+3  A: 

I just got it, and I hope this helps someone else, seeing as a google search for "fmod syncpoint" now returns this as the first result. The duplicates were because some of the callbacks were for the syncpoint type, and some were for end, because the intro section had ended. So with that, I realized I didn't even need my own syncpoints. I just have it using the ending of the intro as the trigger. Cleaner code, and works perfectly.

Tesserex