代码之家  ›  专栏  ›  技术社区  ›  caw

歌词流(Delphi/伪代码)[关闭]

  •  1
  • caw  · 技术社区  · 16 年前

    我想建立一个程序,让歌词的歌曲运行在屏幕上。大概是这样的:

    http://www.youtube.com/watch?v=kIAiBvD9njM

    你能帮助我吗?

    算法:

    • 将标记器推到适合音乐的线条右侧
    • 使当前行上方的行消失
    • 在当前行上方插入新行

    需要什么?

    • 到文本数据的时间(线路何时开始/结束)

    4 回复  |  直到 14 年前
        1
  •  3
  •   PA.    16 年前

    假设您有一个文本文件,其中包含要显示的文本以及高亮显示的注释时间(类似于字幕文件,例如标准提案w3c定时文本)( http://www.w3.org/AudioVideo/TT/ )或者多个媒体播放器使用的子电影字幕文件格式。

    您的程序必须首先读取和解析文本文件,并解码带注释的时间。将其插入名为Subtitles的stringlist中,其中的项目也会保留与此类似的对象

    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
  •  5
  •   Wouter van Nifterick Andrey    16 年前

    如果您对pascal中的卡拉OK代码感兴趣,请务必查看 UltraStar豪华酒店 .

    http://ultrastardx.sourceforge.net/

    在我找到这个程序之前,我的邻居认为我的狗是他们最可怕的噩梦。

    在行动中看到它: po-po-po-pokerface po-po-pokerface.. mum mum mum mah! :)

        3
  •  2
  •   skamradt    16 年前

    另一个选项是创建您自己的标记,该标记包含文本和延迟时间。虽然计时器可以工作,但问题是,随着时间的推移,计时器的准确性不足以为您提供可靠的结果,因为它是基于消息触发的。相反,我将根据您希望事件发生的距离音乐文件开头的距离来执行触发器。这也允许系统在其他应用程序阻塞过程受阻时赶上,并有助于保持同步。

    简单到:

    00:00:15;LYRIC;This is lyric line 1
    00:00:18;FADEOUT
    

    然后,您可以将其解析为采取适当操作的适当对象列表。

        4
  •  0
  •   delphigeist    16 年前

    您应该基于TGraphicControl/TCustomControl(任何具有画布的对象)创建一个新类,并添加一个string属性,现在您必须创建一个计时器作为私有变量,其间隔值通过类发布,类似于 ...

    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;
    

    剩下的就看你了,在你所有的付出之后,为它工作吧:)

    推荐文章