File Coverage

blib/lib/MIDI/Event.pm
Criterion Covered Total %
statement 125 243 51.4
branch 110 252 43.6
condition 22 39 56.4
subroutine 5 9 55.5
pod 3 6 50.0
total 265 549 48.2


line stmt bran cond sub pod time code
1              
2             # Time-stamp: "2010-12-23 09:59:44 conklin"
3             require 5.004; # I need BER working right, among other things.
4             package MIDI::Event;
5              
6 11     11   62 use strict;
  11         23  
  11         612  
7 11         1259 use vars qw($Debug $VERSION @MIDI_events @Text_events @Nontext_meta_events
8             @Meta_events @All_events
9 11     11   251 );
  11         22  
10 11     11   60 use Carp;
  11         22  
  11         50966  
11              
12             $Debug = 0;
13             $VERSION = '0.83';
14              
15             #First 100 or so lines of this module are straightforward. The actual
16             # encoding logic below that is scary, tho.
17              
18             =head1 NAME
19              
20             MIDI::Event - MIDI events
21              
22             =head1 SYNOPSIS
23              
24             # Dump a MIDI file's text events
25             die "No filename" unless @ARGV;
26             use MIDI; # which "use"s MIDI::Event;
27             MIDI::Opus->new( {
28             "from_file" => $ARGV[0],
29             "exclusive_event_callback" => sub{print "$_[2]\n"},
30             "include" => \@MIDI::Event::Text_events
31             } ); # These options percolate down to MIDI::Event::decode
32             exit;
33              
34             =head1 DESCRIPTION
35              
36             Functions and lists to do with MIDI events and MIDI event structures.
37              
38             An event is a list, like:
39              
40             ( 'note_on', 141, 4, 50, 64 )
41              
42             where the first element is the event name, the second is the
43             delta-time, and the remainder are further parameters, per the
44             event-format specifications below.
45              
46             An I is a list of references to such events -- a
47             "LoL". If you don't know how to deal with LoLs, you I read
48             L.
49              
50             =head1 GOODIES
51              
52             For your use in code (as in the code in the Synopsis), this module
53             provides a few lists:
54              
55             =over
56              
57             =item @MIDI_events
58              
59             a list of all "MIDI events" AKA voice events -- e.g., 'note_on'
60              
61             =item @Text_events
62              
63             a list of all text meta-events -- e.g., 'track_name'
64              
65             =item @Nontext_meta_events
66              
67             all other meta-events (plus 'raw_data' and F-series events like
68             'tune_request').
69              
70             =item @Meta_events
71              
72             the combination of Text_events and Nontext_meta_events.
73              
74             =item @All_events
75              
76             the combination of all the above lists.
77              
78             =back
79              
80             =cut
81              
82             ###########################################################################
83             # Some public-access lists:
84              
85             @MIDI_events = qw(
86             note_off note_on key_after_touch control_change patch_change
87             channel_after_touch pitch_wheel_change set_sequence_number
88             );
89             @Text_events = qw(
90             text_event copyright_text_event track_name instrument_name lyric
91             marker cue_point text_event_08 text_event_09 text_event_0a
92             text_event_0b text_event_0c text_event_0d text_event_0e text_event_0f
93             );
94             @Nontext_meta_events = qw(
95             end_track set_tempo smpte_offset time_signature key_signature
96             sequencer_specific raw_meta_event sysex_f0 sysex_f7 song_position
97             song_select tune_request raw_data
98             );
99             # Actually, 'tune_request', for one, is is F-series event, not a
100             # strictly-speaking meta-event
101             @Meta_events = (@Text_events, @Nontext_meta_events);
102             @All_events = (@MIDI_events, @Meta_events);
103              
104             =head1 FUNCTIONS
105              
106             This module provides three functions of interest, which all act upon
107             event structures. As an end user, you probably don't need to use any
108             of these directly, but note that options you specify for
109             MIDI::Opus->new with a from_file or from_handle options will percolate
110             down to these functions; so you should understand the options for the
111             first two of the below functions. (The casual user should merely skim
112             this section.)
113              
114             =over
115              
116             =item MIDI::Event::decode( \$data, { ...options... } )
117              
118             This takes a I to binary MIDI data and decodes it into a
119             new event structure (a LoL), a I to which is returned.
120             Options are:
121              
122             =over 16
123              
124             =item 'include' => LISTREF
125              
126             I, listref is interpreted as a reference to a list of
127             event names (e.g., 'cue_point' or 'note_off') such that only these
128             events will be parsed from the binary data provided. Events whose
129             names are NOT in this list will be ignored -- i.e., they won't end up
130             in the event structure, and they won't be each passed to any callbacks
131             you may have specified.
132              
133             =item 'exclude' => LISTREF
134              
135             I, listref is interpreted as a reference to a list of
136             event names (e.g., 'cue_point' or 'note_off') that will NOT be parsed
137             from the binary stream; they'll be ignored -- i.e., they won't end up
138             in the event structure, and they won't be passed to any callbacks you
139             may have specified. Don't specify both an include and an exclude
140             list. And if you specify I, all events will be decoded --
141             this is what you probably want most of the time. I've created this
142             include/exclude functionality mainly so you can scan a file rather
143             efficiently for just a few specific event types, e.g., just text
144             events, or just sysexes.
145              
146             =item 'no_eot_magic' => 0 or 1
147              
148             See the description of C<'end_track'>, in "EVENTS", below.
149              
150             =item 'event_callback' => CODEREF
151              
152             If defined, the code referred to (whether as C<\&wanted> or as
153             C) is called on every event after it's been parsed into
154             an event list (and any EOT magic performed), but before it's added to
155             the event structure. So if you want to alter the event stream on the
156             way to the event structure (which counts as deep voodoo), define
157             'event_callback' and have it modify its C<@_>.
158              
159             =item 'exclusive_event_callback' => CODEREF
160              
161             Just like 'event_callback'; but if you specify this, the callback is
162             called I of adding the events to the event structure. (So
163             the event structure returned by decode() at the end will always be
164             empty.) Good for cases like the text dumper in the Synopsis, above.
165              
166             =back
167              
168             =item MIDI::Event::encode( \@events, {...options...})
169              
170             This takes a I to an event structure (a LoL) and encodes it
171             as binary data, which it returns a I to. Options:
172              
173             =over 16
174              
175             =item 'unknown_callback' => CODEREF
176              
177             If this is specified, it's interpreted as a reference to a subroutine
178             to be called when an unknown event name (say, 'macro_10' or
179             something), is seen by encode(). The function is fed all of the event
180             (its name, delta-time, and whatever parameters); the return value of
181             this function is added to the encoded data stream -- so if you don't
182             want to add anything, be sure to return ''.
183              
184             If no 'unknown_callback' is specified, encode() will C (well,
185             C) of the unknown event. To merely block that, just set
186             'unknown_callback' to C
187              
188             =item 'no_eot_magic' => 0 or 1
189              
190             Determines whether a track-final 0-length text event is encoded as
191             a end-track event -- since a track-final 0-length text event probably
192             started life as an end-track event read in by decode(), above.
193              
194             =item 'never_add_eot' => 0 or 1
195              
196             If 1, C never ever I an end-track (EOT) event to the
197             encoded data generated unless it's I there as an
198             'end_track' in the given event structure. You probably don't ever
199             need this unless you're encoding for I writing to a MIDI
200             port, instead of to a file.
201              
202             =item 'no_running_status' => 0 or 1
203              
204             If 1, disables MIDI's "running status" compression. Probably never
205             necessary unless you need to feed your MIDI data to a strange old
206             sequencer that doesn't understand running status.
207              
208             =back
209              
210             Note: If you're encoding just a single event at a time or less than a
211             whole trackful in any case, then you probably want something like:
212              
213             $data_r = MIDI::Event::encode(
214             [
215             [ 'note_on', 141, 4, 50, 64 ]
216             ],
217             { 'never_add_eot' => 1} );
218              
219             which just encodes that one event I an event structure of one
220             event -- i.e., an LoL that's just a list of one list.
221              
222             But note that running status will not always apply when you're
223             encoding less than a whole trackful at a time, since running status
224             works only within a LoL encoded all at once. This'll result in
225             non-optimally compressed, but still effective, encoding.
226              
227             =item MIDI::Event::copy_structure()
228              
229             This takes a I to an event structure, and returns a
230             I to a copy of it. If you're thinking about using this, you
231             probably should want to use the more straightforward
232              
233             $track2 = $track->copy
234              
235             instead. But it's here if you happen to need it.
236              
237             =back
238              
239             =cut
240              
241             ###########################################################################
242             sub dump {
243 0 0   0 0 0 my @event = ref($_[0]) ? @{ $_[0] } : @_;
  0         0  
244             # Works as a method (in theory) or as a normal call
245 0         0 print( " [", &MIDI::_dump_quote(@event), "],\n" );
246             }
247              
248             sub copy_structure {
249             # Takes a REFERENCE to an event structure (a ref to a LoL),
250             # and returns a REFERENCE to a copy of that structure.
251 0     0 1 0 my $events_r = $_[0];
252 0 0       0 croak
253             "\$_[0] ($events_r) isn't a reference for MIDI::Event::copy_structure()!!"
254             unless ref($events_r);
255 0         0 return [ map( [@$_], @$events_r ) ];
256             }
257              
258             ###########################################################################
259             # The module code below this line is full of frightening things, all to do
260             # with the actual encoding and decoding of binary MIDI data.
261             ###########################################################################
262              
263             sub read_14_bit {
264             # Decodes to a value 0 to 16383, as is used for some event encoding
265 0     0 0 0 my($b1, $b2) = unpack("C2", $_[0]);
266 0         0 return ($b1 | ($b2 << 7));
267             }
268              
269             sub write_14_bit {
270             # encode a 14 bit quantity, as needed for some events
271             return
272 0     0 0 0 pack("C2",
273             ($_[0] & 0x7F), # lower 7 bits
274             (($_[0] >> 7) & 0x7F), # upper 7 bits
275             );
276             }
277              
278             ###########################################################################
279             #
280             # One definite assumption is made here: that "variable-length-encoded"
281             # quantities MUST NOT exceed 0xFFFFFFF (encoded, "\xFF\xFF\xFF\x7F")
282             # -- i.e., must not take more than 4 bytes to encode.
283             #
284             ###
285              
286             sub decode { # decode track data into an event structure
287             # Calling format: a REFERENCE to a big chunka MTrk track data.
288             # Returns an (unblessed) REFERENCE to an event structure (a LoL)
289             # Note that this is a function call, not a constructor method call.
290              
291             # Why a references and not the things themselves? For efficiency's sake.
292              
293 15     15 1 30 my $data_r = $_[0];
294 15 50       65 my $options_r = ref($_[1]) eq 'HASH' ? $_[1] : {};
295 15         32 my @events = ();
296 15 50       49 unless(ref($data_r) eq 'SCALAR') {
297 0         0 carp "\$_[0] is not a data reference, in MIDI::Event::decode!";
298 0         0 return [];
299             }
300              
301 15         35 my %exclude = ();
302 15 50       62 if(defined($options_r->{ 'exclude' })) {
303 0 0       0 if( ref($options_r->{'exclude'}) eq 'ARRAY' ) {
304             @exclude{
305 0         0 @{ $options_r->{'exclude'} }
  0         0  
306             } = undef;
307             } else {
308 0 0       0 croak
309             "parameter for MIDI::Event::decode option 'exclude' must be a listref!"
310             if $options_r->{'exclude'};
311             # If it's false, carry on silently
312             }
313             } else {
314             # If we get an include (and no exclude), make %exclude a list
315             # of all possible events, /minus/ what include specifies
316 15 50       55 if(defined($options_r->{ 'include' })) {
317 0 0       0 if( ref($options_r->{'include'}) eq 'ARRAY' ) {
318 0         0 @exclude{ @All_events } = undef; # rack 'em
319             delete @exclude{ # and break 'em
320 0         0 @{ $options_r->{'include'} }
  0         0  
321             };
322             } else {
323 0 0       0 croak
324             "parameter for decode option 'include' must be a listref!"
325             if $options_r->{'include'};
326             # If it's false, carry on silently
327             }
328             }
329             }
330 15 50       39 print "Exclusions: ", join(' ', map("<$_>", sort keys %exclude)), "\n"
331             if $Debug;
332              
333 15         31 my $event_callback = undef;
334 15 50       45 if(defined($options_r->{ 'event_callback' })) {
335 0 0       0 if( ref($options_r->{'event_callback'}) eq 'CODE' ) {
336 0         0 $event_callback = $options_r->{'event_callback'};
337             } else {
338 0         0 carp "parameter for decode option 'event_callback' is not a coderef!\n";
339             }
340             }
341 15         21 my $exclusive_event_callback = undef;
342 15 50       44 if(defined($options_r->{ 'exclusive_event_callback' })) {
343 0 0       0 if( ref($options_r->{'exclusive_event_callback'}) eq 'CODE' ) {
344 0         0 $exclusive_event_callback = $options_r->{'exclusive_event_callback'};
345             } else {
346 0         0 carp "parameter for decode option 'exclusive_event_callback' is not a coderef!\n";
347             }
348             }
349              
350              
351 15         29 my $Pointer = 0; # points to where I am in the data
352             ######################################################################
353 15 50       32 if($Debug) {
354 0 0       0 if($Debug == 1) {
355 0         0 print "Track data of ", length($$data_r), " bytes.\n";
356             } else {
357 0         0 print "Track data of ", length($$data_r), " bytes: <", $$data_r ,">\n";
358             }
359             }
360              
361             =head1 EVENTS AND THEIR DATA TYPES
362              
363             =head2 DATA TYPES
364              
365             Events use these data types:
366              
367             =over
368              
369             =item channel = a value 0 to 15
370              
371             =item note = a value 0 to 127
372              
373             =item dtime = a value 0 to 268,435,455 (0x0FFFFFFF)
374              
375             =item velocity = a value 0 to 127
376              
377             =item channel = a value 0 to 15
378              
379             =item patch = a value 0 to 127
380              
381             =item sequence = a value 0 to 65,535 (0xFFFF)
382              
383             =item text = a string of 0 or more bytes of of ASCII text
384              
385             =item raw = a string of 0 or more bytes of binary data
386              
387             =item pitch_wheel = a value -8192 to 8191 (0x1FFF)
388              
389             =item song_pos = a value 0 to 16,383 (0x3FFF)
390              
391             =item song_number = a value 0 to 127
392              
393             =item tempo = microseconds, a value 0 to 16,777,215 (0x00FFFFFF)
394              
395             =back
396              
397             For data types not defined above, (e.g., I and I for
398             C<'key_signature'>), consult L and/or the source for
399             C. And if you don't see it documented, it's probably
400             because I don't understand it, so you'll have to consult a real MIDI
401             reference.
402              
403             =head2 EVENTS
404              
405             And these are the events:
406              
407             =over
408              
409             =cut
410             # Things I use variously, below. They're here just for efficiency's sake,
411             # to avoid remying on each iteration.
412 15         23 my($command, $channel, $parameter, $length, $time, $remainder);
413              
414 15         266 my $event_code = -1; # used for running status
415              
416 15         27 my $event_count = 0;
417             Event: # Analyze the event stream.
418 15         56 while($Pointer + 1 < length($$data_r)) {
419             # loop while there's anything to analyze ...
420 1758         1824 my $eot = 0; # When 1, the event registrar aborts this loop
421 1758         1719 ++$event_count;
422              
423 1758         2102 my @E = ();
424             # E for events -- this is what we'll feed to the event registrar
425             # way at the end.
426              
427             # Slice off the delta time code, and analyze it
428             #!# print "Chew-code <", substr($$data_r,$Pointer,4), ">\n";
429 1758         5249 ($time, $remainder) = unpack("wa*", substr($$data_r,$Pointer,4));
430             #!# print "Delta-time $time using ", 4 - length($remainder), " bytes\n"
431             #!# if $Debug > 1;
432 1758         2653 $Pointer += 4 - length($remainder);
433             # We do this strangeness with remainders because we don't know
434             # how many bytes the w-decoding should move the pointer ahead.
435              
436             # Now let's see what we can make of the command
437 1758         3154 my $first_byte = ord(substr($$data_r, $Pointer, 1));
438             # Whatever parses $first_byte is responsible for moving $Pointer
439             # forward.
440             #!#print "Event \# $event_count: $first_byte at track-offset $Pointer\n"
441             #!# if $Debug > 1;
442              
443             ######################################################################
444 1758 100 0     2697 if ($first_byte < 0xF0) { # It's a MIDI event ########################
    50          
    0          
    0          
    0          
    0          
    0          
445 1679 100       2394 if($first_byte >= 0x80) {
446 927 50       1722 print "Explicit event $first_byte" if $Debug > 2;
447 927         985 ++$Pointer; # It's an explicit event.
448 927         1242 $event_code = $first_byte;
449             } else {
450             # It's a running status mofo -- just use last $event_code value
451 752 50       1356 if($event_code == -1) {
452 0 0       0 warn "Uninterpretable use of running status; Aborting track."
453             if $Debug;
454 0         0 last Event;
455             }
456             # Let the argument-puller-offer move Pointer.
457             }
458 1679         1888 $command = $event_code & 0xF0;
459 1679         1712 $channel = $event_code & 0x0F;
460              
461 1679 100 66     5858 if ($command == 0xC0 || $command == 0xD0) {
462             # Pull off the 1-byte argument
463 11         25 $parameter = substr($$data_r, $Pointer, 1);
464 11         15 ++$Pointer;
465             } else { # pull off the 2-byte argument
466 1668         2299 $parameter = substr($$data_r, $Pointer, 2);
467 1668         1853 $Pointer += 2;
468             }
469              
470             ###################################################################
471             # MIDI events
472              
473             =item ('note_off', I, I, I, I)
474              
475             =cut
476 1679 100       3008 if ($command == 0x80) {
    100          
    50          
    100          
    50          
    0          
    0          
477 485 50       934 next if $exclude{'note_off'};
478             # for sake of efficiency
479 485         1283 @E = ( 'note_off', $time,
480             $channel, unpack('C2', $parameter));
481              
482             =item ('note_on', I, I, I, I)
483              
484             =cut
485             } elsif ($command == 0x90) {
486 1181 50       2169 next if $exclude{'note_on'};
487 1181         2812 @E = ( 'note_on', $time,
488             $channel, unpack('C2', $parameter));
489              
490             =item ('key_after_touch', I, I, I, I)
491              
492             =cut
493             } elsif ($command == 0xA0) {
494 0 0       0 next if $exclude{'key_after_touch'};
495 0         0 @E = ( 'key_after_touch', $time,
496             $channel, unpack('C2', $parameter));
497              
498             =item ('control_change', I, I, I, I)
499              
500             =cut
501             } elsif ($command == 0xB0) {
502 2 50       6 next if $exclude{'control_change'};
503 2         7 @E = ( 'control_change', $time,
504             $channel, unpack('C2', $parameter));
505              
506             =item ('patch_change', I, I, I)
507              
508             =cut
509             } elsif ($command == 0xC0) {
510 11 50       95 next if $exclude{'patch_change'};
511 11         37 @E = ( 'patch_change', $time,
512             $channel, unpack('C', $parameter));
513              
514             =item ('channel_after_touch', I, I, I)
515              
516             =cut
517             } elsif ($command == 0xD0) {
518 0 0       0 next if $exclude{'channel_after_touch'};
519 0         0 @E = ('channel_after_touch', $time,
520             $channel, unpack('C', $parameter));
521              
522             =item ('pitch_wheel_change', I, I, I)
523              
524             =cut
525             } elsif ($command == 0xE0) {
526 0 0       0 next if $exclude{'pitch_wheel_change'};
527 0         0 @E = ('pitch_wheel_change', $time,
528             $channel, &read_14_bit($parameter) - 0x2000);
529             } else {
530 0         0 warn # Should be QUITE impossible!
531             "SPORK ERROR M:E:1 in track-offset $Pointer\n";
532             }
533              
534             ######################################################################
535             } elsif($first_byte == 0xFF) { # It's a Meta-Event! ##################
536 79         260 ($command, $length, $remainder) =
537             unpack("xCwa*", substr($$data_r, $Pointer, 6));
538 79         127 $Pointer += 6 - length($remainder);
539             # Move past JUST the length-encoded.
540              
541             =item ('set_sequence_number', I, I)
542              
543             =cut
544 79 50       704 if($command == 0x00) {
    100          
    100          
    100          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    100          
    100          
    50          
    0          
    0          
545 0         0 @E = ('set_sequence_number',
546             $time,
547             unpack('n',
548             substr($$data_r, $Pointer, $length)
549             )
550             );
551              
552             # Defined text events ----------------------------------------------
553              
554             =item ('text_event', I, I)
555              
556             =item ('copyright_text_event', I, I)
557              
558             =item ('track_name', I, I)
559              
560             =item ('instrument_name', I, I)
561              
562             =item ('lyric', I, I)
563              
564             =item ('marker', I, I)
565              
566             =item ('cue_point', I, I)
567              
568             =item ('text_event_08', I, I)
569              
570             =item ('text_event_09', I, I)
571              
572             =item ('text_event_0a', I, I)
573              
574             =item ('text_event_0b', I, I)
575              
576             =item ('text_event_0c', I, I)
577              
578             =item ('text_event_0d', I, I)
579              
580             =item ('text_event_0e', I, I)
581              
582             =item ('text_event_0f', I, I)
583              
584             =cut
585             } elsif($command == 0x01) {
586 33         89 @E = ('text_event',
587             $time, substr($$data_r, $Pointer, $length)); # DTime, TData
588             } elsif($command == 0x02) {
589 2         10 @E = ('copyright_text_event',
590             $time, substr($$data_r, $Pointer, $length)); # DTime, TData
591             } elsif($command == 0x03) {
592 10         27 @E = ('track_name',
593             $time, substr($$data_r, $Pointer, $length)); # DTime, TData
594             } elsif($command == 0x04) {
595 6         18 @E = ('instrument_name',
596             $time, substr($$data_r, $Pointer, $length)); # DTime, TData
597             } elsif($command == 0x05) {
598 0         0 @E = ('lyric',
599             $time, substr($$data_r, $Pointer, $length)); # DTime, TData
600             } elsif($command == 0x06) {
601 0         0 @E = ('marker',
602             $time, substr($$data_r, $Pointer, $length)); # DTime, TData
603             } elsif($command == 0x07) {
604 0         0 @E = ('cue_point',
605             $time, substr($$data_r, $Pointer, $length)); # DTime, TData
606              
607             # Reserved but apparently unassigned text events --------------------
608             } elsif($command == 0x08) {
609 0         0 @E = ('text_event_08',
610             $time, substr($$data_r, $Pointer, $length)); # DTime, TData
611             } elsif($command == 0x09) {
612 0         0 @E = ('text_event_09',
613             $time, substr($$data_r, $Pointer, $length)); # DTime, TData
614             } elsif($command == 0x0a) {
615 0         0 @E = ('text_event_0a',
616             $time, substr($$data_r, $Pointer, $length)); # DTime, TData
617             } elsif($command == 0x0b) {
618 0         0 @E = ('text_event_0b',
619             $time, substr($$data_r, $Pointer, $length)); # DTime, TData
620             } elsif($command == 0x0c) {
621 0         0 @E = ('text_event_0c',
622             $time, substr($$data_r, $Pointer, $length)); # DTime, TData
623             } elsif($command == 0x0d) {
624 0         0 @E = ('text_event_0d',
625             $time, substr($$data_r, $Pointer, $length)); # DTime, TData
626             } elsif($command == 0x0e) {
627 0         0 @E = ('text_event_0e',
628             $time, substr($$data_r, $Pointer, $length)); # DTime, TData
629             } elsif($command == 0x0f) {
630 0         0 @E = ('text_event_0f',
631             $time, substr($$data_r, $Pointer, $length)); # DTime, TData
632              
633             # Now the sticky events ---------------------------------------------
634              
635             =item ('end_track', I)
636              
637             =cut
638             } elsif($command == 0x2F) {
639 15         58 @E = ('end_track', $time ); # DTime
640             # The code for handling this oddly comes LATER, in the
641             # event registrar.
642              
643             =item ('set_tempo', I, I)
644              
645             =cut
646             } elsif($command == 0x51) {
647 9         46 @E = ('set_tempo',
648             $time,
649             unpack("N",
650             "\x00" . substr($$data_r, $Pointer, $length)
651             )
652             ); # DTime, Microseconds
653              
654             =item ('smpte_offset', I, I
, I, I, I, I)
655              
656             =cut
657             } elsif($command == 0x54) {
658 2         12 @E = ('smpte_offset',
659             $time,
660             unpack("C*", # there SHOULD be exactly 5 bytes here
661             substr($$data_r, $Pointer, $length)
662             ));
663             # DTime, HR, MN, SE, FR, FF
664              
665             =item ('time_signature', I, I, I
, I, I)
666              
667             =cut
668             } elsif($command == 0x58) {
669 2         19 @E = ('time_signature',
670             $time,
671             unpack("C*", # there SHOULD be exactly 4 bytes here
672             substr($$data_r, $Pointer, $length)
673             ));
674             # DTime, NN, DD, CC, BB
675              
676             =item ('key_signature', I, I, I)
677              
678             =cut
679             } elsif($command == 0x59) {
680 0         0 @E = ('key_signature',
681             $time,
682             unpack("cC", # there SHOULD be exactly 2 bytes here
683             substr($$data_r, $Pointer, $length)
684             ));
685             # DTime, SF(signed), MI
686              
687             =item ('sequencer_specific', I, I)
688              
689             =cut
690             } elsif($command == 0x7F) {
691 0         0 @E = ('sequencer_specific',
692             $time, substr($$data_r, $Pointer, $length));
693             # DTime, Binary Data
694              
695             =item ('raw_meta_event', I, I(0-255), I)
696              
697             =cut
698             } else {
699 0         0 @E = ('raw_meta_event',
700             $time,
701             $command,
702             substr($$data_r, $Pointer, $length)
703             # "[uninterpretable meta-event $command of length $length]"
704             );
705             # DTime, Command, Binary Data
706             # It's uninterpretable; record it as raw_data.
707             } # End of the meta-event ifcase.
708              
709 79         106 $Pointer += $length; # Now move Pointer
710              
711             ######################################################################
712             } elsif($first_byte == 0xF0 # It's a SYSEX
713             #########################
714             || $first_byte == 0xF7) {
715             # Note that sysexes in MIDI /files/ are different than sysexes in
716             # MIDI transmissions!!
717             # << The vast majority of system exclusive messages will just use the F0
718             # format. For instance, the transmitted message F0 43 12 00 07 F7 would
719             # be stored in a MIDI file as F0 05 43 12 00 07 F7. As mentioned above,
720             # it is required to include the F7 at the end so that the reader of the
721             # MIDI file knows that it has read the entire message. >>
722             # (But the F7 is omitted if this is a non-final block in a multiblock
723             # sysex; but the F7 (if there) is counted in the message's declared
724             # length, so we don't have to think about it anyway.)
725 0         0 ($command, $length, $remainder) =
726             unpack("Cwa*", substr($$data_r, $Pointer, 5));
727 0         0 $Pointer += 5 - length($remainder); # Move past just the encoding
728              
729             =item ('sysex_f0', I, I)
730              
731             =item ('sysex_f7', I, I)
732              
733             =cut
734 0 0       0 @E = ( $first_byte == 0xF0 ?
735             'sysex_f0' : 'sysex_f7',
736             $time, substr($$data_r, $Pointer, $length) ); # DTime, Data
737 0         0 $Pointer += $length; # Now move past the data
738              
739             ######################################################################
740             # Now, the MIDI file spec says:
741             # = +
742             # =
743             # = | |
744             # I know that, on the wire, can include note_on,
745             # note_off, and all the other 8x to Ex events, AND Fx events
746             # other than F0, F7, and FF -- namely, ,
747             # , and .
748             #
749             # Whether these can occur in MIDI files is not clear specified from
750             # the MIDI file spec.
751             #
752             # So, I'm going to assume that they CAN, in practice, occur.
753             # I don't know whether it's proper for you to actually emit these
754             # into a MIDI file.
755             #
756            
757             ######################################################################
758             } elsif($first_byte == 0xF2) { # It's a Song Position ################
759              
760             =item ('song_position', I)
761              
762             =cut
763             # ::= F2
764 0         0 @E = ('song_position',
765             $time, &read_14_bit(substr($$data_r,$Pointer+1,2) )
766             ); # DTime, Beats
767 0         0 $Pointer += 3; # itself, and 2 data bytes
768              
769             ######################################################################
770             } elsif($first_byte == 0xF3) { # It's a Song Select ##################
771              
772             =item ('song_select', I, I)
773              
774             =cut
775             # ::= F3
776 0         0 @E = ( 'song_select',
777             $time, unpack('C', substr($$data_r,$Pointer+1,1) )
778             ); # DTime, Thing (?!) ... song number? whatever that is
779 0         0 $Pointer += 2; # itself, and 1 data byte
780              
781             ######################################################################
782             } elsif($first_byte == 0xF6) { # It's a Tune Request! ################
783              
784             =item ('tune_request', I)
785              
786             =cut
787             # ::= F6
788 0         0 @E = ( 'tune_request', $time );
789             # DTime
790             # What the Sam Scratch would a tune request be doing in a MIDI /file/?
791 0         0 ++$Pointer; # itself
792              
793             ###########################################################################
794             ## ADD MORE META-EVENTS HERE
795             #Done:
796             # f0 f7 -- sysexes
797             # f2 -- song position
798             # f3 -- song select
799             # f6 -- tune request
800             # ff -- metaevent
801             ###########################################################################
802             #TODO:
803             # f1 -- MTC Quarter Frame Message. one data byte follows.
804             # One data byte follows the Status. It's the time code value, a number
805             # from 0 to 127.
806             # f8 -- MIDI clock. no data.
807             # fa -- MIDI start. no data.
808             # fb -- MIDI continue. no data.
809             # fc -- MIDI stop. no data.
810             # fe -- Active sense. no data.
811             # f4 f5 f9 fd -- unallocated
812              
813             ######################################################################
814             } elsif($first_byte > 0xF0) { # Some unknown kinda F-series event ####
815              
816             =item ('raw_data', I, I)
817              
818             =cut
819             # Here we only produce a one-byte piece of raw data.
820             # But the encoder for 'raw_data' accepts any length of it.
821 0         0 @E = ( 'raw_data',
822             $time, substr($$data_r,$Pointer,1) );
823             # DTime and the Data (in this case, the one Event-byte)
824 0         0 ++$Pointer; # itself
825              
826             ######################################################################
827             } else { # Fallthru. How could we end up here? ######################
828 0         0 warn
829             "Aborting track. Command-byte $first_byte at track offset $Pointer";
830 0         0 last Event;
831             }
832             # End of the big if-group
833              
834              
835             #####################################################################
836             ######################################################################
837             ##
838             # By the Power of Greyskull, I AM THE EVENT REGISTRAR!
839             ##
840 1758 100 66     11091 if( @E and $E[0] eq 'end_track' ) {
841             # This's the code for exceptional handling of the EOT event.
842 15         21 $eot = 1;
843 15 50 33     88 unless( defined($options_r->{'no_eot_magic'})
844             and $options_r->{'no_eot_magic'} ) {
845 15 100       43 if($E[1] > 0) {
846 8         36 @E = ('text_event', $E[1], '');
847             # Make up a fictive 0-length text event as a carrier
848             # for the non-zero delta-time.
849             } else {
850             # EOT with a delta-time of 0. Ignore it!
851 7         31 @E = ();
852             }
853             }
854             }
855            
856 1758 50 66     5981 if( @E and exists( $exclude{$E[0]} ) ) {
857 0 0       0 if($Debug) {
858 0         0 print " Excluding:\n";
859 0         0 &dump(@E);
860             }
861             } else {
862 1758 50       3223 if($Debug) {
863 0         0 print " Processing:\n";
864 0         0 &dump(@E);
865             }
866 1758 100       3076 if(@E){
867 1751 50       2350 if( $exclusive_event_callback ) {
868 0         0 &{ $exclusive_event_callback }( @E );
  0         0  
869             } else {
870 1751 50       3056 &{ $event_callback }( @E ) if $event_callback;
  0         0  
871 1751         5237 push(@events, [ @E ]);
872             }
873             }
874             }
875              
876             =back
877              
878             Three of the above events are represented a bit oddly from the point
879             of view of the file spec:
880              
881             The parameter I for C<'pitch_wheel_change'> is a value
882             -8192 to 8191, although the actual encoding of this is as a value 0 to
883             16,383, as per the spec.
884              
885             Sysex events are represented as either C<'sysex_f0'> or C<'sysex_f7'>,
886             depending on the status byte they are encoded with.
887              
888             C<'end_track'> is a bit stranger, in that it is almost never actually
889             found, or needed. When the MIDI decoder sees an EOT (i.e., an
890             end-track status: FF 2F 00) with a delta time of 0, it is I!
891             If in the unlikely event that it has a nonzero delta-time, it's
892             decoded as a C<'text_event'> with whatever that delta-time is, and a
893             zero-length text parameter. (This happens before the
894             C<'event_callback'> or C<'exclusive_event_callback'> callbacks are
895             given a crack at it.) On the encoding side, an EOT is added to the
896             end of the track as a normal part of the encapsulation of track data.
897              
898             I chose to add this special behavior so that you could add events to
899             the end of a track without having to work around any track-final
900             C<'end_track'> event.
901              
902             However, if you set C as a decoding parameter, none of
903             this magic happens on the decoding side -- C<'end_track'> is decoded
904             just as it is.
905              
906             And if you set C as an encoding parameter, then a
907             track-final 0-length C<'text_event'> with non-0 delta-times is left as
908             is. Normally, such an event would be converted from a C<'text_event'>
909             to an C<'end_track'> event with thath delta-time.
910              
911             Normally, no user needs to use the C option either in
912             encoding or decoding. But it is provided in case you need your event
913             LoL to be an absolutely literal representation of the binary data,
914             and/or vice versa.
915              
916             =cut
917              
918 1758 100       7853 last Event if $eot;
919             }
920             # End of the bigass "Event" while-block
921              
922 15         150 return \@events;
923             }
924              
925             ###########################################################################
926              
927             sub encode { # encode an event structure, presumably for writing to a file
928             # Calling format:
929             # $data_r = MIDI::Event::encode( \@event_lol, { options } );
930             # Takes a REFERENCE to an event structure (a LoL)
931             # Returns an (unblessed) REFERENCE to track data.
932              
933             # If you want to use this to encode a /single/ event,
934             # you still have to do it as a reference to an event structure (a LoL)
935             # that just happens to have just one event. I.e.,
936             # encode( [ $event ] ) or encode( [ [ 'note_on', 100, 5, 42, 64] ] )
937             # If you're doing this, consider the never_add_eot track option, as in
938             # print MIDI ${ encode( [ $event], { 'never_add_eot' => 1} ) };
939              
940 2     2 1 6 my $events_r = $_[0];
941 2 50       8 my $options_r = ref($_[1]) eq 'HASH' ? $_[1] : {};
942 2         6 my @data = (); # what I'll store chunks of data in
943 2         10 my $data = ''; # what I'll join @data all together into
944              
945 2 50       9 croak "MIDI::Event::encode's argument must be an array reference!"
946             unless ref($events_r); # better be an array!
947 2         37 my @events = @$events_r;
948             # Yes, copy it. This is so my end_track magic won't corrupt the original
949              
950 2         5 my $unknown_callback = undef;
951 2 50       8 $unknown_callback = $options_r->{'unknown_callback'}
952             if ref($options_r->{'unknown_callback'}) eq 'CODE';
953              
954 2 50       17 unless($options_r->{'never_add_eot'}) {
955             # One way or another, tack on an 'end_track'
956 2 50       18 if(@events) { # If there's any events...
957 2         14 my $last = $events[ -1 ];
958 2 50       9 unless($last->[0] eq 'end_track') { # ...And there's no end_track already
959 2 50 33     10 if($last->[0] eq 'text_event' and length($last->[2]) == 0) {
960             # 0-length text event at track-end.
961 0 0       0 if($options_r->{'no_eot_magic'}) {
962             # Exceptional case: don't mess with track-final
963             # 0-length text_events; just peg on an end_track
964 0         0 push(@events, ['end_track', 0]);
965             } else {
966             # NORMAL CASE: replace it with an end_track, leaving the DTime
967 0         0 $last->[0] = 'end_track';
968             }
969             } else {
970             # last event was neither a 0-length text_event nor an end_track
971 2         11 push(@events, ['end_track', 0]);
972             }
973             }
974             } else { # an eventless track!
975 0         0 @events = ['end_track',0];
976             }
977             }
978              
979             #print "--\n";
980             #foreach(@events){ MIDI::Event::dump($_) }
981             #print "--\n";
982              
983 2         6 my $maybe_running_status = not $options_r->{'no_running_status'};
984 2         4 my $last_status = -1;
985              
986             # Here so we don't have to re-my on every iteration
987 2         4 my(@E, $event, $dtime, $event_data, $status, $parameters);
988             Event_Encode:
989 2         4 foreach my $event_r (@events) {
990 271 50       558 next unless ref($event_r); # what'd such a thing ever be doing in here?
991 271         796 @E = @$event_r;
992             # Yes, copy it. Otherwise the shifting'd corrupt the original
993 271 50       527 next unless @E;
994              
995 271         398 $event = shift @E;
996 271 50       503 next unless length($event);
997              
998 271         309 $dtime = int shift @E;
999              
1000 271         490 $event_data = '';
1001              
1002 271 100 100     1156 if( # MIDI events -- eligible for running status
      66        
      66        
      66        
      66        
      66        
1003             $event eq 'note_on'
1004             or $event eq 'note_off'
1005             or $event eq 'control_change'
1006             or $event eq 'key_after_touch'
1007             or $event eq 'patch_change'
1008             or $event eq 'channel_after_touch'
1009             or $event eq 'pitch_wheel_change' )
1010             {
1011             #print "ziiz $event\n";
1012             # $status = $parameters = '';
1013             # This block is where we spend most of the time. Gotta be tight.
1014              
1015 265 100       523 if($event eq 'note_off'){
    100          
    50          
    50          
    50          
    0          
    0          
1016 132         178 $status = 0x80 | (int($E[0]) & 0x0F);
1017 132         275 $parameters = pack('C2',
1018             int($E[1]) & 0x7F, int($E[2]) & 0x7F);
1019             } elsif($event eq 'note_on'){
1020 132         257 $status = 0x90 | (int($E[0]) & 0x0F);
1021 132         288 $parameters = pack('C2',
1022             int($E[1]) & 0x7F, int($E[2]) & 0x7F);
1023             } elsif($event eq 'key_after_touch'){
1024 0         0 $status = 0xA0 | (int($E[0]) & 0x0F);
1025 0         0 $parameters = pack('C2',
1026             int($E[1]) & 0x7F, int($E[2]) & 0x7F);
1027             } elsif($event eq 'control_change'){
1028 0         0 $status = 0xB0 | (int($E[0]) & 0x0F);
1029 0         0 $parameters = pack('C2',
1030             int($E[1]) & 0xFF, int($E[2]) & 0xFF);
1031             } elsif($event eq 'patch_change'){
1032 1         3 $status = 0xC0 | (int($E[0]) & 0x0F);
1033 1         4 $parameters = pack('C',
1034             int($E[1]) & 0xFF);
1035             } elsif($event eq 'channel_after_touch'){
1036 0         0 $status = 0xD0 | (int($E[0]) & 0x0F);
1037 0         0 $parameters = pack('C',
1038             int($E[1]) & 0xFF);
1039             } elsif($event eq 'pitch_wheel_change'){
1040 0         0 $status = 0xE0 | (int($E[0]) & 0x0F);
1041 0         0 $parameters = &write_14_bit(int($E[1]) + 0x2000);
1042             } else {
1043 0         0 die "BADASS FREAKOUT ERROR 31415!";
1044             }
1045             # And now the encoding
1046 265 50 33     1560 push(@data,
1047             ($maybe_running_status and $status == $last_status) ?
1048             pack('wa*', $dtime, $parameters) : # If we can use running status.
1049             pack('wCa*', $dtime, $status, $parameters) # If we can't.
1050             );
1051 265         321 $last_status = $status;
1052 265         534 next;
1053             } else {
1054             # Not a MIDI event.
1055             # All the code in this block could be more efficient, but frankly,
1056             # this is not where the code needs to be tight.
1057             # So we wade thru the cases and eventually hopefully fall thru
1058             # with $event_data set.
1059             #print "zaz $event\n";
1060 6         10 $last_status = -1;
1061              
1062 6 50       108 if($event eq 'raw_meta_event') {
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
1063 0         0 $event_data = pack("CCwa*", 0xFF, int($E[0]), length($E[1]), $E[1]);
1064              
1065             # Text meta-events...
1066             } elsif($event eq 'text_event') {
1067 2         19 $event_data = pack("CCwa*", 0xFF, 0x01, length($E[0]), $E[0]);
1068             } elsif($event eq 'copyright_text_event') {
1069 0         0 $event_data = pack("CCwa*", 0xFF, 0x02, length($E[0]), $E[0]);
1070             } elsif($event eq 'track_name') {
1071 0         0 $event_data = pack("CCwa*", 0xFF, 0x03, length($E[0]), $E[0]);
1072             } elsif($event eq 'instrument_name') {
1073 0         0 $event_data = pack("CCwa*", 0xFF, 0x04, length($E[0]), $E[0]);
1074             } elsif($event eq 'lyric') {
1075 0         0 $event_data = pack("CCwa*", 0xFF, 0x05, length($E[0]), $E[0]);
1076             } elsif($event eq 'marker') {
1077 0         0 $event_data = pack("CCwa*", 0xFF, 0x06, length($E[0]), $E[0]);
1078             } elsif($event eq 'cue_point') {
1079 0         0 $event_data = pack("CCwa*", 0xFF, 0x07, length($E[0]), $E[0]);
1080             } elsif($event eq 'text_event_08') {
1081 0         0 $event_data = pack("CCwa*", 0xFF, 0x08, length($E[0]), $E[0]);
1082             } elsif($event eq 'text_event_09') {
1083 0         0 $event_data = pack("CCwa*", 0xFF, 0x09, length($E[0]), $E[0]);
1084             } elsif($event eq 'text_event_0a') {
1085 0         0 $event_data = pack("CCwa*", 0xFF, 0x0a, length($E[0]), $E[0]);
1086             } elsif($event eq 'text_event_0b') {
1087 0         0 $event_data = pack("CCwa*", 0xFF, 0x0b, length($E[0]), $E[0]);
1088             } elsif($event eq 'text_event_0c') {
1089 0         0 $event_data = pack("CCwa*", 0xFF, 0x0c, length($E[0]), $E[0]);
1090             } elsif($event eq 'text_event_0d') {
1091 0         0 $event_data = pack("CCwa*", 0xFF, 0x0d, length($E[0]), $E[0]);
1092             } elsif($event eq 'text_event_0e') {
1093 0         0 $event_data = pack("CCwa*", 0xFF, 0x0e, length($E[0]), $E[0]);
1094             } elsif($event eq 'text_event_0f') {
1095 0         0 $event_data = pack("CCwa*", 0xFF, 0x0f, length($E[0]), $E[0]);
1096             # End of text meta-events
1097              
1098             } elsif($event eq 'end_track') {
1099 2         9 $event_data = "\xFF\x2F\x00";
1100              
1101             } elsif($event eq 'set_tempo') {
1102 2         20 $event_data = pack("CCwa*", 0xFF, 0x51, 3,
1103             substr( pack('N', $E[0]), 1, 3
1104             ));
1105             } elsif($event eq 'smpte_offset') {
1106 0         0 $event_data = pack("CCwCCCCC", 0xFF, 0x54, 5, @E[0,1,2,3,4] );
1107             } elsif($event eq 'time_signature') {
1108 0         0 $event_data = pack("CCwCCCC", 0xFF, 0x58, 4, @E[0,1,2,3] );
1109             } elsif($event eq 'key_signature') {
1110 0         0 $event_data = pack("CCwcC", 0xFF, 0x59, 2, @E[0,1]);
1111             } elsif($event eq 'sequencer_specific') {
1112 0         0 $event_data = pack("CCwa*", 0xFF, 0x7F, length($E[0]), $E[0]);
1113             # End of Meta-events
1114              
1115             # Other Things...
1116             } elsif($event eq 'sysex_f0') {
1117 0         0 $event_data = pack("Cwa*", 0xF0, length($E[0]), $E[0]);
1118             } elsif($event eq 'sysex_f7') {
1119 0         0 $event_data = pack("Cwa*", 0xF7, length($E[0]), $E[0]);
1120              
1121             } elsif($event eq 'song_position') {
1122 0         0 $event_data = "\xF2" . &write_14_bit( $E[0] );
1123             } elsif($event eq 'song_select') {
1124 0         0 $event_data = pack('CC', 0xF3, $E[0] );
1125             } elsif($event eq 'tune_request') {
1126 0         0 $event_data = "\xF6";
1127             } elsif($event eq 'raw_data') {
1128 0         0 $event_data = $E[0];
1129             # End of Other Stuff
1130              
1131             } else {
1132             # The Big Fallthru
1133 0 0       0 if($unknown_callback) {
1134 0         0 push(@data, &{ $unknown_callback }( @$event_r ));
  0         0  
1135             } else {
1136 0         0 warn "Unknown event: \'$event\'\n";
1137             # To surpress complaint here, just set
1138             # 'unknown_callback' => sub { return () }
1139             }
1140 0         0 next;
1141             }
1142              
1143             #print "Event $event encoded part 2\n";
1144 6 50       33 push(@data, pack('wa*', $dtime, $event_data))
1145             if length($event_data); # how could $event_data be empty
1146             }
1147             }
1148 2         29 $data = join('', @data);
1149 2         55 return \$data;
1150             }
1151              
1152             ###########################################################################
1153              
1154             ###########################################################################
1155              
1156             =head1 MIDI BNF
1157              
1158             For your reference (if you can make any sense of it), here is a copy
1159             of the MIDI BNF, as I found it in a text file that's been floating
1160             around the Net since the late 1980s.
1161              
1162             Note that this seems to describe MIDI events as they can occur in
1163             MIDI-on-the-wire. I I that realtime data insertion (i.e., the
1164             ability to have Erealtime byteEs popping up in the I
1165             of messages) is something that can't happen in MIDI files.
1166              
1167             In fact, this library, as written, I correctly parse MIDI data
1168             that has such realtime bytes inserted in messages. Nor does it
1169             support representing such insertion in a MIDI event structure that's
1170             encodable for writing to a file. (Although you could theoretically
1171             represent events with embedded Erealtime byteEs as just
1172             C events; but then, you can always stow anything
1173             at all in a C event.)
1174              
1175             1. ::= < MIDI Stream>
1176             2. ::= |
1177             3. ::= |
1178             |
1179             4. ::=
1180            
1181             5. ::=
1182            
1183             6. ::=
1184            
1185             7. ::=
1186            
1187             8. ::= C | D
1188             9. ::= 8 | 9 | A | B | E
1189             10. ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
1190             | 8 | 9 | A | B | C | D | E | F
1191             11. ::=
1192             12. ::= |
1193             |
1194             13. ::= |
1195             14. ::= |
1196             |
1197             15. ::=
1198             16. ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
1199             17. ::= F8 | FA | FB | FC | FE | FF
1200             18. ::= |
1201             | |
1202             |
1203             19. ::=
1204             20. ::=
1205            
1206            
1207             21. ::= F0
1208             22. ::= F7
1209             23. ::= |
1210             | |
1211             |
1212             24. ::= F6
1213             25. ::=
1214            
1215             26. ::=
1216            
1217             27. ::=F2
1218             28. ::= F3
1219              
1220             =head1 COPYRIGHT
1221              
1222             Copyright (c) 1998-2005 Sean M. Burke. All rights reserved.
1223              
1224             This library is free software; you can redistribute it and/or
1225             modify it under the same terms as Perl itself.
1226              
1227             =head1 AUTHOR
1228              
1229             Sean M. Burke C (Except the BNF --
1230             who knows who's behind that.)
1231              
1232             =cut
1233              
1234             1;
1235              
1236             __END__