.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{ . if \nF \{ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "MIDI::Event 3pm" .TH MIDI::Event 3pm "2016-05-06" "perl v5.22.2" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" MIDI::Event \- MIDI events .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 9 \& # Dump a MIDI file\*(Aqs 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]\en"}, \& "include" => \e@MIDI::Event::Text_events \& } ); # These options percolate down to MIDI::Event::decode \& exit; .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" Functions and lists to do with \s-1MIDI\s0 events and \s-1MIDI\s0 event structures. .PP An event is a list, like: .PP .Vb 1 \& ( \*(Aqnote_on\*(Aq, 141, 4, 50, 64 ) .Ve .PP 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. .PP An \fIevent structure\fR is a list of references to such events \*(-- a \&\*(L"LoL\*(R". If you don't know how to deal with LoLs, you \fImust\fR read perllol. .SH "GOODIES" .IX Header "GOODIES" For your use in code (as in the code in the Synopsis), this module provides a few lists: .ie n .IP "@MIDI_events" 4 .el .IP "\f(CW@MIDI_events\fR" 4 .IX Item "@MIDI_events" a list of all \*(L"\s-1MIDI\s0 events\*(R" \s-1AKA\s0 voice events \*(-- e.g., 'note_on' .ie n .IP "@Text_events" 4 .el .IP "\f(CW@Text_events\fR" 4 .IX Item "@Text_events" a list of all text meta-events \*(-- e.g., 'track_name' .ie n .IP "@Nontext_meta_events" 4 .el .IP "\f(CW@Nontext_meta_events\fR" 4 .IX Item "@Nontext_meta_events" all other meta-events (plus 'raw_data' and F\-series events like \&'tune_request'). .ie n .IP "@Meta_events" 4 .el .IP "\f(CW@Meta_events\fR" 4 .IX Item "@Meta_events" the combination of Text_events and Nontext_meta_events. .ie n .IP "@All_events" 4 .el .IP "\f(CW@All_events\fR" 4 .IX Item "@All_events" the combination of all the above lists. .SH "FUNCTIONS" .IX Header "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.) .IP "MIDI::Event::decode( \e$data, { ...options... } )" 4 .IX Item "MIDI::Event::decode( $data, { ...options... } )" This takes a \fIreference\fR to binary \s-1MIDI\s0 data and decodes it into a new event structure (a LoL), a \fIreference\fR to which is returned. Options are: .RS 4 .IP "'include' => \s-1LISTREF\s0" 16 .IX Item "'include' => LISTREF" \&\fIIf specified\fR, 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 \s-1NOT\s0 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. .IP "'exclude' => \s-1LISTREF\s0" 16 .IX Item "'exclude' => LISTREF" \&\fIIf specified\fR, listref is interpreted as a reference to a list of event names (e.g., 'cue_point' or 'note_off') that will \s-1NOT\s0 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 \fIneither\fR, 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. .IP "'no_eot_magic' => 0 or 1" 16 .IX Item "'no_eot_magic' => 0 or 1" See the description of \f(CW\*(Aqend_track\*(Aq\fR, in \*(L"\s-1EVENTS\*(R",\s0 below. .IP "'event_callback' => \s-1CODEREF\s0" 16 .IX Item "'event_callback' => CODEREF" If defined, the code referred to (whether as \f(CW\*(C`\e&wanted\*(C'\fR or as \&\f(CW\*(C`sub { BLOCK }\*(C'\fR) is called on every event after it's been parsed into an event list (and any \s-1EOT\s0 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 \f(CW@_\fR. .IP "'exclusive_event_callback' => \s-1CODEREF\s0" 16 .IX Item "'exclusive_event_callback' => CODEREF" Just like 'event_callback'; but if you specify this, the callback is called \fIinstead\fR of adding the events to the event structure. (So the event structure returned by \fIdecode()\fR at the end will always be empty.) Good for cases like the text dumper in the Synopsis, above. .RE .RS 4 .RE .IP "MIDI::Event::encode( \e@events, {...options...})" 4 .IX Item "MIDI::Event::encode( @events, {...options...})" This takes a \fIreference\fR to an event structure (a LoL) and encodes it as binary data, which it returns a \fIreference\fR to. Options: .RS 4 .IP "'unknown_callback' => \s-1CODEREF\s0" 16 .IX Item "'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 \fIencode()\fR. 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 ''. .Sp If no 'unknown_callback' is specified, \fIencode()\fR will \f(CW\*(C`warn\*(C'\fR (well, \&\f(CW\*(C`carp\*(C'\fR) of the unknown event. To merely block that, just set \&'unknown_callback' to \f(CW\*(C`sub{return(\*(Aq\*(Aq)}\*(C'\fR .IP "'no_eot_magic' => 0 or 1" 16 .IX Item "'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 \fIdecode()\fR, above. .IP "'never_add_eot' => 0 or 1" 16 .IX Item "'never_add_eot' => 0 or 1" If 1, \f(CW\*(C`encode()\*(C'\fR never ever \fIadds\fR an end-track (\s-1EOT\s0) event to the encoded data generated unless it's \fIexplicitly\fR there as an \&'end_track' in the given event structure. You probably don't ever need this unless you're encoding for \fIstraight\fR writing to a \s-1MIDI\s0 port, instead of to a file. .IP "'no_running_status' => 0 or 1" 16 .IX Item "'no_running_status' => 0 or 1" If 1, disables \s-1MIDI\s0's \*(L"running status\*(R" compression. Probably never necessary unless you need to feed your \s-1MIDI\s0 data to a strange old sequencer that doesn't understand running status. .RE .RS 4 .Sp 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: .Sp .Vb 5 \& $data_r = MIDI::Event::encode( \& [ \& [ \*(Aqnote_on\*(Aq, 141, 4, 50, 64 ] \& ], \& { \*(Aqnever_add_eot\*(Aq => 1} ); .Ve .Sp which just encodes that one event \fIas\fR an event structure of one event \*(-- i.e., an LoL that's just a list of one list. .Sp 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. .RE .IP "\fIMIDI::Event::copy_structure()\fR" 4 .IX Item "MIDI::Event::copy_structure()" This takes a \fIreference\fR to an event structure, and returns a \&\fIreference\fR to a copy of it. If you're thinking about using this, you probably should want to use the more straightforward .Sp .Vb 1 \& $track2 = $track\->copy .Ve .Sp instead. But it's here if you happen to need it. .SH "EVENTS AND THEIR DATA TYPES" .IX Header "EVENTS AND THEIR DATA TYPES" .SS "\s-1DATA TYPES\s0" .IX Subsection "DATA TYPES" Events use these data types: .IP "channel = a value 0 to 15" 4 .IX Item "channel = a value 0 to 15" .PD 0 .IP "note = a value 0 to 127" 4 .IX Item "note = a value 0 to 127" .IP "dtime = a value 0 to 268,435,455 (0x0FFFFFFF)" 4 .IX Item "dtime = a value 0 to 268,435,455 (0x0FFFFFFF)" .IP "velocity = a value 0 to 127" 4 .IX Item "velocity = a value 0 to 127" .IP "channel = a value 0 to 15" 4 .IX Item "channel = a value 0 to 15" .IP "patch = a value 0 to 127" 4 .IX Item "patch = a value 0 to 127" .IP "sequence = a value 0 to 65,535 (0xFFFF)" 4 .IX Item "sequence = a value 0 to 65,535 (0xFFFF)" .IP "text = a string of 0 or more bytes of of \s-1ASCII\s0 text" 4 .IX Item "text = a string of 0 or more bytes of of ASCII text" .IP "raw = a string of 0 or more bytes of binary data" 4 .IX Item "raw = a string of 0 or more bytes of binary data" .IP "pitch_wheel = a value \-8192 to 8191 (0x1FFF)" 4 .IX Item "pitch_wheel = a value -8192 to 8191 (0x1FFF)" .IP "song_pos = a value 0 to 16,383 (0x3FFF)" 4 .IX Item "song_pos = a value 0 to 16,383 (0x3FFF)" .IP "song_number = a value 0 to 127" 4 .IX Item "song_number = a value 0 to 127" .IP "tempo = microseconds, a value 0 to 16,777,215 (0x00FFFFFF)" 4 .IX Item "tempo = microseconds, a value 0 to 16,777,215 (0x00FFFFFF)" .PD .PP For data types not defined above, (e.g., \fIsf\fR and \fImi\fR for \&\f(CW\*(Aqkey_signature\*(Aq\fR), consult MIDI::Filespec and/or the source for \&\f(CW\*(C`MIDI::Event.pm\*(C'\fR. 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 \s-1MIDI\s0 reference. .SS "\s-1EVENTS\s0" .IX Subsection "EVENTS" And these are the events: .IP "('note_off', \fIdtime\fR, \fIchannel\fR, \fInote\fR, \fIvelocity\fR)" 4 .IX Item "('note_off', dtime, channel, note, velocity)" .PD 0 .IP "('note_on', \fIdtime\fR, \fIchannel\fR, \fInote\fR, \fIvelocity\fR)" 4 .IX Item "('note_on', dtime, channel, note, velocity)" .IP "('key_after_touch', \fIdtime\fR, \fIchannel\fR, \fInote\fR, \fIvelocity\fR)" 4 .IX Item "('key_after_touch', dtime, channel, note, velocity)" .IP "('control_change', \fIdtime\fR, \fIchannel\fR, \fIcontroller(0\-127)\fR, \fIvalue(0\-127)\fR)" 4 .IX Item "('control_change', dtime, channel, controller(0-127), value(0-127))" .IP "('patch_change', \fIdtime\fR, \fIchannel\fR, \fIpatch\fR)" 4 .IX Item "('patch_change', dtime, channel, patch)" .IP "('channel_after_touch', \fIdtime\fR, \fIchannel\fR, \fIvelocity\fR)" 4 .IX Item "('channel_after_touch', dtime, channel, velocity)" .IP "('pitch_wheel_change', \fIdtime\fR, \fIchannel\fR, \fIpitch_wheel\fR)" 4 .IX Item "('pitch_wheel_change', dtime, channel, pitch_wheel)" .IP "('set_sequence_number', \fIdtime\fR, \fIsequence\fR)" 4 .IX Item "('set_sequence_number', dtime, sequence)" .IP "('text_event', \fIdtime\fR, \fItext\fR)" 4 .IX Item "('text_event', dtime, text)" .IP "('copyright_text_event', \fIdtime\fR, \fItext\fR)" 4 .IX Item "('copyright_text_event', dtime, text)" .IP "('track_name', \fIdtime\fR, \fItext\fR)" 4 .IX Item "('track_name', dtime, text)" .IP "('instrument_name', \fIdtime\fR, \fItext\fR)" 4 .IX Item "('instrument_name', dtime, text)" .IP "('lyric', \fIdtime\fR, \fItext\fR)" 4 .IX Item "('lyric', dtime, text)" .IP "('marker', \fIdtime\fR, \fItext\fR)" 4 .IX Item "('marker', dtime, text)" .IP "('cue_point', \fIdtime\fR, \fItext\fR)" 4 .IX Item "('cue_point', dtime, text)" .IP "('text_event_08', \fIdtime\fR, \fItext\fR)" 4 .IX Item "('text_event_08', dtime, text)" .IP "('text_event_09', \fIdtime\fR, \fItext\fR)" 4 .IX Item "('text_event_09', dtime, text)" .IP "('text_event_0a', \fIdtime\fR, \fItext\fR)" 4 .IX Item "('text_event_0a', dtime, text)" .IP "('text_event_0b', \fIdtime\fR, \fItext\fR)" 4 .IX Item "('text_event_0b', dtime, text)" .IP "('text_event_0c', \fIdtime\fR, \fItext\fR)" 4 .IX Item "('text_event_0c', dtime, text)" .IP "('text_event_0d', \fIdtime\fR, \fItext\fR)" 4 .IX Item "('text_event_0d', dtime, text)" .IP "('text_event_0e', \fIdtime\fR, \fItext\fR)" 4 .IX Item "('text_event_0e', dtime, text)" .IP "('text_event_0f', \fIdtime\fR, \fItext\fR)" 4 .IX Item "('text_event_0f', dtime, text)" .IP "('end_track', \fIdtime\fR)" 4 .IX Item "('end_track', dtime)" .IP "('set_tempo', \fIdtime\fR, \fItempo\fR)" 4 .IX Item "('set_tempo', dtime, tempo)" .IP "('smpte_offset', \fIdtime\fR, \fIhr\fR, \fImn\fR, \fIse\fR, \fIfr\fR, \fIff\fR)" 4 .IX Item "('smpte_offset', dtime, hr, mn, se, fr, ff)" .IP "('time_signature', \fIdtime\fR, \fInn\fR, \fIdd\fR, \fIcc\fR, \fIbb\fR)" 4 .IX Item "('time_signature', dtime, nn, dd, cc, bb)" .IP "('key_signature', \fIdtime\fR, \fIsf\fR, \fImi\fR)" 4 .IX Item "('key_signature', dtime, sf, mi)" .IP "('sequencer_specific', \fIdtime\fR, \fIraw\fR)" 4 .IX Item "('sequencer_specific', dtime, raw)" .IP "('raw_meta_event', \fIdtime\fR, \fIcommand\fR(0\-255), \fIraw\fR)" 4 .IX Item "('raw_meta_event', dtime, command(0-255), raw)" .IP "('sysex_f0', \fIdtime\fR, \fIraw\fR)" 4 .IX Item "('sysex_f0', dtime, raw)" .IP "('sysex_f7', \fIdtime\fR, \fIraw\fR)" 4 .IX Item "('sysex_f7', dtime, raw)" .IP "('song_position', \fIdtime\fR)" 4 .IX Item "('song_position', dtime)" .IP "('song_select', \fIdtime\fR, \fIsong_number\fR)" 4 .IX Item "('song_select', dtime, song_number)" .IP "('tune_request', \fIdtime\fR)" 4 .IX Item "('tune_request', dtime)" .IP "('raw_data', \fIdtime\fR, \fIraw\fR)" 4 .IX Item "('raw_data', dtime, raw)" .PD .PP Three of the above events are represented a bit oddly from the point of view of the file spec: .PP The parameter \fIpitch_wheel\fR for \f(CW\*(Aqpitch_wheel_change\*(Aq\fR is a value \&\-8192 to 8191, although the actual encoding of this is as a value 0 to 16,383, as per the spec. .PP Sysex events are represented as either \f(CW\*(Aqsysex_f0\*(Aq\fR or \f(CW\*(Aqsysex_f7\*(Aq\fR, depending on the status byte they are encoded with. .PP \&\f(CW\*(Aqend_track\*(Aq\fR is a bit stranger, in that it is almost never actually found, or needed. When the \s-1MIDI\s0 decoder sees an \s-1EOT \s0(i.e., an end-track status: \s-1FF 2F 00\s0) with a delta time of 0, it is \fIignored\fR! If in the unlikely event that it has a nonzero delta-time, it's decoded as a \f(CW\*(Aqtext_event\*(Aq\fR with whatever that delta-time is, and a zero-length text parameter. (This happens before the \&\f(CW\*(Aqevent_callback\*(Aq\fR or \f(CW\*(Aqexclusive_event_callback\*(Aq\fR callbacks are given a crack at it.) On the encoding side, an \s-1EOT\s0 is added to the end of the track as a normal part of the encapsulation of track data. .PP 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 \&\f(CW\*(Aqend_track\*(Aq\fR event. .PP However, if you set \f(CW\*(C`no_eot_magic\*(C'\fR as a decoding parameter, none of this magic happens on the decoding side \*(-- \f(CW\*(Aqend_track\*(Aq\fR is decoded just as it is. .PP And if you set \f(CW\*(C`no_eot_magic\*(C'\fR as an encoding parameter, then a track-final 0\-length \f(CW\*(Aqtext_event\*(Aq\fR with non\-0 delta-times is left as is. Normally, such an event would be converted from a \f(CW\*(Aqtext_event\*(Aq\fR to an \f(CW\*(Aqend_track\*(Aq\fR event with thath delta-time. .PP Normally, no user needs to use the \f(CW\*(C`no_eot_magic\*(C'\fR 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. .SH "MIDI BNF" .IX Header "MIDI BNF" For your reference (if you can make any sense of it), here is a copy of the \s-1MIDI BNF,\s0 as I found it in a text file that's been floating around the Net since the late 1980s. .PP Note that this seems to describe \s-1MIDI\s0 events as they can occur in MIDI-on-the-wire. I \fIthink\fR that realtime data insertion (i.e., the ability to have s popping up in the \fImiddle\fR of messages) is something that can't happen in \s-1MIDI\s0 files. .PP In fact, this library, as written, \fIcan't\fR correctly parse \s-1MIDI\s0 data that has such realtime bytes inserted in messages. Nor does it support representing such insertion in a \s-1MIDI\s0 event structure that's encodable for writing to a file. (Although you could theoretically represent events with embedded s as just \&\f(CW\*(C`raw_data\*(C'\fR events; but then, you can always stow anything at all in a \f(CW\*(C`raw_data\*(C'\fR event.) .PP .Vb 10 \& 1. ::= < MIDI Stream> \& 2. ::= | \& 3. ::= | \& | \& 4. ::= \& \& 5. ::= \& \& 6. ::= \& \& 7. ::= \& \& 8. ::= C | D \& 9. ::= 8 | 9 | A | B | E \& 10. ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | \& | 8 | 9 | A | B | C | D | E | F \& 11. ::= \& 12. ::= | \& | \& 13. ::= | \& 14. ::= | \& | \& 15. ::= \& 16. ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 \& 17. ::= F8 | FA | FB | FC | FE | FF \& 18. ::= | \& | | \& | \& 19. ::= \& 20. ::= \& \& \& 21. ::= F0 \& 22. ::= F7 \& 23. ::= | \& | | \& | \& 24. ::= F6 \& 25. ::= \& \& 26. ::= \& \& 27. ::=F2 \& 28. ::= F3 .Ve .SH "COPYRIGHT" .IX Header "COPYRIGHT" Copyright (c) 1998\-2005 Sean M. Burke. All rights reserved. .PP This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. .SH "AUTHOR" .IX Header "AUTHOR" Sean M. Burke \f(CW\*(C`sburke@cpan.org\*(C'\fR (Except the \s-1BNF\s0 \*(-- who knows who's behind that.)