Margrete RPC
Basic

Time & Musical Position

The Python API uses the models below to express time. All time-related APIs use these models.

Ticks

The lowest-level unit of time is the tick. In Margrete, a whole note has a resolution of TICK_RESOLUTION (1920) ticks, so common note values map to these tick counts:

DurationTicks
Whole note (1/1)1920
Half note (1/2)960
Quarter note (1/4)480
Eighth note (1/8)240
Sixteenth note (1/16)120
Note tick list
from margrete_rpc.chart.notes import Tap
from margrete_rpc.chart.time import TICK_RESOLUTION

tap = Tap(t=TICK_RESOLUTION // 4, x=0, w=4)  # bar 1, beat 2 in 4/4
print(tap.t)  # 480

You can pass ticks directly anywhere a time argument such as t= is accepted.

Positions

Raw tick math often gets hard to read. A musical position (Position) lets you write time in bars and beats:

FormMeaning
(bar,)Start of a bar
(bar, beat)Beat inside a bar
(bar, beat, offset)Beat plus tick offset

All fields are zero-based. For example, bar 1, beat 1 is (0, 0, 0).

For 4/4:

bar 1, beat 1 ── bar 1, beat 2 ── bar 1, beat 3 ── bar 1, beat 4
tick 0           tick 480         tick 960         tick 1440

Any API that takes a time argument can take a musical position (Position) tuple:

from margrete_rpc.chart.notes import Tap

Tap(t=(2,), x=0, w=4)         # bar 3, beat 1
Tap(t=(2, 1), x=0, w=4)       # bar 3, beat 2
Tap(t=(2, 1, 240), x=0, w=4)  # bar 3, beat 2, plus 240 ticks

Inside an open_edit() block, musical position (Position) tuples are resolved using the chart's actual time signatures:

from margrete_rpc.chart.events import BeatEvent
from margrete_rpc.chart.notes import Tap

with m.open_edit(snapshot=False) as tx:
    tx.chart.beats.append(BeatEvent(0, 2, 4))  # 2/4 starting at bar 1
    tx.chart.beats.append(BeatEvent(1, 1, 4))  # 1/4 starting at bar 2
    tx.chart.notes.append(Tap(t=(2, 0), x=0, w=4))

Here (2, 0) still means the start of bar 3, but the resulting tick is affected by the preceding time signatures.

Time-signature changed

Manual conversion

Use tick_to_pos and pos_to_tick when you need to convert values manually:

from margrete_rpc.chart.events import BeatEvent
from margrete_rpc.chart.time import pos_to_tick, tick_to_pos

beat_events = [BeatEvent(0, 4, 4)]

pos = tick_to_pos(1920, beat_events=beat_events)
print(pos)  # Position(bar=1, beat=0, offset=0)

tick = pos_to_tick(2, 3, beat_events=beat_events)
print(tick)  # 2 * 1920 + 3 * 480 = 5280

When beat_events is omitted, these conversion functions use the current chart's time signatures inside open_edit(). Outside open_edit(), they use the default 4/4 time signature.

If your code runs outside open_edit() and the chart is not plain 4/4, pass time signature events explicitly:

from margrete_rpc.chart.events import BeatEvent
from margrete_rpc.chart.time import pos_to_tick

beats = [BeatEvent(0, 3, 4)]  # 3/4
tick = pos_to_tick(10, 0, 0, beat_events=beats)

Division

Musical positions describe where something starts. A division (Division) describes how long it lasts.

Use div_to_tick(numerator, denominator) to convert a note value to ticks:

from margrete_rpc.chart.time import div_to_tick, tick_to_div

quarter = div_to_tick(1, 4)    # 480 ticks
eighth  = div_to_tick(1, 8)    # 240 ticks
dotted  = div_to_tick(3, 4)    # 1440 ticks (three quarter notes)

division = tick_to_div(480)    # Division(numerator=1, denominator=4)

Some APIs also accept division (Division) tuples, such as align() or an AirCrush gap:

# Snap a note's start to the nearest eighth note
note.align((1, 8))

# AirCrush with a sixteenth-note Step gap
AirCrush(t=0, x=0, w=4, h=4, gap=(1, 16), ...)

Positive durations smaller than 1 tick (1/1920), such as 1/2048, are converted to 1 tick.

Using TimeCalculator

For repeated manual time conversions, create a TimeCalculator once instead of passing beat_events to every helper call:

from margrete_rpc.chart.time import TimeCalculator

calc = TimeCalculator(tx.chart.beats)
pos = calc.tick_to_pos(3840)
tick = calc.pos_to_tick(1, 2, 0)

You usually only need TimeCalculator in code that runs outside open_edit(). Inside open_edit(), ticks are calculated automatically using the chart's time signatures.

On this page