主题:[原创]在自制播放器中使用和制作 Lrc 歌词文件
在自制播放器中使用和制作 Lrc 歌词文件
如果我们用 MMControl控件制作了一个播放器,在播放乐曲的同时,一定也想显示歌词。目前比较
流行的是.Lrc歌词文件,它实际上也是纯文本文件,但它在每句歌词前面都加上了时间参数,这样,利
用 MMContro l控件的 Position 属性,我们就可以实时显示相应的歌词。
先来了解一下.Lrc歌词文件的基本结构,例如:
[ti:狼爱上羊]
[ar:一江秋水制作]
[al:2008年1月28日]
[00:00.01]《狼爱上羊》(歌手:汤潮)
[00:29.97]北风呼呼地刮
[00:33.19]雪花飘飘洒洒
……
我们看到,前面三行(有些 Lrc文件可能有四、五行)是歌词文件的一些信息,无关紧要,所以我
们在使用自制的播放器播放或制作歌词文件时,就可以去掉这些内容,后面才是正式的歌词句,在每一
歌词句的前面,都用方括号表示了该句的显示时间,时间格式是分、秒、毫秒,都用两位数字表示。
但是,我们从网上下载的 Lrc文件,常常与实际的歌曲衔接不上,这是因为 Lrc文件的制作者所使
用的歌曲版本与我们所使用的不一致,造成时间参数与歌曲进度不同步。例如上面那首《狼爱上羊》,
第一个歌词句的显示时间是29秒970毫秒,这是因为我从网上下载的歌曲前面有29秒多的过门,过后才是
歌手的声音,如果你下载的《狼爱上羊》前面只有15秒的过门,那么这个 Lrc文件就显然会与歌曲衔接
不上。所以,我们自制的播放器不但要能够显示 Lrc歌词文件,还要能够制作它。
一、显示 Lrc 歌词的方法
在显示歌词的代码中,首先取出时间字串,转换成毫秒,再与Position属性比较,如果相差不多,
就将时间字串后面的歌词句字串显示出来。
MMControl 控件的 Position属性的作用是:根据指定的 TimeFormat返回已打开的设备的位置,一
般用四字节表示,只读。在使用Position属性之前,要先设置属性 TimeFormat=0,这样Position属性
返回的时间单位就是毫秒了。
歌词句是显示在屏幕下方的(如果你想显示在播放器窗体中,那也只要进行简单的修改就行了),
并且从右向左迅速移动,最终停止在屏幕左下方。
好,我们就开始试验吧。
新建一个工程,添加两个窗体Form1和Form3。Form1是播放器窗体,在上面要添加一个 MMControl
控件(将其名称改为MMC),一个 CommonDialog 控件(改其名称为 CD)、一个按纽控件,和其它你认
为需要的控件。Form3是显示歌词用的,在上面添加一个标签和一个计时器,属性设置为:
Form3窗体:
----------
BackColor:黑色
BorderStyle:0
Height:495
Label1标签:
-----------
Font:楷体_GB2312,小一号,粗体
ForeColor:白色
AutoSize:True
BackStyle:0
Height:495
Top:0
Timer1计时器:
------------
Inteval:20
模块的代码:
------------------------------------------------------------------------------------------
Declare Function SetLayeredWindowAttributes Lib "user32" (ByVal hWnd As Long, _
ByVal crKey As Long, ByVal bAlpha As Byte, ByVal dwFlags As Long) As Long
Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd _
As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Declare Function SetWindowPos Lib "user32" (ByVal hWnd As Long, ByVal _
hWndInsertAfter As Long, ByVal X As Long, ByVal Y As Long, ByVal cx As Long, _
ByVal cy As Long, ByVal wFlags As Long) As Long
Public ST As String '歌词文本
Public BJForm3 As Boolean 'Form3调出标记
------------------------------------------------------------------------------------------
Form1的有关代码:
------------------------------------------------------------------------------------------
Option Explicit
Dim BJMode As Boolean 'True-显示歌词;False-制作歌词
Private Sub Command1_Click() '读 lrc 文件
On Error GoTo 100
Dim z As String
CD.Flags = &H1808
CD.DialogTitle = "打开 lrc 歌词文件"
CD.Filter = "Lrc 歌词文件(*.lrc)|*.lrc"
CD.ShowOpen
If Dir(CD.FileName) = "" Then Exit Sub
ST = ""
Open CD.FileName For Input As #1
Do Until EOF(1)
Line Input #1, z
If Len(z) > 0 Then ST = ST & z & "~" '用这个不常用的字符"~"作为歌词句的分隔符
Loop
BJMode = True
100
Close
End Sub
Private Sub 播放_Click()
With MMC
.FileName = "(MP3歌曲的全路径文件名)" '以播放MP3为例
.Command = "Open"
.TimeFormat = 0 '时间格式为毫秒
.Notify = True '打开通知
.Command = "play"
End With
If BJMode Then Form3.Show
End Sub
Private Sub MMC_Done(NotifyCode As Integer)
If NotifyCode = 1 Then '如果播放完毕
If BJForm3 Then Unload Form3
MMC.Command = "stop"
MMC.Command = "close"
End If
End Sub
Private Sub Form_Unload(Cancel As Integer)
If BJForm3 Then Unload Form3
End Sub
------------------------------------------------------------------------------------------
Form3的代码:
------------------------------------------------------------------------------------------
Option Explicit
Dim LrcST As String '歌词句字串
Dim k1 As Long '歌词句在文件中的起始位置
Dim k2 As Long '歌词句的长度
Dim t As Long
Private Sub Form_Load()
SetWindowLong hWnd, -20, &H80000
SetLayeredWindowAttributes hWnd, 0, 0, 1 '将窗体背景黑色设为透明
SetWindowPos hWnd, -1, 0, 0, 0, 0, 3& '窗体总在最上
Move 0, Screen.Height - 540, Screen.Width '将窗体设置到屏幕下方,其宽度与屏幕宽度相同
BJForm3 = True: k1 = 1
End Sub
Private Sub Timer1_Timer()
Dim s As String
If t < Form1.MMC.Position Then
Do
k2 = InStr(k1, ST, "~")
LrcST = Mid$(ST, k1, k2 - k1) '从歌词句中取出含有方括号的字串
k1 = IIf(k2 + 10 > Len(ST), 1, k2 + 1) '设置下一个歌词句在文件中的起始位置
s = Mid$(LrcST, 2, InStr(LrcST, "]") - 2) '取出去掉了方括号的字串
Loop Until IsNumeric(Left$(s, 2)) '如果是时间字串就退出Do循环
t = Val(s) * 60000 + Val(Mid$(s, 4)) * 1000 '将时间字串转换为毫秒
End If
If Abs(Form1.MMC.Position - t) < 200 Then '如果歌词与播放进度的时间差小于200毫秒
t = 0
Label1.Left = Width
Label1.Caption = Mid$(LrcST, InStr(LrcST, "]") + 1) '取出歌词字串
Do
Label1.Left = Label1.Left - 150
DoEvents
Loop Until Label1.Left < 300
End If
End Sub
Private Sub Form_Unload(Cancel As Integer)
BJForm3 = False
End Sub
------------------------------------------------------------------------------------------
在 Timer1_Timer 过程中,第一个 Do 循环的目的是不显示诸如[ti:****]、[ar:****]、
[al:****]、[by:****]这样的内容,如果 Lrc文件是自己制作的,没有这些东东,那么也可以
去掉 Do 和 Loop 这两行代码。第二个 Do 循环的作用是将 Label1 标签从屏幕右外方移至屏幕左。
二、制作 Lrc 歌词文件的方法
要制作 Lrc 歌词文件,首先要有同名的 TXT 歌词文件,可以在网上下载,也可以自己编制。
在 Form1 窗体上再添加一个 Label1 标签,和两个按纽控件,Command2 的作用是读入 TXT歌词文
件,Command3的作用是在歌词句的前面加上含方括号的时间参数,标签的作用是将制作好的含时间参数
的歌词句显示出来。标签的 AutoSize 属性设置为 True。
Form1的有关代码:
------------------------------------------------------------------------------------------
Option Explicit
Dim LrcST As String '歌词文本
Dim k1 As Long '歌词句在TXT歌词文件中的起始位置
Sub Command2_Click()
On Error GoTo 100
CD.Flags = &H1808
CD.DialogTitle = "打开 txt 歌词文件"
CD.Filter = "txt 歌词文件(*.txt)|*.txt"
CD.ShowOpen
If Dir(CD.FileName) <> "" Then
Dim z As String
ST = ""
Open CD.FileName For Input As #1
Do Until EOF(1)
Line Input #1, z
If Len(z) > 0 Then ST = ST & z & "~"
Loop
k1 = InStr(ST, "~") + 1
LrcST = "[00:00.01]" & Left$(ST, k1 - 2)
Label1.Caption = LrcST
End If
BJMode = False
100
Close
End Sub
Private Sub Command3_Click()
If k1 > Len(ST) - 2 Then
If MsgBox("已完成,是否保存 Lrc 歌词文件?", 4, "注意") = 6 Then 保存
Exit Sub
End If
Dim k2 As Long, s As Long, z As String
s = MMC.Position
z = Format(s \ 60000, "00") & ":" & Format((s Mod 60000) \ 1000, "00") & "." & _
Format((s Mod 60000 Mod 1000) \ 10, "00") '将播放时间位置转换为时间字串
k2 = InStr(k1, ST, "~")
Label1.Caption = "[" & z & "]" & Mid$(ST, k1, k2 - k1)
LrcST = LrcST & vbCrLf & Label1.Caption
k1 = k2 + 1
End Sub
------------------------------------------------------------------------------------------
Command3_Click 过程中,“保存”Lrc 歌词文件的代码请自行编写(制作好的 Lrc 歌词文本在
字符型变量 LrcST 中)。
使用方法:首先点击 Command2,打开有关的 TXT 歌词文件,然后点击【播放】,这时候,你就要
认真听,当听到歌手将要唱到下一句时,就用鼠标点一下Command3,这样边听边点击地操作,一直到整
首歌曲唱完,最后保存。
如果我们用 MMControl控件制作了一个播放器,在播放乐曲的同时,一定也想显示歌词。目前比较
流行的是.Lrc歌词文件,它实际上也是纯文本文件,但它在每句歌词前面都加上了时间参数,这样,利
用 MMContro l控件的 Position 属性,我们就可以实时显示相应的歌词。
先来了解一下.Lrc歌词文件的基本结构,例如:
[ti:狼爱上羊]
[ar:一江秋水制作]
[al:2008年1月28日]
[00:00.01]《狼爱上羊》(歌手:汤潮)
[00:29.97]北风呼呼地刮
[00:33.19]雪花飘飘洒洒
……
我们看到,前面三行(有些 Lrc文件可能有四、五行)是歌词文件的一些信息,无关紧要,所以我
们在使用自制的播放器播放或制作歌词文件时,就可以去掉这些内容,后面才是正式的歌词句,在每一
歌词句的前面,都用方括号表示了该句的显示时间,时间格式是分、秒、毫秒,都用两位数字表示。
但是,我们从网上下载的 Lrc文件,常常与实际的歌曲衔接不上,这是因为 Lrc文件的制作者所使
用的歌曲版本与我们所使用的不一致,造成时间参数与歌曲进度不同步。例如上面那首《狼爱上羊》,
第一个歌词句的显示时间是29秒970毫秒,这是因为我从网上下载的歌曲前面有29秒多的过门,过后才是
歌手的声音,如果你下载的《狼爱上羊》前面只有15秒的过门,那么这个 Lrc文件就显然会与歌曲衔接
不上。所以,我们自制的播放器不但要能够显示 Lrc歌词文件,还要能够制作它。
一、显示 Lrc 歌词的方法
在显示歌词的代码中,首先取出时间字串,转换成毫秒,再与Position属性比较,如果相差不多,
就将时间字串后面的歌词句字串显示出来。
MMControl 控件的 Position属性的作用是:根据指定的 TimeFormat返回已打开的设备的位置,一
般用四字节表示,只读。在使用Position属性之前,要先设置属性 TimeFormat=0,这样Position属性
返回的时间单位就是毫秒了。
歌词句是显示在屏幕下方的(如果你想显示在播放器窗体中,那也只要进行简单的修改就行了),
并且从右向左迅速移动,最终停止在屏幕左下方。
好,我们就开始试验吧。
新建一个工程,添加两个窗体Form1和Form3。Form1是播放器窗体,在上面要添加一个 MMControl
控件(将其名称改为MMC),一个 CommonDialog 控件(改其名称为 CD)、一个按纽控件,和其它你认
为需要的控件。Form3是显示歌词用的,在上面添加一个标签和一个计时器,属性设置为:
Form3窗体:
----------
BackColor:黑色
BorderStyle:0
Height:495
Label1标签:
-----------
Font:楷体_GB2312,小一号,粗体
ForeColor:白色
AutoSize:True
BackStyle:0
Height:495
Top:0
Timer1计时器:
------------
Inteval:20
模块的代码:
------------------------------------------------------------------------------------------
Declare Function SetLayeredWindowAttributes Lib "user32" (ByVal hWnd As Long, _
ByVal crKey As Long, ByVal bAlpha As Byte, ByVal dwFlags As Long) As Long
Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd _
As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Declare Function SetWindowPos Lib "user32" (ByVal hWnd As Long, ByVal _
hWndInsertAfter As Long, ByVal X As Long, ByVal Y As Long, ByVal cx As Long, _
ByVal cy As Long, ByVal wFlags As Long) As Long
Public ST As String '歌词文本
Public BJForm3 As Boolean 'Form3调出标记
------------------------------------------------------------------------------------------
Form1的有关代码:
------------------------------------------------------------------------------------------
Option Explicit
Dim BJMode As Boolean 'True-显示歌词;False-制作歌词
Private Sub Command1_Click() '读 lrc 文件
On Error GoTo 100
Dim z As String
CD.Flags = &H1808
CD.DialogTitle = "打开 lrc 歌词文件"
CD.Filter = "Lrc 歌词文件(*.lrc)|*.lrc"
CD.ShowOpen
If Dir(CD.FileName) = "" Then Exit Sub
ST = ""
Open CD.FileName For Input As #1
Do Until EOF(1)
Line Input #1, z
If Len(z) > 0 Then ST = ST & z & "~" '用这个不常用的字符"~"作为歌词句的分隔符
Loop
BJMode = True
100
Close
End Sub
Private Sub 播放_Click()
With MMC
.FileName = "(MP3歌曲的全路径文件名)" '以播放MP3为例
.Command = "Open"
.TimeFormat = 0 '时间格式为毫秒
.Notify = True '打开通知
.Command = "play"
End With
If BJMode Then Form3.Show
End Sub
Private Sub MMC_Done(NotifyCode As Integer)
If NotifyCode = 1 Then '如果播放完毕
If BJForm3 Then Unload Form3
MMC.Command = "stop"
MMC.Command = "close"
End If
End Sub
Private Sub Form_Unload(Cancel As Integer)
If BJForm3 Then Unload Form3
End Sub
------------------------------------------------------------------------------------------
Form3的代码:
------------------------------------------------------------------------------------------
Option Explicit
Dim LrcST As String '歌词句字串
Dim k1 As Long '歌词句在文件中的起始位置
Dim k2 As Long '歌词句的长度
Dim t As Long
Private Sub Form_Load()
SetWindowLong hWnd, -20, &H80000
SetLayeredWindowAttributes hWnd, 0, 0, 1 '将窗体背景黑色设为透明
SetWindowPos hWnd, -1, 0, 0, 0, 0, 3& '窗体总在最上
Move 0, Screen.Height - 540, Screen.Width '将窗体设置到屏幕下方,其宽度与屏幕宽度相同
BJForm3 = True: k1 = 1
End Sub
Private Sub Timer1_Timer()
Dim s As String
If t < Form1.MMC.Position Then
Do
k2 = InStr(k1, ST, "~")
LrcST = Mid$(ST, k1, k2 - k1) '从歌词句中取出含有方括号的字串
k1 = IIf(k2 + 10 > Len(ST), 1, k2 + 1) '设置下一个歌词句在文件中的起始位置
s = Mid$(LrcST, 2, InStr(LrcST, "]") - 2) '取出去掉了方括号的字串
Loop Until IsNumeric(Left$(s, 2)) '如果是时间字串就退出Do循环
t = Val(s) * 60000 + Val(Mid$(s, 4)) * 1000 '将时间字串转换为毫秒
End If
If Abs(Form1.MMC.Position - t) < 200 Then '如果歌词与播放进度的时间差小于200毫秒
t = 0
Label1.Left = Width
Label1.Caption = Mid$(LrcST, InStr(LrcST, "]") + 1) '取出歌词字串
Do
Label1.Left = Label1.Left - 150
DoEvents
Loop Until Label1.Left < 300
End If
End Sub
Private Sub Form_Unload(Cancel As Integer)
BJForm3 = False
End Sub
------------------------------------------------------------------------------------------
在 Timer1_Timer 过程中,第一个 Do 循环的目的是不显示诸如[ti:****]、[ar:****]、
[al:****]、[by:****]这样的内容,如果 Lrc文件是自己制作的,没有这些东东,那么也可以
去掉 Do 和 Loop 这两行代码。第二个 Do 循环的作用是将 Label1 标签从屏幕右外方移至屏幕左。
二、制作 Lrc 歌词文件的方法
要制作 Lrc 歌词文件,首先要有同名的 TXT 歌词文件,可以在网上下载,也可以自己编制。
在 Form1 窗体上再添加一个 Label1 标签,和两个按纽控件,Command2 的作用是读入 TXT歌词文
件,Command3的作用是在歌词句的前面加上含方括号的时间参数,标签的作用是将制作好的含时间参数
的歌词句显示出来。标签的 AutoSize 属性设置为 True。
Form1的有关代码:
------------------------------------------------------------------------------------------
Option Explicit
Dim LrcST As String '歌词文本
Dim k1 As Long '歌词句在TXT歌词文件中的起始位置
Sub Command2_Click()
On Error GoTo 100
CD.Flags = &H1808
CD.DialogTitle = "打开 txt 歌词文件"
CD.Filter = "txt 歌词文件(*.txt)|*.txt"
CD.ShowOpen
If Dir(CD.FileName) <> "" Then
Dim z As String
ST = ""
Open CD.FileName For Input As #1
Do Until EOF(1)
Line Input #1, z
If Len(z) > 0 Then ST = ST & z & "~"
Loop
k1 = InStr(ST, "~") + 1
LrcST = "[00:00.01]" & Left$(ST, k1 - 2)
Label1.Caption = LrcST
End If
BJMode = False
100
Close
End Sub
Private Sub Command3_Click()
If k1 > Len(ST) - 2 Then
If MsgBox("已完成,是否保存 Lrc 歌词文件?", 4, "注意") = 6 Then 保存
Exit Sub
End If
Dim k2 As Long, s As Long, z As String
s = MMC.Position
z = Format(s \ 60000, "00") & ":" & Format((s Mod 60000) \ 1000, "00") & "." & _
Format((s Mod 60000 Mod 1000) \ 10, "00") '将播放时间位置转换为时间字串
k2 = InStr(k1, ST, "~")
Label1.Caption = "[" & z & "]" & Mid$(ST, k1, k2 - k1)
LrcST = LrcST & vbCrLf & Label1.Caption
k1 = k2 + 1
End Sub
------------------------------------------------------------------------------------------
Command3_Click 过程中,“保存”Lrc 歌词文件的代码请自行编写(制作好的 Lrc 歌词文本在
字符型变量 LrcST 中)。
使用方法:首先点击 Command2,打开有关的 TXT 歌词文件,然后点击【播放】,这时候,你就要
认真听,当听到歌手将要唱到下一句时,就用鼠标点一下Command3,这样边听边点击地操作,一直到整
首歌曲唱完,最后保存。