中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Unity實現卡拉OK歌詞過渡效果的方法

發布時間:2021-04-12 12:56:49 來源:億速云 閱讀:208 作者:小新 欄目:編程語言

這篇文章主要介紹了Unity實現卡拉OK歌詞過渡效果的方法,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

演示效果 ↓

Unity實現卡拉OK歌詞過渡效果的方法

  • 實現歌詞動態調整功能

  • 實現動態讀取歌詞文件功能

  • 實現歌曲快進快退功能

  • 實現歌曲單字時間匹配功能

  • 實現可動態更換歌詞前景色背景色功能

注:

這里為實現精準過渡效果使用的是KSC歌詞文件, 并不是LRC文件哦 .

這其中我認為就是如何實現歌詞部分的前景色向后景色過渡的效果了, 開始的時候我想的也是很復雜 , 使用Shader的形式實現 ,網上找了一些相關代碼 , 發現不是特別理想 , 最終還是自己嘗試著用Mask來實現的, 發現效果還不錯 !
因為今天下班就過年回家啦! 其他細節之后會完善的 , 今天把工程文件先上傳了 .

歌詞效果類 ↓

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System;
using DG.Tweening;
using DG.Tweening.Core;

/// <summary>
/// 用于顯示歌詞過渡的效果
/// 1. 獲得路徑加載并解析歌詞文件信息
/// 2. 判斷當前歌曲是否播放( 歌曲暫停的時候歌詞效果也暫停 , 歌曲停止的時候歌詞效果消失 )
/// 3. 判斷歌曲快進或快退事件
/// </summary>
public class LayricPanelEffect : MonoSingleton<LayricPanelEffect>
{
 #region *********************************************************************字段

 //由外部傳入的聲音資源
 [HideInInspector,SerializeField]
 public AudioSource audioSource;
 //歌詞前景顏色;歌詞后景顏色
 [SerializeField]
 public Color32 frontTextColor = Color.white, backTextColor = Color.black, outlineColor = Color.white;
 //歌詞面板的前景部分和后景部分
 public RectTransform rectFrontLyricText, rectBackLyricMask;
 public Slider slider;
 //歌詞文件路徑
 [HideInInspector,SerializeField]
 public string lyricFilePath;

 //是否開始播放當前行歌詞內容
 public bool isStartLyricEffectTransition = true;
 //歌詞調整進度 ( 糾錯 )
 // [HideInInspector]
 public float lyricAdjust = -5f;

 //歌詞文本信息
 // [HideInInspector]
 [SerializeField,HideInInspector]
 public Text _lyricText;
 public Text _textContentLyric, _textLogMessage;

 private Vector2 tempFrontSizeDelta, tempBackSizeDelta;

 //用于訪問歌詞正文部分的內容在KscWord類中
 private KSC.KscWord kscword = new KSC.KscWord ();
 private KSC.KscWord curKscword = new KSC.KscWord ();

 //內部定時器( 由外部傳入參數來控制 , 用來記錄歌曲播放的當前時間軸 )
 private float _timer = 0.00f;

 #endregion

 /// <summary>
 /// 初始化一些變量
 /// </summary>
 void InitSomething ()
 {
 //堅持對歌詞文件進行賦值操作
 if (_lyricText == null || rectFrontLyricText.GetComponent <ContentSizeFitter> () == null) {
 if (rectFrontLyricText.GetComponent <Text> () == null) {
 _lyricText = rectFrontLyricText.gameObject.AddComponent <Text> ();
 }
 _lyricText = rectFrontLyricText.GetComponent <Text> ();

 //保持歌詞實現自適應
 rectFrontLyricText.GetComponent <ContentSizeFitter> ().horizontalFit = ContentSizeFitter.FitMode.PreferredSize;
 rectFrontLyricText.GetComponent <ContentSizeFitter> ().verticalFit = ContentSizeFitter.FitMode.PreferredSize;
 }
 rectBackLyricMask.GetComponentInChildren <Text> ().text = _lyricText.text;

 //歌詞顏色的更改初始化
 rectBackLyricMask.GetComponentInChildren <Text> ().color = backTextColor;
 rectBackLyricMask.GetComponentInChildren <Outline> ().effectColor = outlineColor;
 rectFrontLyricText.GetComponent <Text> ().color = frontTextColor;

 //歌詞過渡的前景部分 ( 用于判斷過度遮罩的長度范圍 )
 tempFrontSizeDelta = rectFrontLyricText.sizeDelta;
 tempBackSizeDelta = rectBackLyricMask.sizeDelta;

 //是否開始當前歌詞行播放標志位
 isStartLyricEffectTransition = true;
 }

