使用背景:
在Android中播放音频文件经常会用到MediaPlayer,但是MediaPlayer存在一些不足的地方,如:资源占用量较高、加载延迟时间较长、不支持多个音频同时播放等。这些缺点决定了MediaPlayer在某些需要密集使用不同音频的情况不会理想,例如游戏开发。在游戏开发中,我们经常需要播放一些游戏的音效,这些音效的都需要是短促、密集、延迟小的,在这种场景下,需要使用到SoundPool来替代MediaPlayer播放这些音效。
SoundPool(声音池):
所处于"android.media.SoundPool"包下,主要用于播放一些较短的声音片段,支持从程序的资源或文件系统加载。与MediaPlayer相比,SoundPool的优势在于CPU的资源占用量低、反应延迟小,并且可以加载多个音频到SoundPool中,通过资源ID来管理。另外SoundPool还支持执行设置声音的品质、音量、播放比率等参数
构造函数:
SoundPool(int maxStreams,int streamType,int srcQuality);
第一个参数为音频池最多支持装载多少个音频,就是音频池的大小;
第二个参数指定声音的类型,在AudioManager类中以常量的形式定义,一般指定为AudioManager.STREAM_MUSIC即可;
第三个参数为音频的质量,默认为0,这个参数为预留参数,现在没有实际意义,为扩展预留字段,一般传0即可。
常用的SoundPool方法:
- int load(Context context,int resId,int priority):从一个文件夹raw下装载一段音频资源,返回值为音频资源在SoundPool的ID。
- int load(String path,int priority):从一个资源文件的路径装载一段音频资源,返回值为音频资源在SoundPool的ID。
- final int play(int soundID,float leftVolume,float rightVolume,int priority,int loop,float rate):根据资源ID,播放一段音频资源。
- final void pause(int streamID):根据装载资源ID,暂停音频资源的播放。
- final void resume(int streamID):根据装载资源ID,继续播放暂停的音频资源。
- final void stop(int streamID):根据装载资源ID,停止音频资源的播放。
- final boolean unload(int soundID) :从音频池中卸载音频资源ID为soundID的资源。
- final void release():释放音频池资源。
上面方法无疑Load()和play()是最重要的,Load()具有多种重载方法,从参数名就可以看出是什么意思。这里讲解一下play()方法,soundID参数为资源ID;leftVolume和rightVolume个参数为左右声道的音量,从大到小取0.0f~1.0f之间的值;priority为音频质量,暂时没有实际意义,传0即可;loop为循环次数,0为播放一次,-1为无线循环,其他正数+1为播放次数,如传递3,循环播放4次;rate为播放速率,从大到小取0.0f~2.0f,1.0f为正常速率播放。
在使用load()装载音频的时候需要注意,load()方法是一个异步的方法,也就是说,在播放音频的时候,很可能此段音频还没有装载到音频池中,这里可以借助SoundPool的一个装载完成的监听事件SoundPool.setOnLoadCompleteListener来保证装载完成在播放声音。SoundPool.setOnLoadCompleteListener()需要实现一个SoundPool.OnLoadCompleteListener接口,其中需要实现onLoadComplete()方法,一下是onLoadComplete()方法的完整签名:
onLoadComplete(SoundPool soundPool, int sampleId, int status)
- soundPool:当前触发事件的声音池。
- sampleId:当前装载完成的音频资源在音频池中的ID。
- status:状态码,展示没有意义,为预留参数,会传递0。
使用示例:
public
class
Util {
public
static
SoundPool
sp
;
public
static
Map<Integer, Integer>
suondMap
;
public
static
Context
context
;
//
public
static
void
initSoundPool(Context
context
){
Util.
context
=
context
;
sp
=
new
SoundPool(1, AudioManager.
STREAM_MUSIC
, 1);//1表示音频池数量 2表示声音类型 3音频质量
suondMap
=
new
HashMap<Integer, Integer>();
suondMap
.put(1,
sp
.load(
context
, R.raw.
beep
, 1)); //异步装载音频文件
}
//
public
static
void
play(
int
sound
,
int
number
){
AudioManager
am
= (AudioManager)Util.
context
.getSystemService(Util.
context
.
AUDIO_SERVICE
);
//获得控制声音的对象
//
float
audioMaxVolume
=
am
.getStreamMaxVolume(AudioManager.
STREAM_MUSIC
);//最大音量
//
float
audioCurrentVolume
=
am
.getStreamVolume(AudioManager.
STREAM_MUSIC
);//当前音量
float
volumnRatio
=
audioCurrentVolume
/
audioMaxVolume
;
sp
.play(
suondMap
.get(
sound
),
//音频文件资源ID
audioCurrentVolume
,
//左声道音量从0.0f
audioCurrentVolume
,
//右声道音量到1.0f之间取值
1,
//音频质量,无实际意义传0即可
number,
//循环次数 0为播放一次,-1为无线循环,其他正数+1为播放次数,如传递3,循环播放4次
1);
//播放速度0.0f~2.0f 1为正常速度
}
public
static
void
pasue() {
sp
.pause(0);
}
}