Beatmap API

Parse, inspect and re-encode .osu files.

Beatmap

class parsecore.Beatmap.beatmap.Beatmap(format_version, general, editor, metadata, difficulty, events, timing_points, colors, hit_objects)[source]

Bases: object

A fully parsed .osu beatmap.

Bundles every section (general, metadata, difficulty, events, timing points, hit objects, colours, editor) and exposes convenient accessors plus decoding and encoding entry points.

Parameters:
  • format_version (int)

  • general (General)

  • editor (Editor)

  • metadata (Metadata)

  • difficulty (Difficulty)

  • events (Events)

  • timing_points (TimingPointsState)

  • colors (Colors)

  • hit_objects (HitObjectsState)

format_version: int
general: General
editor: Editor
metadata: Metadata
difficulty: Difficulty
events: Events
timing_points: TimingPointsState
colors: Colors
hit_objects: HitObjectsState
property control_points: ControlPoints

Return the beatmap’s timing/difficulty/sample/effect control points.

property mode: GameMode

Return the beatmap’s game mode.

property audio_filename: str

Return the audio file name from [General].

property audio_lead_in: int

Return the audio lead-in in milliseconds.

property preview_time: int

Return the audio preview time in milliseconds.

property stack_leniency: float

Return the stack leniency.

property letterbox_in_breaks: bool

Return whether letterboxing is shown during breaks.

property widescreen_storyboard: bool

Return whether the storyboard is widescreen.

property epilepsy_warning: bool

Return whether an epilepsy warning is shown.

property special_style: bool

Return whether osu!mania special (N+1) style is enabled.

property samples_match_playback_rate: bool

Return whether samples follow the playback rate.

property title: str

Return the romanised song title.

property title_unicode: str

Return the song title in its original script.

property artist: str

Return the romanised artist name.

property artist_unicode: str

Return the artist name in its original script.

property creator: str

Return the mapper’s username.

property version: str

Return the difficulty name.

property source: str

Return the song source.

property tags: str

Return the search tags.

property beatmap_id: int

Return the beatmap (difficulty) id.

property beatmap_set_id: int

Return the beatmap set id.

property hp_drain_rate: float

Return the HP drain rate (HP).

property circle_size: float

Return the circle size (CS).

property overall_difficulty: float

Return the overall difficulty (OD).

property approach_rate: float

Return the approach rate (AR).

property slider_multiplier: float

Return the base slider velocity multiplier.

property slider_tick_rate: float

Return the slider tick rate.

classmethod from_path(path)[source]

Decode a beatmap from a .osu file on disk.

Parameters:

path (str) – Path to the .osu file.

Return type:

Beatmap

Returns:

The parsed beatmap.

Raises:
  • ParseBeatmapError – If the file cannot be decoded.

  • UnknownFileFormatError – If the format header is missing.

classmethod from_bytes(data)[source]

Decode a beatmap from in-memory .osu file bytes.

Parameters:

data (bytes) – The raw file contents.

Return type:

Beatmap

Returns:

The parsed beatmap.

Raises:
  • ParseBeatmapError – If the data cannot be decoded.

  • UnknownFileFormatError – If the format header is missing.

to_bytes(*, lazer_compatible=False)[source]

Encode the beatmap to .osu file bytes.

Return type:

bytes

Returns:

The UTF-8 encoded .osu file contents.

Parameters:

lazer_compatible (bool)

encode_to_path(path, *, lazer_compatible=False)[source]

Encode the beatmap and write it to a file.

Parameters:
  • path (str) – Destination path for the .osu file.

  • lazer_compatible (bool)

Return type:

None

encode_to_string(*, lazer_compatible=False)[source]

Encode the beatmap to a .osu file string.

Return type:

str

Returns:

The encoded .osu text.

Parameters:

lazer_compatible (bool)

Sections

Parser and data model for the [General] section of a .osu file.

exception parsecore.Beatmap.section.general.ParseGeneralError(message)[source]

