当前位置: 移动技术网 > IT编程>移动开发>Android > android使用SoundPool播放音效的方法

android使用SoundPool播放音效的方法

2019年07月24日  | 移动技术网IT编程  | 我要评论

明日之子孟子坤,墙纸,专车内遭怪风吹晕

在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)常用方法介绍:

①加载声音资源:

  1. load(context context, int resid, int priority)
  2. load(string path, int priority)
  3. load(filedescriptor fd, long offset, long length, int priority)
  4. load(assetfiledescriptor afd, int priority) 上述方法都会返回一个声音的id,后面我们可以通过这个id来播放指定的声音

参数介绍:

  1. context:上下文
  2. resid:资源id
  3. priority:没什么用的一个参数,建议设置为1,保持和未来的兼容性
  4. path:文件路径
  5. filedescriptor:貌似是流吧,这个我也不知道
  6. assetfiledescriptor:从asset目录读取某个资源文件,用法:
assetfiledescriptor descriptor = assetmanager.openfd("biaobiao.mp3");

②播放控制:

play(int soundid, float leftvolume, float rightvolume, int priority, int loop, float rate)

参数依次是:

  1. soundid:load()返回的声音id号
  2. leftvolume:左声道音量设置
  3. rightvolume:右声道音量设置
  4. priority:指定播放声音的优先级,数值越高,优先级越大。
  5. loop:指定是否循环:-1表示无限循环,0表示不循环,其他值表示要重复播放的次数
  6. 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();
  }
});

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网