如何在游戏中正确使用 SoundPool?

Posted

技术标签:

【中文标题】如何在游戏中正确使用 SoundPool?【英文标题】:How to properly use SoundPool on a game? 【发布时间】:2011-09-15 21:12:39 【问题描述】:

我在使用 SoundPool 时遇到性能问题。每次播放声音时,帧速率都会下降。我添加了一些日志,我可以在 logcat 上看到“播放”功能有时需要 8 毫秒。

我正在使用 *.ogg 文件,并且 SoundPool 初始化是在应用启动时完成的:

mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
mSoundPool = new SoundPool(size, AudioManager.STREAM_MUSIC, 0);
mSoundPoolMap = new HashMap<Integer, Integer>();
mSoundPoolMap.put(index, mSoundPool.load(context, R.raw.shot, 1));

为了播放声音,我使用以下代码(在游戏循环中):

mSoundPool.play(id, streamVolume, streamVolume, 1, loop, 1f);

我的问题是:

我应该在游戏循环之外的另一个线程上调用“play”吗? 我应该通过服务调用“播放”吗? 我做错什么了吗?

谢谢!


更新:

我刚刚测试了在另一个线程上播放声音并通过服务播放声音,但仍然存在延迟。

然后我做了以下测试: * 以 1000 毫秒的间隔播放声音 -> 延迟总是发生 * 以 200 毫秒的间隔播放声音 -> 永远不会发生延迟

这怎么可能?!?!? 经过这些测试,似乎什么都没有播放的时候,SoundPool正在重置,再次播放的时候,初始化的时间比较长……很奇怪!

【问题讨论】:

【参考方案1】:

我通过循环播放静音解决了这个问题:

mSoundPool.play(id, 0, 0, 1, -1, 1f);

滞后完全消失了!

这似乎不是正确的做法,所以如果有人知道如何解释,请告诉我们!

更多信息: http://www.thiagorosa.com.br/en/how-to/improve-soundpool-performance

【讨论】:

这对电池寿命有何影响? 在以特定频率播放声音时,我遇到了类似的滞后问题。但是,我没有得到解决方案。如果静音,为什么需要播放?我也听不到任何其他声音。 只有这个声音是静音的,你让它循环播放静音,然后用音量播放其他声音。这是一种解决方法,它不必有意义,哈哈! =)【参考方案2】:

您可以尝试加载 MP3 而不是 OGG,我发现在某些手机上 OGG 播放效果不佳。

【讨论】:

其实我想说的正好相反。【参考方案3】:

我有一个单独的绘图和游戏循环,当我调用声音池播放时,我的绘图循环会出现一些延迟。并非总是如此,但这使我的应用程序显得迟钝。

我尝试过 wav 和 ogg,但似乎没有太大区别。 Wav 稍微好一点,但它会导致另一个问题,soundpool 有时会在只调用一次时播放两次 wav 文件,所以我切换到了 ogg。

我目前的解决方案是从 new runnable 调用 play 为:

public class MyRunnable implements Runnable 
        private int s_id; 
        public MyRunnable(int sound_id) 
            s_id = sound_id;
        
        public void run() 
            SoundManager.playSound(s_id, 1);
        

然后从我的游戏循环中,我调用

Runnable r = new MyRunnable(sound_id);
handler.postDelayed(r, 0);

我以这种方式经历的延迟要少得多,但我确信这不是正确/最佳的解决方案。

【讨论】:

【参考方案4】:

我应该在游戏循环之外的另一个线程上调用“play”吗?

我应该通过服务调用“玩”吗?

我都试过了,它们似乎都提供了相同的性能提升。两者都解决了我在应用程序中注意到的可见滞后。所以我会说是的,选择其中一个来做,它应该有助于你的表现。

【讨论】:

我只是尝试了这两种方法,但它们并没有显示出性能提升。我使用了***.com/questions/5580537/…的服务思路和我自己做的线程解决方案。【参考方案5】:

我刚刚实现了一些类似于 thiagolr 在后台循环静音的技术。我同意这似乎不是“解决”问题的正确方法——但它确实有效。我使用 MediaPlayer 循环播放背景“声音”,因为如果我使用来自 SoundPool 的流,它有时会被重新用于播放实际的声音效果,而问题又回来了。

我认为有帮助的另一件事是将我的所有音频转换为 16 位 22K ogg。

我认为在后台循环静音的最大缺点是电池电量小,但在应该播放音效时似乎值得。我只在使用 Gingerbread 或更低版本的设备上执行此操作。它在 Kindle Fire 上运行得非常好,我认为在 Nook 平板电脑上运行良好。我的应用程序在 Nook Color 上已经有点慢了,但我认为这并没有让它变得更糟。这些天我需要对我的绘图代码进行完全转换以使用 OpenGL。

【讨论】:

【参考方案6】:

MP3 几乎是您最好的选择,因为虽然所有平台都提供了 OGG,但这些平台可能不支持它。

【讨论】:

以上是关于如何在游戏中正确使用 SoundPool?的主要内容,如果未能解决你的问题,请参考以下文章

Android 编程 - 如何从广播接收器播放 SoundPool 声音?

如何正确释放 SoundPool 对象?

如何在 SoundPool 类中使用 stop() 方法?

使用 SoundPool 进行游戏

如何在自定义视图类中使用 soundPool? [关闭]

如何在特定时间段内使用 SoundPool 同时播放声音