Bases: Exception

Raised when a line in the [General] section cannot be parsed.

Parameters:

message (str)

class parsecore.Beatmap.section.general.GeneralKey(*values)[source]

Bases: Enum

Recognised keys of the [General] section.

AudioFilename = 'AudioFilename'
AudioLeadIn = 'AudioLeadIn'
AudioHash = 'AudioHash'
PreviewTime = 'PreviewTime'
Countdown = 'Countdown'
SampleSet = 'SampleSet'
StackLeniency = 'StackLeniency'
Mode = 'Mode'
LetterboxInBreaks = 'LetterboxInBreaks'
StoryFireInFront = 'StoryFireInFront'
UseSkinSprites = 'UseSkinSprites'
AlwaysShowPlayfield = 'AlwaysShowPlayfield'
OverlayPosition = 'OverlayPosition'
SkinPreference = 'SkinPreference'
EpilepsyWarning = 'EpilepsyWarning'
CountdownOffset = 'CountdownOffset'
SpecialStyle = 'SpecialStyle'
WidescreenStoryboard = 'WidescreenStoryboard'
SamplesMatchPlaybackRate = 'SamplesMatchPlaybackRate'
classmethod from_str(s)[source]

Return the GeneralKey matching a raw key string.

Parameters:

s (str) – The key text as it appears in the file.

Return type:

GeneralKey

Returns:

The matching enum member.

Raises:

ValueError – If the key is not a recognised general key.

class parsecore.Beatmap.section.general.General[source]

Bases: object

Parsed contents of the [General] section with osu!-stable defaults.

audio_filename: str
audio_lead_in: int
preview_time: int
countdown: CountdownType
sample_bank: SampleBank
stack_leniency: float
mode: GameMode
letterbox_in_breaks: bool
special_style: bool
widescreen_storyboard: bool
epilepsy_warning: bool
samples_match_playback_rate: bool
parse_general(line)[source]

Parse a single [General] line into this instance.

Unknown keys are ignored. Recognised keys update the corresponding field in place.

Parameters:

line (str) – One raw key: value line from the section.

Raises:

ParseGeneralError – If a value fails to parse as its expected type.

Return type:

None

parsecore.Beatmap.section.general.GeneralState

alias of General

Parser and data model for the [Metadata] section of a .osu file.

exception parsecore.Beatmap.section.metadata.ParseMetadataError(message)[source]

Bases: Exception

Raised when a line in the [Metadata] section cannot be parsed.

Parameters:

message (str)

class parsecore.Beatmap.section.metadata.MetadataKey(*values)[source]

Bases: Enum

Recognised keys of the [Metadata] section.

Title = 'Title'
TitleUnicode = 'TitleUnicode'
Artist = 'Artist'
ArtistUnicode = 'ArtistUnicode'
Creator = 'Creator'
Version = 'Version'
Source = 'Source'
Tags = 'Tags'
BeatmapID = 'BeatmapID'
BeatmapSetID = 'BeatmapSetID'
classmethod from_str(s)[source]

Return the MetadataKey matching a raw key string.

Parameters:

s (str) – The key text as it appears in the file.

Return type:

MetadataKey

Returns:

The matching enum member.

Raises:

ValueError – If the key is not a recognised metadata key.

class parsecore.Beatmap.section.metadata.Metadata[source]

Bases: object

Parsed contents of the [Metadata] section (title, artist, creator, IDs, …).

title: str
title_unicode: str
artist: str
artist_unicode: str
creator: str
version: str
source: str
tags: str
beatmap_id: int
beatmap_set_id: int
parse_metadata(line)[source]

Parse a single [Metadata] line into this instance.

Unknown keys are ignored; recognised keys update the matching field in place.

Parameters:

line (str) – One raw key:value line from the section.

Raises:

ParseMetadataError – If a numeric value fails to parse.

Return type:

None

parsecore.Beatmap.section.metadata.MetadataState

alias of Metadata

