123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391 |
- /************************************************************************************
- Filename : OVRLipSyncContext.cs
- Content : Interface to Oculus Lip-Sync engine
- Created : August 6th, 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 UnityEngine;
- [RequireComponent(typeof(AudioSource))]
- //-------------------------------------------------------------------------------------
- // ***** OVRLipSyncContext
- //
- /// <summary>
- /// OVRLipSyncContext interfaces into the Oculus phoneme recognizer.
- /// This component should be added into the scene once for each Audio Source.
- ///
- /// </summary>
- public class OVRLipSyncContext : OVRLipSyncContextBase
- {
- // * * * * * * * * * * * * *
- // Public members
- [Tooltip("Allow capturing of keyboard input to control operation.")]
- public bool enableKeyboardInput = false;
- [Tooltip("Register a mouse/touch callback to control loopback and gain (requires script restart).")]
- public bool enableTouchInput = false;
- [Tooltip("Play input audio back through audio output.")]
- public bool audioLoopback = false;
- [Tooltip("Key to toggle audio loopback.")]
- public KeyCode loopbackKey = KeyCode.L;
- [Tooltip("Show viseme scores in an OVRLipSyncDebugConsole display.")]
- public bool showVisemes = false;
- [Tooltip("Key to toggle viseme score display.")]
- public KeyCode debugVisemesKey = KeyCode.D;
- [Tooltip("Skip data from the Audio Source. Use if you intend to pass audio data in manually.")]
- public bool skipAudioSource = false;
- [Tooltip("Adjust the linear audio gain multiplier before processing lipsync")]
- public float gain = 1.0f;
- private bool hasDebugConsole = false;
- public KeyCode debugLaughterKey = KeyCode.H;
- public bool showLaughter = false;
- public float laughterScore = 0.0f;
- // * * * * * * * * * * * * *
- // Private members
- /// <summary>
- /// Start this instance.
- /// Note: make sure to always have a Start function for classes that have editor scripts.
- /// </summary>
- void Start()
- {
- // Add a listener to the OVRTouchpad for touch events
- if (enableTouchInput)
- {
- OVRTouchpad.AddListener(LocalTouchEventCallback);
- }
- // Find console
- OVRLipSyncDebugConsole[] consoles = FindObjectsOfType<OVRLipSyncDebugConsole>();
- if (consoles.Length > 0)
- {
- hasDebugConsole = consoles[0];
- }
- }
- /// <summary>
- /// Handle keyboard input
- /// </summary>
- void HandleKeyboard()
- {
- // Turn loopback on/off
- if (Input.GetKeyDown(loopbackKey))
- {
- ToggleAudioLoopback();
- }
- else if (Input.GetKeyDown(debugVisemesKey))
- {
- showVisemes = !showVisemes;
- if (showVisemes)
- {
- if (hasDebugConsole)
- {
- Debug.Log("DEBUG SHOW VISEMES: ENABLED");
- }
- else
- {
- Debug.LogWarning("Warning: No OVRLipSyncDebugConsole in the scene!");
- showVisemes = false;
- }
- }
- else
- {
- if (hasDebugConsole)
- {
- OVRLipSyncDebugConsole.Clear();
- }
- Debug.Log("DEBUG SHOW VISEMES: DISABLED");
- }
- }
- else if (Input.GetKeyDown(debugLaughterKey))
- {
- showLaughter = !showLaughter;
- if (showLaughter)
- {
- if (hasDebugConsole)
- {
- Debug.Log("DEBUG SHOW LAUGHTER: ENABLED");
- }
- else
- {
- Debug.LogWarning("Warning: No OVRLipSyncDebugConsole in the scene!");
- showLaughter = false;
- }
- }
- else
- {
- if (hasDebugConsole)
- {
- OVRLipSyncDebugConsole.Clear();
- }
- Debug.Log("DEBUG SHOW LAUGHTER: DISABLED");
- }
- }
- else if (Input.GetKeyDown(KeyCode.LeftArrow))
- {
- gain -= 1.0f;
- if (gain < 1.0f) gain = 1.0f;
- string g = "LINEAR GAIN: ";
- g += gain;
- if (hasDebugConsole)
- {
- OVRLipSyncDebugConsole.Clear();
- OVRLipSyncDebugConsole.Log(g);
- OVRLipSyncDebugConsole.ClearTimeout(1.5f);
- }
- }
- else if (Input.GetKeyDown(KeyCode.RightArrow))
- {
- gain += 1.0f;
- if (gain > 15.0f)
- gain = 15.0f;
- string g = "LINEAR GAIN: ";
- g += gain;
- if (hasDebugConsole)
- {
- OVRLipSyncDebugConsole.Clear();
- OVRLipSyncDebugConsole.Log(g);
- OVRLipSyncDebugConsole.ClearTimeout(1.5f);
- }
- }
- }
- /// <summary>
- /// Run processes that need to be updated in our game thread
- /// </summary>
- void Update()
- {
- if (enableKeyboardInput)
- {
- HandleKeyboard();
- }
- laughterScore = this.Frame.laughterScore;
- DebugShowVisemesAndLaughter();
- }
- /// <summary>
- /// Preprocess F32 PCM audio buffer
- /// </summary>
- /// <param name="data">Data.</param>
- /// <param name="channels">Channels.</param>
- public void PreprocessAudioSamples(float[] data, int channels)
- {
- // Increase the gain of the input
- for (int i = 0; i < data.Length; ++i)
- {
- data[i] = data[i] * gain;
- }
- }
- /// <summary>
- /// Postprocess F32 PCM audio buffer
- /// </summary>
- /// <param name="data">Data.</param>
- /// <param name="channels">Channels.</param>
- public void PostprocessAudioSamples(float[] data, int channels)
- {
- // Turn off output (so that we don't get feedback from mics too close to speakers)
- if (!audioLoopback)
- {
- for (int i = 0; i < data.Length; ++i)
- data[i] = data[i] * 0.0f;
- }
- }
- /// <summary>
- /// Pass F32 PCM audio buffer to the lip sync module
- /// </summary>
- /// <param name="data">Data.</param>
- /// <param name="channels">Channels.</param>
- public void ProcessAudioSamplesRaw(float[] data, int channels)
- {
- // Send data into Phoneme context for processing (if context is not 0)
- lock (this)
- {
- if (Context == 0 || OVRLipSync.IsInitialized() != OVRLipSync.Result.Success)
- {
- return;
- }
- var frame = this.Frame;
- OVRLipSync.ProcessFrame(Context, data, frame, channels == 2);
- }
- }
- /// <summary>
- /// Pass S16 PCM audio buffer to the lip sync module
- /// </summary>
- /// <param name="data">Data.</param>
- /// <param name="channels">Channels.</param>
- public void ProcessAudioSamplesRaw(short[] data, int channels)
- {
- // Send data into Phoneme context for processing (if context is not 0)
- lock (this)
- {
- if (Context == 0 || OVRLipSync.IsInitialized() != OVRLipSync.Result.Success)
- {
- return;
- }
- var frame = this.Frame;
- OVRLipSync.ProcessFrame(Context, data, frame, channels == 2);
- }
- }
- /// <summary>
- /// Process F32 audio sample and pass it to the lip sync module for computation
- /// </summary>
- /// <param name="data">Data.</param>
- /// <param name="channels">Channels.</param>
- public void ProcessAudioSamples(float[] data, int channels)
- {
- // Do not process if we are not initialized, or if there is no
- // audio source attached to game object
- if ((OVRLipSync.IsInitialized() != OVRLipSync.Result.Success) || audioSource == null)
- {
- return;
- }
- PreprocessAudioSamples(data, channels);
- ProcessAudioSamplesRaw(data, channels);
- PostprocessAudioSamples(data, channels);
- }
- /// <summary>
- /// Raises the audio filter read event.
- /// </summary>
- /// <param name="data">Data.</param>
- /// <param name="channels">Channels.</param>
- void OnAudioFilterRead(float[] data, int channels)
- {
- if (!skipAudioSource)
- {
- ProcessAudioSamples(data, channels);
- }
- }
- /// <summary>
- /// Print the visemes and laughter score to game window
- /// </summary>
- void DebugShowVisemesAndLaughter()
- {
- if (hasDebugConsole)
- {
- string seq = "";
- if (showLaughter)
- {
- seq += "Laughter:";
- int count = (int)(50.0f * this.Frame.laughterScore);
- for (int c = 0; c < count; c++)
- seq += "*";
- seq += "\n";
- }
- if (showVisemes)
- {
- for (int i = 0; i < this.Frame.Visemes.Length; i++)
- {
- seq += ((OVRLipSync.Viseme)i).ToString();
- seq += ":";
- int count = (int)(50.0f * this.Frame.Visemes[i]);
- for (int c = 0; c < count; c++)
- seq += "*";
- seq += "\n";
- }
- }
- OVRLipSyncDebugConsole.Clear();
- if (seq != "")
- {
- OVRLipSyncDebugConsole.Log(seq);
- }
- }
- }
- void ToggleAudioLoopback()
- {
- audioLoopback = !audioLoopback;
- if (hasDebugConsole)
- {
- OVRLipSyncDebugConsole.Clear();
- OVRLipSyncDebugConsole.ClearTimeout(1.5f);
- if (audioLoopback)
- OVRLipSyncDebugConsole.Log("LOOPBACK MODE: ENABLED");
- else
- OVRLipSyncDebugConsole.Log("LOOPBACK MODE: DISABLED");
- }
- }
- // LocalTouchEventCallback
- void LocalTouchEventCallback(OVRTouchpad.TouchEvent touchEvent)
- {
- string g = "LINEAR GAIN: ";
- switch (touchEvent)
- {
- case (OVRTouchpad.TouchEvent.SingleTap):
- ToggleAudioLoopback();
- break;
- case (OVRTouchpad.TouchEvent.Up):
- gain += 1.0f;
- if (gain > 15.0f)
- gain = 15.0f;
- g += gain;
- if (hasDebugConsole)
- {
- OVRLipSyncDebugConsole.Clear();
- OVRLipSyncDebugConsole.Log(g);
- OVRLipSyncDebugConsole.ClearTimeout(1.5f);
- }
- break;
- case (OVRTouchpad.TouchEvent.Down):
- gain -= 1.0f;
- if (gain < 1.0f) gain = 1.0f;
- g += gain;
- if (hasDebugConsole)
- {
- OVRLipSyncDebugConsole.Clear();
- OVRLipSyncDebugConsole.Log(g);
- OVRLipSyncDebugConsole.ClearTimeout(1.5f);
- }
- break;
- }
- }
- }
|