网上演练贵港万达广场(人员密集)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

278 lines
6.8 KiB

using UnityEngine;
using System;
using System.IO;
using AX.AudioSystem;
[RequireComponent(typeof(AudioSource))]
public class AudioPlayer : MonoBehaviour
{
[Header("音频采样率")]
public int SamplingRate = 8000;
[Header("音频声道数,默认为单声道")]
public int Channels = 1;
[Header("音频录制最大时长,按秒计")]
public int RecordMaxTime = 60;
/// <summary>
/// 表示当前播放器是否正在播放。
/// </summary>
public bool IsPlaying { get { return !stopped && audioSource.isPlaying; } }
/// <summary>
/// 获得播放列表。
/// </summary>
public PlayList PlayList { get { return playList; } }
/// <summary>
/// 获得当前已经播放到播放列表中哪一条曲目了。
/// </summary>
public int PlayIndex
{
get { return playIndex; }
set
{
if (value < -1 || value >= playList.Count)
throw new InvalidOperationException("value");
playIndex = value;
}
}
/// <summary>
/// 表示要开始播放某曲目前的事件。
/// </summary>
public event Action<int, Track> Playing;
/// <summary>
/// 表示播放某曲目结束后的事件。
/// </summary>
public event Action<int, Track> Played;
private AudioSource audioSource;
private OpusDecoder opusDecoder;
private BetterList<float> audioBuffer;
private BetterList<byte> opusBuffer;
private float[] packageBuffer;
private byte[] frameBuffer;
private PlayList playList;
private int playIndex;
private bool stopped;
private const int BufferSize = 8192;
private byte[] buffer = new byte[BufferSize];
void Awake()
{
Initialize();
}
void OnDisable()
{
Stop();
}
void OnDestroy()
{
if (opusDecoder != null)
{
opusDecoder.Dispose();
opusDecoder = null;
}
}
void Update()
{
// 自动播放列表中的语音消息
if (!stopped && playList.Count > 0)
{
// 已经全部播放过
if (playIndex != -1 && playIndex == playList.Count - 1 && playList[playIndex].Played && !playList[playIndex].Playing)
return;
// 正在播放
if (IsPlaying)
return;
// 当前项播放完毕
var curTrack = playList[playIndex];
curTrack.Playing = false;
playList[playIndex] = curTrack;
OnPlayed(playIndex, curTrack);
// 准备播放下一条
var nextIndex = playIndex + 1;
if (nextIndex != playList.Count)
{
var track = playList[nextIndex];
if (!track.Played)
{
playIndex = nextIndex;
track.Played = true;
track.Playing = true;
playList[nextIndex] = track;
PlayAudio(playList[nextIndex].Filename);
}
}
}
}
/// <summary>
/// 立即播放指定的音频文件,即使该播放器正在播放其它音频文件。
/// </summary>
public void Play(string audioFile)
{
var index = playList.IndexOf(audioFile);
if (index == -1)
{
playList.Add(audioFile, true, true);
playIndex = playList.Count - 1;
}
else
{
playIndex = index;
var track = playList[playIndex];
track.Played = true;
track.Playing = true;
playList[playIndex] = track;
}
if (IsPlaying)
Stop();
stopped = false;
PlayAudio(audioFile);
}
/// <summary>
/// 排队播放音频文件。
/// </summary>
public void PlayScheduled(string audioFile)
{
var index = playList.IndexOf(audioFile);
if (index == -1)
playList.Add(audioFile, false, false);
stopped = false;
}
/// <summary>
/// 播放音频。
/// </summary>
public void Play()
{
stopped = false;
}
public void Stop()
{
if (opusDecoder != null)
{
audioSource.Stop();
if (audioSource.clip != null)
{
Destroy(audioSource.clip);
audioSource.clip = null;
}
if (playIndex != -1)
{
var track = playList[playIndex];
track.Playing = false;
playList[playIndex] = track;
}
}
stopped = true;
}
private void Initialize()
{
if (opusDecoder == null)
{
audioSource = GetComponent<AudioSource>();
audioBuffer = new BetterList<float>(RecordMaxTime * SamplingRate * Channels + PromptTone.Data.Length);
opusBuffer = new BetterList<byte>(200 * 1024);
packageBuffer = new float[OpusDecoder.FrameMaxSize * Channels];
opusDecoder = new OpusDecoder((SamplingRate)SamplingRate, (Channel)Channels);
playList = new PlayList();
playIndex = -1;
}
}
private void PlayAudio(string audioFile)
{
OnPlaying(playIndex, playList[playIndex]);
// 先从文件读取数据
using (var stream = new FileStream(audioFile, FileMode.Open, FileAccess.Read, FileShare.Read, BufferSize))
{
var readLength = 0;
while ((readLength = stream.Read(buffer, 0, BufferSize)) > 0)
opusBuffer.AddRange(buffer, 0, readLength);
}
// 解析数据并解码音频
var length = 0;
for (var i = 0; i < opusBuffer.Count; ++i)
{
length = opusBuffer[i];
if (length == 0)
continue;
if (frameBuffer == null || length != frameBuffer.Length)
frameBuffer = new byte[length];
opusBuffer.CopyTo(i + 1, frameBuffer, 0, length);
var decoded = opusDecoder.Decode(frameBuffer, packageBuffer);
audioBuffer.AddRange(packageBuffer, 0, decoded);
i += length;
}
var data = audioBuffer.ToArray();
audioBuffer.Clear();
opusBuffer.Clear();
var clip = AudioClip.Create("VoicePlayback", data.Length, Channels, SamplingRate, false);
clip.SetData(data, 0);
audioSource.clip = clip;
audioSource.Play();
}
public void Clear()
{
Stop();
PlayList.Clear();
playIndex = -1;
}
protected virtual void OnPlaying(int index, Track track)
{
if (Playing != null)
Playing(index, track);
}
protected virtual void OnPlayed(int index, Track track)
{
if (Played != null)
Played(index, track);
}
}