X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=misc%2Ftools%2Fmidichannels.pl;h=4df6978be9bb2cb790d4d5523d80feed46b7979d;hb=8a946096009455bec30aa79c51b4c2877646a779;hp=5dc67ea736d2ac4d46651e49894f6d46cb859d3f;hpb=586a034badc23007ea050879eda39db35c9ae094;p=xonotic%2Fxonotic.git diff --git a/misc/tools/midichannels.pl b/misc/tools/midichannels.pl old mode 100644 new mode 100755 index 5dc67ea7..4df6978b --- a/misc/tools/midichannels.pl +++ b/misc/tools/midichannels.pl @@ -5,7 +5,7 @@ use warnings; use MIDI; use MIDI::Opus; -my ($filename) = @ARGV; +my ($filename, @others) = @ARGV; my $opus = MIDI::Opus->new({from_file => $filename}); my %chanpos = ( @@ -42,6 +42,20 @@ sub clean(@) return reltime grep { ($isclean{$_->[0]} // sub { 0; })->(@$_) } abstime @_; } +for(@others) +{ + my $opus2 = MIDI::Opus->new({from_file => $_}); + if($opus2->ticks() != $opus->ticks()) + { + my $tickfactor = $opus->ticks() / $opus2->ticks(); + for($opus2->tracks()) + { + $_->events(reltime map { $_->[1] = int($_->[1] * $tickfactor + 0.5); $_; } abstime $_->events()); + } + } + $opus->tracks($opus->tracks(), $opus2->tracks()); +} + while() { chomp; @@ -54,6 +68,10 @@ while() $tracks->[$_]->events_r([clean($tracks->[$_]->events())]) for 0..@$tracks-1; } + elsif($cmd eq 'dump') + { + print $opus->dump({ dump_tracks => 1 }); + } elsif($cmd eq 'ticks') { if(@arg) @@ -69,6 +87,115 @@ while() { print "haha, very funny\n"; } + elsif($cmd eq 'retrack') + { + my $tracks = $opus->tracks_r(); + my @newtracks = (); + for(0..@$tracks-1) + { + for(abstime $tracks->[$_]->events()) + { + my $p = $chanpos{$_->[0]}; + if(defined $p) + { + my $c = $_->[$p] + 1; + push @{$newtracks[$c]}, $_; + } + else + { + push @{$newtracks[0]}, $_; + } + } + } + $opus->tracks_r([map { ($_ && @$_) ? MIDI::Track->new({ events => [reltime @$_] }) : () } @newtracks]); + } + elsif($cmd eq 'program') + { + my $tracks = $opus->tracks_r(); + my ($channel, $program) = @arg; + for(0..@$tracks-1) + { + my @events = (); + my $added = 0; + for(abstime $tracks->[$_]->events()) + { + my $p = $chanpos{$_->[0]}; + if(defined $p) + { + my $c = $_->[$p] + 1; + if($c == $channel) + { + next + if $_->[0] eq 'patch_change'; + if(!$added) + { + push @events, ['patch_change', $_->[1], $c-1, $program-1] + if $program; + $added = 1; + } + } + } + push @events, $_; + } + $tracks->[$_]->events_r([reltime @events]); + } + } + elsif($cmd eq 'transpose') + { + my $tracks = $opus->tracks_r(); + my ($track, $channel, $delta) = @arg; + for(($track eq '*') ? (0..@$tracks-1) : $track) + { + for($tracks->[$_]->events()) + { + my $p = $chanpos{$_->[0]}; + if(defined $p) + { + my $c = $_->[$p] + 1; + if($channel eq '*' || $c == $channel) + { + if($_->[0] eq 'note_on' || $_->[0] eq 'note_off') + { + $_->[3] += $delta; + } + } + } + } + } + } + elsif($cmd eq 'percussion') + { + my $tracks = $opus->tracks_r(); + my %map = @arg; + for(0..@$tracks-1) + { + my @events = (); + for(abstime $tracks->[$_]->events()) + { + my $p = $chanpos{$_->[0]}; + if(defined $p) + { + my $c = $_->[$p] + 1; + if($c == 10) + { + if($_->[0] eq 'note_on' || $_->[0] eq 'note_off') + { + if(length $map{$_->[3]}) + { + $_->[3] = $map{$_->[3]}; + } + elsif(exists $map{$_->[3]}) + { + next; + } + } + } + } + push @events, $_; + } + $tracks->[$_]->events_r([reltime @events]); + } + } elsif($cmd eq 'tracks') { my $tracks = $opus->tracks_r(); @@ -109,14 +236,18 @@ while() if(defined $p) { my $c = $_->[$p] + 1; - ++$channels{$c}; + $channels{$c} //= {}; + if($_->[0] eq 'patch_change') + { + ++$channels{$c}{$_->[3]}; + } } ++$notes if $_->[0] eq 'note_on'; $notehash{$_->[2]}{$_->[3]} = $t if $_->[0] eq 'note_on'; $notehash{$_->[2]}{$_->[3]} = undef if $_->[0] eq 'note_off'; $name = $_->[2] if $_->[0] eq 'track_name'; } - my $channels = join " ", sort keys %channels; + my $channels = join " ", map { sprintf "%s(%s)", $_, join ",", sort { $a <=> $b } keys %{$channels{$_}} } sort { $a <=> $b } keys %channels; my @stuck = (); while(my ($k1, $v1) = each %notehash) { @@ -141,7 +272,15 @@ while() } else { - print "Unknown command, allowed commands: ticks, tracks, clean, save\n"; + print "Unknown command, allowed commands:\n"; + print " clean\n"; + print " dump\n"; + print " ticks [value]\n"; + print " retrack\n"; + print " program \n"; + print " transpose \n"; + print " percussion [ ...]\n"; + print " tracks [trackno] [trackno] ...\n"; } print "Done with: $cmd @arg\n"; }