Valhalla Legends Archive

General => General Discussion => Topic started by: iago on December 01, 2003, 10:13 PM

Title: Grabbing mp3 bitrate
Post by: 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
Title: Re:Grabbing mp3 bitrate
Post by: 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
Title: Re:Grabbing mp3 bitrate
Post by: Skywing on December 01, 2003, 10:19 PM
What about variable-bitrate files?
Title: Re:Grabbing mp3 bitrate
Post by: iago on December 01, 2003, 10:23 PM
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!
Title: Re:Grabbing mp3 bitrate
Post by: iago on December 01, 2003, 10:23 PM
Quote from: Skywing on December 01, 2003, 10:19 PM
What about variable-bitrate files?

He'll get over it.
Title: Re:Grabbing mp3 bitrate
Post by: iago on December 02, 2003, 10:37 PM
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

:)
Title: Re:Grabbing mp3 bitrate
Post by: Arta on December 03, 2003, 08:25 AM
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;


?
Title: Re:Grabbing mp3 bitrate
Post by: iago on December 03, 2003, 08:37 AM
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 :)
Title: Re:Grabbing mp3 bitrate
Post by: Arta on December 03, 2003, 09:45 AM
Pretty sure it's standard.
Title: Re:Grabbing mp3 bitrate
Post by: Yoni on December 04, 2003, 02:13 PM
Yes, it's called a bit field, and it's standard C.
Title: Re:Grabbing mp3 bitrate
Post by: iago on December 04, 2003, 04:08 PM
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 :)
Title: Re:Grabbing mp3 bitrate
Post by: MyndFyre on December 04, 2003, 06:05 PM
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?!?
Title: Re:Grabbing mp3 bitrate
Post by: iago on December 04, 2003, 06:42 PM
No, I have exactly one mp3 (thanks, warz, for the beta theme song!).

My friend is a guy I go to school with.
Title: Re:Grabbing mp3 bitrate
Post by: warz on December 04, 2003, 10:15 PM
beta theme song kicks ass!  ;)
Title: Re:Grabbing mp3 bitrate
Post by: iago on December 04, 2003, 10:44 PM
And it happened to be sitting on my desktop when I needed a guinui-pig mp3 :)
Title: Re:Grabbing mp3 bitrate
Post by: Adron on December 05, 2003, 07:36 AM
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 ;)
Title: Re:Grabbing mp3 bitrate
Post by: iago on December 05, 2003, 04:21 PM
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)