forked from YARC-Official/YARG
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
experimental chart parsing, beats fixed up but midis will not work at…
… all
- Loading branch information
1 parent
1dc2b62
commit 1f58b5a
Showing
24 changed files
with
560 additions
and
192 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
namespace YARG.Chart { | ||
public struct Beat { | ||
public uint Position; | ||
public float Time; | ||
public BeatStyle Style; | ||
|
||
public Beat(uint position, float time, BeatStyle type) { | ||
Position = position; | ||
Time = time; | ||
Style = type; | ||
} | ||
} | ||
|
||
public enum BeatStyle { | ||
MEASURE, | ||
STRONG, | ||
WEAK, | ||
} | ||
|
||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
using System.Collections.Generic; | ||
using MoonscraperChartEditor.Song; | ||
|
||
namespace YARG.Chart { | ||
public class BeatHandler { | ||
|
||
private readonly MoonSong _song; | ||
|
||
public List<Beat> Beats; | ||
public List<Beat> Measures; | ||
|
||
public int TotalBeatCount => Beats.Count; | ||
private int lastMeasure; | ||
|
||
public int CurrentMeasure { get; private set; } | ||
|
||
public BeatHandler(MoonSong song) { | ||
_song = song; | ||
|
||
Beats = new List<Beat>(); | ||
Measures = new List<Beat>(); | ||
} | ||
|
||
private void AddBeat(uint tick, BeatStyle type) { | ||
Beats.Add(new Beat(tick, (float) _song.TickToTime(tick), type)); | ||
|
||
if (type == BeatStyle.MEASURE) | ||
Measures.Add(Beats[^1]); | ||
} | ||
|
||
// Thanks mdsitton for the CH beat generation algorithm when I was making SideyBot :) | ||
public void GenerateBeats() { | ||
uint currentTick = 0; | ||
uint lastTick = _song.GetLastTick(); | ||
|
||
// How many ticks to move forward to get to the next beat. | ||
uint forwardStep = 0; | ||
|
||
TimeSignature lastTS = null; | ||
TimeSignature currentTS; | ||
|
||
int currentBeatInMeasure = 0; | ||
int beatsInTS = 0; | ||
|
||
// The last beat style that was generated. Always starts as a measure. | ||
BeatStyle lastStyle = BeatStyle.MEASURE; | ||
|
||
// lastTick + forwardStep ensures we will always look ahead 1 more beat than the lastTick. | ||
while (currentTick < lastTick + forwardStep || lastStyle != BeatStyle.MEASURE) { | ||
// Gets previous time signature before currentTick. | ||
currentTS = _song.GetPrevTS(currentTick); | ||
|
||
// The number of "beats within a beat" there is | ||
uint currentSubBeat = currentTS.denominator / 4; | ||
|
||
bool hasTsChanged = lastTS == null || lastTS.numerator != currentTS.numerator || lastTS.denominator != currentTS.denominator; | ||
|
||
// If denominator is larger than 4 start off with weak beats, if 4 or less use strong beats | ||
var style = currentTS.denominator > 4 ? BeatStyle.WEAK : BeatStyle.STRONG; | ||
|
||
// New time signature. First beat of a new time sig is always a measure. | ||
if (hasTsChanged) { | ||
beatsInTS = 0; | ||
currentBeatInMeasure = 0; | ||
} | ||
|
||
// Beat count is equal to TS numerator, so its a new measure. | ||
if (currentBeatInMeasure == currentTS.numerator) { | ||
currentBeatInMeasure = 0; | ||
} | ||
|
||
if (currentTS.denominator <= 4 || currentBeatInMeasure % currentSubBeat == 0) { | ||
style = BeatStyle.STRONG; | ||
} | ||
|
||
// Make it a measure if first beat of a measure. | ||
if (currentBeatInMeasure == 0) { | ||
style = BeatStyle.MEASURE; | ||
|
||
// Handle 1/x TS's so that only the first beat in the TS gets a measure line | ||
// and then from there it is marked at a strong beat every quarter note with everything else as weak | ||
if (currentTS.numerator == 1 && beatsInTS > 0) { | ||
if (currentTick >= lastTick) { | ||
style = BeatStyle.MEASURE; | ||
} | ||
// if not quarter note length beats every quarter note is stressed | ||
else if (currentTS.denominator <= 4 || (beatsInTS % currentSubBeat) == 0) { | ||
style = BeatStyle.STRONG; | ||
} else { | ||
style = BeatStyle.WEAK; | ||
} | ||
} | ||
} | ||
|
||
// Last beat should never be a strong beat if denominator is bigger than 4. | ||
if (currentBeatInMeasure == currentTS.numerator - 1 && currentTS.denominator > 4) { | ||
style = BeatStyle.WEAK; | ||
} | ||
|
||
AddBeat(currentTick, style); | ||
|
||
currentBeatInMeasure++; | ||
beatsInTS++; | ||
|
||
forwardStep = (uint) (_song.resolution * 4) / currentTS.denominator; | ||
currentTick += forwardStep; | ||
lastTS = currentTS; | ||
lastStyle = style; | ||
} | ||
|
||
lastMeasure = Measures.Count - 1; | ||
} | ||
|
||
public void UpdateCurrentMeasure(double songTime) { | ||
while (CurrentMeasure <= lastMeasure && songTime > Measures[CurrentMeasure].Time) { | ||
CurrentMeasure++; | ||
} | ||
} | ||
|
||
public int GetNoteMeasure(Note note) { | ||
int dif = CurrentMeasure; | ||
|
||
while (dif < Measures.Count && note.Time >= Measures[dif].Time) | ||
dif++; | ||
|
||
return dif; | ||
} | ||
} | ||
|
||
public static class SongHelpers { | ||
public static uint GetLastTick(this MoonSong song) | ||
{ | ||
uint lastTick = 0; | ||
foreach (var songEvent in song.events) | ||
{ | ||
if (songEvent.tick > lastTick) | ||
{ | ||
lastTick = songEvent.tick; | ||
} | ||
} | ||
foreach (var chart in song.Charts) | ||
{ | ||
foreach (var songObject in chart.chartObjects) { | ||
if (songObject.tick <= lastTick) continue; | ||
|
||
lastTick = songObject.tick; | ||
|
||
if (songObject is MoonNote note) | ||
{ | ||
lastTick += note.length; | ||
} | ||
} | ||
} | ||
|
||
return lastTick; | ||
} | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,107 +1,28 @@ | ||
using System.Collections.Generic; | ||
using System.Collections.Generic; | ||
using MoonscraperChartEditor.Song; | ||
using YARG.Data; | ||
|
||
namespace YARG.Chart { | ||
public class GuitarChartLoader : IChartLoader<GuitarNote> { | ||
public class GuitarChartLoader : IChartLoader<NoteInfo> { | ||
public List<NoteInfo> GetNotesFromChart(MoonSong song, MoonChart chart) { | ||
var notes = new List<NoteInfo>(); | ||
|
||
public List<GuitarNote> GetNotesFromChart(MoonSong song, MoonChart chart) { | ||
var notes = new List<GuitarNote>(); | ||
|
||
var starpowers = chart.starPower.ToArray(); | ||
|
||
// Previous note (could be same tick) | ||
Note previousGameNote = null; | ||
|
||
// Previous note that is a different tick | ||
Note previousSeparateGameNote = null; | ||
|
||
Note parentNote = null; | ||
foreach (var moonNote in chart.notes) { | ||
var prevSeparateNote = moonNote.PreviousSeperateMoonNote; | ||
var nextSeparateNote = moonNote.NextSeperateMoonNote; | ||
|
||
var flags = NoteFlags.None; | ||
|
||
foreach (var starpower in starpowers) { | ||
uint spEndTick = starpower.tick + starpower.length; | ||
|
||
// Current note is within the bounds of current StarPower. | ||
// MoonNote tick is bigger or equal to StarPower tick | ||
// and smaller than StarPower end tick. | ||
if (moonNote.tick >= starpower.tick && moonNote.tick < spEndTick) { | ||
flags |= NoteFlags.StarPower; | ||
|
||
// If this is first note, or previous note is before starpower tick, mark as starpower start. | ||
if (prevSeparateNote is null || prevSeparateNote.tick < starpower.tick) | ||
{ | ||
flags |= NoteFlags.StarPowerStart; | ||
} | ||
// If this is last note, or next note is not in starpower range, mark as end of starpower. | ||
if (nextSeparateNote is null || nextSeparateNote.tick >= spEndTick) | ||
{ | ||
flags |= NoteFlags.StarPowerEnd; | ||
} | ||
} | ||
} | ||
|
||
// The tick this note has ended | ||
uint noteFinishTick = moonNote.tick + moonNote.length; | ||
if(nextSeparateNote is not null && nextSeparateNote.tick < noteFinishTick) { | ||
flags |= NoteFlags.ExtendedSustain; | ||
} | ||
if (moonNote.isChord) { | ||
flags |= NoteFlags.Chord; | ||
} | ||
|
||
// Length of the note in realtime | ||
double timeLength = song.TickToTime(moonNote.tick + moonNote.length, song.resolution) - moonNote.time; | ||
|
||
int fret = MoonGuitarNoteToFret(moonNote); | ||
var currentNote = new GuitarNote(previousSeparateGameNote, moonNote.time, timeLength, moonNote.tick, | ||
moonNote.length, fret, moonNote.type, flags); | ||
|
||
// First note, must be a parent note | ||
if (previousGameNote is null) { | ||
parentNote = currentNote; | ||
|
||
previousGameNote = currentNote; | ||
notes.Add(currentNote); | ||
var note = new NoteInfo { | ||
time = (float)moonNote.time, | ||
length = (float)timeLength, | ||
fret = moonNote.rawNote, | ||
hopo = moonNote.type == MoonNote.MoonNoteType.Hopo, | ||
tap = moonNote.type == MoonNote.MoonNoteType.Tap, | ||
}; | ||
|
||
continue; | ||
} | ||
|
||
// Ticks don't match previous game note | ||
if (previousGameNote.Tick != currentNote.Tick) { | ||
parentNote = currentNote; | ||
|
||
previousSeparateGameNote = previousGameNote; | ||
|
||
previousSeparateGameNote.nextNote = currentNote; | ||
currentNote.previousNote = previousSeparateGameNote; | ||
|
||
notes.Add(currentNote); | ||
} else { | ||
// Add as a child note if ticks match | ||
parentNote.AddChildNote(currentNote); | ||
} | ||
|
||
previousGameNote = currentNote; | ||
notes.Add(note); | ||
} | ||
|
||
return notes; | ||
} | ||
|
||
private static int MoonGuitarNoteToFret(MoonNote note) { | ||
return note.guitarFret switch { | ||
MoonNote.GuitarFret.Open => 0, | ||
MoonNote.GuitarFret.Green => 1, | ||
MoonNote.GuitarFret.Red => 2, | ||
MoonNote.GuitarFret.Yellow => 3, | ||
MoonNote.GuitarFret.Blue => 4, | ||
MoonNote.GuitarFret.Orange => 5, | ||
_ => 1 | ||
}; | ||
} | ||
|
||
} | ||
} | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
Oops, something went wrong.