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<OVRLipSync.Viseme, OVRLipSync.MorphData> m_VisemeMorphPair = new Dictionary<OVRLipSync.Viseme, OVRLipSync.MorphData>
	{
		{
			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;
	}
}
