diff --git a/YARG.Core/Song/Preparsers/DrumPreparseHandler.cs b/YARG.Core/Song/Preparsers/DrumPreparseHandler.cs index 8a86e10e2..0ed5563db 100644 --- a/YARG.Core/Song/Preparsers/DrumPreparseHandler.cs +++ b/YARG.Core/Song/Preparsers/DrumPreparseHandler.cs @@ -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()) { @@ -112,7 +108,7 @@ 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; } @@ -120,22 +116,21 @@ public unsafe void ParseMidi(YARGMidiTrack track) // 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; } @@ -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) diff --git a/YARG.Core/Song/Preparsers/Midi/MidiEliteDrumsPreparser.cs b/YARG.Core/Song/Preparsers/Midi/MidiEliteDrumsPreparser.cs index 4251a5c56..53f59bf00 100644 --- a/YARG.Core/Song/Preparsers/Midi/MidiEliteDrumsPreparser.cs +++ b/YARG.Core/Song/Preparsers/Midi/MidiEliteDrumsPreparser.cs @@ -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()) @@ -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; diff --git a/YARG.Core/Song/Preparsers/Midi/MidiFiveFretPreparser.cs b/YARG.Core/Song/Preparsers/Midi/MidiFiveFretPreparser.cs index 5fb990b27..7b2f0d1bb 100644 --- a/YARG.Core/Song/Preparsers/Midi/MidiFiveFretPreparser.cs +++ b/YARG.Core/Song/Preparsers/Midi/MidiFiveFretPreparser.cs @@ -25,8 +25,7 @@ public static unsafe DifficultyMask Parse(YARGMidiTrack track) { ReadOnlySpan 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 @@ -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; diff --git a/YARG.Core/Song/Preparsers/Midi/MidiProGuitarPreparser.cs b/YARG.Core/Song/Preparsers/Midi/MidiProGuitarPreparser.cs index 93737a13d..4a66b4a2f 100644 --- a/YARG.Core/Song/Preparsers/Midi/MidiProGuitarPreparser.cs +++ b/YARG.Core/Song/Preparsers/Midi/MidiProGuitarPreparser.cs @@ -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()) @@ -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; diff --git a/YARG.Core/Song/Preparsers/Midi/MidiProKeysPreparser.cs b/YARG.Core/Song/Preparsers/Midi/MidiProKeysPreparser.cs index ff48c5caa..0cfb69a16 100644 --- a/YARG.Core/Song/Preparsers/Midi/MidiProKeysPreparser.cs +++ b/YARG.Core/Song/Preparsers/Midi/MidiProKeysPreparser.cs @@ -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()) { @@ -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; } diff --git a/YARG.Core/Song/Preparsers/Midi/MidiSixFretPreparser.cs b/YARG.Core/Song/Preparsers/Midi/MidiSixFretPreparser.cs index d2b23273d..1b2d52f49 100644 --- a/YARG.Core/Song/Preparsers/Midi/MidiSixFretPreparser.cs +++ b/YARG.Core/Song/Preparsers/Midi/MidiSixFretPreparser.cs @@ -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()) @@ -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;