midifile.rb

Midifile access for Ruby

— Updated May 2020 —

midifile.rb is a small library script for Ruby that provides facilities for reading and writing standard midifiles. It lets you use very simple code to read a midifile, breaking it out into elements (headers and events) in convenient form for further processing. It reads directly from the file, without storing it all in memory first.

New files can be created as well, usually by building an object in memory, adding elements as desired, and writing the complete sequence to a file at the end. 'Generator' methods are supplied for easy creation of most kinds of events. Simple alterations (such as transposing all the notes) can actually be done without building a new object — elements can be written out immediately they are read from the input.


This release fixes (further!) the rather lamebrained sorting of events done by previous versions. 'Simultaneous' events no longer get shuffled, and the occasional mistiming of the last note is fixed. It is also no longer stupidly slow.

Some minor new hooks have been added to help with handling MIDI streams as well as files

(Previously) New 'channel' accessor methods were added to the MidiItem class that work with 'user' numbering (1..16) rather than the internal 0..15 range of the 'chan' attribute, which should make it easier to avoid confusion.

There is a major change [ugghh!] to Ruby version 1.9 that prevented an earlier midifile.rb working as supplied — fixed as of 2010 August 29. See below for details. (The GMsummary example also needed a minor update for 1.9.)


The code places few restrictions on the user. It will read and write both Format 0 and Format 1 (even Format 2...) files. It is intended to be minimal yet flexible. (Which means probably that you could generate an invalid file fairly easily, but it is straightforward enough that you should be able to avoid this.)

As a taster, here is an absolutely trivial lister for "myfile.mid" (using the basic 'to_s' methods provided):

      require 'midifile.rb'
      open("myfile.mid", "r") {|f|
        mf = Midifile.new(f)
        mf.each {|elem|
          puts elem
        }
      }

The downloadable archives below contain the following:

midifile.rb
The script itself (self contained — install anywhere in your Ruby library path).
README
Some documentation on the classes and methods in the package.
EXAMPLES
A folder with some short demos:
Transpose
reads a midifile and writes a new one with all notes (except ch. 10 percussion) transposed by a desired amount. It copies the file directly without storing in memory.
SMFformat0
Writes out a Format-0 (single-track) midifile from a source Format-1 (multitrack) file.
SMFformat1
The reverse of the above -- creates a Format-1 from Format-0
makeachord
A short demo of how to create a file from scratch — just builds a C-major chord.
GMlister
This attempts to be a complete listing utility for General Midi files.
GMsummary
A modification of the above that accumulates and summarizes the events in the file rather than printing them individually. It can accept several filenames in the command line, and will list them in sequence.
SMPTEtoSMF
A utility to fill a need... Turns an "SMPTE" style header — not understood by many apps — into the more standard style with the tick division in "ticks per beat". The rest of the file is output unchanged.
ChanTran
Translates selected channels of midievents to others.
Quantize
Aligns all events in a file on exact divisions, to the precision desired.
Resustain
Replaces Sustain Pedal (Controller 64) events with suitably lengthened note durations.

[The scripts above are tailored for **ix systems, and can need trivial modification to run under Windows and others. See the README for details.]

Downloads:

You can download the package here:
midifile_rb.tgz — gzipped tar, 21 KB
midifile_rb.zip — zip archive, 31 KB

Ruby 1.9 Problems

I was notified (thanks Thomas!) that the midifile.rb written for 1.8 failed in Ruby 1.9. This was caused by a major -- and barely documented [and please note my displeasure...] -- change of philosophy in that version of Ruby. The midifile.rb module has now been updated to take account of this, and works under both 1.8 and 1.9, as well as with Ruby 2.x.

Note to Windows Users

Remember that Windows thinks every file is text by default... Midifiles are binary, so you need to edit the scripts to make them work properly. (This is mentioned in the README, but is probably worth emphasizing!) All "open(somefilename")" lines must be changed to "open(somefilename, "rb")".


Author:

                                Pete Goodeve
                                Berkeley, California

                e-mail: pete@GoodeveCa.NET
                         pete.goodeve@computer.org

Programs for BeOS
My Home Page