上节写了如何从千千静听服务器下载歌词,这节说说如何让歌词显示出来
首先是分析歌词文件,分析出不同时间对于的歌词
1、定义一个歌词行的类LrcLineItem
public class LrcLineItem { public string TimeString { get; set; } public string Text { get; set; } public double Time { get; set; } public LrcLineItem(string text, double time) { this.Text = text; this.Time = time; //[02:13.60]歌词 int timeint = (int)this.Time; this.TimeString = "[" + (timeint / 60).ToString("d2") + ":" + (timeint % 60).ToString("d2") + (Time - timeint).ToString("f2").Substring(1, 3) + "]" + Text; } public override string ToString() { return this.TimeString; } }
然后计算出歌词中所有的不同时间对于的歌词存放到LrcLineItem数组中
下面定义LrcAnalyze类
public class LrcAnalyze { string title; string artist; string album; string content; List<LrcLineItem> lrcList; public LrcLineItem[] lrcs { get; set; } public LrcAnalyze(string filepath) { lrcList = new List<LrcLineItem>(); using (StreamReader reader = new StreamReader(filepath, Encoding.UTF8)) { content = reader.ReadToEnd(); } Analyze(); } private void Analyze() { StringReader reader = new StringReader(content); string lineStr = reader.ReadLine(); while (lineStr !=null) { if (lineStr != null && lineStr.Length > 3) { switch (lineStr.Substring(1, 2)) { case "ti": title = lineStr.Substring(4, lineStr.Length - 5); break; case "ar": artist = lineStr.Substring(4, lineStr.Length - 5); break; case "al": album = lineStr.Substring(4, lineStr.Length - 5); break; default: GetLrcStr(lineStr); break; } } lineStr = reader.ReadLine(); } //排序(冒泡) SortLrcLine(); } private void GetLrcStr(string lineStr) { int num = (lineStr.LastIndexOf(']') + 1) / 10; string text = lineStr.Substring(num * 10); try { for (int i = 0; i < num; i++) { string timestr = lineStr.Substring(i * 10 + 1, 8); double time = Convert.ToDouble(timestr.Substring(0, 2)) * 60 + Convert.ToDouble(timestr.Substring(3, 5)); lrcList.Add(new LrcLineItem(text, time)); } } catch(FormatException) { } } private void SortLrcLine() { lrcs = lrcList.ToArray(); for (int i = 0; i < lrcs.Length - 1; i++) { for (int j = i + 1; j < lrcs.Length; j++) { if (lrcs[i].Time > lrcs[j].Time) { LrcLineItem temp = lrcs[j]; lrcs[j] = lrcs[i]; lrcs[i] = temp; } } } } //获得相应时间的歌词,返回索引 public int GetIndex(double time) { for (int i = 0; i < lrcs.Length; i++) { if (lrcs[i].Time > time) { return i - 1; } } return lrcs.Length - 1; } //返回多行歌词(count*2+1行) public string[] GetLrcStrings(int count, double time) { int index = GetIndex(time); string[] lrcstrings = new string[count * 2 + 1]; for (int i = 0; i < count; i++) { if (index - count + i > 0) lrcstrings[i] = lrcs[index - count + i].Text; else lrcstrings[i] = string.Empty; } lrcstrings[count] = lrcs[index].Text; for (int i = 0; i < count; i++) { if (index + i < lrcs.Length) lrcstrings[count + i + 1] = lrcs[index + i].Text; else lrcstrings[i] = string.Empty; } return lrcstrings; } }
好了,歌词的分析算是完成了,接下来实践一下
1、创建一个WinForm窗体,添加7个Label控件分别是Label1,Labe2l,Label3,Label4,Label5,Label6,Label7,用于显示歌词,其中Label4的颜色设为红色,其他设为白色
2、添加一个按钮Play,用于开始播放音乐
3、定义两个文件Lrc和Mp3,这里的Mp3文件用之前讲的 AxWindowsMediaPlayer播放
string musicfile = @"G:\Music\郭峰 - 心甘情愿.mp3"; string lrcfile = @"G:\Music\郭峰 - 心甘情愿.lrc";
4、添加一个计时器timer1,用于计算当前播放,时间间隔设为500,没半秒刷新一次歌词,添加触发事件
5、为axWindowsMediaPlayer1添加一个事件函数PositionChange,当进度条改变时,time也相应改变
代码如下
public partial class Form1 : Form { double time = 0; //当前播放时间 LrcAnalyze lrc; //歌词信息 string musicfile = @"G:\Music\郭峰 - 心甘情愿.mp3"; string lrcfile = @"G:\Music\郭峰 - 心甘情愿.lrc"; public Form1() { InitializeComponent(); lrc = new LrcAnalyze(lrcfile); } private void timer1_Tick(object sender, EventArgs e) { this.time = this.time + 0.5; //更新UI string[] strs = this.lrc.GetLrcStrings(3, time); this.label1.Text = strs[0]; this.label2.Text = strs[1]; this.label3.Text = strs[2]; this.label4.Text = strs[3]; this.label5.Text = strs[4]; this.label6.Text = strs[5]; this.label7.Text = strs[6]; } private void axWindowsMediaPlayer1_PositionChange(object sender, AxWMPLib._WMPOCXEvents_PositionChangeEvent e) { this.time = e.newPosition; } private void btnPlay_Click(object sender, EventArgs e) { this.axWindowsMediaPlayer1.URL = musicfile; this.axWindowsMediaPlayer1.Ctlcontrols.play(); this.timer1.Start(); } }