Margrete RPC
Basic

Editing Notes

Mental Model

from margrete_rpc.chart.notes import Tap

with m.open_edit(snapshot=False) as tx:
    a = Tap(t=5760, x=4, w=4)
    b = Tap(t=(2, 0, 0), x=0, w=4)
    c = Tap(t=(2, 1, 0), x=0, w=4)

    a.t == b.t  # True

    tx.chart.notes.extend([a, b, c])
->
Positioning notes example

In this example, the script places three Tap notes in the chart. A note usually contains these fields:

FieldMeaning
tThe note's timing. See Time & Musical Position for details.
pThe note position (Position). For example, (1, 0, 0) means 2nd bar, 1st beat. See Time & Musical Position for details.
xThe note's lane position. The usual range is 0 to 15.
wThe note's width.
hThe Air height. Only Air long notes and AirCrush use it.

Ground Notes

Ground notes usually have t, x, and w fields.

Tap

from margrete_rpc.chart.notes import Tap

note = Tap(t=(0, 0), x=4, w=4)

Flick

Flick has an additional dir field for the flick direction.

from margrete_rpc.chart.notes import Flick, FlickDirection

left = Flick(t=(0, 0), x=4, w=4, dir=FlickDirection.LEFT)
right = Flick(t=(0, 1), x=4, w=4, dir="right")
auto = Flick(t=(0, 2), x=4, w=4)  # defaults to "auto"

dir accepts FlickDirection, or a direction string: "auto", "left" and "right".

Extap

Extap has an additional dir field for the direction of its burst effect.

from margrete_rpc.chart.notes import Extap, ExtapDirection

up = Extap(t=(0, 0), x=4, w=4, dir=ExtapDirection.UP)
spin = Extap(t=(0, 1), x=4, w=4, dir="rotate_left")

dir accepts ExtapDirection, or a direction string: "up", "down", "center", "left", "right", "rotate_left", "rotate_right", "in_out" and "out_in".

Damage

from margrete_rpc.chart.notes import Damage

note = Damage(t=(0, 0), x=4, w=4)

Long Notes

Long notes have a start point and one or more joints.

To mutate the current long note directly, use add_step() and add_ctrl() to add joints:

slide = Slide(t=(0, 0), x=0, w=4)
slide.add_ctrl(t=(0, 2), x=8, w=4)
slide.add_step(t=(1, 0), x=4, w=4)

with_step() and with_ctrl() return a deep copy of the current long note, which is useful when you want to keep the original note unchanged:

from margrete_rpc.chart.notes import Slide

slide = (
    Slide(t=(0, 0), x=0, w=4)
    .with_ctrl(t=(0, 2), x=8, w=4)
    .with_step(t=(1, 0), x=4, w=4)
)

Joints must be added in increasing time order. A long note must have at least one joint before it is sent to Margrete.

Hold

Hold starts at the start point and ends at a Step joint.

from margrete_rpc.chart.notes import Hold

hold = Hold(t=(0, 0), x=4, w=4).with_step(t=(1, 0), x=4, w=4)

Slide

Slide has multiple Step and Control joints.

from margrete_rpc.chart.notes import Slide

slide = (
    Slide(t=(0, 0), x=0, w=4)
    .with_ctrl(t=(0, 2), x=8, w=4)
    .with_step(t=(1, 0), x=4, w=4)
)

When the note is sent to Margrete, the final joint is automatically converted to Step.

AirCrush

AirCrush has these additional fields:

FieldMeaning
hHeight.
gapStep interval. See Time & Musical Position for details.
intervalThe Step interval as a division. For example, gap=(1, 8) means an eighth note. See Time & Musical Position for details.
colorLine color, as ColorValue or a color string.

color accepts these string values: "default", "red", "orange", "yellow", "green", "sky", "blue", "violet", "pink", "white", "black", "grass", "sky_blue", "cobalt_blue", "purple" and "none".

gap also has special values:

ConstantValueEffect
AIRCRUSH_GAP_TRACELIKE0AirTrace (line only).
AIRCRUSH_GAP_HEADONLY0x7FFFFFFFHead Step only.
from margrete_rpc.chart.notes import AirCrush

crush = (
    AirCrush(t=(0, 0), x=4, w=4, h=80, gap=(1, 8), color="blue")
    .with_ctrl(t=(0, 2), x=6, w=4, h=100)
    .with_ctrl(t=(1, 0), x=8, w=4, h=80)
)
AirCrush interval

Air Notes

Air notes must be attached to ground notes.

You can assign .air directly:

from margrete_rpc.chart.notes import Air, AirDirection, Tap

tap = Tap(t=(0, 0), x=4, w=4)
air = Air(AirDirection.UP, t=(0, 0), x=4, w=4)

tap.air = air

You can also use add_air():

tap.add_air(air)

with_air() returns a deep copy of the current ground note, which is useful when you want to keep the original note unchanged:

tap_with_air = tap.with_air(Air("up", t=(0, 0), x=4, w=4))  # original Tap unchanged

The Air note's position must match the note it is attached to:

  • For a ground note, it must match the note's t, x, and w.
  • For a long note, it must match the final joint's t, x, and w.

Standalone Air

Air has an additional dir field for its direction. It also has an inverted field; set it to True to invert its color.

from margrete_rpc.chart.notes import Air, AirDirection, Tap
air = Air(AirDirection.UP, t=(0, 0), x=4, w=4)
air = Air("up", t=(0, 0), x=4, w=4)

dir accepts AirDirection, or a direction string: "up", "down", "up_left", "up_right", "down_left" and "down_right".

AirHold

AirHold works like Hold, but adds an h field: It also has an inverted field; set it to True to invert its color.

from margrete_rpc.chart.notes import AirHold, Hold

hold = Hold(t=(0, 0), x=4, w=4).with_step(t=(1, 0), x=6, w=4)

hold.add_air(
    AirHold(t=(1, 0), x=6, w=4, h=80)
    .with_step(t=(1, 2), x=6, w=4, h=120)
)

AirSlide

AirSlide works like Slide, but adds an h field: It also has an inverted field; set it to True to invert its color.

from margrete_rpc.chart.notes import AirSlide, Slide

slide = Slide(t=(0, 0), x=0, w=4).with_step(t=(1, 0), x=8, w=4)

slide.add_air(
    AirSlide(t=(1, 0), x=8, w=4, h=80)
    .with_ctrl(t=(1, 2), x=10, w=4, h=120)
    .with_step(t=(2, 0), x=8, w=4, h=80)
)

Validating Notes

When open_edit() exits normally, Python validates all chart notes to make sure they follow charting rules. If you want to catch invalid notes earlier, call note.validate() manually.

note.validate()  # raises ValueError if invalid

Common validation failures include:

  • zero or negative note width,
  • long-note joints that are not in increasing time order,
  • missing joints on long notes,
  • Air notes whose t/x/w do not match the attached note.

On this page