functions to get the beat from a song position

will need more testing but I think it works well enough to get into prod
thanks @wooningcharithri#7419 for the psuedo-code
This commit is contained in:
minenice55 2022-06-06 11:02:00 -04:00
parent bdf76f3770
commit 58842fcef5
2 changed files with 58 additions and 13 deletions

View file

@ -85,7 +85,7 @@ namespace HeavenStudio
bool negativeOffset = firstBeatOffset < 0f; bool negativeOffset = firstBeatOffset < 0f;
bool negativeStartTime = false; bool negativeStartTime = false;
Debug.Log("starting playback @ beat " + beat); // Debug.Log("starting playback @ beat " + beat + ", offset is " + firstBeatOffset);
var startPos = GetSongPosFromBeat(beat); var startPos = GetSongPosFromBeat(beat);
if (negativeOffset) if (negativeOffset)
@ -103,9 +103,8 @@ namespace HeavenStudio
} }
//TODO: make this take into account past tempo changes //TODO: make this take into account past tempo changes
songPosBeat = time / secPerBeat; songPosBeat = GetBeatFromSongPos(time - firstBeatOffset);
songPositionInBeats = songPosBeat; // Debug.Log("corrected starting playback @ beat " + songPosBeat);
Debug.Log("offset starting playback @ beat " + songPosBeat);
isPlaying = true; isPlaying = true;
isPaused = false; isPaused = false;
@ -237,6 +236,14 @@ namespace HeavenStudio
return GetBeatFromPosition(position, targetBeat - margin, margin); return GetBeatFromPosition(position, targetBeat - margin, margin);
} }
private List<Beatmap.TempoChange> GetSortedTempoChanges(Beatmap chart)
{
//iterate over all tempo changes, adding to counter
List<Beatmap.TempoChange> tempoChanges = chart.tempoChanges;
tempoChanges.Sort((x, y) => x.beat.CompareTo(y.beat)); //sorts all tempo changes by ascending time (GameManager already does this but juste en cas...)
return tempoChanges;
}
public float GetSongPosFromBeat(float beat) public float GetSongPosFromBeat(float beat)
{ {
Beatmap chart = GameManager.instance.Beatmap; Beatmap chart = GameManager.instance.Beatmap;
@ -249,9 +256,7 @@ namespace HeavenStudio
float lastTempoChangeBeat = 0f; float lastTempoChangeBeat = 0f;
//iterate over all tempo changes, adding to counter //iterate over all tempo changes, adding to counter
List<Beatmap.TempoChange> tempoChanges = chart.tempoChanges; List<Beatmap.TempoChange> tempoChanges = GetSortedTempoChanges(chart);
tempoChanges.Sort((x, y) => x.beat.CompareTo(y.beat)); //sorts all tempo changes by ascending time (GameManager already does this but juste en cas...)
foreach (var t in tempoChanges) foreach (var t in tempoChanges)
{ {
if (t.beat > beat) if (t.beat > beat)
@ -273,9 +278,51 @@ namespace HeavenStudio
counter += (beat - lastTempoChangeBeat) * secPerBeat; counter += (beat - lastTempoChangeBeat) * secPerBeat;
// Debug.Log("GetSongPosFromBeat returning " + counter); // Debug.Log("GetSongPosFromBeat returning " + counter);
return counter - firstBeatOffset; return counter;
} }
//thank you @wooningcharithri#7419 for the psuedo-code
private float BeatsToSecs(float beats, float bpm)
{
// Debug.Log("BeatsToSecs returning " + beats / bpm * 60);
return beats / bpm * 60f;
}
private float SecsToBeats(float s, float bpm)
{
// Debug.Log("SecsToBeats returning " + s / 60f / bpm);
return s / 60f * bpm;
}
public float GetBeatFromSongPos(float seconds)
{
// Debug.Log("Getting beat of seconds " + seconds);
Beatmap chart = GameManager.instance.Beatmap;
float lastTempoChangeBeat = 0f;
float lastBpm = chart.bpm;
float counterSeconds = -firstBeatOffset;
List<Beatmap.TempoChange> tempoChanges = GetSortedTempoChanges(chart);
foreach (var t in tempoChanges)
{
float beatToNext = t.beat - lastTempoChangeBeat;
float secToNext = BeatsToSecs(beatToNext, lastBpm);
float nextSecs = counterSeconds + secToNext;
// Debug.Log("nextSecs is " + nextSecs + ", seconds " + seconds);
if (nextSecs >= seconds)
break;
lastTempoChangeBeat = t.beat;
lastBpm = t.tempo;
counterSeconds = nextSecs;
}
// Debug.Log("lastTempoChangeBeat is " + lastTempoChangeBeat + ", counterSeconds is " + counterSeconds);
return lastTempoChangeBeat + SecsToBeats(seconds - counterSeconds, lastBpm);
}
//
// convert real seconds to beats // convert real seconds to beats
public float GetRestFromRealTime(float seconds) public float GetRestFromRealTime(float seconds)
{ {
@ -296,9 +343,7 @@ namespace HeavenStudio
public float SongLengthInBeats() public float SongLengthInBeats()
{ {
if (!musicSource.clip) return 0; if (!musicSource.clip) return 0;
return GetBeatFromSongPos(musicSource.clip.length);
//TODO: make this take into account past tempo changes
return musicSource.clip.length / secPerBeat;
} }
public bool SongPosLessThanClipLength(float t) public bool SongPosLessThanClipLength(float t)

View file

@ -333,14 +333,14 @@ namespace HeavenStudio
//for tempo changes, just go over all of em until the last one we pass //for tempo changes, just go over all of em until the last one we pass
for (int t = 0; t < tempoChanges.Count; t++) for (int t = 0; t < tempoChanges.Count; t++)
{ {
Debug.Log("checking tempo event " + t + " against beat " + beat + "( tc beat " + tempoChanges[t] + ")"); // Debug.Log("checking tempo event " + t + " against beat " + beat + "( tc beat " + tempoChanges[t] + ")");
if (tempoChanges[t] > beat) if (tempoChanges[t] > beat)
{ {
break; break;
} }
currentTempoEvent = t; currentTempoEvent = t;
} }
Debug.Log("currentTempoEvent is now " + currentTempoEvent); // Debug.Log("currentTempoEvent is now " + currentTempoEvent);
} }
} }