README

MIDI::Make

A Raku module to make MIDI files.

Installation

You can install MIDI::Make using Zef.

➤ zef install MIDI::Make

Import

use MIDI::Make;

Usage

MIDI::Make works by creating the File class and then populating it with zero or more tracks created using the Track class. The resulting MIDI information can be outputed using the File class's render method.

The File class

The File class is used to store and modify MIDI information in order to create a MIDI file. It has some optional parameters, the add-track method to add tracks, and the render method to output the MIDI information created up to that point.

    # Instantiating without parameters.
my $f = File.new;

Parameters

Parameters can be set on instantiation, or anytime afterwards.

format

The format parameter specifies the type of MIDI file format to use.

It can have three values: 0, 1, or 2. The default is 1.

  • 0 - All data is merged on a single track.

  • 1 - Tracks are separated, and played together.

  • 2 - Tracks are separated, and played one after the other.

    # Set on instantiation.
my $f = File.new(:format(0));
    # Set after instantiation.
my $f = File.new;
$f.format: 0;

time-division

The time-division parameter defines how MIDI time will be divided.

It can have two values: quarter for quarter notes, and frame. The default is quarter.

    # Set on instantiation.
my $f = File.new(:time-division('frame'));
    # Set after instantiation.
my $f = File.new;
$f.time-division: 'frame';

PPQ (pulses per quarter note)

The PPQ parameter sets the pulses per quarter note of the time-division parameter when the latter is set to quarter. If time-division is set to frame, PPQ is ignored.

The PPQ value is from 0 to 32767. The default is 48.

    # Set on instantiation.
my $f = File.new(:PPQ(96));
    # Set after instantiation.
my $f = File.new;
$f.PPQ: 96;

FPS (frames per second)

The FPS parameter sets the frames per second of the time-division parameter when the latter is set to frame. If time-division is set to quarter, FPS is ignored.

FPS can have four values: 24, 25, 29.97, or 30. The default is 24.

    # Set on instantiation.
my $f = File.new(:time-division('frame'), :FPS(30));
    # Set after instantiation.
my $f = File.new;
$f.time-division: 'frame';
$f.FPS: 30;

PPF (pulses per frame)

The PPF parameter sets the pulses per frame of the time-division parameter when the latter is set to frame. If time-division is set to quarter, PPF is ignored.

The PPF value is from 0 to 255. The default is 4.

    # Set on instantiation.
my $f = File.new(:time-division('frame'), :PPF(8));
    # Set after instantiation.
my $f = File.new;
$f.time-division: 'frame';
$f.PPF: 8;

Methods

add-track

The add-track method accepts a rendered track, and adds it to the File class.

    # Create a track.
my $t = Track.new;
$t.note-on:  60;
$t.dt:           100;
$t.note-off: 60;

    # Add it to the File class.
my $f = File.new;
$f.add-track($t.render);

render

The render method renders the MIDI file information gathered up to that point.

my $f = File.new;
say $f.render;

Operators

MIDI::Make creates two operators that serve as helpers for the Track class described below.

The quarter notes per minute operator transforms quarter notes per minute to microseconds per quarter note.

This permits specifying tempo in a musical human-readable way.

    # 60 QPM using microseconds per quarter note.
$t.tempo: 1000000;

    # 60 QPM using the MIDI::Make operator.
$t.tempo: ♩60;

\

The time-signature operator is used to specify a time-signature for the Track class's time method.

$t.time: 3\8;

The Track class

The Track class is used to create a MIDI track which can then be added to the File class.

    # Instantiating without parameters.
my $t = Track.new;

Parameters

Parameters can be set on instantiation, or anytime afterwards.

name

The name parameter lets you set the track's name using ASCII characters.

    # Set on instantiation.
my $t = Track.new(:name('piano'));
    # Set after instantiation.
my $t = Track.new;
$t.name: 'piano';

dt

Delta time (dt) sets the time in MIDI pulses between MIDI events.

The dt value is from O to 268435455. The default is 0.

Note: Although it's possible to instantiate dt to a value other than 0, usually you will start a MIDI file with a MIDI event, and not a period of time.

    # Set on instantiation.
my $t = Track.new(:dt(100));
    # Set after instantiation.
my $t = Track.new;
$t.dt: 100;

dt is automatically set to 0 after each of the MIDI events implemented in the Track class: tempo, time, note-off, and note-on. This is done so that you can enter many MIDI events consecutively before setting a new dt.

