NAME¶
midge - generate midi file from text description of music
SYNOPSIS¶
midge [options] [filename]
DESCRIPTION¶
midge generates a type 1 midi file from a text description of music.
midge takes it's input from stdin unless
filename is specified.
OPTIONS¶
-h or
--help
- Show help text.
--version
or --warranty or --about
- Show version and license info.
-v or
--verbose
- Print verbose output to stdout.
-d or
--debug
- Print debugging output to stdout (sets verbose mode
automatically).
-q or
--quiet
- Quiet. no stdout.
-o
file or --outfile file
- Midi output to file. Otherwise to a.out.mid
-c or
--check
- Check input only; No midi output.
-u or
--unroll-loops
- Unroll all the repeat blocks before parsing and save the
unrolled source code to a new file (*.long.mg). Should be set
automatically if needed.
-U or
--no-unroll-save
- Don't save unrolled source to file.
-R or
--no-reset
- Don't insert `reset all controllers' event at start of
tracks.
-t bpm
or --tempo bpm
- Set tempo to bpm beats per minute, overriding value
set in input file.
-b
steps or --bend-steps steps
- Set the number of steps per quarter note for the simple
bend syntax.
--unsafe
- Do not use Safe.pm to run Perl code from %eval
blocks.
-s
number or --seed number
- Use number as the seed for the random number
generator.
-S [scale
[root]] or --show-scale [scale [root]]
- List notes in scale starting from root. If
root is omitted c4 is used. If scale is omitted, a list of
suported scales is shown.
-I
path or --include path
- Add path to include paths. Can be specified multiple
times or path can be a list separated by colons or commas.
Sample source file to play a scale of E.
================start file======================
# this line is a comment
@head { # there must be exactly 1 @head section
# set time signature
$time_sig 4/4
# set tempo in BPM
$tempo 120
} # end of @head section
@body { # there must be exactly 1 @body section
# start a music track on channel 1
# multiple tracks can use the same channel
@channel 1 {
# set patch to electric bass
$patch 34
# notes. see below for explanation.
/l4/e3 # quarter note e in third octave
f
+ # f sharp same octave same length
# use `
-' for flat
g+ a b # rest of notes
c+
4 d+ e # octave changes at c
} # end of track
} # end of @body section
========================end file====================
More examples are included in the examples/ directory of the archive.
In the following, <name> is a required parameter and [name] is an optional
parameter.
Notes.
The format of a note is: [
/options/]<
name>[
+|
-][
octave]
The
/options/ section can contain the following:
l[numerator:]<denominator>
Sets the length of the note to (
numerator or one) divided by
denominator. ie. l4 = quarter note, l1 = whole note, l3:4 = 3/4 note (3
quarter notes tied). An uppercase `
L' may be used instead to
distinguish it from a `1'.
r<number>
Sets the number of times to repeat the note. For example
/
l8
r16/
makes the note duration 1/8 and repeats the note 16 times.
a<number>
Sets the note's note on velocity (attack)
d<number>
Sets the note's note off velocity (decay)
z[+|-]<number>[%]
Offsets the note by
number midi clicks. Positive values play the note
late and negative values play it early. If
number is followed by a `
%´ character it is taken as a percentage of the current note
length. Offset values are
not inherited by subsequent notes.
Z[+|-]<number>[%]
As the above `
z´ option but a random value is used. If
number is negative or positive (plus sign
required), a value
between zero and
number is used. If there is no sign, a value between
plus and minus
number is used.
The offset option will not work with the
repeat note option, but the same
effect can be achieved using a
%repeat block.
Notes cannot be offset backwards (ie played early) unless they are preceded by a
rest. To work around this I have added the
$shorten keyword, described
below. See also
$unquantise.
name is the name of the note ie. [a-g]
required.
+ sharp.
- flat.
octave is the midi octave ie. [1-11]. Although most midi software uses 0
for the lowest octave, I have used 1 for consistency with the midi channels
and instrument names which both count from 1.
If not specified, the length, octave, attack and decay are inherited from the
previous note.
In a drum track, instead of the note names, aliases can be used. For example, to
get an open hi hat, instead of `
f+3' you can use `
hh_o'. See
README.drums for a full list of aliases.
Rests.
Rests are written as note `
r', with
/options/ the same as for
notes, but with only the length and repeat options used. The length value is
inherited from note to rest and vice versa.
Bars.
The pipe symbol (`|') can be used to denote bars. The lengths of bars are not
checked -- this is only to allow more readable source files. Bars can be
numbered by appending a number to the pipe symbol. They may be separated by an
underscore but not by spaces.
Simple bar example: | c d e f | g a b c
Numbered bar examples: |1 c d e f |2 g a b c
|_1 c d e f |_2 g a b c
The consistency of bars can be checked by using the
$bar_strict keyword
in the
@head section. This gives an error or warning unless all tracks
have the same number of bars and numbered bars appear at the same time in each
track:
$bar_strict
warn # Print a warning message for inconsistent bars.
$bar_strict
error # Exit with an error message for inconsistent bars.
Top level keywords.
@head { content }
There must be exactly one
@head section. See below for description of
content.
@body { content }
There must be exactly one
@body section. See below for description of
content.
Keywords in the
@head section.
$time_sig <a/b>
The
b value must be one of 4, 8, 16, 32, 64.
$tempo <t>
t is the tempo in BPM.
Both
$time_sig and
$tempo are also allowed within an @channel
block (described below).
$title <title>
Sets the title of the song to
title. If
title contains spaces it
must be inside double quotes.
$resolution <n>
Sets the number of midi clicks per quarter note to
n. The default is 96.
Keywords in the
@body section.
%define <name> { notes }
Define a sequence of
notes, assigning it to
name to be recalled in
a music track. Defined sequences are used by including:
~<name>[/transpose/]
within a track to include the sequence
name, transposed by
transpose semitones. Previously defined sequences can be used in
subsequent
%define blocks. for instance:
%define a_riff { a3 a c4 d }
%define d_riff { d4 d f g }
%define main_riff {
~a_riff
~d_riff }
Although we could achieve the same result by transposing the first riff to make
the second:
%define a_riff { a3 a c4 d }
%define main_riff {
~a_riff
~a_riff
/5/ }
define blocks may also contain repeat blocks, bend blocks and
$volume/patch/reverb etc.
@channel <number> [name] { content }
Begin a midi track on channel
number, optionally setting the instrument
name to
name. If
name contains spaces it must be inside double
quotes.
content can include notes, rests, previously defined sequences, and the
following keywords:
$time_sig <a/b>
Changes the time signature for the song (affects all tracks). The
b value
must be one of 4, 8, 16, 32, 64.
$tempo <t>
Changes the song tempo (affects all tracks).
t is in BPM.
$patch [[bank_LSB,]bank_MSB,]<number|name>
Set patch number for this channel to
number or
name. Where
number is from 1 to 128 and
name is an alias as defined in
README.patches. Optionally select bank number
bank_MSB. Optionally
select bank LSB number
bank_LSB (used for external midi keyboards).
Each value must be in the range 1-128.
$bank [LSB,]<MSB>
Select bank number
MSB. Optionally setting the LSB value (used for
external midi keyboards) to
LSB. Both values must be in the range
1-128.
$length [n:]<d>
Set default note length. The value is specified in the same format as in the
note options.
$shorten <number>
Shorten each note by
number midi clicks, to allow space for notes to be
offset backwards.
$unquantise [+|-]<number>[%]
Apply a random offset to each note.
number has the same meaning as for
the
Z note option above.
$octave <number>
Set default octave to
number
$volume <number>
Set the track volume to
number
$attack <number>
Set the note's attack to
number
$decay <number>
Set the note's decay to
number
$reverb <number>
Set the reverb depth to
number on the current channel.
$chorus <number>
Set the chorus depth to
number on the current channel.
$pan <number>
Set the pan value to
number. 0 is left 127 is right.
The volume, attack, decay, reverb, chorus and pan values must be integers from 0
to 127. They can also be specified as a range (eg `
8-64'), in which
case a random value within the range is used.
%pan_all { note value ... }
Sets the pan value for each subsequent instance of
note in the current
track. This is mainly intended for panning a drum kit, but could be used on
another track.
value can be an integer or a range (eg `
8-64').
Multiple
note value pairs are allowed. If two notes with different
pan_all values are played at the same time anything could happen.
To affect every note in the channel with a range, use `
*' or
`
any' for
note. The
/r4/<note> method of repeating
notes will not work with this option, but the same effect can be achieved
using a repeat block.
$marker <text>
Adds a marker event with
text as it's content. If
text contains
spaces it must be quoted using double-quote characters.
%repeat <number> { notes }
Repeat
notes number times.
notes can include notes, rests,
predefined sequences and other
%repeat blocks.
%bend <note> { event ... }
Play
note and move the pitch wheel in the manner described by multiple
events, which have the following format:
[n:]<d><+|-><value>
where
n and
d specify the time from the start of the note or from
the previous event, in the same format as the note lengths, and
value
is the amount to bend the note by (the plus or minus sign is required). With
the default pitch wheel range of +/- 2 semitones a value of 32 equates to one
semitone. Note that the bend amount is relative. The maximum
cumulative
bend amount is plus or minus 64.
For example the following:
%bend a3 { 4+32 4-32 2+0 }
Plays the note a3 for 1/4 note, bends up a whole tone for 1/4 then returns down
to a3 and holds for 1/2 note.
$bend_range <number>
Changes the pitch wheel range to +/-
number. This sets the maximum bend
up and down, so if it is set to 4, a bend value of 64 will bend up 4 semitones
and -64 will bend down 4 semitones. The default range for most midi devices is
2 semitones.
$pitch <val>
Set the pitch wheel value to
val. This can be used in conjunction with
separate note on and note off events (see below under `simultaneous notes') to
create complex bending effects. Unlike the
%bend syntax above, this
does
not reset the pitch wheel to the neutral position (64)
Simpler pitch bends can be created with this syntax:
/l8/e4
=>g4
=>e4
This bends from e4 up to g4 and back down to e4 in linear steps over the
duration of an eighth note. By default there are 16 steps per quarter note
duration (8 steps in this example), but a different value can be set using the
`-b' command line switch. Any number of notes can be used, but the first one
must have a length value and each of them must have an octave value.
%choose [time] { weighting item ... }
where time is a length value in the format [n:]<d> the same as used in the
length options, with the `l' omitted.
If
time is not specified:
Choose one
item from a list, where each
item can be a note, rest,
or predefined riff, and each item has a
weighting which defines how
likely it is to be chosen. For example:
%choose { 2 a3 4 c5 3 e4 1 g3 }
gives a3 a 20% chance, c5 - 40% ; e4 - 30% and g3 - 10% Each item
must
have a weighting. See also scales below.
if
time is specified:
Choose multiple
items from the list up to a length of
time. If all
the
items are too long to end the riff exactly at
time, the
remainder is filled with a rest. When choose is used in this way each note or
rest must have a length value and any predefined riffs used must have a fixed
length (ie the first note must have a length value), and the length of the
whole riff must be specified in the choose block in the same format as for
notes. for example:
%define riff_1 { /l2/a3 /l4/b c4 } # riff is 1 bar long
%choose
4:1 { # choose 4 bars
1 /l8/d4 3 /l8/e4 2 /l4/g4 1
/l1/~riff_1
}
If
time is
0 or
- then midge looks for a block of the form:
rhythm { n[:d] ... }
which is taken as a series of note length values for which the pitches are
chosen from the list. Other tokens are passed through, so you can insert
specific notes, predefined riffs or rests. Any token in the block begining
with an underscore will be passed through, with the underscore removed. See
examples/tutorial/choose_scale.mg for an example.
Another way to specify the list of notes/weightings is with the
scale
keyword:
scale minor /l8/g4-6 [ weight ... ]
This selects a G Minor scale from the 4th to 6th octaves (ie g4 to g6). The
length value is unnecesary if you are using a rhythm block. If the
-6
is omitted a single octave is used.
The weight block specifies the note weightings in order. If omitted all
weightings are equal. To ingore a note use a weighting of 0, but there
must be a weighting for each note if the block is present at all.
The
-S switch can be used to show the notes in a scale or a list of
supported scales.
%chain <time> {
start <note>
note1 [ weight note ... ]
...
rhythm [ weight length ... ]
or rhythm { length ... } }
Define a `chain' structure where for each note there is a weighted list of notes
which may follow it. A starting point is picked randomly from all the notes
used, or specified with the
start keyword, and then subsequent notes
are chosen from the appropriate list up to a total length of
time.
The
rhythm keyword has two forms: Using square brackets `[]', a weighted
list of note lengths can be defined, which will be chosen from randomly. Using
braces `{}', a list of length values can be defined which will be used in
sequence (repeating as neccessary). To play through the rhythm block just
once, set the
time to
0 or
-. In this case the rhythm
block is parsed in the same way as described above for
%choose with
time set to zero. The keyword
times can be used as a synonym for
rhythm.
The
start keyword specifies the note to start from when using the chain.
If
start is omitted, the start note is chosen randomly.
Another way define the notes in a
chain block is to use one of the built
in scales. Then the weightings are specified in the form of a matrix, with a
row for each "from" note (one for each note of the scale) and a
column for each "to" note. An example of this form can be found in
the file examples/tutorial/chain_scale.mg
To use the choose or chain blocks, the file must be compiled with the
unroll-loops option (it is set automatically when a choose or chain block is
found). This option saves the unrolled source code in a new file, so if it
produces particularly good output you have an exact copy which you can make
other changes to without losing the generated track.
Note that a choose and chain blocks cannot be inside a %define or inside another
choose or chain block.
%eval { Perl code }
Run a block of Perl code and replace the %eval block with the value returned
from the Perl code.
%eval - { Perl Code }
Run a block of Perl code without reading the return value.
Perl code is run using the Safe module if it is present, with :base_core,
:base_math and :base_mem allowed. If Safe.pm is not available or more
permissions are needed the --unsafe option causes midge to run the %eval
blocks in it's own perl process.
Keywords allowed at any point in the source.
%include <file>
Includes the contents of
file as if they had been written at that point
in the source file.
Must be on a line of it's own in the source file.
Simultaneous Notes.
The most flexible way to play simultaneous notes is by using separate tracks
(you can use the same channel/patch), or by using separate note on and note
off events (see below). However, there is a simpler way with some limitations.
For example:
( c e g ) will play the notes c, e and g simultaneously,
making a C chord. The length of all the simultaneous notes is the same as the
first one (determined by it's own length value or the one inherited from the
previous note, rest, or $length declaration.
One way to use this to make chords is as follows:
%define minor { ( c e- g ) } # define minor to be a c-minor
%define major { ( c e g ) } # define major to be a c-major
%define 7th { ( c e g b- ) } # define 7th to be a c-7th
Then you can use the in your music tracks:
$length 4 $octave 4 # set default length and octave
~major # play a c-major
~minor/9/ # play an a-minor
~7th/5/ # play an f-7th
To make chords sound strummed, the
strum keyword can be used:
$strum 5
This sets the interval between each note in subsequent chords to 5 midi clicks.
To create complex patterns of simultaneous notes on one track, separate note on
and note off events can be used. These are specified in the same way as normal
notes, but with a
+ prepended for note on and a
- prepended for
note off. The length and repeat options cannot be used. The length of notes
entered this way is controlled by putting rests or other notes between the
note on and note off events. eg:
+c4 /l4/r
+e r
+g /l2/r
-c
-e
-g
plays and holds c4, after a 1/4 note plays and holds e4 and after another 1/4
note plays and holds g4, releasing all three after a further 1/2 note.
Tuplets.
While it is possible to create tuplets by choosing a suitable note length, they
can also be written in a more conventional way using the
%tuplet
keyword:
%tuplet n:d { notes... }
plays
n notes in the space of
d.
notes can contain anything
allowed in a @channel block. The note values are then automatically altered to
create the tuplet. For example:
%tuplet 5:3 { /l8/e4 f g f e }
plays five eigth notes in the space of three. Tuplets can be nested to any
depth. See examples/tutorial/tuplet.mg for an example. Midge does
not
check that the length of music inside the tuplet block is correct.
Keys.
If you want to import your midi file into a notation editor you will want to set
the key. This is done with:
$key <name>[+|-][m]
Where
name is a-g, +|- are sharp and flat, and m is minor. If the whole
piece stays in the same key you can set it in the @head section, otherwise it
can appear anywhere in a @channel section, and will affect all tracks.
If you are used to regular music notation and want notes to be sharp or flat
automatically depending on the key, use the
$key_strict keyword
instead. To get a natural note use the
= sign, eg in G,
f= plays
an f natural. The
$key_strict keyword can only be used in the @head
section. The key can still be changed using the regular
$key keyword.
$ctrl <num,val>
Set controller number
num to
val.
$rpn [num-msb,]<num-lsb,val-msb>[,val-lsb]
Set the rpn controller
num to
val
$nrpn [num-msb,]<num-lsb,val-msb>[,val-lsb]
Set the nrpn controller
num to
val
%verbatim { byteval... }
Insert a string of bytes into the midi file. Each
byteval can be in
either decimal (0-255) or hex (0x00-0xFF). The keyword
bytes can be
used instead of
verbatim.
$print <text>
Print
text to stdout. If
text contains spaces it must be quoted
using double quotes (
").
BUGS¶
When building scales, although the pitches are correct, the note names may be
technically wrong, eg `a sharp' instead of `b flat'.
If there is an error in a %repeat or %define block the error message only gives
the line number of the %repeat or %define keyword.
No commercial potential.
If you find any other bugs, please let me know.
SEE ALSO¶
midi2mg(1),
emacs(1),
playmidi(1), drvmidi(1),
timidity(1).
AUTHOR¶
David Riley <dave@dmriley.demon.co.uk>