Skip to content

Commit 4aa6b0e

Browse files
committed
Simplified bpm data structure.
1 parent 2a18e0f commit 4aa6b0e

File tree

12 files changed

+150
-121
lines changed

12 files changed

+150
-121
lines changed

RhythmGameUtilities.Tests/UtilitiesTest.cs

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,12 @@ public void TestConvertSecondsToTicks()
2222
const int seconds = 5;
2323
const int resolution = 192;
2424

25-
var bpmChanges = new Dictionary<int, int>
25+
var bpmChanges = new[]
2626
{
27-
{ 0, 88000 },
28-
{ 3840, 112000 },
29-
{ 9984, 89600 },
30-
{ 22272, 112000 },
31-
{ 33792, 111500 },
32-
{ 34560, 112000 },
33-
{ 42240, 111980 }
27+
new Tempo { Position = 0, BPM = 88000 }, new Tempo { Position = 3840, BPM = 112000 },
28+
new Tempo { Position = 9984, BPM = 89600 }, new Tempo { Position = 22272, BPM = 112000 },
29+
new Tempo { Position = 33792, BPM = 111500 }, new Tempo { Position = 34560, BPM = 112000 },
30+
new Tempo { Position = 42240, BPM = 111980 }
3431
};
3532

3633
var timeSignatureChanges = new[] { new TimeSignature { Position = 0, Numerator = 4, Denominator = 2 } };
@@ -60,15 +57,12 @@ public void TestCalculateBeatBars()
6057
const int resolution = 192;
6158
const int timeSignature = 4;
6259

63-
var bpmChanges = new Dictionary<int, int>
60+
var bpmChanges = new Tempo[]
6461
{
65-
{ 0, 88000 },
66-
{ 3840, 112000 },
67-
{ 9984, 89600 },
68-
{ 22272, 112000 },
69-
{ 33792, 111500 },
70-
{ 34560, 112000 },
71-
{ 42240, 111980 }
62+
new() { Position = 0, BPM = 88000 }, new() { Position = 3840, BPM = 112000 },
63+
new() { Position = 9984, BPM = 89600 }, new() { Position = 22272, BPM = 112000 },
64+
new() { Position = 33792, BPM = 111500 }, new() { Position = 34560, BPM = 112000 },
65+
new() { Position = 42240, BPM = 111980 }
7266
};
7367

7468
var beatBars = Utilities.CalculateBeatBars(bpmChanges, resolution, timeSignature, true);

RhythmGameUtilities/Scripts/Utilities.cs

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ internal static class UtilitiesInternal
1313
public static extern float ConvertTickToPosition(int tick, int resolution);
1414

1515
[DllImport("libRhythmGameUtilities", CallingConvention = CallingConvention.Cdecl)]
16-
public static extern int ConvertSecondsToTicksInternal(float seconds, int resolution, int[] bpmChangesKeys,
17-
int[] bpmChangesValues, int bpmChangesSize, TimeSignature[] timeSignatures, int timeSignaturesSize);
16+
public static extern int ConvertSecondsToTicksInternal(float seconds, int resolution, Tempo[] bpmChanges,
17+
int bpmChangesSize, TimeSignature[] timeSignatures, int timeSignaturesSize);
1818

