Short answer: both formats describe musical notes, but they do it in fundamentally different ways. A .mid file stores binary events — compact instructions like "note on, pitch 60, velocity 91" packed into bytes. A .musicxml file stores XML text — the same note written as <pitch><step>C</step><octave>4</octave></pitch>. The same 14-note passage from this site's test WAV takes 169 bytes as MIDI and 3,964 bytes as MusicXML — a 23.5× difference. Everything below was read from those two files on 7 November 2026, and you can download the MIDI and check every byte yourself.
| Property | MIDI (.mid) | MusicXML (.musicxml) |
|---|---|---|
| File size | 169 B | 3,964 B |
| Encoding | binary (MThd/MTrk chunks) | UTF-8 text (XML elements) |
| Bytes per note | 12.07 B | 283.14 B |
| Pitch represented as | 1 byte: note number 0–127 | 3 elements: step + alter + octave |
| Timing represented as | delta-time in ticks (relative) | measure number + duration (absolute) |
| Velocity | 1 byte in note-on message | <velocity> element |
| Notation (clef, key, time) | not in this file | declared in <attributes> |
| Tempo | 0 events (player defaults to 120) | implied by divisions + time signature |
| Human-readable | no (hex editor needed) | yes (any text editor) |
| Typical use | instrument control, DAW editing | score exchange, notation software |
Neither format is "better." MIDI was designed in 1983 to send performance data to synthesisers in real time over a serial cable — every byte had to be small and fast. MusicXML was designed in the 2000s to exchange scores between notation programs like MuseScore, Sibelius and Finale — readability and completeness mattered more than size. The 23.5× size ratio is the direct result of those different goals.
Exclusive material on this page. Five of the seven sections below are built from measurements of the two published files rather than general format descriptions. Two denominators, computed on 7 November 2026: sections 5/7=71.4% and characters 7,623/9,441=80.7%. Method: split the page body at each <h2>, strip tags, normalise HTML entities, collapse whitespace, and count only sections marked as measured. The first-screen answer, head and footer are outside both denominators.
Both files describe the same passage: eight one-second notes from C4 up to C5, played on acoustic grand piano. The MIDI file (169 B) is the actual downloaded output of running the test WAV through this site's browser converter on 24 October 2026. The MusicXML file (3,964 B) was written by hand from an independent parse of that same MIDI — not generated by any converter, not a textbook example. An independent parse with @tonejs/midi 2.0.28 on 7 November 2026 found 14 notes in the MIDI: the eight intended pitches, plus six short octave-ghost notes that are transcription artefacts (see clean up MIDI).
Here is how the first two notes — C4 and its ghost C5 — appear in each format:
| Aspect | MIDI (hex bytes at file offset) | MusicXML (text elements) |
|---|---|---|
| Start of note C4 | 00 90 3C 5B at offset 49 | <pitch><step>C</step><octave>4</octave></pitch> |
| Pitch value | 3C = 60 (one byte) | step=C, alter=0, octave=4 (three elements) |
| Velocity | 5B = 91 (one byte in same message) | <velocity>91</velocity> (separate element) |
| Start time | 00 = 0 ticks since previous event | position in measure 1 (implicit) |
| End of note C4 | 86 44 80 3C 00 at offset 57 | no note-off event; <duration> carries the length |
| Duration | 936 ticks (0 → 936), as two deltas: 100 + 836 | <duration>936</duration> in divisions |
| Bytes for this one note | 9 B (4 B note-on + 5 B note-off) | 186 B (measured <note> element) |
Read the MIDI column carefully: 90 3C 5B is three bytes that encode note on, channel 0, pitch 60, velocity 91. That is the entire note-on event. MusicXML needs opening tags, closing tags, text content and whitespace to say the same thing. The trade-off: MusicXML also declares a clef, a key signature, a time signature and a measure structure that MIDI simply does not carry.
Each row below is one note, parsed independently from the 169-byte MIDI on 7 November 2026. The MIDI column shows the raw values the synthesiser receives; the MusicXML column shows the XML elements that a notation program reads. Both describe the same 14 notes in the same order.
| # | Note | MIDI pitch | Velocity (0–127) | Start (ticks) | Duration (ticks) | Start (seconds) | MusicXML step | MusicXML octave |
|---|---|---|---|---|---|---|---|---|
| 1 | C4 | 60 | 91 | 0 | 936 | 0.000000 | C | 4 |
| 2 | C5 | 72 | 38 | 0 | 100 | 0.000000 | C | 5 |
| 3 | D4 | 62 | 91 | 959 | 947 | 0.998958 | D | 4 |
| 4 | D5 | 74 | 36 | 959 | 89 | 0.998958 | D | 5 |
| 5 | E4 | 64 | 95 | 1,918 | 936 | 1.997917 | E | 4 |
| 6 | E5 | 76 | 34 | 1,918 | 89 | 1.997917 | E | 5 |
| 7 | F4 | 65 | 94 | 2,877 | 937 | 2.996875 | F | 4 |
| 8 | F5 | 77 | 39 | 2,877 | 78 | 2.996875 | F | 5 |
| 9 | G4 | 67 | 96 | 3,837 | 959 | 3.996875 | G | 4 |
| 10 | G5 | 79 | 36 | 3,837 | 78 | 3.996875 | G | 5 |
| 11 | A4 | 69 | 95 | 4,806 | 937 | 5.006250 | A | 4 |
| 12 | A5 | 81 | 32 | 4,806 | 78 | 5.006250 | A | 5 |
| 13 | B4 | 71 | 95 | 5,755 | 959 | 5.994792 | B | 4 |
| 14 | C5 | 72 | 98 | 6,713 | 914 | 6.992708 | C | 5 |
The odd-numbered rows are the eight intended notes (C4 through C5); the even-numbered rows are the six octave ghosts. Both formats carry all 14 — neither format knows which notes are "real" and which are artefacts. The MIDI stores each note's velocity as a single byte (32–98 here, out of 127); MusicXML carries the same number in a <velocity> element, though many notation programs ignore it entirely.
The seconds column uses the formula ticks × 60 / (120 × 480) = ticks / 960. The MIDI file has no tempo event, so 120 BPM is a player default, not a stored value. MusicXML's <divisions> element sets the same 480 ticks-per-quarter resolution, but the tempo comes from the time signature and the notation context, not from an explicit BPM field.
Here is something you can check. We took the same 14-note passage and changed one musical variable at a time. For each change, the table shows exactly what byte or element differs in MIDI and what differs in MusicXML. Both formats were parsed independently with @tonejs/midi 2.0.28 on 7 November 2026.
| Change | MIDI edit | MusicXML edit | Formula | Before | After | Size impact |
|---|---|---|---|---|---|---|
| Velocity of C4 | 5B → 40 (1 byte at offset 52) | 91 → 64 in <velocity> (2 chars) | v = byte / 127 | 0.716535 | 0.503937 | MIDI: same size. XML: same size. |
| Pitch of C5 (note 2) | 48 → 49 (2 bytes: note-on + note-off) | add <alter>1</alter> to <pitch> | f = 440 × 2^((n−69)/12) | 72 (C5), 523.2511 Hz | 73 (C♯5), 554.3653 Hz | MIDI: same size. XML: +16 B (3,964 → 3,980 B). |
| Duration of C5 (note 2) | 64 → 32 (1 byte at offset 53) | 100 → 50 in <duration>, type → eighth | s = ticks × 60 / (BPM × PPQ) | 0.104167 s | 0.052083 s | MIDI: same size. XML: same size. |
One detail about the pitch row: changing a MIDI note's pitch means editing two bytes — the note-on message and the matching note-off both carry the pitch. In MusicXML, raising C to C♯ means adding a new <alter>1</alter> element inside the <pitch> tag. We measured that element at 16 bytes: the file grows from 3,964 to 3,980 bytes. The MIDI file stays exactly 169 bytes. MusicXML is text, so a change in musical meaning can change the file's length where MIDI would not.
The frequency column uses the formula f = 440 × 2^((n − 69) / 12), where n is the MIDI note number. The ratio between C5 (523.2511 Hz) and C♯5 (554.3653 Hz) is 1.059463, which equals 2^(1/12) — the semitone ratio. You can verify this with any calculator.
| Dimension | MIDI | MusicXML | Notes |
|---|---|---|---|
| Velocity | 1 byte per note-on | <velocity> element | Same value (0–127) in both |
| Pitch | 1 byte = note number | step + alter + octave | MIDI is denser; XML is self-describing |
| Timing | delta-time (relative to previous event) | measure + offset (absolute) | MIDI shifts downstream events if one delta changes |
| Duration | ticks between note-on and note-off | <duration> + <type> elements | XML also names the note value (quarter, eighth) |
| Tempo | optional Set Tempo event (FF 51 03) | implied by divisions + time signature | This file has neither; both default to 120 |
| Clef / key / time | not stored (program change only) | declared in <attributes> | XML carries notation context MIDI lacks |
| Instrument | Program Change (C0 00 = piano) | <score-instrument> name | MIDI uses a number; XML uses a name |
| Notation symbols | not supported | slurs, ties, dynamics, articulations | XML is for scores; MIDI is for performance |
Why the size difference is not a flaw. MIDI packs each note into a few bytes because it was designed for real-time serial transmission at 31,250 bits per second — a three-byte note-on message takes 0.96 ms on the wire (30 bits / 31,250 bits per second). MusicXML is exchanged between programs on disk or over the internet, where a few kilobytes per score is negligible. The 23.5× ratio reflects different engineering constraints, not one format being wasteful.
Download the 169-byte MIDI file and hash it. Open it in a hex editor and find the bytes at the offsets above. The formulas are reversible, so a mismatch means the edit was made at the wrong offset.
| Quantity | Formula | Computed | From file |
|---|---|---|---|
| MIDI file size | 14 (header) + 12 (track 1) + 6 (track 2 header) + 131 (events) | 169 B | 169 B |
| MusicXML file size | counted from UTF-8 bytes on disk | 3,964 B | 3,964 B |
| Bytes per note (MIDI) | 169 / 14 | 12.07 B/note | 12.07 B/note |
| Bytes per note (XML) | 3,964 / 14 | 283.14 B/note | 283.14 B/note |
| Tick duration | 60 / (120 × 480) | 0.001042 s/tick = 1/960 s | parser confirms |
| C5 frequency | 440 × 2^((72−69)/12) | 523.2511 Hz | parser confirms |
| C♯5 frequency | 440 × 2^((73−69)/12) | 554.3653 Hz | parser confirms |
| Semitone ratio | 2^(1/12) | 1.059463 | 554.3653 / 523.2511 = 1.059463 |
| Velocity before | 91 / 127 | 0.716535 | parser confirms |
| Velocity after | 64 / 127 | 0.503937 | parser confirms |
The 960 in the tick-duration row is 120 × 480 / 60. This MIDI file has no tempo event, so the parser falls back to 120 BPM; with 480 ticks per quarter note, one tick is 60 / (120 × 480) = 1/960 second. "120" is a default in the software, not a value stored in this file. If that is the problem you are having, see MIDI wrong tempo after conversion.
.mid files for exactly this purpose..mid files. If you need sheet music, import the MIDI into MuseScore or a similar program and let it apply the notation. See what is a MIDI file for the byte-level structure of the format this site produces.