声音使应用程序滞后 Android - 任何解决方案?

Sound makes app lags on Android - any solution?

所以我的游戏在 PC 上运行流畅(win 10),但在 android phone(Mi 9T pro、SD 855、6GB 内存)上滞后。我并不是说只有声音滞后,图形也有滞后。当我禁用声音时,它运行起来非常流畅(应该如此)。

是的,我知道这个问题已经被问过很多次了。我尝试了所有提供的 "solutions",但没有任何帮助。尝试使用 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);
    }
}

声音 class 看起来像这样:

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 上消除这种滞后的建议都值得赞赏。

不确定延迟,但您不应该同时播放很多声音,因为大多数设备只能输出一个视图通道。我通常做的是有一个声音管理器,当一个声音已经在播放时,我停止那个声音并在一帧中播放新的声音。我个人并没有注意到突然停止的声音,我相信很多游戏都是这样做的。

所以只需要像 SoundManager class 这样的东西,它带有所有声音的数组、列表、集合或映射,当你想播放一个声音循环时,如果它们正在播放就停止。

playSound(String soundName){
  for (Sound sound : soundMap) {
    sound.stop();
  }
  soundMap.get(soundName).play();
}

如果您出于某种原因确实需要同时播放一些声音,则可以将其扩展为拥有多个声音列表。您还可以保留正在播放的声音列表或单个声音对象以直接访问和停止声音。但是只映射了几十种声音,你应该不会有任何性能问题。

使用更严格的声音管理器解决了这个问题 class。

首先,在加载声音样本期间,我计算每个声音样本持续多长时间(大约)。原因是 LibGDX Sound class 不提供该功能。由于我所有的样本都是相同的格式计算就足够了:

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。

然后,我为每个播放调用添加了 "priority" 字段(值 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 个样本,声音听起来也不错....缺失的声音并不明显。