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

NAME

MIDI::Segment - means to segment MIDI by equal duration

SYNOPSIS

  use MIDI;
  use MIDI::Segment;

  my $opus = MIDI::Opus->new( { from_file => 'cowbell.midi' } );

  my ( $mis, $durations ) = MIDI::Segment->new($opus);
  die "not possible to split equally" unless @$durations;

  for my $dur (@$durations) {
    my $segments = $mis->split($dur);
    warn "duration $dur has " . scalar(@$segments) . " segments\n";
    for my $seg (@$segments) {
      # deal with @$seg which are array references for each track that
      # in turn contain some number of MIDI::Event arrays ...
    }
  }

See also eg/melody-shuffle.

DESCRIPTION

This module provides a means to split MIDI::Opus into MIDI::Event segments of equal duration, assuming that is possible. Typical uses would be to display the possible segments or to shuffle them into a new composition with e.g. the shuffle call in List::Util.

MIDI does not contain durations; the dtime or "delta time" of the last note_on event of track may be 0; if that note_on is the last event of the track then the duration of that note is unknown. Also MIDI tracks may be of different durations. These cases are not handled by this module; the user will need to alter the MIDI so that the tracks are of equal duration and the last note_on events have a suitable dtime set. MIDI::Event may be helpful to study if this paragraph did not make much sense, and inspecting the contents of MIDI files with eg/midi-dump.

  $ perl ./eg/midi-dump t/cowbell.midi

Other problems with MIDI include that zero dtime events can be associated with either some previous or next event; worse, these might be ordered so that the control change for the future note happens prior to the off event of the previous note. This has been a long way to say that random MIDI may not segment itself cleanly.

Lilypond MIDI files in particular contain a control track that will need to be removed as this track contains no note_on events.

  my $opus = MIDI::Opus->new( { from_file => 'lilypond.midi' } );
  shift @{ $opus->tracks_r };
  my ( $mis, $durations ) = ...

METHODS

These will throw an exception if anything goes awry.

new opus

Creates a new object and performs duration calculations on the given MIDI::Opus object. Returns the object and an array reference of durations that the opus can be split on, if any.

split duration

Splits the opus into segments of the given duration, assuming that is possible. The returned array reference of segments consists of array references for each track, which in turn contain one or more MIDI event array references.

BUGS

Probably, given the lack of real world MIDI that has been thrown at the code.

SEE ALSO

MIDI, MIDI::Ngram, MIDI::Util

COPYRIGHT AND LICENSE

Copyright 2023 Jeremy Mates

This program is distributed under the (Revised) BSD License: https://opensource.org/licenses/BSD-3-Clause