midi2tones icon indicating copy to clipboard operation
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. *********************************************************************************************/