Коллега, я понимаю, что желательно на VBS, но мне хотелось и самому попробовать что-то накопать, не вдаваясь в подробности битовых операций в VBS. Поэтому я использовал Перл, так как у него есть очень простые и удобные (на мой взгляд) средства для работы с двоичными файлами и битовыми данными. Не обессудьте.
Я специально писал без использования библиотек, чтобы посмотреть самому. Уверен, что CPAN есть соответствующие пакеты.
#!/usr/bin/perl -w
my $BUF;
my $filename = $ARGV[0];
open F, $filename or die "Cannot open file $filename\n";
binmode F, ":raw";
# Check ID3 at the begin of a file
read F, $BUF, 3;
if ( $BUF ne "ID3" ) {
seek F, 0, 0;
} else {
# Read the rst of the ID3
read F, $BUF, 7;
my ($id3_ver, $id3_rev, undef, $id3_size) = unpack("CCCN", $BUF);
$id3_size = (($id3_size & 0xff000000) >> 1) + ($id3_size & 0x00ffffff);
$id3_size = (($id3_size & 0xffff0000) >> 1) + ($id3_size & 0x0000ffff);
$id3_size = (($id3_size & 0xffffff00) >> 1) + ($id3_size & 0x000000ff);
printf "ID3v2.%d.%d\nSize: %d (%04x)\n\n",
$id3_ver, $id3_rev,
$id3_size, $id3_size;
seek F, $id3_size, 1;
}
# Read the first frame's header
read F, $BUF, 4;
close F;
my @MPEG = (
"MPEG Version 2.5",
"reserved",
"MPEG Version 2",
"MPEG Version 1"
);
my @LAYER = (
"reserved",
"Layer III",
"Layer II",
"Layer I"
);
my %BRATE = (
"33" => ["free", 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, "bad"],
"32" => ["free", 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, "bad"],
"31" => ["free", 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, "bad"],
"23" => ["free", 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, "bad"],
"22" => ["free", 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, "bad"],
"21" => ["free", 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, "bad"],
);
my %SAMPLE = (
"3" => [44100, 48000, 32000, "reserv"],
"2" => [22050, 24000, 16000, "reserv"],
"0" => [11025, 12000, 8000, "reserv"],
);
my $mp3_header = unpack("N", $BUF);
my $mp3_mpeg = ($mp3_header & 0x00180000) >> 19;
my $mp3_layer = ($mp3_header & 0x00060000) >> 17;
my $mp3_brate = ($mp3_header & 0x0000f000) >> 12;
my $mp3_sample = ($mp3_header & 0x00000c00) >> 10;
my $mp3_pad = ($mp3_header & 0x00000200) >> 9;
my $bitrate = %BRATE->{"$mp3_mpeg$mp3_layer"}->[$mp3_brate];
my $sample = %SAMPLE->{"$mp3_mpeg"}->[$mp3_sample];
my $frame = int(
$mp3_layer == 3
? (12000 * $bitrate / $sample + $mp3_pad) * 4
: 144000 * $bitrate / $sample + $mp3_pad
);
printf "%s\n%s\n\nBitrate : %s\nSample : %s\nPadding : %s\nFrame : %s\n",
$MPEG[$mp3_mpeg],
$LAYER[$mp3_layer],
$bitrate,
$sample,
$mp3_pad, $frame;