/* 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 voiceArr = FastList.Obtain(); public VoicePacketWrapper[] temp; public int recordLength = 0; public Action EndCallBack; private void Start() { Debug.Log("Start"); } /// /// 录音开始回调 /// protected override void RecordingStart() { base.RecordingStart(); voiceArr = FastList.Obtain(); isCallBack = true; } /// /// 录音停止后回调 /// protected override void RecordingEnd(int length) { if (!this.isCallBack) return; base.RecordingEnd(length); recordLength = length; Debug.Log("RecordingEnd copy start"); FastList allData = FastList.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(); } /// /// 每一次framesize满了就会回调 /// /// protected override void OnAudioDataEncoded( VoicePacketWrapper encodedFrame ) { if (UnityEngine.Random.Range(0f, 1f) <= PacketLoss) { return; } voiceArr.Enqueue(encodedFrame); } #region publicMethod /// /// 开始录音 /// public void StartRecording() { base.microphone.StartRecording(); } /// /// 停止录音 /// public void StopRecording(bool callBack) { this.isCallBack = callBack; base.microphone.StopRecording(); } /// /// 延迟停止录音 /// 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 head = null; FastList 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.Obtain(9); raw = FastList.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; } /// /// 1. Narrow,2.Wide,3.UltraWide /// /// 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; } } }