my $t = Track.new;
$t.note-on:  60;
$t.dt:          100; # Wait 100 MIDI pulses before subsequent events.
$t.note-off: 60;
$t.note-on:  62;
$t.note-on:  64;
$t.dt:          200; # Wait 200 MIDI pulses before subsequent events.
$t.note-off: 62;
$t.note-off: 64;

ch

Channel (ch) sets the MIDI channel to use.

The ch value is from 0 to 15. The default is 0.

    # Set on instantiation.
my $t = Track.new(:ch(1));
    # Set after instantiation.
my $t = Track.new;
$t.ch: 1;

vol_note-off

vol_note-off sets the note-off volume.

The vol_note-off value is from 0 to 127. The default is 0.

Note: A volume for a note-off seems weird, but it can change the sound on certain instruments like an organ on which notes can be depressed at different speeds.

    # Set on instantiation.
my $t = Track.new(:vol_note-off(10));
    # Set after instantiation.
my $t = Track.new;
$t.vol_note-off: 10;

vol_note-on

vol_note-on sets the note-on volume.

The vol_note-on value is from 0 to 127. The default is 0.

    # Set on instantiation.
my $t = Track.new(:vol_note-on(60));
    # Set after instantiation.
my $t = Track.new;
$t.vol_note-on: 60;

Methods

tempo

The tempo method sets the MIDI tempo. It accepts one argument: The tempo in microseconds per quarter note. You can either set it with a value from 0 to 16777215, or use the quarter notes per minute operator defined earlier in this file. The default value is 500000 which is equivalent to a tempo of 120 quarter notes per minute.

my $t = Track.new;
$t.tempo: 1000000; # Set the tempo to 60 quarter notes per minute.
$t.tempo: ♩120;    # Set the tempo to 120 quarter notes per minute.

time

The time method sets the MIDI time-signature. It accepts three optional arguments:

  1. The time-signature set using the time-signature operator defined earlier in this file. The default is 4\4.

  2. The pulses per metronome click (PPMC). This value can be from 0 to 255. The default is 24.

  3. 32nds per quarter note. This value can be from 0 to 255. The default is 8.

my $t = Track.new;
$t.time: 3/4;
$t.time: 4/4, 48;
$t.time: 2/8, 32, 12;

note-off

The note-off method creates a note off. It accepts two arguments: The note number from 0 to 127 (required), and the vol_note-off from 0 to 127 (optional). The default vol_note-off is the one set by the vol_note-off parameter. If vol_note-off is set by this note-off method, it will also set the vol_note-off parameter of the Track class for the next note-off events.

my $t = Track.new;
$t.note-off: 60;      # vol_note-off == 0
$t.note-off: 62, 120; # vol_note-off == 120
$t.note-off: 64;      # vol_note-off == 120

note-on

The note-on method creates a note on. It accepts two arguments: The note number from 0 to 127 (required), and the vol_note-on from 0 to 127 (optional). The default vol_note-on is the one set by the vol_note-on parameter. If vol_note-on is set by this note-on method, it will also set the vol_note-on parameter of the Track class for the next note-on events.

my $t = Track.new;
$t.note-on: 60;      # vol_note-on == 127
$t.note-on: 62, 100; # vol_note-on == 100
$t.note-on: 64;      # vol_note-on == 100

render

The render method renders the MIDI track information gathered up to that point. It is used to pass the track's MIDI data to the File class.

my $t = Track.new;
$t.note-on:  60;
$t.dt:           128;
$t.note-off: 60;

my $f = File.new;
$f.add-track($t.render);

Example

my $t = Track.new;
$t.name:     "piano";
$t.note-on:  60;
$t.dt:           128;
$t.time:     3\2;
$t.note-off: 60;
$t.note-on:  72;
$t.dt:           128;
$t.tempo:    ♩80;
$t.note-off: 72;

my $f = File.new(:PPQ(96));
$f.add-track($t.render);

    # Print the MIDI contents.
say $f.render;

    # Save the MIDI contents to file.
spurt 'file.mid', $f.render;

Running Tests

To run tests, simply run the following terminal command in the root of MIDI::Make.

➤ raku t/main.rakutest

Resources

MIDI::Make v0.1.0

A Raku module to make MIDI files.

Authors

  • Pierre-Emmanuel Lévesque

License

MIT

Dependencies

Test Dependencies

Provides

  • MIDI::Make

Documentation

The Camelia image is copyright 2009 by Larry Wall. "Raku" is trademark of the Yet Another Society. All rights reserved.