X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=misc%2Ftools%2Fmidi2cfg-ng.pl;h=58b4097065280f6bdd0648be09e93502ac3eb494;hb=1f5d74bfbf3e6e79e72d81fdd3d2dd39caef6398;hp=00c826ff6827c6d5919da0075a8d375ff43a2fda;hpb=92972e6be4a9f3d896a1a80d0dbc49644e90aa54;p=xonotic%2Fxonotic.git diff --git a/misc/tools/midi2cfg-ng.pl b/misc/tools/midi2cfg-ng.pl index 00c826ff..58b40970 100755 --- a/misc/tools/midi2cfg-ng.pl +++ b/misc/tools/midi2cfg-ng.pl @@ -342,6 +342,10 @@ sub busybot_cmd_bot_execute($$@) { $commands .= sprintf "sv_cmd bot_cmd %d %s\n", $bot->{id}, join " ", @{$_}[1..@$_-1]; } + elsif($_->[0] eq 'aim_random') + { + $commands .= sprintf "sv_cmd bot_cmd %d aim \"%f 0 %f\"\n", $bot->{id}, $_->[1] + rand($_->[2] - $_->[1]), $_->[3]; + } elsif($_->[0] eq 'barrier') { $commands .= sprintf "sv_cmd bot_cmd %d barrier\n", $bot->{id}; @@ -473,7 +477,7 @@ sub busybot_note_on_bot($$$$$$$) } ++$bot->{seen}{$k0}{$k1}; - if($bot->{lastuse} && $channel == $bot->{lastchannel}) + if(($bot->{lastuse} // -666) >= $time - $time_forgetfulness && $channel == $bot->{lastchannel}) { $bot->{lastchannelsequence} += 1; } @@ -539,16 +543,19 @@ sub botsort($$$$@) map { my $q = 0; - if(($_->{lastuse} // -666) >= $time - $time_forgetfulness) + if($channel != 10) # percussion just should do round robin { - if($channel == $_->{lastchannel}) - { - $q += $_->{lastchannelsequence}; - } - else + if(($_->{lastuse} // -666) >= $time - $time_forgetfulness) { - # better leave this one alone - $q -= $_->{lastchannelsequence}; + if($channel == $_->{lastchannel}) + { + $q += $_->{lastchannelsequence}; + } + else + { + # better leave this one alone + $q -= $_->{lastchannelsequence}; + } } } [$_, $q, rand] @@ -793,46 +800,114 @@ sub ConvertMIDI($$) } } + # sort events @allmidievents = sort { $a->[1] <=> $b->[1] or $a->[2] <=> $b->[2] } @allmidievents; + # find the first interesting event + my $shift = [grep { $_->[0] eq 'note_on' } @allmidievents]->[0][1]; + die "No notes!" + unless defined $shift; + + # shift times by first event, no boring waiting + $_->[0] = ($_->[0] < $shift ? 0 : $_->[0] - $shift) for @tempi; + $_->[1] = ($_->[1] < $shift ? 0 : $_->[1] - $shift) for @allmidievents; + + # fix event list + my %midinotes = (); my $notes_stuck = 0; my %notes_seen = (); my %programs = (); my $t = 0; + my %sustain = (); + + my $note_on = sub + { + my ($ev) = @_; + my $chan = $ev->[4] + 1; + ++$notes_seen{$chan}{($programs{$chan} || 1)}{$ev->[5]}; + if($midinotes{$chan}{$ev->[5]}) + { + --$notes_stuck; + busybot_note_off($t - SYS_TICRATE - 0.001, $chan, $ev->[5]); + } + busybot_note_on($t, $chan, $programs{$chan} || 1, $ev->[5]); + ++$notes_stuck; + $midinotes{$chan}{$ev->[5]} = 1; + }; + + my $note_off = sub + { + my ($ev) = @_; + my $chan = $ev->[4] + 1; + if(exists $sustain{$chan}) + { + push @{$sustain{$chan}}, $ev; + return; + } + if($midinotes{$chan}{$ev->[5]}) + { + --$notes_stuck; + busybot_note_off($t - SYS_TICRATE - 0.001, $chan, $ev->[5]); + } + $midinotes{$chan}{$ev->[5]} = 0; + }; + + my $patch_change = sub + { + my ($ev) = @_; + my $chan = $ev->[4] + 1; + my $program = $ev->[5] + 1; + $programs{$chan} = $program; + }; + + my $sustain_change = sub + { + my ($ev) = @_; + my $chan = $ev->[4] + 1; + if($ev->[6] == 0) + { + # release all currently not pressed notes + my $s = $sustain{$chan}; + delete $sustain{$chan}; + for(@{($s || [])}) + { + $note_off->($_); + } + } + else + { + # no more note-off + $sustain{$chan} = []; + } + }; + for(@allmidievents) { $t = $tick2sec->($_->[1]); - my $track = $_->[3]; + # my $track = $_->[3]; if($_->[0] eq 'note_on') { - my $chan = $_->[4] + 1; - ++$notes_seen{$chan}{($programs{$chan} || 1)}{$_->[5]}; - if($midinotes{$chan}{$_->[5]}) - { - --$notes_stuck; - busybot_note_off($t - SYS_TICRATE - 0.001, $chan, $_->[5]); - } - busybot_note_on($t, $chan, $programs{$chan} || 1, $_->[5]); - ++$notes_stuck; - $midinotes{$chan}{$_->[5]} = 1; + $note_on->($_); } elsif($_->[0] eq 'note_off') { - my $chan = $_->[4] + 1; - if($midinotes{$chan}{$_->[5]}) - { - --$notes_stuck; - busybot_note_off($t - SYS_TICRATE - 0.001, $chan, $_->[5]); - } - $midinotes{$chan}{$_->[5]} = 0; + $note_off->($_); } elsif($_->[0] eq 'patch_change') { - my $chan = $_->[4] + 1; - my $program = $_->[5] + 1; - $programs{$chan} = $program; + $patch_change->($_); } + elsif($_->[0] eq 'control_change' && $_->[5] == 64) # sustain pedal + { + $sustain_change->($_); + } + } + + # fake events for releasing pedal + for(keys %sustain) + { + $sustain_change->(['control_change', $t, undef, undef, $_ - 1, 64, 0]); } print STDERR "For file $filename:\n"; @@ -854,7 +929,7 @@ sub ConvertMIDI($$) my $votehigh = 0; my $votelow = 0; my $votegood = 0; - for(@busybots_allocated) + for(@busybots_allocated, grep { $_->{count} > 0 } values %$busybots) { next # I won't play on this channel if defined $_->{channels} and not $_->{channels}->{$channel}; @@ -990,6 +1065,8 @@ for(;;) my @preallocate_new = map { $_->{classname} } @busybots_allocated; if(@preallocate_new == @preallocate) { + print "sv_cmd bot_cmd reset\n"; + print "sv_cmd bot_cmd setbots @{[scalar @preallocate_new]}\n"; print "$precommands$commands"; exit 0; }