使用SoundPool的基本流程是:创建一个SoundPool对象、载入要播放的音频、播放某个音频、停止播放某个音频。
一个SoundPool对象可以载入多个音频,每个音频载入后对应一个SoundID。播放某个音频时用SoundID指定要播放的音频,并返回播放该音频的ChannelID。要停止播放某个音频,需要通过其ChannelID,注意不是SoundID!使用SoundPool播放音频的示意图如下:
下面用SoundPool编写一个播放音效的应用,可以单次、循环播放音效,界面如下:
有的设备上循环播放参数无效,可以采用Thread来实现。应用主要代码如下:
SoundPool类的主要方法包括:
1)构造函数:SoundPool(int maxStreams, int streamType, int srcQuality)。第一个参数maxStreams指定同时支持多少个声音,即Channel数量;第二个参数streamType指定声音类型,一般游戏中用AudioManager.STREAM_MUSIC;第三个参数srcQuality指定声音品质,目前没用,给0即可。
2)载入音频的load方法一共有4个,这里只列出最常用的两个:
int load(Context context, int resld, int priority):从 resld 所对应的资源加载音频
int load(String path, int priority):从path对应的文件去加载音频
priority参数,目前没用,Android建议设为1,保持和未来的兼容性;加载音频之后都会返回该声音的ID,以后可以通过ID来播放指定音频。
3)播放音频:int play(int soundID, float leftVolume, float rightVolume, int priority, int loop, float rate)。第一个参数soundID指定播放哪个声音;第二三个参数leftVolume、rightVolume指定左、右的音量;第四个参数priority指定播放声音的优先级,数值越大,优先级越高;第五个参数loop指定是否循环,0为不循环,-1为循环;经测试目前无效;第六个参数rate指定播放的比率,数值可从0.5到2, 1为正常比率;返回播放该音频的ChannelID,也叫StreamID,用此ID来对播放进行控制,如停止、暂停等。
4)卸载音频:boolean unload(int soundID)。卸载soundID指定的音频,成功返回true。
5)释放所有资源:void release()。
例子的完整代码如下:
public class MainActivity extends AppCompatActivity {
int[] soundResId = {R.raw.fly, R.raw.fire, R.raw.explode}; // 音频资源
SoundPool soundPool;
int[] soundId; // soundPool为每个装入的音频资源生成的SoundID
int flyStreamId; // soundPool播放fly音频时使用的Channel,通过Channel控制音效播放
PlayThread playThread; // 因为SoundPool的循环播放功能无效,所以用Thread来实现循环播放
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.VERTICAL);
setContentView(ll);
soundId = new int[soundResId.length];
soundPool = new SoundPool(3, AudioManager.STREAM_MUSIC, 100); // 创建SoundPool对象
for(int i=0; i<soundResId.length; i++)
soundId[i] = soundPool.load(this, soundResId[i], 1); // 依次载入音频资源,生成的SoundID存入soundId数组,播放时使用
Button btnFire = new Button(this);
btnFire.setText("Fire");
ll.addView(btnFire);
btnFire.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View arg0) {
soundPool.play(soundId[1], 1, 1, 1, 0, 1); // 播放fire音频,其SoundID存放在soundId[1]
}
});
Button btnExplode = new Button(this);
btnExplode.setText("Explode");
ll.addView(btnExplode);
btnExplode.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View arg0) {
soundPool.play(soundId[2], 1, 1, 1, 0, 1); // 播放explode音频,其SoundID存放在soundId[2]
}
});
Button btnStartFly = new Button(this);
btnStartFly.setText("Start Fly");
ll.addView(btnStartFly);
btnStartFly.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View arg0) {
flyStreamId = soundPool.play(soundId[0], 1, 1, 1, -1, 1f); // 控制循环播放的参数无效
//playThread = new PlayThread(soundId[0], 3000); // 启用一个线程,每隔3000毫秒播放一次fly音频,其长度大约为3000毫秒
//playThread.start();
}
});
Button btnStopFly = new Button(this);
btnStopFly.setText("Stop Fly");
ll.addView(btnStopFly);
btnStopFly.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View arg0) {
soundPool.stop(flyStreamId);
//playThread.stopPlay();
}
});
}
@Override
protected void onDestroy(){
super.onDestroy();
soundPool.release();
}
class PlayThread extends Thread {
boolean flag;
int soundId;
int streamId;
int duration;
public PlayThread(int sId, int d){
soundId = sId;
duration = d;
}
public void run(){
flag = true;
while(flag){
streamId = soundPool.play(soundId, 1, 1, 1, 0, 1f); // 播放音频soundId
try {
sleep(duration); // 等待该音频的播放时间
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void stopPlay(){
soundPool.stop(streamId); // 立即停止SoundPool的streamId频道的播放
flag = false; // 停止播放循环
}
}
}