audio - 声音使应用程序在 Android 上滞后 - 有什么解决方案吗?
问题描述
所以我的游戏在 PC 上运行流畅(win 10),但在安卓手机(小米 9T pro,SD 855,6GB 内存)上运行缓慢。我并不是说只有声音滞后,还有图形。当我禁用声音时,它运行得非常流畅(应该如此)。
是的,我知道这个问题被问过很多次。我尝试了所有提供的“解决方案”,但没有任何帮助。尝试使用 22KHz 样本、44.1Khz、48Khz。尝试在每个样本结束时添加 1 秒的静音。没有帮助。
我正在使用这种方法加载样本:
private void loadSounds(String path)
{
FileHandle dirHandle;
dirHandle = Gdx.files.internal(path);
for (FileHandle entry: dirHandle.list()) {
Sound sound = new Sound(entry.nameWithoutExtension(), path+"/"+entry.name());
sounds.add(sound);
}
}
Sound 类如下所示:
public class Sound {
public String name;
private com.badlogic.gdx.audio.Sound soundObject;
public Sound(String name, String filePath) {
this.name = name;
soundObject = Gdx.audio.newSound(Gdx.files.internal(filePath));
}
public void play()
{
soundObject.play();
}
public void play (float pitch)
{
soundObject.play(1,pitch,0);
}
public void stop()
{
soundObject.stop();
}
public void dispose()
{
soundObject.dispose();
}
}
只是普通的方式,没什么特别的。所以我在应用程序启动时预加载所有声音样本并在游戏期间播放它们。玩会导致滞后,这一点很清楚。任何有关如何摆脱 android 滞后的建议都值得赞赏。
解决方案
通过更严格的声音管理器类解决了这个问题。
首先在加载声音样本期间,我正在计算每个声音样本持续多长时间(大约)。原因是 LibGDX Sound 类不提供该功能。由于我所有的样本都采用相同的格式计算就足够了:
final long WAV_HEADER_SIZE = 2415;
final long WAV_BPS = 41137;
FileHandle file = Gdx.files.internal(filePath);
duration = (long)(1000f * (file.length() - WAV_HEADER_SIZE) / WAV_BPS);
所以我以这种方式获得了以毫秒为单位的样本持续时间。样本为 22Khz、352Kbps。
然后,每当我播放一些声音时,我都会记得播放开始的时间,所以我可以随时使用这个持续时间变量来计算声音是否仍在播放。
有了这个,我可以检查我同时播放了多少声音。我当时达到的最大数字是 8。这种情况很少发生并且不会持续很长时间。常见的样本数是 0 到 4 或 5。
然后,我为每个播放调用添加了“优先级”字段(值 1 - 10),在我播放声音之前,我正在计算当前正在播放的样本数量以及哪些声音具有最低优先级。
final int MAX_PRIORITY = 10;
final int MAX_NUMBER_OF_SOUNDS_PLAYED_SIMULTANEITY = 2;
if (muted > 0 || soundName.isEmpty()) return;
Array<Sound> matchedSounds = new Array<Sound>(10);
int playingCount = 0;
int lowestPriority = MAX_PRIORITY + 1;
int lowestPriorityIndex = -1;
for (int i = 0; i<sounds.size; i++){
Sound sound = sounds.get(i);
if (sound.isPlaying()){
if (sound.priority < lowestPriority){
lowestPriority = sound.priority;
lowestPriorityIndex = i;
}
playingCount++;
}
if (sound.name.startsWith(soundName)) {
matchedSounds.add(sounds.get(i));
}
}
if (playingCount > MAX_NUMBER_OF_SOUNDS_PLAYED_SIMULTANEITY){
if (priority <= lowestPriority){
return;
}else{
sounds.get(lowestPriorityIndex).stop();
}
}
所以我首先检查允许的声音数量是否大于当前播放的声音数量。如果不是,我会定期播放新声音。
如果是,并且新声音的优先级低于所有当前播放的声音,我只是忽略新声音。
如果是并且新的声音不是最低的优先级,我将停止最低的声音并播放新的声音。
这样,我将当前播放的声音数量保持在固定数量。
最令人惊讶的是,当时没有滞后的最大样本数是 2 ?!?! 播放 3 个或更多声音时,什么样的声音系统会滞后?!?这里确实有问题。
无论如何,即使当时最多有 2 个样本,声音听起来也不错.... 丢失的声音并不明显。
推荐阅读
- multithreading - 在 Windows C++ 上创建仅具有管理员访问权限的多线程命名管道服务器时出错
- reactjs - GitLab CI Pipeline Job 给出错误 JavaScript heap out of memory
- apache-beam - 数据流。价值提供者。如何从多个选项中创建?
- android - 如何在应用程序处于前台时更新徽章应用程序编号
- vba - 宏在 mailitem.Subject 项的特殊字符上失败(运行时错误“1004”:应用程序定义或对象定义错误)
- dataframe - 使用pyspark中的条件创建具有运行总量的列
- java - 将 Java 编译为 WebAssembly
- python - Pandas 将一列值(单热编码)映射到具有多个可能值的单列中
- python - 如何根据另一个列表的项目顺序对元组列表进行排序
- swift - 如何从不同的集合构建模型而不破坏 MVC - swift - Firebase