Parser and data model for the [Difficulty] section of a .osu file.

exception parsecore.Beatmap.section.difficulty.ParseDifficultyError(message)[source]

Bases: Exception

Raised when a line in the [Difficulty] section cannot be parsed.

Parameters:

message (str)

class parsecore.Beatmap.section.difficulty.DifficultyKey(*values)[source]

Bases: Enum

Recognised keys of the [Difficulty] section.

HPDrainRate = 'HPDrainRate'
CircleSize = 'CircleSize'
OverallDifficulty = 'OverallDifficulty'
ApproachRate = 'ApproachRate'
SliderMultiplier = 'SliderMultiplier'
SliderTickRate = 'SliderTickRate'
classmethod from_str(s)[source]

Return the DifficultyKey matching a raw key string.

Parameters:

s (str) – The key text as it appears in the file.

Return type:

DifficultyKey

Returns:

The matching enum member.

Raises:

ValueError – If the key is not a recognised difficulty key.

class parsecore.Beatmap.section.difficulty.Difficulty[source]

Bases: object

Difficulty settings of a beatmap (HP, CS, OD, AR, slider multiplier/tick rate).

hp_drain_rate: float
circle_size: float
overall_difficulty: float
approach_rate: float
slider_multiplier: float
slider_tick_rate: float
class parsecore.Beatmap.section.difficulty.DifficultyState(format_version=14)[source]

Bases: object

Accumulates [Difficulty] values while decoding.

The beatmap format version is tracked because older versions default the approach rate to the overall difficulty when ApproachRate is absent.

Parameters:

format_version (int)

has_approach_rate: bool
difficulty: Difficulty
parse_difficulty(line)[source]

Parse a single [Difficulty] line into this instance.

Parameters:

line (str) – One raw key:value line from the section.

Raises:

ParseDifficultyError – If a value fails to parse as a number.

Return type:

None

Parser and data model for the [TimingPoints] section (control points).

exception parsecore.Beatmap.section.timing_points.ParseTimingPointsError(message)[source]

Bases: Exception

Raised when a line in the [TimingPoints] section cannot be parsed.

Parameters:

message (str)

class parsecore.Beatmap.section.timing_points.EffectFlags[source]

Bases: object

Bit flags of a timing point’s effect column (kiai, omit first barline).

NONE = 0
KIAI = 1
OMIT_FIRST_BAR_LINE = 8
class parsecore.Beatmap.section.timing_points.TimingPoint(time=0.0, beat_len=1000.0, omit_first_bar_line=False, time_signature=4)[source]

Bases: object

An uninherited (red) timing point defining a beat length from a time onward.

Parameters:
time: float
beat_len: float
omit_first_bar_line: bool
time_signature: int
class parsecore.Beatmap.section.timing_points.DifficultyPoint(time=0.0, slider_velocity=1.0, generate_ticks=True)[source]

Bases: object

An inherited (green) point overriding slider velocity from a time onward.

Parameters:
time: float
slider_velocity: float
generate_ticks: bool
is_redundant(existing)[source]

Return whether this point has no effect over existing.

Redundant points are dropped so lookups mirror osu!’s behaviour.

Parameters:

existing (DifficultyPoint) – The point currently in effect at this time.

Return type:

bool

Returns:

True if this point changes nothing.

class parsecore.Beatmap.section.timing_points.SamplePoint(time=0.0, sample_bank=SampleBank.Normal, sample_volume=100, custom_sample_bank=0)[source]

Bases: object

A point overriding the hit-sound sample bank and volume from a time onward.

Parameters:
  • time (float)

  • sample_bank (SampleBank)

  • sample_volume (int)

  • custom_sample_bank (int)

time: float
sample_bank: SampleBank
sample_volume: int
custom_sample_bank: int
is_redundant(existing)[source]

Return whether this sample point matches existing.

Parameters:

existing (SamplePoint) – The sample point currently in effect.

Return type:

bool

Returns:

