Skip to main content

Notice

Please note that most of the software linked on this forum is likely to be safe to use. If you are unsure, feel free to ask in the relevant topics, or send a private message to an administrator or moderator. To help curb the problems of false positives, or in the event that you do find actual malware, you can contribute through the article linked here.
Topic: Calculate MP3 bitrate... (Read 16913 times) previous topic - next topic
0 Members and 1 Guest are viewing this topic.

Calculate MP3 bitrate...

First, I'll admit my search-fu sucks.  Second, I'll admit I'm a total newbie to all of this.

Using, say, id3lib, how would I calculate the average bitrate of an mp3?  I've been reading up (obviously in the wrong places), and I think it has something to do with iterating through each of the audio file's frames, getting their size, and averaging them out at the end of the file seek.  Am I right, or completely off base?  If I'm off base, can someone at least clue me in to what I'm looking to do?

Unfortunately, I am sans development box right now (and will be for a while), otherwise I could fool around and figure it out myself.  It'd also help if id3lib's documentation were a bit more concise.  Sure, I know how to tag the hell out of mp3s with it, but it doesn't mention anything about finding bitrate in the documentation or code examples it comes with.

Thanks for any help!
-j

Calculate MP3 bitrate...

Reply #1
You only need the audio size and the duration. If you have a 5 MB file with a length of 3 minutes, you wouls use the following:

5242880 * 8 / 180 / 1000 = ~233 kbps

bps = audio size in bits / duration in seconds

Calculate MP3 bitrate...

Reply #2
Quote
You only need the audio size and the duration. If you have a 5 MB file with a length of 3 minutes, you wouls use the following:

5242880 * 8 / 180 / 1000 = ~233 kbps

bps = audio size in bits / duration in seconds
[a href="index.php?act=findpost&pid=378490"][{POST_SNAPBACK}][/a]


okay, i just woke up literally minutes ago, so i'm a bit dense, to say the least.  where'd the 5242880 come from?  and with those numbers i'm getting ~291kbps.

Calculate MP3 bitrate...

Reply #3
1K = 1024 bytes
1M = 1024K
5MB = 5 * 1024 * 1024 bytes = 5242880 bytes

Calculate MP3 bitrate...

Reply #4
Quote
1K = 1024 bytes
1M = 1024K
5MB = 5 * 1024 * 1024 bytes = 5242880 bytes
[a href="index.php?act=findpost&pid=378592"][{POST_SNAPBACK}][/a]


yeeees, see. dense. was leaving the trailing 24 from the last 1024. i shouldn't be allowed  to do anything in the morning.  ever.

Calculate MP3 bitrate...

Reply #5
Quote
i shouldn't be allowed  to do anything in the morning.  ever.
without adding anything to the discussion but saving the day plus the forum, I hereby announce that you are forbidden to drive, post and think before 6PM and before you didn't had at least three cups of coffee. full moon doesn't hurt either.
Nothing but a Heartache - Since I found my Baby ;)

Calculate MP3 bitrate...

Reply #6
Quote
Quote
i shouldn't be allowed  to do anything in the morning.  ever.
without adding anything to the discussion but saving the day plus the forum, I hereby announce that you are forbidden to drive, post and think before 6PM and before you didn't had at least three cups of coffee. full moon doesn't hurt either.

[a href="index.php?act=findpost&pid=378600"][{POST_SNAPBACK}][/a]


i'm awake!  i'm awake!  a strong brew and a mile walk in the rain will do that.

alright.  another newbie question, since like i said in the original post, i don't have anything to experiment with available.  how, again using id3lib, would you determine if a file is vbr without processing the whole thing?  i've gone through the Parse() routine and that's really the only place where it detects vbr or no vbr, and it chews on the whole file, creating some crazy (and unnecessary) overhead.  i've gone through multiple mp3 specifications describing headers and other bits and pieces, but i haven't found a flag in the mp3 spec that says "hey!  look'it me!  i'm vbr, sucka!"

i know i should be using taglib, but by typing my examples out using id3lib (which is less efficient, thus easier to understand whilst walking through the code), i'll learn more about the file format in general.  and that'll lead to me being able to understand other audio file formats better as well.  i hope everyone understands that.

thanks much for the help so far guys.

Calculate MP3 bitrate...

Reply #7
Why are you using id3lib for getting an MP3's info when id3lib is for reading tags? Anyways, if you find a Xing or VBRI header at the beginning of the file, you can assume that the file is VBR.

