NAME¶
MIDI::Event - MIDI events
SYNOPSIS¶
# Dump a MIDI file's text events
die "No filename" unless @ARGV;
use MIDI; # which "use"s MIDI::Event;
MIDI::Opus->new( {
"from_file" => $ARGV[0],
"exclusive_event_callback" => sub{print "$_[2]\n"},
"include" => \@MIDI::Event::Text_events
} ); # These options percolate down to MIDI::Event::decode
exit;
DESCRIPTION¶
Functions and lists to do with with MIDI events and MIDI event structures.
An event is a list, like:
( 'note_on', 141, 4, 50, 64 )
where the first element is the event name, the second is the delta-time, and the
remainder are further parameters, per the event-format specifications below.
An
event structure is a list of references to such events -- a
"LoL". If you don't know how to deal with LoLs, you
must read
perllol.
GOODIES¶
For your use in code (as in the code in the Synopsis), this module provides a
few lists:
- @MIDI_events
- a list of all "MIDI events" AKA voice events -- e.g.,
'note_on'
- @Text_events
- a list of all text meta-events -- e.g., 'track_name'
- @Nontext_meta_events
- all other meta-events (plus 'raw_data' and F-series events like
'tune_request').
- @Meta_events
- the combination of Text_events and Nontext_meta_events.
- @All_events
- the combination of all the above lists.
FUNCTIONS¶
This module provides three functions of interest, which all act upon event
structures. As an end user, you probably don't need to use any of these
directly, but note that options you specify for MIDI::Opus->new with a
from_file or from_handle options will percolate down to these functions; so
you should understand the options for the first two of the below functions.
(The casual user should merely skim this section.)
- MIDI::Event::decode( \$data, { ...options... } )
- This takes a reference to binary MIDI data and decodes it into a
new event structure (a LoL), a reference to which is returned.
Options are:
- 'include' => LISTREF
- If specified, listref is interpreted as a reference to a list of
event names (e.g., 'cue_point' or 'note_off') such that only these events
will be parsed from the binary data provided. Events whose names are NOT
in this list will be ignored -- i.e., they won't end up in the event
structure, and they won't be each passed to any callbacks you may have
specified.
- 'exclude' => LISTREF
- If specified, listref is interpreted as a reference to a list of
event names (e.g., 'cue_point' or 'note_off') that will NOT be parsed from
the binary stream; they'll be ignored -- i.e., they won't end up in the
event structure, and they won't be passed to any callbacks you may have
specified. Don't specify both an include and an exclude list. And if you
specify neither, all events will be decoded -- this is what you
probably want most of the time. I've created this include/exclude
functionality mainly so you can scan a file rather efficiently for just a
few specific event types, e.g., just text events, or just sysexes.
- 'no_eot_magic' => 0 or 1
- See the description of 'end_track', in "EVENTS", below.
- 'event_callback' => CODEREF
- If defined, the code referred to (whether as "\&wanted" or
as "sub { BLOCK }") is called on every event after it's been
parsed into an event list (and any EOT magic performed), but before it's
added to the event structure. So if you want to alter the event stream on
the way to the event structure (which counts as deep voodoo), define
'event_callback' and have it modify its @_.
- 'exclusive_event_callback' => CODEREF
- Just like 'event_callback'; but if you specify this, the callback is
called instead of adding the events to the event structure. (So the
event structure returned by decode() at the end will always be
empty.) Good for cases like the text dumper in the Synopsis, above.
- MIDI::Event::encode( \@events, {...options...})
- This takes a reference to an event structure (a LoL) and encodes it
as binary data, which it returns a reference to. Options:
- 'unknown_callback' => CODEREF
- If this is specified, it's interpreted as a reference to a subroutine to
be called when an unknown event name (say, 'macro_10' or something), is
seen by encode(). The function is fed all of the event (its name,
delta-time, and whatever parameters); the return value of this function is
added to the encoded data stream -- so if you don't want to add anything,
be sure to return ''.
If no 'unknown_callback' is specified, encode() will "warn"
(well, "carp") of the unknown event. To merely block that, just
set 'unknown_callback' to "sub{return('')}"
- 'no_eot_magic' => 0 or 1
- Determines whether a track-final 0-length text event is encoded as a
end-track event -- since a track-final 0-length text event probably
started life as an end-track event read in by decode(), above.
- 'never_add_eot' => 0 or 1
- If 1, "encode()" never ever adds an end-track (EOT) event
to the encoded data generated unless it's explicitly there as an
'end_track' in the given event structure. You probably don't ever need
this unless you're encoding for straight writing to a MIDI port,
instead of to a file.
- 'no_running_status' => 0 or 1
- If 1, disables MIDI's "running status" compression. Probably
never necessary unless you need to feed your MIDI data to a strange old
sequencer that doesn't understand running status.
Note: If you're encoding just a single event at a time or less than a whole
trackful in any case, then you probably want something like:
$data_r = MIDI::Event::encode(
[
[ 'note_on', 141, 4, 50, 64 ]
],
{ 'never_add_eot' => 1} );
which just encodes that one event
as an event structure of one event --
i.e., an LoL that's just a list of one list.
But note that running status will not always apply when you're encoding less
than a whole trackful at a time, since running status works only within a LoL
encoded all at once. This'll result in non-optimally compressed, but still
effective, encoding.
- MIDI::Event::copy_structure()
- This takes a reference to an event structure, and returns a
reference to a copy of it. If you're thinking about using this, you
probably should want to use the more straightforward
$track2 = $track->copy
instead. But it's here if you happen to need it.
EVENTS AND THEIR DATA TYPES¶
DATA TYPES
Events use these data types:
- channel = a value 0 to 15
- note = a value 0 to 127
- dtime = a value 0 to 268,435,455 (0x0FFFFFFF)
- velocity = a value 0 to 127
- channel = a value 0 to 15
- patch = a value 0 to 127
- sequence = a value 0 to 65,535 (0xFFFF)
- text = a string of 0 or more bytes of of ASCII text
- raw = a string of 0 or more bytes of binary data
- pitch_wheel = a value -8192 to 8191 (0x1FFF)
- song_pos = a value 0 to 16,383 (0x3FFF)
- song_number = a value 0 to 127
- tempo = microseconds, a value 0 to 16,777,215 (0x00FFFFFF)
For data types not defined above, (e.g.,
sf and
mi for
'key_signature'), consult MIDI::Filespec and/or the source for
"MIDI::Event.pm". And if you don't see it documented, it's probably
because I don't understand it, so you'll have to consult a real MIDI
reference.
EVENTS
And these are the events:
- ('note_off', dtime, channel, note,
velocity)
- ('note_on', dtime, channel, note,
velocity)
- ('key_after_touch', dtime, channel, note,
velocity)
- ('control_change', dtime, channel, controller(0-127),
value(0-127))
- ('patch_change', dtime, channel, patch)
- ('channel_after_touch', dtime, channel,
velocity)
- ('pitch_wheel_change', dtime, channel,
pitch_wheel)
- ('set_sequence_number', dtime, sequence)
- ('text_event', dtime, text)
- ('copyright_text_event', dtime, text)
- ('track_name', dtime, text)
- ('instrument_name', dtime, text)
- ('lyric', dtime, text)
- ('marker', dtime, text)
- ('cue_point', dtime, text)
- ('text_event_08', dtime, text)
- ('text_event_09', dtime, text)
- ('text_event_0a', dtime, text)
- ('text_event_0b', dtime, text)
- ('text_event_0c', dtime, text)
- ('text_event_0d', dtime, text)
- ('text_event_0e', dtime, text)
- ('text_event_0f', dtime, text)
- ('end_track', dtime)
- ('set_tempo', dtime, tempo)
- ('smpte_offset', dtime, hr, mn, se, fr,
ff)
- ('time_signature', dtime, nn, dd, cc,
bb)
- ('key_signature', dtime, sf, mi)
- ('sequencer_specific', dtime, raw)
- ('raw_meta_event', dtime, command(0-255), raw)
- ('sysex_f0', dtime, raw)
- ('sysex_f7', dtime, raw)
- ('song_position', dtime)
- ('song_select', dtime, song_number)
- ('tune_request', dtime)
- ('raw_data', dtime, raw)
Three of the above events are represented a bit oddly from the point of view of
the file spec:
The parameter
pitch_wheel for 'pitch_wheel_change' is a value -8192 to
8191, although the actual encoding of this is as a value 0 to 16,383, as per
the spec.
Sysex events are represented as either 'sysex_f0' or 'sysex_f7', depending on
the status byte they are encoded with.
'end_track' is a bit stranger, in that it is almost never actually found, or
needed. When the MIDI decoder sees an EOT (i.e., an end-track status: FF 2F
00) with a delta time of 0, it is
ignored! If in the unlikely event
that it has a nonzero delta-time, it's decoded as a 'text_event' with whatever
that delta-time is, and a zero-length text parameter. (This happens before the
'event_callback' or 'exclusive_event_callback' callbacks are given a crack at
it.) On the encoding side, an EOT is added to the end of the track as a normal
part of the encapsulation of track data.
I chose to add this special behavior so that you could add events to the end of
a track without having to work around any track-final 'end_track' event.
However, if you set "no_eot_magic" as a decoding parameter, none of
this magic happens on the decoding side -- 'end_track' is decoded just as it
is.
And if you set "no_eot_magic" as an encoding parameter, then a
track-final 0-length 'text_event' with non-0 delta-times is left as is.
Normally, such an event would be converted from a 'text_event' to an
'end_track' event with thath delta-time.
Normally, no user needs to use the "no_eot_magic" option either in
encoding or decoding. But it is provided in case you need your event LoL to be
an absolutely literal representation of the binary data, and/or vice versa.
MIDI BNF¶
For your reference (if you can make any sense of it), here is a copy of the MIDI
BNF, as I found it in a text file that's been floating around the Net since
the late 1980s.
Note that this seems to describe MIDI events as they can occur in
MIDI-on-the-wire. I
think that realtime data insertion (i.e., the
ability to have <realtime byte>s popping up in the
middle of
messages) is something that can't happen in MIDI files.
In fact, this library, as written,
can't correctly parse MIDI data that
has such realtime bytes inserted in messages. Nor does it support representing
such insertion in a MIDI event structure that's encodable for writing to a
file. (Although you could theoretically represent events with embedded
<realtime byte>s as just "raw_data" events; but then, you can
always stow anything at all in a "raw_data" event.)
1. <MIDI Stream> ::= <MIDI msg> < MIDI Stream>
2. <MIDI msg> ::= <sys msg> ⎪ <chan msg>
3. <chan msg> ::= <chan 1byte msg> ⎪
⎪ <chan 2byte msg>
4. <chan 1byte msg> ::= <chan stat1 byte> <data singlet>
<running singlets>
5. <chan 2byte msg> ::= <chan stat2 byte> <data pair>
<running pairs>
6. <chan stat1 byte> ::= <chan voice stat1 nibble>
<hex nibble>
7. <chan stat2 byte> ::= <chan voice stat2 nibble>
<hex nibble>
8. <chan voice stat1 nyble>::= C ⎪ D
9. <chan voice stat2 nyble>::= 8 ⎪ 9 ⎪ A ⎪ B ⎪ E
10. <hex nyble> ::= 0 ⎪ 1 ⎪ 2 ⎪ 3 ⎪ 4 ⎪ 5 ⎪ 6 ⎪ 7 ⎪
⎪ 8 ⎪ 9 ⎪ A ⎪ B ⎪ C ⎪ D ⎪ E ⎪ F
11. <data pair> ::= <data singlet> <data singlet>
12. <data singlet> ::= <realtime byte> <data singlet> ⎪
⎪ <data byte>
13. <running pairs> ::= <empty> ⎪ <data pair> <running pairs>
14. <running singlets> ::= <empty> ⎪
⎪ <data singlet> <running singlets>
15. <data byte> ::= <data MSD> <hex nyble>
16. <data MSD> ::= 0 ⎪ 1 ⎪ 2 ⎪ 3 ⎪ 4 ⎪ 5 ⎪ 6 ⎪ 7
17. <realtime byte> ::= F8 ⎪ FA ⎪ FB ⎪ FC ⎪ FE ⎪ FF
18. <sys msg> ::= <sys common msg> ⎪
⎪ <sysex msg> ⎪
⎪ <sys realtime msg>
19. <sys realtime msg> ::= <realtime byte>
20. <sysex msg> ::= <sysex data byte>
<data singlet> <running singlets>
<eox byte>
21. <sysex stat byte> ::= F0
22. <eox byte> ::= F7
23. <sys common msg> ::= <song position msg> ⎪
⎪ <song select msg> ⎪
⎪ <tune request>
24. <tune request> ::= F6
25. <song position msg> ::= <song position stat byte>
<data pair>
26. <song select msg> ::= <song select stat byte>
<data singlet>
27. <song position stat byte>::=F2
28. <song select stat byte> ::= F3
COPYRIGHT¶
Copyright (c) 1998-2002 Sean M. Burke. All rights reserved.
This library is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.
AUTHOR¶
Sean M. Burke "sburke@cpan.org" (Except the BNF -- who knows who's
behind that.)