> ## Documentation Index
> Fetch the complete documentation index at: https://chart-spec.enchor.us/llms.txt
> Use this file to discover all available pages before exploring further.

# Structure

> The layout of a .mid file: its header, tracks and track names, resolution, tempo map and text.

A `.mid` file is a standard MIDI file. It starts with a header, then holds a track for the tempo map and a track for each other part of the chart: the song's events, each instrument and each vocal part.

```text theme={null}
Header  format 1, 3 tracks, resolution 480

TEMPO TRACK
  0      Track name      TEMPO TRACK
  0      Time signature  4/4
  0      Tempo           500000 (120 BPM)
  0      End of track

EVENTS
  0      Track name      EVENTS
  0      Text            section Intro
  1920   Text            section Verse 1
  4320   Text            end
  4320   End of track

PART GUITAR
  0      Track name      PART GUITAR
  1920   Note on         96   Expert green
  2400   Note off        96
  2400   Note on         97   Expert red
  2880   Note off        97
  2880   End of track
```

These pages list each track under its name, with one event per line after its tick. The file stores each event's delta time instead: the number of ticks since the track's previous event.

## The file

* **Required:** MIDI format 1, in which every track has its own timeline.
* The file starts with a header chunk, `MThd`. It holds the format, the number of tracks and the resolution.
* **Required:** a header body 6 bytes long.
* **Required:** after the header, only `MTrk` chunks, one for each track the header counts.

## Resolution

The header's division is the chart's resolution: the number of ticks in a quarter note. **Required:** a number of ticks, from 1 to 32767.

Unlike a `.chart` file's [Resolution](/chart/song#resolution), it is always written, and it can't be more than 32767.

## Tracks

