16 [RequireComponent(typeof(AudioSource))]
27 public float InputGain = 2;
32 public bool ShouldTransmitAudio =
true;
43 private DateTime timeOfLastPacketSend;
44 private float worstTimeBetweenPackets;
46 private int sequenceNumber;
48 private int sampleRateType = 3;
50 private AudioSource audioSource;
52 private bool hasServerConnection;
53 private bool micStarted;
55 public const int AudioPacketSize = 960;
57 private byte[] packetSamples =
new byte[AudioPacketSize * 4];
70 private readonly Mutex audioDataMutex =
new Mutex();
72 #region DebugVariables 76 private AudioSource testSource;
85 if (stage && stage.Manager != null)
87 connection = stage.Manager.GetServerConnection();
89 if (connection == null || !connection.
IsConnected())
98 audioSource = GetComponent<AudioSource>();
101 CheckForErrorOnCall(errorCode);
106 audioSource.volume = HearSelf ? 1.0f : 0.0f;
112 private void OnAudioFilterRead(
float[] buffer,
int numChannels)
116 audioDataMutex.WaitOne();
118 if (micStarted && hasServerConnection)
122 int dataSize = buffer.Length * 4;
123 if (micBuffer.
Write(buffer, 0, dataSize) != dataSize)
125 Debug.LogError(
"Send buffer filled up. Some audio will be lost.");
132 Debug.LogError(e.Message);
136 audioDataMutex.ReleaseMutex();
140 private void Update()
143 audioSource.volume = HearSelf ? 1.0f : 0.0f;
147 audioDataMutex.WaitOne();
149 var connection = GetActiveConnection();
150 hasServerConnection = (connection != null);
151 if (hasServerConnection)
155 TransmitAudio(connection);
161 Debug.LogError(e.Message);
165 audioDataMutex.ReleaseMutex();
169 if (SaveTestClip && testCircularBuffer.UsedCapacity == testCircularBuffer.TotalCapacity)
171 float[] testBuffer =
new float[testCircularBuffer.UsedCapacity / 4];
172 testCircularBuffer.Read(testBuffer, 0, testBuffer.Length * 4);
173 testCircularBuffer.Reset();
174 TestClip = AudioClip.Create(
"testclip", testBuffer.Length / 2, 2, 48000,
false);
175 TestClip.SetData(testBuffer, 0);
178 GameObject testObj =
new GameObject(
"testclip");
179 testObj.transform.parent = transform;
180 testSource = testObj.AddComponent<AudioSource>();
182 testSource.PlayClip(TestClip);
183 SaveTestClip =
false;
190 micBuffer.
Read(packetSamples, 0, 4 * AudioPacketSize);
191 SendFixedSizedChunk(connection, packetSamples, packetSamples.Length);
195 testCircularBuffer.Write(packetSamples, 0, packetSamples.Length);
199 private void SendFixedSizedChunk(
NetworkConnection connection, byte[] data,
int dataSize)
201 DateTime currentTime = DateTime.Now;
202 float seconds = (float)(currentTime - timeOfLastPacketSend).TotalSeconds;
203 timeOfLastPacketSend = currentTime;
206 if (worstTimeBetweenPackets < seconds)
208 worstTimeBetweenPackets = seconds;
211 if (ShowInterPacketTime)
213 Debug.LogFormat(
"Microphone: Milliseconds since last sent: {0}, Worst: {1}",
214 (seconds * 1000.0).ToString(CultureInfo.InvariantCulture),
215 (worstTimeBetweenPackets * 1000.0).ToString(CultureInfo.InvariantCulture));
224 int dataCountFloats = dataSize / 4;
229 versionPacker.SetBits(ref pack, 1);
230 audioStreamCountPacker.SetBits(ref pack, 1);
231 channelCountPacker.SetBits(ref pack, 1);
232 sampleRatePacker.SetBits(ref pack, sampleRateType);
233 sampleTypePacker.SetBits(ref pack, 0);
234 sampleCountPacker.SetBits(ref pack, dataCountFloats);
235 codecTypePacker.SetBits(ref pack, 0);
236 mutePacker.SetBits(ref pack, Mute ? 1 : 0);
237 sequenceNumberPacker.SetBits(ref pack, sequenceNumber++);
238 sequenceNumber %= 32;
249 Vector3 cameraPosRelativeToGlobalAnchor = Vector3.zero;
250 Vector3 cameraDirectionRelativeToGlobalAnchor = Vector3.zero;
252 if (GlobalAnchorTransform != null)
256 GlobalAnchorTransform,
261 GlobalAnchorTransform,
265 cameraPosRelativeToGlobalAnchor.Normalize();
266 cameraDirectionRelativeToGlobalAnchor.Normalize();
269 msg.
Write(cameraPosRelativeToGlobalAnchor.x);
270 msg.
Write(cameraPosRelativeToGlobalAnchor.y);
271 msg.
Write(cameraPosRelativeToGlobalAnchor.z);
274 msg.
Write(cameraDirectionRelativeToGlobalAnchor.x);
275 msg.
Write(cameraDirectionRelativeToGlobalAnchor.y);
276 msg.
Write(cameraDirectionRelativeToGlobalAnchor.z);
278 msg.
WriteArray(data, (uint)dataCountFloats * 4);
283 private void OnDestroy()
288 private bool CheckForErrorOnCall(
int returnCode)
295 private void OnApplicationPause(
bool pause)
307 private void OnApplicationFocus(
bool focused)
309 OnApplicationPause(!focused);
312 private void OnDisable()
314 OnApplicationPause(
true);
317 private void OnEnable()
319 OnApplicationPause(
false);