利用Delphi开发LRC歌词编辑器

来源 :电脑知识与技术 | 被引量 : 0次 | 上传用户:gaowufida
下载到本地 , 更方便阅读
声明 : 本文档内容版权归属内容提供方 , 如果您对本文有版权争议 , 可与客服联系进行内容授权或下架
论文部分内容阅读
  摘要:论述了如何利用Delphi开发LRC歌词编辑器,包括LRC歌词的编辑、显示以及保存。
  关键词:LRC;Mp3;歌词编辑
  中图分类号:TP311文献标识码:A 文章编号:1009-3044(2007)18-31663-04
  Using Delphi development LRC lyrics Editor
  WU Chao-bin
  (Fujian College of Water Conservancy Electirc Power,Yong'an 366000,China)
  Abstract: Discusses how to use Delphi development LRC lyrics editor, including lyrics of the LRC editing, display and preservation.
  Key words:LRC; MP3; lyrics editing
  
  1 引言
  
  LRC歌词是一种包含着“[min:sec:msec]”形式的时间标签的、基于纯文本的歌词专用格式。因为是基于纯文本的格式,所以在电脑上能够方便的编辑。其中的时间标签“[min:sec:msec]”就是用于说明本句歌词在什么时候需要显示(min是分钟值、sec是秒钟值,msec是毫秒值)。例如,以下是阿杜《他一定很爱你》的LRC歌词
  [ti:他一定很爱你]
  [ar:阿杜]
  [al:]
  [offset:-100]
  [00:03.31]他一定很爱你
  [00:34.24]我躲在车里 手握著香槟
  [00:38.42]想要给你 生日的惊喜
  [00:43.44]你越走越近 有两个声音
  [00:47.62]我措手不及 只得楞在那里
  [00:56.81][01:53.65]我应该在车底 不应该在车里
  [01:01.83][01:57.83]看到你们有多甜蜜
  [01:06.01][02:02.69]这样一来我也 比较容易死心
  [01:11.02][02:07.86]给我离开的勇气
  [01:16.04][02:14.55][02:49.66]他一定很爱你 别把我比下去
  [01:22.72][02:19.57][02:54.68]分手也只用了一分钟而已
  [01:27.74][02:23.75][02:58.86]他一定很爱你 比我会讨好你
  [01:32.76][02:28.76][03:03.87]不会像我这样孩子气 为难着你
  其中:offset表示时间整体偏移量,正值表示时间往后偏移,负值表示时间往前偏移。
  
  2 程序实现
  
  2.1 程序界面
  图1
  2.2 歌词编辑方法
  首先打开MP3文件,再打开对应的歌词文件(TXT或LRC格式)。单击“播放”按钮,开始播放歌曲,播放歌曲时,在相应的时间标签上单击,即可将当前时间添加至时间标签。歌曲播放完毕后,此时单击时间标签,不会将当前时间添加至时间标签,这样可以修改有错误的时间标签。
  2.3 MP3文件的播放以及LRC歌词的显示
  为了便于歌词的编辑以及观察编辑的歌词的时间标签是否有误,程序要能够播放MP3文件并能显示LRC歌词。播放MP3文件,这里使用ActiveX控件中的Windows Media Player。安装方法为:单击“Component”菜单下的“Import ActiveX Control …”,在弹出的对话框中选择“Windows Media Player”,将类名改为“TMediaPlay”然后单击“install”按钮。
  2.3.1 以下是播放歌曲时将LRC歌词读到数组mgc中的代码。数组mgc中,mgc[i,1],mgc[i,2],mgc[i,3],mgc[i,4]用来存放时间标签,mgc[i,5]用来存放对应的歌词。
  procedure TForm1.PlaySpeedButtonClick(Sender: TObject);
  varfname,s,s1:string;
   F:textFile;
   min,sec,msec,i,j,l:integer;
  begin
  if fileexists(combobox1.Text) then
  begin
  try
  Form1.MediaPlay1.FileName:=ComboBox1.Text;
  Form1.MediaPlay1.Play;
  l:=round(Form1.MediaPlay1.Duration*1000);
  Trackbar1.Max:=l div 1000;
  //显示歌曲总时间
  min:=ldiv 1000 div 60;
  sec:=l div 1000 -min*60;
  Form1.Label2.Caption:=format('%2u:%2u',[min,sec]);
  Timer1.Enabled:=true;
  canclick:=true;
  except
  begin
   timer1.Enabled:=false;
   canclick:=false;
   messagedlg('不支持的文件格式或其他程序占用音频设备!',mtError,[mbYes],0);
  end;
  end;
  end
  else
  begin
  showmessage('文件不存在!');
  timer1.Enabled:=false;
  end;
  fname:=changeFileExt(ComboBox1.text,'.lrc');
  if fileexists(fname) then
  begin
  toolbar2.Visible:=true;
   AssignFile(F, fname);
   Reset(F);
  //读歌词
  mgcn:=0;
  moffset:=0;
  for i:=1 to 100 do
  for j:=1 to 5 do
  mgc[i,j]:='';
  while not eof(F) do
  begin
  readln(F,s);
  s:=trim(s);
  l:=length(s);
  s1:=copy(s,2,6);moffset:=0;
  if (l>10) and (s1='offset') then moffset:=StrToInt(copy(s,9,l-9));
  if (l>10)and (s[3]>='0') and (s[3]<='9') and (s[1]='[') and (s[10]=']') and (s[11]<>'[') then
  begin
  mgcn:=mgcn+1;
  msec:=StrToInt(copy(s,2,2))*60*1000+StrToInt(copy(s,5,2))*1000+
  StrToInt(copy(s,8,2))*10;
  mgc[mgcn,1]:=IntToStr(msec);
  mgc[mgcn,5]:=copy(s,11,l);
  end;
  
  if (l>20)and(s[1]='[') and (s[10]=']') and
  (s[11]='[') and (s[20]=']') and(s[21]<>'[') then
  begin
  mgcn:=mgcn+1;
  msec:=StrToInt(copy(s,2,2))*60*1000+StrToInt(copy(s,5,2))*1000+
  StrToInt(copy(s,8,2))*10;
  mgc[mgcn,1]:=IntToStr(msec);
  msec:=StrToInt(copy(s,12,2))*60*1000+StrToInt(copy(s,15,2))*1000+
  StrToInt(copy(s,18,2))*10;
  mgc[mgcn,2]:=IntToStr(msec);
  mgc[mgcn,5]:=copy(s,21,l);
  end;
  
  if (l>30)and(s[1]='[') and (s[10]=']') and
  (s[11]='[') and (s[20]=']') and
  (s[21]='[') and (s[30]=']') and
  (s[31]<>'[') then
  begin
  mgcn:=mgcn+1;
  msec:=StrToInt(copy(s,2,2))*60*1000+StrToInt(copy(s,5,2))*1000+
  StrToInt(copy(s,8,2))*10;
  mgc[mgcn,1]:=IntToStr(msec);
  msec:=StrToInt(copy(s,12,2))*60*1000+StrToInt(copy(s,15,2))*1000+
  StrToInt(copy(s,18,2))*10;
  mgc[mgcn,2]:=IntToStr(msec);
   msec:=StrToInt(copy(s,22,2))*60*1000+StrToInt(copy(s,25,2))*1000+
  StrToInt(copy(s,28,2))*10;
  mgc[mgcn,3]:=IntToStr(msec);
  mgc[mgcn,5]:=copy(s,31,l);
  end;
  if (l>40)and(s[1]='[') and (s[10]=']') and
  (s[11]='[') and (s[20]=']') and
  (s[21]='[') and (s[30]=']') and
  (s[31]='[') and (s[40]=']') and
  (s[41]<>'[') then
  begin
  mgcn:=mgcn+1;
  msec:=StrToInt(copy(s,2,2))*60*1000+StrToInt(copy(s,5,2))*1000+
  StrToInt(copy(s,8,2))*10;
  mgc[mgcn,1]:=IntToStr(msec);
  msec:=StrToInt(copy(s,12,2))*60*1000+StrToInt(copy(s,15,2))*1000+
  StrToInt(copy(s,18,2))*10;
  mgc[mgcn,2]:=IntToStr(msec);
  msec:=StrToInt(copy(s,22,2))*60*1000+StrToInt(copy(s,25,2))*1000+
  StrToInt(copy(s,28,2))*10;
  mgc[mgcn,3]:=IntToStr(msec);
  msec:=StrToInt(copy(s,32,2))*60*1000+StrToInt(copy(s,35,2))*1000+
  StrToInt(copy(s,38,2))*10;
  mgc[mgcn,4]:=IntToStr(msec);
  
  mgc[mgcn,5]:=copy(s,41,l);
  end;
  end;
  //读歌词结束
  closefile(F);
  Timer2.Enabled:=true;
  end
  else
  begin
  toolbar2.Visible:=false;
  Timer2.Enabled:=false;
  end;
  end;
  2.3.2 歌词编辑是否正确,需要进行验证,以下是利用时间控件,在label3标签中显示LRC歌词的代码
  procedure TForm1.Timer2Timer(Sender: TObject);
  var msec,i,j,l:integer;
  begin
  l:=round(Form1.MediaPlay1.CurrentPosition*1000);
  //在Label3中显示歌词
  for i:=1 to mgcn do
  for j:=1 to 4 do
  begin
  if mgc[i,j]<>'' then
  begin
  msec:=StrToInt(mgc[i,j]);
  if abs(msec-l-moffset)<150 then
  Label3.Caption:=mgc[i,5];
  end;
  end;
  end;
  2.4 编辑LRC歌词的代码
  2.4.1 将歌词读入网格中
  procedure TForm1.OpenFSpeedButtonClick(Sender: TObject);
  var F:textfile;
  s,s1,ti,ar,al,offset:string;
  gc:array [1..100,1..5] of string;
  i,j,l,gcn:integer;
  begin
   OpenDialog1.Filter:='文本文件(*.txt)|*.txt|歌词文件(*.lrc)|*.lrc';
  if OpenDialog1.Execute then
  begin
  if Opendialog1.FilterIndex=1 then
  begin
  //读取txt文件格式,将歌词放到网格中
  AssignFile(F, OpenDialog1.FileName);
  Reset(F);
  for i:=1 to StringGrid1.RowCount-1 do
  for j:=0 to StringGrid1.ColCount-1 do
  StringGrid1.Cells[j,i]:='';
  i:=1;
  while not eof(F) do
  begin
  readln(F,s);
  s:=trim(s);
  if s<>'' then
  begin
  i:=i+1;
  StringGrid1.RowCount:=i;
  StringGrid1.Cells[4,i-1]:=s;
  end;
  end;
  closefile(F);
  end
  else
  begin
  AssignFile(F, OpenDialog1.FileName);
  Reset(F);
  //读LRC歌词,将时间标签和歌词读到数组 gc 中
   gcn:=0;
  ar:=''; ti:=''; al:=''; offset:='';
  for i:=1 to 100 do
  for j:=1 to 5 do
  gc[i,j]:='';
  while not eof(F) do
  begin
  readln(F,s);
  s:=trim(s);
  l:=length(s);
  s1:=copy(s,2,2) ;
  if s1='ar' then ar:=copy(s,5,l-5);
  if s1='ti' then ti:=copy(s,5,l-5);
  if s1='al' then al:=copy(s,5,l-5);
  s1:=copy(s,2,6);
  if s1='offset' then offset:=copy(s,9,l-9);
  if (l>10)and(s[1]='[') and (s[10]=']') and (s[11]<>'[') then
  begin
  gcn:=gcn+1;
  gc[gcn,1]:=copy(s,1,10);
  gc[gcn,5]:=copy(s,11,l);
  end;
  
  if (l>20)and(s[1]='[') and (s[10]=']') and
  (s[11]='[') and (s[20]=']') and(s[21]<>'[') then
  begin
  gcn:=gcn+1;
  gc[gcn,1]:=copy(s,1,10);
  gc[gcn,2]:=copy(s,11,10);
  gc[gcn,5]:=copy(s,21,l);
  end;
  if (l>30)and(s[1]='[') and (s[10]=']') and
  (s[11]='[') and (s[20]=']') and
  (s[21]='[') and (s[30]=']') and
  (s[31]<>'[') then
  begin
  gcn:=gcn+1;
  gc[gcn,1]:=copy(s,1,10);
  gc[gcn,2]:=copy(s,11,10);
  gc[gcn,3]:=copy(s,21,10);
  gc[gcn,5]:=copy(s,31,l);
  end;
  if (l>40)and(s[1]='[') and (s[10]=']') and
  (s[11]='[') and (s[20]=']') and
  (s[21]='[') and (s[30]=']') and
  (s[31]='[') and (s[40]=']') and
  (s[41]<>'[') then
  begin
  gcn:=gcn+1;
  gc[gcn,1]:=copy(s,1,10);
  gc[gcn,2]:=copy(s,11,10);
  gc[gcn,3]:=copy(s,21,10);
  gc[gcn,4]:=copy(s,31,10);
  gc[gcn,5]:=copy(s,41,l);
  end;
  end;
  //读歌词结束,将时间标签和歌词文件放入网格中
  Edit2.Text:=ti;
  Edit3.Text:=ar;
  Edit4.Text:=al;
  Edit5.Text:=offset;
  StringGrid1.RowCount:=gcn+1;
  for i:=1 to gcn do
  forj:=0 to 4 do
  StringGrid1.Cells[j,i]:=gc[i,j+1];
  closeFile(F);
  end;
  end;
  end;
  2.4.2 将歌曲播放的当前时间放到文本框中。
  procedure TForm1.Timer1Timer(Sender: TObject);
  var min,sec,msec,len:integer;
  s:string;
  t:TDateTime;
  begin
   len:=round(Form1.MediaPlay1.CurrentPosition*1000);
   Form1.TrackBar1.Position:=len div 1000;
   oldpos:=len div 1000;
   min:=len div 1000 div 60;
   sec:=len div 1000-min*60;
   msec:=len mod 1000;
   s:=format('%2d:%2d:%2d.%3d',[0,min,sec,msec]);
   t:=StrToDatetime(s);
   Form1.Edit1.text:=formatDateTime('nn:ss.zzz',t);
   //播放结束时的操作
   if (Form1.MediaPlay1.Duration*1000-len)<300 then
   Form1.StopSpeedButtonClick(sender);
  end;
  2.4.3 单击网格相应位置,将当前时间添加到时间标签中
  procedure TForm1.StringGrid1Click(Sender: TObject);
  begin
  if canclick and (StringGrid1.col<4) then
  StringGrid1.Cells[StringGrid1.Col,StringGrid1.Row]:=
  '['+copy(Edit1.Text,1,8)+']';
  end;
  2.5 保存编辑好的LRC歌词
  LRC歌词编辑完成后,需要将其保存,以下是保存LRC歌词的代码。
  procedure TForm1.SaveSpeedButtonClick(Sender: TObject);
  var F:textFile;
  i,j:integer;
  fname,s:string;
  begin
  //保存歌词文件
  saveDialog1.InitialDir:=mdir;
  SaveDialog1.FileName:=changeFileExt(ComboBox1.text,'.lrc');
  if SaveDialog1.Execute then
  begin
  fname:=saveDialog1.FileName;
  AssignFile(F, fname);
  Rewrite(F);
  writeln(F,'[ti:'+Edit2.text+']');
  writeln(F,'[ar:'+Edit3.text+']');
  writeln(F,'[al:'+Edit4.text+']');
  writeln(F,'[offset:'+Edit5.text+']');
  for i:=1 to StringGrid1.RowCount-1 do
  begin
  s:='';
  for j:=0 to StringGrid1.ColCount-1 do
  s:=s+StringGrid1.Cells[j,i];
  writeln(F,s);
  end;
  closefile(F);
  end;
  end;
  以是代码在Delphi 7.0中调试通过。
  
  3 结束语
  
  本文详细介绍了如何利用Delphi开发一个LRC歌词编辑器,并给出了全部源代码,广大的Delphi编程爱好者可以在此文的基础上,开发出功能更完整的LRC歌词编辑器。
  
  参考文献:
  [1]明日科技. Delphi开发技术大全[M]. 人民邮电出版社,2007.
  [2]明日科技. Delphi组件参考大全[M]. 人民邮电出版社,2006.
  [3]吕伟臣. 精通Delphi 7.0 [M].科学出版社,2004.
  注:本文中所涉及到的图表、注解、公式等内容请以PDF格式阅读原文。
其他文献
摘要:本文介绍了ARP病毒的特点及病毒发作时对局域网的影响,重点介绍了如何查找ARP病毒的根源及清除方法,最后介绍了日常对付ARP病毒的防护方法。  关键词:ARP攻击;局域网;互联网;MAC地址;IP地址  中图分类号:TP393文献标识码:B文章编号:1009-3044(2007)17-31238-01  Solves the Local Area Network which the ARP
期刊
摘要:ARP(AddressResolutionProtocol)地址解析协议用于将计算机的网络IP地址转化为物理MAC地址。 ARP病毒是一种地址欺骗的病毒,ARP病毒通过伪造IP地址和MAC地址实现ARP欺骗,进行ARP重定向和嗅探攻击,用伪造源MAC地址发送ARP响应包,网内PC机的ARP缓存表混乱,网络中产生大量的ARP通信量使网络阻塞。ARP攻击在现今的网络中频频出现,有效的防范ARP形
期刊
摘要:随着计算机网络日益深入人们的日常生活和工作,人们已经不仅仅局限于独立地使用内部专用网络和公共互联网络,而是要利用Internet技术建立自己的内部网。本文介绍了VPN的分类,VPN的特性,涉及的隧道技术、加密、解密技术、认证系统和PPTP协议、L2TP协议、IPSec协议等技术,以及VPN在实际运用中的解决方案和优缺点。  关键词:虚拟;专用;隧道;协议;安全;方案  中图分类号:TP393
期刊
摘要:本文针对家庭网络分布式环境,探讨基于XML语言描述信息家电基本信息的方法,实现了基于JSP+JavaBean+Servlet发布信息家电信息,并自动形成远程的控制界面,同时利用JavaRMI技术实现远程对信息家电的控制,这对于信息家电远程控制的实际应用具有重要意义。  关键词:XML;信息家电;JavaRMI;JSP+JavaBean+Servlet  中图分类号:TP319 文献标识码:A
期刊
摘要:介绍CAN(控制局域网)总线的特点,对CAN总线智能通信节点的工作原理进行了分析,给出了采用AT89S52型单片机构成的通信节点电路原理图和应用单片机汇编语言编写的SJA1000初始化程序,通过节点的软硬件设计,说明了CAN总线的技术优势和应用前景。  关键词:CAN总线; SJA1000; 智能节点; AT89S52  中图分类号:TP393文献标识码:A 文章编号:1009-3044(2
期刊
摘要:本文针对当前存在的信用缺失问题,就如何设计和实现一个基于.Net架构的信用信息交换支撑平台进行了深入研究和分析。从系统结构、数据交换拓扑结构、主要组件、数据交换过程等方面进行了论述,给出了一个基于.NET架构的信用信息交换支撑平台的设计与实现方案。  关键词:信用信息,数据交换,.NET  中图分类号:TP311文献标识码:A 文章编号:1009-3044(2007)17-31185-02 
期刊
摘要:ARP协议主要实现了网络层地址到数据链路层地址的动态映射,并且ARP协议具有无序性、无确认性、动态性、无安全机制等特性。利用这些特性,攻击者可以较容易的实现在局域网内的ARP欺骗攻击,本文详细描述了利用ARP协议的特性进行欺骗攻击的原理和过程,包括主动攻击和被动攻击,表现形式有伪造ARP应答包和克隆主机。最后,提出了针对攻击可以采取的一些策略。  关键词:ARP;网络攻击;网络防御  中图分
期刊
摘要:本文主要探讨了P2P技术及其网络模式中单个主机系统的网络安全策略分析,首先,对P2P概念、网络模型进行分析,指出P2P技术应用的特点,存在的安全问题;接着提P2P网络中Windows系统存在的安全问题及应对策略,最后提出防范措施和技巧。  关键词:P2P,网络安全,Windows系统,策略   中图分类号:TP393文献标识码:A文章编号:1009-3044(2007)17-31266-01
期刊
摘要:多重Agent系统(MAS)已经成为系统开发设计的标准规范,通过智能Agent的特性,可以让系统开发人员可以构建更具效率与弹性的应用系统。本文参考工作流程管理联盟(WfMC)提出的一般化工作流程产品架构,并结合多Agent的设计概念,提出以多Agent为基础的工作流程管理系统的框架,并在JADE平台进行实现。  关键词:工作流程控制;多Agent  中图分类号:TP391 文献标识码:A文章
期刊
摘要:随着网络技术的不断发展,传统的防火墙已经逐渐不能满足网络安全的需要。针对有传统防火墙所带来的问题,提出了一种基于Kerberos认证的分布式防火墙的新型体系结构,在保留传统防火墙优点的基础上,解决了传统防火墙的不安全隐患。为大量内部网络用户,需要重点保护的网络资源提供一个可管理的、分布式的安全网络环境。  关键词:Kerberos协议;分布式防火墙系统;防火墙  中图分类号:TP393文献标
期刊