我想建立一个程序,让歌曲的歌词在屏幕上运行。像这样:
http://www.youtube.com/watch?v=kIAiBvD9njM
你能帮助我吗?
算法:
需要什么?
有些方法对我有很大帮助。任何部分的伪代码甚至Delphi代码都会很棒。
答案 0 :(得分:5)
如果您对pascal中的卡拉OK代码感兴趣,请务必查看 UltraStar Deluxe 。
这是一款超级光滑且非常受欢迎的卡拉OK应用程序。该项目是活跃的,它是开源的。它可以使用FPC编译到各种平台。你可以从Delphi和Lazarus编译它..很好。
http://ultrastardx.sourceforge.net/
我的邻居认为我的狗是他们最糟糕的噩梦,直到我找到了这个程序。
查看实际操作:po-po-po-pokerface po-po-pokerface.. mum mum mum mah!:)
答案 1 :(得分:3)
假设您有一个文本文件,其中包含要显示的文本以及何时高亮显示的注释时间(字幕文件的种类,例如标准提案w3c定时文本(http://www.w3.org/AudioVideo/TT/)或SUB - 多个媒体播放器使用的电影字幕文件格式。
您的程序必须首先读取并解析文本文件,然后解码带注释的时间。将它插入名为Subtitles的字符串列表中,哪些项目也会保留与此类似的对象
type tSubtitle = class
num : integer;
prevTime, fromTime : tdatetime;
toTime, nextTime: tdatetime;
text: string;
end;
您可能希望扩展对象以保留一些突出显示属性。
然后你只需要显示与计时器同步的那些对象。
procedure TForm1.Timer1Timer(Sender: TObject);
var rt : TDateTime;
done:boolean;
si,st,sb:integer;
s:string;
begin
rt:=now-startTime;
st:=0;
sb:=subtitles.Count; // binary search the subtitle for the current time
repeat
si:=(st+sb) div 2;
s:=TSubtitle(subtitles.Objects[si-1]);
done:= ((t>=s.prevTime) and (t<=s.nextTime));
if not done then
begin
if t>s.prevTime then st:=si
else if t<s.nextTime then sb:=si;
if st=sb then done:=true;
end;
until done;
// do what you want with s
end;
答案 2 :(得分:2)
另一种选择是创建您自己解析的标记,其中包含文本和延迟时间。虽然定时器可以正常工作,但问题是随着时间的推移,它不够准确,无法提供可靠的结果,因为它基于消息传递而被解雇。相反,我会根据您希望事件发生的音乐文件开头的距离来执行触发器。如果某些其他应用程序拦截过程受阻,这也可以让系统赶上来,并且应该有助于保持同步。
简单的事情:
00:00:15;LYRIC;This is lyric line 1
00:00:18;FADEOUT
然后,您可以将其解析为采取适当操作的相应对象列表。
答案 3 :(得分:0)
你应该基于TGraphicControl / TCustomControl(任何带有画布的东西)创建一个新类并添加一个字符串属性,现在你必须创建一个定时器作为私有变量,并通过你的类发布它的间隔值,就像这样 ...
type TLyricViewer = class(TGraphicControl)
private
FTimer : TTimer;
FLyric : string;
FBitmap : TBitmap;// offset bitmap on which you draw
// some more variables to store paint information
private
procedure OnNextWord(Sender: TObject);// assign this to FTimer.OnTimer event
public
constructor Create(AOwner: TComponent);
destructor Destroy; override;
public
procedure StartLyric;
procedure StopLyric;
procedure Paint; override;
published
property WordInterval : Integer|Cardinal
read GetWordInterval write SetWordInterval;
end;
...
procedure TLyricViewer.Paint;
begin
// here is where the magic happends
end;
constructor TLyricViewer.Create(AOwner: TComponent);
begin
// create timer, bitmap and set default properties
end;
destructor TLyricViewer.Destroy;
begin
// free and nil the timer and bitmap
inherited Destroy;
end;
剩下的由您决定,在您获得报酬之后,为此工作:)