android使用SoundPool播放音效的方法
在android开发中我们经常使用mediaplayer来播放音频文件,但是mediaplayer存在一些不足,例如:资源占用量较高、延迟时间较长、不支持多个音频同时播放等。这些缺点决定了mediaplayer在某些场合的使用情况不会很理想,例如在对时间精准度要求相对较高的游戏开发中。
在游戏开发中我们经常需要播放一些游戏音效(比如:子弹爆炸,物体撞击等),这些音效的共同特点是短促、密集、延迟程度小。在这样的场景下,我们可以使用soundpool代替mediaplayer来播放这些音效。
soundpool(android.media.soundpool),顾名思义是声音池的意思,主要用于播放一些较短的声音片段,支持从程序的资源或文件系统加载。与mediaplayer相比,soundpool的优势在于cpu资源占用量低和反应延迟小。另外,soundpool还支持自行设置声音的品质、音量、播放比率等参数,支持通过id对多个音频流进行管理。
就现在已知的资料来说,soundpool有一些设计上的bug,从固件版本1.0开始有些还没有修复,我们在使用中应该小心再小心。相信将来google会修复这些问题,但我们最好还是列出来:
1. soundpool最大只能申请1m的内存空间,这就意味着我们只能用一些很短的声音片段,而不是用它来播放歌曲或者做游戏背景音乐。
2. soundpool提供了pause和stop方法,但这些方法建议最好不要轻易使用,因为有些时候它们可能会使你的程序莫名其妙的终止。建议使用这两个方法的时候尽可能多做测试工作,还有些朋友反映它们不会立即中止播放声音,而是把缓冲区里的数据播放完才会停下来,也许会多播放一秒钟。
3. soundpool的效率问题。其实soundpool的效率在这些播放类中算是很好的了,但是有的朋友在g1中测试它还是有100ms左右的延迟,这可能会影响用户体验。也许这不能管soundpool本身,因为到了性能比较好的droid中这个延迟就可以让人接受了。
在现阶段soundpool有这些缺陷,但也有着它不可替代的优点,基于这些我们建议大在如下情况中多使用soundpool:1.应用程序中的声效(按键提示音,消息等)2.游戏中密集而短暂的声音(如多个飞船同时爆炸)
1.相关方法介绍:
1)构造方法:
soundpool(int maxstreams, int streamtype, int srcquality) 参数依次是:
①指定支持多少个声音,soundpool对象中允许同时存在的最大流的数量。
②指定声音类型,流类型可以分为stream_voice_call, stream_system, stream_ring,stream_music 和 stream_alarm四种类型。在audiomanager中定义。
③指定声音品质(采样率变换质量),一般直接设置为0!
在低版本中可以用上述构造方法,而api 21(android 5.0)后这个构造方法就过时了! 而用到一个soundpool.builder的东东,我们要实例化soundpool只需调用:
soundpool.builder spb = new soundpool.builder(); spb.setmaxstreams(10); spb.setaudioattributes(null); //转换音频格式 soundpool sp = spb.build(); //创建soundpool对象
要使用上述代码的话,targetsdk版本要设置大于等于21哦!而且如果minsdk版本小于21 会出现下面的提醒:
2)常用方法介绍:
①加载声音资源:
- load(context context, int resid, int priority)
- load(string path, int priority)
- load(filedescriptor fd, long offset, long length, int priority)
- load(assetfiledescriptor afd, int priority) 上述方法都会返回一个声音的id,后面我们可以通过这个id来播放指定的声音
参数介绍:
- context:上下文
- resid:资源id
- priority:没什么用的一个参数,建议设置为1,保持和未来的兼容性
- path:文件路径
- filedescriptor:貌似是流吧,这个我也不知道
- assetfiledescriptor:从asset目录读取某个资源文件,用法:
assetfiledescriptor descriptor = assetmanager.openfd("biaobiao.mp3");
②播放控制:
play(int soundid, float leftvolume, float rightvolume, int priority, int loop, float rate)
参数依次是:
- soundid:load()返回的声音id号
- leftvolume:左声道音量设置
- rightvolume:右声道音量设置
- priority:指定播放声音的优先级,数值越高,优先级越大。
- loop:指定是否循环:-1表示无限循环,0表示不循环,其他值表示要重复播放的次数
- rate:指定播放速率:1.0的播放率可以使声音按照其原始频率,而2.0的播放速率,可以使声音按照其 原始频率的两倍播放。如果为0.5的播放率,则播放速率是原始频率的一半。播放速率的取值范围是0.5至2.0。
③资源释放:
可以调用release()方法释放所有soundpool对象占据的内存和资源,当然也可以根据声音 id来释放!
3.使用代码示例:
运行效果图:
当点击按钮的时候会,"duang"一下,这里演示了两种load的方法,分别是raw和assests!
关键代码:
mainactivity.java:
private void initsp() throws exception{ //设置最多可容纳5个音频流,音频的品质为5 msoundpool = new soundpool(5, audiomanager.stream_system, 5); soundid.put(1, msoundpool.load(this, r.raw.duang, 1)); soundid.put(2 , msoundpool.load(getassets().openfd("biaobiao.mp3") , 1)); //需要捕获io异常 soundid.put(3, msoundpool.load(this, r.raw.duang, 1)); soundid.put(4, msoundpool.load(this, r.raw.duang, 1)); soundid.put(5, msoundpool.load(this, r.raw.duang, 1)); } @override public void onclick(view v) { switch (v.getid()){ case r.id.btn_play1: msoundpool.play(soundid.get(1), 1, 1, 0, 0, 1); break; case r.id.btn_play2: msoundpool.play(soundid.get(2), 1, 1, 0, 0, 1); break; case r.id.btn_play3: msoundpool.play(soundid.get(3), 1, 1, 0, 0, 1); break; case r.id.btn_play4: msoundpool.play(soundid.get(4), 1, 1, 0, 0, 1); break; case r.id.btn_play5: msoundpool.play(soundid.get(5), 1, 1, 0, 0, 1); break; case r.id.btn_release: msoundpool.release(); //回收soundpool资源 break; }
代码非常简单,另外如果你点击了最后一个按钮的话,soundpool就会被释放,然后再其他按钮 就不会duang了哦~
4.onloadcompletelistener监听声音文件是否加载完毕
嗯,这个是临时想起的,写完在写另一篇的时候突然想起,用法也很简单,我们可以 往上面的代码中添加onloadcompletelistener这个东东,然后重写onloadcomplete()方法 ,最后为soundpool对象设置这个东东即可!
msoundpool.setonloadcompletelistener(new soundpool.onloadcompletelistener() { @override public void onloadcomplete(soundpool soundpool, int sampleid, int status) { toast.maketext(mainactivity.this,"加特技准备完毕~",toast.length_short).show(); } });
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。