344 lines
9.8 KiB
C#
Raw Normal View History

2025-06-07 17:43:34 +08:00
/* Copyright (C) 2014 DaikonForge */
namespace DaikonForge.VoIP
{
using UnityEngine;
using System.Collections.Generic;
using System.Collections;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using System.Text;
using System;
using Cysharp.Threading.Tasks;
public class LocalVoiceController : VoiceControllerBase
{
public float PacketLoss = 0.1f;
//private bool recording = false;
private bool isCallBack = true;
public static int RecordMaxLength = 40;
FastList<VoicePacketWrapper> voiceArr = FastList<VoicePacketWrapper>.Obtain();
public VoicePacketWrapper[] temp;
public int recordLength = 0;
public Action<byte[], byte> EndCallBack;
private void Start()
{
Debug.Log("Start");
}
/// <summary>
/// 录音开始回调
/// </summary>
protected override void RecordingStart()
{
base.RecordingStart();
voiceArr = FastList<VoicePacketWrapper>.Obtain();
isCallBack = true;
}
/// <summary>
/// 录音停止后回调
/// </summary>
protected override void RecordingEnd(int length)
{
if (!this.isCallBack)
return;
base.RecordingEnd(length);
recordLength = length;
Debug.Log("RecordingEnd copy start");
FastList<byte> allData = FastList<byte>.Obtain();
//int len = 0;
for (int i = 0, count = voiceArr.Count; i < count; i++)
{
allData.AddRange(voiceArr[i].GetSampleData());
voiceArr[i].ReleaseSampleData();
}
EndCallBack?.Invoke(allData.ToArray(), (byte)length);
//NativeToolkit.Instance.StopRecordingCallBack(allData.ToArray(), length);
allData.Release();
voiceArr.Release();
}
/// <summary>
/// 每一次framesize满了就会回调
/// </summary>
/// <param name="encodedFrame"></param>
protected override void OnAudioDataEncoded( VoicePacketWrapper encodedFrame )
{
if (UnityEngine.Random.Range(0f, 1f) <= PacketLoss)
{
return;
}
voiceArr.Enqueue(encodedFrame);
}
#region publicMethod
/// <summary>
/// 开始录音
/// </summary>
public void StartRecording()
{
base.microphone.StartRecording();
}
/// <summary>
/// 停止录音
/// </summary>
public void StopRecording(bool callBack)
{
this.isCallBack = callBack;
base.microphone.StopRecording();
}
/// <summary>
/// 延迟停止录音
/// </summary>
public async void StopRecording_Delay(bool callBack)
{
this.isCallBack = callBack;
await UniTask.WaitForSeconds(0.5f);
base.microphone.StopRecording();
}
public AudioClip Decode(byte[] allData, int seconds)
{
base.nextExpectedIndex = 0;
Application.platform.ToString();
int endIndex = 0;
int mHeadEndIndex = 0;
FastList<byte> head = null;
FastList<byte> raw = null;
bool isFirstSample = true;
VoicePacketWrapper packet;
for (int i = 0,length = allData.Length; i < length; i++)
{
if (i == endIndex)
{
if (i > 0)
{
packet = new VoicePacketWrapper(head.ToArray(), raw.ToArray());
if (isFirstSample)
{
isFirstSample = false;
speaker.SetSampleRate(packet.Frequency * 1000, seconds);
}
ReceiveAudioData(packet);
head.Release();
raw.Release();
}
head = FastList<byte>.Obtain(9);
raw = FastList<byte>.Obtain();
endIndex = endIndex + allData[i];
mHeadEndIndex = i + 9;
}
else
{
if (i <= mHeadEndIndex)
{
head.Add(allData[i]);
}
else if(i > mHeadEndIndex && i < endIndex )
{
raw.Add(allData[i]);
}
}
}
if (head != null)
{
head.Release();
}
if (raw != null)
{
raw.Release();
}
return speaker.GetAudioClip();
}
/**
public AudioClip Decode(VoicePacketWrapper[] packets, int seconds)
{
VoicePacketWrapper packet;
base.nextExpectedIndex = 0;
for (int i = 0, length = packets.Length; i < length; i++)
{
packet = packets[i];
if (i == 0)
{
speaker.SetSampleRate(packet.Frequency * 1000, seconds);
}
ReceiveAudioData(packet);
}
return speaker.GetAudioClip();
}
public AudioClip Decode(string[] headStrArr, string[] rawDataStrArr,int seconds)
{
byte[] headData = null;
byte[] rawData = null;
VoicePacketWrapper packet = new VoicePacketWrapper();
base.nextExpectedIndex = 0;
// -- -----test
int headLength = 0;
int rawLength = 0;
for (int i = 0,length = headStrArr.Length; i < length; i++)
{
int count = 0;
headData = GetBytes(headStrArr[i], out count);
rawData = GetBytes(rawDataStrArr[i], out count);
packet = new VoicePacketWrapper(headData, rawData);
if (i == 0)
{
speaker.SetSampleRate(packet.Frequency * 1000, seconds);
}
ReceiveAudioData(packet);
headLength += headStrArr[i].Length;
rawLength += rawDataStrArr[i].Length;
}
Debug.Log(string.Format("xxxxxxxxxxxxxxxxxxxxxxxxxxxDecode {0} / {1} /{2} ", headLength, rawLength, (headLength + rawLength)));
return speaker.GetAudioClip();
}
**/
public override bool IsLocal
{
get { return true; }
}
#endregion
public static string ToHexString(byte[] bytes) // 0xae00cf => "AE00CF "
{
string hexString = string.Empty;
if (bytes != null)
{
StringBuilder strB = new StringBuilder();
for (int i = 0; i < bytes.Length; i++)
{
strB.Append(bytes[i].ToString("X2"));
}
hexString = strB.ToString();
}
//hexString = System.Text.Encoding.UTF8.GetString(bytes);
return hexString;
}
public static byte[] GetBytes(string hexString, out int discarded)
{
discarded = 0;
string newString = "";
char c;
// remove all none A-F, 0-9, characters
for (int i = 0; i < hexString.Length; i++)
{
c = hexString[i];
if (Uri.IsHexDigit(c))
newString += c;
else
discarded++;
}
// if odd number of characters, discard last character
if (newString.Length % 2 != 0)
{
discarded++;
newString = newString.Substring(0, newString.Length - 1);
}
int byteLength = newString.Length / 2;
byte[] bytes = new byte[byteLength];
string hex;
int j = 0;
for (int i = 0; i < bytes.Length; i++)
{
hex = new System.String(new Char[] { newString[j], newString[j + 1] });
bytes[i] = HexToByte(hex);
j = j + 2;
}
//byte[] bytes = System.Text.Encoding.UTF8.GetBytes(hexString);
return bytes;
}
private static byte HexToByte(string hex)
{
byte tt = byte.Parse(hex, System.Globalization.NumberStyles.HexNumber);
return tt;
}
public UnityAudioPlayer GetSpeaker()
{
if (speaker != null)
return (UnityAudioPlayer)speaker;
else
return null;
}
/// <summary>
/// 1. Narrow,2.Wide,3.UltraWide
/// </summary>
/// <param name="level"></param>
public void SetMicphoneRecordingMode(int level)
{
FrequencyMode mode = FrequencyMode.Wide;
switch (level)
{
case 1:
mode = FrequencyMode.Narrow;
break;
case 2:
mode = FrequencyMode.Wide;
break;
case 3:
mode = FrequencyMode.UltraWide;
break;
default:
mode = FrequencyMode.Wide;
break;
}
((MicrophoneInputDevice)microphone).Mode = mode;
}
public void SetMaxRecordingTime(int recordingTime)
{
((MicrophoneInputDevice)microphone).maxRecordTime = recordingTime;
}
}
}