Pro Android学习笔记(一二八):Media Frameworks(3):用SoundPool的音频播放

文章转载只能用于非商业性质,且不能带有虚拟货币、积分、注册等附加条件。转载须注明出处http://blog.csdn.net/flowingflying/以及作者@恺风Wei

MediaPlayer在一个时间只能处理一个音频或视频文件,如果我们需要同时播放多个音频文件,可以创建多个MediaPlayer。如果我们有若干个的音频需要播放,还可以使用SoundPool类,SoundPool类使用了MediaPlayer,但我们不需要访问MediaPlayer API,而是简洁使用SoundPool API。

SoundPool只能处理本地媒体资源。SoundPool为了提高播放性能,使用了内存,使用总量限制为1MB。放入内存多少,和比特率、采样频率、channel数(单声道、双声道,杜比的5.1声道)以及音频的长度有关,如果太大,可能会导致加载失败。SoundPool适合短小但经常反复播放的若干音频。

小例子

我们有5个音频资源,4个位于res/raw,1个位于assets/下面,这些都是时间很短的音频文件。crickets.mp3作为背景音乐不断地循环放松,而其他的4个音乐分别隔某个时间间隔(例如5秒)播放一次。

UI很简单,上面是一个ToggleButton,在暂停和播放之间切换,下面是debug信息的显示。

代码分析

我们重点关注代码如何具体利用SoundPool来实现音频播放、循环播放、暂停、继续播放的控制。

public class SoundPoolActivity extends Activity implements SoundPool.OnLoadCompleteListener{ 
    private SoundPool soundpool = null;
    private AudioManager audioManager = null;     
    private int sid_background,sid_roar,sid_chimp,sid_rooster,sid_bark;
    
    … …
    
    @Override
    protected void onResume() { 
        super.onResume();
        /* 【1】创建我们的SoundPool对象:第一个参数是SoundPool同时共同播放多上个音乐,注意是最大的同时播放数,而不是由多少音频资源。第二参数是音频类型,一般为STREAM_MUSIC;第三个参数目前没有使用,reference建议为0 。*/
        soundpool = new SoundPool(5, AudioManager.STREAM_MUSIC, 0);  
        /* 【3.pre】将资源load()到SoundPool后,才可以进行播放,因此,需要完成load的回调函数。*/
        soundpool.setOnLoadCompleteListener(this);

        // 用于获取当前的音量,后面有用
        audioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
        /* 【2】SoundPool load入音频资源,音频流会从文件中解码,放入内存,这提高了SoundPool的性能。我们给出了用资源和fd方式。对于SD卡,可以用soundpool.load("/mnt/sdcard/abc.mp3",1); load()参数的最后一位是PRIORITY,目前没有真正使用,reference建议设置为1,以便兼容未来版本。*/
        sid_background = soundpool.load(this, R.raw.crickets, 1);  
        sid_roar = soundpool.load(this, R.raw.roar, 1);
        sid_rooster = soundpool.load(this, R.raw.rooster, 1);
        sid_chimp = soundpool.load(this, R.raw.chimp, 1);
       
        try{
            AssetFileDescriptor afd = getAssets().openFd("dogbark.mp3");
            sid_bark = soundpool.load(afd.getFileDescriptor(), 0, afd.getLength(), SOUNDPOOL_LOAD_PRIORITY);
            afd.close();
        }catch(Exception e){ 
            e.printStackTrace();
        }
       
        debug(… …);         
    }

    @Override
    protected void onPause() { 
        soundpool.release(); //停止并释放资源,而停止某个媒体流的播放可以是用stop(sid);SoundPool会释放该媒体流的资源。
        soundpool = null;
        super.onPause();
    }
   
    public void doClick(View v){
        debug … … 
        if(((ToggleButton)v).isChecked()){
            soundpool.autoResume(); //恢复停止播放的音频流,在本例,在某些情况下,不能重新播放背景音,这是因为我们设置了最大同时播放数为5个,假设5个音频同时播放时,我们按了暂停,resume()是刚好又轮到某个音频流再次播放,这时同时播放数会超过设置的最大数,SoundPool会让出最早的音频流,腾出位置给新的声音。
        }else{
            soundpool.autoPause();  //会暂停当前播放的音频流,在本例,背景音频流会播放,但是对于通过queueSound()的未来播放不会被终止。
        }
    }

    @Override //load完后,进行播放,
    public void onLoadComplete(SoundPool soundPool, int sampleId, int status) { 
        debug("sid " + sampleId + " status=" + status);
       
        if(status != 0)
            return; 
        // 获取当前音量,音量范围:0-1.0
        final float currentVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC)
                / (float)audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
       
        // 如果是背景声音,则不断循环播放,如果是其他,则已某个间隔时间播放
        /* play() 第一个参数是音频的id;第二和第三个分别是左右音量;第四个参数是音频流的优先级别,0是最低的基本;第5参数标识是否循环播放,0标识不循环,-1表示循环;第6个参数是播放速率,1.0标识按正常速率播放,有效范围是0.5-2.0。如果成功返回音频流的Id,失败返回0  */ 
        if(soundPool.play(sid_background, currentVolume, currentVolume, 1, -1, 1.0f) == 0){ 
            debug("Failed to start sound " + sampleId);           
        }else if(sampleId == sid_chimp){
            queueSound(sampleId,5000,currentVolume); //延后定期发送
        }else if(sampleId == sid_rooster){
            queueSound(sampleId, 17000, currentVolume);
        }else if(sampleId == sid_roar){
            queueSound(sampleId, 12000, currentVolume);
        }else if(sampleId == sid_bark){
            queueSound(sampleId, 7000, currentVolume);
        }
       
    }
    //利用handler实现固定时间间隔的播放,不同的音频流的间隔时间均不同,我们可以听到1~5个音频的混音效果。
    private void queueSound(final int sid , final long delay , final float volume){
        new Handler().postDelayed(new Runnable() {             
            @Override
            public void run() { 
                debug("sid " + sid + " queueSound() run in "  + Thread.currentThread().getName());
                if(soundpool == null) //如果已经onPause(),即soundpool==null,将停止播放及未来播放
                    return; 

                if(soundpool.play(sid, volume, volume, 1, 0, 1.0f) == 0){
                        debug("Fail to start sound " + sid); 
                 } 
                //每隔delay的时间,重复播放
                queueSound(sid, delay, volume);
            }
        }, delay);
    }

    private void debug(String info){
       … …    
    }

}

小例子代码在:Pro Android学习:media framworks小例子

相关链接:我的Android开发相关文章

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值