diff --git a/Assets/Cryville/Common/Math/FractionUtils.cs b/Assets/Cryville/Common/Math/FractionUtils.cs
index b5b8e20..4c1d868 100644
--- a/Assets/Cryville/Common/Math/FractionUtils.cs
+++ b/Assets/Cryville/Common/Math/FractionUtils.cs
@@ -12,12 +12,12 @@ namespace Cryville.Common.Math {
/// The error.
/// The numerator.
/// The denominator.
- /// is less than 0 or is not greater than 0 or not less than 1.
+ /// is less than 0 or is not greater than 0 or greater than 1.
public static void ToFraction(double value, double error, out int n, out int d) {
if (value < 0.0)
throw new ArgumentOutOfRangeException("value", "Must be >= 0.");
- if (error <= 0.0 || error >= 1.0)
- throw new ArgumentOutOfRangeException("accuracy", "Must be > 0 and < 1.");
+ if (error <= 0.0 || error > 1.0)
+ throw new ArgumentOutOfRangeException("error", "Must be > 0 and <= 1.");
int num = (int)System.Math.Floor(value);
value -= num;
diff --git a/Assets/Cryville/Crtr/Extensions/TimingModel.cs b/Assets/Cryville/Crtr/Extensions/TimingModel.cs
index 8081109..bb6b8f5 100644
--- a/Assets/Cryville/Crtr/Extensions/TimingModel.cs
+++ b/Assets/Cryville/Crtr/Extensions/TimingModel.cs
@@ -42,15 +42,24 @@ namespace Cryville.Crtr.Extensions {
}
}
public class TimeTimingModel : TimingModel {
- public TimeTimingModel(double offset = 0) : base(offset) { }
+ public readonly double InputTimeAccuracy;
+ public TimeTimingModel(double accuracy = 2e-3, double offset = 0) : base(offset) {
+ if (accuracy <= 0) throw new ArgumentOutOfRangeException("accuracy");
+ InputTimeAccuracy = accuracy;
+ }
public void ForwardTo(double t) {
if (t == Time) return;
if (BPM == 0) throw new InvalidOperationException("BPM not determined");
BeatTime += (t - Time) * BPM / 60;
int n, d;
- FractionUtils.ToFraction(BeatTime, 1f / 48 / BPM * 60, out n, out d);
+ FractionUtils.ToFraction(BeatTime, Math.Min(1, InputTimeAccuracy * BPM / 60), out n, out d);
FractionalBeatTime = new BeatTime(n, d);
Time = t;
}
+ public void ForceSnap() {
+ var alignedBeat = (int)Math.Round(BeatTime);
+ BeatTime = alignedBeat;
+ FractionalBeatTime = new BeatTime(alignedBeat, 1);
+ }
}
}
diff --git a/Assets/Cryville/Crtr/Extensions/osu/osuChartConverter.cs b/Assets/Cryville/Crtr/Extensions/osu/osuChartConverter.cs
index c77c860..0f3b929 100644
--- a/Assets/Cryville/Crtr/Extensions/osu/osuChartConverter.cs
+++ b/Assets/Cryville/Crtr/Extensions/osu/osuChartConverter.cs
@@ -108,10 +108,11 @@ namespace Cryville.Crtr.Extensions.osu {
else if (ev is osuEvent.TimingChange) {
var tev = (osuEvent.TimingChange)ev;
if (tm == null) {
- tm = new TimeTimingModel(tev.StartTime / 1e3);
+ tm = new TimeTimingModel(tev.StartTime / 1e3) { InputTimeAccuracy = 2e-3 };
bgmEv.offset = (float)(tev.StartTime / 1e3 + OFFSET);
}
tm.BeatLength = tev.BeatLength / 1e3;
+ tm.ForceSnap();
chart.sigs.Add(new Chart.Signature {
time = tm.FractionalBeatTime,
tempo = (float)tm.BPM,