123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374 |
- /************************************************************************************
- Filename : OVRLipSyncMicInput.cs
- Content : Interface to microphone input
- Created : May 12, 2015
- Copyright : Copyright Facebook Technologies, LLC and its affiliates.
- All rights reserved.
- Licensed under the Oculus Audio SDK License Version 3.3 (the "License");
- you may not use the Oculus Audio SDK except in compliance with the License,
- which is provided at the time of installation or download, or which
- otherwise accompanies this software in either electronic or hard copy form.
- You may obtain a copy of the License at
- https://developer.oculus.com/licenses/audio-3.3/
- Unless required by applicable law or agreed to in writing, the Oculus Audio SDK
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ************************************************************************************/
- using System;
- using UnityEngine;
- using System.Diagnostics;
- using Debug = UnityEngine.Debug;
- using System.Threading;
- [RequireComponent(typeof(AudioSource))]
- public class OVRLipSyncMicInput : MonoBehaviour
- {
- public enum micActivation
- {
- HoldToSpeak,
- PushToSpeak,
- ConstantSpeak
- }
- // PUBLIC MEMBERS
- [Tooltip("Manual specification of Audio Source - " +
- "by default will use any attached to the same object.")]
- public AudioSource audioSource = null;
- [Tooltip("Enable a keypress to toggle the microphone device selection GUI.")]
- public bool enableMicSelectionGUI = false;
- [Tooltip("Key to toggle the microphone selection GUI if enabled.")]
- public KeyCode micSelectionGUIKey = KeyCode.M;
- [SerializeField]
- [Range(0.0f, 100.0f)]
- [Tooltip("Microphone input volume control.")]
- private float micInputVolume = 100;
- [SerializeField]
- [Tooltip("Requested microphone input frequency")]
- private int micFrequency = 48000;
- public float MicFrequency
- {
- get { return micFrequency; }
- set { micFrequency = (int)Mathf.Clamp((float)value, 0, 96000); }
- }
- [Tooltip("Microphone input control method. Hold To Speak and Push" +
- " To Speak are driven with the Mic Activation Key.")]
- public micActivation micControl = micActivation.ConstantSpeak;
- [Tooltip("Key used to drive Hold To Speak and Push To Speak methods" +
- " of microphone input control.")]
- public KeyCode micActivationKey = KeyCode.Space;
- [Tooltip("Will contain the string name of the selected microphone device - read only.")]
- public string selectedDevice;
- // PRIVATE MEMBERS
- private bool micSelected = false;
- private int minFreq, maxFreq;
- private bool focused = true;
- private bool initialized = false;
- //----------------------------------------------------
- // MONOBEHAVIOUR OVERRIDE FUNCTIONS
- //----------------------------------------------------
- /// <summary>
- /// Awake this instance.
- /// </summary>
- void Awake()
- {
- // First thing to do, cache the unity audio source (can be managed by the
- // user if audio source can change)
- if (!audioSource) audioSource = GetComponent<AudioSource>();
- if (!audioSource) return; // this should never happen
- }
- /// <summary>
- /// Start this instance.
- /// </summary>
- void Start()
- {
- audioSource.loop = true; // Set the AudioClip to loop
- audioSource.mute = false;
- InitializeMicrophone();
- }
- /// <summary>
- /// Initializes the microphone.
- /// </summary>
- ///
- private void InitializeMicrophone()
- {
- if (initialized)
- {
- return;
- }
- if (Microphone.devices.Length == 0)
- {
- return;
- }
- selectedDevice = Microphone.devices[0].ToString();
- micSelected = true;
- GetMicCaps();
- initialized = true;
- }
- /// <summary>
- /// Update this instance.
- /// </summary>
- void Update()
- {
- if (!focused)
- {
- if (Microphone.IsRecording(selectedDevice))
- {
- StopMicrophone();
- }
- return;
- }
- if (!Application.isPlaying)
- {
- StopMicrophone();
- return;
- }
- // Lazy Microphone initialization (needed on Android)
- if (!initialized)
- {
- InitializeMicrophone();
- }
- audioSource.volume = (micInputVolume / 100);
- //Hold To Speak
- if (micControl == micActivation.HoldToSpeak)
- {
- if (Input.GetKey(micActivationKey))
- {
- if (!Microphone.IsRecording(selectedDevice))
- {
- StartMicrophone();
- }
- }
- else
- {
- if (Microphone.IsRecording(selectedDevice))
- {
- StopMicrophone();
- }
- }
- }
- //Push To Talk
- if (micControl == micActivation.PushToSpeak)
- {
- if (Input.GetKeyDown(micActivationKey))
- {
- if (Microphone.IsRecording(selectedDevice))
- {
- StopMicrophone();
- }
- else if (!Microphone.IsRecording(selectedDevice))
- {
- StartMicrophone();
- }
- }
- }
- //Constant Speak
- if (micControl == micActivation.ConstantSpeak)
- {
- if (!Microphone.IsRecording(selectedDevice))
- {
- StartMicrophone();
- }
- }
- //Mic Selected = False
- if (enableMicSelectionGUI)
- {
- if (Input.GetKeyDown(micSelectionGUIKey))
- {
- micSelected = false;
- }
- }
- }
- /// <summary>
- /// Raises the application focus event.
- /// </summary>
- /// <param name="focus">If set to <c>true</c>: focused.</param>
- void OnApplicationFocus(bool focus)
- {
- focused = focus;
- if (!focused)
- StopMicrophone();
- }
- /// <summary>
- /// Raises the application pause event.
- /// </summary>
- /// <param name="pauseStatus">If set to <c>true</c>: paused.</param>
- void OnApplicationPause(bool pauseStatus)
- {
- focused = !pauseStatus;
- if (!focused)
- StopMicrophone();
- }
- void OnDisable()
- {
- StopMicrophone();
- }
- /// <summary>
- /// Raises the GU event.
- /// </summary>
- void OnGUI()
- {
- MicDeviceGUI((Screen.width / 2) - 150, (Screen.height / 2) - 75, 300, 50, 10, -300);
- }
- //----------------------------------------------------
- // PUBLIC FUNCTIONS
- //----------------------------------------------------
- /// <summary>
- /// Mics the device GU.
- /// </summary>
- /// <param name="left">Left.</param>
- /// <param name="top">Top.</param>
- /// <param name="width">Width.</param>
- /// <param name="height">Height.</param>
- /// <param name="buttonSpaceTop">Button space top.</param>
- /// <param name="buttonSpaceLeft">Button space left.</param>
- public void MicDeviceGUI(
- float left,
- float top,
- float width,
- float height,
- float buttonSpaceTop,
- float buttonSpaceLeft)
- {
- //If there is more than one device, choose one.
- if (Microphone.devices.Length >= 1 && enableMicSelectionGUI == true && micSelected == false)
- {
- for (int i = 0; i < Microphone.devices.Length; ++i)
- {
- if (GUI.Button(new Rect(left + ((width + buttonSpaceLeft) * i),
- top + ((height + buttonSpaceTop) * i), width, height),
- Microphone.devices[i].ToString()))
- {
- StopMicrophone();
- selectedDevice = Microphone.devices[i].ToString();
- micSelected = true;
- GetMicCaps();
- StartMicrophone();
- }
- }
- }
- }
- /// <summary>
- /// Gets the mic caps.
- /// </summary>
- public void GetMicCaps()
- {
- if (micSelected == false) return;
- //Gets the frequency of the device
- Microphone.GetDeviceCaps(selectedDevice, out minFreq, out maxFreq);
- if (minFreq == 0 && maxFreq == 0)
- {
- Debug.LogWarning("GetMicCaps warning:: min and max frequencies are 0");
- minFreq = 44100;
- maxFreq = 44100;
- }
- if (micFrequency > maxFreq)
- micFrequency = maxFreq;
- }
- /// <summary>
- /// Starts the microphone.
- /// </summary>
- public void StartMicrophone()
- {
- if (micSelected == false) return;
- //Starts recording
- audioSource.clip = Microphone.Start(selectedDevice, true, 1, micFrequency);
- Stopwatch timer = Stopwatch.StartNew();
- // Wait until the recording has started
- while (!(Microphone.GetPosition(selectedDevice) > 0) && timer.Elapsed.TotalMilliseconds < 1000) {
- Thread.Sleep(50);
- }
- if (Microphone.GetPosition(selectedDevice) <= 0)
- {
- throw new Exception("Timeout initializing microphone " + selectedDevice);
- }
- // Play the audio source
- audioSource.Play();
- }
- /// <summary>
- /// Stops the microphone.
- /// </summary>
- public void StopMicrophone()
- {
- if (micSelected == false) return;
- // Overriden with a clip to play? Don't stop the audio source
- if ((audioSource != null) &&
- (audioSource.clip != null) &&
- (audioSource.clip.name == "Microphone"))
- {
- audioSource.Stop();
- }
- // Reset to stop mouth movement
- OVRLipSyncContext context = GetComponent<OVRLipSyncContext>();
- context.ResetContext();
- Microphone.End(selectedDevice);
- }
- //----------------------------------------------------
- // PRIVATE FUNCTIONS
- //----------------------------------------------------
- /// <summary>
- /// Gets the averaged volume.
- /// </summary>
- /// <returns>The averaged volume.</returns>
- float GetAveragedVolume()
- {
- // We will use the SR to get average volume
- // return OVRSpeechRec.GetAverageVolume();
- return 0.0f;
- }
- }
|