| Track | Holds | |
| - | - | - |
| The first track | Tempos and time signatures. See [The tempo track](#the-tempo-track) | **Required**, first |
| `EVENTS` | Practice sections and other events for the whole song. See [EVENTS track](/mid/events) | |
| An instrument, such as `PART GUITAR` | The notes, modifiers and phrases of every difficulty. See [Instrument tracks](/mid/instrument-tracks) | |
| A vocal part, such as `PART VOCALS` | Vocal notes, lyrics and phrases. See [Vocals and harmonies](/mid/vocals) | |

* The other tracks follow the tempo track, in any order, except that harmonies come in order. See [Vocals and harmonies](/mid/vocals#vocal-tracks).
* **Required:** one track at most for `EVENTS`, for each instrument and for each vocal part.

A `.chart` file has a section for each instrument and difficulty. A `.mid` file has one track for each instrument, which holds all of its difficulties.

### Track names

Every track starts with its name, a track name event, `FF 03`:

* **Required:** exactly one name in each track, as its first event, at tick 0.
* **Required:** the name exactly as these pages list it, in capitals, such as `PART GUITAR`.

The first track's name has no meaning. **Required:** a name other than `EVENTS` and the names of instrument and vocal tracks. **Recommended:** `TEMPO TRACK`.

## MIDI events

A track holds three kinds of event:

* **Channel events,** such as note-ons and note-offs. A note's channel has no meaning, except that a note-off ends a note on its own channel. See [Note pairing](/mid/note-pairing).
* **Meta events,** such as track names, text, tempos and time signatures.
* **SysEx events,** which some modifiers use. See [Note modifiers](/mid/modifiers#the-phase-shift-sysex-event).

Rules for every track:

* **Required:** each delta time at most 4 bytes long.
* **Required:** an end of track event, `FF 2F`, as the track's last event.

Delta times can't be negative, so a track's events are always in tick order.

**Edge case: running status.** A channel event may leave out its status byte when it's the same as the previous channel event's. Scanners keep that status across meta and SysEx events, though the MIDI standard ends it there. An exporter should write the status byte of the first channel event after a meta or SysEx event.

### Events at one tick

A scanner reads a track's events at one tick in the order the file holds them. The order matters for:

* a note-off and a note-on of one pitch. See [Note pairing](/mid/note-pairing#events-at-one-tick);
* text events that change the notes after them, such as `ENHANCED_OPENS`. See [Note modifiers](/mid/modifiers#open-notes).

**Recommended:** at one tick, the time signature before the tempo, as in a `.chart` file. scan-chart's export writes them in this order.

## The tempo track

The first track holds the chart's tempos and time signatures. It's the `.mid` form of a `.chart` file's [\[SyncTrack\]](/chart/sync-track). A scanner reads tempos and time signatures only from this track. **Recommended:** only its name, tempos and time signatures.

### Tempos

A tempo event, `FF 51`, sets the tempo from its tick to the next tempo. Its 3 bytes hold the length of a quarter note, in microseconds:

| Value | Tempo |
| - | - |
| `500000` | 120 BPM |
| `600000` | 100 BPM |
| `400000` | 150 BPM |

* The tempo in BPM is 60,000,000 divided by the value.
* **Required:** a whole number from 1 to 16,777,215.
* **Required:** one tempo at most at a tick.

A `.chart` tempo is in thousandths of a beat per minute instead. See [Tempo markers](/chart/sync-track#tempo-markers). Neither format can hold every tempo of the other exactly.

### Time signatures

A time signature event, `FF 58`, sets the meter from its tick to the next time signature. Its first two bytes are the numerator and the exponent: the denominator is 2 to the power of the exponent.

| Numerator and exponent | Time signature |
| - | - |
| `4 2` | 4/4 |
| `3 3` | 3/8 |
| `6 3` | 6/8 |
| `7 4` | 7/16 |

* **Required:** a numerator from 1 to 255, and an exponent from 0 to 7, for the denominators 1 to 128.
* **Required:** one time signature at most at a tick.
* The event's last two bytes, MIDI clocks per metronome click and 32nd notes per quarter note, have no effect.

Unlike in a `.chart` file, the exponent is always written. Time signatures only change the lines that appear during gameplay, as in a `.chart` file. See [Time signatures](/chart/sync-track#time-signatures).

### The start of the chart

**Recommended:** a tempo and a time signature at tick 0.

**Edge case:** until its first tempo, a chart plays at 120 BPM, and until its first time signature, it's in 4/4.

## Text

Text events hold practice sections, lyrics and the other events these pages list.

* **Required:** in `EVENTS` and instrument tracks, every text is a text event, `FF 01`. Vocal tracks hold lyrics. See [Lyrics](/mid/vocals#lyrics).
* **Required:** text is UTF-8. A `.mid` file has no byte order mark.

In `EVENTS` and instrument tracks, square brackets around the whole text are optional, as in a `.chart` file: `[section Intro]` means the same as `section Intro`. **Recommended:** no brackets. A range shift is the exception: it's written with them. See [Range shifts](/mid/instrument-tracks#range-shifts). In a vocal track, text that starts with `[` is never a lyric. See [Lyrics](/mid/vocals#lyrics).

## Ignored

* **Tempos and time signatures in any track but the first.**
* **Notes and text in the first track.**
* **`BEAT` and `VENUE` tracks,** from Rock Band charts. Clone Hero ignores them. YARG draws its beat lines from `BEAT` notes 12, 13 and 14, and reads lighting and camera cuts from `VENUE`. An exporter should keep them when rewriting a file.
* **A track with any other name.** [Instrument tracks](/mid/instrument-tracks#ignored) lists the ones from other games.

## Invalid forms

scan-chart saves an edited `.mid` song by keeping every event you didn't edit as the file wrote it, apart from extra track names. When it exports a `.mid` file anew, as converting does, it writes every track in the standard form. Where the two differ, the forms below say so.

<Accordion title="A format other than 1">
  A scanner refuses the file, as scan-chart does. Clone Hero and YARG don't check the format. A format 0 file holds a single track, which Clone Hero reads as the tempo track, so it finds no instrument and doesn't list the song.
</Accordion>

<Accordion title="A header that isn't 6 bytes long">
  A scanner reads the first 6 bytes, as Clone Hero and scan-chart do. YARG's song scan refuses the file. scan-chart's export writes a 6-byte header.
</Accordion>

<Accordion title="A track count that doesn't match the tracks">
  A scanner reads every track, whatever the header counts, as Clone Hero and YARG do. scan-chart reports the wrong count. Saving with scan-chart keeps the header as it is, and its export writes the right count.
</Accordion>

<Accordion title="A chunk of another kind among the tracks">
  A scanner refuses the file, as scan-chart does, unless the chunk comes after the last track the header counts. Clone Hero stops reading at the chunk, and keeps the tracks before it. YARG's song scan refuses the file.
</Accordion>

<Accordion title="A delta time longer than 4 bytes">
  A scanner refuses the file, as YARG's song scan and scan-chart do. Clone Hero misreads it.
</Accordion>

<Accordion title="Running status before a track's first channel event">
  Every scanner refuses the file.
</Accordion>

<Accordion title="A system common or real-time byte inside a track">
  A scanner refuses a file whose track holds a status byte from F1 to F6, or from F8 to FE, as Clone Hero and scan-chart do. YARG's song scan skips it.
</Accordion>

<Accordion title="No end of track, or events after it">
  A scanner reads a track without an end of track to the end of its chunk, as Clone Hero and scan-chart do. YARG's song scan can fail on it, and then doesn't list the song. scan-chart's export adds an end of track.

  A scanner ignores the events after the end of track, as Clone Hero and YARG do. So it also ignores a note whose note-off comes after it. Saving with scan-chart keeps them as they are. scan-chart reports them, and `fixIssues` can move the end of track after them, which changes the TrackHash.
</Accordion>

<Accordion title="A damaged file">
  A scanner reads a file cut short between two events up to the cut, as Clone Hero and scan-chart do. It refuses a file cut inside an event, as Clone Hero does, and a tempo or time signature of the wrong length, as scan-chart does. scan-chart reads every complete event before a cut inside an event. Clone Hero reads the fixed fields of a tempo or time signature of the wrong length.
</Accordion>

<Accordion title="A resolution of 0, or in SMPTE frames">
  Clone Hero and scan-chart refuse the file. YARG's song scan refuses a resolution of 0, and lists a file in SMPTE frames, which then fails to load.
</Accordion>

<Accordion title="More than one track name at tick 0, or an event before the name">
  A scanner uses the last name at tick 0, wherever it is among the events at tick 0, as Clone Hero and scan-chart do. YARG uses the first name it recognizes. YARG skips the first event of the EVENTS, BEAT, VENUE and vocal tracks, taking it to be the name. It reads every tempo and time signature late when the tempo track's first event isn't at tick 0. scan-chart reports `multipleMidiTrackNames` for a track with more than one name at tick 0, and saving with scan-chart removes every name at tick 0 but the last.
</Accordion>

<Accordion title="A name in another letter case">
  A scanner reads it in any letter case, as Clone Hero and scan-chart do, so `part guitar` is lead guitar. YARG ignores the track. scan-chart's export writes the name in capitals.
</Accordion>

<Accordion title="A name with spaces at its ends, or no name at tick 0">
  Every scanner ignores the track. scan-chart keeps it, and writes it back as it is.
</Accordion>

<Accordion title="A first track named EVENTS, or named as an instrument">
  A scanner reads a first track named `EVENTS` as the EVENTS track, as well as the tempo track, and reads no notes from the first track, as Clone Hero and scan-chart do. YARG doesn't read it as the EVENTS track. YARG's gameplay reads no notes from it either, though YARG's song scan lists an instrument named there. scan-chart's export writes a separate tempo track.
</Accordion>

<Accordion title="A tempo of 0, or a numerator of 0">
  Clone Hero and YARG fail to load the chart. Clone Hero finds it only when the song is played, because its song scan doesn't read the tempo track. scan-chart refuses the file.
</Accordion>

<Accordion title="Two tempos, or two time signatures, at one tick">
  Clone Hero and YARG use the later one. scan-chart times the notes with the later one, but keeps both, and its export writes both.
</Accordion>

<Accordion title="An exponent of 8 or more">
  A scanner refuses the file. Clone Hero and YARG store the denominator in one byte, which can't hold 256 or more, and from their code neither loads the chart. scan-chart reads 2 to the power of the exponent, which is exact up to an exponent of 30.
</Accordion>

<Accordion title="Text of another type in EVENTS or an instrument track">
  A scanner reads the text a hash depends on, the coda, mix events, `ENHANCED_OPENS` and `ENABLE_CHART_DYNAMICS`, only from a text event, `FF 01`, as Clone Hero and scan-chart do. Other text of another type Clone Hero ignores. YARG reads the types `FF 04` to `FF 09`, and scan-chart reads `FF 05`, `FF 06` and `FF 07`, so a section written as a marker event, `FF 06`, is a section there but not in Clone Hero. See [EVENTS track](/mid/events#invalid-forms). scan-chart's export writes such text as `FF 01`.
</Accordion>

<Accordion title="Text that isn't UTF-8">
  Clone Hero reads each byte that isn't valid UTF-8 as the replacement character, and its song scan reports lyrics that hold one. YARG reads the whole file again as ISO-8859-1 when any byte isn't valid UTF-8, which changes UTF-8 text elsewhere in the file. scan-chart decides for each event whether it's UTF-8 or ISO-8859-1. scan-chart's export writes UTF-8.
</Accordion>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.