MIDI to ABC · midi2abc 3.64 · every number below was run here

MIDI to ABC: two commands, and six header lines you have to check.

ABC notation is a text format: a block of header fields, then the notes as letters. Converting a MIDI file to it takes two commands, and the second one is where most files go wrong, because the first one guesses and writes the guess into the header as if it were fact.

midi2abc song.mid -o song.abc # open song.abc and fix T:, plus M: and Q: if they are guesses abc2midi song.abc -o song-fixed.mid

The short answer

Three lines are wrong by default and you have to fix them by hand. T: is always the filename, never the title inside your MIDI. M: is 4/4 whenever the file has no time-signature event — and the converter tells you so with a comment line. Q: is 120 whenever the file has no tempo event, and 120 is also a perfectly normal real tempo, so you cannot tell the difference by looking.

The flag you would reach for does not work. -Q 90 does not set the tempo to 90. Five values, in both argument positions, all produced Q:1/4=120. And -m 3/4, which does set the meter, silently changes the tempo line from 120 to 60 as a side effect. Measured below.

So the working method is to edit the text, not the flags. Change T:, M: and Q: in the .abc file, run abc2midi, and read its warnings — they name the bar numbers whose length no longer matches the meter.

The real output

What the converter prints for a MIDI file with no tempo and no meter

The input is a 329-byte file: 34 note events, nine bars, and no FF 51 tempo event, no FF 58 time-signature event and no FF 59 key-signature event — which is what most browser converters, including this site's own, produce. This is midi2abc song.mid -o song.abc, pasted without editing:

X: 1 T: from song.mid %***Missing time signature meta command in MIDI file M: 4/4 L: 1/8 Q:1/4=120 % Last note suggests Mixolydian mode tune K:C % 0 sharps V:1 E2 E2 F2 G2| \ G2 F2 E2 D2| \ C2 C2 D2 E2| \ E3D D4| E2 E2 F2 G2| \ G2 F2 E2 D2| \ C2 C2 D2 E2| \ D3C C4| [GECC,]8|

Eighteen lines. Nine of them are header, including the voice declaration; the other nine are music — eight bars and a closing chord. Two of the header lines are comments — they start with % — and those two comments are the converter admitting which of its values are guesses. Everything after this page's field-by-field walk comes from files this small, because a small file makes every field checkable by eye.

Field by field

What each header line reads, and what it writes when the file is silent

Each field below was tested by changing one thing in the input file and re-running the converter. The tests used five MIDI files: the 329-byte one above; the same waltz with and without a meter event (242 and 257 bytes); a file with two sharps in its key signature; a file of sixteen sixteenth notes; and files at 90 and 60 BPM.

X: The tune number, and it is always 1

X: is the reference number of the tune. One ABC file may hold several tunes, and this is the index that tells them apart. A MIDI file is one performance of one piece, so every run produced X: 1 — across all five test files, with no variation. Leave it alone.

T: The title — and it is your filename, not your title

This is the first field that costs you something. midi2abc writes T: from followed by the input filename. It does not read the title inside the MIDI file.

The test: a 307-byte waltz with a FF 03 track-name event reading Waltz in D, plus a FF 01 text event. The output header still said T: from v-keyd.mid. The title in the file was ignored, and the filename was promoted into the document title.

So T: is the one field you rewrite every single time. It is also the field a reader sees first, and the one that survives into anything that indexes ABC files.

M: The meter, read from the file or invented as 4/4

M: comes from the FF 58 event. When that event is absent, the converter does two things at once: it writes a comment saying the event is missing, and it writes M: 4/4 anyway. The comment does not stop the 4/4 from being used.

InputBytesTime-signature eventHeader it produced
Waltz, no meter242none%***Missing time signature meta command in MIDI file
M: 4/4
Waltz, meter inserted257FF 58 = 3/4M: 3/4, and no comment

The two files hold the same 24 notes. The difference is fifteen bytes of meta event, and it changes where every bar line falls:

