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.

372 lines
10 KiB

  1. /************************************************************************************
  2. Filename : OVRLipSyncMicInput.cs
  3. Content : Interface to microphone input
  4. Created : May 12, 2015
  5. Copyright : Copyright Facebook Technologies, LLC and its affiliates.
  6. All rights reserved.
  7. Licensed under the Oculus Audio SDK License Version 3.3 (the "License");
  8. you may not use the Oculus Audio SDK except in compliance with the License,
  9. which is provided at the time of installation or download, or which
  10. otherwise accompanies this software in either electronic or hard copy form.
  11. You may obtain a copy of the License at
  12. https://developer.oculus.com/licenses/audio-3.3/
  13. Unless required by applicable law or agreed to in writing, the Oculus Audio SDK
  14. distributed under the License is distributed on an "AS IS" BASIS,
  15. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. See the License for the specific language governing permissions and
  17. limitations under the License.
  18. ************************************************************************************/
  19. using System;
  20. using UnityEngine;
  21. using System.Diagnostics;
  22. using Debug = UnityEngine.Debug;
  23. using System.Threading;
  24. [RequireComponent(typeof(AudioSource))]
  25. public class OVRLipSyncMicInput : MonoBehaviour
  26. {
  27. public enum micActivation
  28. {
  29. HoldToSpeak,
  30. PushToSpeak,
  31. ConstantSpeak
  32. }
  33. // PUBLIC MEMBERS
  34. [Tooltip("Manual specification of Audio Source - " +
  35. "by default will use any attached to the same object.")]
  36. public AudioSource audioSource = null;
  37. [Tooltip("Enable a keypress to toggle the microphone device selection GUI.")]
  38. public bool enableMicSelectionGUI = false;
  39. [Tooltip("Key to toggle the microphone selection GUI if enabled.")]
  40. public KeyCode micSelectionGUIKey = KeyCode.M;
  41. [SerializeField]
  42. [Range(0.0f, 100.0f)]
  43. [Tooltip("Microphone input volume control.")]
  44. private float micInputVolume = 100;
  45. [SerializeField]
  46. [Tooltip("Requested microphone input frequency")]
  47. private int micFrequency = 48000;
  48. public float MicFrequency
  49. {
  50. get { return micFrequency; }
  51. set { micFrequency = (int)Mathf.Clamp((float)value, 0, 96000); }
  52. }
  53. [Tooltip("Microphone input control method. Hold To Speak and Push" +
  54. " To Speak are driven with the Mic Activation Key.")]
  55. public micActivation micControl = micActivation.ConstantSpeak;
  56. [Tooltip("Key used to drive Hold To Speak and Push To Speak methods" +
  57. " of microphone input control.")]
  58. public KeyCode micActivationKey = KeyCode.Space;
  59. [Tooltip("Will contain the string name of the selected microphone device - read only.")]
  60. public string selectedDevice;
  61. // PRIVATE MEMBERS
  62. private bool micSelected = false;
  63. private int minFreq, maxFreq;
  64. private bool focused = true;
  65. private bool initialized = false;
  66. //----------------------------------------------------
  67. // MONOBEHAVIOUR OVERRIDE FUNCTIONS
  68. //----------------------------------------------------
  69. /// <summary>
  70. /// Awake this instance.
  71. /// </summary>
  72. void Awake()
  73. {
  74. // First thing to do, cache the unity audio source (can be managed by the
  75. // user if audio source can change)
  76. if (!audioSource) audioSource = GetComponent<AudioSource>();
  77. if (!audioSource) return; // this should never happen
  78. }
  79. /// <summary>
  80. /// Start this instance.
  81. /// </summary>
  82. void Start()
  83. {
  84. audioSource.loop = true; // Set the AudioClip to loop
  85. audioSource.mute = false;
  86. InitializeMicrophone();
  87. }
  88. /// <summary>
  89. /// Initializes the microphone.
  90. /// </summary>
  91. private void InitializeMicrophone()
  92. {
  93. if (initialized)
  94. {
  95. return;
  96. }
  97. if (Microphone.devices.Length == 0)
  98. {
  99. return;
  100. }
  101. selectedDevice = Microphone.devices[0].ToString();
  102. micSelected = true;
  103. GetMicCaps();
  104. initialized = true;
  105. }
  106. /// <summary>
  107. /// Update this instance.
  108. /// </summary>
  109. void Update()
  110. {
  111. if (!focused)
  112. {
  113. if (Microphone.IsRecording(selectedDevice))
  114. {
  115. StopMicrophone();
  116. }
  117. return;
  118. }
  119. if (!Application.isPlaying)
  120. {
  121. StopMicrophone();
  122. return;
  123. }
  124. // Lazy Microphone initialization (needed on Android)
  125. if (!initialized)
  126. {
  127. InitializeMicrophone();
  128. }
  129. audioSource.volume = (micInputVolume / 100);
  130. //Hold To Speak
  131. if (micControl == micActivation.HoldToSpeak)
  132. {
  133. if (Input.GetKey(micActivationKey))
  134. {
  135. if (!Microphone.IsRecording(selectedDevice))
  136. {
  137. StartMicrophone();
  138. }
  139. }
  140. else
  141. {
  142. if (Microphone.IsRecording(selectedDevice))
  143. {
  144. StopMicrophone();
  145. }
  146. }
  147. }
  148. //Push To Talk
  149. if (micControl == micActivation.PushToSpeak)
  150. {
  151. if (Input.GetKeyDown(micActivationKey))
  152. {
  153. if (Microphone.IsRecording(selectedDevice))
  154. {
  155. StopMicrophone();
  156. }
  157. else if (!Microphone.IsRecording(selectedDevice))
  158. {
  159. StartMicrophone();
  160. }
  161. }
  162. }
  163. //Constant Speak
  164. if (micControl == micActivation.ConstantSpeak)
  165. {
  166. if (!Microphone.IsRecording(selectedDevice))
  167. {
  168. StartMicrophone();
  169. }
  170. }
  171. //Mic Selected = False
  172. if (enableMicSelectionGUI)
  173. {
  174. if (Input.GetKeyDown(micSelectionGUIKey))
  175. {
  176. micSelected = false;
  177. }
  178. }
  179. }
  180. /// <summary>
  181. /// Raises the application focus event.
  182. /// </summary>
  183. /// <param name="focus">If set to <c>true</c>: focused.</param>
  184. void OnApplicationFocus(bool focus)
  185. {
  186. focused = focus;
  187. if (!focused)
  188. StopMicrophone();
  189. }
  190. /// <summary>
  191. /// Raises the application pause event.
  192. /// </summary>
  193. /// <param name="pauseStatus">If set to <c>true</c>: paused.</param>
  194. void OnApplicationPause(bool pauseStatus)
  195. {
  196. focused = !pauseStatus;
  197. if (!focused)
  198. StopMicrophone();
  199. }
  200. void OnDisable()
  201. {
  202. StopMicrophone();
  203. }
  204. /// <summary>
  205. /// Raises the GU event.
  206. /// </summary>
  207. void OnGUI()
  208. {
  209. MicDeviceGUI((Screen.width / 2) - 150, (Screen.height / 2) - 75, 300, 50, 10, -300);
  210. }
  211. //----------------------------------------------------
  212. // PUBLIC FUNCTIONS
  213. //----------------------------------------------------
  214. /// <summary>
  215. /// Mics the device GU.
  216. /// </summary>
  217. /// <param name="left">Left.</param>
  218. /// <param name="top">Top.</param>
  219. /// <param name="width">Width.</param>
  220. /// <param name="height">Height.</param>
  221. /// <param name="buttonSpaceTop">Button space top.</param>
  222. /// <param name="buttonSpaceLeft">Button space left.</param>
  223. public void MicDeviceGUI(
  224. float left,
  225. float top,
  226. float width,
  227. float height,
  228. float buttonSpaceTop,
  229. float buttonSpaceLeft)
  230. {
  231. //If there is more than one device, choose one.
  232. if (Microphone.devices.Length >= 1 && enableMicSelectionGUI == true && micSelected == false)
  233. {
  234. for (int i = 0; i < Microphone.devices.Length; ++i)
  235. {
  236. if (GUI.Button(new Rect(left + ((width + buttonSpaceLeft) * i),
  237. top + ((height + buttonSpaceTop) * i), width, height),
  238. Microphone.devices[i].ToString()))
  239. {
  240. StopMicrophone();
  241. selectedDevice = Microphone.devices[i].ToString();
  242. micSelected = true;
  243. GetMicCaps();
  244. StartMicrophone();
  245. }
  246. }
  247. }
  248. }
  249. /// <summary>
  250. /// Gets the mic caps.
  251. /// </summary>
  252. public void GetMicCaps()
  253. {
  254. if (micSelected == false) return;
  255. //Gets the frequency of the device
  256. Microphone.GetDeviceCaps(selectedDevice, out minFreq, out maxFreq);
  257. if (minFreq == 0 && maxFreq == 0)
  258. {
  259. Debug.LogWarning("GetMicCaps warning:: min and max frequencies are 0");
  260. minFreq = 44100;
  261. maxFreq = 44100;
  262. }
  263. if (micFrequency > maxFreq)
  264. micFrequency = maxFreq;
  265. }
  266. /// <summary>
  267. /// Starts the microphone.
  268. /// </summary>
  269. public void StartMicrophone()
  270. {
  271. if (micSelected == false) return;
  272. //Starts recording
  273. audioSource.clip = Microphone.Start(selectedDevice, true, 1, micFrequency);
  274. Stopwatch timer = Stopwatch.StartNew();
  275. // Wait until the recording has started
  276. while (!(Microphone.GetPosition(selectedDevice) > 0) && timer.Elapsed.TotalMilliseconds < 1000) {
  277. Thread.Sleep(50);
  278. }
  279. if (Microphone.GetPosition(selectedDevice) <= 0)
  280. {
  281. throw new Exception("Timeout initializing microphone " + selectedDevice);
  282. }
  283. // Play the audio source
  284. audioSource.Play();
  285. }
  286. /// <summary>
  287. /// Stops the microphone.
  288. /// </summary>
  289. public void StopMicrophone()
  290. {
  291. if (micSelected == false) return;
  292. // Overriden with a clip to play? Don't stop the audio source
  293. if ((audioSource != null) &&
  294. (audioSource.clip != null) &&
  295. (audioSource.clip.name == "Microphone"))
  296. {
  297. audioSource.Stop();
  298. }
  299. // Reset to stop mouth movement
  300. OVRLipSyncContext context = GetComponent<OVRLipSyncContext>();
  301. context.ResetContext();
  302. Microphone.End(selectedDevice);
  303. }
  304. //----------------------------------------------------
  305. // PRIVATE FUNCTIONS
  306. //----------------------------------------------------
  307. /// <summary>
  308. /// Gets the averaged volume.
  309. /// </summary>
  310. /// <returns>The averaged volume.</returns>
  311. float GetAveragedVolume()
  312. {
  313. // We will use the SR to get average volume
  314. // return OVRSpeechRec.GetAverageVolume();
  315. return 0.0f;
  316. }
  317. }