Unity在安卓的声音优化

Unity在安卓端的声音播放会有些延迟,所以需要用到Android原生态的声音播放的接口,那就是SoundPool这个类,只不过使用这个类的注意事项挺多的,第一就是不能加载转换成PCM流后超过1M的声音文件(安卓系统版本比较低的话会报堆溢出的,而且会有明显的卡顿感,高版本不会报这个错误加载速度正常,估计是高版本的SoundPool有所修改,判断了超过1M的就不去加载了),第二就算PCM流在1M以内,文件时间过长的话,SoundPool还是会截取前10秒左右播放,也就是说放不了长音乐的那种。在Unity里可以查看转换成PCM流文件的大小,如下图:

网上有一个Unity的音频插件,这个音频插件也是使用SoundPool,但是用起来比较复杂,因为一个声音文件对应一个声音ID,一个声音ID播放的时候会返回不同的流ID,这样要改变这个声音的属性(音量,速率等等)就需要用到这个流ID,也就是说一个声音可以同时播放的,但是返回的流ID播放结束以后就没有用了,加上SoundPool适合播放那种短小的音效,所以准备继承这个SoundPool这个类,写一个比较好用的Unity的音效插件,大概思路就是一个声音ID映射上一个流ID,也就是一个音效不可能同时在播放的(比如之前声音1还在播放,又需要播放声音1,这样直接把之前那个声音停掉,重新播放这个音效),虽然这个算是一个限制SoundPool同时可以在线播放同一个音效,但是作为音效确实没有必要有这个功能,具体代码如下:

package com.daveant.nativeaudio_sdk;

import android.app.Activity;
import android.content.res.AssetFileDescriptor;
import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Vibrator;
import android.util.Log;
import java.io.IOException;
import java.util.HashMap;

public class SoundPlayer extends SoundPool{

