midi2tones
midi2tones copied to clipboard
Fork of MIDITONES - Convert MIDI files to a simplified time-ordered sequence of note commands
trafficstars
/********************************************************************************************* *
- MIDI2TONES: Convert a MIDI file into a simple bytestream of notes
- This is a fork of MIDITONES as it stood on September 27, 2016
- Copyright (c) 2011,2013,2015,2016, Len Shustek
- https://github.com/LenShustek/miditones
- The purpose of the fork was to add an alternate output format.
- MIDI2TONES 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
- https://github.com/MLXXXp/midi2tones
- This was written for the "Playtune" series of Arduino and Teensy microcontroller
- synthesizers. See the separate documentation for the various Playtune players at
- https://github.com/LenShustek/arduino-playtune
- https://github.com/LenShustek/ATtiny-playtune
- https://github.com/LenShustek/Playtune_poll
- https://github.com/LenShustek/Playtune_samp
- and also the ArduboyPlaytune library derived from arduino-playtune
- https://github.com/Arduboy/ArduboyPlaytune
- MIDI2TONES may also prove useful for other simple music synthesizers.
- 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.
- An alternate output format can be specified, which consists of a single monotonic
- stream of frequency/duration pairs of 16 bit values. The specified frequency can
- also include a flag to indicate that the note is to be played at a higher volume,
- if the velocity of the MIDI note is above a certain value.
- This format is suitable for use with the ArduboyTones library, which is on GitHub at
- https://github.com/MLXXXp/ArduboyTones
- 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.
- MIDI2TONES 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 Playtune bytestream generated by MIDI2TONES into a piano-player
- like listing for debugging or annotation. See the documentation in the
- beginning of its source code.
- ***** The MIDI2TONES command line *****
- To convert a MIDI file called "chopin.mid" into a command bytestream, execute
-
midi2tones 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:
-
midi2tones <options> <basefilename> - Options must be specified individually, each with its own "-" lead-in, and separated
- with spaces. A forward slash "/" can be used instead of a dash "-" for option lead-ins.
- The
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
.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:
- -on Generate output format "n".
-
Two formats are available: -
1: The Playtune format (which is the default if this option isn't given). -
2: The frequency/duration pair format, as used by ArduboyTones. - -v Add velocity (volume) information to the output bytestream.
- -vn For the alternate format, "n" specifies the minimum velocity value that will
-
produce a high volume tone. Without this option all tones will be -
normal volume. - -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
.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 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
.log file. - -lg Log output bytestream generation information to the
.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. -
For the alternate output format, only the lowest bit will be used to specify -
the single channel to be processed, and without this option channel 0 will -
be used. - -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.
- -fx For the alternate output format, instead of using defined note names,
-
output actual frequency values in decimal format depending on "x": -
-fa: For high volume notes use format "<freq>+TONE_HIGH_VOLUME". -
-fb: For high volume notes just add 0x8000 to the frequency value. - -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. Will be generated if
-
the -r option was given. - 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. - ***** The alternate frequency/duration pair output format *****
- The generated stream is a series of frequency/duration value pairs. The frequency
- is in Hz and the duration is in milliseconds. Each value is 16 bits. For a binary
- file the values are stored high byte first. The ArduboyTones player supports
- frequencies from 16 Hz to 32767 Hz but MIDI2TONES converts MIDI note numbers in the
- range from note 12 (16.352 Hz rounded to 16 Hz) to note 127 (12543.9 Hz rounded
- to 12544 Hz).
- Periods of silence are represented by a frequency/duration pair with a frequency
- value of 0.
- Since the output is monotonic, only one MIDI channel is processed. The lowest bit
- set in the -cn option's mask will indicate the channel to be used. If the -cn option
- isn't given, channel 0 will be used.
- Tones can be specified to play at either normal or high volume. High volume is
- indicated by setting the high bit of the frequency value (i.e. adding 0x8000 to the
- desired frequency). A note will be set to high volume if the -vn option is used and
- the MIDI velocity of the note is equal to or greater than the option value.
- For the C output format, frequencies will be output as note names, as defined in the
- ArduboyTones library's ArduboyTonesPitches.h file. If the -f option is given,
- the actual frequency, in decimal, will be used instead. Durations will be output
- in decimal.
- Output files are terminated with a single 16 bit value of 0x8000 to indicate
- end of score - stop playing. A file can instead be terminated with 0x8001 to indicate
- end of score - start playing again from the beginning, which is specified using the
- -r option.
- Len Shustek, 4 Feb 2011 and later.
- Frequency/duration pair output format and other changes:
- Scott Allen, 27 Sept 2016 and later. *********************************************************************************************/