Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scanning Architecture Refactor + Additional CacheHandler Documentation #217

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
2 changes: 1 addition & 1 deletion TestConsole/CacheLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public static SongCache LoadCache()
throw new Exception($"Please add at least one song directory to {SongDirsPath}");

var task = Task.Run(() => CacheHandler.RunScan(
fast: false,
tryQuickScan: false,
SongCachePath,
BadSongsPath,
MULTITHREADING,
Expand Down
3 changes: 1 addition & 2 deletions YARG.Core.Benchmarks/Parsing/DotChartParsingBenchmarks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ namespace YARG.Core.Benchmarks
// [SimpleJob(RunStrategy.ColdStart, targetCount: 25, invocationCount: 1)]
public class DotChartParsingBenchmarks
{
private ParseSettings settings = ParseSettings.Default;
private string chartText;

[GlobalSetup]
Expand All @@ -25,7 +24,7 @@ public void Initialize()
[Benchmark]
public SongChart ChartParsing()
{
return SongChart.FromDotChart(settings, chartText);
return SongChart.FromDotChart(in ParseSettings.Default_Chart, chartText);
}
}
}
4 changes: 1 addition & 3 deletions YARG.Core.Benchmarks/Parsing/MidiParsingBenchmarks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ namespace YARG.Core.Benchmarks
// [SimpleJob(RunStrategy.ColdStart, targetCount: 25, invocationCount: 1)]
public class MidiParsingBenchmarks
{

private ParseSettings settings = ParseSettings.Default;
private MidiFile midi;

[GlobalSetup]
Expand All @@ -26,7 +24,7 @@ public void Initialize()
[Benchmark]
public SongChart ChartParsing()
{
return SongChart.FromMidi(settings, midi);
return SongChart.FromMidi(in ParseSettings.Default_Midi, midi);
}
}
}
6 changes: 2 additions & 4 deletions YARG.Core.UnitTests/Engine/DrumEngineTester.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ public class DrumEngineTester

private string? _chartsDirectory;

private readonly ParseSettings _settings = ParseSettings.Default;

