4 # A MIDI file to Ann Hell Scripting converter
6 # (C) Angel Ortega 2006
8 # NOTE: this is by no means a general-purpose MIDI to Ann Hell Scripting
9 # Converter; it has been tuned to work on MIDI files converted from .mts
10 # files by MIDI Workshop / Master Tracks Pro. YMMV.
12 # This program mades the following assumptions:
14 # * A new track starts on patch_change messages.
25 # last note on time (to detect chords)
26 my $last_note_on_time = -1;
37 # length of a whole note
41 my $last_length = undef;
50 # set as a multiplier for the note
51 $ret = "1*" . $len / $whole;
56 $ret = int($whole / $len);
59 if($last_length eq $ret)
75 my @letters = ( 'c', 'c#', 'd', 'd#', 'e', 'f', 'f#',
76 'g', 'g#', 'a', 'a#', 'b');
79 if($e->{'type'} eq 'rest')
82 $ret = 'r' . note_length
($e->{'length'});
86 my $note_num = $e->{'note'} - 5;
88 my $octave = int($note_num / 12);
89 my $note = $letters[$note_num % 12];
91 # if last octave is different, set it
92 if($octave != $last_octave)
95 $last_octave = $octave;
98 $ret .= $note . note_length
($e->{'length'});
110 foreach my $t (@subtracks)
117 # if no length, there are still pending events; abort
118 return(undef) if !$e->{'length'};
122 $subret .= print_note
($e);
128 if(scalar(@subtracks) > 1)
130 $ret = '<' . join(';', @l) . ">\n";
145 my $subtrack = undef;
147 # find a subtrack with closed events
148 foreach my $t (@subtracks)
161 # if there is no subtrack, alloc a new one
165 push(@subtracks, $subtrack);
174 my ($dtime, $chan, $note, $vel) = @_;
175 my $subtrack = undef;
177 $subtrack = find_subtrack
();
179 # if this note has a delta, push some silence
188 if(my $ret = flush_subtracks
())
191 $subtrack = find_subtrack
();
207 push(@
{$subtrack}, $event);
209 # store it for easy access
210 $notes[$note] = $event;
216 my ($dtime, $chan, $note, $vel) = @_;
217 my $e = $notes[$note];
223 $e->{'length'} = $time - $e->{'time'};
225 if(my $ret = flush_subtracks
())
236 # print "$event @_\n";
238 if($event eq 'note_on')
242 elsif($event eq 'note_off')
244 note_off_event
( @_ );
246 elsif($event eq 'track_name')
248 print("/* $event @_ */\n");
250 elsif($event eq 'patch_change')
252 print("/* $event @_ */\n");
255 $time = $last_time = 0;
257 $last_length = undef;
265 ##############################################
267 my $input = $ARGV[0] or die "Usage: $0 {midi file}";
270 "from_file" => $input,
271 "exclusive_event_callback" => sub { &event_callback
}