Re: midi re-tempoizer
[email protected] (Jean-Pierre Vidal) Sun, 5 Dec 2004 08:52:34 +0000
| Newsgroups | perl.midi |
|---|---|
| Message-ID | <[email protected]> |
Le vendredi 3 D=E9cembre 2004 10:18, zentara a =E9crit=A0:
[snip]
>=20
> Cool. This is a much asked for utility.
>=20
> I've been wracking my brain trying to figure out how to
> get the total playlength of a midi using Perl.
>=20
> Would anyone know how to do this?
>=20
Try this:
#!perl -w
use strict;
use MIDI;
my $filename =3D shift;
die "usage : perl $0 midifile\n" if !defined $filename;
my @tempo_ticks;
my @tempo_value;
my $total_ticks;
my $max_ticks =3D 0;
my $opus =3D new MIDI::Opus({'from_file' =3D> $filename});
my $tpqn =3D $opus->ticks(); # ticks per quarter note
my @tracks =3D $opus->tracks();
for my $tr (@tracks) {
$total_ticks =3D 0;
my $tempo_ix =3D 0;
my @events =3D $tr->events();
for my $e (@events) {
if ($$e[0] eq 'set_tempo' ) {
$tempo_ticks[$tempo_ix] =3D $$e[1];
$tempo_ticks[$tempo_ix] +=3D $tempo_ticks[$tempo_ix - 1] if $tempo_ix > =
0;
$tempo_value[$tempo_ix] =3D $$e[2];=20
$tempo_ix++;=20
}
if ($$e[0] =3D~ 'note') {
$total_ticks +=3D $$e[1]; # add deltatime for note_on and note_off
}
}
$max_ticks =3D $total_ticks if $total_ticks > $max_ticks;
}
my $duration =3D 0;
if ($#tempo_ticks =3D=3D 0) {
$duration =3D $max_ticks / $tpqn * $tempo_value[0] / 1000000;
}=20
else {
for (1..$#tempo_ticks) {
$duration +=3D ($tempo_ticks[$_] - $tempo_ticks[$_-1]) / $tpqn *=20
$tempo_value[$_-1] / 1000000;
$max_ticks -=3D $tempo_ticks[$_];
}
}
$duration =3D int($duration + .5);
print "duration : $duration s\n";
__END__
Better would be a bridge between MIDI::Opus and MIDI::Score, and a function=
=20
$score->duration;-)
Jean-Pierre