【问题标题】:FMOD Ex dropping sounds, eventually going silentFMOD Ex 掉落声音,最终静音
【发布时间】:2015-02-21 17:39:21
【问题描述】:

我正在尝试将旧的开源 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 失败了,但我很想被证明是错误的。

【问题讨论】:

    标签: macos audio fmod


    【解决方案1】:

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

    【讨论】:

    • 这就像一个魅力。我没有意识到 WAV 默认与 MOD 具有相同的优先级,这意味着它们可以窃取频道。谢谢!
    • 嗯,这主要是有效的。音乐永远不会中断。但是如果我运行游戏足够长的时间,最终所有的 WAV 都会停止播放;然而,音乐永远不会停止。 FMOD 没有返回任何错误。
    【解决方案2】:

    每次播放以下 WAV 时,FMOD 都会永久丢失一个频道。如果我用我的文件替换现有的 jaguar.wav,我可以在“playsound”示例中重现这种通道丢失行为。

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

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

    你好约翰,

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

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

    亲切的问候,马修布洛克 |高级平台工程师

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

    【讨论】:

    • 感谢您的信息。我很难在 2015 年找到可靠的 MOD 播放竞争者 :) FMOD 的故障似乎是由于 WAV 中不寻常的采样率 - 链接的采样率为 22254Hz(经典的 Mac OS 声音使用此频率),而我有另一个 11127Hz 的声音这也显示了故障。我可以通过重新采样 WAV 来解决这个问题。烦人,但不值得重写。
    • 我从未使用过 FMOD,但我很惊讶它没有重新采样功能。 bass 和 bassmod 库已经存在了很长时间,几乎可以做任何你能想象到的事情。这些年来,我尝试了其他一些方法,但还没有找到任何听起来不错的东西——尤其是在播放 mod 文件时。 :)
    • 谁说 FMOD 没有重采样器?他们当然有 :) 它只是在这里有一个通道泄漏错误,莫名其妙。
    • 我明白了——从你原来的评论来看,它听起来好像它没有能力,这反过来又导致了问题。据我所知,问题是重采样无法正常工作。
    • 嗯,我当时还在努力理解这个问题。而且我不知道为什么 FMOD 在播放我的 WAV 时会泄漏频道,要清楚。我能看到的关于这个 WAV 的唯一有趣的事情是它具有非典型频率,并且用具有正常频率的 WAV 替换它似乎可以解决问题,但是如果不查看 FMOD 源,我不能肯定地说该错误在重采样器中。
    【解决方案3】:

    根据您提供的波形样本,FMOD 的行为是正确的,正如您所发现的那样。该样本有一个由 FMOD 支持的循环,并且最后的样本只是永远重复。虽然没用,但这是正确的,并且样本中的差异非常小,以至于听不见。虽然不是波形格式原始规范的一部分,但后来添加了扩展信息以支持元数据,例如作者、标题、cmets 和多个循环点。

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

    从历史上看,一些游戏系统在声音的末尾有一段静音,并在该区域设置了一个循环点。这样做的简短原因是为了减少硬件音频通道中声音结束时可能发生的爆音。

    奇怪的是,您的 .wav 的最后 16 个样本看起来像垃圾,我想知道您使用的 .wav 资产是否是从用于游戏机的源转换而来的,这就是虚假循环信息的来源好吧。

    这本来是一条评论,但我卑微的代表不允许这样做。

    【讨论】:

    • 我是 WAV 的作者,所以我不需要担心循环数据是故意的。不是 :) 数据是从 2001 年的 Mac 'snd' 资源转换而来的;不幸的是,我不记得我使用了哪个工具。原始游戏不依赖任何特殊的“snd”技巧。它们应该是简单的采样声音。
    • @StilesCrisis 幸运的是你知道来源。那个 WAV 在有一个循环点方面是独一无二的吗?另外,最后 16 个样本对您来说看起来像噪音吗? One-shot 游戏声音通常会衰减到 0,因此它们不会弹出。许多(包括较旧的)系统和声卡驱动程序会自动将 ADSR(攻击衰减维持释放)类型效果应用于 WAV 播放,主要消除不以 0 开始或结束的波形的爆音。您可能想要快速抽查您的其他一些源波。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-15
    相关资源
    最近更新 更多