Edit: Also look here for more information.

Calculate MP3 bitrate...

Reply #8
Quote
Why are you using id3lib for getting an MP3's info when id3lib is for reading tags? Anyways, if you find a Xing or VBRI header at the beginning of the file, you can assume that the file is VBR.

Edit: Also look here for more information.
[a href="index.php?act=findpost&pid=378637"][{POST_SNAPBACK}][/a]


Cause it's the only way I know how at the moment.  I JUST started researching this stuff yesterday.  Can anyone point me in the direction of a good reference for finding the magical Xing and Info headers in audio files?  From what I've read, they're not always in the same place, which complicates things a bit.

Any help at all would be much appreciated.  Anything you have to throw at me.  As long as it's not rotten tomatoes.

edit: seb, didn't catch your edit before I posted this.  very, very good resource there.  thanks!  but any other links would be nice.  i'm just piling them up to go through them and get the hang of this, so any info is helpful.

Calculate MP3 bitrate...

Reply #9
You shouldn't use the filesize to determine the bitrate, because headers and tags artificially boost the filesize.

I don't have the code in front of me, but I wrote a function a while ago to do this. First look for the VBR header, either XING or VBRI. If you find one, iterate through the file, adding up all the bitrates in each frame, and dividing by the number of frames. If you don't find a VBR header, you can simply use the bitrate found in the first frame.

Edit: When I get home, I'll post the code I wrote in Java to do this.

Calculate MP3 bitrate...

Reply #10
Quote
You shouldn't use the filesize to determine the bitrate, because headers and tags artificially boost the filesize.

I don't have the code in front of me, but I wrote a function a while ago to do this. First look for the VBR header, either XING or VBRI. If you find one, iterate through the file, adding up all the bitrates in each frame, and dividing by the number of frames. If you don't find a VBR header, you can simply use the bitrate found in the first frame.

Edit: When I get home, I'll post the code I wrote in Java to do this.
[a href="index.php?act=findpost&pid=378677"][{POST_SNAPBACK}][/a]



I doubt that a "normal" use of tags will have a big impact on the calculation. However, parsing an MP3 frame-by-frame can be time consuming.

Calculate MP3 bitrate...

Reply #11
Quote
I doubt that a "normal" use of tags will have a big impact on the calculation. However, parsing an MP3 frame-by-frame can be time consuming.
[a href="index.php?act=findpost&pid=378700"][{POST_SNAPBACK}][/a]


Using buffered reads it's pretty quick. But it's all relative; if you want accuracy (it sounds like he does) you should use this method, if not, use the file size. In the worst case tags and headers will have a significant impact on file size.

Calculate MP3 bitrate...

Reply #12
Quote
Quote
I doubt that a "normal" use of tags will have a big impact on the calculation. However, parsing an MP3 frame-by-frame can be time consuming.
[a href="index.php?act=findpost&pid=378700"][{POST_SNAPBACK}][/a]


Using buffered reads it's pretty quick. But it's all relative; if you want accuracy (it sounds like he does) you should use this method, if not, use the file size. In the worst case tags and headers will have a significant impact on file size.
[a href="index.php?act=findpost&pid=378714"][{POST_SNAPBACK}][/a]


Not concerned with *exact* accuracy, and in most cases, headers won't get in the way of getting an "accurate enough" result.

And goat, thanks much for the Java code offering.  Can't wait to see!

Calculate MP3 bitrate...

Reply #13
Code: [Select]
/*
Written by Greg Taylor
Part of Design and Implementation of a TCP/IP Network-Based Embedded MP3 Player
Senior Project at California Polytechnic State University, San Luis Obispo
Spring 2004
*/

import java.io.*;

public class MP3File extends File {
  public MP3File(String pathname) throws NullPointerException {
      super(pathname);

      mTag = new ID3v1();
  }

  public MP3File(String parent, String pathname) throws NullPointerException {
      super(parent, pathname);

      mTag = new ID3v1();
  }

  public MP3File(File fileName) throws NullPointerException {
      this(fileName.getAbsolutePath());
  }

  /*
  * This method should be called before any of the other accessor methods
  * because if an MP3 does not have a tag, calling other accessor methods
  * will return null strings, but not cause an error otherwise.
  */
  public boolean hasTag() throws IOException {
      readTag();
      return mHasTag;
  }

