41

我正在为 android 2.2 编程,并尝试使用 SoundPool类同时播放多个声音,但在随机时间,声音会停止从扬声器中发出。

对于将要播放的每个声音,这都会打印在 logcat 中:

AudioFlinger could not create track. status: -12 
Error creating AudioTrack
Audio track delete

没有抛出异常,程序继续执行,除了体积不足之外没有任何变化。我很难追踪导致错误的条件或在错误发生后重新创建它。我在任何地方都找不到文档中的错误,并且几乎不知所措。

任何帮助将不胜感激!

编辑:我忘了提到我正在加载 mp3 文件,而不是 ogg。

4

9 回答 9

22

对于我最近尝试加载和播放的一些声音,我遇到了几乎完全相同的问题。

我什至将其分解为加载导致此错误的单个 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()。这释放了其他应用程序需要的底层资源。不要依赖垃圾收集器在 finalize 中清理的媒体对象,因为这具有不可预测的时间。

于 2012-08-19T06:47:39.037 回答
3

我遇到了类似的问题,我的 Android 游戏中的音乐跟踪器会丢失音符,并且出现 Audioflinger 错误(尽管我的状态是 -22)。但是我让它工作了,所以这可能会帮助一些人。

当单个样本同时输出多次时会出现问题。所以在我的情况下,它是在两个或多个轨道上播放的单个样本。这似乎偶尔会出现僵局或其他情况,两个音符中的一个会被丢弃。解决方案是拥有样本的两个副本(两个实际的 ogg 文件 - 相同但都在资产中)。然后在每首曲目上,即使我播放的是相同的样本,但它来自不同的文件。这完全解决了我的问题。

不知道为什么它会在我将样本缓存到内存时起作用,但即使将同一个文件加载到两个不同的声音中也无法解决它。只有当样本来自两个不同的文件时,错误才会消失。

我敢肯定这不会帮助每个人,它不是最漂亮的修复,但它可能会帮助某人。

于 2013-01-28T00:32:00.083 回答
2

john.k.doe 是对的。您必须减小 mp3 文件的大小。您应该将每个文件的大小保持在 100kb 以下。我不得不使用 32kbps 的恒定比特率 (CBR) 而不是通常的 128kbps 将我的 200kb 文件减少到 72kb。这对我有用!

于 2013-05-09T03:38:25.970 回答
1

我遇到了这个问题。为了解决它,我在播放完声音后运行 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 秒,因此我将 2000 毫秒的值放入 Thread.sleep() 中,以便仅在播放器完成后释放资源。

于 2013-11-06T15:02:01.373 回答
1

尝试

 final ToneGenerator tg = new ToneGenerator(AudioManager.STREAM_NOTIFICATION, 50);
 tg.startTone(ToneGenerator.TONE_PROP_BEEP, 200);
 tg.release();

发布应该保留你的资源。

于 2012-12-27T03:53:47.703 回答
1

如上所述,循环存在问题:当我将重复设置为 -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);

它正在工作,但不同设备的延迟不同。

于 2015-07-01T15:50:32.613 回答
1

我看到太多过于复杂的答案。错误 -12 表示您没有释放变量。播放 OGG 音频文件 8 次后,我遇到了同样的问题。这对我有用:

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 异常)。

它就像魅力一样!

于 2017-10-30T09:50:15.743 回答
1

在我的情况下,将 MP3 的质量和文件大小降低到 100kb 以下是不够的,因为一些 51kb 文件可以工作,而一些持续时间较长的 41kb 文件仍然没有。

帮助我们的是将采样率从 44100 降低到 22050,或者将持续时间缩短到不到 5 秒。

于 2015-09-03T21:06:20.403 回答
0

单个 soundPool 的内部内存限制为 1(一)Mb。如果您的声音质量非常高,您可能会遇到这个问题。如果你有很多声音并且达到了这个限制,只需创建更多的声音池,并在它们之间分配你的声音。

如果您在到达那里之前内存不足,您甚至可能无法达到硬轨限制。

该错误不仅在达到流或轨道限制时出现,而且在内存限制时出现。Soundpool 将停止播放旧的和/或取消优先级的声音以播放新的声音。

于 2013-10-08T00:21:21.303 回答