Help - Search - Members - Calendar
Full Version: Efficient bitrate calculation
Hydrogenaudio Forums > Lossy Audio Compression > MP3 > MP3 - Tech
freakngoat
I am writing a program in which I must somehow get the bitrate of MP3 files. Right now I am using a brute force method of adding up all the bitrates stored in each frame header and dividing by the number of frames. I'm getting accurate results, but this is very inefficient having to read the whole file byte by byte looking for each frame header.

It doesn't seem the Lame tag always stores the bitrate (VBR), and it only stores the length of the music in bytes, not seconds. So how is this normally done?
freakngoat
My method is actually turning out to not be as slow as I thought, as long as I use buffered reads (this should have been done in the first place). Its actually pretty quick, and easily meets the time requirements of my project now. And I can increase speed even more if the file is determined to be CBR (no Xing header) by only reading one frame header.

However, if anyone knows of a faster method than what I described in my previous post, I'd love to hear it.
sony666
not every file that lacks a Xing header is CBR. Encode a file with FhG VBR method to see, they have their own header format sad.gif

I would take the first few 100 frames, if all those are the same bitrate you can be pretty sure it's a CBR file (unless they are all 32kbit which would indicate a long, silent lead-in)
freakngoat
Yes, I did consider an FhG VBR file. Trouble is I don't have any to test with. If anyone has a *short* clip they could share, containing a FhG VBR header, that would be great.

The FhG VBR header contains in ASCII "VBRI" similar to how the Xing VBR header contains "Xing", correct? That is how I indentify whether a file is VBR or not--search the first 2k or so of the file for these ASCII strings.

I don't think it would be wise to just take the first 100 frames, because of the very problem you mention.
getID3()
QUOTE(freakngoat @ Mar 2 2004, 08:40 PM)
It doesn't seem the Lame tag always stores the bitrate (VBR), and it only stores the length of the music in bytes, not seconds. So how is this normally done?

If you have the bitrate and the bytesize, that's enough to get you the length in seconds, whether it's VBR or CBR. Let's take an example:

file A = 5480654 bytes, 192 kb/s CBR (winamp says 228 seconds)
192kbps = 192000 bits/sec = 24000 bytes/sec (1kbps = 1000 bps; 1 bit = 8 bytes)
5480654 / 24000 = 228.3605833 seconds

So as a formula:
seconds = bytes / (bitrate / 8)


Scanning the file frame-by-frame is of course the most accurate way and (if properly designed) can report the most accurate times & bitrates for corrupted files. You should scan for the first frame header, calculate the length of that frame in bytes, skip ahead that far to where the next frame header should be, check to see if a valid frame header is found there - if yes then continue, if no then go back to where you were and scan byte by byte until you find the next valid frame header (that is followed by a valid frame header to ensure you haven't found a false synch).

For any method you should probably have basic ID3v2 skipping code (it's very simple, read 10 bytes, calculate length of ID3v2, skip those bytes and then start scanning from there).

Xing and LAME both use the same VBR header structure (although LAME includes more information than the basic Xing specification, it's not relevant to the bitrate/playtime calculation). LAME also uses the identical structure with "Info" instead of "Xing" as the identifier - typically this is only for LAME CBR files with forced header, but it's legal to use "Info" or "Xing" for either VBR or CBR. PM me if you want to Xing SDK that outlines the header format. You can see an abbreviated description of it plus the full description of the LAME extension of it here:
http://gabriel.mp3-tech.org/mp3infotag.html

There's a couple (very) short VBRI-header sample files here:
http://www.getid3.org/samples/mp3/vbri/

The "Xing"/"Info" string is located either 13, 21 or 36 bytes from the frame header, depending on MPEG version and number of channels:
MPEG-1 = 36 bytes (except mono = 21 bytes)
MPEG-2 = 21 bytes (except mono = 13 bytes)
MPEG-2.5 = 21 bytes (mono as well)

The "VBRI" string is always at 36 bytes. PM me if you want the VBRI SDK.
Sebastian Mares
The official VBRI SDK can be found on the Fraunhofer IIS website: http://www.iis.fraunhofer.de/amm/download/mp3_vbr_sdk.zip
freakngoat
Thanks guys. I now have a very accurate, fast, working bitrate calculation, that works with everything I throw at it.
Konrad
I've got also some questions regarding bitrate calculation in MP3s.

Are you really sure that in MPEG 2-5 the XING header always starts at 21 byte (even in mono), since in the SDK there is no hint that MPEG 2-5 is different from MPEG 2. This is the code
CODE
// get selected MPEG header data
h_id       = (buf[1] >> 3) & 1;
h_sr_index = (buf[2] >> 2) & 3;
h_mode     = (buf[3] >> 6) & 3;


// determine offset of header
if( h_id ) {        // mpeg1
   if( h_mode != 3 ) buf+=(32+4);
   else              buf+=(17+4);
}
else {      // mpeg2
   if( h_mode != 3 ) buf+=(17+4);
   else              buf+=(9+4);
}


What about the VBR_SCALE_FLAG? Should I consider this for calculating bitrate or for seeking within files?

Thank you in advance for your help.

Regards Konrad
Sebastian Mares
It's at 0xD for Mono and at 0x15 for (Joint) Stereo and Dual Channel files. No difference between MPEG 2 and 2.5.

Hint: getID3(), it seems that your PHP script is wrong:

CODE

               '2.5' => array ('mono'          => 0x15,
                               'stereo'        => 0x15,
                               'joint stereo'  => 0x15,
                               'dual channel'  => 0x15
                              )
Konrad
Thank you very much for your answer. Perhaps you could answer me another question. In XING and also in VBRI header there is an entry which contains the number of bytes. Is this number of bytes including ID3-Tags&VBR Header itself? I assume that the number includes the MP3 frame header and also the optional CRC checksum as well as the padding byte(s). Perhaps you can help me also with this issue.

Regards Konrad
Hirudin
QUOTE(freakngoat @ Mar 12 2004, 02:51 AM)
Thanks guys. I now have a very accurate, fast, working bitrate calculation, that works with everything I throw at it.
*



Awesome, that sounds like exactly what I'm looking for. Do you have this available for download somewhere?

Does anyone else know of a program that will calculate the exact average bitrate for VBR files? (By "exact" I mean something like: 206.329374, NOT the average rounded to the nearist whole number.) I've tried searching, but every search containing "average bitrate" returns a ton of ABR nonsense.

[edit]
P.S.
Actually, I finally found one for myself. (I looked a lot before posting too BTW.)

Anyway, you can get it here http://www.mpgedit.org/mpgedit/home.html

Use "mpgedit <filename>" for a quick check.
[/edit]
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Invision Power Board © 2001-2008 Invision Power Services, Inc.