SoundPool与mediaPlayer的使用

本文探讨了在游戏开发中如何有效利用SoundPool和MediaPlayer进行音频播放,包括资源占用、内存限制、播放控制及音频格式选择等问题。重点介绍了如何避免SoundPool的常见陷阱,如立即播放、循环播放、音量调整等,并提供了实际代码示例。
摘要由CSDN通过智能技术生成
MediaPlayer来播放音频文件:
资源占用量较高、延迟时间较长、不支持多个音频同时播放等。
SoundPool来播放音乐:
1.SoundPool最大只能申请1M的内存空间,这就意味着我们只能使用一些很短的声音片段,而不是用它来播放歌曲或者游戏背景音乐(背景音乐可以考虑使用JetPlayer来播放)。
2.SoundPool提供了pause和stop方法,但这些方法建议最好不要轻易使用,因为有些时候它们可能会使你的程序莫名其妙的终止。还有些朋友反映它们不会立即中止播放声音,而是把缓冲区里的数据播放完才会停下来,也许会多播放一秒钟。
3.音频格式建议使用OGG格式。使用WAV格式的音频文件存放游戏音效,经过反复测试,在音效播放间隔较短的情况下会出现异常关闭的情况(有说法是SoundPool目前只对16bit的WAV文件有较好的支持)。后来将文件转成OGG格式,问题得到了解决。
4.在使用SoundPool播放音频的时候,如果在初始化中就调用播放函数进行播放音乐那么根本没有声音,不是因为没有执行,而是SoundPool需要一准备时间!囧。当然这个准备时间也很短,不会影响使用,只是程序一运行就播放会没有声音罢了。


对此我们对游戏开发中到底需要用什么来做进行了分析,总结就是SoundPool适合做特效声,其实播放背景音乐我感觉还是用MediaPlayer比较好。

注意:
这里要强调一下,调整音频是用这个音频管理器调用setStreamVolume()的方式去调整,而不是MediaPlayer.setVolue(intLeftVolume,int RightVolume);这个方法的两个参数也是调正左右声道而不是调节声音大小。

package com.example.zhangying.simplemusicplayer;
 
import android.content.Context;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.SoundPool;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import java.util.HashMap;

/**
 * 下面对以上进行总结:
 *
 * 一个SoundPool可以:
 * 1.管理多个音频资源,通过load()函数,成功则返回非0的soundID;
 * 2.同时播放多个音频,通过play()函数,成功则返回非0的streamID;
 * 3.pause()、resume()和stop()等操作是针对streamID(播放流)的;
 * 4.当设置为无限循环时,需要手动调用stop()来终止播放;
 * 5.播放流的优先级(play()中的priority参数),只在同时播放数超过设定的最大数时起作用;
 * 6.程序中不用考虑(play触发的)播放流的生命周期,无效的soundID/streamID不会导致程序错误。
 */
