8 my ($filename) = @ARGV;
9 my $opus = MIDI::Opus->new({from_file => $filename});
17 channel_after_touch => 2,
18 pitch_wheel_change => 2
22 set_tempo => sub { 1; },
23 note_off => sub { 1; },
24 note_on => sub { 1; },
25 control_change => sub { $_[3] == 64; },
31 return map { [$_->[0], $t += $_->[1], @{$_}[2..(@$_-1)]]; } @_;
37 return map { my $tsave = $t; $t = $_->[1]; [$_->[0], $t - $tsave, @{$_}[2..(@$_-1)]]; } @_;
42 return reltime grep { ($isclean{$_->[0]} // sub { 0; })->(@$_) } abstime @_;
48 my @arg = split /\s+/, $_;
50 print "Executing: $cmd @arg\n";
53 my $tracks = $opus->tracks_r();
54 $tracks->[$_]->events_r([clean($tracks->[$_]->events())])
57 elsif($cmd eq 'ticks')
61 $opus->ticks($arg[0]);
65 print "Ticks: ", $opus->ticks(), "\n";
68 elsif($cmd eq 'tricks')
70 print "haha, very funny\n";
72 elsif($cmd eq 'tracks')
74 my $tracks = $opus->tracks_r();
87 next if $taken{$_}++ and not $force;
88 push @t, $tracks->[$_];
103 for($tracks->[$_]->events())
106 $_->[0] = 'note_off' if $_->[0] eq 'note_on' and $_->[4] == 0;
108 my $p = $chanpos{$_->[0]};
111 my $c = $_->[$p] + 1;
114 ++$notes if $_->[0] eq 'note_on';
115 $notehash{$_->[2]}{$_->[3]} = $t if $_->[0] eq 'note_on';
116 $notehash{$_->[2]}{$_->[3]} = undef if $_->[0] eq 'note_off';
117 $name = $_->[2] if $_->[0] eq 'track_name';
119 my $channels = join " ", sort keys %channels;
121 while(my ($k1, $v1) = each %notehash)
123 while(my ($k2, $v2) = each %$v1)
125 push @stuck, sprintf "%d:%d@%.1f%%", $k1+1, $k2, $v2 * 100.0 / $t
129 print " $name" if defined $name;
130 print " (channel $channels)" if $channels ne "";
131 print " ($events events)" if $events;
132 print " ($notes notes)" if $notes;
133 print " (notes @stuck stuck)" if @stuck;
138 elsif($cmd eq 'save')
140 $opus->write_to_file($arg[0]);
144 print "Unknown command, allowed commands: ticks, tracks, clean, save\n";
146 print "Done with: $cmd @arg\n";