一、使用MediaPlayer來播放音頻檔案存在一些不足:
例如:資源佔用量較高、延遲時間較長、不支援多個音頻同時播放等。
這些缺點決定了MediaPlayer在某些場合的使用方式不會很理想,所有,一般的遊戲開發都是用的Soundpool。
在沒有瞭解Soundpool之前,我也是使用的普通的MediaPlayer進行檔案播放,但這個方法不適合用於遊戲開發,因為遊戲裡面經常要同時播放幾個音樂檔案,用過MediaPlayer的朋友都該知道,它是不支援即時播放多個聲音的,而且還會出現或多或少的延遲,尤其是在快速連續播放聲音(比如連續猛點按鈕)時,會非常明顯,長的時候會出現3~5秒的延遲,【使用MediaPlayer.seekTo() 這個方法來解決此問題】;
相對於使用SoundPool存在的一些問題:
1. SoundPool是為播放小檔案而存在的。一般限定Soundpool播放檔案的大小為1M。
2. SoundPool提供了pause和stop方法,但這些方法建議最好不要輕易使用,因為有些時候它們可能會使你的程式莫名其妙的終止。還有些朋友反映它們不會立即中止播放聲音,而是把緩衝區裡的資料播放完才會停下來,也許會多播放一秒鐘。
3. 音頻格式建議使用OGG格式。使用WAV格式的音頻檔案存放遊戲音效,經過反覆測試,在音效播放間隔較短的情況下會出現異常關閉的情況(有說法是SoundPool目前只對16bit的WAV檔案有較好的支援)。後來將檔案轉成OGG格式,問題得到瞭解決。
4.在使用SoundPool播放音訊時候,如果在初始化中就調用播放函數進行播放音樂那麼根本沒有聲音,不是因為沒有執行,而是SoundPool需要一準備時間!這就是剛剛我們說的用OnLoadCompleteListener來解決的問題。如果你非得是1.6甚至更低的話,那建議在播放的時候,將play放到一個點擊事件中去,當然在這個中也要注意一下兩點。
a、 別忘記綁定操作! mp.setOnCompletionListener(this);
b、如果你設定了迴圈播放 mp.setLooping(true); 的話,那麼永遠都不會監聽到播放完成的狀態!!
二、SoundPool
SoundPool
構造方法
構造方法 |
描述 |
public SoundPool (int maxStreams, int streamType, int srcQuality) |
參數說明: maxStreams:指定支援多少個檔案 streamType:指定聲音類型 srcQuality:聲音品質 |
常見方法
方法名稱 |
描述 |
public int load (Context context, int resId, int priority) |
從資源ID所對應的資源載入聲音 |
public int load (AssetFileDescriptor afd, int priority) |
從原始資源檔中載入聲音 |
public int load (FileDescriptor fd, long offset, long length, int priority) |
從原始資源檔中載入聲音並設定載入從哪開始到多長的音效檔 |
public int load (String path, int priority) |
從指定檔案路徑載入聲音 |
public final void pause (int streamID) |
暫停 |
public final int play (int soundID, float leftVolume, float rightVolume, int priority, int loop, float rate) |
播放 參數說明: soundID:資源ID leftVolume:左頻道聲音 rightVolume:右頻道聲音 loop:-1代表迴圈,0代表不迴圈 rate:值0.5-2.0設定1為正常 |
public final void release () |
釋放SoundPool對象資源 |
public final void stop (int streamID) |
停止 |
public void setOnLoadCompleteListener (SoundPool.OnLoadCompleteListener listener) |
設定監聽器,在載入音樂檔案完成時觸發該事件 |
三、上代碼:
main.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/mainlayout" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#ffffffff" android:orientation="vertical" > <Button android:id="@+id/bt" android:layout_width="fill_parent" android:layout_height="fill_parent" /></LinearLayout>
SoundPoolActivity.java
import android.app.Activity;import android.media.AudioManager;import android.media.SoundPool;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;public class SoundPoolActivity extends Activity implementsSoundPool.OnLoadCompleteListener{/** Called when the activity is first created. */private Button button;private int[] menuSound;private SoundPool mSoundPool = null;private int i =0;// private final Handler mHandler = new MyHandler();@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);button = (Button) findViewById(R.id.bt);mSoundPool = new SoundPool(10, AudioManager.STREAM_SYSTEM, 0);mSoundPool.setOnLoadCompleteListener(ViewgroupActivity.this);menuSound = new int[2];mSoundPool = new SoundPool(2, AudioManager.STREAM_SYSTEM, 0);menuSound[0] = mSoundPool.load(getApplicationContext(),R.raw.eng_music, 1);menuSound[1] = mSoundPool.load(getApplicationContext(),R.raw.eng_music, 1);button.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubif((i%2)==0){i++;mSoundPool.play(menuSound[0], 10, 10, 0, 0, (float) 1);// 播放鈴聲}else {mSoundPool.play(menuSound[1], 10, 10, 0, 0, (float) 1);// 播放鈴聲}}});}@Overrideprotected void onDestroy() {// TODO Auto-generated method stubmSoundPool.release();mSoundPool.stop(menuSound[0]);mSoundPool.stop(menuSound[1]);super.onDestroy();}@Overridepublic void onLoadComplete(SoundPool arg0, int arg1, int arg2) {// TODO Auto-generated method stub}}