欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

android使用SoundPool播放音效的方法

程序员文章站 2023-08-22 19:51:48
在android开发中我们经常使用mediaplayer来播放音频文件,但是mediaplayer存在一些不足,例如:资源占用量较高、延迟时间较长、不支持多个音频同时播放等...

在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 会出现下面的提醒:

android使用SoundPool播放音效的方法

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.使用代码示例:

运行效果图:

android使用SoundPool播放音效的方法

当点击按钮的时候会,"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();
  }
});

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