|
|
|
/*********************************************************************************************
|
|
|
|
*
|
|
|
|
* MIDITONES: Convert a MIDI file into a simple bytestream of notes
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* MIDITONES converts a MIDI music file into a much simplified stream of commands, so that
|
|
|
|
* the music can easily be played on a small microcontroller-based synthesizer that has
|
|
|
|
* only simple tone generators. This is on github at www.github.com/LenShustek/miditones.
|
|
|
|
*
|
|
|
|
* Volume ("velocity") and instrument information in the MIDI file can either be
|
|
|
|
* discarded or kept. All the tracks are processed and merged into a single time-ordered
|
|
|
|
* stream of "note on", "note off", "change instrument" and "delay" commands.
|
|
|
|
*
|
|
|
|
* This was written for the "Playtune" series of Arduino and Teensy microcontroller
|
|
|
|
* synthesizers. See the separate documentation for the various Playtune.players at
|
|
|
|
* www.github.com/LenShustek/arduino-playtune
|
|
|
|
* www.github.com/LenShustek/ATtiny-playtune
|
|
|
|
* www.github.com/LenShustek/Playtune_poll
|
|
|
|
* www.github.com/LenShustek/Playtune_samp
|
|
|
|
* www.github.com/LenShustek/Playtune_synth
|
|
|
|
* MIDITONES may also prove useful for other simple music synthesizers..
|
|
|
|
*
|
|
|
|
* The output can be either a C-language source code fragment that initializes an
|
|
|
|
* array with the command bytestream, or a binary file with the bytestream itself.
|
|
|
|
*
|
|
|
|
* MIDITONES is written in standard ANSI C and is meant to be executed from the
|
|
|
|
* command line. There is no GUI interface.
|
|
|
|
*
|
|
|
|
* The MIDI file format is complicated, and this has not been tested on all of its
|
|
|
|
* variations. In particular we have tested only format type "1", which seems
|
|
|
|
* to be what most of them are. Let me know if you find MIDI files that it
|
|
|
|
* won't digest and I'll see if I can fix it.
|
|
|
|
*
|
|
|
|
* There is a companion program in the same repository called Miditones_scroll
|
|
|
|
* that can convert the bytestream generated by MIDITONES into a piano-player
|
|
|
|
* like listing for debugging or annotation. See the documentation in the
|
|
|
|
* beginning of its source code.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* ***** The MIDITONES command line *****
|
|
|
|
*
|
|
|
|
* To convert a MIDI file called "chopin.mid" into a command bytestream, execute
|
|
|
|
*
|
|
|
|
* miditones chopin
|
|
|
|
*
|
|
|
|
* It will create a file in the same directory called "chopin.c" which contains
|
|
|
|
* the C-language statement to intiialize an array called "score" with the bytestream.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* The general form for command line execution is this:
|
|
|
|
*
|
|
|
|
* miditones <options> <basefilename>
|
|
|
|
*
|
|
|
|
* The <basefilename> is the base name, without an extension, for the input and
|
|
|
|
* output files. It can contain directory path information, or not.
|
|
|
|
*
|
|
|
|
* The input file is <basefilename>.mid The output filename(s)
|
|
|
|
* are the base file name with .c, .bin, and/or .log extensions.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* The following commonly-used command-line options can be specified:
|
|
|
|
*
|
|
|
|
* -v Add velocity (volume) information to the output bytestream
|
|
|
|
*
|
|
|
|
* -i Add instrument change commands to the output bytestream
|
|
|
|
*
|
|
|
|
* -pt Translate notes in the MIDI percussion track to note numbers 128..255
|
|
|
|
* and assign them to a tone generator as usual.
|
|
|
|
*
|
|
|
|
* -d Generate a self-describing file header that says which optional bytestream
|
|
|
|
* fields are present. This is highly recommended if you are using later
|
|
|
|
* Playtune players that can check the header to know what data to expect.
|
|
|
|
*
|
|
|
|
* -b Generate a binary file with the name <basefilename>.bin, instead of a
|
|
|
|
* C-language source file with the name <basefilename>.c.
|
|
|
|
*
|
|
|
|
* -tn Generate the bytestream so that at most "n" tone generators are used.
|
|
|
|
* The default is 6 tone generators, and the maximum is 16. The program
|
|
|
|
* will report how many notes had to be discarded because there weren't
|
|
|
|
* enough tone generators.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* The best combination of options to use with the later Playtune music players is:
|
|
|
|
* -v -i -pt -d
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* The following are lesser-used command-line options:
|
|
|
|
*
|
|
|
|
* -p Only parse the MIDI file, and don't generate an output file.
|
|
|
|
* Tracks are processed sequentially instead of being merged into chronological order.
|
|
|
|
* This is mostly useful for debugging MIDI file parsing problems.
|
|
|
|
*
|
|
|
|
* -lp Log input file parsing information to the <basefilename>.log file
|
|
|
|
*
|
|
|
|
* -lg Log output bytestream generation information to the <basefilename>.log file
|
|
|
|
*
|
|
|
|
* -nx Put about "x" items on each line of the C file output
|
|
|
|
*
|
|
|
|
* -sn Use bytestream generation strategy "n".
|
|
|
|
* Two strategies are currently implemented:
|
|
|
|
* 1:favor track 1 notes instead of all tracks equally
|
|
|
|
* 2:try to keep each track to its own tone generator
|
|
|
|
*
|
|
|
|
* -cn Only process the channel numbers whose bits are on in the number "n".
|
|
|
|
* For example, -c3 means "only process channels 0 and 1". In addition to decimal,
|
|
|
|
* "n" can be also specified in hex using a 0x prefix or octal with a 0 prefix.
|
|
|
|
*
|
|
|
|
* -kn Change the musical key of the output by n chromatic notes.
|
|
|
|
* -k-12 goes one octave down, -k12 goes one octave up, etc.
|
|
|
|
*
|
|
|
|
* -pi Ignore notes in the MIDI percussion track 9 (also called 10 by some)
|
|
|
|
*
|
|
|
|
* -dp Generate IDE-dependent C code to define PROGMEM
|
|
|
|
*
|
|
|
|
* -r Terminate the output file with a "restart" command instead of a "stop" command.
|
|
|
|
*
|
|
|
|
* -h Give command-line help.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* ***** The score bytestream *****
|
|
|
|
*
|
|
|
|
* The generated bytestream is a series of commands that turn notes on and off,
|
|
|
|
* maybe change instruments, and begin delays until the next note change.
|
|
|
|
* Here are the details, with numbers shown in hexadecimal.
|
|
|
|
*
|
|
|
|
* If the high-order bit of the byte is 1, then it is one of the following commands:
|
|
|
|
*
|
|
|
|
* 9t nn [vv]
|
|
|
|
* Start playing note nn on tone generator t, replacing any previous note.
|
|
|
|
* Generators are numbered starting with 0. The note numbers are the MIDI
|
|
|
|
* numbers for the chromatic scale, with decimal 69 being Middle A (440 Hz).
|
|
|
|
* If the -v option was given, a second byte is added to indicate note volume.
|
|
|
|
*
|
|
|
|
* 8t Stop playing the note on tone generator t.
|
|
|
|
*
|
|
|
|
* Ct ii Change tone generator t to play instrument ii from now on. This will only
|
|
|
|
* be generated if the -i option was given.
|
|
|
|
*
|
|
|
|
* F0 End of score; stop playing.
|
|
|
|
*
|
|
|
|
* E0 End of score; start playing again from the beginning.
|
|
|
|
*
|
|
|
|
* If the high-order bit of the byte is 0, it is a command to delay for a while until
|
|
|
|
* the next note change. The other 7 bits and the 8 bits of the following byte are
|
|
|
|
* interpreted as a 15-bit big-endian integer that is the number of milliseconds to
|
|
|
|
* wait before processing the next command. For example,
|
|
|
|
*
|
|
|
|
* 07 D0
|
|
|
|
*
|
|
|
|
* would cause a delay of 0x07d0 = 2000 decimal millisconds, or 2 seconds. Any tones
|
|
|
|
* that were playing before the delay command will continue to play.
|
|
|
|
*
|
|
|
|
* If the -d option is specified, the bytestream begins with a little header that tells
|
|
|
|
* what optional information will be in the data. This makes the file more self-describing,
|
|
|
|
* and allows music players to adapt to different kinds of files. The later Playtune
|
|
|
|
* players do that. The header looks like this:
|
|
|
|
*
|
|
|
|
* 'Pt' Two ascii characters that signal the presence of the header
|
|
|
|
* nn The length (in one byte) of the entire header, 6..255
|
|
|
|
* ff1 A byte of flag bits, three of which are currently defined:
|
|
|
|
* 80 velocity information is present
|
|
|
|
* 40 instrument change information is present
|
|
|
|
* 20 translated percussion notes are present
|
|
|
|
* ff2 Another byte of flags, currently undefined
|
|
|
|
* tt The number (in one byte) of tone generators actually used in this music.
|
|
|
|
*
|
|
|
|
* Any subsequent header bytes covered by the count, if present, are currently undefined
|
|
|
|
* and should be ignored by players.
|
|
|
|
*
|
|
|
|
* Len Shustek, 4 Feb 2011 and later
|
|
|
|
*
|