Skip to main content
RPE (Re:PhiEdit) is a popular community chart format created for the Re:PhiEdit charting tool. It features rich easing support and an event layer system.

File Structure

{
  "META": {
    "RPEVersion": 120,
    "offset": 0,
    "name": "Song Name",
    "song": "audio.mp3",
    "background": "bg.png",
    "composer": "Artist",
    "charter": "Charter",
    "level": "SP Lv.?",
    "id": "unique-id"
  },
  "BPMList": [
    {
      "bpm": 120.0,
      "startTime": [0, 0, 1]
    }
  ],
  "judgeLineList": [
    // Line objects
  ]
}

Field Reference

RpeChart Root

META
object
required
Chart metadata containing song information, authorship, and file references.
BPMList
array
required
Global BPM change points (unlike Official format’s per-line BPM).
judgeLineList
array
required
Array of judgment lines with event layers.

META Object

RPEVersion
integer
required
RPE format version. Common values: 100, 120.
offset
integer
required
Audio offset in milliseconds (stored as integer).
name
string
Song display name.
song
string
Audio file path.
background
string
Background image path.
composer
string
Music composer/artist.
charter
string
Chart creator.
level
string
Difficulty level (free-form text).
id
string
Unique chart identifier.

BPM Point

{
  "bpm": 140.0,
  "startTime": [8, 0, 1]
}
bpm
number
required
Tempo in beats per minute.
startTime
array
required
Beat position as [bar, numerator, denominator].

Judge Line

{
  "eventLayers": [
    // Event layer objects
  ],
  "notes": [
    // Note objects
  ]
}
eventLayers
array
required
Array of event layers. Each layer contains move, rotate, alpha, and speed events.
During import, all event layers are flattened into a single layer. Overlapping events from different layers may produce unexpected results.
notes
array
required
Notes attached to this line.

Event Layer

{
  "moveXEvents": [],
  "moveYEvents": [],
  "rotateEvents": [],
  "alphaEvents": [],
  "speedEvents": []
}
moveXEvents
array
Horizontal position events.
moveYEvents
array
Vertical position events.
rotateEvents
array
Rotation events.
alphaEvents
array
Opacity events (0-255).
speedEvents
array
Speed events.

Common Event

Used for move, rotate, and alpha events.
{
  "startTime": [0, 0, 1],
  "endTime": [4, 0, 1],
  "start": 0.0,
  "end": 100.0,
  "easingType": 2,
  "bezier": 0,
  "bezierPoints": [0.0, 0.0, 0.0, 0.0]
}
startTime
array
required
Event start beat [bar, numerator, denominator].
endTime
array
required
Event end beat.
start
number|integer
required
Starting value. Type depends on event:
  • Position: number (pixels)
  • Rotation: number (degrees)
  • Alpha: integer (0-255)
end
number|integer
required
Ending value.
easingType
integer
required
Easing function ID (see Easing Table).
bezier
integer
required
Whether to use custom bezier curve:
  • 0 - Use standard easing
  • 1 - Use bezier curve from bezierPoints
bezierPoints
array
required
Bezier control points [x1, y1, x2, y2] for custom easing.

Speed Event

{
  "startTime": [0, 0, 1],
  "endTime": [4, 0, 1],
  "start": 1.0,
  "end": 1.0
}
Speed events always use linear easing regardless of bezier settings.

Note

{
  "type": 1,
  "startTime": [2, 0, 1],
  "endTime": [2, 0, 1],
  "positionX": 0.0,
  "above": 1,
  "speed": 1.0,
  "size": 1.0,
  "visibleTime": 999999.0
}
type
integer
required
Note type:
  • 1 - Tap
  • 2 - Hold
  • 3 - Flick
  • 4 - Drag
RPE numbering differs from Official format! (2 and 3 are swapped)
startTime
array
required
Note start beat.
endTime
array
required
Note end beat. Same as startTime for non-hold notes.
positionX
number
required
Horizontal position in pixels (not normalized like Official format).
above
integer
required
Position relative to line:
  • 1 - Above
  • 2 - Below
speed
number
required
Note approach speed multiplier.
size
number
default:"1.0"
Note size multiplier. Ignored during import (not supported in Phichain).
visibleTime
number
default:"999999.0"
How early the note becomes visible. Ignored during import.

Easing Mapping