1919
[DllImport("libRhythmGameUtilities", CallingConvention = CallingConvention.Cdecl)]
2020
public static extern bool IsOnTheBeat(int bpm, float currentTime, float delta);
@@ -26,8 +26,8 @@ public static extern int ConvertSecondsToTicksInternal(float seconds, int resolu
2626
public static extern float CalculateAccuracyRatio(int position, int currentPosition, int delta);
2727

2828
[DllImport("libRhythmGameUtilities", CallingConvention = CallingConvention.Cdecl)]
29-
public static extern IntPtr CalculateBeatBarsInternal(int[] bpmChangesKeys,
30-
int[] bpmChangesValues, int bpmChangesSize, int resolution, int ts,
29+
public static extern IntPtr CalculateBeatBarsInternal(Tempo[] bpmChanges, int bpmChangesSize, int resolution,
30+
int ts,
3131
bool includeHalfNotes, out int size);
3232

3333
}
@@ -56,11 +56,11 @@ public static float ConvertTickToPosition(int tick, int resolution)
5656
/// <param name="resolution">The resolution of the song.</param>
5757
/// <param name="bpmChanges">All BPM changes within the song.</param>
5858
/// <param name="timeSignatureChanges">All time signature changes within the song.</param>
59-
public static int ConvertSecondsToTicks(float seconds, int resolution, Dictionary<int, int> bpmChanges,
59+
public static int ConvertSecondsToTicks(float seconds, int resolution, Tempo[] bpmChanges,
6060
TimeSignature[] timeSignatureChanges)
6161
{
62-
return UtilitiesInternal.ConvertSecondsToTicksInternal(seconds, resolution, bpmChanges.Keys.ToArray(),
63-
bpmChanges.Values.ToArray(), bpmChanges.Count, timeSignatureChanges, timeSignatureChanges.Length);
62+
return UtilitiesInternal.ConvertSecondsToTicksInternal(seconds, resolution, bpmChanges, bpmChanges.Length,
63+
timeSignatureChanges, timeSignatureChanges.Length);
6464
}
6565

6666
/// <summary>
@@ -86,12 +86,11 @@ public static int RoundUpToTheNearestMultiplier(int value, int multiplier)
8686
return UtilitiesInternal.RoundUpToTheNearestMultiplier(value, multiplier);
8787
}
8888

89-
public static BeatBar[] CalculateBeatBars(Dictionary<int, int> bpmChanges, int resolution = 192, int ts = 4,
89+
public static BeatBar[] CalculateBeatBars(Tempo[] bpmChanges, int resolution = 192, int ts = 4,
9090
bool includeHalfNotes = true)
9191
{
92-
93-
var ptrArray = UtilitiesInternal.CalculateBeatBarsInternal(bpmChanges.Keys.ToArray(),
94-
bpmChanges.Values.ToArray(), bpmChanges.Count, resolution, ts, includeHalfNotes,
92+
var ptrArray = UtilitiesInternal.CalculateBeatBarsInternal(bpmChanges, bpmChanges.Length, resolution, ts,
93+
includeHalfNotes,
9594
out var size);
9695

9796
var beatBarSize = Marshal.SizeOf(typeof(BeatBar));
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using System.Runtime.InteropServices;
2+
3+
namespace RhythmGameUtilities
4+
{
5+
6+
[StructLayout(LayoutKind.Sequential)]
7+
public struct Tempo
8+
{
9+
10+
public int Position;
11+
12+
public int BPM;
13+
14+
}
15+
16+
}

UnityPackage/Editor/Tests/UtilitiesTest.cs

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,12 @@ public void TestConvertSecondsToTicks()
2222
const int seconds = 5;
2323
const int resolution = 192;
2424

25-
var bpmChanges = new Dictionary<int, int>
25+
var bpmChanges = new[]
2626
{
27-
{ 0, 88000 },
28-
{ 3840, 112000 },
29-
{ 9984, 89600 },
30-
{ 22272, 112000 },
31-
{ 33792, 111500 },
32-
{ 34560, 112000 },
33-
{ 42240, 111980 }
27+
new Tempo { Position = 0, BPM = 88000 }, new Tempo { Position = 3840, BPM = 112000 },
28+
new Tempo { Position = 9984, BPM = 89600 }, new Tempo { Position = 22272, BPM = 112000 },
29+
new Tempo { Position = 33792, BPM = 111500 }, new Tempo { Position = 34560, BPM = 112000 },
30+
new Tempo { Position = 42240, BPM = 111980 }
3431
};
3532

3633
var timeSignatureChanges = new[] { new TimeSignature { Position = 0, Numerator = 4, Denominator = 2 } };
@@ -60,15 +57,12 @@ public void TestCalculateBeatBars()
6057
const int resolution = 192;
6158
const int timeSignature = 4;
6259

63-
var bpmChanges = new Dictionary<int, int>
60+
var bpmChanges = new Tempo[]
6461
{
65-
{ 0, 88000 },
66-
{ 3840, 112000 },
67-
{ 9984, 89600 },
68-
{ 22272, 112000 },
69-
{ 33792, 111500 },
70-
{ 34560, 112000 },
71-
{ 42240, 111980 }
62+
new() { Position = 0, BPM = 88000 }, new() { Position = 3840, BPM = 112000 },
63+
new() { Position = 9984, BPM = 89600 }, new() { Position = 22272, BPM = 112000 },
64+
new() { Position = 33792, BPM = 111500 }, new() { Position = 34560, BPM = 112000 },
65+
new() { Position = 42240, BPM = 111980 }
7266
};
7367

7468
var beatBars = Utilities.CalculateBeatBars(bpmChanges, resolution, timeSignature, true);

UnityPackage/Scripts/Utilities.cs

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ internal static class UtilitiesInternal
1313
public static extern float ConvertTickToPosition(int tick, int resolution);
1414

1515
[DllImport("libRhythmGameUtilities", CallingConvention = CallingConvention.Cdecl)]
16-
public static extern int ConvertSecondsToTicksInternal(float seconds, int resolution, int[] bpmChangesKeys,
17-
int[] bpmChangesValues, int bpmChangesSize, TimeSignature[] timeSignatures, int timeSignaturesSize);
16+
public static extern int ConvertSecondsToTicksInternal(float seconds, int resolution, Tempo[] bpmChanges,
17+
int bpmChangesSize, TimeSignature[] timeSignatures, int timeSignaturesSize);
1818

1919
[DllImport("libRhythmGameUtilities", CallingConvention = CallingConvention.Cdecl)]
2020
public static extern bool IsOnTheBeat(int bpm, float currentTime, float delta);
@@ -26,8 +26,8 @@ public static extern int ConvertSecondsToTicksInternal(float seconds, int resolu
2626
public static extern float CalculateAccuracyRatio(int position, int currentPosition, int delta);
2727

2828
[DllImport("libRhythmGameUtilities", CallingConvention = CallingConvention.Cdecl)]
29-
public static extern IntPtr CalculateBeatBarsInternal(int[] bpmChangesKeys,
30-
int[] bpmChangesValues, int bpmChangesSize, int resolution, int ts,
29+
public static extern IntPtr CalculateBeatBarsInternal(Tempo[] bpmChanges, int bpmChangesSize, int resolution,
30+
int ts,
3131
bool includeHalfNotes, out int size);
3232

3333
}
@@ -56,11 +56,11 @@ public static float ConvertTickToPosition(int tick, int resolution)
5656
/// <param name="resolution">The resolution of the song.</param>
5757
/// <param name="bpmChanges">All BPM changes within the song.</param>
5858
/// <param name="timeSignatureChanges">All time signature changes within the song.</param>
59-
public static int ConvertSecondsToTicks(float seconds, int resolution, Dictionary<int, int> bpmChanges,
59+
public static int ConvertSecondsToTicks(float seconds, int resolution, Tempo[] bpmChanges,
6060
TimeSignature[] timeSignatureChanges)
6161
{
62-
return UtilitiesInternal.ConvertSecondsToTicksInternal(seconds, resolution, bpmChanges.Keys.ToArray(),
63-
bpmChanges.Values.ToArray(), bpmChanges.Count, timeSignatureChanges, timeSignatureChanges.Length);
62+
return UtilitiesInternal.ConvertSecondsToTicksInternal(seconds, resolution, bpmChanges, bpmChanges.Length,
63+
timeSignatureChanges, timeSignatureChanges.Length);
6464
}
6565

6666
/// <summary>
@@ -86,12 +86,11 @@ public static int RoundUpToTheNearestMultiplier(int value, int multiplier)
8686
return UtilitiesInternal.RoundUpToTheNearestMultiplier(value, multiplier);
8787
}
8888

89-
public static BeatBar[] CalculateBeatBars(Dictionary<int, int> bpmChanges, int resolution = 192, int ts = 4,
89+
public static BeatBar[] CalculateBeatBars(Tempo[] bpmChanges, int resolution = 192, int ts = 4,
9090
bool includeHalfNotes = true)
9191
{
92-
93-
var ptrArray = UtilitiesInternal.CalculateBeatBarsInternal(bpmChanges.Keys.ToArray(),
94-
bpmChanges.Values.ToArray(), bpmChanges.Count, resolution, ts, includeHalfNotes,
92+
var ptrArray = UtilitiesInternal.CalculateBeatBarsInternal(bpmChanges, bpmChanges.Length, resolution, ts,
93+
includeHalfNotes,
9594
out var size);
9695

9796
var beatBarSize = Marshal.SizeOf(typeof(BeatBar));

UnityPackage/Structs/Tempo.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using System.Runtime.InteropServices;
2+
3+
namespace RhythmGameUtilities
4+
{
5+
6+
[StructLayout(LayoutKind.Sequential)]
7+
public struct Tempo
8+
{
9+
10+
public int Position;
11+
12+
public int BPM;
13+
14+
}
15+
16+
}

include/RhythmGameUtilities/Parsers.hpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "Enums/TypeCode.h"
1111

1212
#include "Structs/Note.h"
13+
#include "Structs/Tempo.h"
1314
#include "Structs/TimeSignature.h"
1415

1516
#include "Common.hpp"
@@ -108,7 +109,7 @@ std::map<std::string, std::string> ParseMetaDataFromChartSection(
108109
std::vector<TimeSignature> ParseTimeSignaturesFromChartSection(
109110
std::vector<std::pair<std::string, std::vector<std::string>>> section)
110111
{
111-
auto timeSignatures = std::vector<TimeSignature>();
112+
auto timeSignaturesChanges = std::vector<TimeSignature>();
112113

113114
for (auto &line : section)
114115
{
@@ -119,27 +120,30 @@ std::vector<TimeSignature> ParseTimeSignaturesFromChartSection(
119120
auto denominator =
120121
line.second.size() > 2 ? std::stoi(line.second.at(2)) : 2;
121122

122-
timeSignatures.push_back({position, numerator, denominator});
123+
timeSignaturesChanges.push_back({position, numerator, denominator});
123124
}
124125
}
125126

126-
return timeSignatures;
127+
return timeSignaturesChanges;
127128
}
128129

129-
std::map<int, int> ParseBpmFromChartSection(
130+
std::vector<Tempo> ParseBpmFromChartSection(
130131
std::vector<std::pair<std::string, std::vector<std::string>>> section)
131132
{
132-
auto bpm = std::map<int, int>();
133+
auto bpmChanges = std::vector<Tempo>();
133134

134135
for (auto &line : section)
135136
{
136137
if (line.second.front() == ToString(TypeCode::BPM_Marker))
137138
{
138-
bpm.insert({std::stoi(line.first), std::stoi(line.second.at(1))});
139+
auto position = std::stoi(line.first);
140+
auto bpm = std::stoi(line.second.at(1));
141+
142+
bpmChanges.push_back({position, bpm});
139143
}
140144
}
141145

142-
return bpm;
146+
return bpmChanges;
143147
}
144148

145149
std::vector<Note> ParseNotesFromChartSection(
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#pragma once
2+
3+
namespace RhythmGameUtilities
4+
{
5+
6+
struct Tempo
7+
{
8+
int Position;
9+
10+
int BPM;
11+
};
12+
13+
} // namespace RhythmGameUtilities

include/RhythmGameUtilities/Utilities.hpp

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include "Structs/BeatBar.h"
1010
#include "Structs/Note.h"
11+
#include "Structs/Tempo.h"
1112
#include "Structs/TimeSignature.h"
1213

1314
#include "Common.hpp"
@@ -34,7 +35,7 @@ const float SECONDS_PER_MINUTE = 60.0f;
3435
*/
3536

3637
int ConvertSecondsToTicks(float seconds, int resolution,
37-
std::map<int, int> bpmChanges,
38+
std::vector<Tempo> bpmChanges,
3839
std::vector<TimeSignature> timeSignatureChanges)
3940
{
4041
auto bpmIterator = bpmChanges.begin();
@@ -43,13 +44,13 @@ int ConvertSecondsToTicks(float seconds, int resolution,
4344
auto totalTicks = 0;
4445
auto remainingSeconds = seconds;
4546
auto previousTick = 0;
46-
auto previousBPM = bpmIterator->second / 1000.0;
47+
auto previousBPM = bpmIterator->BPM / 1000.0;
4748
auto previousTimeSignature = timeSignatureIterator->Numerator;
4849

4950
while (remainingSeconds > 0)
5051
{
5152
int nextBPMChange =
52-
bpmIterator != bpmChanges.end() ? bpmIterator->first : INT_MAX;
53+
bpmIterator != bpmChanges.end() ? bpmIterator->Position : INT_MAX;
5354

5455
int nextTimeSignatureChange =
5556
timeSignatureIterator != timeSignatureChanges.end()
@@ -74,7 +75,7 @@ int ConvertSecondsToTicks(float seconds, int resolution,
7475

7576
if (nextChangeTick == nextBPMChange)
7677
{
77-
previousBPM = bpmIterator->second / 1000.0;
78+
previousBPM = bpmIterator->BPM / 1000.0;
7879
++bpmIterator;
7980
}
8081

@@ -122,13 +123,20 @@ GenerateAdjacentKeyPairs(std::map<int, int> keyValuePairs)
122123
return adjacentKeyPairs;
123124
}
124125

125-
std::vector<BeatBar> CalculateBeatBars(std::map<int, int> bpmChanges,
126+
std::vector<BeatBar> CalculateBeatBars(std::vector<Tempo> bpmChanges,
126127
int resolution, int ts,
127128
bool includeHalfNotes)
128129
{
129130
std::vector<BeatBar> beatBars;
130131

131-
auto keyValuePairs = GenerateAdjacentKeyPairs(bpmChanges);
132+
std::map<int, int> bpmChangePositions;
133+
134+
for (const auto &bpmChange : bpmChanges)
135+
{
136+
bpmChangePositions[bpmChange.Position] = bpmChange.BPM;
137+
}
138+
139+
auto keyValuePairs = GenerateAdjacentKeyPairs(bpmChangePositions);
132140

133141
for (const auto &keyValuePair : keyValuePairs)
134142
{
@@ -137,12 +145,15 @@ std::vector<BeatBar> CalculateBeatBars(std::map<int, int> bpmChanges,
137145

138146
for (auto tick = startTick; tick < endTick; tick += resolution)
139147
{
140-
beatBars.push_back({tick, bpmChanges[startTick]});
148+
149+
auto position = tick;
150+
auto bpm = bpmChangePositions[startTick];
151+
152+
beatBars.push_back({tick, bpm});
141153

142154
if (includeHalfNotes && tick != endTick)
143155
{
144-
beatBars.push_back(
145-
{tick + resolution / 2, bpmChanges[startTick]});
156+
beatBars.push_back({tick + resolution / 2, bpm});
146157
}
147158
}
148159
}

0 commit comments

Comments
 (0)