ContinuousPhysicalTimeline

timelines.ContinuousPhysicalTimeline(
    length=0,
    unit=None,
    number_type=None,
    id_prefix='tl',
    uid=None,
    name=None,
    locked=False,
    meta=None,
)

A physical timeline with continuous coordinates.

Used for acoustic time measurements where arbitrary precision is needed (e.g., note onsets at 1.234 seconds).

Default unit: seconds. Default number type: float. Allowed units: seconds, milliseconds, minutes (NOT samples/frames).

Provides convenience methods for creating metrical timelines connected via TimelineGroups (per TTA specification, children must share the parent’s unit; cross-domain relationships use groups).

Methods

Name Description
create_metrical_grid Create a metrical grid timeline with automatic beat/measure computation.
create_metrical_region Create a metrical grid for an existing region.

create_metrical_grid

timelines.ContinuousPhysicalTimeline.create_metrical_grid(
    first_beat_at,
    tempo_bpm,
    beats_per_measure=4,
    beat_unit=Fraction(1, 4),
    end_at=None,
    start_mc=1,
    start_mn='1',
    anacrusis_quarters=None,
    measure_type='none',
    beat_type='none',
    name=None,
)

Create a metrical grid timeline with automatic beat/measure computation.

This is the primary convenience method for users who have an audio file and know: (1) tempo, (2) meter, and (3) where the first beat is. They do NOT need to know the total length in quarters - the library computes that automatically.

A timeline can accommodate other timelines as Children when they use the same measuring unit. Therefore, a logical timeline (quarters) cannot be a child of a physical timeline (seconds). Instead, this method creates a standalone ContinuousLogicalTimeline and connects it to this physical timeline via a TimelineGroup with bidirectional linear interpolation.

The returned MetricalResult provides convenient access to: - The created grid (ContinuousLogicalTimeline in quarters) - The TimelineGroup connecting physical and logical coordinates - Methods for timestamp queries with metrical information

Parameters

Name Type Description Default
first_beat_at float Coordinate (in seconds) of the first beat. required
tempo_bpm float Tempo in beats per minute. required
beats_per_measure int Number of beats per measure. Default 4. 4
beat_unit Fraction Note value of one beat. Default 1/4 (quarter note). Use Fraction(1, 8) for eighth-note beats (e.g., 6/8 time). Fraction(1, 4)
end_at float | None Coordinate (in seconds) where the grid ends. If None, extends to the end of the physical timeline. None
start_mc int MC (measure count) of the first measure. Default 1. 1
start_mn str MN (measure number label) of the first measure. Default “1”. Use “0” for anacrusis (pickup measure). '1'
anacrusis_quarters Fraction | None If set, the first measure is shorter (pickup). Specified in quarter notes. None
measure_type Literal['none', 'events', 'children'] How to represent measures in the grid: - “none”: No measure entities (default) - “events”: Create Measure as IntervalEvents - “children”: Create each measure as a Child timeline 'none'
beat_type Literal['none', 'instants', 'intervals', 'segments'] How to represent beats in the grid: - “none”: No beat entities (default) - “instants”: Create Beat as InstantEvents - “intervals”: Create Beat as IntervalEvents (with duration) - “segments”: Create a SegmentLine with beat Segments 'none'
name str | None Human-readable name for the grid timeline. None

Returns

Name Type Description
MetricalResult MetricalResult containing the grid, group, and accessor methods.

Raises

Name Type Description
ValueError If first_beat_at is negative or after end_at.

Examples

>>> # Audio file at 120 BPM, 4/4, first beat at 0.5 seconds
>>> audio = ContinuousPhysicalTimeline(length=180.0)
>>> result = audio.create_metrical_grid(
...     first_beat_at=0.5,
...     tempo_bpm=120.0,
...     beats_per_measure=4,
... )
>>> # Query metrical info at 60 seconds
>>> result.timestamp_at_seconds(60.0)
{'seconds': 60.0, 'quarters': 119.0, 'mc': 30, 'beat': Fraction(4, 1), 'mn': '30'}
>>> # Find where measure 10, beat 1 is
>>> result.seconds_at(mc=10, beat=Fraction(1, 1))
18.5
>>> # Access the group for general coordinate conversion
>>> result.group.convert(100.0, result.grid.id, audio.id)  # quarters -> seconds
50.5
>>> # With anacrusis (pickup beat)
>>> result = audio.create_metrical_grid(
...     first_beat_at=0.25,
...     tempo_bpm=100.0,
...     beats_per_measure=3,
...     start_mn="0",
...     anacrusis_quarters=Fraction(1, 1),  # 1 beat pickup
... )

create_metrical_region

timelines.ContinuousPhysicalTimeline.create_metrical_region(
    region_name,
    tempo_bpm,
    beats_per_measure=4,
    beat_unit=Fraction(1, 4),
    start_mc=1,
    start_mn='1',
    anacrusis_quarters=None,
    measure_type='none',
    beat_type='none',
)

Create a metrical grid for an existing region.

This method creates a metrical grid that corresponds to a named region on this physical timeline. Per TTA Table 2, regions are named parts of a timeline defined by a TimeInterval. This method creates the metrical structure for that region.

Parameters

Name Type Description Default
region_name str Name of an existing region on this timeline. required
tempo_bpm float Tempo in beats per minute. required
beats_per_measure int Number of beats per measure. Default 4. 4
beat_unit Fraction Note value of one beat. Default 1/4 (quarter note). Fraction(1, 4)
start_mc int MC (measure count) of the first measure. Default 1. 1
start_mn str MN (measure number label) of the first measure. '1'
anacrusis_quarters Fraction | None If set, the first measure is shorter (pickup). None
measure_type Literal['none', 'events', 'children'] How to represent measures: - “none”: No measure entities (default) - “events”: Create Measure as IntervalEvents - “children”: Create each measure as a Child timeline 'none'
beat_type Literal['none', 'instants', 'intervals', 'segments'] How to represent beats: - “none”: No beat entities (default) - “instants”: Create Beat as InstantEvents - “intervals”: Create Beat as IntervalEvents - “segments”: Create a SegmentLine with beat Segments 'none'

Returns

Name Type Description
MetricalResult MetricalResult containing the grid, group, and accessor methods.

Raises

Name Type Description
KeyError If the region does not exist.

Examples

>>> audio = ContinuousPhysicalTimeline(length=300.0)
>>> audio.add_region("verse", start=10.0, end=50.0)
>>> result = audio.create_metrical_region(
...     region_name="verse",
...     tempo_bpm=100.0,
...     beats_per_measure=4,
... )
>>> result.timestamp_at_seconds(25.0)
{'seconds': 25.0, 'quarters': 25.0, 'mc': 7, 'beat': Fraction(2, 1), 'mn': '7'}