True if this point changes nothing.

class parsecore.Beatmap.section.timing_points.EffectPoint(time=0.0, kiai=False, scroll_speed=1.0)[source]

Bases: object

A point carrying effect state (kiai time, scroll speed) from a time onward.

Parameters:
time: float
kiai: bool
scroll_speed: float
is_redundant(existing)[source]

Return whether this effect point matches existing.

Parameters:

existing (EffectPoint) – The effect point currently in effect.

Return type:

bool

Returns:

True if this point changes nothing.

class parsecore.Beatmap.section.timing_points.ControlPoints(timing_points=<factory>, difficulty_points=<factory>, effect_points=<factory>, sample_points=<factory>)[source]

Bases: object

All timing/difficulty/sample/effect points of a beatmap, kept time-sorted.

Parameters:
  • timing_points (list[TimingPoint])

  • difficulty_points (list[DifficultyPoint])

  • effect_points (list[EffectPoint])

  • sample_points (list[SamplePoint])

timing_points: list[TimingPoint]
difficulty_points: list[DifficultyPoint]
effect_points: list[EffectPoint]
sample_points: list[SamplePoint]
difficulty_point_at(time)[source]

Return the difficulty point in effect at time.

Parameters:

time (float) – The time in milliseconds.

Return type:

DifficultyPoint

Returns:

The active difficulty point (a default if none precedes time).

effect_point_at(time)[source]

Return the effect point in effect at time.

Parameters:

time (float) – The time in milliseconds.

Return type:

EffectPoint

Returns:

The active effect point (a default if none precedes time).

sample_point_at(time)[source]

Return the sample point in effect at time.

Parameters:

time (float) – The time in milliseconds.

Return type:

SamplePoint

Returns:

The active sample point (a default if none precedes time).

timing_point_at(time)[source]

Return the timing point in effect at time.

Parameters:

time (float) – The time in milliseconds.

Return type:

TimingPoint

Returns:

The active timing point (the first one if time precedes all points).

add_timing(point)[source]

Insert a timing point, keeping the list time-sorted.

Parameters:

point (TimingPoint) – The timing point to add.

Return type:

None

add_difficulty(point)[source]

Insert a difficulty point unless it is redundant.

Parameters:

point (DifficultyPoint) – The difficulty point to add.

Return type:

None

add_effect(point)[source]

Insert an effect point unless it is redundant.

Parameters:

point (EffectPoint) – The effect point to add.

Return type:

None

add_sample(point)[source]

Insert a sample point unless it is redundant.

Parameters:

point (SamplePoint) – The sample point to add.

Return type:

None

class parsecore.Beatmap.section.timing_points.TimingPointsState(mode, default_bank, default_volume)[source]

Bases: object

Accumulates control points while decoding, resolving pending sample state.

Parameters:
  • mode (GameMode)

  • default_bank (SampleBank)

  • default_volume (int)

general_mode
general_default_sample_bank
general_default_sample_volume
pending_time: float
pending_timing: TimingPoint | None
pending_difficulty: DifficultyPoint | None
pending_effect: EffectPoint | None
pending_sample: SamplePoint | None
control_points
flush_pending()[source]

Commit any buffered control point at the pending time.

Return type:

None

push_point(time, point, timing_change)[source]

Buffer a parsed control point at a given time.

Parameters:
  • time (float) – The point’s time in milliseconds.

  • point – The control point value.

  • timing_change (bool) – Whether this line was an uninherited (red) point.

Return type:

None

parse_timing_points(line)[source]

Parse a single [TimingPoints] line into control points.

Parameters:

line (str) – One raw comma-separated timing-point line.

Raises:

ParseTimingPointsError – If the line is malformed.

Return type:

None

Hit objects & sliders

Parser and data model for the [HitObjects] section (circles, sliders, …).

exception parsecore.Beatmap.section.hit_objects.hit_objects.ParseHitObjectsError(message)[source]

Bases: Exception

