对于MediaPlayer无法同时播放多个声音的问题,Android提供了声音池工具SoundPool,使用声音池即可对多个声音的播放进度调度。
1.SoundPool优点
- 资源占用量小,不像MediaPlayer那么耗资源。
- 相对MediaPlayer来说,延迟时间非常小。
- 可以同时播放多个音频,从而实现游戏过程中多个声音叠加的情景。
2.SoundPool使用限制
- SoundPool最大只能申请1MB的内存,这意味着它只能播放一些很短的声音片段,不能用于播放歌曲或者游戏背景音乐。
- 虽然SoundPool提供了pause和Stop方法,但是轻易不要使用这两个方法,因为他们可能会让App异常或崩溃。
- SoundPool建议播放ogg格式的音频,据说它对Wav格式的支持不是太好。
- 待播放的音频要提前加载进声音池,不要等到要播放的时候才加载,否则可能播放没声音。因为SoundPool不会等音频加载完了才播放,而MediaPlayer会等待加载完毕才播放。
3.SoundPool常用方法
- 构造函数:可设置最大音频个数、音频类型、音频质量。其中音频类型一般是AudioManager.STREAM_MUSIC,音频质量取值为0到100。
- load:加载指定的音频文件。返回值为该音频的编号。
- unload:卸载指定编号的音频。
- play:播放指定编号的音频。可同时设置左右声道的音量(取值为0.0到1.0)、优先级(0为最低)、是否循环播放(0为播放一次,-1为无限循环)、播放速率(取值为0.5-2.0,其中1.0为正常速率)。
- setVolume:设置指定编号音频的音量大小。
- setPriority:设置指定编号音频的优先级。
- setLoop:设置指定编号的音频是否循环播放。
- setRate:设置指定编号音频的播放速率。
- pause:暂停播放指定编号的音频。
- resume:恢复播放指定编号的音频。
- autoPause:暂停所有正在播放的音频。
- autoResume:恢复播放所有被暂停的音频。
- stop:停止播放指定编号的音频。
- release:释放所有音频资源。
- setOnLoadCompleteListener:设置音频加载完毕的监听器。需实现接口OnLoadCompleteListener的onLoadComplete方法,该方法在音频加载结束后触发。
4..SoundPool使用示例
public class MainActivity extends WaterPermissionActivity<MainModel>
implements MainCallback, View.OnClickListener {
private HashMap<Integer,Integer> mSoundMap;//声音编号映射
private SoundPool mSoundPool;//声音池对象
private Button bt_total;
private Button bt1;
private Button bt2;
private Button bt3;
@Override
protected MainModel getModelImp() {
return new MainModel(this,this);
}
@Override
protected int getContentLayoutId() {
return R.layout.activity_main;
}
@Override
protected void initWidget() {
statusBarColor(R.color.white,false);
bt_total = findViewById(R.id.bt_total);
bt1 = findViewById(R.id.bt1);
bt2 = findViewById(R.id.bt2);
bt3 = findViewById(R.id.bt3);
bt_total.setOnClickListener(this);
bt1.setOnClickListener(this);
bt2.setOnClickListener(this);
bt3.setOnClickListener(this);
initSound();
}
/**
* 初始化声音池
*/
private void initSound(){
mSoundMap = new HashMap<>();
mSoundPool = new SoundPool(3, AudioManager.STREAM_MUSIC,100);
loadSound(1,R.raw.beep1);
loadSound(2,R.raw.beep2);
loadSound(3,R.raw.ring);
}
/**
* 把音频资源添加到声音池
* @param seq
* @param resid
*/
private void loadSound(int seq,int resid){
int soundID = mSoundPool.load(this,resid,1);
mSoundMap.put(seq,soundID);
}
/**
* 播放指定音频
* @param seq
*/
private void playSound(int seq){
int soundID = mSoundMap.get(seq);
mSoundPool.play(soundID,1.0f,1.0f,1,0,1.0f);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.bt_total:
playSound(1);
playSound(2);
playSound(3);
break;
case R.id.bt1:
playSound(1);
break;
case R.id.bt2:
playSound(2);
break;
case R.id.bt3:
playSound(3);
break;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mSoundPool!=null){
mSoundPool.release();
}
}
}