Assignment for RMIT Mixed Reality in 2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

152 lines
3.9 KiB

  1. namespace Oculus.Platform
  2. {
  3. using UnityEngine;
  4. using System;
  5. using System.Collections.Generic;
  6. public class VoipAudioSourceHiLevel : MonoBehaviour
  7. {
  8. // This is a delegate that exists as a surface for OnAudioFilterRead
  9. // It will be callled on unity's audio thread
  10. public class FilterReadDelegate : MonoBehaviour
  11. {
  12. public VoipAudioSourceHiLevel parent;
  13. float[] scratchBuffer;
  14. void Awake()
  15. {
  16. int bufferSizeElements = (int)CAPI.ovr_Voip_GetOutputBufferMaxSize();
  17. scratchBuffer = new float[bufferSizeElements];
  18. }
  19. void OnAudioFilterRead(float[] data, int channels)
  20. {
  21. int sizeToFetch = data.Length / channels;
  22. int sourceBufferSize = sizeToFetch;
  23. if (sourceBufferSize > scratchBuffer.Length)
  24. {
  25. Array.Clear(data, 0, data.Length);
  26. throw new Exception(string.Format("Audio system tried to pull {0} bytes, max voip internal ring buffer size {1}", sizeToFetch, scratchBuffer.Length));
  27. }
  28. int available = parent.pcmSource.PeekSizeElements();
  29. if (available < sourceBufferSize)
  30. {
  31. if (verboseLogging)
  32. {
  33. Debug.LogFormat(
  34. "Voip starved! Want {0}, but only have {1} available",
  35. sourceBufferSize,
  36. available);
  37. }
  38. return;
  39. }
  40. int copied = parent.pcmSource.GetPCM(scratchBuffer, sourceBufferSize);
  41. if (copied < sourceBufferSize)
  42. {
  43. Debug.LogWarningFormat(
  44. "GetPCM() returned {0} samples, expected {1}",
  45. copied,
  46. sourceBufferSize);
  47. return;
  48. }
  49. int dest = 0;
  50. float tmpPeakAmp = -1;
  51. for (int i = 0; i < sizeToFetch; i++)
  52. {
  53. float val = scratchBuffer[i];
  54. for (int j = 0; j < channels; j++)
  55. {
  56. data[dest++] = val;
  57. if (val > tmpPeakAmp)
  58. {
  59. tmpPeakAmp = val;
  60. }
  61. }
  62. }
  63. parent.peakAmplitude = tmpPeakAmp;
  64. }
  65. }
  66. int initialPlaybackDelayMS;
  67. public UInt64 senderID
  68. {
  69. set
  70. {
  71. pcmSource.SetSenderID(value);
  72. }
  73. }
  74. public AudioSource audioSource;
  75. public float peakAmplitude;
  76. protected IVoipPCMSource pcmSource;
  77. static int audioSystemPlaybackFrequency;
  78. static bool verboseLogging = false;
  79. protected void Stop() {}
  80. VoipSampleRate SampleRateToEnum(int rate) {
  81. switch(rate) {
  82. case 48000:
  83. return VoipSampleRate.HZ48000;
  84. case 44100:
  85. return VoipSampleRate.HZ44100;
  86. case 24000:
  87. return VoipSampleRate.HZ24000;
  88. default:
  89. return VoipSampleRate.Unknown;
  90. }
  91. }
  92. protected void Awake()
  93. {
  94. CreatePCMSource();
  95. if(audioSource == null) {
  96. audioSource = gameObject.AddComponent<AudioSource>();
  97. }
  98. audioSource.gameObject.AddComponent<FilterReadDelegate>();
  99. var filterDelegate = audioSource.gameObject.GetComponent<FilterReadDelegate>();
  100. filterDelegate.parent = this;
  101. initialPlaybackDelayMS = 40;
  102. audioSystemPlaybackFrequency = AudioSettings.outputSampleRate;
  103. CAPI.ovr_Voip_SetOutputSampleRate(SampleRateToEnum(audioSystemPlaybackFrequency));
  104. if(verboseLogging) {
  105. Debug.LogFormat("freq {0}", audioSystemPlaybackFrequency);
  106. }
  107. }
  108. void Start() {
  109. audioSource.Stop();
  110. }
  111. protected virtual void CreatePCMSource()
  112. {
  113. pcmSource = new VoipPCMSourceNative();
  114. }
  115. protected static int MSToElements(int ms) {
  116. return ms * audioSystemPlaybackFrequency / 1000;
  117. }
  118. void Update()
  119. {
  120. pcmSource.Update();
  121. if (!audioSource.isPlaying && pcmSource.PeekSizeElements() >= MSToElements(initialPlaybackDelayMS)) {
  122. if(verboseLogging) {
  123. Debug.LogFormat("buffered {0} elements, starting playback", pcmSource.PeekSizeElements());
  124. }
  125. audioSource.Play();
  126. }
  127. }
  128. }
  129. }