  public String getTitle() throws IOException {
      readTag();
      return mTag.getTitle();
  }

  public String getArtist() throws IOException {
      readTag();
      return mTag.getArtist();
  }

  public String getAlbum() throws IOException {
      readTag();
      return mTag.getAlbum();
  }

  public String getYear() throws IOException {
      readTag();
      return mTag.getYear();
  }

  public String getComment() throws IOException {
      readTag();
      return mTag.getComment();
  }

  public int getAlbumTrack() throws IOException {
      readTag();
      return mTag.getAlbumTrack();
  }

  public String getGenre() throws IOException {
      readTag();
      return mTag.getGenre();
  }

  public int getBitrate() throws IOException {
      if (!mReadBitrate) {
        calcBitrate();
        mReadBitrate = true;
      }

      return mBitrate;
  }

  public boolean isVBR() {return mIsVBR;}

  private void readTag() throws IOException {
      if (!mReadTag) {
        mHasTag = mTag.readTag(this);
        mReadTag = true;
      }
  }

  private void calcBitrate() throws IOException {
      long totalBitrate = 0, bitrate, bytesRead;
      int numFrames = 0;
      int currByte;
      int frameHeader = 0xFA;
      int nibbleAfterBitrate = 0;
      BufferedInputStream in =
            new BufferedInputStream(new FileInputStream(this));
      String XingVBRHeader = "Xing"; // Xing VBR header contains this
      String FhGVBRHeader = "VBRI"; // Fraunhofer VBR header contains this
      byte buf[] = new byte[XingVBRHeader.length()];
      boolean foundCBRBitrate = false;

      // Look for VBR Header to indicate whether MP3 is VBR
      for (bytesRead = 0; bytesRead < VBR_HEADER_DEPTH; bytesRead++) {
        // shift bytes into buf from left
        System.arraycopy(buf, 1, buf, 0, buf.length - 1);
        buf[buf.length - 1] = (byte) in.read();

        if (new String(buf, ID3v1.ENC_TYPE).substring(0,
              XingVBRHeader.length()).equals(XingVBRHeader)) {
            mIsVBR = true;
            break;
        }
        else if (new String(buf, ID3v1.ENC_TYPE).substring(0,
              FhGVBRHeader.length()).equals(FhGVBRHeader)) {
            mIsVBR = true;
            break;
        }
      }

      // reset to beginning of file
      in = new BufferedInputStream(new FileInputStream(this));

      if (!mIsVBR) {
        // mBitrate gets bitrate from first valid frame header
        currByte = in.read();
        while (currByte != -1 && !foundCBRBitrate) {

            // first byte of frame header
            if (currByte == 0xFF) {
              currByte = in.read();

              // second byte of frame header
              if (currByte != -1 && (currByte & frameHeader) == frameHeader) {
                  mBitrate = readBitrate(in);
                  if (mBitrate != -1) {
                    foundCBRBitrate = true;
                  }
              }
            }
            currByte = in.read();
        }
      }
      else {
        // mBitrate gets bitrate averaged over all valid frame headers
        currByte = in.read();
        while (currByte != -1) {

            // first byte of frame header
            if (currByte == 0xFF) {
              currByte = in.read();

              // second byte of frame header
              if (numFrames == 0 && (currByte & frameHeader) == frameHeader) {
                  // mark this position in file so we can compare nibble after
                  // bitrate
                  in.mark(1);
                  bitrate = readBitrate(in);

                  if (bitrate != -1) {
                    // save the form of this header so we only search for this
                    // type of header
                    frameHeader = currByte;
                    in.reset();
                    nibbleAfterBitrate = in.read() & 0x0F;
                    totalBitrate += bitrate;
                    numFrames++;
                  }
              }

              if (currByte == frameHeader) {
                  // mark this position in file so we can compare nibble after
                  // bitrate
                  in.mark(1);
                  bitrate = readBitrate(in);
                  in.reset();

                  if (bitrate != -1 && ((in.read() & 0x0F) ==
                        nibbleAfterBitrate)) {
                    totalBitrate += bitrate;
                    numFrames++;
                  }
              }
            }
            currByte = in.read();
        }

        if (numFrames > 0) {
            mBitrate = (int) totalBitrate/numFrames;
        }
        else {
            mBitrate = 0;
        }
      }

      in.close();
  }