Raised when a line in the [HitObjects] section cannot be parsed.

Parameters:

message (str)

Return type:

None

class parsecore.Beatmap.section.hit_objects.hit_objects.HitObjectType[source]

Bases: object

Bit flags of a hit object’s type column (circle, slider, spinner, hold, new combo).

CIRCLE = 1
SLIDER = 2
NEW_COMBO = 4
SPINNER = 8
COMBO_OFFSET = 112
HOLD = 128
static has_flag(value, flag)[source]

Return whether a type flag is set.

Parameters:
  • value (int) – The raw type bitfield.

  • flag (int) – The single flag to test for.

Return type:

bool

Returns:

True if the flag bit is present.

class parsecore.Beatmap.section.hit_objects.hit_objects.HitSampleDefaultName(*values)[source]

Bases: Enum

Default hit-sound sample names (normal, whistle, finish, clap).

Normal = 'hitnormal'
Whistle = 'hitwhistle'
Finish = 'hitfinish'
Clap = 'hitclap'
class parsecore.Beatmap.section.hit_objects.hit_objects.HitSampleInfo(name_default, name_file, bank, suffix, volume, custom_sample_bank, bank_specified, is_layered)[source]

Bases: object

A resolved hit sample: bank, name/file, volume and layering.

Parameters:
  • name_default (HitSampleDefaultName | None)

  • name_file (str | None)

  • bank (SampleBank)

  • suffix (int | None)

  • volume (int)

  • custom_sample_bank (int)

  • bank_specified (bool)

  • is_layered (bool)

name_default: HitSampleDefaultName | None
name_file: str | None
bank: SampleBank
suffix: int | None
volume: int
custom_sample_bank: int
bank_specified: bool
is_layered: bool
class parsecore.Beatmap.section.hit_objects.hit_objects.SampleBankInfo(filename=None, bank_for_normal=None, bank_for_addition=None, volume=0, custom_sample_bank=0)[source]

Bases: object

Working sample-bank state while parsing one hit object’s hit sounds.

Parameters:
  • filename (str | None)

  • bank_for_normal (SampleBank | None)

  • bank_for_addition (SampleBank | None)

  • volume (int)

  • custom_sample_bank (int)

filename: str | None
bank_for_normal: SampleBank | None
bank_for_addition: SampleBank | None
volume: int
custom_sample_bank: int
read_custom_sample_bank(parts, banks_only)[source]

Parse the trailing sampleSet:... fields of a hit object.

Parameters:
  • parts (list[str]) – The colon-split extras (bank, addition bank, index, volume, file).

  • banks_only (bool) – If True, only read the two bank fields.

Return type:

None

convert_sound_type(sound_type)[source]

Expand a hit-sound bitfield into concrete sample infos.

Parameters:

sound_type (HitSoundType) – The hit-sound flags for the object.

Return type:

list[HitSampleInfo]

Returns:

One HitSampleInfo per active sound (normal plus any additions).

class parsecore.Beatmap.section.hit_objects.hit_objects.HitObjectCircle(pos, new_combo, combo_offset)[source]

Bases: object

A hit circle at a position.

Parameters:
pos: Pos
new_combo: bool
combo_offset: int
class parsecore.Beatmap.section.hit_objects.hit_objects.HitObjectSpinner(pos, duration, new_combo)[source]

Bases: object

A spinner with a start and end time.

Parameters:
pos: Pos
duration: float
new_combo: bool
class parsecore.Beatmap.section.hit_objects.hit_objects.HitObjectHold(pos_x, duration)[source]

Bases: object

An osu!mania hold note (column plus duration).

Parameters:
pos_x: float
duration: float
class parsecore.Beatmap.section.hit_objects.hit_objects.HitObjectSlider(pos, new_combo, combo_offset, path, node_samples, repeat_count, velocity, edge_sounds=<factory>)[source]

Bases: object

A slider: path, repeats, per-node samples and edge sounds.

