Well I went and looked at the gnmidi set of utilities, and there is a way to do it, with the free utility mididir.exe.
It runs under wine like this:
wine -- mididir.exe -length
That will give a print out like this for each midi file in
the directory:
Y:\ZLIG~MY.MID: (33 kb, format 1, 11 tracks, GS, 3:00)
Where the MM::SS is at the end after GS,Now you have 2 problems, working out a way to translate the crappy 8.3 notation output for the filename to the real filename, and extracting the MM::SS info and probably throwing it in a hash for saving in a database.
Heres an UPDATE: If you go to the free utilities section of gnmidi.com, there is the miditime utility. You can run it on an individual file like this:
#!/usr/bin/perl
my $midifile = shift;
system("wine -- midifade -songtime $midifile");
and you will get output like this
song: units 0 - 34475 time 0:00.000000 - 2:59.545800
So run it with backticks, and grab the last set of digits.
I'm not really a human, but I play one on earth.
flash japh
| [reply] [d/l] [select] |
| [reply] |
Perhaps you can use the score method of MIDI.
score: a structure of notes like an event structure, but where notes are represented as single items, and where timing of items is absolute from the beginning of the track, instead of being represented in delta-times. | [reply] [d/l] |
I would think that dumping the midi into a wav file, then
getting the time length of the wav would be the easiest. Of of course it is a "clunky approach", but easy. It would be sweeter to loop thru the midis, and summing the note durations, but there is the problem of overlapping notes. So maybe it can't be done that way? Anyways, you could use timidity to create a temp.wav with
system("timidity -Ow -o temp.wav $input.mid")
Then you can get the length of the wav with:
#!/usr/bin/perl -w
use strict;
use Fcntl;
my $fnm = shift;
sysopen WAV,$fnm,O_RDONLY;
my $riff;
sysread WAV,$riff,12;
my $fmt;
sysread WAV,$fmt,24;
my $data;
sysread WAV,$data,8;
close WAV;
# RIFF header: 'RIFF', long length, type='WAVE'
my ($r1,$r2,$r3) = unpack "A4VA4", $riff;
# WAV header, 'fmt ', long length, short unused, short channels,
# long samples/second, long bytes per second, short bytes per sample,
# short bits per sample
my ($f1,$f2,$f3,$f4,$f5,$f6,$f7,$f8) = unpack "A4VvvVVvv",$fmt;
# DATA header, 'DATA', long length
my ($d1,$d2) = unpack "A4V", $data;
my $playlength = $d2/$f6;
print << "EOF";
RIFF header: $r1, length $r2, type $r3
Format: $f1, length $f2, always $f3, channels $f4,
sample rate $f5, bytes per second $f6,
bytes per sample $f7, bits per sample $f8
Data: $d1, length $d2
Playlength: $playlength seconds
EOF
The drawback to using this method, is that timidity takes the exact playlength of the midi to do the conversion, which
could take a long time to process thousands of midis. But you would only have to do it once, and save the lengths in a file of your choice, then you could select midis from the list to give you an exact program of length "$x seconds". Maybe there are better midi-2-wav dumpers out there, that do it faster?
I know on the midi newsgroups, they always refer to the
win32 gnmidi set of utilities to do this type of thing. gnmidi does run under Wine, so it may be worth investigating. gnmidi
Another thought is to determine the BPM(beats per minute) of the midi, then count the number of beats, and the duration of a beat?
I'm not really a human, but I play one on earth.
flash japh
| [reply] [d/l] [select] |
You're the best!
Perhaps it might help to also read
this tip that I found yesterday.
I can't judge your recent code until I study a little more about Midi. I've also got the MIDI.PM family. And I guess that most might be obtained with MIDI::Score. But it's all my guessing.
Besides, I managed to use Midifade by providing a Win-DOS short midi filename (but keeping also the long filename). I used dir /X instead of opendir. Then, some splitting whitespaces would provide both: short and long filename to do all the job.
I had some complains, I guess, with the speed of the qx commands but I have overcome that difficult part.
Anyway, I am interested in studying a bit more about handling MIDI files and your code would be of great help.
Lot's of thanks, zentara!
.{\('v')/}
_`(___)' __________________________
Wherever I lay my KNOPPIX disk, a new FREE LINUX nation could be established.
| [reply] [d/l] [select] |
Yes, I have the information from your tip, but just couldn't
seem to "get my head around it". :-) I tried testing on midi files ranging from 96 ticks/qn to 480 ticks/qn, and could only get good results with perl if I used a different equation for each range...sort of a lookup table. However, the gnmidi utility was always correct, and the various midi players also report correct time. The gnmidi source is not open source, so I can't see what he does, but I may look at the open source midi players, and see how they compute it in C. It's got to be a simple equation, yet it's implementation
eludes me. :-(
I'm not really a human, but I play one on earth.
flash japh
| [reply] |