feat : use invariant culture in chart converts
This commit is contained in:
+279
-277
@@ -1,300 +1,302 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BAKKA_Editor
|
||||
{
|
||||
internal class Chart
|
||||
{
|
||||
public List<Note> Notes { get; set; }
|
||||
public List<Gimmick> Gimmicks { get; set; }
|
||||
/// <summary>
|
||||
/// Offset in seconds.
|
||||
/// </summary>
|
||||
public double Offset { get; set; }
|
||||
/// <summary>
|
||||
/// Movie offset in seconds
|
||||
/// </summary>
|
||||
public double MovieOffset { get; set; }
|
||||
String SongFileName { get; set; }
|
||||
List<Gimmick> TimeEvents { get; set; }
|
||||
public bool HasInitEvents
|
||||
internal class Chart
|
||||
{
|
||||
get
|
||||
{
|
||||
return TimeEvents != null &&
|
||||
TimeEvents.Count > 0 &&
|
||||
Gimmicks.Count(x => x.Measure == 0 && x.GimmickType == GimmickType.BpmChange) >= 1 &&
|
||||
Gimmicks.Count(x => x.Measure == 0 && x.GimmickType == GimmickType.TimeSignatureChange) >= 1;
|
||||
}
|
||||
}
|
||||
public bool IsSaved { get; set; }
|
||||
|
||||
public Chart()
|
||||
{
|
||||
Notes = new();
|
||||
Gimmicks = new();
|
||||
Offset = 0;
|
||||
MovieOffset = 0;
|
||||
SongFileName = "";
|
||||
IsSaved = true;
|
||||
}
|
||||
|
||||
public bool ParseFile(string filename)
|
||||
{
|
||||
var file = File.ReadAllLines(filename);
|
||||
|
||||
int index = 0;
|
||||
|
||||
do
|
||||
{
|
||||
var line = file[index];
|
||||
|
||||
var path = Utils.GetTag(line, "#MUSIC_FILE_PATH ");
|
||||
if (path != null)
|
||||
SongFileName = path;
|
||||
|
||||
var offset = Utils.GetTag(line, "#OFFSET");
|
||||
if (offset != null)
|
||||
Offset = Convert.ToDouble(offset);
|
||||
|
||||
offset = Utils.GetTag(line, "#MOVIEOFFSET");
|
||||
if (offset != null)
|
||||
MovieOffset = Convert.ToDouble(offset);
|
||||
|
||||
|
||||
if (line.Contains("#BODY"))
|
||||
private static readonly CultureInfo _defaultParsingCulture = CultureInfo.InvariantCulture;
|
||||
public List<Note> Notes { get; set; }
|
||||
public List<Gimmick> Gimmicks { get; set; }
|
||||
/// <summary>
|
||||
/// Offset in seconds.
|
||||
/// </summary>
|
||||
public double Offset { get; set; }
|
||||
/// <summary>
|
||||
/// Movie offset in seconds
|
||||
/// </summary>
|
||||
public double MovieOffset { get; set; }
|
||||
String SongFileName { get; set; }
|
||||
List<Gimmick> TimeEvents { get; set; }
|
||||
public bool HasInitEvents
|
||||
{
|
||||
index++;
|
||||
break;
|
||||
}
|
||||
|
||||
} while(++index < file.Length);
|
||||
|
||||
int lineNum;
|
||||
Gimmick gimmickTemp;
|
||||
Note noteTemp;
|
||||
Dictionary<int, Note> notesByLine = new();
|
||||
Dictionary<int, int> refByLine = new();
|
||||
for (int i = index; i < file.Length; i++)
|
||||
{
|
||||
if (String.IsNullOrWhiteSpace(file[i]))
|
||||
continue;
|
||||
|
||||
var parsed = file[i].Split(new string[] {" "}, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
|
||||
NoteBase temp = new();
|
||||
temp.BeatInfo = new BeatInfo(Convert.ToInt32(parsed[0]), Convert.ToInt32(parsed[1]));
|
||||
temp.GimmickType = (GimmickType)Convert.ToInt32(parsed[2]);
|
||||
|
||||
switch (temp.GimmickType)
|
||||
{
|
||||
case GimmickType.NoGimmick:
|
||||
noteTemp = new Note(temp.BeatInfo);
|
||||
noteTemp.NoteType = (NoteType)Convert.ToInt32(parsed[3]);
|
||||
lineNum = Convert.ToInt32(parsed[4]);
|
||||
noteTemp.Position = Convert.ToInt32(parsed[5]);
|
||||
noteTemp.Size = Convert.ToInt32(parsed[6]);
|
||||
noteTemp.HoldChange = Convert.ToBoolean(Convert.ToInt32(parsed[7]));
|
||||
if (noteTemp.NoteType == NoteType.MaskAdd || noteTemp.NoteType == NoteType.MaskRemove)
|
||||
get
|
||||
{
|
||||
noteTemp.MaskFill = (MaskType)Convert.ToInt32(parsed[8]);
|
||||
return TimeEvents != null &&
|
||||
TimeEvents.Count > 0 &&
|
||||
Gimmicks.Count(x => x.Measure == 0 && x.GimmickType == GimmickType.BpmChange) >= 1 &&
|
||||
Gimmicks.Count(x => x.Measure == 0 && x.GimmickType == GimmickType.TimeSignatureChange) >= 1;
|
||||
}
|
||||
else if (noteTemp.NoteType == NoteType.HoldStartNoBonus ||
|
||||
noteTemp.NoteType == NoteType.HoldJoint ||
|
||||
noteTemp.NoteType == NoteType.HoldStartBonusFlair)
|
||||
}
|
||||
public bool IsSaved { get; set; }
|
||||
|
||||
public Chart()
|
||||
{
|
||||
Notes = new();
|
||||
Gimmicks = new();
|
||||
Offset = 0;
|
||||
MovieOffset = 0;
|
||||
SongFileName = "";
|
||||
IsSaved = true;
|
||||
}
|
||||
|
||||
public bool ParseFile(string filename)
|
||||
{
|
||||
var file = File.ReadAllLines(filename);
|
||||
|
||||
int index = 0;
|
||||
|
||||
do
|
||||
{
|
||||
refByLine[lineNum] = Convert.ToInt32(parsed[8]);
|
||||
var line = file[index];
|
||||
|
||||
var path = Utils.GetTag(line, "#MUSIC_FILE_PATH ");
|
||||
if (path != null)
|
||||
SongFileName = path;
|
||||
var offset = Utils.GetTag(line, "#OFFSET");
|
||||
if (offset != null)
|
||||
Offset = Convert.ToDouble(offset, _defaultParsingCulture);
|
||||
|
||||
offset = Utils.GetTag(line, "#MOVIEOFFSET");
|
||||
if (offset != null)
|
||||
MovieOffset = Convert.ToDouble(offset, _defaultParsingCulture);
|
||||
|
||||
|
||||
if (line.Contains("#BODY"))
|
||||
{
|
||||
index++;
|
||||
break;
|
||||
}
|
||||
|
||||
} while (++index < file.Length);
|
||||
|
||||
int lineNum;
|
||||
Gimmick gimmickTemp;
|
||||
Note noteTemp;
|
||||
Dictionary<int, Note> notesByLine = new();
|
||||
Dictionary<int, int> refByLine = new();
|
||||
for (int i = index; i < file.Length; i++)
|
||||
{
|
||||
if (String.IsNullOrWhiteSpace(file[i]))
|
||||
continue;
|
||||
|
||||
var parsed = file[i].Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
|
||||
NoteBase temp = new();
|
||||
temp.BeatInfo = new BeatInfo(Convert.ToInt32(parsed[0], _defaultParsingCulture), Convert.ToInt32(parsed[1], _defaultParsingCulture));
|
||||
temp.GimmickType = (GimmickType)Convert.ToInt32(parsed[2], _defaultParsingCulture);
|
||||
|
||||
switch (temp.GimmickType)
|
||||
{
|
||||
case GimmickType.NoGimmick:
|
||||
noteTemp = new Note(temp.BeatInfo);
|
||||
noteTemp.NoteType = (NoteType)Convert.ToInt32(parsed[3], _defaultParsingCulture);
|
||||
lineNum = Convert.ToInt32(parsed[4], _defaultParsingCulture);
|
||||
noteTemp.Position = Convert.ToInt32(parsed[5], _defaultParsingCulture);
|
||||
noteTemp.Size = Convert.ToInt32(parsed[6], _defaultParsingCulture);
|
||||
noteTemp.HoldChange = Convert.ToBoolean(Convert.ToInt32(parsed[7], _defaultParsingCulture));
|
||||
if (noteTemp.NoteType == NoteType.MaskAdd || noteTemp.NoteType == NoteType.MaskRemove)
|
||||
{
|
||||
noteTemp.MaskFill = (MaskType)Convert.ToInt32(parsed[8], _defaultParsingCulture);
|
||||
}
|
||||
else if (noteTemp.NoteType == NoteType.HoldStartNoBonus ||
|
||||
noteTemp.NoteType == NoteType.HoldJoint ||
|
||||
noteTemp.NoteType == NoteType.HoldStartBonusFlair)
|
||||
{
|
||||
refByLine[lineNum] = Convert.ToInt32(parsed[8], _defaultParsingCulture);
|
||||
}
|
||||
Notes.Add(noteTemp);
|
||||
notesByLine[lineNum] = Notes.Last();
|
||||
break;
|
||||
case GimmickType.BpmChange:
|
||||
gimmickTemp = new Gimmick(temp.BeatInfo, temp.GimmickType);
|
||||
gimmickTemp.BPM = Convert.ToDouble(parsed[3], _defaultParsingCulture);
|
||||
Gimmicks.Add(gimmickTemp);
|
||||
break;
|
||||
case GimmickType.TimeSignatureChange:
|
||||
gimmickTemp = new Gimmick(temp.BeatInfo, temp.GimmickType);
|
||||
gimmickTemp.TimeSig = new TimeSignature() { Upper = Convert.ToInt32(parsed[3], _defaultParsingCulture), Lower = parsed.Length == 5 ? Convert.ToInt32(parsed[4], _defaultParsingCulture) : 4 };
|
||||
Gimmicks.Add(gimmickTemp);
|
||||
break;
|
||||
case GimmickType.HiSpeedChange:
|
||||
gimmickTemp = new Gimmick(temp.BeatInfo, temp.GimmickType);
|
||||
gimmickTemp.HiSpeed = Convert.ToDouble(parsed[3], _defaultParsingCulture);
|
||||
Gimmicks.Add(gimmickTemp);
|
||||
break;
|
||||
case GimmickType.ReverseStart:
|
||||
case GimmickType.ReverseMiddle:
|
||||
case GimmickType.ReverseEnd:
|
||||
case GimmickType.StopStart:
|
||||
case GimmickType.StopEnd:
|
||||
default:
|
||||
Gimmicks.Add(new Gimmick(temp.BeatInfo, temp.GimmickType));
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
Notes.Add(noteTemp);
|
||||
notesByLine[lineNum] = Notes.Last();
|
||||
break;
|
||||
case GimmickType.BpmChange:
|
||||
gimmickTemp = new Gimmick(temp.BeatInfo, temp.GimmickType);
|
||||
gimmickTemp.BPM = Convert.ToDouble(parsed[3]);
|
||||
Gimmicks.Add(gimmickTemp);
|
||||
break;
|
||||
case GimmickType.TimeSignatureChange:
|
||||
gimmickTemp = new Gimmick(temp.BeatInfo, temp.GimmickType);
|
||||
gimmickTemp.TimeSig = new TimeSignature() { Upper = Convert.ToInt32(parsed[3]), Lower = parsed.Length == 5 ? Convert.ToInt32(parsed[4]) : 4 };
|
||||
Gimmicks.Add(gimmickTemp);
|
||||
break;
|
||||
case GimmickType.HiSpeedChange:
|
||||
gimmickTemp = new Gimmick(temp.BeatInfo, temp.GimmickType);
|
||||
gimmickTemp.HiSpeed = Convert.ToDouble(parsed[3]);
|
||||
Gimmicks.Add(gimmickTemp);
|
||||
break;
|
||||
case GimmickType.ReverseStart:
|
||||
case GimmickType.ReverseMiddle:
|
||||
case GimmickType.ReverseEnd:
|
||||
case GimmickType.StopStart:
|
||||
case GimmickType.StopEnd:
|
||||
default:
|
||||
Gimmicks.Add(new Gimmick(temp.BeatInfo, temp.GimmickType));
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Generate hold references
|
||||
for (int i = 0; i < Notes.Count; i++)
|
||||
{
|
||||
if (refByLine.ContainsKey(i))
|
||||
{
|
||||
Notes[i].NextNote = notesByLine[refByLine[i]];
|
||||
Notes[i].NextNote.PrevNote = Notes[i];
|
||||
}
|
||||
}
|
||||
|
||||
RecalcTime();
|
||||
|
||||
IsSaved = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool WriteFile(string filename, bool setSave = true)
|
||||
{
|
||||
using (StreamWriter sw = new StreamWriter(new FileStream(filename, FileMode.Create), new UTF8Encoding(false)))
|
||||
{
|
||||
// LF line ending
|
||||
sw.NewLine = "\n";
|
||||
|
||||
sw.WriteLine("#MUSIC_SCORE_ID 0");
|
||||
sw.WriteLine("#MUSIC_SCORE_VERSION 0");
|
||||
sw.WriteLine("#GAME_VERSION ");
|
||||
sw.WriteLine($"#MUSIC_FILE_PATH {SongFileName}");
|
||||
sw.WriteLine($"#OFFSET {Offset:F6}");
|
||||
sw.WriteLine($"#MOVIEOFFSET {MovieOffset:F6}");
|
||||
sw.WriteLine("#BODY");
|
||||
|
||||
foreach (var gimmick in Gimmicks)
|
||||
{
|
||||
sw.Write($"{gimmick.BeatInfo.Measure,4:F0}{gimmick.BeatInfo.Beat,5:F0}{((int)gimmick.GimmickType),5:F0}");
|
||||
switch (gimmick.GimmickType)
|
||||
{
|
||||
case GimmickType.BpmChange:
|
||||
sw.WriteLine($" {gimmick.BPM:F6}");
|
||||
break;
|
||||
case GimmickType.TimeSignatureChange:
|
||||
sw.WriteLine($"{gimmick.TimeSig.Upper,5:F0}{gimmick.TimeSig.Lower,5:F0}");
|
||||
break;
|
||||
case GimmickType.HiSpeedChange:
|
||||
sw.WriteLine($" {gimmick.HiSpeed:F6}");
|
||||
break;
|
||||
default:
|
||||
sw.WriteLine("");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var note in Notes)
|
||||
{
|
||||
sw.Write($"{note.BeatInfo.Measure,4:F0}{note.BeatInfo.Beat,5:F0}{((int)note.GimmickType),5:F0}{(int)note.NoteType,5:F0}");
|
||||
sw.Write($"{Notes.IndexOf(note),5:F0}{note.Position,5:F0}{note.Size,5:F0}{Convert.ToInt32(note.HoldChange),5:F0}");
|
||||
if (note.IsMask)
|
||||
sw.Write($"{(int)note.MaskFill,5:F0}");
|
||||
if (note.NextNote != null)
|
||||
sw.Write($"{Notes.IndexOf(note.NextNote),5:F0}");
|
||||
sw.WriteLine("");
|
||||
}
|
||||
}
|
||||
|
||||
IsSaved = setSave;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void RecalcTime()
|
||||
{
|
||||
Gimmicks = Gimmicks.OrderBy(x => x.Measure).ToList();
|
||||
var timeSig = Gimmicks.FirstOrDefault(x => x.GimmickType == GimmickType.TimeSignatureChange && x.Measure == 0.0f);
|
||||
var bpm = Gimmicks.FirstOrDefault(x => x.GimmickType == GimmickType.BpmChange && x.Measure == 0.0f);
|
||||
if (timeSig == null || bpm == null)
|
||||
return; // Cannot calculate times without either starting value
|
||||
|
||||
TimeEvents = new();
|
||||
for (int i = 0; i < Gimmicks.Count; i++)
|
||||
{
|
||||
var evt = TimeEvents.FirstOrDefault(x => x.BeatInfo.MeasureDecimal == Gimmicks[i].BeatInfo.MeasureDecimal);
|
||||
|
||||
if (Gimmicks[i].GimmickType == GimmickType.BpmChange)
|
||||
{
|
||||
if (evt == null)
|
||||
{
|
||||
TimeEvents.Add(new Gimmick()
|
||||
// Generate hold references
|
||||
for (int i = 0; i < Notes.Count; i++)
|
||||
{
|
||||
BeatInfo = new BeatInfo(Gimmicks[i].BeatInfo),
|
||||
BPM = Gimmicks[i].BPM,
|
||||
TimeSig = new TimeSignature(timeSig.TimeSig)
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
evt.BPM = Gimmicks[i].BPM;
|
||||
}
|
||||
bpm = Gimmicks[i];
|
||||
if (refByLine.ContainsKey(i))
|
||||
{
|
||||
Notes[i].NextNote = notesByLine[refByLine[i]];
|
||||
Notes[i].NextNote.PrevNote = Notes[i];
|
||||
}
|
||||
}
|
||||
|
||||
RecalcTime();
|
||||
|
||||
IsSaved = true;
|
||||
return true;
|
||||
}
|
||||
if (Gimmicks[i].GimmickType == GimmickType.TimeSignatureChange)
|
||||
|
||||
public bool WriteFile(string filename, bool setSave = true)
|
||||
{
|
||||
if (evt == null)
|
||||
{
|
||||
TimeEvents.Add(new Gimmick()
|
||||
using (StreamWriter sw = new StreamWriter(new FileStream(filename, FileMode.Create), new UTF8Encoding(false)))
|
||||
{
|
||||
BeatInfo = new BeatInfo(Gimmicks[i].BeatInfo),
|
||||
BPM = bpm.BPM,
|
||||
TimeSig = new TimeSignature(Gimmicks[i].TimeSig)
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
evt.TimeSig = new TimeSignature(Gimmicks[i].TimeSig);
|
||||
}
|
||||
timeSig = Gimmicks[i];
|
||||
// LF line ending
|
||||
sw.NewLine = "\n";
|
||||
|
||||
sw.WriteLine("#MUSIC_SCORE_ID 0");
|
||||
sw.WriteLine("#MUSIC_SCORE_VERSION 0");
|
||||
sw.WriteLine("#GAME_VERSION ");
|
||||
sw.WriteLine($"#MUSIC_FILE_PATH {SongFileName}");
|
||||
sw.WriteLine($"#OFFSET {Offset:F6}");
|
||||
sw.WriteLine($"#MOVIEOFFSET {MovieOffset:F6}");
|
||||
sw.WriteLine("#BODY");
|
||||
|
||||
foreach (var gimmick in Gimmicks)
|
||||
{
|
||||
sw.Write($"{gimmick.BeatInfo.Measure,4:F0}{gimmick.BeatInfo.Beat,5:F0}{((int)gimmick.GimmickType),5:F0}");
|
||||
switch (gimmick.GimmickType)
|
||||
{
|
||||
case GimmickType.BpmChange:
|
||||
sw.WriteLine($" {gimmick.BPM:F6}");
|
||||
break;
|
||||
case GimmickType.TimeSignatureChange:
|
||||
sw.WriteLine($"{gimmick.TimeSig.Upper,5:F0}{gimmick.TimeSig.Lower,5:F0}");
|
||||
break;
|
||||
case GimmickType.HiSpeedChange:
|
||||
sw.WriteLine($" {gimmick.HiSpeed:F6}");
|
||||
break;
|
||||
default:
|
||||
sw.WriteLine("");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var note in Notes)
|
||||
{
|
||||
sw.Write($"{note.BeatInfo.Measure,4:F0}{note.BeatInfo.Beat,5:F0}{((int)note.GimmickType),5:F0}{(int)note.NoteType,5:F0}");
|
||||
sw.Write($"{Notes.IndexOf(note),5:F0}{note.Position,5:F0}{note.Size,5:F0}{Convert.ToInt32(note.HoldChange, _defaultParsingCulture),5:F0}");
|
||||
if (note.IsMask)
|
||||
sw.Write($"{(int)note.MaskFill,5:F0}");
|
||||
if (note.NextNote != null)
|
||||
sw.Write($"{Notes.IndexOf(note.NextNote),5:F0}");
|
||||
sw.WriteLine("");
|
||||
}
|
||||
}
|
||||
|
||||
IsSaved = setSave;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Run through all time events and generate valid start times
|
||||
TimeEvents[0].StartTime = Offset * 1000.0;
|
||||
for (int i = 1; i < TimeEvents.Count; i++)
|
||||
{
|
||||
TimeEvents[i].StartTime = ((TimeEvents[i].Measure - TimeEvents[i - 1].Measure) * (4.0f * TimeEvents[i - 1].TimeSig.Ratio * (60000.0 / TimeEvents[i - 1].BPM))) + TimeEvents[i - 1].StartTime;
|
||||
}
|
||||
public void RecalcTime()
|
||||
{
|
||||
Gimmicks = Gimmicks.OrderBy(x => x.Measure).ToList();
|
||||
var timeSig = Gimmicks.FirstOrDefault(x => x.GimmickType == GimmickType.TimeSignatureChange && x.Measure == 0.0f);
|
||||
var bpm = Gimmicks.FirstOrDefault(x => x.GimmickType == GimmickType.BpmChange && x.Measure == 0.0f);
|
||||
if (timeSig == null || bpm == null)
|
||||
return; // Cannot calculate times without either starting value
|
||||
|
||||
TimeEvents = new();
|
||||
for (int i = 0; i < Gimmicks.Count; i++)
|
||||
{
|
||||
var evt = TimeEvents.FirstOrDefault(x => x.BeatInfo.MeasureDecimal == Gimmicks[i].BeatInfo.MeasureDecimal);
|
||||
|
||||
if (Gimmicks[i].GimmickType == GimmickType.BpmChange)
|
||||
{
|
||||
if (evt == null)
|
||||
{
|
||||
TimeEvents.Add(new Gimmick()
|
||||
{
|
||||
BeatInfo = new BeatInfo(Gimmicks[i].BeatInfo),
|
||||
BPM = Gimmicks[i].BPM,
|
||||
TimeSig = new TimeSignature(timeSig.TimeSig)
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
evt.BPM = Gimmicks[i].BPM;
|
||||
}
|
||||
bpm = Gimmicks[i];
|
||||
}
|
||||
if (Gimmicks[i].GimmickType == GimmickType.TimeSignatureChange)
|
||||
{
|
||||
if (evt == null)
|
||||
{
|
||||
TimeEvents.Add(new Gimmick()
|
||||
{
|
||||
BeatInfo = new BeatInfo(Gimmicks[i].BeatInfo),
|
||||
BPM = bpm.BPM,
|
||||
TimeSig = new TimeSignature(Gimmicks[i].TimeSig)
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
evt.TimeSig = new TimeSignature(Gimmicks[i].TimeSig);
|
||||
}
|
||||
timeSig = Gimmicks[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Run through all time events and generate valid start times
|
||||
TimeEvents[0].StartTime = Offset * 1000.0;
|
||||
for (int i = 1; i < TimeEvents.Count; i++)
|
||||
{
|
||||
TimeEvents[i].StartTime = ((TimeEvents[i].Measure - TimeEvents[i - 1].Measure) * (4.0f * TimeEvents[i - 1].TimeSig.Ratio * (60000.0 / TimeEvents[i - 1].BPM))) + TimeEvents[i - 1].StartTime;
|
||||
}
|
||||
}
|
||||
/*
|
||||
((60000.0 / evt.BPM) * 4.0 * evt.TimeSig.Ratio) * measure = time
|
||||
time / ((60000.0 / evt.BPM) * 4.0 * evt.TimeSig.Ratio) = measure
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Translate clock time to beats
|
||||
/// </summary>
|
||||
/// <param name="time">Current timestamp in ms</param>
|
||||
/// <returns></returns>
|
||||
public BeatInfo GetBeat(float time)
|
||||
{
|
||||
if (TimeEvents == null || TimeEvents.Count == 0)
|
||||
return new BeatInfo(-1, 0);
|
||||
|
||||
var evt = TimeEvents.Where(x => time >= x.StartTime).LastOrDefault();
|
||||
if (evt == null)
|
||||
evt = TimeEvents[0];
|
||||
return new BeatInfo((float)((time - evt.StartTime) / ((60000.0 / evt.BPM) * 4.0f * evt.TimeSig.Ratio) + evt.Measure));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Translate measures into clock time
|
||||
/// </summary>
|
||||
/// <param name="beat"></param>
|
||||
/// <returns></returns>
|
||||
public int GetTime(BeatInfo beat)
|
||||
{
|
||||
if (TimeEvents == null || TimeEvents.Count == 0)
|
||||
return 0;
|
||||
|
||||
var evt = TimeEvents.Where(x => beat.MeasureDecimal >= x.Measure).LastOrDefault();
|
||||
if (evt == null)
|
||||
evt = TimeEvents[0];
|
||||
return (int)(((60000.0 / evt.BPM) * 4.0f * evt.TimeSig.Ratio) * (beat.MeasureDecimal - evt.Measure) + evt.StartTime);
|
||||
}
|
||||
}
|
||||
/*
|
||||
((60000.0 / evt.BPM) * 4.0 * evt.TimeSig.Ratio) * measure = time
|
||||
time / ((60000.0 / evt.BPM) * 4.0 * evt.TimeSig.Ratio) = measure
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Translate clock time to beats
|
||||
/// </summary>
|
||||
/// <param name="time">Current timestamp in ms</param>
|
||||
/// <returns></returns>
|
||||
public BeatInfo GetBeat(float time)
|
||||
{
|
||||
if (TimeEvents == null || TimeEvents.Count == 0)
|
||||
return new BeatInfo(-1, 0);
|
||||
|
||||
var evt = TimeEvents.Where(x => time >= x.StartTime).LastOrDefault();
|
||||
if (evt == null)
|
||||
evt = TimeEvents[0];
|
||||
return new BeatInfo((float)((time - evt.StartTime) / ((60000.0 / evt.BPM) * 4.0f * evt.TimeSig.Ratio) + evt.Measure));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Translate measures into clock time
|
||||
/// </summary>
|
||||
/// <param name="beat"></param>
|
||||
/// <returns></returns>
|
||||
public int GetTime(BeatInfo beat)
|
||||
{
|
||||
if (TimeEvents == null || TimeEvents.Count == 0)
|
||||
return 0;
|
||||
|
||||
var evt = TimeEvents.Where(x => beat.MeasureDecimal >= x.Measure).LastOrDefault();
|
||||
if (evt == null)
|
||||
evt = TimeEvents[0];
|
||||
return (int)(((60000.0 / evt.BPM) * 4.0f * evt.TimeSig.Ratio) * (beat.MeasureDecimal - evt.Measure) + evt.StartTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user