RPE uses integer IDs for easing functions:
IDEasing FunctionIDEasing Function
0Linear15EaseInQuint
1Linear16EaseOutExpo
2EaseOutSine17EaseInExpo
3EaseInSine18EaseOutCirc
4EaseOutQuad19EaseInCirc
5EaseInQuad20EaseOutBack
6EaseInOutSine21EaseInBack
7EaseInOutQuad22EaseInOutCirc
8EaseOutCubic23EaseInOutBack
9EaseInCubic24EaseOutElastic
10EaseOutQuart25EaseInElastic
11EaseInQuart26EaseOutBounce
12EaseInOutCubic27EaseInBounce
13EaseInOutQuart28EaseInOutBounce
14EaseOutQuint29EaseInOutElastic
Source: phichain-chart/src/format/rpe.rs:130-161

Complete Example

{
  "META": {
    "RPEVersion": 120,
    "offset": -50,
    "name": "Example Chart",
    "song": "music.mp3",
    "background": "bg.jpg",
    "composer": "Composer Name",
    "charter": "Charter Name",
    "level": "SP Lv.15",
    "id": "example-001"
  },
  "BPMList": [
    {
      "bpm": 140.0,
      "startTime": [0, 0, 1]
    },
    {
      "bpm": 160.0,
      "startTime": [16, 0, 1]
    }
  ],
  "judgeLineList": [
    {
      "eventLayers": [
        {
          "moveXEvents": [
            {
              "startTime": [0, 0, 1],
              "endTime": [8, 0, 1],
              "start": 0.0,
              "end": 200.0,
              "easingType": 8,
              "bezier": 0,
              "bezierPoints": [0.0, 0.0, 0.0, 0.0]
            }
          ],
          "moveYEvents": [
            {
              "startTime": [0, 0, 1],
              "endTime": [8, 0, 1],
              "start": 0.0,
              "end": 0.0,
              "easingType": 1,
              "bezier": 0,
              "bezierPoints": [0.0, 0.0, 0.0, 0.0]
            }
          ],
          "rotateEvents": [
            {
              "startTime": [0, 0, 1],
              "endTime": [8, 0, 1],
              "start": 0.0,
              "end": -360.0,
              "easingType": 7,
              "bezier": 0,
              "bezierPoints": [0.0, 0.0, 0.0, 0.0]
            }
          ],
          "alphaEvents": [
            {
              "startTime": [0, 0, 1],
              "endTime": [100, 0, 1],
              "start": 255,
              "end": 255,
              "easingType": 1,
              "bezier": 0,
              "bezierPoints": [0.0, 0.0, 0.0, 0.0]
            }
          ],
          "speedEvents": [
            {
              "startTime": [0, 0, 1],
              "endTime": [100, 0, 1],
              "start": 1.0,
              "end": 1.0
            }
          ]
        }
      ],
      "notes": [
        {
          "type": 1,
          "startTime": [0, 0, 1],
          "endTime": [0, 0, 1],
          "positionX": 0.0,
          "above": 1,
          "speed": 1.0,
          "size": 1.0,
          "visibleTime": 999999.0
        },
        {
          "type": 2,
          "startTime": [2, 0, 1],
          "endTime": [4, 0, 1],
          "positionX": 100.0,
          "above": 1,
          "speed": 1.0,
          "size": 1.0,
          "visibleTime": 999999.0
        }
      ]
    }
  ]
}

Key Differences from Official

Global BPM List

BPM changes apply globally, not per-line.

Pixel Coordinates

Position values are in pixels, not normalized 0-1.

Rich Easing

30 easing functions plus custom bezier curves.

Rotation Sign

Rotation values are negated during conversion (RPE rotates opposite direction).

Conversion Notes

Event Layer Flattening

RPE supports multiple event layers per line, but Phichain flattens them:
// All layers combined
let x_events = line.event_layers
    .iter()
    .flat_map(|layer| layer.move_xevents.clone())
    .collect();
If layers have overlapping events, the behavior is undefined.

Rotation Direction

RPE rotation is negated during conversion:
// Import: RPE → Phichain
start: -event.start,
end: -event.end,

// Export: Phichain → RPE  
start: -rpe_event.start,
end: -rpe_event.end,

Note Timing

Hold duration is computed from beat difference:
let start_beat = note.start_time.into();
let end_beat = note.end_time.into();
let hold_beat = end_beat - start_beat;

Source Code

RPE format implementation:
  • phichain-chart/src/format/rpe.rs

Official Format

Compare with official Phigros format

Easing Functions

Learn about easing functions