My friend is looking for a program which can scan through a folder of mp3's (thousands, likely), and grab the bitrate, and list them in a file.
A) Does anybody know if such a program exists?
B) Anybody know the format of an mp3 header so I can just grab it manually?
thanks!
-iago
Maybe this will help you create a program that loops through a directory, and finds bitrates.
http://www.pscode.com/vb/scripts/ShowCode.asp?txtCodeId=512&lngWId=3
What about variable-bitrate files?
Quote from: warz on December 01, 2003, 10:17 PM
Maybe this will help you create a program that loops through a directory, and finds bitrates.
http://www.pscode.com/vb/scripts/ShowCode.asp?txtCodeId=512&lngWId=3
Wow, a good answer in 4 minutes. Damn people here are l33t :)
Thanks, I'm sure that'll work, or can be modified nicely!
Quote from: Skywing on December 01, 2003, 10:19 PM
What about variable-bitrate files?
He'll get over it.
I deleted my old post, since I changed my program substantially. Here is the new one:
// MP3Checker.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
struct FrameHeader
{
BYTE AudioVersionID;
BYTE LayerDescription;
BYTE Protection;
BYTE Bitrate;
BYTE SamplingFrequency;
BYTE Padding;
BYTE Private;
BYTE ChannelMode;
BYTE ModeExtension;
BYTE Copyright;
BYTE Original;
BYTE Emphasis;
};
// Extracts a series of bits from a byte
int GetBits(unsigned int byte, BYTE start, BYTE length)
{
byte = byte << (32 - (start + length));
byte = byte >> (32 - (start + length));
byte = byte >> start;
return byte;
}
int GetBits(unsigned int byte, BYTE start, BYTE length, BYTE size)
{
byte = byte << (size - (start + length));
byte = byte >> (size - (start + length));
byte = byte >> start;
return byte;
}
bool GetMP3Info(char *Filename, FrameHeader *Header)
{
// the current byte while scanning the file
BYTE ch;
// the file
printf("Opening file: %s\n", Filename);
FILE *File = fopen(Filename, "rb");
// where in the file we are
int loc = 0;
if(File == NULL)
{
printf("Error: file not found\n");
return false;
}
// First, we have to find the byte 0xFF
printf("Scanning for 0xFF\n");
while((ch = getc(File)) != 0xFF)
{
loc++;
//printf("%02X ", ch);
}
printf("Found @ %d\n", loc);
ungetc(ch, File);
DWORD Data;
fread(&Data, 1, 4, File);
// The byte order is read in in Big-Endian, so fix that
Data = (Data & 0x000000FF) << 24 |
(Data & 0x0000FF00) << 8 |
(Data & 0x00FF0000) >> 8 |
(Data & 0xFF000000) >> 24;
//printf("Data = %08X", Data);
printf("Setting the header\n");
Header->AudioVersionID = GetBits(Data, 19, 2);
Header->LayerDescription = GetBits(Data, 17, 2);
Header->Protection = GetBits(Data, 16, 1);
Header->Bitrate = GetBits(Data, 12, 4);
Header->SamplingFrequency = GetBits(Data, 10, 2);
Header->Padding = GetBits(Data, 9, 1);
Header->Private = GetBits(Data, 8, 1);
Header->ChannelMode = GetBits(Data, 6, 2);
Header->ModeExtension = GetBits(Data, 4, 2);
Header->Copyright = GetBits(Data, 3, 1);
Header->Original = GetBits(Data, 2, 1);
Header->Emphasis = GetBits(Data, 0, 2);
printf("Closing %s\n", Filename);
if(File)
{
fclose(File);
}
return true;
}
char *Version[] = { "Version 2.5", "Reserved", "Version 2", "Version 1" };
char *Layer[] = { "Reserved", "Layer III", "Layer II", "Layer I" };
char *Protection[] = { "Protected", "Not Protected" };
// Assuming MP3
char *BitRate[] = { "Variable", "32", "40", "48", "56", "64", "80", "96", "112", "128", "160", "192", "224", "256", "320", "Bad" };
double SampleRate[] = { 44.1, 48.0, 32.0, -1 };
char *ChannelMode[] = { "Stereo", "Joint stereo", "Dual channel", "Single channel" };
char *Copyright[] = { "Copyrighted", "Not copyrighted" };
//#define pause
#define MAXLEN 1024
int main(int argc, char* argv[])
{
FrameHeader *fh = new FrameHeader;
FILE *out;
char File[MAXLEN];
printf("Checking if output file exists...\n");
if((out = fopen("out.csv", "r")) == NULL)
{
// Create the file if it doesn't exist
printf("out.csv not found; creating\n");
out = fopen("out.csv", "w");
fprintf(out, "Filename, Version, Layer, Protection, Bitrate, Samplerate, Channel Mode, Copyright\n");
}
else
{
fclose(out);
out = fopen("out.csv", "a");
}
//fgets(File, MAXLEN, stdin);
while(fgets(File, MAXLEN, stdin) != NULL)
{
strtok(File, "\n");
printf("Processing: %s\n", File);
printf("Getting info...\n");
if(GetMP3Info(File, fh) == false)
{
printf("Invalid file; skipping\n");
fprintf(out, "Invalid file format\n", File);
#ifdef pause
system("pause");
#endif
}
else
{
//FILE *out = fopen("out.csv", "a");
//printf("Outputting data\n");
printf("Outputting data: %d, %d, %d, %d, %d, %d, %d\n",
fh->AudioVersionID,
fh->LayerDescription,
fh->Protection,
fh->Bitrate,
fh->SamplingFrequency,
fh->ChannelMode,
fh->Copyright);
fprintf(out, "%s, %s, %s, %s, %s, %.1f, %s, %s\n",
File,
Version[fh->AudioVersionID],
Layer[fh->LayerDescription],
Protection[fh->Protection],
BitRate[fh->Bitrate],
SampleRate[fh->SamplingFrequency],
ChannelMode[fh->ChannelMode],
Copyright[fh->Copyright]
);
}
printf("\n");
}
printf("Closing output file\n");
fclose(out);
printf("Done!\n\n");
system("pause");
return 0;
}
Note that it expects to recieve the filenames on stdin, so here's what you should do:
To scan this folder+all subfolders for mp3's:
dir /o/s/b/a-d *.mp3 | MP3Checker.exe
To scan entire drive (say, C drive):
dir /o/s/b/a-d c:\*.mp3 | MP3Checker.exe
:)
Instead of GetBits, can't you do:
struct FrameHeader
{
BYTE FirstField:2, SecondField:6;
BYTE SomethingElse:4, SecondHalfOfSomethingElse:4;
...
}
And then do:
FrameHeader *Header = (FrameHeader*)Data;
?
I didn't know you could declare something as only certain bits. And if you can, is it portable across platorms?
Doing it like this is fine, anyway, but that's not a bad idea :)
Pretty sure it's standard.
Yes, it's called a bit field, and it's standard C.
Well anywhere, I plan to work more on this later.
What I want to do is add support to reading ID3 and ID3v2 tags, and allow the user to choose which fields to output. This way, people can make a quick database of their music which they can either refer to or they can share with friends and such.
I think Grok discussed something like this before, on my forum, but for movies. But I still think this would be neat :)
Quote from: iago on December 01, 2003, 10:13 PM
My friend is looking for a program which can scan through a folder of mp3's (thousands, likely), and grab the bitrate, and list them in a file.
A) Does anybody know if such a program exists?
B) Anybody know the format of an mp3 header so I can just grab it manually?
thanks!
-iago
So - is this mysterious friend really
yourself?!?
No, I have exactly one mp3 (thanks, warz, for the beta theme song!).
My friend is a guy I go to school with.
beta theme song kicks ass! ;)
And it happened to be sitting on my desktop when I needed a guinui-pig mp3 :)
Quote from: iago on December 04, 2003, 04:08 PM
I think Grok discussed something like this before, on my forum, but for movies. But I still think this would be neat :)
I might have offered to make a tool to read id3 tags and submit them to the central reference database. Something like the tool you're now making ;)
This project has been bumped back to #2 now, since it works to my friends satisfaction, and I've been updated my Starcraft Plugin (finally)