X-Git-Url: https://git.xonotic.org/?p=xonotic%2Fxonotic.git;a=blobdiff_plain;f=misc%2Ftools%2Fmidi2cfg-ng.pl;h=4fcf9760a22134d54dbbfbab75b48151bc961fc7;hp=70a37517b26536eafea744c9f67a897c69003b8b;hb=6fcc8ff816109d10b4709c86cd4f36e897286a93;hpb=9b9cf0d6e1b76e5e10a3d2d22a5db8e29bd48229 diff --git a/misc/tools/midi2cfg-ng.pl b/misc/tools/midi2cfg-ng.pl index 70a37517..4fcf9760 100755 --- a/misc/tools/midi2cfg-ng.pl +++ b/misc/tools/midi2cfg-ng.pl @@ -14,6 +14,7 @@ use constant SYS_TICRATE => 0.033333; use constant MIDI_FIRST_NONCHANNEL => 17; use constant MIDI_DRUMS_CHANNEL => 10; +use constant TEXT_EVENT_CHANNEL => -1; die "Usage: $0 filename.conf midifile1 transpose1 midifile2 transpose2 ..." unless @ARGV > 1 and @ARGV % 2; @@ -25,6 +26,8 @@ my $timeoffset_postdone = 2; my $timeoffset_preintermission = 2; my $timeoffset_postintermission = 2; my $time_forgetfulness = 1.5; +my %lists = (); +my %listindexes = (); my ($config, @midilist) = @ARGV; @@ -88,7 +91,7 @@ sub botconfig_read($) while(<$fh>) { chomp; - s/\s*#.*//; + s/\s*\/\/.*//; next if /^$/; if(s/^\t\t//) { @@ -161,14 +164,14 @@ sub botconfig_read($) $super = $currentbot->{percussion}->{$1}; $currentbot->{percussion}->{$1} = $appendref = []; } - elsif(/^vocals$/) + elsif(/^text (.*)$/) { - $super = $currentbot->{vocals}; - $currentbot->{vocals} = $appendref = []; + $super = $currentbot->{text}->{$1}; + $currentbot->{text}->{$1} = $appendref = []; } else { - print "unknown command: $_\n"; + print STDERR "unknown command: $_\n"; } } elsif(/^bot (.*)/) @@ -207,9 +210,14 @@ sub botconfig_read($) { $time_forgetfulness = $1; } + elsif(/^list (.*?) (.*)/) + { + $lists{$1} = [split / /, $2]; + $listindexes{$1} = 0; + } else { - print "unknown command: $_\n"; + print STDERR "unknown command: $_\n"; } } @@ -298,6 +306,19 @@ sub busybot_cmd_bot_test($$$@) return 1; } +sub buildstring(@) +{ + return + join " ", + map + { + $_ =~ /^\@(.*)$/ + ? do { $lists{$1}[$listindexes{$1}++ % @{$lists{$1}}]; } + : $_ + } + @_; +} + sub busybot_cmd_bot_execute($$@) { my ($bot, $time, @commands) = @_; @@ -340,11 +361,11 @@ sub busybot_cmd_bot_execute($$@) } elsif($_->[0] eq 'cmd') { - $commands .= sprintf "sv_cmd bot_cmd %d %s\n", $bot->{id}, join " ", @{$_}[1..@$_-1]; + $commands .= sprintf "sv_cmd bot_cmd %d %s\n", $bot->{id}, buildstring @{$_}[1..@$_-1]; } elsif($_->[0] eq 'aim_random') { - $commands .= sprintf "sv_cmd bot_cmd %d aim %f 0 %f\n", $_->[1] + rand($_->[2] - $_->[1]), $_->[3]; + $commands .= sprintf "sv_cmd bot_cmd %d aim \"%f 0 %f\"\n", $bot->{id}, $_->[1] + rand($_->[2] - $_->[1]), $_->[3]; } elsif($_->[0] eq 'barrier') { @@ -354,7 +375,11 @@ sub busybot_cmd_bot_execute($$@) } elsif($_->[0] eq 'raw') { - $commands .= sprintf "%s\n", join " ", @{$_}[1..@$_-1]; + $commands .= sprintf "%s\n", buildstring @{$_}[1..@$_-1]; + } + else + { + warn "Invalid command: @$_"; } } @@ -381,6 +406,8 @@ sub busybot_note_off_bot($$$$) { my ($bot, $time, $channel, $note) = @_; #print STDERR "note off $bot:$time:$channel:$note\n"; + return 1 + if not $bot->{busy}; my ($busychannel, $busynote, $cmds) = @{$bot->{busy}}; return 1 if not defined $cmds; # note off cannot fail @@ -405,16 +432,19 @@ sub busybot_get_cmds_bot($$$) { my ($bot, $channel, $note) = @_; my ($k0, $k1, $cmds, $cmds_off) = (undef, undef, undef, undef); - if($channel <= 0) + if($channel == TEXT_EVENT_CHANNEL) { # vocals - $cmds = $bot->{vocals}; + $note =~ /^([^:]*):(.*)$/; + my $name = $1; + my $data = $2; + $cmds = $bot->{text}->{$name}; if(defined $cmds) { - $cmds = [ map { [ map { $_ eq '%s' ? $note : $_ } @$_ ] } @$cmds ]; + $cmds = [ map { [ map { $_ eq '%s' ? $data : $_ } @$_ ] } @$cmds ]; } - $k0 = "vocals"; - $k1 = $channel; + $k0 = "text"; + $k1 = $name; } elsif($channel == 10) { @@ -437,6 +467,7 @@ sub busybot_get_cmds_bot($$$) sub busybot_note_on_bot($$$$$$$) { my ($bot, $time, $channel, $program, $note, $init, $force) = @_; + return -1 # I won't play on this channel if defined $bot->{channels} and not $bot->{channels}->{$channel}; return -1 # I won't play this program @@ -471,7 +502,7 @@ sub busybot_note_on_bot($$$$$$$) if not busybot_cmd_bot_test $bot, $time + $notetime, $force, @$cmds; busybot_cmd_bot_execute $bot, $time + $notetime, @$cmds; } - if(defined $cmds and defined $cmds_off) + if(defined $cmds_off) { $bot->{busy} = [$channel, $note, $cmds_off]; } @@ -509,11 +540,6 @@ sub busybot_note_off($$$) # print STDERR "note off $time:$channel:$note\n"; - return 0 - if $channel <= 0; - return 0 - if $channel == 10; - if(my $bot = $notechannelbots{$channel}{$note}) { busybot_note_off_bot $bot, $time, $channel, $note; @@ -569,6 +595,7 @@ sub busybot_note_on($$$$) if($notechannelbots{$channel}{$note}) { + print STDERR "THIS SHOULD NEVER HAPPEN\n"; busybot_note_off $time, $channel, $note; } @@ -772,6 +799,8 @@ sub ConvertMIDI($$) my ($command, $delta, @data) = @$_; $command = 'note_off' if $command eq 'note_on' and $data[2] == 0; $tick += $delta; + next + if $command eq 'text_event' && $data[0] !~ /:/; push @allmidievents, [$command, $tick, $sequence++, $track, @data]; } } @@ -794,14 +823,34 @@ sub ConvertMIDI($$) } else { - push @allmidievents, ['note_on', $tick * $scale + $shift, $sequence++, -1, -1, $file]; - push @allmidievents, ['note_off', $tick * $scale + $shift, $sequence++, -1, -1, $file]; + push @allmidievents, ['text_event', $tick * $scale + $shift, $sequence++, -1, "vocals:$file"]; } } } + # HACK for broken rosegarden export: put patch changes first by clearing their sequence number + for(@allmidievents) + { + if($_->[0] eq 'patch_change') + { + $_->[2] = -1; + } + } + + # 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' || $_->[0] eq 'text_event' } @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 = (); @@ -841,6 +890,16 @@ sub ConvertMIDI($$) $midinotes{$chan}{$ev->[5]} = 0; }; + my $text_event = sub + { + my ($ev) = @_; + + my $chan = TEXT_EVENT_CHANNEL; + + busybot_note_on($t, TEXT_EVENT_CHANNEL, -1, $ev->[4]); + busybot_note_off($t, TEXT_EVENT_CHANNEL, $ev->[4]); + }; + my $patch_change = sub { my ($ev) = @_; @@ -882,6 +941,10 @@ sub ConvertMIDI($$) { $note_off->($_); } + elsif($_->[0] eq 'text_event') + { + $text_event->($_); + } elsif($_->[0] eq 'patch_change') { $patch_change->($_); @@ -908,7 +971,7 @@ sub ConvertMIDI($$) my $good = 0; for my $channel(sort keys %notes_seen) { - next if $channel == 10 or $channel < 0; + next if $channel == 10; for my $program(sort keys %{$notes_seen{$channel}}) { for my $note(sort keys %{$notes_seen{$channel}{$program}}) @@ -1014,7 +1077,7 @@ sub Deallocate() print STDERR "$counthash{$cn} bots of $cn have played:\n"; for my $type(sort keys %{$notehash{$cn}}) { - for my $note(sort { $a <=> $b } keys %{$notehash{$cn}{$type}}) + for my $note(sort keys %{$notehash{$cn}{$type}}) { my $cnt = $notehash{$cn}{$type}{$note}; print STDERR " $type $note ($cnt times)\n"; @@ -1038,6 +1101,7 @@ my @preallocate = (); $noalloc = 0; for(;;) { + %listindexes = (); $commands = ""; eval { @@ -1053,7 +1117,6 @@ 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;