Valhalla Legends Forums Archive | General Discussion | Grabbing mp3 bitrate

AuthorMessageTime
iago
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
December 2, 2003, 4:13 AM
warz
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
December 2, 2003, 4:17 AM
Skywing
What about variable-bitrate files?
December 2, 2003, 4:19 AM
iago
[quote author=warz link=board=2;threadid=4009;start=0#msg33134 date=1070338657]
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
[/quote]

Wow, a good answer in 4 minutes. Damn people here are l33t :)

Thanks, I'm sure that'll work, or can be modified nicely!
December 2, 2003, 4:23 AM
iago
[quote author=Skywing link=board=2;threadid=4009;start=0#msg33136 date=1070338784]
What about variable-bitrate files?
[/quote]

He'll get over it.
December 2, 2003, 4:23 AM
iago
I deleted my old post, since I changed my program substantially. Here is the new one:

[code]// 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;
}

[/code]

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

:)
December 3, 2003, 4:37 AM
Arta
Instead of GetBits, can't you do:

[code]
struct FrameHeader
{
BYTE FirstField:2, SecondField:6;
BYTE SomethingElse:4, SecondHalfOfSomethingElse:4;
...
}
[/code]

And then do:

[code]
FrameHeader *Header = (FrameHeader*)Data;
[/code]

?
December 3, 2003, 2:25 PM
iago
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 :)
December 3, 2003, 2:37 PM
Arta
Pretty sure it's standard.
December 3, 2003, 3:45 PM
Yoni
Yes, it's called a bit field, and it's standard C.
December 4, 2003, 8:13 PM
iago
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 :)
December 4, 2003, 10:08 PM
Myndfyr
[quote author=iago link=board=2;threadid=4009;start=0#msg33133 date=1070338405]
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
[/quote]

So - is this mysterious friend really yourself?!?
December 5, 2003, 12:05 AM
iago
No, I have exactly one mp3 (thanks, warz, for the beta theme song!).

My friend is a guy I go to school with.
December 5, 2003, 12:42 AM
warz
beta theme song kicks ass! ;)
December 5, 2003, 4:15 AM
iago
And it happened to be sitting on my desktop when I needed a guinui-pig mp3 :)
December 5, 2003, 4:44 AM
Adron
[quote author=iago link=board=2;threadid=4009;start=0#msg33674 date=1070575736]
I think Grok discussed something like this before, on my forum, but for movies. But I still think this would be neat :)
[/quote]

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 ;)
December 5, 2003, 1:36 PM
iago
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)
December 5, 2003, 10:21 PM

Search