Android开发之SoundPool

忙了两天终于得空写点东西,感慨良多,今天主要总结一下,这个SoundPool的使用,以及注意事项。

首先,SoundPool的定位,她是一个音效播放的执行者,这跟MediaPlayer的最终效果是一样的,她们都是用来播放音乐的。

今天,我们主讲一下,SoundPool这个类。附带的说一说她与MediaPlayer的区别。

下面我们说一下SoundPool播放音频的实现步骤:

1. new出一个实例 ;

 
1 new SoundPool(int maxStream, int streamType, int srcQuality);

maxStream —— 同时播放的流的最大数量

streamType —— 流的类型,一般为STREAM_MUSIC(具体在AudioManager类中列出)

srcQuality —— 采样率转化质量,当前无效果,使用0作为默认值

比如说,

new SoundPool(4, AudioManager.STREAM_MUSIC, 100);

创建了一个最多支持4个流同时播放的,类型标记为音乐的SoundPool。

2.加载

一般把多个声音放到HashMap中去,比如
soundPool = new SoundPool(4, AudioManager.STREAM_MUSIC, 100);
soundPoolMap = new HashMap<Integer, Integer>();
soundPoolMap.put(1, soundPool.load(this, R.raw.ring, 1));

当然,我们也可以加载单个的Music,那我们怎么实现播放指定的Music呢?

有关载入音效的方法,有以下几种方法:

 
1 int load(Context context, int resId, int priority) //从APK资源载入(就是说,在你码代码的时候工程中的文件。比如,我在res/raw这个文件夹中放了一个ring.mp3,那,resIdential就是 R.raw.ring)
2 int load(FileDescriptor fd, long offset, long length, int priority) //从FileDescriptor对象载入
3 int load(AssetFileDescriptor afd, int priority) //从Asset对象载入
4 int load(String path, int priority) //从完整文件路径名载入
5
6 所有的最后一个参数 priority 是优先级。这里用于播放多个文件时,系统会优先处理。

3,播放

play(int soundID, float leftVolume, float rightVolume, int priority, int loop, float rate);

其中soundID,就是刚刚load方法得到的那个int型参数,leftVolume和rightVolume表示左右音量,priority表示优先级,loop表示循环次数,rate表示速率,如
//速率最低0.5最高为2,1代表正常速度

 
1 sp.play(soundId, 1, 1, 0, 0, 1);

4,停止

停止可以使用 pause(int streamID) 方法,这里的streamID和soundID均在构造SoundPool类的第一个参数中指明了总数量,而id从0开始。

OK,这就是一个SoundPool的流程,可是,有人要问了,为什么我按这个流程写下来,却没有播放呢?

不饶弯子,因为,在play之前Soundpool没有初始化完毕,那我们如何知道,Soundpool的load已经完毕了呢?Android提供了检测是否初始化完毕的方法,SoundPool.OnLoadCompleteListener;但是这个方法是从SDK2.2才开始有的。所以找错之前,先看看自己的平台。。。
下面讲下两个播放形式的利弊:

一,使用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); 的话,那么永远都不会监听到播放完成的状态!!

下面分享一下源码,

 
01 import android.app.Activity;
02 import android.media.AudioManager;
03 import android.media.SoundPool;
04 import android.os.Bundle;
05 import android.os.Handler;
06 import android.os.Message;
07 import android.view.View;
08 import android.view.View.OnClickListener;
09 import android.widget.Button;
10 import android.media.SoundPool.OnLoadCompleteListener;</p>
11 public class DemoActivity extends Activity implements SoundPool.OnLoadCompleteListener{
12
13 private Button button;
14 private SoundPool sndPool;
15 private int hitOkSfx;
16 private static final int SOUND_LOAD_OK = 1;
17 private final Handler mHandler = new MyHandler() ;
18 @Override
19 public void onCreate(Bundle savedInstanceState) {
20 super.onCreate(savedInstanceState);
21 setContentView(R.layout.main);
22 button = (Button)findViewById(R.id.button1);
23 sndPool = new SoundPool(10, AudioManager.STREAM_SYSTEM, 0);
24 sndPool.setOnLoadCompleteListener(this);
25 hitOkSfx = sndPool.load(this, R.raw.ring, 1);
26 button.setOnClickListener(new OnClickListener() {
27 @Override
28 public void onClick(View v) {
29 // TODO Auto-generated method stub
30 sndPool.play(hitOkSfx, 10, 10, 0, 0, (float)1);//播放铃声
31 }
32 });
33 }
34 @Override
35 protected void onDestroy() {
36 // TODO Auto-generated method stub
37 sndPool.release();
38 sndPool.stop(hitOkSfx);
39 super.onDestroy();
40
41 }
42 private class MyHandler extends Handler {
43 public void handleMessage(Message msg){
44 switch( msg.what){
45 case SOUND_LOAD_OK:
46 sndPool.play(hitOkSfx, 10, 10, 0, 0, (float)1);//播放铃声
47 break;
48 }
49 }
50 }
51 @Override
52 public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
53 // TODO Auto-generated method stub
54 Message msg = mHandler.obtainMessage(SOUND_LOAD_OK); ;
55 msg.arg1 = sampleId ;
56 mHandler.sendMessage(msg);
57 }
58
59 }

这个就到这里了吧。。。

转自:http://www.andcoder.com/archives-2011-08-173.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值