simfile.timing.engine

Classes

SongTime

A floating-point time value, denoting a temporal position in a simfile.

EventTag

Types of timing events.

TimingEngine

Convert song time to beats and vice-versa.

Module Contents

class simfile.timing.engine.SongTime

Bases: float

A floating-point time value, denoting a temporal position in a simfile.

class simfile.timing.engine.EventTag

Bases: enum.IntEnum

Types of timing events.

The order of these values determines how multiple events on the same beat will be sorted: for example, delays must occur before stops in order to correctly time notes on a beat with both a delay and a stop.

Warps, delays, stops, and fakes have a corresponding “end” type that TimingEngine uses to simplify the beat/time conversion logic. These can be used to disambiguate the time at a given beat (for stops & delays) or the beat at a given time (for warps).

FAKE = -2
FAKE_END = -1
WARP = 0
WARP_END = 1
BPM = 2
DELAY = 3
DELAY_END = 4
STOP = 5
STOP_END = 6
class simfile.timing.engine.TimingEngine(timing_data: simfile.timing.TimingData)

Convert song time to beats and vice-versa.

Under the hood, this class arranges timing events chronologically, determines the song time and BPM at each event, then extrapolates from those calculated values for each bpm_at() / time_at() / beat_at() call.

timing_data: simfile.timing.TimingData
bpm_at(beat: simfile.timing.Beat) decimal.Decimal

Find the song’s BPM at a given beat.

Neither warps, stops, nor delays affect the output of this method: warps are not considered “infinite BPM”, nor are pauses considered “zero BPM”.

hittable(beat: simfile.timing.Beat) bool

Determine if a note on the given beat would be hittable.

A beat is considered “unhittable” only if it’s inside a warp or fake segment (including the segment’s start beat, excluding its end beat) and it doesn’t coincide with a stop or delay.

Note that there is also a fake note type (F in note data) that this function is unaware of. Consider using the time_chart() function to handle both fake regions and note types.

time_at(beat: simfile.timing.Beat, event_tag: EventTag = EventTag.STOP) SongTime

Determine the song time at a given beat.

On most beats, the event_tag parameter is inconsequential. The only time it matters is when stops or delays are involved:

  • On stops, providing a value of EventTag.STOP or lower will return the time at which the stop is reached, whereas providing EventTag.STOP_END will return the time when the stop ends.

  • On delays, providing a value of EventTag.DELAY or lower will return the time at which the delay is reached, whereas providing EventTag.DELAY_END or higher will return the time when the delay ends.

The default value of EventTag.STOP effectively matches the time at which a note on the given beat must be hit (assuming such a note is hittable()).

beat_at(time: SongTimeOrFloat, event_tag: EventTag = EventTag.STOP) simfile.timing.Beat

Determine the beat at a given time in the song.

At most times, the event_tag parameter is inconsequential. The only time it matters is when the time lands exactly on a warp segment:

  • Providing EventTag.WARP or lower will return the beat where the warp starts.

  • Providing EventTag.WARP_END or higher will return the beat where the warp ends (or is interrupted by a stop or delay).

Note that the above scenario is floating-point precise. It will likely require a song time obtained from time_at() in order for the event tag to make a difference.