Flow Control and Grids

BeatGrid, repeats, metrical structure

Flow Control and Grids

Musical timelines are not always linear — repeat signs, Da Capo, and multiple endings introduce jumps. This tutorial shows BeatGrid for rapid measure/beat querying and how loaders handle flow structures.

from fractions import Fraction

from timetoalign import BeatGrid

BeatGrid from Tempo

Given a constant tempo and duration, BeatGrid.from_tempo() builds a metrical timeline with vectorised beat/measure accessors.

grid = BeatGrid.from_tempo(
    tempo_bpm=120.0,
    beats_per_measure=4,
    length_seconds=30.0,
    uid="demo_grid",
)
grid
BeatGrid[demo_grid] (4 cmaps)
                      0 __________________________________ 60 quarters

Querying Measure and Beat

# At quarter-note position 6.0 --- which measure and beat?
{
    "quarters": 6.0,
    "measure": grid.measure_at(6.0),
    "beat": grid.beat_at(6.0),
}
{'quarters': 6.0, 'measure': 2, 'beat': Fraction(3, 1)}
# Reverse: measure 3, beat 1 --- what quarter-note position?
grid.quarter_at(measure=3, beat=Fraction(1))
Fraction(8, 1)

Vectorised Accessors

Beat and measure times as numpy arrays, useful for exporting to Sonic Visualiser or Audacity.

grid.beat_seconds()[:12]
array([0. , 0.5, 1. , 1.5, 2. , 2.5, 3. , 3.5, 4. , 4.5, 5. , 5.5])
grid.measure_seconds()
array([ 0.,  2.,  4.,  6.,  8., 10., 12., 14., 16., 18., 20., 22., 24.,
       26., 28.])

Export to CSV

# grid.export_to_csv("beats.csv", format="sonic_visualiser")

Loading Scores with Flow

Loaders such as Music21Loader parse repeat signs and jumps from MusicXML or MEI. The resulting timeline includes FlowControlElement events. See the How-To notebooks for worked examples with real scores containing repeats and D.S. markings.

Congratulations! With these four tutorials you have met the core abstractions: Timelines, Events, ConversionMaps, TimelineGroups, AlignmentBundles, and BeatGrids. The How-To Guides explore real-world workflows in depth.