 void Awake ()
 { 
 //初始化
 InitSomething ();
 }

 /// <summary>
 /// 控制歌詞面板的顯示
 /// 1. 僅僅顯示歌詞面板信息 , 沒有過渡效果!
 /// </summary>
 /// <param name="row">歌詞正文部分行號.</param>
 /// <param name="isPanelView">If set to <c>true</c> 顯示面板歌詞</param>
 public void LyricPanelControllerView (KSC.KscWord curRowInfo, bool isPanelView)
 {
// Debug.Log ("當前行是否開始=====>" + isPanelView.ToString ());
 _textLogMessage.text = isStartLyricEffectTransition.ToString ();

 rectBackLyricMask.sizeDelta = new Vector2 (0f, rectFrontLyricText.sizeDelta.y);

 rectBackLyricMask.GetComponentInChildren <Text> ().text = _lyricText.text = "";
 if (isPanelView) {
 //根據時間得到當前播放的是第i行的歌詞
 //處理歌詞面板信息 , 顯示歌詞
 foreach (var item in curRowInfo.PerLineLyrics) {
 _lyricText.text += item;
 rectBackLyricMask.GetComponentInChildren<Text> ().text = _lyricText.text;
 }
 StartCoroutine (LyricPanelControllerEffect (curRowInfo, isPanelView));
 } else {
 StopAllCoroutines ();
 rectBackLyricMask.sizeDelta = new Vector2 (0f, rectFrontLyricText.sizeDelta.y);
// StartCoroutine (LyricPanelControllerEffect (curRowInfo, isPanelView));
 //當前歌詞結束以后將歌詞框初始化成0
 rectBackLyricMask.GetComponentInChildren <Text> ().text = _lyricText.text = string.Empty;
 }
 }

 /// <summary>
 /// 開始實現歌此過渡效果, 僅僅效果實現
 /// 1. 使用Dotween的doSizedata實現
 /// 2. 動態調整蒙板的sizedata寬度
 /// 3. 根據歌曲當前播放的時間進度進行調整
 /// </summary>
 /// <returns>The panel controller effect.</returns>
 /// <param name="isPanelEffect">If set to <c>true</c> is panel effect.</param>
 public IEnumerator LyricPanelControllerEffect (KSC.KscWord curRowInfo, bool isPanelEffect)
 {
 //當前時間歌詞播放進度的百分比比例
 int curWordIndex = 0;
 if (isPanelEffect) {
 rectBackLyricMask.DORewind ();
 yield return null;
 rectBackLyricMask.sizeDelta = new Vector2 (0f, rectFrontLyricText.sizeDelta.y);
 //開始效果過渡
 if (audioSource.isPlaying) {
 for (int i = 0; i < curKscword.PerLinePerLyricTime.Length; i++) {
 rectBackLyricMask.DOSizeDelta (
 new Vector2 (((float)(i + 1) / curKscword.PerLinePerLyricTime.Length) * rectFrontLyricText.sizeDelta.x, rectFrontLyricText.sizeDelta.y)
 , curKscword.PerLinePerLyricTime [i] / 1000f
 , false).SetEase (Ease.Linear);
// Debug.Log ("第" + i + "個歌詞時間");
 yield return new WaitForSeconds (curKscword.PerLinePerLyricTime [i] / 1000f);
 }
 } else {
 Debug.LogError ("歌曲沒有播放 !!!!");
 }
 } else {
 yield return null;
 rectBackLyricMask.DOSizeDelta (new Vector2 (0f, rectFrontLyricText.sizeDelta.y), 0f, true);
 }
 }

