FMOD声音库 - 同步点让我疯狂!

时间:2009-12-21 15:10:51

标签: c# audio fmod

有FMOD经验的人可以阻止我失去它。我无法让这些同步点表现出来。我有一些游戏音乐,包括两个部分,一个介绍和一个循环。它们是独立的声音,在介绍结束后,它开始循环部分,永远重复。我在介绍的最后设置了一个同步点来触发循环。它工作得很好,直到我尝试停止并重新启动音乐(例如当播放器死亡时)。无论如何,同步点一旦重新开始介绍就会坚持触发,即使它是在介绍结束时设置的。结果是音乐的两个部分同时播放 - 而且似乎在单个频道上,因为我告诉它重用频道。这甚至可能吗?这是我的一些代码(注意系统,介绍,循环和通道是成员变量):

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;
}

这是同步点:

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;
}

至少,这是回调的一个版本。我已经尝试了大约20个人。请注意,我告诉它删除同步点 - 当我检查返回时它没关系。我尝试了一个loop.deleteSyncPoint以防万一。我还在它上面做了一个getsyncpointinfo,以确保它是我正在触发的StartLoop同步点。然而,在呼叫停止后再次呼叫时,它仍然会触发:

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);
}

请注意,Stop()也尝试删除同步点,但它也无法执行此操作(即使结果返回OK)。我在停止时尝试将通道位置设置为0,这使情况变得更糟。在deletesyncpoint()调用之后,我在同步点中尝试了channel.stop(),但这导致了堆栈溢出,因为它在每次调用时都一直调用同步点,尽管试图将其删除。我给它错误的指针或什么?我已经尝试编写某种标志来说不要播放循环部分,但我不能因为它将设置在Play()的中间,并且在Play()结束后立即调用同步点,在下次调用系统更新时。 FMOD坏了还是我遗漏了一些明显的东西?或者是一些非常模糊和无证的东西......

1 个答案:

答案 0 :(得分:5)

我刚刚得到它,我希望这有助于其他人,因为谷歌搜索“fmod syncpoint”现在返回这个作为第一个结果。重复是因为一些回调是针对同步点类型的,有些是为了结束,因为介绍部分已经结束。因此,我意识到我甚至不需要自己的同步点。我只是使用介绍的结尾作为触发器。更清洁的代码,并且工作得很好。