Android--SoundPool

简介:

SoundPool

  SoundPool(声音池),所处于"android.media.SoundPool"包下,主要用于播放一些较短的声音片段,支持从程序的资源或文件系统加载。与MediaPlayer相比,SoundPool的优势在于CPU的资源占用量低、反应延迟小,并且可以加载多个音频到SoundPool中,通过资源ID来管理。另外SoundPool还支持执行设置声音的品质、音量、播放比率等参数。

  SoundPool提供一个构造函数,以下是它的完整签名:

    SoundPool(int maxStreams,int streamType,int srcQuality)

  通过上面的构造函数即可完成SoundPool的初始化,第一个参数为音频池最多支持装载多少个音频,就是音频池的大小;第二个参数指定声音的类型,在AudioManager类中以常量的形式定义,一般指定为AudioManager.STREAM_MUSIC即可;第三个参数为音频的质量,默认为0,这个参数为预留参数,现在没有实际意义,为扩展预留字段,一般传0即可。

 

  对于一个音频池,涉及到音频的加载、播放、暂停、继续、释放资源等操作,SoundPool也为我们提供了相应的方法,其底层也是用C++编写的native方法。以下介绍一些常用的SoundPool方法:

  • int load(Context context,int resId,int priority):从一个文件夹raw下装载一段音频资源,返回值为音频资源在SoundPool的ID。
  • int load(String path,int priority):从一个资源文件的路径装载一段音频资源,返回值为音频资源在SoundPool的ID。
  • final int play(int soundID,float leftVolume,float rightVolume,int priority,int loop,float rate):根据资源ID,播放一段音频资源。
  • final void pause(int streamID):根据装载资源ID,暂停音频资源的播放。
  • final void resume(int streamID):根据装载资源ID,继续播放暂停的音频资源。
  • final void stop(int streamID):根据装载资源ID,停止音频资源的播放。
  • final boolean unload(int soundID) :从音频池中卸载音频资源ID为soundID的资源。
  • final void release():释放音频池资源。

  上面方法无疑Load()和play()是最重要的,Load()具有多种重载方法,从参数名就可以看出是什么意思。这里讲解一下play()方法,soundID参数为资源ID;leftVolume和rightVolume个参数为左右声道的音量,从大到小取0.0f~1.0f之间的值;priority为音频质量,暂时没有实际意义,传0即可;loop为循环次数,0为播放一次,-1为无线循环,其他正数+1为播放次数,如传递3,循环播放4次;rate为播放速率,从大到小取0.0f~2.0f,1.0f为正常速率播放。

  在使用load()装载音频的时候需要注意,load()方法是一个异步的方法,也就是说,在播放音频的时候,很可能此段音频还没有装载到音频池中,这里可以借助SoundPool的一个装载完成的监听事件SoundPool.setOnLoadCompleteListener来保证装载完成在播放声音。SoundPool.setOnLoadCompleteListener()需要实现一个SoundPool.OnLoadCompleteListener接口,其中需要实现onLoadComplete()方法,一下是onLoadComplete()方法的完整签名:

    onLoadComplete(SoundPool soundPool, int sampleId, int status)

  • soundPool:当前触发事件的声音池。
  • sampleId:当前装载完成的音频资源在音频池中的ID。
  • status:状态码,展示没有意义,为预留参数,会传递0。

 

使用SoundPool示例

  上面已经介绍了SoundPool的使用所涉及到的内容,下面通过一个简单的示例来演示一下SoundPool的使用,播放的音频资源都是我从其他app中拷贝出来的,没有实际意义。示例中的注释写的比较全,这里不再累述了。

复制代码
 1 package cn.bgxt.soundpooldemo;
 2 
 3 import java.util.HashMap;
 4 import java.util.Map;
 5 
 6 import android.media.AudioManager;
 7 import android.media.SoundPool;
 8 import android.media.SoundPool.OnLoadCompleteListener;
 9 import android.os.Bundle;
