A few weeks ago, I made a feeble attempt to calculate midi playlengths in Midi Playlength calculator. It didn't take into account differing midi tempos. So I asked on the perl.midi maillist, and one of the midi gurus Jean Pierre Vidal worked up a solution. Please advise me if you find any midis which this script dosn't give correct times, or if you have code tweaks.
#!/usr/bin/perl use strict; use MIDI; # by Jean-Pierre Vidal on the perl.midi maillist # jeanpierre.vidal@free.fr my $filename = shift; die "unknown file $filename\n" unless -e $filename; die "usage : perl $0 midifile\n" unless defined $filename; my $opus = new MIDI::Opus( { 'from_file' => $filename } ); #$opus->dump({'dump_tracks' => 1}); # ticks per quarter note my $tpqn = $opus->ticks(); my @tracks = $opus->tracks(); # convert tracks to score my @score = (); for my $tr (@tracks) { my @events = $tr->events; my ( $score_r, $ticks ) = MIDI::Score::events_r_to_score_r( \@even +ts ); @score = ( @score, @$score_r ); } my $score_r = MIDI::Score::sort_score_r( \@score ); #MIDI::Score::dump_score( $score_r ); my $duration = 0; my $tempo = .5; #default for midi's with no set_tempo as per spe +cs my $tempo_start = 0; my $last_time = 0; for my $note (@$score_r) { if($$note[0] eq 'set_tempo'){print $$note[0],"\n"} if ( $$note[0] eq 'set_tempo' ) { # if this 'tempo change' is not the last 'note', # we will calculate another $last_time later $last_time = 0; # $duration += ( $$note[1] - $tempo_start ) / $tpqn * $tempo; # tempo in seconds per quarter note $tempo = $$note[2] / 1_000_000; $tempo_start = $$note[1]; } elsif ( $$note[0] eq 'note' ) { # try to get the largest note after last tempo change my $l_t = ( $$note[1] - $tempo_start ) + $$note[2]; $last_time = $l_t if $l_t > $last_time; } } $duration += $last_time / $tpqn * $tempo; my $dmn = int( $duration / 60 ); my $dms = $duration - $dmn * 60; printf "%d mn %.1f s\n", $dmn, $dms; __END__

In reply to Midi Playlength calculator-II by zentara

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.