Mish

Introduction

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.

Tools

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.

Reference

General Model

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:

Notes and Chords

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.

Rests

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.

Lyrics

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.

State Change Directives

Time

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

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

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.

Base Note

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.

Velocity

(info coming soon)

Number of Beats Per Measure

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.

Default Articulation

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.

MIDI Event Directives

Markers

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 Changes

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.

Control Changes

(info coming soon)

Program Changes

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.

Pitch Bends

(implementation coming soon)

Aftertouch

(implementation coming soon)