using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using UnityEngine; public class OVRLipSync : MonoBehaviour { [DllImport("OVRLipSync")] private static extern int ovrLipSyncDll_Initialize(int samplerate, int buffersize); [DllImport("OVRLipSync")] private static extern void ovrLipSyncDll_Shutdown(); [DllImport("OVRLipSync")] private static extern IntPtr ovrLipSyncDll_GetVersion(ref int Major, ref int Minor, ref int Patch); [DllImport("OVRLipSync")] private static extern int ovrLipSyncDll_CreateContext(ref uint context, OVRLipSync.ContextProviders provider); [DllImport("OVRLipSync")] private static extern int ovrLipSyncDll_DestroyContext(uint context); [DllImport("OVRLipSync")] private static extern int ovrLipSyncDll_ResetContext(uint context); [DllImport("OVRLipSync")] private static extern int ovrLipSyncDll_SendSignal(uint context, OVRLipSync.Signals signal, int arg1, int arg2); [DllImport("OVRLipSync")] private static extern int ovrLipSyncDll_ProcessFrame(uint context, float[] audioBuffer, OVRLipSync.Flags flags, ref int frameNumber, ref int frameDelay, float[] visemes, int visemeCount); [DllImport("OVRLipSync")] private static extern int ovrLipSyncDll_ProcessFrameInterleaved(uint context, float[] audioBuffer, OVRLipSync.Flags flags, ref int frameNumber, ref int frameDelay, float[] visemes, int visemeCount); public OVRLipSync.VariableData Variable { get { return this.m_Variable; } } public static int SamplingRate { get; private set; } public static int BuffSize { get; private set; } public void Init() { if (OVRLipSync.sInstance == null) { OVRLipSync.sInstance = this; int outputSampleRate = AudioSettings.outputSampleRate; int num; int num2; AudioSettings.GetDSPBufferSize(out num, out num2); OVRLipSync.SamplingRate = outputSampleRate; OVRLipSync.BuffSize = num; string message = string.Format("OvrLipSync Awake: Queried SampleRate: {0:F0} BufferSize: {1:F0}", outputSampleRate, num); Debug.LogWarning(message); OVRLipSync.sInitialized = OVRLipSync.Initialize(outputSampleRate, num); if (OVRLipSync.sInitialized != OVRLipSync.Result.Success) { Debug.LogWarning(string.Format("OvrLipSync Awake: Failed to init Speech Rec library", new object[0])); } return; } Debug.LogWarning(string.Format("OVRLipSync Awake: Only one instance of OVRPLipSync can exist in the scene.", new object[0])); } private void OnDestroy() { if (OVRLipSync.sInstance != this) { Debug.LogWarning("OVRLipSync OnDestroy: This is not the correct OVRLipSync instance."); return; } } public static OVRLipSync.Result Initialize(int sampleRate, int bufferSize) { OVRLipSync.sInitialized = (OVRLipSync.Result)OVRLipSync.ovrLipSyncDll_Initialize(sampleRate, bufferSize); return OVRLipSync.sInitialized; } public static void Shutdown() { OVRLipSync.ovrLipSyncDll_Shutdown(); OVRLipSync.sInitialized = OVRLipSync.Result.Unknown; } public static OVRLipSync.Result IsInitialized() { return OVRLipSync.sInitialized; } public static OVRLipSync.Result CreateContext(ref uint context, OVRLipSync.ContextProviders provider) { if (OVRLipSync.IsInitialized() != OVRLipSync.Result.Success) { return OVRLipSync.Result.CannotCreateContext; } return (OVRLipSync.Result)OVRLipSync.ovrLipSyncDll_CreateContext(ref context, provider); } public static OVRLipSync.Result DestroyContext(uint context) { if (OVRLipSync.IsInitialized() != OVRLipSync.Result.Success) { return OVRLipSync.Result.Unknown; } return (OVRLipSync.Result)OVRLipSync.ovrLipSyncDll_DestroyContext(context); } public static OVRLipSync.Result ResetContext(uint context) { if (OVRLipSync.IsInitialized() != OVRLipSync.Result.Success) { return OVRLipSync.Result.Unknown; } return (OVRLipSync.Result)OVRLipSync.ovrLipSyncDll_ResetContext(context); } public static OVRLipSync.Result SendSignal(uint context, OVRLipSync.Signals signal, int arg1, int arg2) { if (OVRLipSync.IsInitialized() != OVRLipSync.Result.Success) { return OVRLipSync.Result.Unknown; } return (OVRLipSync.Result)OVRLipSync.ovrLipSyncDll_SendSignal(context, signal, arg1, arg2); } public static OVRLipSync.Result ProcessFrame(uint context, float[] audioBuffer, OVRLipSync.Flags flags, OVRLipSync.Frame frame) { if (OVRLipSync.IsInitialized() != OVRLipSync.Result.Success) { return OVRLipSync.Result.Unknown; } return (OVRLipSync.Result)OVRLipSync.ovrLipSyncDll_ProcessFrame(context, audioBuffer, flags, ref frame.frameNumber, ref frame.frameDelay, frame.Visemes, frame.Visemes.Length); } public static OVRLipSync.Result ProcessFrameInterleaved(uint context, float[] audioBuffer, OVRLipSync.Flags flags, OVRLipSync.Frame frame) { if (OVRLipSync.IsInitialized() != OVRLipSync.Result.Success) { return OVRLipSync.Result.Unknown; } return (OVRLipSync.Result)OVRLipSync.ovrLipSyncDll_ProcessFrameInterleaved(context, audioBuffer, flags, ref frame.frameNumber, ref frame.frameDelay, frame.Visemes, frame.Visemes.Length); } public void SetLipSync(Maid maid, bool is_start = true) { maid.SetMicLipSync(is_start); } public void SetLipSync(int maid_no = 0, bool is_start = true) { Maid maid = GameMain.Instance.CharacterMgr.GetMaid(maid_no); if (!maid) { Debug.LogErrorFormat("メイド{0}番は存在しません", new object[] { maid_no }); return; } this.SetLipSync(maid, is_start); } public OVRLipSync.MorphData GetMorphData(OVRLipSync.Viseme viseme) { return this.m_VisemeMorphPair[viseme]; } public OVRLipSync.MorphData GetMorphData(int index) { return this.m_VisemeMorphPair.ElementAt(index).Value; } private Dictionary m_VisemeMorphPair = new Dictionary { { OVRLipSync.Viseme.sil, new OVRLipSync.MorphData(0f, 0f, 0f) }, { OVRLipSync.Viseme.PP, new OVRLipSync.MorphData(0f, 0f, 1f) }, { OVRLipSync.Viseme.FF, new OVRLipSync.MorphData(0f, 0f, 1f) }, { OVRLipSync.Viseme.TH, new OVRLipSync.MorphData(0f, 0.5f, 0f) }, { OVRLipSync.Viseme.DD, new OVRLipSync.MorphData(0f, 0f, 1f) }, { OVRLipSync.Viseme.kk, new OVRLipSync.MorphData(0f, 0f, 1f) }, { OVRLipSync.Viseme.CH, new OVRLipSync.MorphData(0f, 0.5f, 0f) }, { OVRLipSync.Viseme.SS, new OVRLipSync.MorphData(0f, 0f, 1f) }, { OVRLipSync.Viseme.nn, new OVRLipSync.MorphData(0f, 0f, 0.7f) }, { OVRLipSync.Viseme.RR, new OVRLipSync.MorphData(0f, 0f, 0f) }, { OVRLipSync.Viseme.aa, new OVRLipSync.MorphData(1f, 0f, 0f) }, { OVRLipSync.Viseme.E, new OVRLipSync.MorphData(0f, 1f, 0f) }, { OVRLipSync.Viseme.ih, new OVRLipSync.MorphData(0f, 0.5f, 0f) }, { OVRLipSync.Viseme.oh, new OVRLipSync.MorphData(1f, 0f, 0.4f) }, { OVRLipSync.Viseme.ou, new OVRLipSync.MorphData(0f, 0f, 1f) } }; public static readonly int VisemeCount = Enum.GetNames(typeof(OVRLipSync.Viseme)).Length; public static readonly int SignalCount = Enum.GetNames(typeof(OVRLipSync.Signals)).Length; public const string strOVRLS = "OVRLipSync"; private static OVRLipSync.Result sInitialized = OVRLipSync.Result.Unknown; public static OVRLipSync sInstance = null; public const float SensitivityMin = 1f; public const float SensitivityMax = 10f; [SerializeField] [Header("各数値設定")] private OVRLipSync.VariableData m_Variable = new OVRLipSync.VariableData(); public enum Result { Success, Unknown = -2200, CannotCreateContext = -2201, InvalidParam = -2202, BadSampleRate = -2203, MissingDLL = -2204, BadVersion = -2205, UndefinedFunction = -2206 } public enum Viseme { sil, PP, FF, TH, DD, kk, CH, SS, nn, RR, aa, E, ih, oh, ou } public class MorphData { public MorphData(float lip1 = 0f, float lip2 = 0f, float lip3 = 0f) { this.LipSync1 = lip1; this.LipSync2 = lip2; this.LipSync3 = lip3; } public float LipSync1; public float LipSync2; public float LipSync3; } public enum Flags { None, DelayCompensateAudio } public enum Signals { VisemeOn, VisemeOff, VisemeAmount, VisemeSmoothing } public enum ContextProviders { Main, Other } [Serializable] public class Frame { public void CopyInput(OVRLipSync.Frame input) { this.frameNumber = input.frameNumber; this.frameDelay = input.frameDelay; input.Visemes.CopyTo(this.Visemes, 0); } public int frameNumber; public int frameDelay; public float[] Visemes = new float[OVRLipSync.VisemeCount]; } [Serializable] public class VariableData { public float MicSensitivity { get { return this.m_MicSensitivity; } set { this.m_MicSensitivity = Mathf.Clamp(value, 1f, 10f); } } public float MicVolume { get { return this.m_MicVolume; } set { this.m_MicVolume = Mathf.Clamp01(value); } } [SerializeField] [Header("マイクの感度")] [Range(1f, 10f)] private float m_MicSensitivity = 1f; [Header("入力された音声を再生しない")] public bool Mute = true; [SerializeField] [Header("出力するマイクの音量")] [Range(0f, 1f)] private float m_MicVolume = 1f; } }