LibGDX: AudioFlinger 无法创建音轨,状态 -12
LibGDX: AudioFlinger could not create track, status -12
我最近在 LibGDX 游戏中添加了声音。它的设置使我需要的所有声音都加载到 AssetManager
中,当我需要从 getSound(String name)
方法播放它们时,我会检索它们。
当你玩的时候它工作了一点点,但最终它停止播放一些,有时是大部分。我会优先考虑最近播放的那些,如果需要的话停止那些较旧的,但 LibGDX 似乎并没有给你那么多的控制权。
发生这种情况时我得到的日志错误
E/AudioTrack: AudioFlinger could not create track, status: -12
E/SoundPool: Error creating AudioTrack
.
它通常一次会播放很多声音,一次可能会播放 10-20 个小声音,视情况而定,所以我很确定这是问题所在。我在这里读到有关使用 SoundPool
播放声音后释放声音的信息,但我不完全确定如何使用 LibGDX 执行此操作,或者如果可能的话,因为我没有看到class我看的时候就是这样
此外,我对所有声音都使用 ogg 文件,其中 none 非常大。
谢谢!
已解决!通过创建我自己的(一种伪)Sound
class,以及一个加载器,它可以与使用 assetManager.setLoader()
的 AssetManager
一起使用。在自定义 Sound
class 中,我将每个声音设置为在 Array<Long>
中跟踪它们的 soundId
,然后每次播放时我都会检查数组的大小一个 limit
变量,停止数组中最旧的声音。 0 意味着一次只能播放一个,直到我决定有必要为止。这可能不是一个完美的解决方案,但它似乎工作得很好。
欢迎批评指正
我创建的“Sound
”class:
public class MySound {
private Sound sound;
private Array<Long> ids;
private int limit;
public MySound(Sound sound) {
this.sound = sound;
ids = new Array<Long>();
limit = 0;
}
public long play() {
limitSounds();
long id = sound.play();
ids.add(id);
return id;
}
public long play(float volume) {
limitSounds();
long id = sound.play(volume);
ids.add(id);
return id;
}
public long play(float volume, float pitch, float pan) {
limitSounds();
long id = sound.play(volume, pitch, pan);
ids.add(id);
return id;
}
public long loop() {
limitSounds();
long id = sound.loop();
ids.add(id);
return id;
}
public long loop(float volume) {
limitSounds();
long id = sound.loop(volume);
ids.add(id);
return id;
}
public long loop(float volume, float pitch, float pan) {
limitSounds();
long id = sound.loop(volume, pitch, pan);
ids.add(id);
return id;
}
public void stop() {
ids.clear();
sound.stop();
}
public void pause() {
sound.pause();
}
public void resume() {
sound.resume();
}
public void dispose() {
sound.dispose();
}
public void stop(long soundId) {
if (ids.contains(soundId, true)) {
ids.removeValue(soundId, true);
}
sound.stop(soundId);
}
public void pause(long soundId) {
sound.pause(soundId);
}
public void resume(long soundId) {
sound.resume(soundId);
}
public void setLooping(long soundId, boolean looping) {
sound.setLooping(soundId, looping);
}
public void setPitch(long soundId, float pitch) {
sound.setPitch(soundId, pitch);
}
public void setVolume(long soundId, float volume) {
sound.setVolume(soundId, volume);
}
public void setPan(long soundId, float pan, float volume) {
sound.setPan(soundId, pan, volume);
}
private void limitSounds () {
if (ids.size > limit) {
sound.stop(ids.get(0));
ids.removeIndex(0);
}
}
public void setLimit (int limit) {
this.limit = limit;
}
}
MySoundLoader
class, 对于 AssetManager
:
public class MySoundLoader extends AsynchronousAssetLoader<MySound, MySoundLoader.SoundParameter> {
private MySound sound;
public MySoundLoader(FileHandleResolver resolver) {
super(resolver);
}
@Override
public Array<AssetDescriptor> getDependencies(String fileName, FileHandle file, SoundParameter parameter) {
return null;
}
@Override
public void loadAsync(AssetManager manager, String fileName, FileHandle file, SoundParameter parameter) {
sound = new MySound(Gdx.audio.newSound(file));
}
@Override
public MySound loadSync(AssetManager manager, String fileName, FileHandle file, SoundParameter parameter) {
MySound sound = this.sound;
this.sound = null;
return sound;
}
static public class SoundParameter extends AssetLoaderParameters<MySound> {
}
}
我最近在 LibGDX 游戏中添加了声音。它的设置使我需要的所有声音都加载到 AssetManager
中,当我需要从 getSound(String name)
方法播放它们时,我会检索它们。
当你玩的时候它工作了一点点,但最终它停止播放一些,有时是大部分。我会优先考虑最近播放的那些,如果需要的话停止那些较旧的,但 LibGDX 似乎并没有给你那么多的控制权。
发生这种情况时我得到的日志错误
E/AudioTrack: AudioFlinger could not create track, status: -12
E/SoundPool: Error creating AudioTrack
.
它通常一次会播放很多声音,一次可能会播放 10-20 个小声音,视情况而定,所以我很确定这是问题所在。我在这里读到有关使用 SoundPool
播放声音后释放声音的信息,但我不完全确定如何使用 LibGDX 执行此操作,或者如果可能的话,因为我没有看到class我看的时候就是这样
此外,我对所有声音都使用 ogg 文件,其中 none 非常大。 谢谢!
已解决!通过创建我自己的(一种伪)Sound
class,以及一个加载器,它可以与使用 assetManager.setLoader()
的 AssetManager
一起使用。在自定义 Sound
class 中,我将每个声音设置为在 Array<Long>
中跟踪它们的 soundId
,然后每次播放时我都会检查数组的大小一个 limit
变量,停止数组中最旧的声音。 0 意味着一次只能播放一个,直到我决定有必要为止。这可能不是一个完美的解决方案,但它似乎工作得很好。
欢迎批评指正
我创建的“Sound
”class:
public class MySound {
private Sound sound;
private Array<Long> ids;
private int limit;
public MySound(Sound sound) {
this.sound = sound;
ids = new Array<Long>();
limit = 0;
}
public long play() {
limitSounds();
long id = sound.play();
ids.add(id);
return id;
}
public long play(float volume) {
limitSounds();
long id = sound.play(volume);
ids.add(id);
return id;
}
public long play(float volume, float pitch, float pan) {
limitSounds();
long id = sound.play(volume, pitch, pan);
ids.add(id);
return id;
}
public long loop() {
limitSounds();
long id = sound.loop();
ids.add(id);
return id;
}
public long loop(float volume) {
limitSounds();
long id = sound.loop(volume);
ids.add(id);
return id;
}
public long loop(float volume, float pitch, float pan) {
limitSounds();
long id = sound.loop(volume, pitch, pan);
ids.add(id);
return id;
}
public void stop() {
ids.clear();
sound.stop();
}
public void pause() {
sound.pause();
}
public void resume() {
sound.resume();
}
public void dispose() {
sound.dispose();
}
public void stop(long soundId) {
if (ids.contains(soundId, true)) {
ids.removeValue(soundId, true);
}
sound.stop(soundId);
}
public void pause(long soundId) {
sound.pause(soundId);
}
public void resume(long soundId) {
sound.resume(soundId);
}
public void setLooping(long soundId, boolean looping) {
sound.setLooping(soundId, looping);
}
public void setPitch(long soundId, float pitch) {
sound.setPitch(soundId, pitch);
}
public void setVolume(long soundId, float volume) {
sound.setVolume(soundId, volume);
}
public void setPan(long soundId, float pan, float volume) {
sound.setPan(soundId, pan, volume);
}
private void limitSounds () {
if (ids.size > limit) {
sound.stop(ids.get(0));
ids.removeIndex(0);
}
}
public void setLimit (int limit) {
this.limit = limit;
}
}
MySoundLoader
class, 对于 AssetManager
:
public class MySoundLoader extends AsynchronousAssetLoader<MySound, MySoundLoader.SoundParameter> {
private MySound sound;
public MySoundLoader(FileHandleResolver resolver) {
super(resolver);
}
@Override
public Array<AssetDescriptor> getDependencies(String fileName, FileHandle file, SoundParameter parameter) {
return null;
}
@Override
public void loadAsync(AssetManager manager, String fileName, FileHandle file, SoundParameter parameter) {
sound = new MySound(Gdx.audio.newSound(file));
}
@Override
public MySound loadSync(AssetManager manager, String fileName, FileHandle file, SoundParameter parameter) {
MySound sound = this.sound;
this.sound = null;
return sound;
}
static public class SoundParameter extends AssetLoaderParameters<MySound> {
}
}