The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Test2::Tools::MIDI - test MIDI file contents

SYNOPSIS

  use MIDI::Simple;
  my $o = new_score;
  $o->{Score} = [];    # KLUGE clear the init text_event
  noop c9, o4;
  for (1 .. 4) { n 'qn', 'Gs' }
  write_score 'cowbell.midi';

  use Test2::Tools::MIDI;
  open my $fh, '<', 'cowbell.midi' or die "open $!\n";
  binmode $fh;
  midi_header $fh, 0, 1, 96; # format 0, 1 track, 96 ticks
  midi_track $fh, 36;
  for (1 .. 4) {
      midi_note_on  $fh,  0, 9, 56, 64;
      midi_note_off $fh, 96, 9, 56,  0;
  }
  midi_footer $fh, 0;
  midi_eof $fh;

DESCRIPTION

This module offers functions that test whether MIDI files (or an in-memory string) contain particular MIDI structures and events. See the MIDI module (among other software and hardware) for means to generate MIDI files.

Details of the MIDI protocol might be good to know. In brief, there is a midi_header structure that indicates among other things how many tracks there are. Each midi_track has a header structure and a footer event, in between which are various MIDI events of some predetermined length (including that of the footer event). Events are generally composed of a time delay (a variable length quantity, see read_vlq), followed by an event ID, followed by event specific data, if any. MIDI::Event documents the general structure of the events.

FUNCTIONS

The midi_* functions are exported by default; other utility functions are not. Various functions will confess if something goes awry, usually due to I/O errors on the MIDI file-handle.

midi_aftertouch file-handle dtime channel pitch velocity

Test that a key_after_touch event is what it should be.

midi_channel_aftertouch file-handle dtime channel velocity

Check that a MIDI channel_aftertouch is correct.

midi_control_change file-handle dtime channel controller value

Test a MIDI control change event. Note that controller may be reported as a pitch problem and value as a velocity problem due to this sharing code with midi_note_on and similar functions.

midi_eof file-handle

Test that the file-handle ends where it is expected to.

midi_header file-handle format ntracks division

Test for a MIDI header which among other things will have a particular format (0 for a single track, 1 for multiple tracks, or possibly other values), some number of tracks ntracks, and a particular division (usually a positive number of ticks such as 96).

A MIDI header is generally followed by some number of tracks (that ideally should agree with ntracks), each of which containing some number of events.

Check that there is a MIDI footer event with the given dtime (usually 0) in the file-handle. (The MIDI::Opus module hides the footer in dumps though does parse it.)

midi_note_off file-handle dtime channel pitch velocity

Check that there is a MIDI note_off event with the given details in the file-handle. See the MIDI::Event module for more documentation on the fields.

midi_note_on file-handle dtime channel pitch velocity

Like midi_note_off but checks for a slightly different MIDI code. Some software (LilyPond comes to mind) does not generate midi_note_off events but instead issues a midi_note_on with the velocity set to 0.

midi_patch file-handle dtime channel patch

Check for a patch change event with the given details.

midi_pitch_wheel file-handle dtime channel wheel

Test that a MIDI pitch wheel event is correct. The wheel is a 14-bit value split into two bytes that has an offset applied to it.

midi_skip file-handle size

Skips over size bytes in the file-handle. Good for any pesky MIDI events that are not (yet?) supported by this module.

midi_skip_dtime file-handle size

Like midi_skip but first skips over a variable length quantity, which will be of some unknown length between 1 and 4 bytes, inclusive.

  $ perl -E 'say for map { length pack w => $_ } 0, 0xFFFFFFF'
  1
  4
midi_tempo file-handle dtime tempo

Check that a MIDI tempo event with the given dtime and tempo is present.

midi_track file-handle length

Test that a MIDI track is of a certain length in bytes.

midi_text file-handle dtime text-type string

Test that there is a text event of the given text-type with the text string. text-type must be one of:

  text copyright name instrument lyric marker cue
  text8 text9 texta textb textc textd texte textf
read_vlq file-handle

Reads a variable length quantity (VLQ) from the file-handle, or failing that throws an error. VLQ are used for MIDI durations (dtime). The w template to the pack or unpack functions is a more efficient way to convert such quantities, though does not work on a file handle.

BUGS

None known. However, the module is very incomplete.

SEE ALSO

MIDI::Event, Test2::Suite

COPYRIGHT AND LICENSE

Copyright 2024 Jeremy Mates

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