Skip to content

Commit

Permalink
Switch to bitmasks from boolean arrays for .mid preparsers
Browse files Browse the repository at this point in the history
  • Loading branch information
sonicfind committed Oct 6, 2024
1 parent 197b68a commit 8e95d63
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 47 deletions.
27 changes: 11 additions & 16 deletions YARG.Core/Song/Preparsers/DrumPreparseHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,16 +90,12 @@ public unsafe void ParseMidi(YARGMidiTrack track)
const int MAX_NUMPADS = 7;
const int DRUMNOTE_MAX = 101;
const int DOUBLE_KICK_NOTE = 95;
const int EXPERT_INDEX = 3;
const int EXPERT_PLUS_INDEX = 4;
const int DOUBLE_KICK_OFFSET = EXPERT_INDEX * MAX_NUMPADS + 1;
const int DOUBLE_KICK_MASK = 1 << (3 * MAX_NUMPADS + 1);
const int FIVE_LANE_INDEX = 6;
const int YELLOW_FLAG = 110;
const int GREEN_FLAG = 112;

// +1 for Expert+
var difficulties = stackalloc bool[MidiPreparser_Constants.NUM_DIFFICULTIES + 1];
var statuses = stackalloc bool[MidiPreparser_Constants.NUM_DIFFICULTIES * MAX_NUMPADS];
int statusBitMask = 0;
var note = default(MidiNote);
while (track.ParseEvent())
{
Expand All @@ -112,30 +108,29 @@ public unsafe void ParseMidi(YARGMidiTrack track)
// Must be checked first as it still resides in the normal note range window
if (note.value == DOUBLE_KICK_NOTE)
{
if (difficulties[EXPERT_PLUS_INDEX])
if ((_validations & DifficultyMask.ExpertPlus) > 0)
{
continue;
}

// Note Ons with no velocity equates to a note Off by spec
if (track.Type == MidiEventType.Note_On && note.velocity > 0)
{
statuses[DOUBLE_KICK_OFFSET] = true;
statusBitMask |= DOUBLE_KICK_MASK;
}
// NoteOff here
else if (statuses[DOUBLE_KICK_OFFSET])
else if ((statusBitMask & DOUBLE_KICK_MASK) > 0)
{
_validations |= DifficultyMask.Expert | DifficultyMask.ExpertPlus;
difficulties[EXPERT_INDEX] = true;
difficulties[EXPERT_PLUS_INDEX] = true;
}
}
else if (MidiPreparser_Constants.DEFAULT_NOTE_MIN <= note.value && note.value <= DRUMNOTE_MAX)
{
int noteOffset = note.value - MidiPreparser_Constants.DEFAULT_NOTE_MIN;
int diffIndex = MidiPreparser_Constants.DIFF_INDICES[noteOffset];
var diffMask = (DifficultyMask) (1 << (diffIndex + 1));
// Necessary to account for potential five lane
if (difficulties[diffIndex] && Type != DrumsType.Unknown && Type != DrumsType.UnknownPro)
if ((_validations & diffMask) > 0 && Type != DrumsType.Unknown && Type != DrumsType.UnknownPro)
{
continue;
}
Expand All @@ -148,20 +143,20 @@ public unsafe void ParseMidi(YARGMidiTrack track)
continue;
}

int statusMask = 1 << (diffIndex * MAX_NUMPADS + laneIndex);
// Note Ons with no velocity equates to a note Off by spec
if (track.Type == MidiEventType.Note_On && note.velocity > 0)
{
statuses[diffIndex * MAX_NUMPADS + laneIndex] = true;
statusBitMask |= statusMask;
if (laneIndex == FIVE_LANE_INDEX)
{
Type = DrumsType.FiveLane;
}
}
// NoteOff here
else if (statuses[diffIndex * MAX_NUMPADS + laneIndex])
else if ((statusBitMask & statusMask) > 0)
{
_validations |= (DifficultyMask) (1 << (diffIndex + 1));
difficulties[diffIndex] = true;
_validations |= diffMask;
}
}
else if (YELLOW_FLAG <= note.value && note.value <= GREEN_FLAG && Type != DrumsType.FiveLane)
Expand Down
14 changes: 7 additions & 7 deletions YARG.Core/Song/Preparsers/Midi/MidiEliteDrumsPreparser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ public static class Midi_EliteDrums_Preparser
public static unsafe DifficultyMask Parse(YARGMidiTrack track)
{
var validations = default(DifficultyMask);
var difficulties = stackalloc bool[MidiPreparser_Constants.NUM_DIFFICULTIES];
var statuses = stackalloc bool[MidiPreparser_Constants.NUM_DIFFICULTIES * NUM_LANES];
long statusBitMask = 0;

var note = default(MidiNote);
while (track.ParseEvent())
Expand All @@ -28,21 +27,22 @@ public static unsafe DifficultyMask Parse(YARGMidiTrack track)

int diffIndex = MidiPreparser_Constants.EXTENDED_DIFF_INDICES[note.value];
int laneIndex = MidiPreparser_Constants.EXTENDED_LANE_INDICES[note.value];
if (difficulties[diffIndex] || laneIndex >= NUM_LANES)
var diffMask = (DifficultyMask)(1 << (diffIndex + 1));
if ((validations & diffMask) > 0 || laneIndex >= NUM_LANES)
{
continue;
}

long statusMask = 1L << (diffIndex * NUM_LANES + laneIndex);
// Note Ons with no velocity equates to a note Off by spec
if (track.Type == MidiEventType.Note_On && note.velocity > 0)
{
statuses[diffIndex * NUM_LANES + laneIndex] = true;
statusBitMask |= statusMask;
}
// Note off here
else if (statuses[diffIndex * NUM_LANES + laneIndex])
else if ((statusBitMask & statusMask) > 0)
{
validations |= (DifficultyMask) (1 << (diffIndex + 1));
difficulties[diffIndex] = true;
validations |= diffMask;
if (validations == MidiPreparser_Constants.ALL_DIFFICULTIES)
{
break;
Expand Down
14 changes: 7 additions & 7 deletions YARG.Core/Song/Preparsers/Midi/MidiFiveFretPreparser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ public static unsafe DifficultyMask Parse(YARGMidiTrack track)
{
ReadOnlySpan<byte> SYSEXTAG = stackalloc byte[] { (byte) 'P', (byte) 'S', (byte) '\0', };
var validations = default(DifficultyMask);
var difficulties = stackalloc bool[MidiPreparser_Constants.NUM_DIFFICULTIES];
var statuses = stackalloc bool[MidiPreparser_Constants.NUM_DIFFICULTIES * NUM_LANES];
int statusBitMask = 0;

// Zero is reserved for open notes. Open notes apply in two situations:
// 1. The 13s will swap to zeroes when the ENHANCED_OPENS toggle occurs
Expand Down Expand Up @@ -55,21 +54,22 @@ public static unsafe DifficultyMask Parse(YARGMidiTrack track)
int noteOffset = note.value - FIVEFRET_MIN;
int diffIndex = MidiPreparser_Constants.DIFF_INDICES[noteOffset];
int laneIndex = indices[noteOffset];
if (difficulties[diffIndex] || laneIndex >= NUM_LANES)
var diffMask = (DifficultyMask) (1 << (diffIndex + 1));
if ((validations & diffMask) > 0 || laneIndex >= NUM_LANES)
{
continue;
}

int statusMask = 1 << (diffIndex * NUM_LANES + laneIndex);
// Note Ons with no velocity equates to a note Off by spec
if (track.Type == MidiEventType.Note_On && note.velocity > 0)
{
statuses[diffIndex * NUM_LANES + laneIndex] = true;
statusBitMask |= statusMask;
}
// Note off here
else if (statuses[diffIndex * NUM_LANES + laneIndex])
else if ((statusBitMask & statusMask) > 0)
{
validations |= (DifficultyMask) (1 << (diffIndex + 1));
difficulties[diffIndex] = true;
validations |= diffMask;
if (validations == MidiPreparser_Constants.ALL_DIFFICULTIES)
{
break;
Expand Down
14 changes: 7 additions & 7 deletions YARG.Core/Song/Preparsers/Midi/MidiProGuitarPreparser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ public static DifficultyMask Parse_22Fret(YARGMidiTrack track)
private static unsafe DifficultyMask Parse(YARGMidiTrack track, int maxVelocity)
{
var validations = default(DifficultyMask);
var difficulties = stackalloc bool[MidiPreparser_Constants.NUM_DIFFICULTIES];
var statuses = stackalloc bool[MidiPreparser_Constants.NUM_DIFFICULTIES * NUM_STRINGS];
int statusBitMask = 0;

var note = default(MidiNote);
while (track.ParseEvent())
Expand All @@ -43,25 +42,26 @@ private static unsafe DifficultyMask Parse(YARGMidiTrack track, int maxVelocity)
int noteOffset = note.value - PROGUITAR_MIN;
int diffIndex = MidiPreparser_Constants.EXTENDED_DIFF_INDICES[noteOffset];
int laneIndex = MidiPreparser_Constants.EXTENDED_LANE_INDICES[noteOffset];
var diffMask = (DifficultyMask) (1 << (diffIndex + 1));
// Ghost notes aren't played
if (difficulties[diffIndex] || laneIndex >= NUM_STRINGS || track.Channel == ARPEGGIO_CHANNEL)
if ((validations & diffMask) > 0 || laneIndex >= NUM_STRINGS || track.Channel == ARPEGGIO_CHANNEL)
{
continue;
}

int statusMask = 1 << (diffIndex * NUM_STRINGS + laneIndex);
// Note Ons with no velocity equates to a note Off by spec
if (track.Type == MidiEventType.Note_On && note.velocity > 0)
{
if (MIN_VELOCITY <= note.velocity && note.velocity <= maxVelocity)
{
statuses[diffIndex * NUM_STRINGS + laneIndex] = true;
statusBitMask |= statusMask;
}
}
// Note off here
else if (statuses[diffIndex * NUM_STRINGS + laneIndex])
else if ((statusBitMask & statusMask) > 0)
{
validations |= (DifficultyMask) (1 << (diffIndex + 1));
difficulties[diffIndex] = true;
validations |= diffMask;
if (validations == MidiPreparser_Constants.ALL_DIFFICULTIES)
{
break;
Expand Down
7 changes: 4 additions & 3 deletions YARG.Core/Song/Preparsers/Midi/MidiProKeysPreparser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public static class Midi_ProKeys_Preparser

public static unsafe bool Parse(YARGMidiTrack track)
{
var statuses = stackalloc bool[NOTES_IN_DIFFICULTY];
int statusBitMask = 0;
var note = default(MidiNote);
while (track.ParseEvent())
{
Expand All @@ -19,11 +19,12 @@ public static unsafe bool Parse(YARGMidiTrack track)
track.ExtractMidiNote(ref note);
if (PROKEYS_MIN <= note.value && note.value <= PROKEYS_MAX)
{
int statusMask = 1 << (note.value - PROKEYS_MIN);
if (track.Type == MidiEventType.Note_On && note.velocity > 0)
{
statuses[note.value - PROKEYS_MIN] = true;
statusBitMask |= statusMask;
}
else if (statuses[note.value - PROKEYS_MIN])
else if ((statusBitMask & statusMask) > 0)
{
return true;
}
Expand Down
14 changes: 7 additions & 7 deletions YARG.Core/Song/Preparsers/Midi/MidiSixFretPreparser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ public static class Midi_SixFret_Preparser
public static unsafe DifficultyMask Parse(YARGMidiTrack track)
{
var validations = default(DifficultyMask);
var difficulties = stackalloc bool[MidiPreparser_Constants.NUM_DIFFICULTIES];
var statuses = stackalloc bool[MidiPreparser_Constants.NUM_DIFFICULTIES * NUM_LANES];
int statusBitMask = 0;

var note = default(MidiNote);
while (track.ParseEvent())
Expand All @@ -38,21 +37,22 @@ public static unsafe DifficultyMask Parse(YARGMidiTrack track)
int noteOffset = note.value - SIXFRET_MIN;
int diffIndex = MidiPreparser_Constants.DIFF_INDICES[noteOffset];
int laneIndex = INDICES[noteOffset];
if (difficulties[diffIndex] || laneIndex >= NUM_LANES)
var diffMask = (DifficultyMask) (1 << (diffIndex + 1));
if ((validations & diffMask) > 0 || laneIndex >= NUM_LANES)
{
continue;
}

int statusMask = 1 << (diffIndex * NUM_LANES + laneIndex);
// Note Ons with no velocity equates to a note Off by spec
if (track.Type == MidiEventType.Note_On && note.velocity > 0)
{
statuses[diffIndex * NUM_LANES + laneIndex] = true;
statusBitMask |= statusMask;
}
// Note off here
else if (statuses[diffIndex * NUM_LANES + laneIndex])
else if ((statusBitMask & statusMask) > 0)
{
validations |= (DifficultyMask) (1 << (diffIndex + 1));
difficulties[diffIndex] = true;
validations |= diffMask;
if (validations == MidiPreparser_Constants.ALL_DIFFICULTIES)
{
break;
Expand Down

0 comments on commit 8e95d63

Please sign in to comment.