Parameters:
  • pos (Pos)

  • new_combo (bool)

  • combo_offset (int)

  • path (SliderPath)

  • node_samples (list[list[HitSampleInfo]])

  • repeat_count (int)

  • velocity (float)

  • edge_sounds (list[int])

pos: Pos
new_combo: bool
combo_offset: int
path: SliderPath
node_samples: list[list[HitSampleInfo]]
repeat_count: int
velocity: float
edge_sounds: list[int]
class parsecore.Beatmap.section.hit_objects.hit_objects.HitObject(start_time, kind, samples)[source]

Bases: object

A single parsed hit object (its kind plus shared start time and samples).

Parameters:
  • start_time (float)

  • kind (HitObjectCircle | HitObjectSpinner | HitObjectHold | HitObjectSlider)

  • samples (list[HitSampleInfo])

start_time: float
kind: HitObjectCircle | HitObjectSpinner | HitObjectHold | HitObjectSlider
samples: list[HitSampleInfo]
parsecore.Beatmap.section.hit_objects.hit_objects.is_linear(p0, p1, p2)[source]

Return whether three points are collinear.

Parameters:
  • p0 (Pos) – First point.

  • p1 (Pos) – Second point.

  • p2 (Pos) – Third point.

Return type:

bool

Returns:

True if the points lie on a straight line (within tolerance).

parsecore.Beatmap.section.hit_objects.hit_objects.convert_points(curve_points, points, end_points, first, offset)[source]

Parse one segment of a slider path string into control points.

Parameters:
  • curve_points (list[PathControlPoint]) – The output list to append to.

  • points (list[str]) – The pipe-split anchor tokens for this segment.

  • end_points (str | None) – An optional extra endpoint token.

  • first (bool) – Whether this is the first segment of the path.

  • offset (Pos) – The slider’s start position (anchors are stored relative to it).

Return type:

None

parsecore.Beatmap.section.hit_objects.hit_objects.convert_path_str(point_str, offset)[source]

Parse a full slider path string into control points.

Parameters:
  • point_str (str) – The raw path string (e.g. B|320:96|...).

  • offset (Pos) – The slider’s start position.

Return type:

list[PathControlPoint]

Returns:

The parsed control points.

class parsecore.Beatmap.section.hit_objects.hit_objects.HitObjectsState[source]

Bases: object

Accumulates hit objects while decoding the [HitObjects] section.

last_object_type: int | None
hit_objects: list[HitObject]
last_object_was_spinner()[source]

Return whether the previously parsed object was a spinner.

Return type:

bool

Returns:

True if the last object was a spinner (affects new-combo handling).

parse_hit_object(line)[source]

Parse a single [HitObjects] line and append the object.

Parameters:

line (str) – One raw comma-separated hit-object line.

Raises:

ParseHitObjectsError – If the line is too short or malformed.

Return type:

None

Slider path geometry: control points, curve types and length calculation.

class parsecore.Beatmap.section.hit_objects.slider.PathType(kind, degree=None)[source]

Bases: object

The interpolation type of a slider segment (linear, bezier, catmull, perfect circle).

Parameters:
  • kind (SplineType)

  • degree (int | None)

kind: SplineType
degree: int | None
classmethod new_from_str(s)[source]

Return the PathType for a path-type character.

Parameters:

s (str) – The single-letter type code (L, B, C or P).

Return type:

PathType

Returns:

The matching path type (bezier as the fallback).

class parsecore.Beatmap.section.hit_objects.slider.PathControlPoint(pos, path_type=None)[source]

Bases: object

A slider anchor point, optionally starting a new segment of a given type.

Parameters:
  • pos (Pos)

  • path_type (PathType | None)

pos: Pos
path_type: PathType | None
class parsecore.Beatmap.section.hit_objects.slider.Curve(mode, points, expected_len)[source]

Bases: object

A sampled slider path built from its control points.

The path is approximated exactly like osu!-stable (piecewise bezier, catmull and circular-arc segments) and then clamped/extended to the expected length so distances match the game.