 /// <summary>
 /// 開始播放音樂的時候調用
 /// </summary>
 /// <param name="lyricFilePath">歌詞文件路徑.</param>
 /// <param name="audioSource">Audiosource用于判斷播放狀態.</param>
 /// <param name="frontColor">前景色.</param>
 /// <param name="backColor">后景.</param>
 /// <param name="isIgronLyricColor">如果設置為 <c>true</c> 則使用系統配置的默認顏色.</param>
 public void StartPlayMusic (string lyricFilePath, AudioSource audioSource, Color frontColor, Color backColor, Color outlineColor, bool isIgronLyricColor)
 {
 _timer = 0f;

 //初始化ksc文件
 KSC.InitKsc (lyricFilePath);

 this.lyricFilePath = lyricFilePath;
 this.audioSource = audioSource;

 _textContentLyric.text = string.Empty;

 if (!isIgronLyricColor) {
 //歌曲顏色信息
 this.frontTextColor = frontColor;
 this.backTextColor = backColor;
 this.outlineColor = outlineColor;
 }

 #region ****************************************************輸出歌詞文件信息
 //對初始化完成后的信息進行輸出
 if (KSC.Instance.SongName != null) {
 print ("歌名==========>" + KSC.Instance.SongName);
 }
 if (KSC.Instance.Singer != null) {
 print ("歌手==========>" + KSC.Instance.Singer);
 }
 if (KSC.Instance.Pinyin != null) {
 print ("拼音==========>" + KSC.Instance.Pinyin);
 }
 if (KSC.Instance.SongClass != null) {
 print ("歌類==========>" + KSC.Instance.SongClass);
 }
 if (KSC.Instance.InternalNumber > 0) {
 print ("歌曲編號=======>" + KSC.Instance.InternalNumber);
 }
 if (KSC.Instance.Mcolor != Color.clear) {
 print ("男唱顏色=======>" + KSC.Instance.Mcolor);
 }
 if (KSC.Instance.Mcolor != Color.clear) {
 print ("女唱顏色=======>" + KSC.Instance.Wcolor);
 }
 if (KSC.Instance.SongStyle != null) {
 print ("風格==========>" + KSC.Instance.SongStyle);
 }
 if (KSC.Instance.WordCount > 0) {
 print ("歌名字數=======>" + KSC.Instance.WordCount);
 }
 if (KSC.Instance.LangClass != null) {
 print ("語言種類=======>" + KSC.Instance.LangClass);
 }

 //一般是獨唱歌曲的時候使用全Tag標簽展現參數信息
 foreach (var item in KSC.Instance.listTags) {
 print (item);
 }
 #endregion

 //顯示整個歌詞內容
 for (int i = 0; i < KSC.Instance.Add.Values.Count; i++) {
 KSC.Instance.Add.TryGetValue (i, out kscword);
 for (int j = 0; j < kscword.PerLineLyrics.Length; j++) {
 _textContentLyric.text += kscword.PerLineLyrics [j];
 }
 _textContentLyric.text += "\n";
 }
 }

 /// <summary>
 /// 停止播放按鈕
 /// </summary>
 public void StopPlayMusic ()
 {
 Debug.Log ("停止播放按鈕");
 }

 /// <summary>
 /// 主要用于歌詞部分的卡拉OK過渡效果
 /// 1. 動態賦值歌詞框的長度
 /// 2. 支持快進快退同步顯示
 /// </summary>
 int row = 0, tempRow = 0;