10 import android.app.Activity;
11 import android.util.Log;
12 import android.view.View;
13 import android.view.View.OnClickListener;
14 import android.widget.Button;
15 import android.widget.Toast;
16 
17 public class MainActivity extends Activity {
18     private Button btn_newqqmsg, btn_newweibontf, btn_newweibotoast;
19     private SoundPool pool;
20     private Map<String, Integer> poolMap;
21 
22     @Override
23     protected void onCreate(Bundle savedInstanceState) {
24         super.onCreate(savedInstanceState);
25         setContentView(R.layout.activity_main);
26         btn_newqqmsg = (Button) findViewById(R.id.btn_newqqmsg);
27         btn_newweibontf = (Button) findViewById(R.id.btn_newweibontf);
28         btn_newweibotoast = (Button) findViewById(R.id.btn_newweibotoast);
29 
30         poolMap = new HashMap<String, Integer>();
31         // 实例化SoundPool,大小为3
32         pool = new SoundPool(3, AudioManager.STREAM_MUSIC, 0);
33         // 装载音频进音频池,并且把ID记录在Map中
34         poolMap.put("newqqmsg", pool.load(this, R.raw.qqmsg, 1));
35         poolMap.put("newweibontf", pool.load(this, R.raw.notificationsound, 1));
36         poolMap.put("newweibotoast", pool.load(this, R.raw.newblogtoast, 1));
37 
38         pool.setOnLoadCompleteListener(new OnLoadCompleteListener() {
39 
40             @Override
41             public void onLoadComplete(SoundPool soundPool, int sampleId,
42                     int status) {
43                 // 每次装载完成均会回调
44                 Log.i("main", "音频池资源id为:" + sampleId + "的资源装载完成");
45                 // 当前装载完成ID为map的最大值,即为最后一次装载完成
46                 if (sampleId == poolMap.size()) {
47                     Toast.makeText(MainActivity.this, "加载声音池完成!",
48                             Toast.LENGTH_SHORT).show();
49                     btn_newqqmsg.setOnClickListener(click);
50                     btn_newweibontf.setOnClickListener(click);
51                     btn_newweibotoast.setOnClickListener(click);
52                     // 进入应用播放四次声音
53                     pool.play(poolMap.get("newweibotoast"), 1.0f, 1.0f, 0, 3,
54                             1.0f);
55                 }
56             }
57         });
58     }
59 
60     private View.OnClickListener click = new OnClickListener() {
61 
62         @Override
63         public void onClick(View v) {
64 
65             switch (v.getId()) {
66             case R.id.btn_newqqmsg:
67                 if (pool != null) {
68                     pool.play(poolMap.get("newqqmsg"), 1.0f, 1.0f, 0, 0, 1.0f);
69                 }
70                 break;
71             case R.id.btn_newweibontf:
72                 if (pool != null) {
73                     pool.play(poolMap.get("newweibontf"), 1.0f, 1.0f, 0, 0,
74                             1.0f);
75                 }
76                 break;
77             case R.id.btn_newweibotoast:
78                 if (pool != null) {
79                     pool.play(poolMap.get("newweibotoast"), 1.0f, 1.0f, 0, 0,
80                             1.0f);
81                 }
82                 break;
83             default:
84                 break;
85             }
86         }
87     };
88 
89     @Override
90     protected void onDestroy() {
91         // 销毁的时候释放SoundPool资源
92         if (pool != null) {
93             pool.release();
94             pool = null;
95         }
96         super.onDestroy();
97     }
98 }
复制代码

  效果展示:

 

SoundPool使用的注意事项

  因为SoundPool的一些设计上的BUG,从固件版本1.0开始就有些没有修复的,以后应该会慢慢修复。这里简单提一下:

  1. 虽然SoundPool可以装载多个音频资源,但是最大只能申请1MB的内存空间,这就意味着只能用使用它播放一些很短的声音片段,而不是用它来播放歌曲或者做游戏背景音乐。
  2. SoundPool提供的pause()、resume()、stop()最好不要轻易使用,因为它有时候会使程序莫名其妙的终止,如果使用,最好做大量的测试。而且有时候也不会立即终止播放声音,而是会等缓冲区的音频数据播放完才会停止。
  3. 虽然SoundPool比MediaPlayer的效率好,但也不是绝对不存在延迟的问题,尤其在那些性能不太好的手机中,SoundPool的延迟问题会更严重,但是现在一般的手机配置,那一点的延迟还是可以接受的。

 

  源码下载

 