Parameters:
path: list[Pos]
lengths: list[float]
dist()[source]

Return the total sampled path length.

Return type:

float

Returns:

The curve length in osu! pixels.

progress_to_dist(progress)[source]

Convert a 0-1 progress fraction to a distance along the path.

Parameters:

progress (float) – The fractional progress along the slider.

Return type:

float

Returns:

The corresponding distance in osu! pixels.

class parsecore.Beatmap.section.hit_objects.slider.SliderPath(mode, control_points, expected_dist)[source]

Bases: object

A slider’s control points plus its expected length, lazily sampled into a Curve.

Parameters:
  • mode (GameMode)

  • control_points (list[PathControlPoint])

  • expected_dist (float | None)

mode: GameMode
control_points: list[PathControlPoint]
expected_dist: float | None
curve()[source]

Return the sampled curve, building it on first access.

Return type:

Curve

Returns:

The cached Curve for this path.

class parsecore.Beatmap.section.hit_objects.slider.SliderEventType(*values)[source]

Bases: Enum

The kind of event emitted while traversing a slider (head, tick, repeat, tail).

Head = 0
Tick = 1
Repeat = 2
LastTick = 3
Tail = 4
class parsecore.Beatmap.section.hit_objects.slider.SliderEvent(kind, span_idx, span_start_time, time, path_progress)[source]

Bases: object

A scoring event on a slider at a given time (head, tick, repeat or tail).

Parameters:
  • kind (SliderEventType)

  • span_idx (int)

  • span_start_time (float)

  • time (float)

  • path_progress (float)

kind: SliderEventType
span_idx: int
span_start_time: float
time: float
path_progress: float
parsecore.Beatmap.section.hit_objects.slider.generate_slider_events(start_time, span_duration, velocity, tick_dist, total_dist, span_count)[source]

Yield the scoring events of a slider in time order.

Reproduces osu!-stable’s tick/repeat/tail placement.

Parameters:
  • start_time (float) – The slider’s start time in milliseconds.

  • span_duration (float) – Duration of a single span (one traversal).

  • velocity (float) – Slider velocity in pixels per millisecond.

  • tick_dist (float) – Distance between ticks in pixels.

  • total_dist (float) – Total path length in pixels.

  • span_count (int) – Number of spans (repeats + 1).

Yields:

Each SliderEvent in chronological order.

Return type:

Generator[SliderEvent, None, None]

Utilities

class parsecore.Beatmap.utils.Pos(x=0.0, y=0.0)[source]

Bases: object

A 2D position/vector whose arithmetic is computed in 32-bit floats.

Every operation routes through f32() so that distances, dot products and curve math reproduce osu!’s float behaviour exactly.

Parameters:
x: float
y: float
length_squared()[source]

Return the squared length (x*x + y*y) in f32.

Return type:

float

Returns:

The squared magnitude of the vector.

length()[source]

Return the vector length in f32.

Return type:

float

Returns:

The Euclidean magnitude, computed as osu! does.

dot(other)[source]

Return the f32 dot product with another vector.

Parameters:

other (Pos) – The other vector.

Return type:

float

Returns:

self.x*other.x + self.y*other.y in f32.

distance(other)[source]

Return the f32 distance to another position.

Parameters:

other (Pos) – The other position.

Return type:

float

Returns:

The length of self - other.

normalize()[source]

Return a unit vector in the same direction.

Return type:

Pos

Returns:

self divided by its length (in f32).

parsecore.Beatmap.utils.f32(value)[source]

Round a double to IEEE-754 single precision (32-bit float).

osu! and osu!lazer perform position and several timing calculations in 32-bit floats. Mirroring that here is what keeps parsecore bit-exact with the game, so this helper is applied wherever the reference uses float (Rust f32).

Parameters:

value (float) – The double-precision value.

Return type:

float

Returns:

value rounded to the nearest 32-bit float, as a Python float.