 void FixedUpdate ()
 {
 #region *********************************************************播放過渡效果核心代碼
 //如果是播放狀態并且沒有快進或快退 , 獲得當前播放時間 , 如果都下一句歌詞了 , 則切換到下一句歌詞進行過渡效果
 //1. 是否是暫停;
 //2. 是否開始播放
 //3. 是否播放停止
 if (audioSource != null && audioSource.isPlaying) {
 //進度條
 slider.value = _timer / audioSource.clip.length;
 //快進快退快捷鍵
 if (Input.GetKey (KeyCode.RightArrow)) {
 audioSource.time = Mathf.Clamp ((audioSource.time + 1f), 0f, 4.35f * 60f);
 } else if (Input.GetKey (KeyCode.LeftArrow)) {
 audioSource.time = Mathf.Clamp ((audioSource.time - 1f), 0f, 4.35f * 60f);
// } else if (Input.GetKeyUp (KeyCode.LeftArrow)) {
 isStartLyricEffectTransition = true;
 rectBackLyricMask.GetComponentInChildren <Text> ().text = rectFrontLyricText.GetComponent <Text> ().text = string.Empty;
 }

 //實時計時
 _timer = audioSource.time;

 //歌曲開始播放的時間
 _textLogMessage.text = _timer.ToString ("F2");

 for (int i = 0; i < KSC.Instance.Add.Count; i++) {

 KSC.Instance.Add.TryGetValue (i, out kscword);

 //根據時間判斷當前播放的是哪一行的歌詞文件 ( 減去0.01可保證兩句歌詞銜接太快的時候的bug )
 if ((_timer >= (kscword.PerLineLyricStartTimer + lyricAdjust + 0.1f) && _timer <= (kscword.PerLintLyricEndTimer + lyricAdjust - 0.1f)) && isStartLyricEffectTransition) {
 tempRow = i;
 KSC.Instance.Add.TryGetValue (tempRow, out curKscword);
 isStartLyricEffectTransition = false;
 Debug.Log ("當前播放====>" + i + "行");
 //歌詞面板顯示當前播放內容
 LyricPanelControllerView (curKscword, !isStartLyricEffectTransition);
 } else if ((_timer >= (curKscword.PerLintLyricEndTimer + lyricAdjust)) && !isStartLyricEffectTransition) {
 isStartLyricEffectTransition = true;
 //設置不顯示歌詞內容
 LyricPanelControllerView (curKscword, !isStartLyricEffectTransition);
 } 
 }

// KSC.Instance.Add.TryGetValue (row, out kscword);
//
// //根據時間判斷當前播放的是哪一行的歌詞文件 ( 減去0.01可保證兩句歌詞銜接太快的時候的bug )
// if ((_timer >= (kscword.PerLineLyricStartTimer + lyricAdjust + 0.1f) && _timer <= (kscword.PerLintLyricEndTimer + lyricAdjust)) && isStartLyricEffectTransition) {
// tempRow = row;
// KSC.Instance.Add.TryGetValue (tempRow, out curKscword);
// isStartLyricEffectTransition = false;
// Debug.Log ("當前播放====>" + row + "行");
// //歌詞面板顯示當前播放內容
// LyricPanelControllerView (curKscword, !isStartLyricEffectTransition);
// } else if ((_timer >= (curKscword.PerLintLyricEndTimer + lyricAdjust)) && !isStartLyricEffectTransition) {
// isStartLyricEffectTransition = true;
// //設置不顯示歌詞內容
// LyricPanelControllerView (curKscword, !isStartLyricEffectTransition);
// row = (row + 1) % KSC.Instance.Add.Count;
// } 
 #endregion
 }
 }
}

###KSC文件解析類 ↓

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using System.Text;
using UnityEngine.UI;
using System;
using System.Text.RegularExpressions;
using System.Runtime.InteropServices;

/// <summary>
/// KSC歌詞文件解析屬性, 單例工具類 ( 解析解析解析解析解析解析解析解析解析!!!!!!重要的事情多說幾遍 )
/// 1. 歌詞部分標題信息用單例instance訪問
/// 2. 正文信息部分使用KSCWord對象訪問( 每句開始時間\結束時間\每句歌詞文字的數組\每句歌詞文件時間的數組 )
/// </summary>
public class KSC : Singleton<KSC>
{
 /// <summary>
 /// 歌曲 歌名
 /// </summary>
 public string SongName { get; set; }

 /// <summary>
 /// 歌名字數 歌名字數
 /// </summary>
 public int WordCount{ get; set; }

 /// <summary>
 /// 歌名字數 歌名的拼音聲母
 /// </summary>
 public string Pinyin{ get; set; }

 /// <summary>
 /// 歌名字數 歌曲語言種類
 /// </summary>
 public string LangClass{ get; set; }

 /// <summary>
 /// 歌類,如男女樂隊等
 /// </summary>
 public string SongClass{ get; set; }

 /// <summary>
 /// 藝術家 演唱者,對唱則用斜杠"/"分隔
 /// </summary>
 public string Singer { get; set; }

 /// <summary>
 /// 歌曲編號 歌曲編號
 /// </summary>
 public int InternalNumber{ get; set; }

 /// <summary>
 /// 歌曲風格
 /// </summary>
 public string SongStyle{ get; set; }

 /// <summary>
 /// 視頻編號 
 /// </summary>
 public string VideoFileName{ get; set; }

 /// <summary>
 /// 前景顏色
 /// </summary>
 public Color Mcolor{ get; set; }

 /// <summary>
 /// 后景顏色
 /// </summary>
 public Color Wcolor{ get; set; }

 /// <summary>
 /// 偏移量
 /// </summary>
 public string Offset { get; set; }

 /// <summary>
 /// 各類標簽
 /// </summary>
 public List<string> listTags = new List<string> ();

