SoundPool类简介与适用场合

http://www.devdiv.com/forum.php?mod=viewthread&tid=130200

一、SoundPool类简介与适用场合

        1)SoundPool简介

        SoundPool类是Android用于管理和播放应用程序的音频资源的类。一个SoundPool对象可以看作是一个可以从APK中导入资源或者从文件系统中载入文件的样本集合。它利用MediaPlayer服务为音频解码为一个原始16位PCM流。这个特性使得应用程序可以进行流压缩,而无须忍受在播放音频时解压所带来的CPU负载和时延。

        此外对于低延迟播放,SoundPool还可以管理多个音频流。当SoundPool对象构造时,maxStreams参数的设置表示的是在单一的SoundPool中,同一时间所能播放流的最大数量。利用SoundPool可以跟踪活跃的流的数量。如果其数量超过流的最大数目,SoundPool会基于优先级自动停止先前播放的流。限制流的最大数目,有助于减轻CPU的负荷,减少音频混合对视觉和UI性能的影响。

        声音可以通过设置一个非零的循环价值循环。如果值为-1将导致声音永远循环。在这种情况下,应用程序必须明确地调用stop()函数,以停止声音。其他非零值将导致声音按指定数量的时间重复。

        在SoundPool中,播放速率也可以改变。1.0的播放率可以使声音按照其原始频率(如果必要的话,将重新采样硬件输出频率)。而2.0的播放速率,可以使声音按照其原始频率的两倍播放。如果为0.5的播放率,则播放速率是原始频率的一半。播放速率的取值范围是0.5至2.0。

        优先级的运行从低到高排列的。当用户调用play()函数时,如果活跃的流数目大于规定的maxStreams参数,流分配器将会结束优先级最低的流。如果有多条流都处于最低优先级,优先级系统将会选择关闭最老的流。

        一旦声音被成功加载和播放,应用程序可以调用SoundPool.play()来触发的声音。播放过程中的流可又被暂停或继续播放。应用程序还可以通过调整播放率改变音高。

        注意,由于资源的限制,流可以被停止,streamID是一个对特定流实例的引用。如果流被停止并且允许更高优先级的流播放,流就不再有效了。然而,应用程序允许调用没有错误的streamID方法。因为如果应用程序不需要关心流的生命周期,这可能有助于简化程序逻辑。

        2)适用场合

        SoundPool在载入声音文件过程中,使用了单独的线程,不会对视觉和UI性能产生影响。但是由于SoundPool对载入声音文件大小有所限制,这就导致了如果SoundPool没有载入完成,而不能安全调用play方法。好在Android SDK提供了一个SoundPool.OnLoadCompleteListener类来帮助我们了解声音文件是否载入完成,用户只须重载 onLoadComplete(SoundPool soundPool, int sampleId, int status) 方法即可实现。

与MediaPlayer相比,MediaPlayer存在着资源占用量较高、延迟时间较长、不支持多个音频同时播放等缺点,但SoundPool本身由于内存资源申请有严格限制,所以在开发过程中,笔者建议尽量用SoundPool来播放一些较短的声音片段或者音效。  

二、使用SoundPool播放声音

        1)SoundPool对象初始化

        我们可以调用SoundPool的构造函数public SoundPool (int maxStreams, int streamType, int srcQuality)来初始化SoundPool对象。

        其中参数说明如下:

        maxStreams:指定支持多少个声音,SoundPool对象中允许同时存在的最大流的数量。
        streamType:制定声音类型,流类型可以分为STREAM_VOICE_CALL, STREAM_SYSTEM, STREAM_RING,STREAM_MUSIC 和 STREAM_ALARM四种类型。在AudioManager中定义。
        srcQuality:指定声音品质(采样率变换质量)。目前没有用到,可以设为0。

        2)载入声音资源

        调用load方法载入声音资源,SoundPool提供了4个Load方法,比较常用的是以下两个:

        Public int load(Context context, int resId, int priority):从resId所对应的资源加载声音。
        Public int load(String path, int priority):从path对应的文件中加载声音。

        上面两个方法中都有一个priority参数,该参数目前还没有任何作用,Android建议将该参数设置为1,保持和未来的兼容性。

        同时,这两个方法加载声音之后,都会返回该声音的ID,以后程序就可以通过该声音的ID来播放指定声音。

        3)播放控制

        要播放SoundPool中的声音,须调用int 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。

        4)释放资源

        播放结束,我们可以调用release()方法释放所有SoundPool对象占据的内存和资源。

        5)实例分析

        下面通过一个简单的Demo来分析一下SoundPool的用法,布局文件非常简单,不再给出代码。

        MainActivity.java的内容如下:

