Звуковая библиотека FMOD - точки синхронизации сводят меня с ума! - PullRequest
1 голос
/ 21 декабря 2009

Может кто-то с опытом FMOD, пожалуйста, не дайте мне потерять его. Я не могу заставить эти syncpoints вести себя. У меня есть немного игровой музыки, которая состоит из двух частей, вступления и цикла. Это отдельные звуки, и после того, как вступление заканчивается, начинается цикл, который повторяется вечно. Я установил синхронизацию в конце вступления, чтобы запустить цикл. Это работает просто отлично, пока я не попробую остановить и перезапустить музыку (например, когда плеер умирает). Независимо от того, что Syncpoint настаивает на стрельбе, как только вступление перезапускается, даже если оно настроено на конец вступления. Эффект состоит в том, что обе части музыки воспроизводятся одновременно - и на одном канале это кажется, так как я говорю ему повторно использовать канал. Это вообще возможно? Вот часть моего кода (обратите внимание, что system, intro, loop и channel являются переменными-членами):

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 на всякий случай. Я также выполнил getyncpointinfo, чтобы убедиться, что запускается моя точка синхронизации StartLoop. И все же он срабатывает, когда игра снова вызывается, после вызова 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);
}

Обратите внимание, что Stop () также пытается удалить точку синхронизации, но также не может это сделать (даже если результат возвращается в порядке). Я пытался установить позицию канала на 0 при остановке, что ухудшило ситуацию. Я попробовал channel.stop () в моей точке синхронизации после вызова deletetesyncpoint (), и все же это вызвало переполнение стека, потому что он продолжал вызывать синхронизацию при каждом вызове до остановки, несмотря на попытку удалить ее. Я даю неправильный указатель или что-то в этом роде? Я попытался создать какой-то флаг, чтобы сказать, что он просто не воспроизводит секцию цикла, но я не могу, потому что он будет установлен в середине Play (), а точка синхронизации вызывается сразу после завершения Play (), при следующем обращении к обновлению системы. FMOD не работает или я упускаю что-то очевидное? Или что-то действительно неясное и недокументированное ...

1 Ответ

5 голосов
/ 21 декабря 2009

Я только что получил, и я надеюсь, что это поможет кому-то еще, поскольку поиск в Google по запросу "fmod syncpoint" теперь возвращает это как первый результат. Дубликаты возникли из-за того, что некоторые обратные вызовы были для типа syncpoint, а некоторые для конца, потому что вступительный раздел закончился. Поэтому я понял, что мне даже не нужны мои собственные точки синхронизации. Я просто использую окончание вступления в качестве триггера. Более чистый код и отлично работает.

...