Mish (MIDI shorthand) is a text-based music notation language. It is not particularly unique in this role, but I designed it to match my own mental model of music very closely, so it's extremely easy for me to use. Maybe you'll find it useful too.
So why would you want to use a text-based music notation language? Western music is most often represented using Common Music Notation (CMN), which is what most people think of as sheet music. Despite its popularity, however, CMN is an awkward language to use on a computer because it is graphical in nature, rather than textual. Although GUIs are ubiquitous these days, computer interfaces for entering and editing text are simply more mature, more efficient, and more powerful than those for entering graphics. A picture might be worth a thousand words, but I can type those thousand words far faster than I can draw the picture.
A song represented in Mish is similar to a computer program represented in C. It is human readable, but needs to be compiled into a binary form, namely a standard MIDI file, before the computer can play it. Mish can also be written out with pencil and paper, but it is not optimized for a musician to perform from, as he would with CMN.
The standard Mish compiler is a command-line utility called mish
. It has no requirements other than ANSI C, so it should work on just about any computer. Open source and free, it is available as part of my MIDI Utilities package.
An online frontend called Web Mish is also available. This allows you to use Mish without installing anything on your own computer. However, there is no guarantee that the Web Mish service will be available forever, so it is safer for you to download and run mish
locally if you care about your Mish files working in the future.
A Mish file is a sequence of tokens separated by whitespace. The symbol #
indicates that the rest of the line is a comment, which is equivalent to whitespace.
The sequence of tokens is processed in the order encountered. Tokens may either add MIDI events into the output file, or update the state of the Mish processor, or both. Events are added in much the same manner as writing on paper with a pen; once you add someting, it cannot be erased or changed, but you can move the pen around at random and add more in any order.
The state of the Mish processor is made up of the following:
chord ::= note+ additional_beat* dynamics? articulation?
note ::= octave_modifier? chromatic_modifier? diatonic
note ::= "[
" ( number | ( "x
" hex_number ) ) "]
"
octave_modifier ::= octave_up* | octave_down*
octave_up ::= "'
"
octave_down ::= ",
"
chromatic_modifier ::= sharp* | flat*
sharp ::= "+
"
flat ::= "-
"
diatonic ::= do | re | mi | fa | so | la | ti
do ::= "1
"
re ::= "2
"
mi ::= "3
"
fa ::= "4
"
so ::= "5
"
la ::= "6
"
ti ::= "7
"
additional_beat ::= "-
"
dynamics ::= louder* | softer*
louder ::= "<
"
softer ::= ">
"
articulation ::= staccato | legato
staccato ::= "!
"
legato ::= "~
"
A chord token indicates that MIDI note on events for each of the specified notes should be added at the current track, channel, and time. Notes specified in the standard manner have pitches relative to the current base note, while absolute notes are specified by MIDI note number (1
to 128
, or in hex, x00
to x7F
). Note velocities are relative to the current velocity. The chord starts with a duration of one beat, plus the specified number of additional beats, all relative to the current number of beats per measure. The current time is advanced by the duration of the chord.
The chord token also indicates that MIDI note off events should be added for each of the specified notes, but the time for those events depends on the chord's articulation. The type of articulation usually depends on the current default articulation, but if the chord is marked with a staccato or legato symbol, that type of articulation is used instead. If the chord has normal articulation, then MIDI note off events are added after the duration minus the current note gap. If the chord is legato, then the note off events are added after the full duration. If the chord is staccato, then the note off events are added after the current minimum note length.
rest ::= beat+
beat ::= "-
"
A rest does not add any events to the output file, but it advances the current time by the specified number of beats, relative to the current number of beats per measure.
lyric ::= ""
" text ""
"
A lyric token indicates that a MIDI lyric event should be added to the current track at the current time, which does not advance. \"
can be used to include a quote inside the lyric.
time_directive ::= "time
" "=
" number
time_directive ::= "time
" "+
" number
time_directive ::= "time
" "-
" number
time_directive ::= "time
" "=
" ""
" text ""
"
A time directive indicates that the current time should be moved to the value specified in terms of the current number of beats per measure. If a marker is specified instead of a number, the output file is scanned for the first marker with a matching name, and the current time is set to its time; it is an error to refer to a marker which has not yet been added.
track_directive ::= "track
" "=
" number
A track directive indicates that the current track should be set to the specified number. Track zero is the conductor track, reserved for tempo changes and such; the first conventional track is one. Empty tracks will be added as needed.
channel_directive ::= "chan
" "=
" ( number | ( "x
" hex_number ) )
A channel directive indicates that the current channel should be set to the specified number (1
to 16
, or in hex, x0
to xF
). Remember that in General MIDI, track ten is reserved for drums.
note_directive ::= "note
" "=
" ( number | ( "x
" hex_number ) )
note_directive ::= "note
" "+
" number
note_directive ::= "note
" "-
" number
A note directive indicates that the current base note should be changed, either to an absolute MIDI note number (1
to 128
, or in hex, x00
to x7F
), or relative to its previous value.
(info coming soon)
beat_directive ::= "beat
" "=
" number
beat_directive ::= "beat
" "*
" number ( "/
" number )?
beat_directive ::= "beat
" "/
" number
A beat directive indicates that the current number of beats per measure should be changed, either to an absolute value, or relative to its previous value.
articulation_directive ::= "art
" "=
" "normal
"
articulation_directive ::= "art
" "=
" "staccato
"
articulation_directive ::= "art
" "=
" "legato
"
An articulation directive indicates that the current default articulation should be changed to the specified value.
marker_directive ::= "mark
" "=
" ""
" text ""
"
A marker directive indicates that a MIDI marker meta event should be added at the current time. It can be used for navigation later.
tempo_directive ::= ramp? "tempo
" "=
" number
tempo_directive ::= ramp? "tempo
" "+
" number
tempo_directive ::= ramp? "tempo
" "-
" number
tempo_directive ::= ramp? "tempo
" "*
" number ( "/
" number )?
tempo_directive ::= ramp? "tempo
" "/
" number
ramp ::= beat+
beat ::= "-
"
A tempo directive indicates that a MIDI tempo meta event should be added at the current time. The value, which can be either absolute or relative to the previous value, is specified in beats per minute.
If a ramp is specified, then a series of tempo events will be added instead of a single one. The ramp starts with the most recent tempo at the current time, and progresses linearly to the specified tempo after specified number of beats. The current time is advanced.
(info coming soon)
program_change_directive ::= "prog
" "=
" ( number | ( "x
" hex_number ) )
A program change directive indicates that a MIDI program change event should be added at the current track, channel, and time. Its value can range from 1
to 128
, or in hex, x00
to x7F
.
(implementation coming soon)
(implementation coming soon)