2012-08-15 60 views
35

我正在爲android 2.2編程,並試圖使用 SoundPool類同時播放幾個聲音,但是隨機時間的聲音會停止從揚聲器中傳出。AudioFlinger無法創建曲目。狀態:-12

對於本來玩過這個每個聲音印在logcat中:

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

沒有異常被拋出,程序可以繼續,而不只是缺乏成交量的任何變更執行。我很難追查哪些情況會導致錯誤,或者在發生錯誤後重新創建它。我無法在任何地方找到文檔中的錯誤,而且幾乎無所適從。

任何幫助將不勝感激!

編輯:我忘了提及我加載MP3文件,而不是ogg。

+5

您創建多少首曲目? AFAIK -12是'NO_MEMORY',這可能意味着你已經用完了曲目(我認爲開放曲目的最大數量曾經是32--不知道這是否仍然如此)。 – Michael 2012-08-15 08:50:36

+0

嗯,我加載了很多曲目,但它們被分成了5個soundpools。每個soundpool將有最多15個加載的聲音。你知道32個最大音軌是系統範圍還是每個聲音池? – user1599837 2012-08-15 20:07:10

+0

它是每個混音器線程(其中你有一個每個輸出線程AFAIK)。但是由於許多平臺對所有非A​​2DP播放使用單個輸出線程,因此它基本上成爲全侷限制。 – Michael 2012-08-16 09:20:10

回答

20

我幾乎與我最近嘗試加載和播放的一些聲音完全相同的問題。

我甚至把它分解成載入一個導致這個錯誤的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()。 這釋放了其他應用程序需要的底層資源。 不要依靠 垃圾收集器進行清理的媒體對象,因爲它具有不可預知的時間。

0

嘗試

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

釋放應該保持你的資源。

2

我有一個類似的問題,我的Android遊戲中的音樂追蹤器會掉落音符,我得到Audioflinger錯誤(雖然我的狀態是-22)。然而,我得到了它的工作,所以這可能會幫助一些人。

單個樣品同時輸出多次時發生問題。所以在我的情況下,這是一個在兩個或多個軌道上播放的單個樣本。這似乎偶爾會出現僵局或者其他問題,並且兩個音符中的一個將被丟棄。解決方案是有兩個樣本副本(兩個實際的ogg文件 - 完全相同,但都在資產中)。然後,即使我在播放同一個樣本,但在每個曲目中,它都來自不同的文件。這完全解決了我的問題。

不知道爲什麼它會將樣本緩存到內存中,但即使將相同的文件加載到兩個不同的聲音中也沒有修復它。只有當樣本從兩個不同的文件中出來時,錯誤纔會消失。

我相信這不會幫助每個人,它不是最漂亮的修復程序,但它可能有助於某人。

2

john.k.doe是對的。你必須減小你的mp3文件的大小。你應該保持每個文件大小在100kb以下。我必須使用32kbps的恆定比特率(CBR)而不是通常的128kbps將我的200kb文件減少到72kb。這對我有效!

0

單個soundPool具有1(Mb)的內部內存限制。如果你的聲音質量很高,你可能會碰到這個問題。如果你有很多聲音並且達到了這個極限,只需要創建更多的聲音庫,然後在你的聲音中分配你的聲音。

如果內存不足,您甚至可能無法達到硬軌限制。

該錯誤不僅會在達到流或跟蹤限制時出現,還會出現內存限制。 Soundpool將停止播放舊的和/或優先級不高的聲音以播放新聲音。

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秒以內,所以我把價值2000毫秒的Thread.sleep()方法,以釋放只玩家完成後的資源。

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); 

,它的工作,但延遲對不同設備的不同。

1

在我的情況下,將MP3的質量和文件大小降低到100kb以下是不夠的,因爲一些51kb文件可以工作,而一些更長時間的41kb文件仍然沒有。

什麼幫助我們將採樣率從44100降低到22050或將持續時間縮短到不到5秒。

0

我看到太多過於複雜的答案。錯誤-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以避免空指針異常)。

它的作品像魅力!