 /// <summary>
 /// 歌詞正文部分信息 ( key = 行號 value = 解析出來的歌詞正文部分的每句歌詞信息 )
 /// </summary>
 public Dictionary<int,KscWord> Add = new Dictionary<int, KscWord> ();


 /// <summary>
 /// 獲得歌詞信息
 /// </summary>
 /// <param name="LrcPath">歌詞路徑</param>
 /// <returns>返回歌詞信息(Lrc實例)</returns>
 public static KSC InitKsc (string LrcPath)
 {
 int row = 0;
 //KscWord對象
 //清除之前的歌曲歌詞, 保持當前
 KSC.Instance.Add.Clear ();
 using (FileStream fs = new FileStream (LrcPath, FileMode.Open, FileAccess.Read, FileShare.Read)) {
 string line = string.Empty;
 using (StreamReader sr = new StreamReader (fs, Encoding.Default)) {
 
 while ((line = sr.ReadLine ()) != null) {
 //每次循環新建一個對象用于存儲不同行數內容
 KSC.KscWord kscWord = new KSC.KscWord ();
 #region ######################################合唱歌曲格式
 if (line.StartsWith ("karaoke.songname := '")) {
 Instance.SongName = SplitStrInfo (line);
 } else if (line.StartsWith ("karaoke.internalnumber := ")) {
 if (SplitIntInfo (line) != 0) {
 Instance.InternalNumber = SplitIntInfo (line);
 }
 } else if (line.StartsWith ("karaoke.singer := '")) {
 Instance.Singer = SplitStrInfo (line);
 } else if (line.StartsWith ("karaoke.wordcount := ")) {
 if (SplitIntInfo (line) != 0) {
 Instance.WordCount = SplitIntInfo (line);
 }
 } else if (line.StartsWith ("karaoke.pinyin := '")) {
 Instance.Pinyin = SplitStrInfo (line);
 } else if (line.StartsWith ("karaoke.langclass := '")) {
 Instance.LangClass = SplitStrInfo (line);
 } else if (line.StartsWith ("karaoke.songclass := '")) {
 Instance.SongClass = SplitStrInfo (line);
 } else if (line.StartsWith ("karaoke.songstyle := '")) {
 Instance.SongStyle = SplitStrInfo (line);
 } else if (line.StartsWith ("karaoke.videofilename :='")) {
 Instance.VideoFileName = SplitStrInfo (line);
 } else if (line.StartsWith ("mcolor :=rgb(")) {
 if (SplitColorInfo (line) != Color.clear) {
 Instance.Mcolor = SplitColorInfo (line);
 }
 } else if (line.StartsWith ("wcolor :=rgb(")) {
 if (SplitColorInfo (line) != Color.clear) {
 Instance.Wcolor = SplitColorInfo (line);
 }
 #endregion

 #region ##################################################獨唱歌曲風格
 } else if (line.StartsWith ("karaoke.tag('")) {
 //獲取tag標簽的參數信息
 KSC.Instance.listTags.Add (SplitTagInfo (line));
 #endregion 

 #region ################################################歌詞正文部分解析
 } else if (line.StartsWith (("karaoke.add"))) {   //表示歌詞正文部分
 if (SplitLyricStartTime (line) != null) {
 //行號 ( 從0行開始 )

 //獲取每句歌詞部分的開始時間
 kscWord.PerLineLyricStartTimer = SplitLyricStartTime (line);
 //獲取每句歌詞部分的結束時間
 kscWord.PerLintLyricEndTimer = SplitLyricEndTime (line);
 //獲取每行歌詞的內容,并存儲到KSCWord中 ( 歌詞文字的數組信息 左 → 右 )
 kscWord.PerLineLyrics = SplitPerLineLyrics (line);
 //獲取每行中單個文字的過渡時間數組 ( 歌詞文字過渡時間數組 左 → 右 )
 kscWord.PerLinePerLyricTime = SplitPerLinePerLyricTime (line);
 KSC.Instance.Add.Add (row, kscWord);
 row++;
 }
 } else {
 //忽略ksc文件中的其他部分
 if (line != "" && !line.Contains ("CreateKaraokeObject") && !line.Contains ("karaoke.rows") && !line.Contains ("karaoke.clear;") && !Regex.IsMatch (line, @"^\//")) {
 Debug.LogWarning ("歌詞含有不能解析的部分 ===> " + line);
 }
 }
 #endregion
 }
 }
 } 
 Debug.Log ("LyricFileInitialized" + " Path : \n" + LrcPath);
 return Instance;
 }

