FMOD Ex掉声,最终沉默

时间:2015-02-21 17:39:22

标签: macos audio fmod

我正在尝试将旧的开源FMOD 3游戏(Candy Crisis)移植到OS X上的最新版FMOD Ex 4.它的声音需求非常简单 - 它播放WAV,有时会改变它们的频率或扬声器混音,还播放MOD跟踪音乐,有时会改变速度。我发现游戏最初工作正常,但在几分钟内,它开始提前截断声音,然后音乐失去频道并最终停止,然后随着时间推移所有声音停止。如果我降低可用于FMOD的频道数量,我可以更快地重现问题。

即使我从不播放音乐文件,我也可以发现截断/丢失的声音问题,但音乐肯定会让事情变得更糟。我也试着评出调整声音频率和扬声器组合的代码,这不是问题。

我每帧都在呼叫update()

以下是我与FMOD进行WAV互动的全部内容:

void InitSound( void )
{
    FMOD_RESULT   result = FMOD::System_Create(&g_fmod);
    FMOD_ERRCHECK(result);

    unsigned int  version;
    result = g_fmod->getVersion(&version);
    FMOD_ERRCHECK(result);

    if (version < FMOD_VERSION)
    {
        printf("Error!  You are using an old version of FMOD %08x.  This program requires %08x\n", version, FMOD_VERSION);
        abort();
    }

    result = g_fmod->init(8 /* was originally 64, but 8 repros the issue faster */, FMOD_INIT_NORMAL, 0);
    FMOD_ERRCHECK(result);

    for (int index=0; index<kNumSounds; index++)
    {
        result = g_fmod->createSound(QuickResourceName("snd", index+128, ".wav"), FMOD_DEFAULT, 0, &s_sound[index]);
        FMOD_ERRCHECK(result);
    }
}


void PlayMono( short which )
{
    if (soundOn)
    {
        FMOD_RESULT       result = g_fmod->playSound(FMOD_CHANNEL_FREE, s_sound[which], false, NULL);
        FMOD_ERRCHECK(result);
    }
}

void PlayStereoFrequency( short player, short which, short freq )
{
    if (soundOn)
    {
        FMOD::Channel*    channel = NULL;
        FMOD_RESULT       result = g_fmod->playSound(FMOD_CHANNEL_FREE, s_sound[which], true, &channel);
        FMOD_ERRCHECK(result);

        result = channel->setSpeakerMix(player, 1.0f - player, 0, 0, 0, 0, 0, 0);
        FMOD_ERRCHECK(result);

        float channelFrequency;
        result = s_sound[which]->getDefaults(&channelFrequency, NULL, NULL, NULL);
        FMOD_ERRCHECK(result);

        result = channel->setFrequency((channelFrequency * (16 + freq)) / 16);
        FMOD_ERRCHECK(result);

        result = channel->setPaused(false);
        FMOD_ERRCHECK(result);
    }
}

void UpdateSound()
{
    g_fmod->update();
}

这就是我玩MOD的方式。

void ChooseMusic( short which )
{
    if( musicSelection >= 0 && musicSelection <= k_songs )  
    {
        s_musicChannel->stop();
        s_musicChannel = NULL;

        s_musicModule->release();
        s_musicModule = NULL;

        musicSelection = -1;
    }

    if (which >= 0 && which <= k_songs)
    {
        FMOD_RESULT result = g_fmod->createSound(QuickResourceName("mod", which+128, ""), FMOD_DEFAULT, 0, &s_musicModule);
        FMOD_ERRCHECK(result);

        result = g_fmod->playSound(FMOD_CHANNEL_FREE, s_musicModule, true, &s_musicChannel);
        FMOD_ERRCHECK(result);

        EnableMusic(musicOn);
        s_musicModule->setLoopCount(-1);
        s_musicChannel->setPaused(false);

        musicSelection = which;
        s_musicPaused  = 0;
    }
}

如果有人想要试验这个,请告诉我,我会将项目上传到某处。我的直觉是FMOD被破坏但我很想被证明是错误的。

3 个答案:

答案 0 :(得分:2)

听起来您的音乐需要设置为比其他声音更高的优先级。请记住,较低的数字更重要。我想你可以在频道上设置优先级。

答案 1 :(得分:2)

每次播放以下WAV时,FMOD会永久丢失一个频道。我能够在&#34; playound&#34;中重现这种失去通道的行为。例如,如果我用我的文件替换现有的jaguar.wav。

https://drive.google.com/file/d/0B1eDRY8sV_a9SXMyNktXbWZOYWs/view?usp=sharing

我联系了Firelight并得到了回复。显然WAV可以包含循环命令!我不知道。

  

你好约翰,

     

我已经查看了您提供的两个文件。两个文件都结束了   具有2个样本无限循环区域。

     

FMOD 4(以及FMOD 5)将看到中的循环区域   文件并自动启用FMOD_LOOP_NORMAL,如果你还没有   指定任何循环模式。假设你想要一次性行为就过去了   在创建声音时在FMOD_LOOP_OFF中。

     

亲切的问候,Mathew Block |高级平台工程师

从技术上讲,这种行为与FMOD_DEFAULT(指定隐含FMOD_LOOP_OFF)的记录行为相矛盾,因此他们计划在此处改进文档。

答案 2 :(得分:2)

根据您提供的波形示例,FMOD的行为正确,因为您看起来已经找到了。样本有一个受FMOD尊重的循环,最后的样本只是永远重复。虽然没用,但这是正确的,并且样本中的差异很小,以至于听不到。虽然不是波形格式的原始规范的一部分,但后来添加了扩展信息以支持元数据,例如作者,标题,注释和多个循环点。

最好的办法是检查包含循环信息的所有源资产。简单地播放没有循环信息的所有声音可能不是最好的解决方法。一些循环可能是有意的。那些将有代码阻止他们。通常,在游戏中,当需要循环时,整个波形是循环的。然后,您可以编写或使用将剥离循环信息的工具。如果您确实编写了自己的工具,我建议您将音频重新采样到硬件的本机输出采样率。您需要确保您的重新采样器样本准确(没有时移)并且不会引入噪音。

历史上,有些游戏系统在声音结尾处有一个部分,在此区域设置了静音和循环点。原因很简单,就是减少硬件音频通道声音结束时可能出现的弹出声。

好奇地,你的.wav的最后16个样本看起来像垃圾,我想知道你使用的.wav资产是否是从用于游戏控制台的源转换而来的,这是伪造循环信息来自哪里好。

这可能是一个评论,但我的低级代表不允许。