• Welcome to Valhalla Legends Archive.
 

Grabbing mp3 bitrate

Started by iago, December 01, 2003, 10:13 PM

Previous topic - Next topic

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
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*


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

Skywing

What about variable-bitrate files?

iago

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!
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*


iago

#4
Quote from: Skywing on December 01, 2003, 10:19 PM
What about variable-bitrate files?

He'll get over it.
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*


iago

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

:)
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*


Arta

#6
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;


?

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 :)
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*


Arta


Yoni

Yes, it's called a bit field, and it's standard C.

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 :)
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*


MyndFyre

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?!?
QuoteEvery generation of humans believed it had all the answers it needed, except for a few mysteries they assumed would be solved at any moment. And they all believed their ancestors were simplistic and deluded. What are the odds that you are the first generation of humans who will understand reality?

After 3 years, it's on the horizon.  The new JinxBot, and BN#, the managed Battle.net Client library.

Quote from: chyea on January 16, 2009, 05:05 PM
You've just located global warming.

iago

No, I have exactly one mp3 (thanks, warz, for the beta theme song!).

My friend is a guy I go to school with.
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*


warz

beta theme song kicks ass!  ;)

iago

And it happened to be sitting on my desktop when I needed a guinui-pig mp3 :)
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*