总结

  本篇博客介绍了SoundPool的使用,虽然SoundPool还有一些不足的地方,当时对于应用中一些简短的特效音,如按键音、短消息音,或者一些游戏中密集的声音,如射击的枪声,爆破的声音等。都是可以使用SoundPool的,效率会比使用MediaPlayer要高的多。



本文转自承香墨影博客园博客,原文链接:http://www.cnblogs.com/plokmju/p/android_SoundPool.html,如需转载请自行联系原作者


相关文章
|
语音技术 Android开发
Android使用SoundPool播放语音,并实现按顺序延时播放
Android使用SoundPool播放语音,并实现按顺序延时播放
|
Android开发
Android SoundPool
 SoundPool SoundPool 主要用于播放一些较短的声音片段,与 MediaPlayer 相比,  SoundPool 的优势在于 CPU 资源占用量低和反应延迟小。另外,  SoundPool 还支持自行设置声音的品质、音量、 播放比率等参数。 SoundPool(int maxStreams, int streamType, int srcQuality
1649 0
|
6天前
|
搜索推荐 Android开发 开发者
探索安卓开发中的自定义视图:打造个性化UI组件
【10月更文挑战第39天】在安卓开发的世界中,自定义视图是实现独特界面设计的关键。本文将引导你理解自定义视图的概念、创建流程,以及如何通过它们增强应用的用户体验。我们将从基础出发,逐步深入,最终让你能够自信地设计和实现专属的UI组件。
|
8天前
|
Android开发 Swift iOS开发
探索安卓与iOS开发的差异和挑战
【10月更文挑战第37天】在移动应用开发的广阔舞台上,安卓和iOS这两大操作系统扮演着主角。它们各自拥有独特的特性、优势以及面临的开发挑战。本文将深入探讨这两个平台在开发过程中的主要差异,从编程语言到用户界面设计,再到市场分布的不同影响,旨在为开发者提供一个全面的视角,帮助他们更好地理解并应对在不同平台上进行应用开发时可能遇到的难题和机遇。
|
10天前
|
XML 存储 Java
探索安卓开发之旅:从新手到专家
【10月更文挑战第35天】在数字化时代,安卓应用的开发成为了一个热门话题。本文旨在通过浅显易懂的语言,带领初学者了解安卓开发的基础知识,同时为有一定经验的开发者提供进阶技巧。我们将一起探讨如何从零开始构建第一个安卓应用,并逐步深入到性能优化和高级功能的实现。无论你是编程新手还是希望提升技能的开发者,这篇文章都将为你提供有价值的指导和灵感。
|
8天前
|
存储 API 开发工具
探索安卓开发:从基础到进阶
【10月更文挑战第37天】在这篇文章中,我们将一起探索安卓开发的奥秘。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的信息和建议。我们将从安卓开发的基础开始,逐步深入到更复杂的主题,如自定义组件、性能优化等。最后,我们将通过一个代码示例来展示如何实现一个简单的安卓应用。让我们一起开始吧!
|
9天前
|
存储 XML JSON
探索安卓开发:从新手到专家的旅程
【10月更文挑战第36天】在这篇文章中,我们将一起踏上一段激动人心的旅程,从零基础开始,逐步深入安卓开发的奥秘。无论你是编程新手,还是希望扩展技能的老手,这里都有适合你的知识宝藏等待发掘。通过实际的代码示例和深入浅出的解释,我们将解锁安卓开发的关键技能,让你能够构建自己的应用程序,甚至贡献于开源社区。准备好了吗?让我们开始吧!
22 2