【问题标题】:AudioFlinger could not create track. status: -12AudioFlinger 无法创建轨道。状态:-12
【发布时间】:2012-08-11 11:19:45
【问题描述】:

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

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

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

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

任何帮助将不胜感激!

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

【问题讨论】:

  • 您要创建多少首曲目? AFAIK -12 是NO_MEMORY,这可能意味着您已经用完了轨道(我认为开放轨道的最大数量曾经是 32 - 不确定是否仍然如此)。
  • 嗯,我正在加载很多曲目,但它们被分成 5 个音池。每个音池最多可以加载约 15 个声音。你知道 32 条最大音轨是系统范围的还是每个声音池的?
  • 它是每个混音器线程(其中每个输出线程 AFAIK 都有一个)。但由于许多平台对所有非 A2DP 播放都使用单个输出线程,因此它基本上成为了一个全局限制。
  • 当我调用 stop 但未能在我的轨道上调用 release 时,我得到了这个。

标签: android soundpool


【解决方案1】:

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

我什至将其分解为加载导致此错误的单个 mp3。

我注意到一件事:当我加载循环为 -1 时,它会因“状态 12”错误而失败,但当我加载循环 0 次时,它会成功。甚至尝试加载 1 次都失败了。

最终的解决方案是在音频编辑器中打开 mp3 并以稍低的质量重新编辑它,以使文件现在更小,并且似乎不会占用系统中那么多的资源。

最后,这个讨论鼓励对你正在使用的对象执行释放,因为对可以使用的资源确实有一个硬限制,而且它是系统范围的,所以如果你使用几个资源,其他应用将无法使用它们。

https://groups.google.com/forum/#!topic/android-platform/tyITQ09vV3s/discussion%5B1-25%5D

对于音频,每个活动 AudioTrack 对象的硬性限制为 32 个 设备(不是每个应用程序:您需要与系统的其余部分共享这 32 个),并且 AudioTrack 在 SoundPool 内部使用, ToneGenerator、MediaPlayer、基于 OpenSL ES 的原生音频等。但是 实际的 AudioTrack 限制为

由于负载过重,视频播放器的限制要低得多 该视频放在设备上。

我会借此机会提醒媒体开发者:请 请记住在您的应用暂停时为媒体对象调用 release()。 这释放了其他应用程序需要的底层资源。 不要依赖在 finalize 中清理的媒体对象 垃圾收集器,因为它具有不可预测的时间。

【讨论】:

    【解决方案2】:

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

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

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

    我确信这不会帮助所有人,也不是最漂亮的解决方案,但它可能会对某人有所帮助。

    【讨论】:

    • 非常感谢!这真的帮助了我:) 在播放语音(使用 exo 播放器)时切换到耳机时,我遇到了问题中提到的错误。问题实际上是“同时”部分,在调用暂停后立即播放声音,没有任何延迟。
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      试试

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

      发布应该保留你的资源。

      【讨论】:

        【解决方案5】:

        我遇到了这个问题。为了解决这个问题,我在播放完声音后运行 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() 中,以便仅在播放器完成后释放资源。

        【讨论】:

          【解决方案6】:

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

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

          【讨论】:

            【解决方案7】:

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

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

            【讨论】:

              【解决方案8】:

              我看到太多过于复杂的答案。错误 -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 以避免空指针异常)。

              它就像魅力一样!

              【讨论】:

                【解决方案9】:

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

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

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

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2012-03-24
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2018-01-20
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多