The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

MIDI::Tweaks - Enhancements to MIDI.pm.

SYNOPSIS

This module implements a number of MIDI tweaks using the Sean Burke's MIDI module.

    # Read midi data.
    my $op = new MIDI::Tweaks::Opus ({ from_file => "orig.mid" });

    # Reset all volume controls.
    $_->change_volume({ value => 100 }) foreach $op->tracks;

    # Slowdown a bit.
    $op->change_tempo({ ratio => 0.9 });

    # Prepare the individual tracks.
    my $track0  = $op->tracks_r->[0];
    my $acc     = $op->tracks_r->[1]->change_velocity({ value =>  30 });
    my $solo    = $op->tracks_r->[2]->change_velocity({ value => 110 });
    my $high    = $op->tracks_r->[3]->change_velocity({ value => 100 });
    my $low     = $op->tracks_r->[4]->change_velocity({ value => 100 });

    # $low contains the middle + lower parts. Split.
    (my $mid, $low) = $low->split_hilo;

    # Produce a midi for low voice only.
    $op->tracks($track0, $acc, $low);
    $op->write_to_file("low.mid");

Warning: This module is still under development. The interface to the methods may change when new features are added.

Two scripts are provided when installing this module:

  midi-tweak: applies some tweaks to MIDI files

  midi-dump: dumps contents of a MIDI file in an understandable format

CONSTANTS

The following constants will be exported by default.

EV_TYPE

The offset in an event (array ref) of the type information.

EV_TIME

The offset in an event (array ref) of the delta time.

EV_CHAN

The offset in an event (array ref) of the channel.

EV_NOTE_PITCH

The offset in a note event of the pitch.

EV_NOTE_VELO

The offset in a note event of the velocity.

EV_MARKER_NAME

The offset in a marker event of the name.

FUNCTIONS

The following functions can be exported on demand.

MIDI::Tweaks::is_note_event

Function. Takes an event (array reference) as argument. Returns true if the event is a 'note on' or 'note off' event.

MIDI::Tweaks::is_note_on

Function. Takes an event (array reference) as argument. Returns true if the event is a 'note on' event with a non-zero velocity.

MIDI::Tweaks::is_note_off

Function. Takes an event (array reference) as argument. Returns true if the event is a 'note off' event, or a 'note on' event with zero velocity.

MIDI::Tweaks::is_channel_event

Function. Takes an event (array reference) as argument. Returns true if the event aqpplies to specific channel.

OPUS METHODS

MIDI::Tweaks::Opus::new

Method. Does whatever MIDI::Opus::new does, but checks for sanity and produces an Opus with absolute time stamps.

The options hash may contain a key require_sanity that controls the level of sanity checking:

  0:    no checking
  1:    normal checking
  warn: normal checking, but warn instead of die

MIDI::Tweaks::Opus::write_to_handle

Method. Copies the Opus, converts the time stamps to delta times and passes the result to MIDI::Opus::write_to_handle.

Note that this method is used internally by write_to_file.

MIDI::Tweaks::Opus::dump

Method. Copies the Opus, converts the time stamps to delta times and passes the result to MIDI::Opus::dump.

MIDI::Tweaks::Opus::check_sanity

Method, internal. Verifies that the MIDI data obeys certain criteria that make it suitable for tweaking. In particular, there must be a one-to-one relationship between tracks and channels.

This method is called internally by the MIDI::Tweaks::Opus::new method.

MIDI::Tweaks::Opus::delta2time

Method, internal. Modifies the Opus by changing the delta times of all events of all tracks to an absolute time value.

This method is called internally by the MIDI::Tweaks::Opus::new method.

THIS MAKES THE OPUS NO LONGER DIRECTLY VALID FOR MIDI. When this method has been applied to an Opus it should be undone later by a call to time2delta. This is handled transparently by the MIDI::Tweaks::Opus::write_to_file and MIDI::Tweaks::Opus::dump methods.

MIDI::Tweaks::Opus::time2delta

Method, internal. Modifies the Opus by making all time events relative (delta times).

This method undoes the effect of a previous delta2time, making the Opus valid MIDI data again.

This method is called internally by MIDI::Tweaks::Opus::write_to_file and MIDI::Tweaks::Opus::dump methods.

MIDI::Tweaks::Opus::change_pitch

Method. One argument, the options hash.

Modifies the pitch of the Opus.

This method just calls MIDI::Track::change_pitch on all tracks. See MIDI::Track::change_pitch for details. It skips the track associated with channel 9 which is typically associated with percussion.

MIDI::Tweaks::Opus::change_tempo

Method. One argument, the options hash.

Modifies the tempo settings of the Opus.

The options has must contain either value => number or ratio => number. In the first case, the tempo is set to the specified value (beats per minute). In the second case, the tempo is changed according to the ratio.

TRACK METHODS

MIDI::Track::name

Method. Returns the first track name as designated by an 'track name' event. If none was found, returns undef.

MIDI::Track::channel

Method. Returns the channel controlled by this track. If none was found, returns zero.

Note that channels are numbered from one, as per MIDI standard.

