Basic WebVTT Support + Sample VTTs on existing OpenTaiko Originals (#458)
* Basic WebVTT support for song lyrics * Sample VTTs for existing OpenTaiko Originals - DON'T LOOK BACK - Dear Stars - Forever Fading Away - TRIPLE HELIX
This commit is contained in:
parent
7b4f265d6f
commit
e6a5968021
@ -1309,6 +1309,8 @@ namespace TJAPlayer3
|
||||
public List<Bitmap> listLyric; //歌詞を格納していくリスト。スペル忘れた(ぉい
|
||||
public List<STLYRIC> listLyric2;
|
||||
|
||||
public bool usingLyricsFile; //If lyric file is used (VTT/LRC), ignore #LYRIC tags & do not parse other lyric file tags
|
||||
|
||||
private int listBalloon_Normal_数値管理;
|
||||
private int listBalloon_Expert_数値管理;
|
||||
private int listBalloon_Master_数値管理;
|
||||
@ -1379,6 +1381,7 @@ namespace TJAPlayer3
|
||||
this.MAKER = "";
|
||||
this.SELECTBG = "";
|
||||
this.bLyrics = false;
|
||||
this.usingLyricsFile = false;
|
||||
this.eジャンル = Eジャンル.None;
|
||||
this.PREVIEW = "";
|
||||
this.PREIMAGE = "";
|
||||
@ -4001,7 +4004,7 @@ namespace TJAPlayer3
|
||||
|
||||
this.listChip.Add(chip);
|
||||
}
|
||||
else if (command == "#LYRIC")
|
||||
else if (command == "#LYRIC" && !usingLyricsFile) // Do not parse LYRIC tags if a lyric file is already loaded
|
||||
{
|
||||
if (TJAPlayer3.r現在のステージ.eステージID == CStage.Eステージ.曲読み込み)//起動時に重たくなってしまう問題の修正用
|
||||
this.listLyric.Add(this.pf歌詞フォント.DrawPrivateFont(argument, TJAPlayer3.Skin.Game_Lyric_ForeColor, TJAPlayer3.Skin.Game_Lyric_BackColor));
|
||||
@ -5419,7 +5422,48 @@ namespace TJAPlayer3
|
||||
this.bHIDDENBRANCH = true;
|
||||
}
|
||||
}
|
||||
else if (strCommandName.Equals("LYRICFILE"))
|
||||
else if (strCommandName.Equals("LYRICS") && !usingLyricsFile)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(strCommandParam))
|
||||
{
|
||||
string[] files = SplitComma(strCommandParam);
|
||||
string[] filePaths = new string[files.Length];
|
||||
for (int i = 0; i < files.Length; i++)
|
||||
{
|
||||
filePaths[i] = this.strフォルダ名 + files[i];
|
||||
|
||||
if (File.Exists(filePaths[i]))
|
||||
{
|
||||
try
|
||||
{
|
||||
if (TJAPlayer3.r現在のステージ.eステージID == CStage.Eステージ.曲読み込み)
|
||||
{
|
||||
if (filePaths[i].EndsWith(".vtt"))
|
||||
{
|
||||
using (VTTParser parser = new VTTParser())
|
||||
{
|
||||
this.listLyric2.AddRange(parser.ParseVTTFile(filePaths[i], i, this.pf歌詞フォント));
|
||||
}
|
||||
this.bLyrics = true;
|
||||
this.usingLyricsFile = true;
|
||||
}
|
||||
else if (filePaths[i].EndsWith(".lrc"))
|
||||
{
|
||||
this.LyricFileParser(filePaths[i], i);
|
||||
this.bLyrics = true;
|
||||
this.usingLyricsFile = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.WriteLine("Something went wrong while parsing a lyric file. More details : {0}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (strCommandName.Equals("LYRICFILE") && !usingLyricsFile)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(strCommandParam))
|
||||
{
|
||||
@ -5435,6 +5479,7 @@ namespace TJAPlayer3
|
||||
if (TJAPlayer3.r現在のステージ.eステージID == CStage.Eステージ.曲読み込み)//起動時に重たくなってしまう問題の修正用
|
||||
this.LyricFileParser(strFilePath[index], index);
|
||||
this.bLyrics = true;
|
||||
this.usingLyricsFile = true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
235
TJAPlayer3/Songs/VTTParser.cs
Normal file
235
TJAPlayer3/Songs/VTTParser.cs
Normal file
@ -0,0 +1,235 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using static TJAPlayer3.CDTX;
|
||||
|
||||
namespace TJAPlayer3
|
||||
{
|
||||
public class VTTParser : IDisposable
|
||||
{
|
||||
/*
|
||||
|
||||
TO-DO :
|
||||
- Tag support (lang, timestamp, color(?), ruby/rt)
|
||||
- Adjust bitmap position/anchor when lyric contains newlines (currently snapped to top-center, gets trimmed going down) (also how on earth do i do this lmao)
|
||||
- NOTE support (for comments within file)
|
||||
|
||||
*/
|
||||
|
||||
private static string[] _vttdelimiter;
|
||||
|
||||
private static Regex regexTimestamp;
|
||||
private static Regex regexTag;
|
||||
|
||||
private static Regex regexOffset;
|
||||
private static Regex regexLang;
|
||||
|
||||
private bool _isDisposed;
|
||||
|
||||
public VTTParser()
|
||||
{
|
||||
_vttdelimiter = new[] { "-->", "- >", "->" };
|
||||
|
||||
regexTimestamp = new Regex(@"(-)?(([0-9]+):)?([0-9]+):([0-9]+)[,\\.]([0-9]+)");
|
||||
regexTag = new Regex(@"<[^>]*>"); // For now, all tags will be ignored & removed.
|
||||
|
||||
regexOffset = new Regex(@"Offset:\s*((-)?(([0-9]+):)?([0-9]+):([0-9]+)[,\\.]([0-9]+));?"); // i.e. "WebVTT Offset: 00:01.001;"
|
||||
regexLang = new Regex(@"Language:\s*([A-Za-z]+);?"); // i.e. "WebVTT Language: ja;"
|
||||
}
|
||||
|
||||
#region Dispose stuff
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!_isDisposed && disposing)
|
||||
{
|
||||
_vttdelimiter = null;
|
||||
regexTimestamp = null;
|
||||
regexTag = null;
|
||||
|
||||
regexOffset = null;
|
||||
regexLang = null;
|
||||
|
||||
_isDisposed = true;
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
internal List<STLYRIC> ParseVTTFile(string filepath, int order, CPrivateFastFont drawer)
|
||||
{
|
||||
List<STLYRIC> lrclist = new List<STLYRIC>() { };
|
||||
List<string> lines = File.ReadAllLines(filepath).ToList();
|
||||
long offset = 0;
|
||||
|
||||
// Header stuff
|
||||
if (lines[0].StartsWith("WEBVTT"))
|
||||
{
|
||||
Match languageMatch = regexLang.Match(lines[0]);
|
||||
if (languageMatch.Success)
|
||||
{
|
||||
if (!(languageMatch.Groups[1].Value.ToLower() == CLangManager.fetchLang()))
|
||||
{
|
||||
Debug.WriteLine("WebVTT header language does not match user's selected language. Aborting VTT parse.");
|
||||
return lrclist;
|
||||
}
|
||||
}
|
||||
Match offsetMatch = regexOffset.Match(lines[0]);
|
||||
if (offsetMatch.Success)
|
||||
{
|
||||
offset = ParseTimestamp(offsetMatch.Groups[1].Value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.WriteLine("WebVTT lyric file at {0} does not start with \"WEBVTT\". Aborting VTT parse.");
|
||||
return lrclist;
|
||||
}
|
||||
|
||||
List<(string, long)> lyrics = new List<(string, long)>() { };
|
||||
|
||||
long startTime = -1;
|
||||
long endTime = -1;
|
||||
string line = String.Empty;
|
||||
|
||||
for (int i = 1; i < lines.Count; i++) // Skip header line (line 0)
|
||||
{
|
||||
long start;
|
||||
long end;
|
||||
|
||||
if (TryParseTimestamp(lines[i], out start, out end))
|
||||
{
|
||||
if (start > endTime && endTime != -1)
|
||||
{
|
||||
lyrics.Add((string.Empty, endTime + offset));
|
||||
// If new start timestamp is greater than old end timestamp,
|
||||
// it is assumed there is a gap in-between displaying lyrics.
|
||||
}
|
||||
|
||||
if (startTime != -1)
|
||||
{
|
||||
lyrics.Add((line, startTime + offset));
|
||||
// When new timestamp is found,
|
||||
// create lyrics with existing timestamp.
|
||||
}
|
||||
|
||||
startTime = start;
|
||||
endTime = end;
|
||||
|
||||
line = string.Empty;
|
||||
}
|
||||
else // If timestamp parse failed, let's assume it's a lyric. ¯\_(ツ)_/¯
|
||||
{
|
||||
if (line != "") line += Environment.NewLine;
|
||||
line += String.Join(String.Empty, regexTag.Split(lines[i])); // Remove tags by splitting, then join back into single string
|
||||
}
|
||||
}
|
||||
lyrics.Add((line, startTime + offset));
|
||||
lyrics.Add((String.Empty, endTime + offset));
|
||||
|
||||
foreach ((string, long) lyric in lyrics)
|
||||
{
|
||||
lrclist.Add(CreateLyric(lyric, drawer, order));
|
||||
}
|
||||
|
||||
return lrclist;
|
||||
|
||||
}
|
||||
internal bool TryParseTimestamp(string input, out long startTime, out long endTime)
|
||||
{
|
||||
var split = input.Split(_vttdelimiter, StringSplitOptions.None);
|
||||
if (split.Length == 2 && regexTimestamp.IsMatch(split[0]) && regexTimestamp.IsMatch(split[1]))
|
||||
{
|
||||
startTime = ParseTimestamp(split[0]);
|
||||
endTime = ParseTimestamp(split[1]);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
startTime = -1;
|
||||
endTime = -1;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
internal long ParseTimestamp(string input)
|
||||
{
|
||||
int hours;
|
||||
int minutes;
|
||||
int seconds;
|
||||
int milliseconds = -1;
|
||||
|
||||
Match match = regexTimestamp.Match(input);
|
||||
if (match.Success)
|
||||
{
|
||||
hours = !string.IsNullOrEmpty(match.Groups[3].Value) ? int.Parse(match.Groups[3].Value) : 0; // Hours are sometimes not included in timestamps.
|
||||
minutes = int.Parse(match.Groups[4].Value);
|
||||
seconds = int.Parse(match.Groups[5].Value);
|
||||
milliseconds = int.Parse(match.Groups[6].Value);
|
||||
|
||||
TimeSpan result = new TimeSpan(0, hours, minutes, seconds, milliseconds);
|
||||
return (long)result.TotalMilliseconds * (match.Groups[1].Value == "-" ? -1 : 1);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
internal STLYRIC CreateLyric(string lyric, long time, CPrivateFastFont draw, int order)
|
||||
{
|
||||
return CreateLyric((lyric, time), draw, order);
|
||||
}
|
||||
internal STLYRIC CreateLyric((string, long) lyric, CPrivateFastFont draw, int order)
|
||||
{
|
||||
string[] split = lyric.Item1.Split(new string[]{"\\r\\n", "\\n", "\r\n", "\n"}, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
List<Bitmap> textures = new List<Bitmap>();
|
||||
int width = 1;
|
||||
int height = 1;
|
||||
|
||||
for (int i = 0; i < split.Length; i++)
|
||||
{
|
||||
textures.Add(draw.DrawPrivateFont(split[i], TJAPlayer3.Skin.Game_Lyric_ForeColor, TJAPlayer3.Skin.Game_Lyric_BackColor));
|
||||
width = width < textures[i].Width ? textures[i].Width : width;
|
||||
height += textures[i].Height;
|
||||
}
|
||||
|
||||
Bitmap texture = new Bitmap(width, height);
|
||||
|
||||
if (textures.Count != 0)
|
||||
{
|
||||
using (Graphics canvas = Graphics.FromImage(texture))
|
||||
{
|
||||
canvas.Clear(Color.Transparent);
|
||||
|
||||
Point pos = new Point(0, 0);
|
||||
foreach (Bitmap bitmap in textures)
|
||||
{
|
||||
pos.X = (width - bitmap.Width) / 2;
|
||||
canvas.DrawImage(bitmap, pos);
|
||||
pos.Y += bitmap.Height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
STLYRIC stlrc = new STLYRIC()
|
||||
{
|
||||
|
||||
Text = lyric.Item1,
|
||||
TextTex = texture,
|
||||
Time = lyric.Item2,
|
||||
index = order
|
||||
};
|
||||
|
||||
return stlrc;
|
||||
}
|
||||
}
|
||||
}
|
@ -152,6 +152,7 @@
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Songs\C曲リストノードComparers\C曲リストノードComparerLevel.cs" />
|
||||
<Compile Include="Songs\C曲リストノードComparers\C曲リストノードComparerSubtitle.cs" />
|
||||
<Compile Include="Songs\VTTParser.cs" />
|
||||
<Compile Include="Stages\01.StartUp\CCharacter.cs" />
|
||||
<Compile Include="Stages\01.StartUp\CPuchichara.cs" />
|
||||
<Compile Include="Stages\07.Game\Taiko\AIBattle.cs" />
|
||||
|
@ -4,6 +4,7 @@ BPM:200
|
||||
WAVE:DON'T LOOK BACK.ogg
|
||||
OFFSET:-0.0095
|
||||
DEMOSTART:44.082
|
||||
LYRICS:DON'T LOOK BACK.vtt
|
||||
SCOREMODE:2
|
||||
PREIMAGE:DLB.png
|
||||
MAKER:bol
|
||||
|
@ -0,0 +1,43 @@
|
||||
WEBVTT
|
||||
|
||||
01:18.205 --> 01:20.338
|
||||
Coming through straight, I rest my case (Do it, do it)
|
||||
|
||||
01:20.338 --> 01:22.472
|
||||
Hands up in the sunshine when we (Do it, do it)
|
||||
|
||||
01:22.472 --> 01:24.338
|
||||
You know that when the beat drop, I always need more
|
||||
|
||||
01:24.338 --> 01:25.672
|
||||
But that shawty says she with the glock so
|
||||
|
||||
01:25.672 --> 01:25.938
|
||||
DON'T
|
||||
|
||||
01:25.938 --> 01:26.205
|
||||
DON'T LOOK
|
||||
|
||||
01:26.205 --> 01:26.738
|
||||
DON'T LOOK BACK
|
||||
|
||||
01:26.738 --> 01:28.872
|
||||
Coming through straight, I rest my case (Do it, do it)
|
||||
|
||||
01:28.872 --> 01:31.005
|
||||
Hands up in the sunshine when we (Do it, do it)
|
||||
|
||||
01:31.005 --> 01:32.872
|
||||
You know that when the beat drop, I always need more
|
||||
|
||||
01:32.872 --> 01:34.205
|
||||
But that shawty says she with the glock so
|
||||
|
||||
01:34.205 --> 01:34.472
|
||||
DON'T
|
||||
|
||||
01:34.472 --> 01:34.738
|
||||
DON'T LOOK
|
||||
|
||||
01:34.738 --> 01:35.005
|
||||
DON'T LOOK BACK
|
@ -5,6 +5,7 @@ WAVE:stars.ogg
|
||||
OFFSET:-0.028
|
||||
MAKER:Dashy
|
||||
DEMOSTART:59.472
|
||||
LYRICS:stars.vtt
|
||||
PREIMAGE:stars.png
|
||||
BGMOVIE:stars.mp4
|
||||
|
||||
|
90
Test/Songs/08 OpenTaiko Original/038 - Dear Stars/stars.vtt
Normal file
90
Test/Songs/08 OpenTaiko Original/038 - Dear Stars/stars.vtt
Normal file
@ -0,0 +1,90 @@
|
||||
WEBVTT
|
||||
|
||||
00:00.732 --> 00:07.683
|
||||
another day has passed
|
||||
|
||||
00:07.683 --> 00:13.902
|
||||
and you've awakened as always
|
||||
|
||||
00:13.902 --> 00:20.488
|
||||
each and every million of stars, you're all
|
||||
|
||||
00:20.488 --> 00:25.427
|
||||
finally with me at last
|
||||
|
||||
00:25.427 --> 00:33.659
|
||||
so i ask to you, dear stars...
|
||||
|
||||
00:36.585 --> 00:39.146
|
||||
"why must this happen?
|
||||
|
||||
00:39.146 --> 00:42.439
|
||||
these little mistakes hurt so much
|
||||
|
||||
00:42.439 --> 00:45.183
|
||||
all of these fake words
|
||||
|
||||
00:45.183 --> 00:48.110
|
||||
all i did today... hurt so much"
|
||||
|
||||
00:48.110 --> 00:51.036
|
||||
"i can only hide these feelings each day
|
||||
|
||||
00:51.036 --> 00:53.780
|
||||
and stay tainted with regret
|
||||
|
||||
00:53.780 --> 00:56.890
|
||||
and perhaps you're the only ones
|
||||
|
||||
00:56.890 --> 01:00.000
|
||||
who understand how i feel"
|
||||
|
||||
01:00.000 --> 01:05.487
|
||||
"shining above me, watching over me
|
||||
|
||||
01:05.487 --> 01:08.597
|
||||
i can only wish, dear stars
|
||||
|
||||
01:08.597 --> 01:11.524
|
||||
that you could tell me what i could do"
|
||||
|
||||
01:11.524 --> 01:14.634
|
||||
"you saw everything, you felt everything,
|
||||
|
||||
01:14.634 --> 01:17.378
|
||||
you've been through it all, you know it all"
|
||||
|
||||
01:17.378 --> 01:18.841
|
||||
why can't i just stay here
|
||||
|
||||
01:18.841 --> 01:20.304
|
||||
and find you all again
|
||||
|
||||
01:20.304 --> 01:22.682
|
||||
until i fall asleep?
|
||||
|
||||
01:22.682 --> 01:25.609
|
||||
dear twinkling, shining stars,
|
||||
|
||||
01:25.609 --> 01:29.268
|
||||
oh, whatever could i do...?
|
||||
|
||||
01:52.682 --> 01:58.170
|
||||
i don't want to go on
|
||||
i don't want to, i don't want to, i don't want to, i don't want to,
|
||||
|
||||
01:58.170 --> 02:03.292
|
||||
i can't keep going anymore
|
||||
not anymore, not anymore, not anymore...
|
||||
|
||||
02:03.292 --> 02:06.036
|
||||
so, dear stars,
|
||||
so, dear stars,
|
||||
|
||||
02:06.036 --> 02:13.170
|
||||
let me stay with you forever
|
||||
let me stay with you forever
|
||||
|
||||
02:13.170 --> 02:16.096
|
||||
please
|
||||
please
|
@ -4,6 +4,7 @@ BPM:200
|
||||
WAVE:Forever Fading Away.ogg
|
||||
OFFSET:-0.029
|
||||
DEMOSTART:95.529
|
||||
LYRICS:Forever Fading Away.vtt
|
||||
PREIMAGE:Forever Fading Away.png
|
||||
BGMOVIE:Forever Fading Away.mp4
|
||||
MAKER:DashyDesu & Colin
|
||||
|
@ -0,0 +1,142 @@
|
||||
WEBVTT
|
||||
|
||||
00:38.400 --> 00:44.100
|
||||
Cloudless faded light blue skies
|
||||
|
||||
00:44.100 --> 00:48.000
|
||||
surrounded the world he saw
|
||||
|
||||
00:48.000 --> 00:52.800
|
||||
an urgency was suddenly born
|
||||
|
||||
00:52.800 --> 00:57.600
|
||||
as that memory began to disappear...
|
||||
|
||||
00:57.600 --> 01:01.800
|
||||
place, faces, sounds and tastes
|
||||
|
||||
01:01.800 --> 01:06.900
|
||||
empty streets, and light gray drizzling clouds
|
||||
|
||||
01:06.900 --> 01:11.400
|
||||
He seeked to discover the reason
|
||||
|
||||
01:11.400 --> 01:16.800
|
||||
for such settings being so familiar
|
||||
|
||||
01:16.800 --> 01:17.400
|
||||
mem
|
||||
|
||||
01:17.400 --> 01:18.000
|
||||
memor
|
||||
|
||||
01:18.000 --> 01:18.600
|
||||
memories
|
||||
|
||||
01:18.600 --> 01:19.200
|
||||
memories and
|
||||
|
||||
01:19.200 --> 01:19.800
|
||||
memories and frag
|
||||
|
||||
01:19.800 --> 01:20.400
|
||||
memories and fragments
|
||||
|
||||
01:20.400 --> 01:21.000
|
||||
memories and fragments of
|
||||
|
||||
01:21.000 --> 01:21.600
|
||||
memories and fragments of that
|
||||
|
||||
01:21.600 --> 01:22.800
|
||||
memories and fragments of that time
|
||||
|
||||
01:22.800 --> 01:23.400
|
||||
he
|
||||
|
||||
01:23.400 --> 01:24.000
|
||||
he re
|
||||
|
||||
01:24.000 --> 01:25.200
|
||||
he remem
|
||||
|
||||
01:25.200 --> 01:26.400
|
||||
he remembered
|
||||
|
||||
01:26.400 --> 01:27.000
|
||||
that
|
||||
|
||||
01:27.000 --> 01:27.600
|
||||
that mom
|
||||
|
||||
01:27.600 --> 01:28.200
|
||||
that moment
|
||||
|
||||
01:28.200 --> 01:28.800
|
||||
that moment breezed
|
||||
|
||||
01:28.800 --> 01:29.400
|
||||
that moment breezed by
|
||||
|
||||
01:29.400 --> 01:30.000
|
||||
that moment breezed by from
|
||||
|
||||
01:30.000 --> 01:30.600
|
||||
that moment breezed by from long
|
||||
|
||||
01:30.600 --> 01:31.200
|
||||
that moment breezed by from long a
|
||||
|
||||
01:31.200 --> 01:32.400
|
||||
that moment breezed by from long ago
|
||||
|
||||
01:32.400 --> 01:33.000
|
||||
he
|
||||
|
||||
01:33.000 --> 01:33.600
|
||||
he re
|
||||
|
||||
01:33.600 --> 01:34.200
|
||||
he real
|
||||
|
||||
01:34.200 --> 01:35.400
|
||||
he realized...
|
||||
|
||||
01:35.400 --> 01:37.800
|
||||
as all those moments dissolve away,
|
||||
|
||||
01:37.800 --> 01:40.200
|
||||
just like always...
|
||||
|
||||
01:40.200 --> 01:45.000
|
||||
just like always, he'll continue living life his way...
|
||||
|
||||
01:45.000 --> 01:51.600
|
||||
only covered in thoughts as time fades away
|
||||
|
||||
01:51.600 --> 01:54.750
|
||||
time and time again...
|
||||
|
||||
01:54.750 --> 01:59.400
|
||||
no matter hours, seconds, weeks, they disappear
|
||||
|
||||
01:59.400 --> 02:04.200
|
||||
they disappear and are left with not any meaning
|
||||
|
||||
02:04.200 --> 02:10.800
|
||||
the time passes and then never reappears...
|
||||
|
||||
02:10.800 --> 02:19.200
|
||||
he stays in that pure white world...
|
||||
|
||||
02:33.600 --> 02:43.200
|
||||
now this time that was once at his fingertips
|
||||
|
||||
02:43.200 --> 02:49.200
|
||||
had began to drift away
|
||||
|
||||
02:49.200 --> 02:52.800
|
||||
so he remains in the pure white world...
|
||||
|
||||
02:52.800 --> 03:02.400
|
||||
forever, endless, ilimitable.
|
@ -4,6 +4,7 @@ BPM:160
|
||||
WAVE:TRIPLE HELIX.ogg
|
||||
OFFSET:-0.001
|
||||
DEMOSTART:120.001
|
||||
LYRICS:TRIPLE HELIX.vtt
|
||||
MAKER:Colin
|
||||
|
||||
COURSE:Oni
|
||||
|
@ -0,0 +1,14 @@
|
||||
WEBVTT
|
||||
|
||||
00:42.000 --> 00:57.000
|
||||
(rapping)
|
||||
|
||||
01:00.000 --> 01:03.375
|
||||
(rapping)
|
||||
|
||||
01:06.000 --> 01:09.000
|
||||
(rapping)
|
||||
|
||||
01:11.813 --> 01:15.000
|
||||
(rapping)
|
||||
|
Loading…
Reference in New Issue
Block a user