天天看點

按時間讀取歌詞

按時間讀取歌詞
using System.Collections;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System;

[HideInInspector]
[CustomEditor(typeof(PlayMusic))]
public class PlayMusicEditor : Editor
{
    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();
        PlayMusic playMusic = (PlayMusic)target;
        GetDirectoryPath("lyricPath", ref playMusic.lyricPath);
    }

    /// <summary>
    /// 獲得拖動的檔案的路徑
    /// </summary>
    /// <param name="label"></param>
    /// <param name="path"></param>
    public void GetDirectoryPath(string label, ref string path)
    {
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField(label, GUILayout.MaxWidth(55));
        Rect rect = EditorGUILayout.GetControlRect();
        path = EditorGUI.TextField(rect, path);
        EditorGUILayout.EndHorizontal();

        if ((Event.current.type == EventType.DragUpdated
          || Event.current.type == EventType.DragExited)
          && rect.Contains(Event.current.mousePosition))
        {
            DragAndDrop.visualMode = DragAndDropVisualMode.Generic;
            if (DragAndDrop.paths != null && DragAndDrop.paths.Length > 0)
            {
                path = DragAndDrop.paths[0];
            }
        }
    }
}

/// <summary>
/// 該類引用自 http://www.cnblogs.com/liuxiaobo93/p/3896914.html?from=singlemessage&isappinstalled=0
/// </summary>
[HideInInspector]
public class Lrc
{
    #region field
    public struct LrcData
    {
        public float time;
        public string timeString;
        public string content;
    }

    public string Title { get; set; }
    public string Artist { get; set; }
    public string Album { get; set; }
    public string LrcBy { get; set; }
    public string Offset { get; set; }
    public List<LrcData> lrcList = new List<LrcData>();
    #endregion

    #region public function

    /// <summary>
    /// 讀取歌詞
    /// </summary>
    /// <param name="path"></param>
    public void ReadLyric(string path)
    {
        ArrayList list = FileOperate.ReadFile(path);
        if (null == list) return;

        Regex regextime = new Regex("\\[([0-9.:]*)\\]");
        Regex regexword = new Regex(@".*\](.*)");

        foreach (string line in list)
        {
            if (line.StartsWith("[ti:"))
            {
                Title = SplitInfo(line);
            }
            else if (line.StartsWith("[ar:"))
            {
                Artist = SplitInfo(line);
            }
            else if (line.StartsWith("[al:"))
            {
                Album = SplitInfo(line);
            }
            else if (line.StartsWith("[by:"))
            {
                LrcBy = SplitInfo(line);
            }
            else if (line.StartsWith("[offset:"))
            {
                Offset = SplitInfo(line);
            }
            else
            {
                try
                {
                    Match mcw = regexword.Match(line);
                    string word = mcw.Groups[1].Value;
                    MatchCollection mct = regextime.Matches(line);
                    foreach (Match item in mct)
                    {
                        double time = TimeSpan.Parse("00:" + item.Groups[1].Value).TotalSeconds;
                        LrcData data = new LrcData();
                        data.timeString = item.Groups[1].Value;
                        data.time = (float)time;
                        data.content = word;
                        lrcList.Add(data);
                    }
                }
                catch
                {
                    continue;
                }

            }
        }
    }
    #endregion

    #region private function
    private string SplitInfo(string line)
    {
        return line.Substring(line.IndexOf(":") + 1).TrimEnd(']');
    }
    #endregion
}

public class PlayMusic : MonoBehaviour
{
    #region field
    [HideInInspector]
    public string lyricPath;
    public AudioSource source;

    private int index = 0;
    private float time;
    private Lrc lrc;

    public Action<Lrc.LrcData> OnCurrentLyric;
    public Action<float> OnTimeChanaged;
    #region encapsulation

    public Lrc Lyric
    {
        get
        {
            if (null == lrc)
            {
                lrc = new Lrc();
                lrc.ReadLyric(lyricPath);
            }
            return lrc;
        }
    }

    #endregion
    #endregion

    #region public function

    public int GetIndex()
    {
        return index;
    }

    public float GetLength()
    {
        return source.clip.length;
    }

    public void Play()
    {
        index = 0;
        source.Play();
    }

    public void Stop()
    {
        source.Stop();
    }

    public void SetNewMusic(AudioClip clip, string lyricPath)
    {
        if (source.isPlaying)
            source.Stop();

        source.clip = clip;
        this.lyricPath = lyricPath;
        Lyric.ReadLyric(lyricPath);
        index = 0;
    }

    /// <summary>
    /// 設定開始時間
    /// </summary>
    /// <param name="value"></param>
    public void SetStartTime(float value)
    {
        source.time = value;
        for (int i = 0; i < Lyric.lrcList.Count; i++)
        {
            if (value < lrc.lrcList[i].time)
            {
                index = i - 1;
                break;
            }
        }
        //有可能找不到時間
        if (-1 == index) index = 0;
    }

    #endregion

    #region private function

    private void Update()
    {
        if (source.isPlaying)
        {
            //如果播放時間改變
            if (Mathf.Abs(time - source.time) > 0.01f)
            {
                time = source.time;
                if (null != OnTimeChanaged) OnTimeChanaged(source.time);
            }

            //如果播放時間大于目前顯示的時間
            if (source.time > Lyric.lrcList[index].time)
            {
                if (null != OnCurrentLyric) OnCurrentLyric(Lyric.lrcList[index]);
                index++;
            }
        }
    }
    #endregion
}
           

-------------------------------------測試-------------------------------------

using UnityEngine;
using UnityEngine.UI;

public class View : MonoBehaviour {

    public Text content;
    public Slider slider;
    public PlayMusic playMusic;

    private void Awake()
    {
        slider.maxValue = playMusic.GetLength();
        GameObject sliderGame = slider.gameObject;
        EventListener.Get(sliderGame).onLeftUp += OnValueChanaged;
        EventListener.Get(sliderGame).onLeftDown += OnStop;
        playMusic.OnCurrentLyric += OnCurrentLyric;
        playMusic.OnTimeChanaged += onTimeChanaged;
    }

    public void OnClickButton()
    {
        playMusic.Play();
    }

    private void OnStop()
    {
        playMusic.Stop();
    }

    private void OnValueChanaged()
    {
        playMusic.SetStartTime(slider.value);
        playMusic.Play();
    }

    private void OnCurrentLyric(Lrc.LrcData data)
    {
        content.text = data.content;
    }

    private void onTimeChanaged(float time)
    {
        slider.value = time;
    }
}
           

繼續閱讀