在Android开发中我们经常使用MediaPlayer来播放音频文件,但是MediaPlayer存在一些不足,例如:资源占用量较高、延迟时间较长、不支持多个音频同时播放等。
SoundPool(android.media.SoundPool),顾名思义是声音池的意思,主要用于播放一些较短的声音片段,支持从程序的资源或文件系统加载。与MediaPlayer相比,SoundPool的优势在于CPU资源占用量低和反应延迟小。另外,SoundPool还支持自行设置声音的品质、音量、播放比率等参数,支持通过ID对多个音频流进行管理。
- SoundPool存在的缺陷
1.SoundPool最大只能申请1M的内存空间,这就意味着我们只能用一些很短的声音片段,而不是用它来播放歌曲或者做游戏背景音乐。
2.SoundPool提供了pause和stop方法,但这些方法建议最好不要轻易使用,因为有些时候它们可能会使你的程序莫名其妙的终止。建议使用这两个方法的时候尽可能多做测试工作,还有些朋友反映它们不会立即中止播放声音,而是把缓冲区里的数据播放完才会停下来,也许会多播放一秒钟。
3.SoundPool的效率问题。其实SoundPool的效率在这些播放类中算是很好的了,但是有的朋友在G1中测试它还是有100ms左右的延迟,这可能会影响用户体验。也许这不能管SoundPool本身,因为到了性能比较好的Droid中这个延迟就可以让人接受了。
在现阶段SoundPool有这些缺陷,但也有着它不可替代的优点,基于这些我们建议大在如下情况中多使用SoundPool:
1.应用程序中的声效(按键提示音,消息等)
2.游戏中密集而短暂的声音(如多个飞船同时爆炸)
【from:http://blog.csdn.net/meng_tianshi/article/details/7515714】
开发步骤:
1>往项目的res/raw目录中放入音效文件。
2>新建SoundPool对象,然后调用SoundPool.load()加载音效,调用SoundPool.play()方法播放指定音效文件。
以语音报号为例的程序示例:
1 int loadId; 2 int loadId1; 3 int loadId2; 4 int loadId3; 5 int loadId4; 6 int loadId5; 7 int loadId6; 8 int loadId7; 9 int loadId8; 10 int loadId9; 11 SoundPool soundPool; 12 int currentVol = 100; 13 14 soundPool = new SoundPool(2, AudioManager.STREAM_MUSIC, 100); 15 loadId = soundPool.load(context, R.raw.zero, 1); 16 loadId1 = soundPool.load(context, R.raw.one, 2); 17 loadId2 = soundPool.load(context, R.raw.two, 3); 18 loadId3 = soundPool.load(context, R.raw.three, 4); 19 loadId4 = soundPool.load(context, R.raw.four, 5); 20 loadId5 = soundPool.load(context, R.raw.five, 4); 21 loadId6 = soundPool.load(context, R.raw.six, 3); 22 loadId7 = soundPool.load(context, R.raw.seven, 2); 23 loadId8 = soundPool.load(context, R.raw.eight, 1); 24 loadId9 = soundPool.load(context, R.raw.nine, 1); 25 26 @Override 27 public void afterTextChanged(Editable s) { 28 if (Rest_Length > 0) { 29 near_user_close.setVisibility(View.VISIBLE); 30 if ((lengthbefore <= Rest_Length) 31 && (Rest_Length - lengthbefore == 1)) { 32 lengthbefore = Rest_Length; 33 SaveServerParam smic = new SaveServerParam(); 34 Map<String, String> mictag = smic.getSvrParam(context); 35 if (mictag.get("micparam").equals("TRUE")) { 36 int value = Integer.parseInt(telnumb.getText() 37 .toString().substring(lengthbefore - 1)); 38 switch (value) { 39 case 0: 40 soundPool.play(loadId, currentVol, currentVol, 1, 0, 1f);// 备注3 41 break; 42 case 1: 43 soundPool.play(loadId1, currentVol, currentVol, 1, 0, 1f);// 备注3 44 break; 45 case 2: 46 soundPool.play(loadId2, currentVol, currentVol, 1, 0, 1f);// 备注3 47 break; 48 case 3: 49 soundPool.play(loadId3, currentVol, currentVol, 1, 0, 1f);// 备注3 50 break; 51 case 4: 52 soundPool.play(loadId4, currentVol, currentVol, 1, 0, 1f);// 备注3 53 break; 54 case 5: 55 soundPool.play(loadId5, currentVol, currentVol, 1, 0, 1f);// 备注3 56 break; 57 case 6: 58 soundPool.play(loadId6, currentVol, currentVol, 1, 0, 1f);// 备注3 59 break; 60 case 7: 61 soundPool.play(loadId7, currentVol, currentVol, 1, 0, 1f);// 备注3 62 break; 63 case 8: 64 soundPool.play(loadId8, currentVol, currentVol, 1, 0, 1f);// 备注3 65 break; 66 case 9: 67 soundPool.play(loadId9, currentVol, currentVol, 1, 0, 1f);// 备注3 68 break; 69 } 70 } 71 /*lengthbefore是记录的之前的字符长度 72 * Rest_Length是当前的字符长度 73 * */ 74 }else if(lengthbefore > Rest_Length){ 75 lengthbefore = Rest_Length; 76 } 77 } 78 }
SoundPool报sample 1 not READY异常:
因为未完成加载就播放了,应该监听加载完成后调用播放
1 SoundPool soundPool = new SoundPool(10, AudioManager.STREAM_MUSIC, 5); 2 //载入音频流,返回在池中的id 3 final int sourceid = soundPool.load(mContext, R.raw.move_sound, 0); 4 //播放音频,第二个参数为左声道音量;第三个参数为右声道音量;第四个参数为优先级;第五个参数为循环次数,0不循环,-1循环;第六个参数为速率,速率最低0.5最高为2,1代表正常速度 5 soundPool.setOnLoadCompleteListener(new OnLoadCompleteListener() { 6 7 public void onLoadComplete(SoundPool soundPool, int sampleId, int status) { 8 // TODO Auto-generated method stub 9 soundPool.play(sourceid, 2, 2, 0, 0, 1); 10 } 11 });