我正在尝试将旧的开源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被破坏但我很想被证明是错误的。
答案 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资产是否是从用于游戏控制台的源转换而来的,这是伪造循环信息来自哪里好。
这可能是一个评论,但我的低级代表不允许。