[SetUp]
public void Setup()
{
Expand All @@ -37,7 +35,7 @@ public void DrumSoloThatEndsInChord_ShouldWorkCorrectly()
{
var chartPath = Path.Combine(_chartsDirectory!, "drawntotheflame.mid");
var midi = MidiFile.Read(chartPath);
var chart = SongChart.FromMidi(_settings, midi);
var chart = SongChart.FromMidi(in ParseSettings.Default_Midi, midi);
var notes = chart.ProDrums.GetDifficulty(Difficulty.Expert);

var engine = new YargDrumsEngine(notes, chart.SyncTrack, _engineParams, true);
Expand All @@ -56,7 +54,7 @@ public void DrumTrackWithKickDrumRemoved_ShouldWorkCorrectly()
{
var chartPath = Path.Combine(_chartsDirectory!, "drawntotheflame.mid");
var midi = MidiFile.Read(chartPath);
var chart = SongChart.FromMidi(_settings, midi);
var chart = SongChart.FromMidi(in ParseSettings.Default_Midi, midi);
var notes = chart.ProDrums.GetDifficulty(Difficulty.Expert);

notes.RemoveKickDrumNotes();
Expand Down
4 changes: 2 additions & 2 deletions YARG.Core.UnitTests/Parsing/ParseBehaviorTests.Midi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ namespace YARG.Core.UnitTests.Parsing
public class MidiParseBehaviorTests
{
private const uint SUSTAIN_CUTOFF_THRESHOLD = RESOLUTION / 3;
private static readonly uint HopoThreshold = (uint)GetHopoThreshold(ParseSettings.Default, RESOLUTION);
private const uint HOPO_THRESHOLD = (RESOLUTION / 3) + 1;

private static readonly Dictionary<MoonInstrument, string> InstrumentToNameLookup = new()
{
Expand Down Expand Up @@ -450,7 +450,7 @@ private static void GenerateNotesForDifficulty<TNoteEvent>(MidiEventList events,
if ((canForceStrum || canForceHopo) && (flags & Flags.Forced) != 0)
{
MoonNoteType type;
if (canForceHopo && lastStartDelta >= HopoThreshold)
if (canForceHopo && lastStartDelta >= HOPO_THRESHOLD)
{
type = MoonNoteType.Hopo;
// Apply additional flag to match the parsed data
Expand Down
4 changes: 2 additions & 2 deletions YARG.Core/Chart/Loaders/MoonSong/MoonSongLoader.Lyrics.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using MoonscraperChartEditor.Song;
Expand Down Expand Up @@ -69,7 +69,7 @@ public void AddPhraseEvent(string text, uint tick)
public LyricsTrack LoadLyrics()
{
var converter = new LyricConverter(_moonSong);
var maxTick = _moonSong.Charts.Max(x => x.events.LastOrDefault()?.tick + (uint)_moonSong.resolution ?? 0);
var maxTick = _moonSong.Charts.Max(x => x.events.LastOrDefault()?.tick + _moonSong.resolution ?? 0);
TextEvents.ConvertToPhrases(_moonSong.events, converter, maxTick);
return new LyricsTrack(converter.Phrases);
}
Expand Down
9 changes: 3 additions & 6 deletions YARG.Core/Chart/Loaders/MoonSong/MoonSongLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,8 @@ private delegate TNote CreateNoteDelegate<TNote>(MoonNote moonNote, CurrentPhras
private MoonSong.MoonInstrument _currentMoonInstrument;
private MoonSong.Difficulty _currentMoonDifficulty;

public MoonSongLoader(MoonSong song, ParseSettings settings)
public MoonSongLoader(MoonSong song, in ParseSettings settings)
{
if (settings.NoteSnapThreshold < 0)
settings.NoteSnapThreshold = 0;

_moonSong = song;
_settings = settings;
}
Expand Down Expand Up @@ -333,7 +330,7 @@ private static bool IsEventInPhrase(MoonObject songObj, MoonPhrase phrase)
if (phrase.length == 0)
return songObj.tick == phrase.tick;

return songObj.tick >= phrase.tick && songObj.tick < (phrase.tick + phrase.length);
return phrase.tick <= songObj.tick && songObj.tick < (phrase.tick + phrase.length);
}

private static bool IsNoteClosestToEndOfPhrase(MoonSong song, MoonNote note, MoonPhrase phrase)
Expand Down Expand Up @@ -366,7 +363,7 @@ private static bool IsNoteClosestToEndOfPhrase(MoonSong song, MoonNote note, Moo
if (previousNote is null)
{
// This is the first note in the chart, check by distance
float tickThreshold = song.resolution / 3; // 1/12th note
uint tickThreshold = song.resolution / 3; // 1/12th note
return Math.Abs((int) note.tick - endTick) < tickThreshold;
}
else if (note.tick >= endTick && previousNote.tick < endTick)
Expand Down
78 changes: 19 additions & 59 deletions YARG.Core/Chart/ParsingProperties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,31 @@ public struct ParseSettings
public static readonly ParseSettings Default = new()
{
DrumsType = DrumsType.Unknown,
HopoThreshold = SETTING_DEFAULT,
SustainCutoffThreshold = SETTING_DEFAULT,
ChordHopoCancellation = false,
StarPowerNote = SETTING_DEFAULT,
NoteSnapThreshold = 0,
};

public static readonly ParseSettings Default_Chart = new()
{
DrumsType = DrumsType.Unknown,
HopoThreshold = SETTING_DEFAULT,
HopoFreq_FoF = SETTING_DEFAULT,
EighthNoteHopo = false,
SustainCutoffThreshold = 0,
ChordHopoCancellation = false,
StarPowerNote = SETTING_DEFAULT,
NoteSnapThreshold = 0,
};

public static readonly ParseSettings Default_Midi = new()
{
DrumsType = DrumsType.Unknown,
HopoThreshold = SETTING_DEFAULT,
SustainCutoffThreshold = SETTING_DEFAULT,
ChordHopoCancellation = false,
StarPowerNote = 116,
NoteSnapThreshold = 0,

StarPowerNote = SETTING_DEFAULT,
};

/// <summary>
Expand All @@ -57,23 +72,6 @@ public struct ParseSettings
/// </remarks>
public long HopoThreshold;

/// <summary>
/// The FoF HOPO threshold setting number to use.
/// </summary>
/// <remarks>
/// Uses the <c>hopofreq</c> tag from song.ini files.<br/>
/// 0 -> 1/24th note, 1 -> 1/16th note, 2 -> 1/12th note, 3 -> 1/8th note, 4 -> 1/6th note, 5 -> 1/4th note.
/// </remarks>
public int HopoFreq_FoF;

/// <summary>
/// Set the HOPO threshold to a 1/8th note instead of a 1/12th note.
/// </summary>
/// <remarks>
/// Uses the <c>eighthnote_hopo</c> tag from song.ini files.
/// </remarks>
public bool EighthNoteHopo;

/// <summary>
/// Skip marking single notes after chords as HOPOs
/// if the single note shares a fret with the chord.
Expand Down Expand Up @@ -105,43 +103,5 @@ public struct ParseSettings
/// Defaults to 116.
/// </remarks>
public int StarPowerNote;

/// <summary>
/// Calculates the HOPO threshold to use from the various HOPO settings.
/// </summary>
public readonly float GetHopoThreshold(float resolution)
{
// Prefer in this order:
// 1. hopo_threshold
// 2. eighthnote_hopo
// 3. hopofreq

if (HopoThreshold > 0)
{
return HopoThreshold;
}
else if (EighthNoteHopo)
{
return resolution / 2;
}
else if (HopoFreq_FoF >= 0)
{
int denominator = HopoFreq_FoF switch
{
0 => 24,
1 => 16,
2 => 12,
3 => 8,
4 => 6,
5 => 4,
_ => throw new NotImplementedException($"Unhandled hopofreq value {HopoFreq_FoF}!")
};
return (resolution * 4) / denominator;
}
else
{
return resolution / 3;
}
}
}
}
58 changes: 57 additions & 1 deletion YARG.Core/Extensions/StreamExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ public static TType Read<TType>(this Stream stream, Endianness endianness)
public static bool ReadBoolean(this Stream stream)
{
byte b = (byte)stream.ReadByte();
return Unsafe.As<byte, bool>(ref b);
unsafe
{
return *(bool*)&b;
}
}

public static int Read7BitEncodedInt(this Stream stream)
Expand Down Expand Up @@ -124,6 +127,59 @@ public static void Write<TType>(this Stream stream, TType value, Endianness endi
}
}

public static void Write(this Stream stream, bool value)
{
unsafe
{
stream.WriteByte(*(byte*) &value);
}
}

public static void Write7BitEncodedInt(this Stream stream, int value)
{
// Write out an int 7 bits at a time. The high bit of the byte,
// when on, tells reader to continue reading more bytes.
uint v = (uint) value; // support negative numbers
while (v >= 0x80)
{
stream.WriteByte((byte) (v | 0x80));
v >>= 7;
}
stream.WriteByte((byte) v);
}

public static unsafe void Write(this Stream stream, string value)
{
if (value.Length == 0)
{
stream.WriteByte(0);
return;
}

var buffer = stackalloc byte[value.Length * 4];
fixed (char* chars = value)
{
int len = Encoding.UTF8.GetBytes(chars, value.Length, buffer, value.Length * 4);
stream.Write7BitEncodedInt(len);
stream.Write(new ReadOnlySpan<byte>(buffer, len));
}
}

public static void Write(this Stream stream, Color color)
{
stream.Write(color.ToArgb(), Endianness.Little);
}

public static void Write(this Stream stream, Guid guid)
{
Span<byte> span = stackalloc byte[16];
if (!guid.TryWriteBytes(span))
{
throw new InvalidOperationException("Failed to write GUID bytes.");
}
stream.Write(span);
}

private static unsafe void CorrectByteOrder<TType>(byte* bytes, Endianness endianness)
where TType : unmanaged, IComparable, IComparable<TType>, IConvertible, IEquatable<TType>, IFormattable
{
Expand Down
6 changes: 3 additions & 3 deletions YARG.Core/IO/AbridgedFileInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,10 @@ public AbridgedFileInfo(string filename, in DateTime lastUpdatedTime)
LastUpdatedTime = lastUpdatedTime;
}

public void Serialize(BinaryWriter writer)
public void Serialize(MemoryStream stream)
{
writer.Write(FullName);
writer.Write(LastUpdatedTime.ToBinary());
stream.Write(FullName);
stream.Write(LastUpdatedTime.ToBinary(), Endianness.Little);
}

public bool Exists()
Expand Down
Loading