Initial Commit
This commit is contained in:
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Meta.WitAi;
|
||||
using Meta.WitAi.Data;
|
||||
using Meta.WitAi.Interfaces;
|
||||
using UnityEngine;
|
||||
|
||||
public class AudioClipAudioSource : MonoBehaviour, IAudioInputSource
|
||||
{
|
||||
[SerializeField] private AudioSource _audioSource;
|
||||
[SerializeField] private List<AudioClip> _audioClips;
|
||||
[Tooltip("If true, the associated clips will be played again from the beginning with multiple requests after the clip queue has been exhausted.")]
|
||||
[SerializeField] private bool _loopRequests;
|
||||
|
||||
private bool _isRecording;
|
||||
|
||||
private Queue<int> _audioQueue = new Queue<int>();
|
||||
private int clipIndex = 0;
|
||||
private float[] activeClip;
|
||||
private int activeClipIndex;
|
||||
private float[] activeClipBuffer = new float[0];
|
||||
|
||||
private List<float[]> clipData = new List<float[]>();
|
||||
|
||||
private void Start()
|
||||
{
|
||||
foreach (var clip in _audioClips)
|
||||
{
|
||||
AddClipData(clip);
|
||||
VLog.D($"Added {clip.name} to queue");
|
||||
}
|
||||
}
|
||||
|
||||
private void SendSample(float[] sample)
|
||||
{
|
||||
var len = Math.Min(_audioQueue.Dequeue(), activeClip.Length - activeClipIndex);
|
||||
|
||||
try
|
||||
{
|
||||
VLog.D("Sending length: " + len);
|
||||
activeClipBuffer = new float[len];
|
||||
Array.Copy(activeClip, activeClipIndex, activeClipBuffer, 0, len);
|
||||
activeClipIndex += len;
|
||||
}
|
||||
catch (ArgumentException e)
|
||||
{
|
||||
VLog.D(e);
|
||||
}
|
||||
|
||||
var max = float.MinValue;
|
||||
foreach (var f in activeClipBuffer)
|
||||
{
|
||||
max = Mathf.Max(f, max);
|
||||
}
|
||||
|
||||
OnSampleReady?.Invoke(activeClipBuffer.Length, activeClipBuffer, max);
|
||||
}
|
||||
|
||||
public event Action OnStartRecording;
|
||||
public event Action OnStartRecordingFailed;
|
||||
public event Action<int, float[], float> OnSampleReady;
|
||||
public event Action OnStopRecording;
|
||||
public void StartRecording(int sampleLen)
|
||||
{
|
||||
if (_isRecording)
|
||||
{
|
||||
OnStartRecordingFailed?.Invoke();
|
||||
return;
|
||||
}
|
||||
_isRecording = true;
|
||||
if (clipIndex >= _audioClips.Count && _loopRequests)
|
||||
{
|
||||
clipIndex = 0;
|
||||
}
|
||||
if (clipIndex < _audioClips.Count)
|
||||
{
|
||||
activeClip = clipData[clipIndex];
|
||||
activeClipIndex = 0;
|
||||
VLog.D($"Starting clip {clipIndex}");
|
||||
_isRecording = true;
|
||||
VLog.D($"Playing {_audioClips[clipIndex].name}");
|
||||
_audioSource.PlayOneShot(_audioClips[clipIndex]);
|
||||
StartCoroutine(ProcessClip(_audioClips[clipIndex], clipData[clipIndex]));
|
||||
OnStartRecording?.Invoke();
|
||||
}
|
||||
else
|
||||
{
|
||||
OnStartRecordingFailed?.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator ProcessClip(AudioClip clip, float[] clipData)
|
||||
{
|
||||
int chunkSize = 0;
|
||||
for (int index = 0; index < clipData.Length; index += chunkSize)
|
||||
{
|
||||
chunkSize = (int) (16000 * Time.deltaTime);
|
||||
int len = Math.Min(chunkSize, clipData.Length - index);
|
||||
var data = new float[chunkSize];
|
||||
Array.Copy(clipData, index, data, 0, len);
|
||||
|
||||
var max = float.MinValue;
|
||||
foreach (var f in data)
|
||||
{
|
||||
max = Mathf.Max(f, max);
|
||||
}
|
||||
|
||||
VLog.D($"Sending {index}/{clipData.Length} [{data.Length}] samples with a max volume of {max}");
|
||||
OnSampleReady?.Invoke(data.Length, data, max);
|
||||
yield return null;
|
||||
}
|
||||
StopRecording();
|
||||
clipIndex++;
|
||||
}
|
||||
|
||||
public void StopRecording()
|
||||
{
|
||||
_isRecording = false;
|
||||
OnStopRecording?.Invoke();
|
||||
}
|
||||
|
||||
public bool IsRecording => _isRecording;
|
||||
|
||||
public AudioEncoding AudioEncoding => new AudioEncoding();
|
||||
public bool IsInputAvailable => true;
|
||||
public void CheckForInput()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public bool SetActiveClip(string clipName)
|
||||
{
|
||||
int index = _audioClips.FindIndex(0, (AudioClip clip) => {
|
||||
if (clip.name == clipName)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
if (index < 0 || index >= _audioClips.Count)
|
||||
{
|
||||
VLog.D($"Couldn't find clip {clipName}");
|
||||
return false;
|
||||
}
|
||||
|
||||
clipIndex = index;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void AddClip(AudioClip clip)
|
||||
{
|
||||
_audioClips.Add(clip);
|
||||
AddClipData(clip);
|
||||
VLog.D($"Clip added {clip.name}");
|
||||
}
|
||||
|
||||
private void AddClipData(AudioClip clip)
|
||||
{
|
||||
var samples = new float[clip.samples];
|
||||
clip.GetData(samples, 0);
|
||||
clipData.Add(samples);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4b79645f07e0044b397f62aa9d6cbce7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Meta.WitAi.Utilities
|
||||
{
|
||||
public class DictionaryList<T, U>
|
||||
{
|
||||
private Dictionary<T, List<U>> dictionary = new Dictionary<T, List<U>>();
|
||||
|
||||
public void Add(T key, U value)
|
||||
{
|
||||
if (!TryGetValue(key, out var values))
|
||||
{
|
||||
dictionary[key] = values;
|
||||
}
|
||||
values.Add(value);
|
||||
}
|
||||
|
||||
public void RemoveAt(T key, int index)
|
||||
{
|
||||
if (TryGetValue(key, out var values)) values.RemoveAt(index);
|
||||
}
|
||||
|
||||
public void Remove(T key, U value)
|
||||
{
|
||||
if (TryGetValue(key, out var values)) values.Remove(value);
|
||||
}
|
||||
|
||||
#region Getters
|
||||
public List<U> this[T key]
|
||||
{
|
||||
get
|
||||
{
|
||||
List<U> values;
|
||||
if (!TryGetValue(key, out values))
|
||||
{
|
||||
values = new List<U>();
|
||||
dictionary[key] = values;
|
||||
}
|
||||
return values;
|
||||
}
|
||||
set => dictionary[key] = value;
|
||||
}
|
||||
|
||||
public bool TryGetValue(T key, out List<U> values)
|
||||
{
|
||||
if (!dictionary.TryGetValue(key, out values))
|
||||
{
|
||||
values = new List<U>();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bdab2e04b3d44a0c8abfa43a51c2dba6
|
||||
timeCreated: 1646061057
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace Meta.WitAi.Utilities
|
||||
{
|
||||
public class DynamicRangeAttribute : PropertyAttribute
|
||||
{
|
||||
public string RangeProperty { get; private set; }
|
||||
public float DefaultMin { get; private set; }
|
||||
public float DefaultMax { get; private set; }
|
||||
|
||||
public DynamicRangeAttribute(string rangeProperty, float defaultMin = float.MinValue, float defaultMax = float.MaxValue)
|
||||
{
|
||||
DefaultMin = defaultMin;
|
||||
DefaultMax = defaultMax;
|
||||
RangeProperty = rangeProperty;
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ebe9cc040d3f14698b96d8e5d7155c44
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using Meta.WitAi.Attributes;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.Serialization;
|
||||
using Utilities;
|
||||
|
||||
namespace Meta.WitAi.Utilities
|
||||
{
|
||||
[AddComponentMenu("Wit.ai/Utilities/Conversions/Float to String")]
|
||||
public class FloatToStringEvent : MonoBehaviour
|
||||
{
|
||||
[FormerlySerializedAs("format")]
|
||||
[Tooltip("The format value to be used on the float")]
|
||||
[SerializeField] private string _floatFormat;
|
||||
[Tooltip("The format of the string itself. {0} will represent the float value provided")]
|
||||
[SerializeField] private string _stringFormat;
|
||||
|
||||
[Space(WitRuntimeStyles.HeaderPaddingTop)]
|
||||
[TooltipBox("Triggered when ConvertFloatToString(float) is called. The string in this event will be formatted based on the format fields.")]
|
||||
[SerializeField] private StringEvent onFloatToString = new StringEvent();
|
||||
|
||||
/// <summary>
|
||||
/// Converts a float to a string using the component format values and emits an onFloatToString event.
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public void ConvertFloatToString(float value)
|
||||
{
|
||||
string floatStringValue;
|
||||
if (string.IsNullOrEmpty(_floatFormat))
|
||||
{
|
||||
floatStringValue = value.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
floatStringValue = value.ToString(_floatFormat);
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(_stringFormat))
|
||||
{
|
||||
onFloatToString?.Invoke(floatStringValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
onFloatToString?.Invoke(string.Format(_stringFormat, floatStringValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class StringEvent : UnityEvent<string> {}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c63293fa01c74b159135d721528a5c47
|
||||
timeCreated: 1626731148
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace Meta.WitAi.Utilities
|
||||
{
|
||||
public static class GameObjectSearchUtility
|
||||
{
|
||||
/// <summary>
|
||||
/// Finds the first available scene scripts of a specific object type
|
||||
/// </summary>
|
||||
/// <param name="includeInactive">Whether inactive GameObjects should be searched</param>
|
||||
/// <typeparam name="T">Script type being searched</typeparam>
|
||||
/// <returns>The first found script matching the specified type</returns>
|
||||
public static T FindSceneObject<T>(bool includeInactive = true) where T : UnityEngine.Object
|
||||
{
|
||||
T[] results = FindSceneObjects<T>(includeInactive, true);
|
||||
return results == null || results.Length == 0 ? null : results[0];
|
||||
}
|
||||
/// <summary>
|
||||
/// Finds all scene scripts of a specific object type
|
||||
/// </summary>
|
||||
/// <param name="includeInactive">Whether inactive GameObjects should be searched</param>
|
||||
/// <param name="returnImmediately">Whether the method should return as soon as a matching script is found</param>
|
||||
/// <typeparam name="T">Script type being searched</typeparam>
|
||||
/// <returns>All scripts matching the specified type</returns>
|
||||
public static T[] FindSceneObjects<T>(bool includeInactive = true, bool returnImmediately = false) where T : UnityEngine.Object
|
||||
{
|
||||
// Use default functionality
|
||||
if (!includeInactive)
|
||||
{
|
||||
return GameObject.FindObjectsOfType<T>();
|
||||
}
|
||||
|
||||
// Get results
|
||||
List<T> results = new List<T>();
|
||||
|
||||
// Iterate loaded scenes
|
||||
for (int s = 0; s < SceneManager.sceneCount; s++)
|
||||
{
|
||||
// Iterate root
|
||||
foreach (var rootGameObject in SceneManager.GetSceneAt(s).GetRootGameObjects())
|
||||
{
|
||||
T[] children = rootGameObject.GetComponentsInChildren<T>(includeInactive);
|
||||
if (children != null && children.Length > 0)
|
||||
{
|
||||
results.AddRange(children);
|
||||
if (returnImmediately)
|
||||
{
|
||||
return results.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return all
|
||||
return results.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 56bfa5a57ef40774c8506e7cebc7c154
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Meta.WitAi.Utilities
|
||||
{
|
||||
public static class IOUtility
|
||||
{
|
||||
// Log error
|
||||
private static void LogError(string error)
|
||||
{
|
||||
VLog.E($"IO Utility - {error}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a directory recursively if desired and returns true if successful
|
||||
/// </summary>
|
||||
/// <param name="directoryPath">The directory to be created</param>
|
||||
/// <param name="recursively">Will traverse parent directories if needed</param>
|
||||
/// <returns>Returns true if the directory exists</returns>
|
||||
public static bool CreateDirectory(string directoryPath, bool recursively = true)
|
||||
{
|
||||
// Null
|
||||
if (string.IsNullOrEmpty(directoryPath))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Already exists
|
||||
if (Directory.Exists(directoryPath))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check parent
|
||||
if (recursively)
|
||||
{
|
||||
string parentDirectoryPath = Path.GetDirectoryName(directoryPath);
|
||||
if (!string.IsNullOrEmpty(parentDirectoryPath) && !CreateDirectory(parentDirectoryPath, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(directoryPath);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LogError($"Create Directory Exception\nDirectory Path: {directoryPath}\n{e}");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Successfully created
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes a directory and returns true if the directory no longer exists
|
||||
/// </summary>
|
||||
/// <param name="directoryPath">The directory to be created</param>
|
||||
/// <param name="forceIfFilled">Whether to force a deletion if the directory contains contents</param>
|
||||
/// <returns>Returns true if the directory does not exist</returns>
|
||||
public static bool DeleteDirectory(string directoryPath, bool forceIfFilled = true)
|
||||
{
|
||||
// Already gone
|
||||
if (!Directory.Exists(directoryPath))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Directory.Delete(directoryPath, forceIfFilled);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LogError($"Delete Directory Exception\nDirectory Path: {directoryPath}\n{e}");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Successfully deleted
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 61d1f1da493566e4db1372a37e97fc02
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using Meta.WitAi.Attributes;
|
||||
using UnityEngine;
|
||||
using Utilities;
|
||||
|
||||
namespace Meta.WitAi.Utilities
|
||||
{
|
||||
[AddComponentMenu("Wit.ai/Utilities/Conversions/String to String")]
|
||||
public class StringToStringEvent : MonoBehaviour
|
||||
{
|
||||
[Tooltip("The string format string that will be used to reformat input strings. Ex: I don't know how to respond to {0}")]
|
||||
[SerializeField] private string _format;
|
||||
|
||||
[Space(WitRuntimeStyles.HeaderPaddingTop)]
|
||||
[TooltipBox("Triggered when FormatString(float) is called. The string in this event will be formatted based on the format field.")]
|
||||
[SerializeField] public StringEvent onStringEvent = new StringEvent();
|
||||
|
||||
/// <summary>
|
||||
/// Trigger an onStringEvent with a provided format.
|
||||
/// </summary>
|
||||
/// <param name="format">The string format to use in the event</param>
|
||||
/// <param name="value">The value that will get populated in {0} in the format string.</param>
|
||||
public void FormatString(string format, string value)
|
||||
{
|
||||
if (string.IsNullOrEmpty(format))
|
||||
{
|
||||
onStringEvent?.Invoke(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
onStringEvent?.Invoke(string.Format(format, value));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Trigger an onStringEvent with the built in format value
|
||||
/// </summary>
|
||||
/// <param name="value">The text to insert into {0} in the format value.</param>
|
||||
public void FormatString(string value)
|
||||
{
|
||||
FormatString(_format, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cba129c809a34fc5a35b03548ee4efc7
|
||||
timeCreated: 1680109375
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using Meta.WitAi.Data;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Meta.WitAi.Lib
|
||||
{
|
||||
/// <summary>
|
||||
/// Applies the current Voice Mic mic output to an audio
|
||||
/// source clip for use with external lip sync scripts such
|
||||
/// as OVRAvatarLipSyncContext.
|
||||
/// </summary>
|
||||
public class VoiceLipSyncMic : MonoBehaviour
|
||||
{
|
||||
[Tooltip("Audio desired sample size for lipsync. The mic frequency will be adjusted to match this.")]
|
||||
public int AudioSampleRate = 48000;
|
||||
|
||||
[Tooltip("Manual specification of Audio Source. Default will use any attached to the same object.")]
|
||||
public AudioSource AudioSource;
|
||||
|
||||
// Obtain audio source & generate clip
|
||||
private void Awake()
|
||||
{
|
||||
// Setup audio source
|
||||
if (!AudioSource)
|
||||
{
|
||||
AudioSource = GetComponent<AudioSource>();
|
||||
if (!AudioSource)
|
||||
{
|
||||
AudioSource = gameObject.AddComponent<AudioSource>();
|
||||
}
|
||||
}
|
||||
AudioSource.loop = true;
|
||||
AudioSource.playOnAwake = false;
|
||||
if (AudioSource.isPlaying)
|
||||
{
|
||||
AudioSource.Stop();
|
||||
}
|
||||
|
||||
// Get mic from audio buffer & set sample rate
|
||||
if (AudioBuffer.Instance?.MicInput is Mic mic)
|
||||
{
|
||||
mic.AudioClipSampleRate = AudioSampleRate;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("VoiceMicLipSync only works with Mic script.");
|
||||
}
|
||||
}
|
||||
|
||||
// Enable audio buffer recording
|
||||
private void OnEnable()
|
||||
{
|
||||
// Get buffer
|
||||
AudioBuffer buffer = AudioBuffer.Instance;
|
||||
if (buffer == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Get mic from audio buffer & get audio clip
|
||||
if (AudioBuffer.Instance?.MicInput is Mic mic)
|
||||
{
|
||||
AudioSource.clip = mic.AudioClip;
|
||||
}
|
||||
buffer.Events.OnSampleReady += OnMicSampleReady;
|
||||
buffer.StartRecording(this);
|
||||
}
|
||||
|
||||
// Begin playback if possible
|
||||
private void OnMicSampleReady(RingBuffer<byte>.Marker marker, float levelMax)
|
||||
{
|
||||
if (!AudioSource.isPlaying && AudioSource.clip != null)
|
||||
{
|
||||
AudioSource.Play();
|
||||
}
|
||||
}
|
||||
|
||||
// Stop audio buffer recording
|
||||
private void OnDisable()
|
||||
{
|
||||
// Stop playback
|
||||
if (AudioSource.isPlaying)
|
||||
{
|
||||
AudioSource.Stop();
|
||||
}
|
||||
AudioSource.clip = null;
|
||||
|
||||
// Breakdown buffer
|
||||
AudioBuffer buffer = AudioBuffer.Instance;
|
||||
if (buffer == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
buffer.StopRecording(this);
|
||||
buffer.Events.OnSampleReady -= OnMicSampleReady;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 69e476f7fc7baaf46b09dc40dbfecd38
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
||||
namespace Meta.WitAi.Utilities
|
||||
{
|
||||
[Serializable]
|
||||
public struct VoiceServiceReference
|
||||
{
|
||||
[SerializeField] internal VoiceService voiceService;
|
||||
|
||||
public VoiceService VoiceService
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!voiceService)
|
||||
{
|
||||
VoiceService[] services = Resources.FindObjectsOfTypeAll<VoiceService>();
|
||||
if (services != null)
|
||||
{
|
||||
// Set as first instance that isn't a prefab
|
||||
voiceService = Array.Find(services, (o) => o.gameObject.scene.rootCount != 0);
|
||||
}
|
||||
}
|
||||
|
||||
return voiceService;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[CustomPropertyDrawer(typeof(VoiceServiceReference))]
|
||||
public class VoiceServiceReferenceDrawer : PropertyDrawer
|
||||
{
|
||||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
return EditorGUIUtility.singleLineHeight;
|
||||
}
|
||||
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
var refProp = property.FindPropertyRelative("voiceService");
|
||||
var reference = refProp.objectReferenceValue as VoiceService;
|
||||
var voiceServices = GameObject.FindObjectsOfType<VoiceService>();
|
||||
var voiceServiceNames = new string[voiceServices.Length + 1];
|
||||
int index = 0;
|
||||
voiceServiceNames[0] = "Autodetect";
|
||||
if (voiceServices.Length == 1)
|
||||
{
|
||||
voiceServiceNames[0] = $"{voiceServiceNames[0]} - {voiceServices[0].name}";
|
||||
}
|
||||
for (int i = 0; i < voiceServices.Length; i++)
|
||||
{
|
||||
voiceServiceNames[i + 1] = voiceServices[i].name;
|
||||
if (voiceServices[i] == reference)
|
||||
{
|
||||
index = i + 1;
|
||||
}
|
||||
}
|
||||
EditorGUI.BeginProperty(position, label, property);
|
||||
var updatedIndex = EditorGUI.Popup(position, index, voiceServiceNames);
|
||||
if (index != updatedIndex)
|
||||
{
|
||||
if (updatedIndex > 0)
|
||||
{
|
||||
refProp.objectReferenceValue = voiceServices[updatedIndex - 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
refProp.objectReferenceValue = null;
|
||||
}
|
||||
|
||||
property.serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b69aa53204096d540b373b139a54546b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
namespace Utilities
|
||||
{
|
||||
public class WitRuntimeStyles
|
||||
{
|
||||
// Header padding
|
||||
public const float HeaderPaddingTop = 8f;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c91c720c1ebf4a51b8a3f173beb23f46
|
||||
timeCreated: 1680201046
|
||||
Reference in New Issue
Block a user