FMOD Ex 掉落声音,最终变得无声
FMOD Ex dropping sounds, eventually going silent
我正在尝试将一个旧的开源 FMOD 3 游戏(糖果危机)移植到 OS X 上的最新版本的 FMOD Ex 4。它声音需求非常简单——它播放 WAV,有时改变它们的频率或扬声器组合,还播放 MOD 跟踪器音乐,有时改变速度。我发现游戏一开始运行良好,但在几分钟后,它开始提前截断声音,然后音乐失去频道并最终停止,然后随着时间的推移所有声音都停止了。如果我减少 FMOD.
可用的频道数,我可以使问题更快地重现
即使我从不播放音乐文件,我也可能会出现 truncated/missing 声音问题,但音乐肯定会让事情变得更糟。我也试过注释掉调整声音频率和扬声器混音的代码,但那不是问题所在。
我每帧调用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();
}
下面是我玩 MODs 的方式。
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 失败了,但我很乐意被证明是错误的。
听起来您的音乐需要设置为比其他声音更高的优先级。请记住,数字越小越重要。我想你可以在频道上设置优先级。
每次播放下面的WAV,FMOD都会永久丢失一个频道。如果我用我的文件替换现有的 jaguar.wav,我可以在 "playsound" 示例中重现这种丢失频道的行为。
https://drive.google.com/file/d/0B1eDRY8sV_a9SXMyNktXbWZOYWs/view?usp=sharing
我联系了 Firelight 并得到了这个回复。显然 WAV 可以包含一个循环命令!我不知道。
Hello John,
I've taken a look at the two files you have provided. Both files end
with a 2 sample infinite loop region.
FMOD 4 (and FMOD 5 for that matter) will see the loop region in the
file and automatically enable FMOD_LOOP_NORMAL if you haven't
specified any loop mode. Assuming you want one-shot behavior just pass
in FMOD_LOOP_OFF when you create the sound.
Kind regards, Mathew Block | Senior Platform Engineer
从技术上讲,此行为与 FMOD_DEFAULT
的记录行为相矛盾(指定暗示 FMOD_LOOP_OFF
),因此他们计划改进此处的文档。
根据您提供的波形样本,FMOD 的行为是正确的,就像您已经发现的那样。该样本有一个由 FMOD 认可的循环,最后的样本将永远重复。虽然没有用,但这是正确的,样本中的差异非常小,以至于听不见。虽然不是 wave 格式原始规范的一部分,但后来添加了扩展信息以支持元数据,例如作者、标题、评论和多个循环点。
最好的办法是检查所有源资产中是否包含循环信息。简单地播放没有循环信息的所有声音可能不是最好的解决方法。有些循环可能是故意的。那些将具有阻止它们的代码。通常,在游戏中,需要循环时会循环整个波形。然后您可以编写或使用一个工具来去除循环信息。如果您确实编写了自己的工具,我建议您将音频重新采样为硬件的本机输出采样率。您需要确保您的重采样器采样准确(没有时移)并且没有引入噪音。
过去,某些游戏系统在声音结束时有一段静音,并在该区域设置了循环点。这样做的简短原因是为了减少硬件音频通道中声音结束时可能出现的爆音。
奇怪的是,你的 .wav 的最后 16 个样本看起来像垃圾,我想知道你正在使用的 .wav 资产是否是从一个用于游戏机的源转换而来的,这就是虚假循环信息的来源来自也。
这本来是一条评论,但我卑微的代表不允许。
我正在尝试将一个旧的开源 FMOD 3 游戏(糖果危机)移植到 OS X 上的最新版本的 FMOD Ex 4。它声音需求非常简单——它播放 WAV,有时改变它们的频率或扬声器组合,还播放 MOD 跟踪器音乐,有时改变速度。我发现游戏一开始运行良好,但在几分钟后,它开始提前截断声音,然后音乐失去频道并最终停止,然后随着时间的推移所有声音都停止了。如果我减少 FMOD.
可用的频道数,我可以使问题更快地重现即使我从不播放音乐文件,我也可能会出现 truncated/missing 声音问题,但音乐肯定会让事情变得更糟。我也试过注释掉调整声音频率和扬声器混音的代码,但那不是问题所在。
我每帧调用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();
}
下面是我玩 MODs 的方式。
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 失败了,但我很乐意被证明是错误的。
听起来您的音乐需要设置为比其他声音更高的优先级。请记住,数字越小越重要。我想你可以在频道上设置优先级。
每次播放下面的WAV,FMOD都会永久丢失一个频道。如果我用我的文件替换现有的 jaguar.wav,我可以在 "playsound" 示例中重现这种丢失频道的行为。
https://drive.google.com/file/d/0B1eDRY8sV_a9SXMyNktXbWZOYWs/view?usp=sharing
我联系了 Firelight 并得到了这个回复。显然 WAV 可以包含一个循环命令!我不知道。
Hello John,
I've taken a look at the two files you have provided. Both files end with a 2 sample infinite loop region.
FMOD 4 (and FMOD 5 for that matter) will see the loop region in the file and automatically enable FMOD_LOOP_NORMAL if you haven't specified any loop mode. Assuming you want one-shot behavior just pass in FMOD_LOOP_OFF when you create the sound.
Kind regards, Mathew Block | Senior Platform Engineer
从技术上讲,此行为与 FMOD_DEFAULT
的记录行为相矛盾(指定暗示 FMOD_LOOP_OFF
),因此他们计划改进此处的文档。
根据您提供的波形样本,FMOD 的行为是正确的,就像您已经发现的那样。该样本有一个由 FMOD 认可的循环,最后的样本将永远重复。虽然没有用,但这是正确的,样本中的差异非常小,以至于听不见。虽然不是 wave 格式原始规范的一部分,但后来添加了扩展信息以支持元数据,例如作者、标题、评论和多个循环点。
最好的办法是检查所有源资产中是否包含循环信息。简单地播放没有循环信息的所有声音可能不是最好的解决方法。有些循环可能是故意的。那些将具有阻止它们的代码。通常,在游戏中,需要循环时会循环整个波形。然后您可以编写或使用一个工具来去除循环信息。如果您确实编写了自己的工具,我建议您将音频重新采样为硬件的本机输出采样率。您需要确保您的重采样器采样准确(没有时移)并且没有引入噪音。
过去,某些游戏系统在声音结束时有一段静音,并在该区域设置了循环点。这样做的简短原因是为了减少硬件音频通道中声音结束时可能出现的爆音。
奇怪的是,你的 .wav 的最后 16 个样本看起来像垃圾,我想知道你正在使用的 .wav 资产是否是从一个用于游戏机的源转换而来的,这就是虚假循环信息的来源来自也。
这本来是一条评论,但我卑微的代表不允许。