using System.IO; using UnityEngine; namespace VelNet.Voice { public class VelVoicePlayer : NetworkComponent { /// /// must be set for the player only /// public VelVoice voiceSystem; /// /// must be set for the clone only /// public AudioSource source; private AudioClip myClip; public int bufferedAmount; public int playedAmount; private int lastTime; /// /// a buffer of 0s to force silence, because playing doesn't stop on demand /// private readonly float[] empty = new float[1000]; private float delayStartTime; public override void ReceiveBytes(byte[] message) { float[] temp = voiceSystem.DecodeOpusData(message, message.Length); myClip.SetData(temp, bufferedAmount % source.clip.samples); bufferedAmount += temp.Length; myClip.SetData(empty, bufferedAmount % source.clip.samples); //buffer some empty data because otherwise you'll hear sound (but it'll be overwritten by the next sample) if (!source.isPlaying) { delayStartTime = Time.time; //I've received a packet but I haven't played it } } // Start is called before the first frame update private void Start() { voiceSystem = GameObject.FindObjectOfType(); if (voiceSystem == null) { Debug.LogError("No microphone found. Make sure you have one in the scene."); return; } if (networkObject.IsMine) { voiceSystem.encodedFrameAvailable += (frame) => { //float[] temp = new float[frame.count]; //System.Array.Copy(frame.array, temp, frame.count); MemoryStream mem = new MemoryStream(); BinaryWriter writer = new BinaryWriter(mem); writer.Write(frame.array, 0, frame.count); this.SendBytes(mem.ToArray(), false); }; } myClip = AudioClip.Create(this.name, 16000 * 10, 1, 16000, false); source.clip = myClip; source.loop = true; source.Pause(); } // Update is called once per frame private void Update() { if (bufferedAmount > playedAmount) { int offset = bufferedAmount - playedAmount; if ((offset > 1000) || (Time.time - delayStartTime) > .1f) //this seems to make the quality better { int temp = Mathf.Max(0, offset - 2000); source.pitch = Mathf.Min(2, 1 + temp / 18000.0f); //okay to behind by 2000. These numbers correspond to about 2x speed at a seconds behind if (!source.isPlaying) { source.Play(); } } else { return; } } else if (playedAmount >= bufferedAmount) { playedAmount = bufferedAmount; source.Pause(); source.timeSamples = bufferedAmount % source.clip.samples; } //Debug.Log(playedAmount); if (source.timeSamples >= lastTime) { playedAmount += (source.timeSamples - lastTime); } else //repeated { int total = source.clip.samples - lastTime + source.timeSamples; playedAmount += total; } lastTime = source.timeSamples; } } }