242 bytes, M: 4/4 — four notes per line, six lines C,2 C2 E2 D,2| \ D2 ^F2 E,2 E2| \ ^G2 F,2 F2 A2| \ G,2 G2 B2 F,2| 257 bytes, M: 3/4 — three notes per line, eight lines C,2 C2 E2| \ D,2 D2 ^F2| \ E,2 E2 ^G2| \ F,2 F2 A2|

In the first version the bar line lands after the first note of the next bar, so each written bar contains four notes and spans one and a third real bars. In the second, every bar holds exactly the three notes the waltz was written in. Nothing was added or removed; the same notes are simply grouped differently. This is the same experiment as the fifteen bytes on the sheet-music-to-MIDI page, seen through ABC instead of through a staff.

L: The unit, fixed at 1/8 whatever the notes do

L: is the default note length. Every duration in the body is a multiple of it, so a sixteenth note under L: 1/8 is written as half a unit: C/2.

midi2abc writes L: 1/8 and leaves it there. A file of sixteen sixteenth notes still came out as L: 1/8, with the body reading C/2D/2E/2F/2 G/2A/2B/2c/2. That is not an error and not a sign that something was lost — it is one eighth split in half.

There is a flag, -gu, that is documented as guessing the unit from the note durations. On the same file it did not change L: at all. It changed two other things instead:

L:Q:Body
default1/81/4=120C/2D/2E/2F/2 — sixteen sixteenths
with -gu1/81/4=240CD EF GA Bc — sixteen eighths

Total playing time is identical, because doubling every note and doubling the tempo cancels out. What changed is the notation: a passage of sixteenths is now written as eighths at twice the speed. It plays the same and reads wrong, which is the worst kind of wrong, because you only find it when someone tries to perform from it.

Q: The tempo, read from the file — and the flags that do not set it

Q: comes from the FF 51 event, and it tracks that event exactly:

Input tempo eventValueHeader
FF 51 at 90 BPM666,666 µs per quarterQ:1/4=90
FF 51 at 60 BPM1,000,000 µs per quarterQ:1/4=60
no tempo event—Q:1/4=120

That last row is the trap. 120 is the format's default, and 120 is also the most common real tempo, so a file that never had a tempo looks exactly like a file that had 120 written into it. If you care about the tempo, check the source for FF 51 before you trust the line.

Now the flags. midi2abc documents -Q <tempo in quarter-notes per minute>. It does nothing here:

CommandQ: in the output
-Q 60, -Q 90, -Q 120, -Q 180, -Q 2401/4=120 in all five cases, whether the flag went before or after the filename
-Q 60 on a file that really is 90 BPM1/4=90 — the file's own tempo, the flag ignored
-m 4/4, -m 3/4, -m 6/81/4=60 — the meter flag halves the tempo as a side effect
-m 2/41/4=30

So: -Q is dead, and -m quietly rewrites the tempo while setting the meter. Both were checked with the flag before and after the filename, so it is not an argument-order problem. Edit the Q: line in the text instead — that path is verified in the last section.

K: The key, read from the file or defaulted to C

K: comes from the FF 59 key-signature event. The two cases look completely different in the output:

InputKey-signature eventHeader
Waltz in DFF 59 = 2 sharpsK:D % 2 sharps
The 329-byte filenoneK:C % 0 sharps plus % Last note suggests Mixolydian mode tune

The second case has a comment that reads like a diagnosis but is only a comment. K:C is what the notes are written in, so a tune whose last note suggests Mixolydian will be spelled with accidentals all over it — the F natural in =F is there because the header says C major and the note is not in C major. The comment did not change a single note.

Unlike -Q, the key flag works: -k 2 on the same file produced K:D % 2 sharps. If you know the key and the file does not carry it, that is one flag you can use.

The round trip

Converting back writes the guess into the file as fact

Here is why the header matters more than it looks. Run abc2midi on the ABC that midi2abc produced from a file with no meter, and the 4/4 guess becomes a real time-signature event in the new MIDI file:

ABC fed back inNew MIDITime-signature event written
M: 4/4 (the guess)475 bytesff 58 04 04 02 30 — 4/4
M: 3/4 (the true meter)424 bytesff 58 04 03 02 12 — 3/4

