Re: MIDI question

[email protected] ("Sean M. Burke") Sun, 11 May 2003 15:01:26 -0800
Newsgroups perl.midi
Message-ID <[email protected]>
A new MIDI-Perl user recently asked me how to iterate over events in tracks 
in an opus and see which channels were being used.

Here is an example program for that task:

use strict;
use MIDI;
my $in = $ARGV[0] || die "What input file?";

my $opus = MIDI::Opus->new({ 'from_file' => $in });
print "Track count: ", scalar($opus->tracks), "\n";

my $total = 0;
foreach my $t (@{ $opus->tracks_r }) {
   my @channels;
   $#channels = 15; # preallocate the array
   foreach my $e (@{ $t->events_r || next }) {
     # Iterate over each event in the track.
     #print "@$e\n";
     if($e->[0] eq 'note_on') {
       # ('note_on', dtime, channel, note, velocity)
       $channels[ $e->[2] ] = 1;
       #print "@$e\n";
     }
   }

   my @which = grep $channels[$_], 0 .. 15;
   my $count = scalar @which;
   $total += $count;
   print "This track used $count tracks, whose numbers are: @which\n";
}
print "Total tracks used: $total\n";
__END__


Note that we cheat and don't survey all possible events that involve a 
track (like patch_change), but just look at the note_on events.
This could possibly be made faster by using special arguments to the ->new, 
something like include => ['note_on'] to have the system not even bother to 
save any other kinds of events.

--
Sean M. Burke    http://search.cpan.org/~sburke/