    private class soundInfo
    {
        public float leftVolume;
        public float rightVolume;
        public int priority;
        public int loop;
        public float rate;
        public soundInfo(float leftVolume,float rightVolume,int priority,int loop,float rate)
        {
            this.leftVolume = leftVolume;
            this.rightVolume = rightVolume;
            this.priority = priority;
            this.loop = loop;
            this.rate = rate;
        }
    }
    //private List
    private String TAG = "DAudio";
    private Activity activity = null;//当前上下文
    private static Integer vibratorId = 0;
    private HashMap<Integer,Vibrator> vibratorsSet = new HashMap<Integer,Vibrator>();
    private HashMap<Integer,Integer> soundsSet = new HashMap<Integer,Integer>();
    private HashMap<Integer,soundInfo> soundsInfo = new HashMap<Integer,soundInfo>();
    public SoundPlayer(int maxStreams, Activity activity) {
        super(maxStreams, AudioManager.STREAM_MUSIC, 0);
        this.activity = activity;
        setOnLoadCompleteListener(new OnLoadCompleteListener() {
            @Override
            public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
                soundsSet.put(sampleId,null);
                soundsInfo.put(sampleId,new soundInfo(1,1,1,0,1));
            }
        });
    }

    public void SetVolume(final int soundId,final float leftVolume,final float rightVolume)
    {
        Integer opSoundId = soundsSet.get(soundId);
        Log.w(TAG, "SetVolume:"+TAG);
        if(opSoundId != null) {
            setVolume(opSoundId, leftVolume, rightVolume);
            soundInfo sInfo = soundsInfo.get(soundId);
            sInfo.leftVolume = leftVolume;
            sInfo.rightVolume = rightVolume;
            soundsInfo.remove(soundId);
            soundsInfo.put(soundId,sInfo);
        }
    }

    public void SetRate(final int soundId,final float rate)
    {
        Integer opSoundId = soundsSet.get(soundId);
        Log.w(TAG, "SetRate:"+TAG);
        if(opSoundId != null) {
            setRate(opSoundId, rate);
            soundInfo sInfo = soundsInfo.get(soundId);
            sInfo.rate = rate;
            soundsInfo.remove(soundId);
            soundsInfo.put(soundId,sInfo);
        }
    }

    public void SetLoop(final int soundId,final int loop)
    {
        Integer opSoundId = soundsSet.get(soundId);
        Log.w(TAG, "SetLoop:"+TAG);
        if(opSoundId != null) {
            setLoop(opSoundId, loop);
            soundInfo sInfo = soundsInfo.get(soundId);
            sInfo.loop = loop;
            soundsInfo.remove(soundId);
            soundsInfo.put(soundId,sInfo);
        }
    }

    public void Play(final int soundId,final float leftVolume,final float rightVolume,
                     final int priority,final int loop,final float rate){
        if(soundsSet.containsKey(soundId) == false || soundId==0){
            Log.e(TAG, "找不到这个声音ID:"+TAG);
            return;
        }
        activity.runOnUiThread(new Runnable(){
            @Override
            public void run() {
                Log.w(TAG, "播放的声音ID:" + soundId);
                Integer opSoundId = soundsSet.get(soundId);
                if(opSoundId != null)
                    stop(opSoundId);
                soundInfo sInfo = soundsInfo.get(soundId);
                sInfo.leftVolume = leftVolume;
                sInfo.rightVolume = rightVolume;
                sInfo.priority = priority;
                sInfo.loop = loop;
                sInfo.rate = rate;
                soundsInfo.remove(soundId);
                soundsSet.remove(soundId);
                opSoundId = play(soundId,leftVolume,rightVolume,priority,loop,rate);
                soundsSet.put(soundId,opSoundId);
                soundsInfo.put(soundId,sInfo);
            }
        });
    }

    public void Play(final int soundId){
        if(soundsSet.containsKey(soundId) == false || soundId==0){
            Log.e(TAG, "找不到这个声音ID:" + soundId);
            return;
        }
        activity.runOnUiThread(new Runnable(){
            @Override
            public void run() {
                Log.w(TAG, "播放的声音ID:" + soundId);
                Integer opSoundId = soundsSet.get(soundId);
                if(opSoundId != null)
                    stop(opSoundId);
                soundsSet.remove(soundId);
                soundInfo sInfo = soundsInfo.get(soundId);
                opSoundId = play(soundId,sInfo.leftVolume,sInfo.rightVolume, sInfo.priority,sInfo.loop,sInfo.rate);
                soundsSet.put(soundId,opSoundId);
            }
        });
    }

    public int loadByAsset(String soundName){
        AssetFileDescriptor afd = null;
        try {
            afd = activity.getAssets().openFd(soundName);
        } catch (IOException e) {
            Log.e(TAG, "加载路径资源异常");
            return -1;
        }
        int soundId = load(afd, 1);
        return soundId;
    }

    public void unloadSound(int soundId){
        if(unload(soundId)) {
            Log.w(TAG, "卸载成功:" + soundId);
            soundsSet.remove(soundId);
            soundsInfo.remove(soundId);
        }
    }

    public void Realease()
    {
        release();
        soundsSet.clear();
        soundsInfo.clear();
        vibratorsSet.clear();
    }

    public void Pause(int soundId)
    {
        Integer opSoundId = soundsSet.get(soundId);
        Log.w(TAG, "Pause:" + opSoundId);
        if(opSoundId != null)
            pause(opSoundId);
    }

    public void Resume(int soundId)
    {
        Integer opSoundId = soundsSet.get(soundId);
        Log.w(TAG, "Resume:" + opSoundId);
        if(opSoundId != null)
            resume(opSoundId);
    }

    public void Stop(int soundId)
    {
        Integer opSoundId = soundsSet.get(soundId);
        Log.w(TAG, "Stop:" + opSoundId);
        if(opSoundId != null)
            stop(opSoundId);
    }

    public void SetVibrator(int time) {
        Vibrator vibrator = (Vibrator)activity.getSystemService(activity.VIBRATOR_SERVICE);
        vibrator.vibrate(time);
    }

    public int SetVibrators(long[] time,int loop)
    {
        Vibrator vibrator = (Vibrator)activity.getSystemService(activity.VIBRATOR_SERVICE);
        vibrator.vibrate(time,loop);
        vibratorsSet.put(vibratorId, vibrator);
        vibratorId ++;
        return vibratorId-1;
    }

    public void CancelVibrators(int vibratorId)
    {
        if(vibratorsSet.containsKey(vibratorId)) {
            vibratorsSet.get(vibratorId).cancel();
            vibratorsSet.remove(vibratorId);
        }
        else
            Log.e(TAG, "CancelVibrators找不到这个ID");
    }
}

具体Unity的例子工程在以下这个链接:

https://download.csdn.net/download/m0_37920739/11096820

发布了26 篇原创文章 · 获赞 3 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/m0_37920739/article/details/88988842