14 [RequireComponent(typeof(AudioSource))]
38 public const int MaximumProminentSpeakers = 4;
43 private int prominentSpeakerCount;
52 private readonly Mutex audioDataMutex =
new Mutex();
54 private const float KDropOffMaximum = 5f;
55 private const float KPanMaximum = 5f;
57 public float DropOffMaximumMetres = 5.0f;
58 public float PanMaximumMetres = 5.0f;
60 public float MinimumDistance = .01f;
62 private byte[] networkPacketBufferBytes;
65 #region DebugVariables 67 private AudioSource testSource;
75 for (
int prominentSpeaker = 0; prominentSpeaker < MaximumProminentSpeakers; prominentSpeaker++)
84 private void TryConnect()
91 if (sharingStage && sharingStage.
Manager != null)
103 Debug.Log(
"SpeakerController Start called");
109 Debug.Log(
"Exception: " + ex);
113 private void OnDestroy()
115 if (listener != null)
127 InternalStartSpeaker();
128 Debug.Log(
"SpeakerController: Connection to session server succeeded!");
134 InternalStopSpeaker();
136 prominentSpeakerCount = 0;
138 Debug.Log(
"SpeakerController: Session server disconnected!");
143 InternalStopSpeaker();
144 Debug.Log(
"SpeakerController: Connection to session server failed!");
150 private void InternalStartSpeaker()
152 GetComponent<AudioSource>().Play();
158 private void InternalStopSpeaker()
160 GetComponent<AudioSource>().Stop();
163 private void Update()
167 AudioSource audioSource = GetComponent<AudioSource>();
168 GameObject remoteHead = GameObject.Find(
"mixamorig:Head");
171 transform.parent = remoteHead.transform;
172 transform.localPosition =
new Vector3();
173 transform.localRotation = Quaternion.identity;
175 audioSource.spatialize =
true;
176 audioSource.spatialBlend = 1;
180 audioSource.spatialize =
false;
181 audioSource.spatialBlend = 0;
185 if (SaveTestClip && testCircularBuffer.UsedCapacity == testCircularBuffer.TotalCapacity)
187 float[] testBuffer =
new float[testCircularBuffer.UsedCapacity / 4];
188 testCircularBuffer.Read(testBuffer, 0, testBuffer.Length * 4);
189 testCircularBuffer.Reset();
190 TestClip = AudioClip.Create(
"testclip", testBuffer.Length / 2, 2, 48000,
false);
191 TestClip.SetData(testBuffer, 0);
194 GameObject testObj =
new GameObject(
"testclip");
195 testObj.transform.parent = transform;
196 testSource = testObj.AddComponent<AudioSource>();
198 testSource.PlayClip(TestClip,
true);
199 SaveTestClip =
false;
217 versionExtractor.GetBitsValue(pack);
218 int audioStreamCount = audioStreamCountExtractor.GetBitsValue(pack);
219 int channelCount = channelCountExtractor.GetBitsValue(pack);
220 int sampleRate = sampleRateExtractor.GetBitsValue(pack);
221 int sampleType = sampleTypeExtractor.GetBitsValue(pack);
222 int bytesPerSample =
sizeof(float);
225 bytesPerSample =
sizeof(Int16);
228 int sampleCount = sampleCountExtractor.GetBitsValue(pack);
229 int codecType = codecTypeExtractor.GetBitsValue(pack);
232 sequenceNumberExtractor.GetBitsValue(pack);
242 audioDataMutex.WaitOne();
244 prominentSpeakerCount = 0;
246 for (
int i = 0; i < audioStreamCount; i++)
248 float averageAmplitude = message.
ReadFloat();
249 UInt32 hrtfSourceID = (UInt32)message.
ReadInt32();
250 Vector3 hrtfPosition =
new Vector3();
251 Vector3 hrtfDirection =
new Vector3();
252 if (hrtfSourceID != 0)
262 Vector3 cameraPosRelativeToGlobalAnchor = Vector3.zero;
263 Vector3 cameraDirectionRelativeToGlobalAnchor = Vector3.zero;
265 if (GlobalAnchorTransform != null)
269 GlobalAnchorTransform,
273 GlobalAnchorTransform,
277 cameraPosRelativeToGlobalAnchor.Normalize();
278 cameraDirectionRelativeToGlobalAnchor.Normalize();
280 Vector3 soundVector = hrtfPosition - cameraPosRelativeToGlobalAnchor;
281 soundVector.Normalize();
284 float fltx = (KDropOffMaximum / DropOffMaximumMetres) * Vector3.Dot(soundVector, cameraDirectionRelativeToGlobalAnchor);
286 Vector3 myRight = Quaternion.Euler(0, 90, 0) * cameraDirectionRelativeToGlobalAnchor;
287 float flty = -(KPanMaximum / PanMaximumMetres) * Vector3.Dot(soundVector, myRight);
289 Vector3 myUp = Quaternion.Euler(90, 0, 0) * cameraDirectionRelativeToGlobalAnchor;
290 float fltz = (KPanMaximum / PanMaximumMetres) * Vector3.Dot(soundVector, myUp);
293 Vector3 flt =
new Vector3(fltx, flty, fltz);
294 if (flt.magnitude < (MinimumDistance * KDropOffMaximum))
296 flt = flt.normalized * MinimumDistance * KDropOffMaximum;
302 AddProminentSpeaker(hrtfSourceID, averageAmplitude, fltx, flty, fltz);
305 for (
int j = 0; j < channelCount; j++)
308 Int16 size = (Int16)sampleCount;
317 int totalBytes = size * bytesPerSample;
318 if (networkPacketBufferBytes.Length != totalBytes)
320 networkPacketBufferBytes =
new byte[totalBytes];
322 message.
ReadArray(networkPacketBufferBytes, (uint)(totalBytes));
330 if (hrtfSourceID > 0)
335 circularBuffer.
Write(networkPacketBufferBytes, 0, networkPacketBufferBytes.Length);
341 Debug.LogError(e.Message);
345 audioDataMutex.ReleaseMutex();
349 private void OnAudioFilterRead(
float[] data,
int numChannels)
353 audioDataMutex.WaitOne();
354 int byteCount = data.Length * 4;
355 circularBuffer.
Read(data, 0, byteCount);
358 testCircularBuffer.Write(data, 0, byteCount);
363 Debug.LogError(e.Message);
367 audioDataMutex.ReleaseMutex();
371 private void AddProminentSpeaker(UInt32 sourceID,
float averageAmplitude,
float posX,
float posY,
float posZ)
373 if (prominentSpeakerCount < MaximumProminentSpeakers)
376 prominentSpeakerInfo.
SourceId = sourceID;
386 return prominentSpeakerCount;
391 if (index < prominentSpeakerCount)
393 return prominentSpeakerList[index];