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 vibratorsSet = new HashMap();
private HashMap soundsSet = new HashMap();
private HashMap soundsInfo = new HashMap();
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