midi re-tempoizer
[email protected] ("Sean M. Burke") Thu, 02 Dec 2004 20:22:14 -0900
| Newsgroups | perl.midi |
|---|---|
| Message-ID | <[email protected]> |
Speeds up or slows down a MIDI file by altering its set_tempo events: require 5; use strict; use warnings; use constant DEBUG => 0; use MIDI; # [email protected] 2004-12-02 $ARGV[0] = $1/$2 if $ARGV[0] and $ARGV[0] =~ m[^(\d+)/(\d+)$]s; my( $scale, $in, $out ) = @ARGV; die "Usage: scaletempo scalefactor infile.mid outfile.mid scalefactor = how much faster to make it. 2 = twice as fast 6/7 = slow it down to 6/7ths of its current speed .5 = slow it down to half of its current speed " unless @ARGV == 3 and $scale =~ m/^(?: (?: \d*\.\d+ ) | \d+ )$/sx and $scale != 0 and length( $in ) and length( $out ) and -e $in and -r $in ; my $opus = MIDI::Opus->new({ 'from_file' => $in }); DEBUG and print "$in contains ", scalar($opus->tracks), " tracks.\n"; my $tweaked = 0; foreach my $t ( $opus->tracks ) { DEBUG and print " Tweaking track $t\n"; foreach my $e ( @{ $t->events_r || next } ) { if( $e->[0] eq 'set_tempo' ) { $tweaked = 1; DEBUG > 1 and print " event @$e\n"; $e->[2] = int( .5 + $e->[2] / $scale ); DEBUG > 1 and print " => @$e\n"; } } } unless($tweaked) { DEBUG and print "No track events found. Faking it.\n"; my $new_ev = [ 'set_tempo', 0, int( .5 + 500_000 / $scale ) ]; if( $opus->tracks == 1 ) { DEBUG and print "Prepending [@$new_ev] to the one track.\n"; unshift @{ $opus->tracks_r->[0]->events_r || die "No events in track 0?!" }, $new_ev; } else { DEBUG and print "Prepending a [@$new_ev] tempo-track.\n"; unshift @{ $opus->tracks_r }, MIDI::Track->new( { 'events' => [$new_ev], } ); } } DEBUG and print "Writing $out\n"; $opus->write_to_file( $out ); DEBUG and print "Done.\n"; exit; __END__ -- Sean M. Burke http://search.cpan.org/~sburke/