MIDI::Track::delta2time

Method, internal. Modifies the track by changing the delta times of all events to an absolute time value.

THIS MAKES THE TRACK NO LONGER VALID FOR MIDI. When this method has been applied to a track it should be undone later by a call to time2delta.

MIDI::Track::time2delta

Method, internal. Modifies the track by making all time events relative (delta times).

This method undoes the effect of a previous delta2time, making the track valid MIDI data again.

MIDI::Track::has_deltatime

Method, internal. Returns true if the track events have delta time stamps.

This method is not fail safe, i.e., it can return thw wrong result if a track does not have sensible events.

MIDI::Track::mapper

Method. One or two arguments. First argument is optional: an options hash. Second, or only, argument must be a code ref.

Applies to code ref to all events of the track. Returns the track (for convenience);

Note that if the code ref modifies the event, this actually modifies the track. If this is not desired, copy it first, or use copy => 1 in the options hash.

The code ref gets two arguments, the event (an array ref), and the remainder of the options hash.

Examples:

   $track->mapper(sub { print $_->[0] });
   $new = $track->mapper({ copy => 1 },
                         sub { $_->[1] += 10 });

MIDI::Track::change_pitch

Method. One argument, the options hash.

Changes the pitch of each 'note on' event according to the options.

The options has must contain int => number. The number indicates the number of half-tones the pitch should be raised. A negative number will lower the pitch. Any remaining options are passed to the mapper function.

Note that key signatures will be changed as well.

MIDI::Track::change_velocity

Method. One argument, the options hash.

Changes the velocity of each 'note on' event according to the options.

The options has must contain either value => number or ratio => number. In the first case, the velocity is set to the specified value (which must be a number between 0 and 127). In the second case, the velocity is changed according to the ratio.

Any remaining options are passed to the mapper function.

Note that setting the velocity to zero effectively turns the 'note on' events into 'note off' events.

Also note that tracks usually have an initial 'control_change' event that controls the overall volume for a channel. Use change_volume to change this setting.

MIDI::Track::change_tempo

Method. One argument, the options hash.

Changes the tempo of a trackaccording to the options.

The options has must contain either value => number or ratio => number. In the first case, each occurence of a tempo event is changed to the specified value. In the second case, the tempo is changed according to the ratio.

Any remaining options are passed to the mapper function.

Note that usually track 0 controls the tempi for an opus.

MIDI::Track::change_volume

Method. One argument, the options hash.

Changes the volume of the channel.

The options has must contain either value => number or ratio => number. In the first case, the volume is set to the specified value (which must be a number between 0 and 127). In the second case, the volume is changed according to the ratio.

Any remaining options are passed to the mapper function.

MIDI::Track::split_pitch

Method. One argument, the options hash.

The track is split into two tracks, depending on whether the pitch of a note event is lower than a preset value. Non-note events are copied to both tracks.

The options hash may contain pitch => number to specify the pitch value to split on. All notes whose pitches are less than the split value are copied to the lower track, all other notes are copied to the upper track.

Default value is 56. This is a suitable value to split a single MIDI track containing a piano part into left hand and right hand tracks.

All events are copied, and the track is not modified.

This method returns a list, the higher track and the lower track.

MIDI::Track::split_hilo

Method. No arguments.

The track is split into two tracks, high and low.

If there are two 'note on' (or 'note off') events at the same time, the event with the highest pitch gets copied to the high track and the other to the low track. If there's only one note, or if it is not a note event, it gets copied to both tracks.

All events are copied, and the track is not modified.

This method returns a list (high track, low track).

NOTE: This process assumes that if there are two notes, they start and end at the same time.

NOTE: This process discards all non-note events from the resultant tracks. Sorry.

MIDI::Track::split_hml

Method. No arguments.

The track is split into three tracks, high, middle and low.

If there are three 'note on' (or 'note off') events at the same time, the event with the highest pitch gets copied to the high track, the event with the lowest pitch gets copied to the low track, and the other to the middle track.

If there are two 'note on' (or 'note off') events at the same time, the event with the highest pitch gets copied to the high track and the other to the middle and low tracks.

If there's only one note event at that time, or if it is not a note event, it gets copied to all tracks.

All events are copied, and the track is not modified.

This method returns a list (high track, middle track, low track).

NOTE: This process assumes that if there are two or three notes, they start and end at the same time.

NOTE: This process discards all non-note events from the resultant tracks. Sorry.

AUTHOR

Johan Vromans, <jvromans at squirrel.nl>

BUGS

Please report any bugs or feature requests to bug-midi-tweaks at rt.cpan.org, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=MIDI-Tweaks. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.

SEE ALSO

MIDI, MIDI::Opus, midi-dump, midi-tweak.

SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc MIDI::Tweaks

Development of this module is hosted on GitHub: https://github.com/sciurius/perl-MIDI-Tweaks. Feel free to fork and contribute.

ACKNOWLEDGEMENTS

COPYRIGHT & LICENSE

Copyright 2008,2017 Johan Vromans, Squirrel Consultancy. All rights reserved.

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.