 #region ****************************************************************解析歌詞用的正則表達式部分 需更新

 /// <summary>
 /// 處理信息(私有方法)
 /// </summary>
 /// <param name="line"></param>
 /// <returns>返回基礎信息</returns>
 public static string SplitStrInfo (string line)
 {
// char[] ch = new char[]{ '\0', '\0' };
// return line.Substring (line.IndexOf ("'") + 1).TrimEnd (ch);
 string pattern = @"'\S{1,20}'"; //獲取歌曲標簽信息
 Match match = Regex.Match (line, pattern);

 //去除兩端的小分號
 string resout = string.Empty;
 resout = match.Value.Replace ("\'", string.Empty);
 return resout;
 }

 /// <summary>
 /// 處理參數是數字的情況
 /// </summary>
 /// <returns>The int info.</returns>
 /// <param name="line">Line.</param>
 public static int SplitIntInfo (string line)
 {
 string pattern = @"\d+"; //獲取歌曲標簽參數為數字的信息
 Match match = Regex.Match (line, pattern);

 //去除兩端的小分號
 int result = 0;
 result = Int32.Parse (match.Value);
 return result;
 }

 /// <summary>
 /// 處理參數顏色色值的情況 如: mcolor :=rgb(0, 0, 255);
 /// </summary>
 /// <returns>The color info.</returns>
 /// <param name="line">Line.</param>
 public static Color32 SplitColorInfo (string line)
 {
 string pattern = @"[r,R][g,G][b,G]?[\(](2[0-4][0-9])|25[0-5]|[01]?[0-9][0-9]?"; //獲取歌曲標簽參數為顏色值的信息
 MatchCollection matches = Regex.Matches (line, pattern);

 return new Color (float.Parse (matches [0].ToString ()), float.Parse (matches [1].ToString ()), float.Parse (matches [2].ToString ()));
 }

 /// <summary>
 /// 獲取歌曲的標簽部分信息 如 : karaoke.tag('語種', '國語'); // 國語/粵語/臺語/外語
 /// </summary>
 /// <returns>The tag info.</returns>
 public static string SplitTagInfo (string line)
 {
 string temp;
 string pattern = @"\([\W|\w]+\)"; //獲取歌曲標簽參數為顏色值的信息
 Match match = Regex.Match (line, pattern);
 temp = match.Value.Replace ("(", string.Empty).Replace (")", string.Empty).Replace ("'", string.Empty).Replace (",", ":");
 return temp;
 }

 /// <summary>
 /// 獲取每句歌詞正文部分的開始時間 (單位 : 秒)
 /// </summary>
 /// <returns>The lyric start time.</returns>
 /// <param name="line">Line.</param>
 public static float SplitLyricStartTime (string line)
 {
 float time = 0f;
 Regex regex = new Regex (@"\d{2}:\d{2}\.\d{2,3}", RegexOptions.IgnoreCase); //匹配單句歌詞時間 如: karaoke.add('00:29.412', '00:32.655'
 MatchCollection mc = regex.Matches (line);
 time = (float)TimeSpan.Parse ("00:" + mc [0].Value).TotalSeconds;
 return time;
 }

 /// <summary>
 /// 獲取每句歌詞正文部分的結束時間 (單位 : 秒)
 /// </summary>
 /// <returns>The lyric start time.</returns>
 /// <param name="line">Line.</param>
 public static float SplitLyricEndTime (string line)
 {
 Regex regex = new Regex (@"\d{2}:\d{2}\.\d{2,3}", RegexOptions.IgnoreCase); //匹配單句歌詞時間 如: karaoke.add('00:29.412', '00:32.655'
 MatchCollection mc = regex.Matches (line);
 float time = (float)TimeSpan.Parse ("00:" + mc [1].Value).TotalSeconds;
 return time;
 }

