A program to "de/compile" SMF (Standard MIDI File) files to and from plain text. The midicomp executable will read and write to SMF files (in format 0 or 1), and also read and write it's own plain text representation of MIDI events allowing conversion between the plain text and binary formats.
This means a regular binary .mid file can be converted to plain text as a "bit perfect" copy of the original MIDI file. It can then be edited with any text editor and filtered through any script language and/or batch processing job. When the alterations have been finalized then the plain text version can be "compiled" back into a regular MIDI file.
Originally based on mf2t/t2fm by Piet van Oostrum and others. It should build on any linux simply by typing "make" in the source directory.
v0.0.2 20070722 Fixed gcc4+ compiler bug and exit warnings
v0.0.1 20031129 Initial release, combined mf2t+t2fm, added getopt args
-d --debug send any debug output to stderr -v --verbose output in columns with notes on -c --compile compile ascii input into SMF -n --note note on/off value as note|octave -t --time use absolute time instead of ticks -fN --fold=N fold sysex data at N columns
midicomp some.mid # to view as plain text midicomp some.mid > some.asc # to create a text version
midicomp -c some.asc some.mid # input and output filenames midicomp -c some.mid < some.asc # input from stdin with one arg midicomp some.mid | somefilter | midicomp -c some2.mid
File header: Mfile <format> <ntrks> <division> Start of track: MTrk End of track: TrkEnd Note On: On <ch> <note> <vol> Note Off: Off <ch> <note> <vol> Poly Pressure: PoPr[PolyPr] <ch> <note> <val> Channel Pressure: ChPr[ChanPr] <ch> <val> Controller parameter: Par[Param] <ch> <con> <val> Pitch bend: Pb <ch> <val> Program change: PrCh[ProgCh] <ch> <prog> Sysex message: SysEx <hex> Arbutrary midi bytes: Arb <hex> Sequence nr: Seqnr <num> Key signature: KeySig <num> <manor> Tempo: Tempo <num> Time signature: TimeSig <num>/<num> <num> <num> SMPTE event: SMPTE <num> <num> <num> <num> <num> Meta text events: Meta <texttype> <string> Meta end of track: Meta TrkEnd Sequencer specific: SeqSpec <type> <hex> Misc meta events: Meta <type> <hex>
<ch> ch=<num>
<note> n=<noteval> [note=<noteval>]
<vol> v=<num> [vol=<num>]
<val> v=<num> [val=<num>]
<con> c=<num> [con=<num>]
<prog> p=<num> [prog=<num>]
<manor> minor or major
<noteval> either a <num> or A-G optionally followed
by #, followed by <num> without
intermediate spaces.
<texttype> Text Copyright SeqName TrkName InstrName
Lyric Marker Cue
<type> a hex number of the form 0xab
<hex> a sequence of 2-digit hex numbers without
0x separated by space
<string> a string between double quotes
(like "text")
Channel numbers are 1-based, all other numbers are as they appear in the midifile.
<division> is either a positive number (giving the time resolution in clicks per quarter note) or a negative number followed by a positive number (giving SMPTE timing).
<format> <ntrks> <num> are decimal numbers.
The <num> in the Pb is the real value (two midibytes combined)
In Tempo it is a long (32 bits) value. Others are in the interval 0-127
The SysEx sequence contains the leading F0 and the trailing F7.
In a string certain characters are escaped:
midicomp will accept all formats that mf2t can produce, plus a number of others. Input is case insensitive (except in strings) and extra tabs and spaces are allowed. Newlines are required but empty lines are allowed. Comment starts with # at the beginning of a lexical item and continues to the end of the line. The only other places where a # is legal are insides strings and as a sharp symbol in a symbolic note.
In symbolic notes + and # are allowed for sharp, b and - for flat.
In bar:beat:click time the : may also be /
On input a string may also contain \t for a tab, and in a folded string any whitespace at the beginning of a continuation line is skipped.
Hex sequences may be input without intervening spaces if each byte is given as exactly 2 hex digits.
Hex sequences may be given where a string is required and vice versa.
Hex numbers of the form 0xaaa and decimal numbers are equivalent. Also allowed as numbers are "bank numbers" of the form '123. In fact this is equivalent to the octal number 012 (subtract 1 from each digit, digits 1-8 allowed). The letters a-h may also be used for 1-8.
The input is checked for correctness but not extensively. An errormessage will generally imply that the resulting midifile is illegal.
In awk each parameter is a field, in perl you can use split to get the parameters (except for strings).
The following perl script changes note off messages to note on with vol=0, deletes controller 3 changes, makes some note reassignments on channel 10, and changes the channel numbers from channel 1 depending on the track number.
%drum = (62, 36, 63, 47, 65, 61, 67, 40, 68, 54);
while (<>) {
next if /c=3/;
s/Off(.*)v=[0-9]*/On\1v=0/;
if (/ch=10/ && /n=([0-9]*)/ && $drum{$1}) {
s/n=$1/"n=".$drum{$1}/e;
}
if (/^MTrk/) {++$trknr ; print "track $trknr\n";}
if ($trknr > 2) { s/ch=1\b/ch=3/; }
else { s/ch=1\b/ch=4/; }
print || die "Error: $!\n";
}
and this is the corresponding awk script.
BEGIN { drum[62] = 36; drum[63] = 47; drum[65] = 61; \
drum[67] = 40; drum[68] = 54 }
/c=3/ { next }
($2 == "Off") { $2 = "On"; $5 = "v=0" }
/ch=10/ { n = substr($4, 3); if (n in drum) $4 = "n=" drum[n] }
/^MTrk/ { trknr++ }
/ch=1 / { if (trknr > 2) { $3 = "ch=2" } else { $3 = "ch=3" } }
{ print }