The original file had no meter event at all. After one trip through ABC, it has one, and if you did not edit the header, that event is wrong. The guess has been laundered into data. A program downstream has no way to know it was a guess, because it is now the same fifteen bytes a correct meter would be.

Which is why the fix has to happen in the text, before abc2midi runs. Changing M: 4/4 to M: 3/4, Q:1/4=120 to Q:1/4=90 and the T: line, then re-running, produced exactly the bytes it should: ff 58 04 03 02 12 for 3/4, 666,666 µs for 90 BPM, and the new title in FF 03.

It also produced three warnings, and those are the most useful lines in the whole exercise:

Warning in line-char 16-11 : Track 1 Bar 6 has 4 time units while the time signature has 3 Warning in line-char 17-6 : Track 1 Bar 7 has 4 time units while the time signature has 3 Warning in line-char 18-8 : Track 1 Bar 8 has 4 time units while the time signature has 3

M: changes how bar lines are drawn. It does not re-bar the notes. Change the meter and leave the body alone, and you get a file that claims 3/4 while three of its bars hold four beats — and abc2midi still writes the 3/4 event, because it writes what the header says. The header and the music are two independent statements, and nothing forces them to agree.

The procedure

The order that works

  1. midi2abc song.mid -o song.abc
  2. Open song.abc. Rewrite T: — it is the filename and always will be.
  3. If the file contains %***Missing time signature meta command, decide what the meter really is and edit M:. Do not use -m for this; it changes Q: too.
  4. If the source had no FF 51 event, edit Q: by hand. Do not use -Q; it does nothing.
  5. Read the body and check that the bar lines match the meter you just set. This is the step everyone skips, and it is the one the warnings will catch for you.
  6. abc2midi song.abc -o song-fixed.mid, then read the warnings about bars that do not match the time signature.
  7. Verify: the new file should contain FF 58 if you set a meter and FF 51 if you set a tempo. If it does not, the header line was not where the converter looks for it.

Where this site fits. This site's converter writes MIDI without a tempo event and without a time-signature event — that is deliberate, and it is why the file you get here will take the "missing time signature" path in ABC. If you want to see what those two events look like as bytes, and what inserting them does to bar lines, the sheet-music-to-MIDI page walks the same fifteen bytes through a staff instead of a text header.

If what you wanted was notes on a staff, not ABC text, you are on the wrong page: MIDI to sheet music renders the file in the browser and reports which of these header values your file is missing.

FAQ

Questions about MIDI and ABC.

Is ABC notation the same thing as the .abc files on abcnotation.com?

Yes. Same format, same extension, same header fields. A file written by midi2abc is an ordinary ABC file that any ABC reader will open — it is not a private dialect. The only thing that makes it look unusual is the two % comment lines, which are legal ABC and which most readers ignore.

Why does my ABC file say “Missing time signature meta command”?

Because the MIDI file has no FF 58 event. Search the source for those two bytes; if they are absent, nothing was lost in the conversion, the meter was simply never written. The converter then falls back to 4/4 and says so in a comment. The comment is the converter being honest, not the file being broken.

Why is my title “from song.mid” instead of the title I set?

Because T: is built from the filename. In the test here the MIDI carried a FF 03 track name of “Waltz in D” and the ABC still said T: from v-keyd.mid. Rewrite the line; there is no flag that makes it read the embedded title.

Can I go back from ABC to MIDI?

Yes, with abc2midi, and the round trip is where the header turns into hard data: whatever M: says becomes a real FF 58 event in the output, including when it is a guess. That is why editing the header before the return trip matters more than editing it for looks.

Why is my ABC full of C/2 instead of plain letters?

Because L: 1/8 is the unit and those notes are half of it, i.e. sixteenths. It is correct and it plays correctly. If you would rather read plain letters, -gu will rewrite them — and it will also double the tempo line to keep the playing time the same, so check Q: afterwards.

Does the meter in the header change my notes?

No. It changes where bar lines are drawn and nothing else; pitches and durations are untouched. If the notes are in the wrong place, that is a separate problem, and setting the meter will not hide it — it will just make the warnings stop.

Keep going

Related pages, and which one answers what