My MIDI file maker

 

As an amateur pianist I have several times wanted to enter scores into programs that can generate MIDI or MusicXML files to play on my Roland digital piano. Entering the data from a score has always been a tedious process, particularly when there are several notes to sound at the same time or if I want to alter note velocities (loudness) in a controlled and regular way.

I set myself a project to define the simplest possible syntax for score data entry and to write a program to read the data and generate a MIDI file. I now (May 2024) have the first version of a working Java program to do this. I will describe my syntax definitions and make the program available.

The program is designed to generate a single track. If you want a multi-instrument file make several single tracks and use a sequencer program (such as Power Tracks Pro) to put them together. This is part of the simplifying strategy for my program. Even separate staves for the piano are not considered: you could make a track for each hand in separate text files and later combine them or you could enter all notes in the single track.

MIDI = Musical Instrument Digital Interface. MIDI has a standard specification which has existed since the 1980s and is very widely used by all kinds of musicians. All digital instruments can read streams of MIDI data sent to them through a serial cable. My piano (and probably most instruments) can also read MIDI data from a file on a USB stick. The specification for MIDI data and files can easily be found online.

 Syntax for data input

The input to my MIDI generator program is simply a text file. It can be edited in any simple text editor (but NOT a word processor because that would add a lot of formatting information that would not make sense to my program). Windows NotePad would suffice as the text editor. I use Notepad++, downloadable free of charge.

The text file contains a series of short lines which may be in upper or lower case. Even note names, such as middle C can be written either as C4 or c4.

Empty lines are ignored, so you can space things out as required.

Lines beginning with // are taken to be comments for you to read but the program ignores them.

Several lines begin with letters followed by a colon. In such lines only the first 3 letters of the word will suffice to determine what type of line it is, but if you wish to write a full word before the colon, for clarity to yourself, that will make no difference to the program.

Other lines begin with a number and in those cases you must follow the example format exactly (no extra characters).

 Lines at the start of the text file

The first 3 of these should always be present.

sig:3/4 sets the time signature, just like you would see at the start of a score. In this example there are 3 beats to the bar (measure) in quadruple time.

bpm:60 sets the speed, in beats per minute.

div:12 (divisions) says there are 12 time divisions per bar (measure). This is one of the most significant features of this syntax. Instead of worrying about whether each note is a crotchet (quarter note), quaver (eighth note) or whatever we simply divide each bar (measure) into a number of equal divisions and for each note we specify the starting division number and the number of divisions it is to sound for (see below for the details of setting a note). Important: division numbers start from 1 in each bar (measure).

The above 3 kinds of line can occur more than once in the file, after any bar line (see below). But note that for most scores there is no need to change div frequently.

ins:0,66,0 (instrument) is an optional line at the very start. It selects a bank and does a program change to choose a particular voice. The example here is for the Concert Piano in my Roland instrument. Your instrument should have a MIDI implementation chart listing all the voices available to you and it will specify 3 numbers like that (probably called MSB, LSB and PC).

 At the start of each bar (measure)

bar:23 Only the word bar is noticed by the program. The number after the colon is for your convenience, so you can see where you are in the score. The bar resets division counting, to start from 1 again.

 Lines that can appear anywhere

These lines alter settings that will be used by all subsequent lines unless changed again. Such settings will not appear in the final MIDI file but will affect things that will be there, such as the velocity (loudness) of notes when they appear.

key:4# By setting the key you can avoid having to put accidentals on all the notes that require them simply for the key. Having set this example (E major/C# minor) any C4 will automatically become note 65 (C4#) rather than 64, unless countermanded by another accidental (see note entry, below). For flat keys use the letter b instead of #. To set C major/A minor, which is the key at the start, write key:0

vel:ff sets the normal (unemphasised) velocity (loudness) for subsequent notes. Recognised values after the colon are: ppp, pp, p, mp, mf, f, ff, fff.

The following 4 possible lines define factors by which note velocities will be multiplied automatically if they meet certain conditions (but not above 127, the maximum allowed by the MIDI specification). The examples here show the initial values if you do not put any of these lines in your file.

fir:1.2 (first) is the multiplying factor for notes on the first beat/division in any bar.

oth:1.1 (other) emphasises notes on other beats.

mel:1.1 (melody) emphasises melody notes. See note entry below for how to say a note is a melody note.

str:1.2 (stress) is for stressed notes. Again, note entry can set any note as stressed.

 Things that happen on a division

The remaining possible lines all start with a 1- or 2-digit number which is the division number within the bar (starting at number 1). There are various optional letters and numbers so some examples will show the possibilities.

1C5/3 At division 1, note C5 (C above middle C) with duration of 3 divisions.

2c5/3v The same note at division 2 but the final v means stressed (emphasised).

4A6#/4m Note A6 sharpened at division 4, lasting for 4 divisions and the m at the end means this is a melody note, slightly louder than other notes.

4c4x/6 Middle C double sharp (x), duration 6 divisions.

6B5bb/4 bb = double flat (b would be single flat)

8F4n/4 n = natural (use when the current key would sharpen or flatten it).

10D5b/1s At division 10, D5 flat staccato. In this case the duration (1) is ignored - it becomes half a division.

A small restriction at present is that only one optional final letter (m, v or s) can be used, not a combination of those.

For those who know about regular expressions in Java, here is the RegEx used for parsing these note-entry lines:
^(\\d{1,2})([a-g])(\\d)([[#nx][b{1,2}]]?)/(\\d{1,2})([msv]?)$
This is applied after each line has been converted to lower case.

 Pedals

There are lines for starting and ending pedals (sustain or soft) which also start with the division numbers on which they occur:

1ped Pedal start, at division 1.

6* Pedal end, at division 6.

3una Una corda start.

6tre Una corda end (usually shown in scores as tre corda).

It is assumed that your instrument is able to respond to MIDI controller events for these pedals. An alternative would be for my program to modify note ending times for the sustain pedal (MIDI calls it HOLD) but that has not been programmed so far.

 Planned

Further possible commands might cover crescendos, diminuendos and repeat sections.

I am also considering how an interactive form might be used instead of text editing. And then possibly HTML/JS as a web page instead of Java.

 The Java program

A zip of the JAR file (made with JDK 8) for the first version is available here.

A more complete set of files will soon be available on github.

Next page