public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Button button1;//使用MediaPlayer播放声音
    private Button button2;//暂停MediaPlayer声音
    private Button button3;//使用SoundPool播放声音
    private Button button4;//暂停SoundPool声音
    private TextView textView;//显示文本信息
    private MediaPlayer mediaPlayer;//
    /**
     * SoundPool初始化的过程是异步的,也就是说对SoundPool初始化时系统会自动启动一个后台线程来完成初始化工作。
     * 因此,并不影响前台其他程序的运行,但也带来了一个问题,调用初始化操作后不能立即播放,需要等待一下,否则 可能会出错。
     * SoundPool可以同时播放多个音频文件,但MediaPlayer同一时间却只能播放一个
     */
    private SoundPool soundPool;
    private HashMap soundPoolMap;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initSounds();//初始化声音
        setContentView(R.layout.activity_main);
        initView();
        initListener();
    }

    /**
     * 初始化声音方法
     */
    private void initSounds() {
        /**
         * 两个参数:1.上下文。2.音频资源的id(R.raw.)
         *如果是播放指定sd卡上的音乐的话使用: mediaPlayer.setDataSource();
         * 如果是应用中自带的音乐(如游戏中的音效),就不是sdcard中的音乐了,一般情况下会将音频资源存放在应用目录下的''res\raw\'下,并通过create()方法返回一个MediaPlayer对象。
         */
        mediaPlayer = MediaPlayer.create(this, R.raw.backsound);//初始化MediaPlayer

        /**
         *public SoundPool(int maxStream, int streamType, int srcQuality)
         *maxStream —— 同时播放的流的最大数量
         *streamType —— 流的类型,一般为STREAM_MUSIC(具体在AudioManager类中列出)
         *srcQuality —— 采样率转化质量,当前无效果,使用0作为默认值,它表示音质,它也可以设置为100
         */
        soundPool = new SoundPool(4, AudioManager.STREAM_MUSIC, 0);//
        soundPoolMap = new HashMap();
        /**
         * API中指出,其中第三个参数priority参数目前没有效果,建议设置为1。
         * soundPool.load(this, R.raw.dingdong, 1);加载音频资源
         * 一个SoundPool能同时管理多个音频,所以可以通过多次调用load函数来记载,如果记载成功将返回一个非0的soundID ,用于播放时指定特定的音频。
         * 需要注意的是,
         *流的加载过程是一个将音频解压为原始16位PCM数据的过程,由一个后台线程来进行处理异步,所以初始化后不能立即播放,需要等待一点时间。
         *
         */
        soundPoolMap.put(1, soundPool.load(this, R.raw.dingdong, 1));
    }

    private void initListener() {
        button1.setOnClickListener(this);
        button2.setOnClickListener(this);
        button3.setOnClickListener(this);
        button4.setOnClickListener(this);
    }

    private void initView() {
        textView = (TextView) findViewById(R.id.textView);
        button1 = (Button) findViewById(R.id.button1);
        button2 = (Button) findViewById(R.id.button2);
        button3 = (Button) findViewById(R.id.button3);
        button4 = (Button) findViewById(R.id.button4);
    }


    /**
     * 使用soundPool播放音乐的方法
     *  leftVolume left volume value (range = 0.0 to 1.0)
     *  rightVolume right volume value (range = 0.0 to 1.0)
     */
    public void playSound(int sound, int loop) {
        AudioManager mgr = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
        float streamVolume = mgr.getStreamVolume(AudioManager.STREAM_MUSIC);//当前音量
        float streamMaxVolume = mgr.getStreamMaxVolume(AudioManager.STREAM_MUSIC);//最大音量(获得当前手机最大铃声)
        float volume = streamVolume / streamMaxVolume;
        /**
         * final int play(int soundID, float leftVolume, float rightVolume, int priority, int loop, float rate)
         *播放指定音频的音效,并返回一个streamID 。
         *priority —— 流的优先级,值越大优先级高,影响当同时播放数量超出了最大支持数时SoundPool对该流的处理;
         *loop —— 循环播放的次数,0为值播放一次,-1为无限循环,其他值为播放loop+1次(例如,3为一共播放4次).
         *rate —— 播放的速率,范围0.5-2.0(0.5为一半速率,1.0为正常速率,2.0为两倍速率)
         * volume设置为1的话应该是最大的音量了。
         */
        soundPool.play(soundPoolMap.get(sound), volume, volume, 1, loop, 1f);//播放声音
    }

    @Override
    public void onClick(View v) {

        if (v == button1) {
            textView.setText("使用MediaPlayer播放声音");
            if (!mediaPlayer.isPlaying()) {
                mediaPlayer.start();//播放音乐
            }
        } else if (v == button2) {
            textView.setText("暂停MediaPlayer声音");
            if (mediaPlayer.isPlaying()) {
                mediaPlayer.pause();
            }
        } else if (v == button3) {//点击了使用SoundPool播放声音按钮
            textView.setText("点击了使用SoundPool播放声音按钮");
            this.playSound(1, 0);//使用SoundPool播放声音按钮

        } else if (v == button4) {
            textView.setText("点击了暂停SoundPool声音按钮");
            soundPool.pause(1);//暂停SoundPool声音
        }
    }
}

布局文件:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="没有任何声音" />

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="使用MediaPlayer播放声音" />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="暂停MediaPlayer声音" />

    <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="使用SoundPool播放声音"/>

    <Button
        android:id="@+id/button4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="暂停SoundPool声音"/>

</LinearLayout>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值