我正在为Android 2.2编程,我正在尝试使用 SoundPool课程可同时播放多种声音,但在随机时间感觉声音将不再从扬声器中传出。
对于本来会播放的每个声音都会打印在logcat中:
AudioFlinger could not create track. status: -12
Error creating AudioTrack
Audio track delete
不会抛出任何异常,程序会继续执行而不会因为缺少音量而进行任何更改。我很难跟踪导致错误的条件或在错误发生后重新创建错误。我无法在任何地方找到文档中的错误,而且几乎不知所措。
非常感谢任何帮助!
编辑:我忘了提到我正在加载mp3文件,而不是ogg。
答案 0 :(得分:21)
我几乎遇到了与我最近试图加载和播放的一些声音完全相同的问题。
我甚至将其分解为加载导致此错误的单个mp3。
我注意到一件事:当我加载-1的循环时,它会因“状态12”错误而失败,但是当我将它加载到循环0次时,它会成功。甚至试图加载1次失败。
最终的解决方案是在音频编辑器中打开mp3并以稍微低一点的质量重新编辑它,以便文件现在变小,并且似乎不占用系统中相当多的资源。
最后,有一个讨论鼓励对正在使用的对象执行发布,因为确实存在可以使用的资源的硬限制,并且它是系统范围的,所以如果你使用了几个资源,其他应用程序将无法使用它们。
https://groups.google.com/forum/#!topic/android-platform/tyITQ09vV3s/discussion%5B1-25%5D
对于音频,每个音频限制为32个有效的AudioTrack对象 设备(不是每个应用程序:你需要与系统的其余部分共享32个),AudioTrack在SoundPool下面内部使用, ToneGenerator,MediaPlayer,基于OpenSL ES的原生音频等。但是 实际的AudioTrack限制是< 32;它更多地取决于软因素 如内存,CPU负载等。另请注意限制器中的 Android音频混音器目前没有动态范围压缩, 因此,如果您有大量活动声音,则可以剪辑 他们都很响亮。
对于视频播放器,由于负载过重,限制要低得多 该视频放在设备上。
我会以此为契机提醒媒体开发者:拜托 记得在应用暂停时为媒体对象调用release()。 这释放了其他应用程序所需的底层资源。 不要依赖于最终确定的被清理的媒体对象 垃圾收集器,因为它具有不可预测的时间。
答案 1 :(得分:2)
我有一个类似的问题,我的Android游戏中的音乐跟踪器会丢失笔记,我得到了Audioflinger错误(虽然我的状态是-22)。我得到了它,所以这可能会帮助一些人。
同时多次输出单个样品时出现问题。所以在我的情况下,它是在两个或多个轨道上播放的单个样本。这似乎偶尔会陷入僵局或其他事情中,其中一个会被丢弃。解决方案是拥有两个样本副本(两个实际的ogg文件 - 相同但都在资产中)。然后在每个轨道上,即使我正在播放相同的样本,它也来自不同的文件。这完全解决了我的问题。
不确定为什么它可以正常工作,因为我将样本缓存到内存中,但即使将相同的文件加载到两个不同的声音也无法修复它。只有当样本来自两个不同的文件时,错误才会消失。
我确信这对每个人都没有帮助,这不是最漂亮的解决方案,但它可能对某人有所帮助。
答案 2 :(得分:2)
答案 3 :(得分:1)
如上所述,循环存在问题:当我将repeat设置为-1时,我得到此错误,但是0时一切正常。 我注意到当我试图逐个播放时,有些声音会出现此错误。例如:
mSoundPool.stop(mStreamID);
mStreamID = mSoundPool.play(mRandID, mVolume, mVolume, 1, -1, 1f);
在这种情况下,第一首曲目播放正常,但当我切换声音时,下一首曲目会出现此错误。似乎使用循环,缓冲区以某种方式重载,并且mSoundPool.stop无法立即释放资源。
<强>解决方案强>:
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
mStreamID = mSoundPool.play(mRandID, mVolume, mVolume, 1, -1, 1f);
}, 350);
并且它正在工作,但不同设备的延迟是不同的。
答案 4 :(得分:1)
在我的情况下,将MP3的质量和文件大小降低到100kb以下是不够的,因为一些51kb的文件工作,而一些较长的41kb文件仍然没有。
帮助我们的是将采样率从44100降低到22050或将持续时间缩短到不到5秒。
答案 5 :(得分:1)
我看到太多过于复杂的答案。错误-12表示您没有释放变量。 我播放8次OGG音频文件后遇到了同样的问题。 这对我有用:
SoundPoolPlayer onBeep; //Global variable
if(onBeep!=null){
onBeep.release();
}
onBeep = SoundPoolPlayer.create(getContext(), R.raw.micon);
onBeep.setOnCompletionListener(
new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) { //mp will be null here
loge("ON Beep! END");
startGoogleASR_API_inner();
}
}
);
onBeep.play();
在.play()之后立即释放变量会使事情变得混乱,并且无法在onCompletion中释放变量,因此请注意在使用变量之前如何释放变量(并检查null以避免nullpointer异常)。
它就像魅力一样!
答案 6 :(得分:0)
尝试
final ToneGenerator tg = new ToneGenerator(AudioManager.STREAM_NOTIFICATION, 50);
tg.startTone(ToneGenerator.TONE_PROP_BEEP, 200);
tg.release();
发布应保留您的资源。
答案 7 :(得分:0)
单个soundPool的内部存储器限制为1(一)Mb。如果您的声音质量非常高,您可能会遇到这种情况。如果你有很多声音并达到这个限制,只需创建更多的音池,并在它们之间分配声音。
如果在到达目的地之前内存不足,您甚至可能无法达到硬限制。
该错误不仅会在达到流或曲目限制时出现,还会出现内存限制。 Soundpool将停止播放旧的和/或去优先级的声音以播放新的声音。
答案 8 :(得分:0)
我遇到了这个问题。为了解决这个问题,我在完成播放声音后运行了SoundPool对象的方法.release()。
这是我的代码:
SoundPool pool = new SoundPool(10, AudioManager.STREAM_MUSIC, 50);
final int teste = pool.load(this.ctx,this.soundS,1);
pool.setOnLoadCompleteListener(new OnLoadCompleteListener(){
@Override
public void onLoadComplete(SoundPool sound,int sampleId,int status){
pool.play(teste, 20,20, 1, 0, 1);
new Thread(new Runnable(){
@Override
public void run(){
try {
Thread.sleep(2000);
pool.release();
} catch (InterruptedException e) { e.printStackTrace(); }
}
}).start();
}
});
请注意,在我的情况下,我的声音最长1-2秒,所以我在Thread.sleep()中输入2000毫秒的值,以便在播放器完成后才释放资源。