325 lines
11 KiB
C#
325 lines
11 KiB
C#
//using MoPhoGames.USpeak.Core;
|
||
using System.Collections.Generic;
|
||
using Thousandto.Code.Center;
|
||
using Thousandto.Core.Asset;
|
||
using Thousandto.Core.Base;
|
||
using UnityEngine;
|
||
|
||
namespace Thousandto.Code.Logic
|
||
{
|
||
/// <summary>
|
||
/// UIEntergameForm的逻辑处理类
|
||
/// </summary>
|
||
public partial class ChatSystem
|
||
{
|
||
public const int MAX_RECORD_DURATION = 15; //最长录音时间
|
||
public int VoiceIndex; //接收到的语音序列,从0开始增加
|
||
public int LocalVoiceIndex; //本人发送的语音,发送时就计算序列
|
||
public MyAction _action; //回调
|
||
public MonoBehaviour Coro; //用于启动协程,每次打开聊天窗的时候赋值
|
||
|
||
private bool _recording; //是否正在录音
|
||
private float MinLenght = 1.0f; //最短有效录音
|
||
private int _audioLength; //录音时长
|
||
private AudioClip _audioClip;
|
||
private byte[] _compressedRecordData;
|
||
|
||
//通常的无损音质的采样率是44100,即每秒音频用44100个float数据表示,但是语音只需8000(通常移动电话是8000)就够了
|
||
//不然音频数据太大,不利于传输和存储
|
||
public const int SamplingRate = 8000;
|
||
public AudioSource ChatAudioSource;
|
||
|
||
private Dictionary<int, byte[]> _voiceDataDic = new Dictionary<int, byte[]>();
|
||
private Dictionary<string, string> _voiceKeyToVoiceData = new Dictionary<string, string>();
|
||
|
||
#region 录音操作
|
||
public void StartRecord()
|
||
{
|
||
_audioLength = 0;
|
||
_compressedRecordData = null;
|
||
_recording = true;
|
||
|
||
StopPlayingAudio();
|
||
SuspendAllSound();
|
||
|
||
//GameCenter.UniSoundSystem.SuspendSystem();
|
||
//按钮按下开始录音
|
||
//Microphone.End(null);//这句可以不需要,但是在开始录音以前调用一次是好习惯
|
||
//string[] micDevices = Microphone.devices;
|
||
//for (int i = 0; micDevices != null && i < micDevices.Length; ++i)
|
||
//{
|
||
// UnityEngine.Debug.LogError("话筒: " + micDevices[i]);
|
||
//}
|
||
_audioClip = null;
|
||
//_audioClip = Microphone.Start(null, false, MAX_RECORD_DURATION, SamplingRate);
|
||
}
|
||
|
||
//是否正在录音
|
||
public bool IsRecording()
|
||
{
|
||
return _recording;
|
||
}
|
||
|
||
public void EndRecord()
|
||
{
|
||
/*
|
||
//按钮弹起结束录音
|
||
int audioLength;//录音的长度,单位为秒,ui上可能需要显示
|
||
int lastPos = Microphone.GetPosition(null);
|
||
if (Microphone.IsRecording(null))
|
||
{
|
||
//录音小于10秒
|
||
audioLength = lastPos / SamplingRate;//录音时长
|
||
}
|
||
else
|
||
{
|
||
audioLength = MAX_RECORD_DURATION;
|
||
}
|
||
Microphone.End(null);//此时录音结束,clip已可以播放了
|
||
|
||
ResumeAllSound();
|
||
//GameCenter.UniSoundSystem.ResumeSystem();
|
||
if (audioLength < MinLenght) return;//录音小于2秒就不处理了
|
||
|
||
|
||
int samples = 0;
|
||
_compressedRecordData = null;// USpeakAudioClipCompressor.CompressAudioClip(_audioClip, out samples, BandMode.Narrow);
|
||
//_audioClip = null;
|
||
_audioLength = audioLength;
|
||
_recording = false;
|
||
*/
|
||
}
|
||
|
||
public void SuspendAllSound()
|
||
{
|
||
if (GameCenter.GameSetting.GetSetting(GameSettingKeyCode.EnableBGMusic) != 0)
|
||
{
|
||
AudioPlayer.SetVolume(AudioTypeCode.Music, 0f);
|
||
}
|
||
|
||
if (GameCenter.GameSetting.GetSetting(GameSettingKeyCode.EnableSound) != 0)
|
||
{
|
||
AudioPlayer.SetVolume(AudioTypeCode.Sfx, 0f);
|
||
AudioPlayer.SetVolume(AudioTypeCode.Ambient, 0f);
|
||
AudioPlayer.SetVolume(AudioTypeCode.Speech, 0f);
|
||
AudioPlayer.SetVolume(AudioTypeCode.UI, 0f);
|
||
}
|
||
}
|
||
|
||
public void ResumeAllSound()
|
||
{
|
||
if (GameCenter.GameSetting.GetSetting(GameSettingKeyCode.EnableBGMusic) != 0)
|
||
{
|
||
float v = (float)GameCenter.GameSetting.GetSetting(GameSettingKeyCode.BGMusicVolume)/100f;
|
||
AudioPlayer.SetVolume(AudioTypeCode.Music, v);
|
||
}
|
||
|
||
if (GameCenter.GameSetting.GetSetting(GameSettingKeyCode.EnableSound) != 0)
|
||
{
|
||
float v = (float)GameCenter.GameSetting.GetSetting(GameSettingKeyCode.SoundVolume) / 100f;
|
||
AudioPlayer.SetVolume(AudioTypeCode.Sfx, v);
|
||
AudioPlayer.SetVolume(AudioTypeCode.Ambient, v);
|
||
AudioPlayer.SetVolume(AudioTypeCode.Speech, v);
|
||
AudioPlayer.SetVolume(AudioTypeCode.UI, v);
|
||
}
|
||
}
|
||
|
||
public void SendRecord(ChatInfo info)
|
||
{
|
||
if (_recording)
|
||
{
|
||
EndRecord();
|
||
}
|
||
|
||
LocalVoiceIndex = ++VoiceIndex;
|
||
|
||
addVoiceDataToCache(LocalVoiceIndex, _compressedRecordData);
|
||
|
||
string content = byteToString(_compressedRecordData);
|
||
MSG_Chat.ChatReqCS req = new MSG_Chat.ChatReqCS();
|
||
req.chattype = info.ChatType;
|
||
req.recRoleId = info.Receiver;
|
||
req.condition = content;
|
||
req.voiceLen = _audioLength;
|
||
req.chatchannel = info.Channel;
|
||
req.Send();
|
||
|
||
//UnityEngine.Debug.LogError("录音时长:" + _audioLength);
|
||
//UnityEngine.Debug.LogError("录音数据长度:" + _compressedRecordData.Length);
|
||
}
|
||
#endregion
|
||
|
||
#region 语音播放操作
|
||
//是否有语音在播放
|
||
public bool IsAudioPlaying()
|
||
{
|
||
if (ChatAudioSource != null)
|
||
{
|
||
return ChatAudioSource.isPlaying;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
//关闭正在播放的语音
|
||
public void StopPlayingAudio()
|
||
{
|
||
if (ChatAudioSource != null && ChatAudioSource.isPlaying)
|
||
{
|
||
ChatAudioSource.Stop();
|
||
}
|
||
}
|
||
|
||
// method
|
||
public bool PlayAudio(byte[] data, AudioSource audioSrc)
|
||
{
|
||
if (audioSrc == null)
|
||
{
|
||
return false;
|
||
}
|
||
audioSrc.clip = null;
|
||
AudioClip clip = null;// USpeakAudioClipCompressor.DecompressAudioClip(data, 0, 1, false, BandMode.Narrow, 1.0f);
|
||
// play test
|
||
audioSrc.clip = clip;
|
||
audioSrc.Play();
|
||
|
||
SuspendAllSound();
|
||
//GameCenter.UniSoundSystem.SuspendSystem();
|
||
|
||
return true;
|
||
}
|
||
|
||
#endregion
|
||
|
||
|
||
#region 窗体事件
|
||
public void OnFormClose()
|
||
{
|
||
//关闭窗体时,关闭语音,并且恢复背景声音
|
||
if (IsAudioPlaying())
|
||
{
|
||
StopPlayingAudio();
|
||
}
|
||
|
||
ResumeAllSound();
|
||
//GameCenter.UniSoundSystem.ResumeSystem();
|
||
}
|
||
#endregion
|
||
|
||
#region 私有功能函数
|
||
//添加聊天数据到缓存中保存
|
||
private void addVoiceDataToCache(int index, byte[] data)
|
||
{
|
||
//超30个就remove
|
||
if (_voiceDataDic.Count >= 30)
|
||
{
|
||
var itor = _voiceDataDic.Keys.GetEnumerator();
|
||
itor.MoveNext();
|
||
int key = itor.Current;
|
||
_voiceDataDic.Remove(key);
|
||
|
||
//在_voiceKeyToVoiceData中去移除对应的key
|
||
var itor2 = _voiceKeyToVoiceData.GetEnumerator();
|
||
string keyStr = "" + key;
|
||
while (itor2.MoveNext())
|
||
{
|
||
if (itor2.Current.Value == keyStr)
|
||
{
|
||
_voiceKeyToVoiceData.Remove(itor2.Current.Key);
|
||
break;
|
||
}
|
||
}
|
||
|
||
}
|
||
else
|
||
{
|
||
if (_voiceDataDic.ContainsKey(index))
|
||
{
|
||
_voiceDataDic[index] = data;
|
||
}
|
||
else
|
||
_voiceDataDic.Add(index, data);
|
||
}
|
||
|
||
}
|
||
|
||
private string byteToString(byte[] voiceData)
|
||
{
|
||
char[] charArray = new char[voiceData.Length];
|
||
for (int i = 0; i < voiceData.Length; ++i)
|
||
{
|
||
charArray[i] = (char)voiceData[i];
|
||
}
|
||
|
||
string str = new string(charArray);
|
||
|
||
return str;
|
||
}
|
||
|
||
private byte[] stringToBytes(string str)
|
||
{
|
||
char[] charArray = str.ToCharArray();
|
||
byte[] data = new byte[charArray.Length];
|
||
for (int i = 0; i < charArray.Length; ++i)
|
||
{
|
||
data[i] = (byte)charArray[i];
|
||
}
|
||
return data;
|
||
}
|
||
#endregion
|
||
|
||
#region 协议请求
|
||
public void ReqVoiceData(string key, MyAction action)
|
||
{
|
||
_action = action;
|
||
if (_voiceKeyToVoiceData.ContainsKey(key))
|
||
{
|
||
int voiceIndexKey = int.Parse(_voiceKeyToVoiceData[key]);
|
||
if (_voiceDataDic.ContainsKey(voiceIndexKey))
|
||
{
|
||
PlayAudio(_voiceDataDic[voiceIndexKey], ChatAudioSource);
|
||
if (_action != null)
|
||
_action();
|
||
return;
|
||
}
|
||
}
|
||
|
||
MSG_Chat.ChatGetContentCS reqVoice = new MSG_Chat.ChatGetContentCS();
|
||
reqVoice.key = key;
|
||
reqVoice.Send();
|
||
}
|
||
#endregion
|
||
|
||
#region 协议返回
|
||
|
||
public void GS2U_ChatGetContentSC(MSG_Chat.ChatGetContentSC result)
|
||
{
|
||
byte[] voiceData = stringToBytes(result.voice);
|
||
|
||
//有保存,重置数据
|
||
if (_voiceKeyToVoiceData.ContainsKey(result.voiceKey))
|
||
{
|
||
int index = int.Parse(_voiceKeyToVoiceData[result.voiceKey]);
|
||
addVoiceDataToCache(index, voiceData);
|
||
}
|
||
|
||
PlayAudio(voiceData, ChatAudioSource);
|
||
if (_action != null)
|
||
_action();
|
||
|
||
//CoroutinePool.AddTask(playAudioIE(obj, this));
|
||
}
|
||
|
||
public void TestOnChatVoiceReceive(int channel, int voiceID, int length)
|
||
{
|
||
//Audio: m_param1 = key; m_param2 = length m_param3 = ""
|
||
ChatNode node = new ChatNode();
|
||
node.ChannelID = channel;
|
||
node.Param1 = "" + voiceID;
|
||
node.Param2 = "" + length;
|
||
node.Param3 = null;
|
||
}
|
||
#endregion
|
||
}
|
||
}
|