123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 |
- /**
- * Copyright(c) Live2D Inc. All rights reserved.
- *
- * Use of this source code is governed by the Live2D Open Software license
- * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
- */
- using UnityEngine;
- namespace Live2D.Cubism.Framework.MouthMovement
- {
- /// <summary>
- /// Real-time <see cref="CubismMouthController"/> input from <see cref="AudioSource"/>s.
- /// </summary>
- [RequireComponent(typeof(CubismMouthController))]
- public sealed class CubismAudioMouthInput : MonoBehaviour
- {
- /// <summary>
- /// Audio source to sample.
- /// </summary>
- [SerializeField]
- public AudioSource AudioInput;
- /// <summary>
- /// Sampling quality.
- /// </summary>
- [SerializeField]
- public CubismAudioSamplingQuality SamplingQuality;
- /// <summary>
- /// Audio gain.
- /// </summary>
- [Range(1.0f, 10.0f)]
- public float Gain = 1.0f;
- /// <summary>
- /// Smoothing.
- /// </summary>
- [Range(0.0f, 1.0f)]
- public float Smoothing;
- /// <summary>
- /// Current samples.
- /// </summary>
- private float[] Samples { get; set; }
- /// <summary>
- /// Last root mean square.
- /// </summary>
- private float LastRms { get; set; }
- /// <summary>
- /// Buffer for <see cref="Mathf.SmoothDamp(float, float, ref float, float)"/> velocity.
- /// </summary>
- // ReSharper disable once InconsistentNaming
- private float VelocityBuffer;
- /// <summary>
- /// Targeted <see cref="CubismMouthController"/>.
- /// </summary>
- private CubismMouthController Target { get; set; }
- /// <summary>
- /// True if instance is initialized.
- /// </summary>
- private bool IsInitialized
- {
- get { return Samples != null; }
- }
- /// <summary>
- /// Makes sure instance is initialized.
- /// </summary>
- private void TryInitialize()
- {
- // Return early if already initialized.
- if (IsInitialized)
- {
- return;
- }
- // Initialize samples buffer.
- switch (SamplingQuality)
- {
- case (CubismAudioSamplingQuality.VeryHigh):
- {
- Samples = new float[256];
- break;
- }
- case (CubismAudioSamplingQuality.Maximum):
- {
- Samples = new float[512];
- break;
- }
- default:
- {
- Samples = new float[256];
- break;
- }
- }
- // Cache target.
- Target = GetComponent<CubismMouthController>();
- }
- #region Unity Event Handling
- /// <summary>
- /// Samples audio input and applies it to mouth controller.
- /// </summary>
- private void Update()
- {
- // 'Fail' silently.
- if (AudioInput == null)
- {
- return;
- }
- // Sample audio.
- var total = 0f;
- AudioInput.GetOutputData(Samples, 0);
- for (var i = 0; i < Samples.Length; ++i)
- {
- var sample = Samples[i];
- total += (sample * sample);
- }
- // Compute root mean square over samples.
- var rms = Mathf.Sqrt(total / Samples.Length) * Gain;
- // Clamp root mean square.
- rms = Mathf.Clamp(rms, 0.0f, 1.0f);
- // Smooth rms.
- rms = Mathf.SmoothDamp(LastRms, rms, ref VelocityBuffer, Smoothing * 0.1f);
- // Set rms as mouth opening and store it for next evaluation.
- Target.MouthOpening = rms;
- LastRms = rms;
- }
- /// <summary>
- /// Initializes instance.
- /// </summary>
- private void OnEnable()
- {
- TryInitialize();
- }
- #endregion
- }
- }
|