0
点赞
收藏
分享

微信扫一扫

Android开发之SoundPool


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

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

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

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

1. new出一个实例 ;


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代表正常速度

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
 }


这个就到这里了吧。。。

举报

相关推荐

0 条评论