view source
print ?
01 package com.devdiv.test.soundpool_test;
02  
03 import java.util.HashMap;
04  
05 import android.app.Activity;
06 import android.media.AudioManager;
07 import android.media.SoundPool;
08 import android.os.Bundle;
09 import android.view.View;
10 import android.view.View.OnClickListener;
11 import android.widget.Button;
12  
13 public class MainActivity extends Activity implements OnClickListener {
14        
15         Button bombButton;
16         Button shotButton;
17         Button arrowButton;
18         Button allButton;
19        
20         SoundPool mSoundPool = null;
21        
22         HashMap<Integer, Integer> soundMap = new HashMap<Integer, Integer>();
23  
24     @Override
25     public void onCreate(Bundle savedInstanceState) {
26         super.onCreate(savedInstanceState);
27         setContentView(R.layout.activity_main);
28        
29         bombButton = (Button) findViewById(R.id.bomb);
30         shotButton = (Button) findViewById(R.id.shot);
31         arrowButton = (Button) findViewById(R.id.arrow);
32         allButton = (Button) findViewById(R.id.all);
33        
34                 //设置最多可容纳10个音频流,音频的品质为5
35         mSoundPool = new SoundPool(10, AudioManager.STREAM_SYSTEM, 5);
36                 //load方法加载指定音频文件,并返回所加载的音频ID。此处使用HashMap来管理这些音频流
37                 soundMap.put(1 , mSoundPool.load(this, R.raw.bomb , 1));
38                 soundMap.put(2 , mSoundPool.load(this, R.raw.shot , 1));
39                 soundMap.put(3 , mSoundPool.load(this, R.raw.arrow , 1));
40                
41                 bombButton.setOnClickListener(this);
42                 shotButton.setOnClickListener(this);
43                 arrowButton.setOnClickListener(this);
44                 allButton.setOnClickListener(this);
45     }
46    
47         //重写OnClickListener监听器接口的方法
48         @Override
49         public void onClick(View v) {
50                 // TODO Auto-generated method stub
51                 //判断哪个按钮被单击
52                 switch (v.getId()) {
53                 case R.id.bomb:
54                         mSoundPool.play(soundMap.get(1), 1, 1, 0, 0, 1);
55                         break;
56                 case R.id.shot:
57                         mSoundPool.play(soundMap.get(2), 1, 1, 0, 0, 1);
58                         break;
59                 case R.id.arrow:
60                         mSoundPool.play(soundMap.get(3), 1, 1, 0, 0, 1);
61                         break;
62                 case R.id.all:
63                         mSoundPool.play(soundMap.get(1), 1, 1, 0, 0, 1);
64                         mSoundPool.play(soundMap.get(2), 1, 1, 0, 0, 1);
65                         mSoundPool.play(soundMap.get(3), 1, 1, 0, 0, 1);
66                 default:
67                         break;
68                 }
69         }
70  
71 }

        通常,为了更好地管理SoundPool所加载的每个声音的ID,程序一般会使用一个HashMap<Integer,Integer>对象来管理声音。按照上面的步骤初始化,载入声音,并且把按钮绑定监听器,点击按钮播放相应声音。

你可能感兴趣的:(SoundPool类简介与适用场合)