  private int readBitrate(InputStream in) throws IOException {
      int info = in.read();
      int bitrate;

      if (info == -1) {
        return -1;
      }

      switch (info & 0xF0) { // only look at most significant nibble
        case 0x10:
            bitrate = 32;
            break;

        case 0x20:
            bitrate = 40;
            break;

        case 0x30:
            bitrate = 48;
            break;

        case 0x40:
            bitrate = 56;
            break;

        case 0x50:
            bitrate = 64;
            break;

        case 0x60:
            bitrate = 80;
            break;

        case 0x70:
            bitrate = 96;
            break;

        case 0x80:
            bitrate = 112;
            break;

        case 0x90:
            bitrate = 128;
            break;

        case 0xA0:
            bitrate = 160;
            break;

        case 0xB0:
            bitrate = 192;
            break;

        case 0xC0:
            bitrate = 224;
            break;

        case 0xD0:
            bitrate = 256;
            break;

        case 0xE0:
            bitrate = 320;
            break;

        default: // invalid or free bitrate
            bitrate = -1;
            break;
      }

      return bitrate;
  }

  private ID3tag mTag;
  private int mBitrate;
  private boolean mHasTag;
  private boolean mReadTag;
  private boolean mReadBitrate;
  private boolean mIsVBR;
    // how far into file to look for VBR header
  private static final int VBR_HEADER_DEPTH = 4096;
}

edit: codebox instead of code


Calculate MP3 bitrate...

Reply #15
Ha, just looking at my code above from two years ago I've found a bug. If you call isVBR() before  getBitrate() it will always return false. In my server application I'm positive this was never an issue, but it might be for someone just taking this code stand alone.

To fix the bug change the definition of isVBR() to:

Code: [Select]
public boolean isVBR() {
  if (!mReadBitrate) {
     calcBitrate();
     mReadBitrate = true;
  }

  return mIsVBR;
}

Calculate MP3 bitrate...

Reply #16
Sorry, been away from the computer for a while.  Thanks for the code.  It was helpful.

But quick question... to find the first valid frame, you go through your file reading 32 bits at a time, finding the first occurance of 2047 (11111111111) at the beginning of your 32 bit block?  I've seen a ton of documents saying to find the first occurance of 255 (11111111), but that doesn't match up with the frame sync header.

Correct, or am I off somewhere?  Haven't been able to do much research or such without a computer for the last bunch of days.

Thanks!

Calculate MP3 bitrate...

Reply #17
edit: nevermind, figured it out.

Calculate MP3 bitrate...

Reply #18
Sorry about not letting this thread die, but what's a good, *accurate* way to calculate the average bitrate of a variable bitrate mp3?  I haven't dug too much into headers and whatnot yet, but it seems that once you find your vbr header, you're left out on your own to figure out what the average bitrate is since the frames' bitrate fields are blank (or supposed to be blank).

Calculate MP3 bitrate...

Reply #19
Sorry about not letting this thread die, but what's a good, *accurate* way to calculate the average bitrate of a variable bitrate mp3?  I haven't dug too much into headers and whatnot yet, but it seems that once you find your vbr header, you're left out on your own to figure out what the average bitrate is since the frames' bitrate fields are blank (or supposed to be blank).


The frames' bitrate fields are not blank in a VBR file. Each frame has a specific bitrate, you must average them over the entire file to get an accurate calculation. You must be thinking of "free" bitrate files, which is different from VBR. In that case the bitrate field is set to invalid. These files do not conform to specification.

Also, to answer your question above about what bits to check for the header (in order to help others), I used additional bits because my program was only designed for MPEG 1, layer 3 files.

 

Calculate MP3 bitrate...

Reply #20
The frames' bitrate fields are not blank in a VBR file. Each frame has a specific bitrate, you must average them over the entire file to get an accurate calculation. You must be thinking of "free" bitrate files, which is different from VBR. In that case the bitrate field is set to invalid. These files do not conform to specification.

Also, to answer your question above about what bits to check for the header (in order to help others), I used additional bits because my program was only designed for MPEG 1, layer 3 files.


Ahhhh, I thought you were left guessing at bitrate and framesize cause I thought all VBR frames had 'free' bitrates (one of the specs I was looking at indicated as such).  I got it reading in plenty of info so far (with some unexplainable weirdness, but I hacked myself right out of that).  Gonna see what I can get done tonight.  Thanks much for the clarifications... some of these specs are wonky.