 /// <summary>
 /// 獲取每句歌詞部分的每個文字 和 PerLinePerLyricTime相匹配 (單位 : 秒)
 /// </summary>
 /// <returns>The line lyrics.</returns>
 /// <param name="line">Line.</param>
 public static string[] SplitPerLineLyrics (string line)
 {
 List<string> listStrResults = new List<string> ();
 string pattern1 = @"\[[\w|\W]{1,}]{1,}"; //獲取歌曲正文每個單詞 如 : karaoke.add('00:25.183', '00:26.730', '[五][十][六][個][星][座]', '312,198,235,262,249,286');
 string pattern2 = @"\'(\w){1,}\'"; //獲取歌曲正文每個單詞 如 : karaoke.add('00:28.420', '00:35.431', '夕陽底晚風里', '322,1256,2820,217,1313,1083');
 Match match = (line.Contains ("[") && line.Contains ("]")) ? Regex.Match (line, pattern1) : Regex.Match (line, pattern2);
 //刪除掉 [ ] '
 if (match.Value.Contains ("[") && match.Value.Contains ("]")) { //用于合唱類型的歌詞文件
 string[] resultStr = match.Value.Replace ("][", "/").Replace ("[", string.Empty).Replace ("]", string.Empty).Split ('/');
 foreach (var item in resultStr) {
 listStrResults.Add (item);
 }
 } else if (match.Value.Contains ("'")) {  //用于獨唱類型的歌詞文件 ( 尚未測試英文歌詞文件!!!!!!!!!!!!!!!!!!!!!!! )
 char[] tempChar = match.Value.Replace ("'", string.Empty).ToCharArray ();
 foreach (var item in tempChar) {
 listStrResults.Add (item.ToString ());
 }
 }
 return listStrResults.ToArray ();
 }

 /// <summary>
 /// 獲取每句歌詞部分的每個文字需要的過渡時間 和 PerLineLyrics相匹配 (單位 : 秒)
 /// </summary>
 /// <returns>The line per lyric time.</returns>
 /// <param name="line">Line.</param>
 public static float[] SplitPerLinePerLyricTime (string line)
 {
 string pattern = @"\'((\d){0,}\,{0,1}){0,}\'"; //獲取歌曲正文每個單詞過渡時間 如 : karaoke.add('00:25.183', '00:26.730', '[五][十][六][個][星][座]', '312,198,235,262,249,286');

 string str = null;
 List<float> listfloat = new List<float> ();
 //刪除掉 多余項
 str = Regex.Match (line, pattern).Value.Replace ("'", string.Empty);
// Debug.Log (str);
 foreach (var item in str.Split (',')) {
 listfloat.Add (float.Parse (item));
 }
 return listfloat.ToArray ();
 }

 #endregion

 #region ********************************************************************歌詞正文部分的時間與文字信息

 /// <summary>
 /// 用單獨的類來管理歌詞的正文部分 ( 在KSC類下 )主要用來存儲每句歌詞和每個歌詞的時間信息
 /// 1. 每句歌詞的時間的 ( 開始 - 結束 )
 /// 2. 每句歌詞中單個文字的時間信息 (集合的形式實現)
 /// </summary>
 public class KscWord
 {
 /// <summary>
 /// 每行歌詞部分開始的時間 (單位 : 秒) (key=行號,value=時間)
 /// </summary>
 public float PerLineLyricStartTimer { get; set; }

 /// <summary>
 /// 每行歌詞部分結束時間 (單位 : 秒) (key=行號,value=時間)
 /// </summary>
 public float PerLintLyricEndTimer { get; set; }

 /// <summary>
 /// 每行歌詞的單個文字集合
 /// </summary>
 public string[] PerLineLyrics{ get; set; }

 /// <summary>
 /// 每行歌詞中單個文字的速度過渡信息 (單位 : 毫秒)
 /// </summary>
 public float[] PerLinePerLyricTime{ get; set; }
 }

 #endregion
}

感謝你能夠認真閱讀完這篇文章,希望小編分享的“Unity實現卡拉OK歌詞過渡效果的方法”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

五家渠市| 锡林浩特市| 平遥县| 仙桃市| 陆川县| 天水市| 新平| 北宁市| 平凉市| 伊吾县| 丹巴县| 洪湖市| 宜兰市| 南陵县| 湘乡市| 阿图什市| 罗山县| 托克托县| 城口县| 长乐市| 札达县| 安远县| 长宁县| 安庆市| 彝良县| 瓦房店市| 营口市| 隆尧县| 新乐市| 天祝| 扶风县| 花莲县| 古田县| 辉县市| 肥东县| 玉田县| 甘洛县| 万年县| 祁连县| 阳朔县| 黄山市|