Midifile access for Ruby

— Updated November 2014 —

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:

The script itself (self contained — install anywhere in your Ruby library path).
Some documentation on the classes and methods in the package.
A folder with some short demos:
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.
Writes out a Format-0 (single-track) midifile from a source Format-1 (multitrack) file.
The reverse of the above -- creates a Format-1 from Format-0
A short demo of how to create a file from scratch — just builds a C-major chord.
This attempts to be a complete listing utility for General Midi files.
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.
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.
Translates selected channels of midievents to others.
Aligns all events in a file on exact divisions, to the precision desired.
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.]


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 should work under both 1.8 and 1.9.


                                Pete Goodeve
                                Berkeley, California

                e-mail: pete@GoodeveCa.NET

Programs for BeOS
My Home Page