2011-03-05 62 views
21

我有一個.wav文件,我想在我的遊戲中使用,當前我正在加載遊戲中每個活動的onCreate()聲音。Soundpool示例沒有準備好

soundCount = soundpool.load(this,R.raw.count, 1); 

活動開始後會播放聲音。

soundpool.play(soundCount, 0.9f, 0.9f, 1, -1, 1f); 

問題是有時我會碰到錯誤"sample x not ready"。 啓動遊戲後,是否可以加載.wav文件並將其保存在內存中,並在以後的整個遊戲中使用它?或者是否有可能等待1-2秒來完成聲音加載?

回答

32

您需要等待它完成後才能通過SoundPool.setOnLoadCompleteListener添加偵聽器。

+7

不幸的是,setOnLoadCompleteListener不是API 8 :(之前提供是否有任何其他衆所周知的解決方案來解決這個問題,除了使用setOnLoadCompleteListener?/感謝 – SteD 2011-03-05 08:13:54

5

由於我的項目與Android 1.5兼容,我無法使用setOnLoadCompleteListener,因此我決定讓播放的聲音延遲。 我的源代碼如下:

playSound_Delayed(soundId, 100); 

//(..)

private void playSound_Delayed (final int soundId, final long millisec) { 
    // TIMER 
    final Handler mHandler = new Handler(); 
    final Runnable mDelayedTimeTask = new Runnable() { 
    int counter = 0; 
    public void run() { 
     counter++; 

     if (counter == 1) { 
      boolean ret = mHandler.postDelayed(this, millisec); 
      if (ret==false) Log.w("playSound_Delayed", "mHandler.postAtTime FAILED!"); 
     } else { 
      playSound(soundId); 
     } 
    } 
    }; 
    mDelayedTimeTask.run(); 
} 
+1

不完全的話題,但你可能想替換System.err的.println與Log.w爲了在LogCat上顯示 – superjos 2012-01-20 15:44:32

+1

System.err.println確實在logcat中顯示了System.err標記,但我同意Log.w更清潔 – entropy 2012-10-04 20:31:12

2

的的Soundpool庫使用的MediaPlayer服務到音頻解碼成原始的16位PCM單聲道或立體聲流,我們只需調用Stream的準備工作,根據聲音文件的大小需要一些時間。如果我們在該過程結束之前嘗試播放聲音,則會出現「sample x not ready」錯誤。

有兩種方案來解決這個

  1. 實施setOnLoadCompleteListener或
  2. 等待任意時間量,以便準備在

然後播放 注意,沒有例外這種情況或應用程序不崩潰沒有任何try-catch

4

你應該使用setOnLoadComplet如果可能的話,可以使用eListener ...如果沒有,請在打電話時圍繞'play'換一個while循環。例如:

int waitLimit = 1000; 
int waitCounter = 0; 
int throttle = 10; 
while(soundPool.play(soundId, 1.f, 1.f, 1, 0, 1.f) == 0 && waitCounter < waitLimit) 
{waitCounter++; SystemClock.sleep(throttle);} 

這將在10ms間隔重試'播放'1000次。這當然應該在非ui線程上運行,並且仍然不理想。但也許比等待任意時間稍微強一點,並期望游泳池準備就緒。

1

這聽起來很瘋狂,但不要馬上播放聲音。給你的應用程序幾秒鐘來初始化SoundPool。在我的應用程序中,這正是問題;我添加了一個假的「加載」屏幕〜3秒,然後一切正常。 (我甚至不需要預先加載聲音。)

+0

這就是我正在做的但我覺得它真的很煩人,遊戲加載一秒鐘,加載屏幕只是爲了聽起來的緣故 – 2012-04-16 18:40:10

+0

@WKS我也有一個想法,使加載屏幕成爲一個迷你遊戲或放置一些交互性在它作爲一個「復活節彩蛋」ki nda的事情,即使它只是幾秒鐘可見。 – ashes999 2012-04-16 18:52:56

2
private SoundPool soundPool; 
private int my_sound; 
boolean loaded = false; 

//在構造

soundPool = new SoundPool(10, AudioManager.STREAM_MUSIC, 0); 
my_sound = soundPool.load(this, R.raw.blast_sound, 1); 

soundPool.setOnLoadCompleteListener(new OnLoadCompleteListener() { 
    public void onLoadComplete(SoundPool soundPool, int sampleId,int status) { 
     loaded = true; 
    } 
}); 

//然後在任何你想要播放的聲音,類型

if (loaded) { 
soundPool.play(my_sound, 0.9f, 0.9f, 1, 0, 1f); 
} 
2

我解決了用簡單的做,而cicle問題。方法play()如果​​成功返回非零streamID,如果失敗則返回零。所以,檢查返回值就足夠了。

int streamID = -1; 
do { 
    streamID = soundPool.play(soundPoolMap.get(index), streamVolume, streamVolume, 1, 0, 1f); 
} while(streamID==0); 
2

這會爲你工作肯定!

public void playWavFile() { 

    Thread streamThread = new Thread(new Runnable() {   

     @Override 
     public void run() {     
      SoundPool soundPool; 
      final int wav; 
      String path = "/mnt/sdcard/AudioRecorder/record.wav"; 
      soundPool = new SoundPool(5,AudioManager.STREAM_MUSIC, 0); 
      wav = soundPool.load(path, 1); 
      soundPool.setOnLoadCompleteListener(new OnLoadCompleteListener() { 
       @Override 
       public void onLoadComplete(SoundPool soundPool, int sampleId, int status) { 
        // TODO Auto-generated method stub 
        soundPool.play(wav,100, 100, 0, 0, 1f); 
       } 
      }); 

     }   
    }); 

    streamThread.start(); 
}