Quickstart

A five-minute tour of Timelines

Quickstart

Music exists simultaneously as audio, notation, and images — each with its own coordinate system. Time To Align! provides a single framework for connecting them.

Domain Description Examples
Physical Wall-clock time Seconds, samples, frames
Logical Symbolic/musical time Beats, quarters, ticks
Graphical Visual coordinates Pixels, centimetres

This whirlwind tour covers the core concepts in under five minutes. Each section links to a full tutorial.

from pathlib import Path

from timetoalign import BeatGrid, MatchfileLoader, TimelineGroup
from timetoalign.loader.midi.performance import PerformanceMidiLoader
from timetoalign.loader.score.partitura import PartituraLoader
from timetoalign.loader.score.tsv import TSVLoader
from timetoalign.maps import TicksToQuarters

DATA_DIR = Path(".").resolve().parents[1] / "tests" / "data"

Same content, different formats

Before the tour, a quick demonstration of what Time To Align! is for. We load Chopin’s Etude Op. 10 No. 3 from both MusicXML and a TSV note list, and check that both loaders see the same musical content.

pt_loader = PartituraLoader()
pt_loader.load(DATA_DIR / "vienna_1x22" / "Chopin_op10_no3.musicxml")
tsv_loader = TSVLoader.from_file(
    DATA_DIR / "vienna_1x22" / "ms3" / "chopin_op10_no3.notes.tsv"
)

{
    "Partitura (MusicXML)": len(pt_loader.store.notes),
    "TSV (MS3 export)": len(tsv_loader.store.notes),
}
{'Partitura (MusicXML)': 498, 'TSV (MS3 export)': 498}

Both loaders find 498 notes — different formats, same musical content. From here on we use the Partitura loader as the source for the tour.

1. Timelines & Events

Promote the loaded score into a timeline with nested children. (Full tutorial)

score = pt_loader.create_timeline(uid="score")
score
ContinuousLogicalTimeline[score] (547 events, 3 children, 3 cmaps)
                      0 ________________________________ 41.5 quarters
  ├─ notes            0 ________________________________ 41.5 (498 events)
  ├─ measures         0 ________________________________ 41.5 (22 events)
  └─ controls         0 ______________________________   40 (27 events)

2. Timestamps

A cross-section showing coordinates in the root and all children. (Full tutorial)

score.get_timestamps().head(5)
axis (quarters) score (quarters) notes (quarters) measures (quarters) controls (quarters) quarters_to_ticks (ticks) quarters_to_measures (measures) raw_quarters (quarters)
id
notes:note:000001 0 0 0 0 0 0 1 -1/2
notes:note:000002 1/2 1/2 1/2 1/2 1/2 240 2 0
notes:note:000006 3/4 3/4 3/4 3/4 3/4 360 17/8 1/4
notes:note:000008 1 1 1 1 1 480 9/4 1/2
notes:note:000010 5/4 5/4 5/4 5/4 5/4 600 19/8 3/4

3. Conversion Maps

Translate between units (e.g., quarters to MIDI ticks). (Full tutorial)

q2t = TicksToQuarters(ppq=480).inverse()
score.add_conversion_map(q2t)
score.convert_to(score.make_coordinate(8), target_unit="ticks")
Coordinate(3840, ticks)

4. Timeline Groups

Link timelines for coordinate transfer. (Full tutorial)

perf = PerformanceMidiLoader.from_file(
    DATA_DIR / "midi" / "performance" / "rachmaninoff_perf.mid"
).create_timeline(uid="perf")

group = TimelineGroup(id="demo")
group.add_timeline(score)
group.add_timeline(perf)

ts = group.get_timestamp_at(20.0, "score")
ts
TimeStamp interpolated
ID Coordinate Type
score 20 quarters axis
perf 5560 ticks child
quarters 19.5 quarters cmap
ticks 9600 ticks cmap
measures 11.75 measures cmap

5. Alignment Bundles

Load 22 performances from .match files in one go. (Full tutorial)

match_files = sorted((DATA_DIR / "vienna_1x22").glob("*.match"))
bundle = MatchfileLoader().load(*match_files).create_alignment_bundle()

{"timelines": len(bundle.timeline_ids), "groups": len(bundle.group_ids)}
{'timelines': 23, 'groups': 1}

6. Beat Grids

Rapid measure/beat queries for metrical structure. (Full tutorial)

grid = BeatGrid.from_tempo(tempo_bpm=120, beats_per_measure=4, length_seconds=30)
{"quarters": 6.0, "measure": grid.measure_at(6.0), "beat": grid.beat_at(6.0)}
{'quarters': 6.0, 'measure': 2, 'beat': Fraction(3, 1)}

That’s it. The tutorials that follow unpack each topic in detail; the How-To Guides show real-world workflows.